Browse Source

remove deprecated content-directory-schemas package

Mokhtar Naamani 4 years ago
parent
commit
c79fec5d1e
64 changed files with 0 additions and 2809 deletions
  1. 0 10
      content-directory-schemas/.gitignore
  2. 0 1
      content-directory-schemas/.npmignore
  3. 0 279
      content-directory-schemas/README.md
  4. 0 52
      content-directory-schemas/examples/createChannel.ts
  5. 0 68
      content-directory-schemas/examples/createChannelWithoutTransaction.ts
  6. 0 76
      content-directory-schemas/examples/createVideo.ts
  7. 0 47
      content-directory-schemas/examples/updateChannelTitle.ts
  8. 0 47
      content-directory-schemas/examples/updateChannelTitleWithoutTransaction.ts
  9. 0 7
      content-directory-schemas/inputs/classes/ChannelClass.json
  10. 0 6
      content-directory-schemas/inputs/classes/ContentCategoryClass.json
  11. 0 6
      content-directory-schemas/inputs/classes/FeaturedVideoClass.json
  12. 0 7
      content-directory-schemas/inputs/classes/HttpMediaLocationClass.json
  13. 0 7
      content-directory-schemas/inputs/classes/JoystreamMediaLocationClass.json
  14. 0 6
      content-directory-schemas/inputs/classes/KnownLicenseClass.json
  15. 0 6
      content-directory-schemas/inputs/classes/LanguageClass.json
  16. 0 7
      content-directory-schemas/inputs/classes/LicenseClass.json
  17. 0 7
      content-directory-schemas/inputs/classes/MediaLocationClass.json
  18. 0 7
      content-directory-schemas/inputs/classes/UserDefinedLicenseClass.json
  19. 0 7
      content-directory-schemas/inputs/classes/VideoClass.json
  20. 0 7
      content-directory-schemas/inputs/classes/VideoMediaClass.json
  21. 0 6
      content-directory-schemas/inputs/classes/VideoMediaEncodingClass.json
  22. 0 18
      content-directory-schemas/inputs/classes/index.js
  23. 0 20
      content-directory-schemas/inputs/entityBatches/ContentCategoryBatch.json
  24. 0 61
      content-directory-schemas/inputs/entityBatches/KnownLicenseBatch.json
  25. 0 43
      content-directory-schemas/inputs/entityBatches/LanguageBatch.json
  26. 0 27
      content-directory-schemas/inputs/entityBatches/VideoMediaEncodingBatch.json
  27. 0 49
      content-directory-schemas/inputs/schemas/ChannelSchema.json
  28. 0 20
      content-directory-schemas/inputs/schemas/ContentCategorySchema.json
  29. 0 12
      content-directory-schemas/inputs/schemas/FeaturedVideoSchema.json
  30. 0 20
      content-directory-schemas/inputs/schemas/HttpMediaLocationSchema.json
  31. 0 13
      content-directory-schemas/inputs/schemas/JoystreamMediaLocationSchema.json
  32. 0 52
      content-directory-schemas/inputs/schemas/KnownLicenseSchema.json
  33. 0 20
      content-directory-schemas/inputs/schemas/LanguageSchema.json
  34. 0 23
      content-directory-schemas/inputs/schemas/LicenseSchema.json
  35. 0 19
      content-directory-schemas/inputs/schemas/MediaLocationSchema.json
  36. 0 13
      content-directory-schemas/inputs/schemas/UserDefinedLicenseSchema.json
  37. 0 13
      content-directory-schemas/inputs/schemas/VideoMediaEncodingSchema.json
  38. 0 40
      content-directory-schemas/inputs/schemas/VideoMediaSchema.json
  39. 0 99
      content-directory-schemas/inputs/schemas/VideoSchema.json
  40. 0 56
      content-directory-schemas/package.json
  41. 0 155
      content-directory-schemas/schemas/extrinsics/AddClassSchema.schema.json
  42. 0 48
      content-directory-schemas/schemas/extrinsics/CreateClass.schema.json
  43. 0 38
      content-directory-schemas/schemas/propertyValidationDefs.schema.json
  44. 0 105
      content-directory-schemas/scripts/devInitContentLead.ts
  45. 0 65
      content-directory-schemas/scripts/initializeContentDir.ts
  46. 0 163
      content-directory-schemas/scripts/inputSchemasToEntitySchemas.ts
  47. 0 56
      content-directory-schemas/scripts/schemasToTS.ts
  48. 0 85
      content-directory-schemas/scripts/validate.ts
  49. 0 435
      content-directory-schemas/src/helpers/InputParser.ts
  50. 0 86
      content-directory-schemas/src/helpers/extrinsics.ts
  51. 0 19
      content-directory-schemas/src/helpers/initialize.ts
  52. 0 40
      content-directory-schemas/src/helpers/inputs.ts
  53. 0 16
      content-directory-schemas/src/helpers/propertyType.ts
  54. 0 8
      content-directory-schemas/src/helpers/schemas.ts
  55. 0 6
      content-directory-schemas/src/index.ts
  56. 0 27
      content-directory-schemas/tsconfig.json
  57. 0 7
      content-directory-schemas/tsconfig.lib.json
  58. 0 4
      content-directory-schemas/types/EntityBatch.d.ts
  59. 0 67
      content-directory-schemas/types/extrinsics/AddClassSchema.d.ts
  60. 0 30
      content-directory-schemas/types/extrinsics/CreateClass.d.ts
  61. 0 2
      content-directory-schemas/types/extrinsics/index.d.ts
  62. 0 1
      content-directory-schemas/types/utility.d.ts
  63. 0 2
      content-directory-schemas/typings/@joystream/prettier-config/index.d.ts
  64. 0 60
      content-directory-schemas/vscode-recommended.settings.json

+ 0 - 10
content-directory-schemas/.gitignore

@@ -1,10 +0,0 @@
-operations.json
-
-# Auto-generated
-schemas/entities
-schemas/entityBatches
-schemas/entityReferences
-types/entities
-
-# Build
-lib

+ 0 - 1
content-directory-schemas/.npmignore

@@ -1 +0,0 @@
-operations.json

+ 0 - 279
content-directory-schemas/README.md

@@ -1,279 +0,0 @@
-# Content directory tooling
-
-## Definitions
-
-In order to make this documentation as clear as possible it is important to make a strict distinction between two types of schemas:
-
-- `json-schemas` mean files with `.schema.json` extension. This is a common standard for describing how to validate other `json` files or objects (ie. a `package.json` file may be an example of a file that can be supported by a `json-schema`). A documentation of this standard can be found here: https://json-schema.org/
-- `runtime-scheams` means schemas as they are "understood" by the `content-directory` runtime module, so schemas that can be added to classes via `api.tx.contentDirectory.addClassSchema` and linked to entities via `api.tx.contentDirectory.addSchemaSupportToEntity`
-
-## Content directory input
-
-### Initializing content directory
-
-In order to intialize the content directory on a development chain based on data that is provided in form of json files inside `/inputs` directory (`classes`, `schemas` and example entities - `entityBatches`), we can run:
-
-```
-yarn workspace @joystream/cd-schemas initialize:dev
-```
-
-This will handle:
-
-- Creating a membership for `ALICE` (if not already created)
-- Setting (hiring) `ALICE` as content curators lead (if not already set)
-- Creating classes in the runtime based on `inputs/classes` json inputs (if the content directory is currently empty)
-- Creating schemas in the runtime based on `inputs/schemas` and adding them to the related classes
-- Creating entities based on `inputs/entityBatches`. Those json inputs allow describing entities and relationships between them in a simplified way and are then converted into one huge `api.tx.contentDirectory.transaction` call (this is further described in _**Entity batches**_ section).
-
-### Input files naming
-
-In order to get the full benefit of the tooling, in some cases you may need to respect a specific pattern of file naming:
-
-Each input file name should end with `Class`, `Schema` or `Batch` (depending on the input type, ie. `LanguageBatch`).
-It is also recommended that each of those file names starts with a class name (currently in `entityBatches` there's no distinction between schemas and classes, as it is assumed there will be a one-to-one relationship between them)
-
-### `json-schemas` support for json inputs in `VSCode`
-
-In order to link json files inside `inputs` directory to `json-schemas` inside `schemas` and have them validated in real-time by the IDE, follow the steps below:
-
-**If you don't have `.vscode/settings.json` in the root monorepo workspace yet:**
-
-1. Create `.vscode` directory inside your monorepo workspace
-1. Copy `vscode-recommended.settings.json` into this `.vscode` directory and rename it to `settings.json`.
-
-**If you already have the `.vscode/settings.json` file in the root monorepo workspace:**
-
-1. Copy the settings from `vscode-recommended.settings.json` and merge them with the existing `.vscode/settings.json`
-
-Now all the json files matching `*Class.json`, `*Schema.json`, `*{EntityName}Batch.json` patters will be linked to the correct `json schemas`. If you edit any file inside `inputs` or add a new one that follows the naming pattern (described in _Input files naming_), you should get the benefit of autocompleted properties, validated input, on-hover tooltips with property descriptions etc.
-
-For more context, see: https://code.visualstudio.com/docs/languages/json
-
-### Validate inputs and `json-schemas` via a command
-
-All inputs inside `inputs` directory and `json-schemas` used to validate those inputs can also be validated using `yarn workspace @joystream/cd-schemas validate` command. This is mainly to facilitate checking the validity of `.json` and `.schema.json` files inside `content-directory-schemas` through CI.
-
-### Entity batches
-
-The concept of entity batches (`inputs/entityBatches`) basically provides an easy way of describing complex input to content directory (ie. many entities related to each other in many ways) without the need to deal with lower-level, hard-to-validate runtime operations like `CreateEntity` and `AddSchemaSupportEntity` and trying to glue them together into a huge `api.tx.contentDirectory.transaction` call.
-
-Instead, the script that initializes the content directory (`scripts/initializeContentDir.ts`) is able to generate the complex `api.tx.contentDirectory.transaction` call based on a more human-readable input provided in `inputs/entityBatches`.
-
-This input can be provided as a simple json array of objects matching `{ [propertyName]: propertyValue}` structure.
-
-For example, in order to describe creating entities as simple as `Language`, which only has `Code` and `Name` properties, we can just create an array of objects like:
-
-```
-[
-  { "Code": "EN", "Name": "English" },
-  { "Code": "RU", "Name": "Russian" },
-  { "Code": "DE", "Name": "German" }
-]
-```
-
-_(This is the actual content of `inputs/entityBatches/LanguageBatch.json`)_
-
-#### Related entities
-
-There also exists a specific syntax for defining relations between entities in batches.
-We can do it by either using `"new"` or `"existing"` keyword.
-
-- The `"new"` keyword allows describing a scenario where related entity should be created **along with** the main entity and then referenced by it. An example of this could be `Video` and `VideoMedia` which have a one-to-one relationship and it doesn't make much sense to specify them in separate batches. Instead, we can use a syntax like:
-
-```
-{
-  "title": "Awesome video",
-  /* other Video properties... */
-  "media": { "new": {
-    "pixelWidth": 1024,
-    "pixelHeight": 764,
-    /* other VideoMedia object properties... */
-  }
-}
-```
-
-- The `"existing"` keyword allows referencing an entity created as part of any other batch inside `inputs/entityBatches`. We can do it by specifying the value of **any unique property of the referenced entity**. So, for example to reference a `Language` entity from `VideoBatch.json` file, we use this syntax:
-
-```
-{
-  "title": "Awesome video",
-  /* other Video properties... */
-  "language": { "existing": { "Code": "EN" } }
-}
-```
-
-## `json-schemas` and tooling
-
-### Entity `json-schemas`
-
-There is a script that provides an easy way of converting `runtime-schemas` (based on inputs from `inputs/schemas`) to `json-schemas` (`.schema.json` files) which allow validating the input (ie. json files) describing some specific entities. It can be run with:
-
-```
-yarn workspace @joystream/cd-schemas generate:entity-schemas
-```
-
-Those `json-schemas` are currently mainly used for validating the inputs inside `inputs/entityBatches`.
-
-The generated `json-schemas` include:
-
-- `schemas/entities` - `json-schemas` that provide validation for given entity (ie. `Video`) input. They can, for example, check if the `title` property in a json object is a string that is no longer than `64` characters. They are used to validate a single entity in `inputs/entityBatches`, but can also be re-used to provide "frontend" validation of any entity input to the content directory (ie. input provided to/via `joystream-cli`).
-- `schemas/entityReferences` - `json-schemas` that describe how an entity of given class can be referenced. Currently they are used for providing an easy way of referencing entites between batches in `inputs/entityBatches`. For more details on how entities can be referenced in batches, read the _**Entity batches**_ section.
-- `schemas/entityBatches` - very simple `json-schemas` that basically just provide `array` wrappers over `schemas/entities`. Those are the actual `json-schemas` that can be linked to json input files inside `inputs/entityBatches` (ie. via `.vscode/settings.json`)
-
-### Typescript support
-
-Thanks to the `json-schema-to-typescript` library, we can very simply generate Typescript interfaces based on existing `json-schemas`. This can be done via:
-
-```
-yarn workspace @joystream/cd-schemas generate:types
-```
-
-This command will generate:
-
-- `types/entities` based on `schemas/entities`, providing typescript interfaces for entities like `Video` etc. (note that this interface will include a peculiar way of describing entity relationships, further described in _**Entity batches**_ section)
-- `types/extrinsics` based on `schemas/extrinsics`, providing typescript interfaces for input to extrinsics like `AddClassSchema` and `CreateClass`
-
-The most obvious use-case of those interfaces currently is that when we're parsing any json files inside `inputs` using a Typescript code, we can assert that the resulting object will be of given type, ie.:
-
-```
-const createClassInput = JSON.parse(fs.readFileSync('/path/to/inputs/LanguageClass.json')) as CreateClass
-```
-
-Besides that, a Typescript code can be written to generate some inputs (ie. using a loop) that can then can be used to create classes/schemas or insert entities into the content directory.
-
-There are a lot of other potential use-cases, but for the purpose of this documentation it should be enough to mention there exists this very easy way of converting `.schema.json` files into Typescript interfaces.
-
-## Using as library
-
-The `content-directory-schemas` directory of the monorepo is constructed in such a way, that it should be possible to use it as library and import from it json schemas, types (mentioned in `Typescript support` section) and tools to, for example, convert entity input like this described in the `Entity batches` section into `CreateEntity`, `AddSchemaSupportToEntity` and/or `UpdateEntityPropertyValues` operations.
-
-### Examples
-
-The best way to ilustrate this would be by providing some examples:
-
-#### Creating a channel
-```
-  import { InputParser } from '@joystream/cd-schemas'
-  import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
-  // Other imports...
-
-  async main() {
-    // Initialize the api, SENDER_KEYPAIR and SENDER_MEMBER_ID...
-
-    const channel: ChannelEntity = {
-      handle: 'Example channel',
-      description: 'This is an example channel',
-      language: { existing: { code: 'EN' } },
-      coverPhotoUrl: '',
-      avatarPhotoUrl: '',
-      isPublic: true,
-    }
-
-    const parser = InputParser.createWithKnownSchemas(api, [
-      {
-        className: 'Channel',
-        entries: [channel],
-      },
-    ])
-
-    const operations = await parser.getEntityBatchOperations()
-    await api.tx.contentDirectory
-      .transaction({ Member: SENDER_MEMBER_ID }, operations)
-      .signAndSend(SENDER_KEYPAIR)
-  }
-```
-_Full example with comments can be found in `content-directory-schemas/examples/createChannel.ts` and ran with `yarn workspace @joystream/cd-schemas example:createChannel`_
-
-#### Creating a video
-```
-import { InputParser } from '@joystream/cd-schemas'
-import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
-// ...
-
-async main() {
-  // ...
-
-  const video: VideoEntity = {
-    title: 'Example video',
-    description: 'This is an example video',
-    language: { existing: { code: 'EN' } },
-    category: { existing: { name: 'Education' } },
-    channel: { existing: { handle: 'Example channel' } },
-    media: {
-      new: {
-        encoding: { existing: { name: 'H.263_MP4' } },
-        pixelHeight: 600,
-        pixelWidth: 800,
-        location: {
-          new: {
-            httpMediaLocation: {
-              new: { url: 'https://testnet.joystream.org/' },
-            },
-          },
-        },
-      },
-    },
-    license: {
-      new: {
-        knownLicense: {
-          existing: { code: 'CC_BY' },
-        },
-      },
-    },
-    duration: 3600,
-    thumbnailUrl: '',
-    isExplicit: false,
-    isPublic: true,
-  }
-
-  const parser = InputParser.createWithKnownSchemas(api, [
-    {
-      className: 'Video',
-      entries: [video],
-    },
-  ])
-
-  const operations = await parser.getEntityBatchOperations()
-  await api.tx.contentDirectory
-    .transaction({ Member: SENDER_MEMBER_ID }, operations)
-    .signAndSend(SENDER_KEYPAIR)
-}
-```
-_Full example with comments can be found in `content-directory-schemas/examples/createVideo.ts` and ran with `yarn workspace @joystream/cd-schemas example:createChannel`_
-
-#### Update channel handle
-
-```
-import { InputParser } from '@joystream/cd-schemas'
-import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
-// ...
-
-async function main() {
-  // ...
-
-  const channelUpdateInput: Partial<ChannelEntity> = {
-    handle: 'Updated channel handle',
-  }
-
-  const parser = InputParser.createWithKnownSchemas(api)
-
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel' }, 'Channel')
-
-  const updateOperations = await parser.getEntityUpdateOperations(channelUpdateInput, 'Channel', CHANNEL_ID)
-
-  await api.tx.contentDirectory
-    .transaction({ Member: SENDER_MEMBER_ID }, [updateOperation])
-    .signAndSend(SENDER_KEYPAIR)
-}
-```
-_Full example with comments can be found in `content-directory-schemas/examples/updateChannelHandle.ts` and ran with `yarn workspace @joystream/cd-schemas example:updateChannelHandle`_
-
-Note: Updates can also inlucde `new` and `existing` keywords. In case `new` is specified inside the update - `CreateEntity` and `AddSchemaSupportToEntity` operations will be included as part of the operations returned by `InputParser.getEntityUpdateOperations`.
-
-## Current limitations
-
-Some limitations that should be dealt with in the nearest future:
-
-- Filename restrictions described in **_Input files naming_** section
-- Some code runs on the assumption that there is only one schema for each class, which is very limiting
-- `Vector<Reference>` property type is not yet supported when parsing entity batches

+ 0 - 52
content-directory-schemas/examples/createChannel.ts

@@ -1,52 +0,0 @@
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { types as joyTypes } from '@joystream/types'
-import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
-import { InputParser } from '@joystream/cd-schemas'
-import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
-
-async function main() {
-  // Initialize the api
-  const provider = new WsProvider('ws://127.0.0.1:9944')
-  const api = await ApiPromise.create({ provider, types: joyTypes })
-
-  // Get Alice keypair
-  const keyring = new Keyring()
-  keyring.addFromUri('//Alice', undefined, 'sr25519')
-  const [ALICE] = keyring.getPairs()
-
-  const channel: ChannelEntity = {
-    handle: 'Example channel',
-    description: 'This is an example channel',
-    // We can use "existing" syntax to reference either an on-chain entity or other entity that's part of the same batch.
-    // Here we reference language that we assume was added by initialization script (initialize:dev), as it is part of
-    // input/entityBatches/LanguageBatch.json
-    language: { existing: { code: 'EN' } },
-    coverPhotoUrl: '',
-    avatarPhotoUrl: '',
-    isPublic: true,
-  }
-  // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
-  const parser = InputParser.createWithKnownSchemas(
-    api,
-    // The second argument is an array of entity batches, following standard entity batch syntax ({ className, entries }):
-    [
-      {
-        className: 'Channel',
-        entries: [channel], // We could specify multiple entries here, but in this case we only need one
-      },
-    ]
-  )
-  // We parse the input into CreateEntity and AddSchemaSupportToEntity operations
-  const operations = await parser.getEntityBatchOperations()
-  await api.tx.contentDirectory
-    .transaction(
-      { Member: 0 }, // We use member with id 0 as actor (in this case we assume this is Alice)
-      operations // We provide parsed operations as second argument
-    )
-    .signAndSend(ALICE)
-}
-
-main()
-  .then(() => process.exit())
-  .catch(console.error)

+ 0 - 68
content-directory-schemas/examples/createChannelWithoutTransaction.ts

@@ -1,68 +0,0 @@
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { types as joyTypes } from '@joystream/types'
-import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
-import { InputParser } from '@joystream/cd-schemas'
-import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
-import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
-import { EntityId } from '@joystream/types/content-directory'
-
-// Alternative way of creating a channel using separate extrinsics (instead of contentDirectory.transaction)
-async function main() {
-  // Initialize the api
-  const provider = new WsProvider('ws://127.0.0.1:9944')
-  const api = await ApiPromise.create({ provider, types: joyTypes })
-
-  // Get Alice keypair
-  const keyring = new Keyring()
-  keyring.addFromUri('//Alice', undefined, 'sr25519')
-  const [ALICE] = keyring.getPairs()
-
-  const parser = InputParser.createWithKnownSchemas(api)
-
-  // In this case we need to fetch some data first (like classId and language entity id)
-  const classId = await parser.getClassIdByName('Channel')
-  const languageEntityId = await parser.findEntityIdByUniqueQuery({ code: 'EN' }, 'Language')
-
-  // We use FlattenRelations to exlude { new } and { existing } (which are not allowed if we want to parse only a single entity)
-  const channel: FlattenRelations<ChannelEntity> = {
-    handle: 'Example channel 2',
-    description: 'This is an example channel',
-    language: languageEntityId,
-    coverPhotoUrl: '',
-    avatarPhotoUrl: '',
-    isPublic: true,
-  }
-
-  // In this case we use some basic callback to retrieve entityId from the extrinsc event
-  const entityId = await new Promise<EntityId>((resolve, reject) => {
-    api.tx.contentDirectory.createEntity(classId, { Member: 0 }).signAndSend(ALICE, {}, (res) => {
-      if (res.isError) {
-        reject(new Error(res.status.type))
-      }
-      res.events.forEach(({ event: e }) => {
-        if (e.method === 'EntityCreated') {
-          resolve(e.data[1] as EntityId)
-        }
-        if (e.method === 'ExtrinsicFailed') {
-          reject(new Error('Extrinsic failed'))
-        }
-      })
-    })
-  })
-
-  const inputPropertyValuesMap = await parser.parseToInputEntityValuesMap({ ...channel }, 'Channel')
-  // Having entityId we can create and send addSchemaSupport tx
-  await api.tx.contentDirectory
-    .addSchemaSupportToEntity(
-      { Member: 0 }, // Context (in this case we assume it's Alice's member id)
-      entityId,
-      0, // Schema (currently we have one schema per class, so it can be just 0)
-      inputPropertyValuesMap
-    )
-    .signAndSend(ALICE)
-}
-
-main()
-  .then(() => process.exit())
-  .catch(console.error)

+ 0 - 76
content-directory-schemas/examples/createVideo.ts

@@ -1,76 +0,0 @@
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { types as joyTypes } from '@joystream/types'
-import { Keyring } from '@polkadot/keyring'
-// Import input parser and video entity from @joystream/cd-schemas (we use it as library here)
-import { InputParser } from '@joystream/cd-schemas'
-import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
-
-async function main() {
-  // Initialize the api
-  const provider = new WsProvider('ws://127.0.0.1:9944')
-  const api = await ApiPromise.create({ provider, types: joyTypes })
-
-  // Get Alice keypair
-  const keyring = new Keyring()
-  keyring.addFromUri('//Alice', undefined, 'sr25519')
-  const [ALICE] = keyring.getPairs()
-
-  const video: VideoEntity = {
-    title: 'Example video',
-    description: 'This is an example video',
-    // We reference existing language and category by their unique properties with "existing" syntax
-    // (those referenced here are part of inputs/entityBatches)
-    language: { existing: { code: 'EN' } },
-    category: { existing: { name: 'Education' } },
-    // We use the same "existing" syntax to reference a channel by unique property (handle)
-    // In this case it's a channel that we created in createChannel example
-    channel: { existing: { handle: 'Example channel' } },
-    media: {
-      // We use "new" syntax to sygnalize we want to create a new VideoMedia entity that will be related to this Video entity
-      new: {
-        // We use "exisiting" enconding from inputs/entityBatches/VideoMediaEncodingBatch.json
-        encoding: { existing: { name: 'H.263_MP4' } },
-        pixelHeight: 600,
-        pixelWidth: 800,
-        // We create nested VideoMedia->MediaLocation->HttpMediaLocation relations using the "new" syntax
-        location: { new: { httpMediaLocation: { new: { url: 'https://testnet.joystream.org/' } } } },
-      },
-    },
-    // Here we use combined "new" and "existing" syntaxes to create Video->License->KnownLicense relations
-    license: {
-      new: {
-        knownLicense: {
-          // This license can be found in inputs/entityBatches/KnownLicenseBatch.json
-          existing: { code: 'CC_BY' },
-        },
-      },
-    },
-    duration: 3600,
-    thumbnailUrl: '',
-    isExplicit: false,
-    isPublic: true,
-  }
-  // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
-  const parser = InputParser.createWithKnownSchemas(
-    api,
-    // The second argument is an array of entity batches, following standard entity batch syntax ({ className, entries }):
-    [
-      {
-        className: 'Video',
-        entries: [video], // We could specify multiple entries here, but in this case we only need one
-      },
-    ]
-  )
-  // We parse the input into CreateEntity and AddSchemaSupportToEntity operations
-  const operations = await parser.getEntityBatchOperations()
-  await api.tx.contentDirectory
-    .transaction(
-      { Member: 0 }, // We use member with id 0 as actor (in this case we assume this is Alice)
-      operations // We provide parsed operations as second argument
-    )
-    .signAndSend(ALICE)
-}
-
-main()
-  .then(() => process.exit())
-  .catch(console.error)

+ 0 - 47
content-directory-schemas/examples/updateChannelTitle.ts

@@ -1,47 +0,0 @@
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { types as joyTypes } from '@joystream/types'
-import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
-import { InputParser } from '@joystream/cd-schemas'
-import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
-
-async function main() {
-  // Initialize the api
-  const provider = new WsProvider('ws://127.0.0.1:9944')
-  const api = await ApiPromise.create({ provider, types: joyTypes })
-
-  // Get Alice keypair
-  const keyring = new Keyring()
-  keyring.addFromUri('//Alice', undefined, 'sr25519')
-  const [ALICE] = keyring.getPairs()
-
-  // Create partial channel entity, only containing the fields we wish to update
-  const channelUpdateInput: Partial<ChannelEntity> = {
-    handle: 'Updated channel handle',
-  }
-
-  // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
-  const parser = InputParser.createWithKnownSchemas(api)
-
-  // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
-  // created in ./createChannel.ts example (normally we would probably use some other way to do it, ie.: query node)
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel' }, 'Channel')
-
-  // Use getEntityUpdateOperations to parse the update input
-  const updateOperations = await parser.getEntityUpdateOperations(
-    channelUpdateInput,
-    'Channel', // Class name
-    CHANNEL_ID // Id of the entity we want to update
-  )
-
-  await api.tx.contentDirectory
-    .transaction(
-      { Member: 0 }, // We use member with id 0 as actor (in this case we assume this is Alice)
-      updateOperations // In this case this will be just a single UpdateEntityPropertyValues operation
-    )
-    .signAndSend(ALICE)
-}
-
-main()
-  .then(() => process.exit())
-  .catch(console.error)

+ 0 - 47
content-directory-schemas/examples/updateChannelTitleWithoutTransaction.ts

@@ -1,47 +0,0 @@
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { types as joyTypes } from '@joystream/types'
-import { Keyring } from '@polkadot/keyring'
-// Import input parser and channel entity from @joystream/cd-schemas (we use it as library here)
-import { InputParser } from '@joystream/cd-schemas'
-import { ChannelEntity } from '@joystream/cd-schemas/types/entities'
-import { FlattenRelations } from '@joystream/cd-schemas/types/utility'
-
-// Alternative way of update a channel using updateEntityPropertyValues extrinsic
-async function main() {
-  // Initialize the api
-  const provider = new WsProvider('ws://127.0.0.1:9944')
-  const api = await ApiPromise.create({ provider, types: joyTypes })
-
-  // Get Alice keypair
-  const keyring = new Keyring()
-  keyring.addFromUri('//Alice', undefined, 'sr25519')
-  const [ALICE] = keyring.getPairs()
-
-  // Create partial channel entity, only containing the fields we wish to update
-  const channelUpdateInput: Partial<FlattenRelations<ChannelEntity>> = {
-    handle: 'Updated channel handle 2',
-  }
-
-  // Create the parser with known entity schemas (the ones in content-directory-schemas/inputs)
-  const parser = InputParser.createWithKnownSchemas(api)
-
-  // We can reuse InputParser's `findEntityIdByUniqueQuery` method to find entityId of the channel we
-  // created in ./createChannelWithoutTransaction.ts example
-  // (normally we would probably use some other way to do it, ie.: query node)
-  const CHANNEL_ID = await parser.findEntityIdByUniqueQuery({ handle: 'Example channel 2' }, 'Channel')
-
-  // We use parser to create input property values map
-  const newPropertyValues = await parser.parseToInputEntityValuesMap(channelUpdateInput, 'Channel')
-
-  await api.tx.contentDirectory
-    .updateEntityPropertyValues(
-      { Member: 0 }, // We use member with id 0 as actor (in this case we assume this is Alice)
-      CHANNEL_ID,
-      newPropertyValues
-    )
-    .signAndSend(ALICE)
-}
-
-main()
-  .then(() => process.exit())
-  .catch(console.error)

+ 0 - 7
content-directory-schemas/inputs/classes/ChannelClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "Channel",
-  "description": "A channel belonging to certain member. Members can publish certain type of content (ie. videos) through channels.",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 25,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 6
content-directory-schemas/inputs/classes/ContentCategoryClass.json

@@ -1,6 +0,0 @@
-{
-  "name": "ContentCategory",
-  "description": "A category the content may be published under",
-  "maximum_entities_count": 500,
-  "default_entity_creation_voucher_upper_bound": 500
-}

+ 0 - 6
content-directory-schemas/inputs/classes/FeaturedVideoClass.json

@@ -1,6 +0,0 @@
-{
-  "name": "FeaturedVideo",
-  "description": "Featured video references",
-  "maximum_entities_count": 10,
-  "default_entity_creation_voucher_upper_bound": 10
-}

+ 0 - 7
content-directory-schemas/inputs/classes/HttpMediaLocationClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "HttpMediaLocation",
-  "description": "An object describing http location of media object",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 7
content-directory-schemas/inputs/classes/JoystreamMediaLocationClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "JoystreamMediaLocation",
-  "description": "An object describing location of media object in a format specific to Joystream platform",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 6
content-directory-schemas/inputs/classes/KnownLicenseClass.json

@@ -1,6 +0,0 @@
-{
-  "name": "KnownLicense",
-  "description": "A commonly recognized license (ie. CC_BY_SA)",
-  "maximum_entities_count": 500,
-  "default_entity_creation_voucher_upper_bound": 500
-}

+ 0 - 6
content-directory-schemas/inputs/classes/LanguageClass.json

@@ -1,6 +0,0 @@
-{
-  "name": "Language",
-  "description": "A language in which the content on the platform may be published",
-  "maximum_entities_count": 500,
-  "default_entity_creation_voucher_upper_bound": 500
-}

+ 0 - 7
content-directory-schemas/inputs/classes/LicenseClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "License",
-  "description": "Describes a license the media can be published under",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 7
content-directory-schemas/inputs/classes/MediaLocationClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "MediaLocation",
-  "description": "An object describing how the related media object can be accessed",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 7
content-directory-schemas/inputs/classes/UserDefinedLicenseClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "UserDefinedLicense",
-  "description": "Custom license defined by the user",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 7
content-directory-schemas/inputs/classes/VideoClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "Video",
-  "description": "Describes a Video",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 7
content-directory-schemas/inputs/classes/VideoMediaClass.json

@@ -1,7 +0,0 @@
-{
-  "name": "VideoMedia",
-  "description": "Describes a video media object",
-  "maximum_entities_count": 5000,
-  "default_entity_creation_voucher_upper_bound": 100,
-  "class_permissions": { "any_member": true }
-}

+ 0 - 6
content-directory-schemas/inputs/classes/VideoMediaEncodingClass.json

@@ -1,6 +0,0 @@
-{
-  "name": "VideoMediaEncoding",
-  "description": "Available encoding format for the video media",
-  "maximum_entities_count": 100,
-  "default_entity_creation_voucher_upper_bound": 50
-}

+ 0 - 18
content-directory-schemas/inputs/classes/index.js

@@ -1,18 +0,0 @@
-const EXPECTED_CLASS_ORDER = [
-  'Channel',
-  'ContentCategory',
-  'HttpMediaLocation',
-  'JoystreamMediaLocation',
-  'KnownLicense',
-  'Language',
-  'License',
-  'MediaLocation',
-  'UserDefinedLicense',
-  'Video',
-  'VideoMedia',
-  'VideoMediaEncoding',
-  'FeaturedVideo',
-]
-
-// Exports class input jsons in a predictable order
-module.exports = EXPECTED_CLASS_ORDER.map((className) => require(`./${className}Class.json`))

+ 0 - 20
content-directory-schemas/inputs/entityBatches/ContentCategoryBatch.json

@@ -1,20 +0,0 @@
-{
-  "className": "ContentCategory",
-  "entries": [
-    { "name": "Film & Animation" },
-    { "name": "Autos & Vehicles" },
-    { "name": "Music" },
-    { "name": "Pets & Animals" },
-    { "name": "Sports" },
-    { "name": "Travel & Events" },
-    { "name": "Gaming" },
-    { "name": "People & Blogs" },
-    { "name": "Comedy" },
-    { "name": "Entertainment" },
-    { "name": "News & Politics" },
-    { "name": "Howto & Style" },
-    { "name": "Education" },
-    { "name": "Science & Technology" },
-    { "name": "Nonprofits & Activism" }
-  ]
-}

+ 0 - 61
content-directory-schemas/inputs/entityBatches/KnownLicenseBatch.json

@@ -1,61 +0,0 @@
-{
-  "className": "KnownLicense",
-  "entries": [
-    {
-      "code": "PDM",
-      "name": "Public Domain",
-      "description": "For items which are not protected by copyright. This is not a license, but rather a copyright status. Some government-produced works, items with expired copyrights, and those which are ineligible for copyright protection may be included in this category.",
-      "url": "https://creativecommons.org/share-your-work/public-domain/pdm",
-      "attributionRequired": false
-    },
-    {
-      "code": "CC0",
-      "name": "Public Domain Dedication",
-      "description": "The CC0 (Public Domain Dedication) License allows creators to waive all rights to their creations and release them into the Public Domain.",
-      "url": "https://creativecommons.org/share-your-work/public-domain/cc0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY",
-      "name": "Creative Commons Attribution License",
-      "description": "Sharing and adapting this content is permitted, but attribution must be provided. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by/4.0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY_SA",
-      "name": "Creative Commons Attribution-ShareAlike License",
-      "description": "Sharing and adapting this content is permitted, but attribution must be provided. Any derivative works must be distributed under the same license. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by-sa/4.0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY_ND",
-      "name": "Creative Commons Attribution-NoDerivs License",
-      "description": "Sharing this content is permitted, but attribution must be provided. You may not remix, transform, or build upon the material. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by-nd/4.0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY_NC",
-      "name": "Creative Commons Attribution-NonCommercial License",
-      "description": "Sharing and adapting this content is permitted, but attribution must be provided. Commercial use is not permitted. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by-nc/4.0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY_NC_SA",
-      "name": "Creative Commons Attribution-NonCommercial-ShareAlike License",
-      "description": "Sharing and adapting this content is permitted, but attribution must be provided. Any derivative works must be distributed under the same license. Commercial use is not permitted. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by-nc-sa/4.0",
-      "attributionRequired": true
-    },
-    {
-      "code": "CC_BY_NC_ND",
-      "name": "Creative Commons Attribution-NonCommercial-NoDerivs License",
-      "description": "Sharing this content is permitted, but attribution must be provided. You may not remix, transform, or build upon the material. Commercial use is not permitted. Read the License Deed for more information.",
-      "url": "https://creativecommons.org/licenses/by-nc-nd/4.0",
-      "attributionRequired": true
-    }
-  ]
-}

+ 0 - 43
content-directory-schemas/inputs/entityBatches/LanguageBatch.json

@@ -1,43 +0,0 @@
-{
-  "className": "Language",
-  "entries": [
-    { "code": "EN", "name": "English" },
-    { "code": "RU", "name": "Russian" },
-    { "code": "DE", "name": "German" },
-    { "code": "IT", "name": "Italian" },
-    { "code": "ES", "name": "Spanish" },
-    { "code": "UK", "name": "Ukrainian" },
-    { "code": "CZ", "name": "Czech" },
-    { "code": "PL", "name": "Polish" },
-    { "code": "RO", "name": "Romanian" },
-    { "code": "NO", "name": "Norwegian" },
-    { "code": "AR", "name": "Arabic" },
-    { "code": "BG", "name": "Bulgarian" },
-    { "code": "ZH", "name": "Chinese" },
-    { "code": "HR", "name": "Croatian" },
-    { "code": "DA", "name": "Danish" },
-    { "code": "NL", "name": "Dutch" },
-    { "code": "FI", "name": "Finnish" },
-    { "code": "FR", "name": "French" },
-    { "code": "EL", "name": "Greek" },
-    { "code": "HI", "name": "Hindi" },
-    { "code": "HU", "name": "Hungarian" },
-    { "code": "ID", "name": "Indonesian" },
-    { "code": "GA", "name": "Irish" },
-    { "code": "IS", "name": "Icelandic" },
-    { "code": "JA", "name": "Japanese" },
-    { "code": "KO", "name": "Korean" },
-    { "code": "LT", "name": "Lithuanian" },
-    { "code": "MK", "name": "Macedonian" },
-    { "code": "PT", "name": "Portuguese" },
-    { "code": "SR", "name": "Serbian" },
-    { "code": "SK", "name": "Slovak" },
-    { "code": "SL", "name": "Slovenian" },
-    { "code": "SV", "name": "Swedish" },
-    { "code": "TH", "name": "Thai" },
-    { "code": "BO", "name": "Tibetan" },
-    { "code": "TR", "name": "Turkish" },
-    { "code": "VI", "name": "Vietnamese" },
-    { "code": "CY", "name": "Welsh" }
-  ]
-}

+ 0 - 27
content-directory-schemas/inputs/entityBatches/VideoMediaEncodingBatch.json

@@ -1,27 +0,0 @@
-{
-  "className": "VideoMediaEncoding",
-  "entries": [
-    { "name": "H.263_MP4" },
-    { "name": "H.263_3GP" },
-    { "name": "H.263_AVI" },
-    { "name": "H.264_MP4" },
-    { "name": "H.264_3GP" },
-    { "name": "H.264_AVI" },
-    { "name": "H.264_MKV" },
-    { "name": "H.265_MP4" },
-    { "name": "H.265_3GP" },
-    { "name": "H.265_AVI" },
-    { "name": "VP8_WEBM" },
-    { "name": "VP8_MP4" },
-    { "name": "VP8_AVI" },
-    { "name": "VP8_MKV" },
-    { "name": "VP9_WEBM" },
-    { "name": "VP9_MP4" },
-    { "name": "VP9_AVI" },
-    { "name": "VP9_MKV" },
-    { "name": "AV1_MP4" },
-    { "name": "MVC_MP4" },
-    { "name": "MVC_3GP" },
-    { "name": "MVC_MKV" }
-  ]
-}

+ 0 - 49
content-directory-schemas/inputs/schemas/ChannelSchema.json

@@ -1,49 +0,0 @@
-{
-  "className": "Channel",
-  "newProperties": [
-    {
-      "name": "handle",
-      "description": "The handle of the Channel",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Text": 64 } }
-    },
-    {
-      "name": "description",
-      "description": "The description of a Channel",
-      "required": true,
-      "property_type": { "Single": { "Text": 1024 } }
-    },
-    {
-      "name": "coverPhotoUrl",
-      "description": "Url for Channel's cover (background) photo. Recommended ratio: 16:9.",
-      "required": false,
-      "property_type": { "Single": { "Text": 256 } }
-    },
-    {
-      "name": "avatarPhotoUrl",
-      "description": "Channel's avatar photo.",
-      "required": false,
-      "property_type": { "Single": { "Text": 256 } }
-    },
-    {
-      "name": "isPublic",
-      "description": "Flag signaling whether a channel is public.",
-      "required": true,
-      "property_type": { "Single": "Bool" }
-    },
-    {
-      "name": "isCensored",
-      "description": "Channel censorship status set by the Curator.",
-      "required": false,
-      "property_type": { "Single": "Bool" },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "language",
-      "description": "The primary langauge of the channel's content",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "Language" } } }
-    }
-  ]
-}

+ 0 - 20
content-directory-schemas/inputs/schemas/ContentCategorySchema.json

@@ -1,20 +0,0 @@
-{
-  "className": "ContentCategory",
-  "newProperties": [
-    {
-      "name": "name",
-      "description": "The name of the category",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Text": 64 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "description",
-      "description": "The description of the category",
-      "required": false,
-      "property_type": { "Single": { "Text": 1024 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 12
content-directory-schemas/inputs/schemas/FeaturedVideoSchema.json

@@ -1,12 +0,0 @@
-{
-  "className": "FeaturedVideo",
-  "newProperties": [
-    {
-      "name": "video",
-      "description": "Reference to a video",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Reference": { "className": "Video" } } }
-    }
-  ]
-}

+ 0 - 20
content-directory-schemas/inputs/schemas/HttpMediaLocationSchema.json

@@ -1,20 +0,0 @@
-{
-  "className": "HttpMediaLocation",
-  "newProperties": [
-    {
-      "name": "url",
-      "description": "The http url pointing to the media",
-      "required": true,
-      "unique": false,
-      "property_type": { "Single": { "Text": 256 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "port",
-      "description": "The port to use when connecting to the http url (defaults to 80)",
-      "required": false,
-      "property_type": { "Single": "Uint16" },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 13
content-directory-schemas/inputs/schemas/JoystreamMediaLocationSchema.json

@@ -1,13 +0,0 @@
-{
-  "className": "JoystreamMediaLocation",
-  "newProperties": [
-    {
-      "name": "dataObjectId",
-      "description": "Id of the data object in the Joystream runtime dataDirectory module",
-      "property_type": { "Single": { "Text": 48 } },
-      "required": true,
-      "unique": true,
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 52
content-directory-schemas/inputs/schemas/KnownLicenseSchema.json

@@ -1,52 +0,0 @@
-{
-  "className": "KnownLicense",
-  "newProperties": [
-    {
-      "name": "code",
-      "description": "Short, commonly recognized code of the licence (ie. CC_BY_SA)",
-      "required": true,
-      "unique": true,
-      "property_type": {
-        "Single": { "Text": 16 }
-      },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "name",
-      "description": "Full, descriptive name of the license (ie. Creative Commons - Attribution-NonCommercial-NoDerivs)",
-      "required": false,
-      "unique": true,
-      "property_type": {
-        "Single": { "Text": 64 }
-      },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "description",
-      "description": "Short description of the license conditions",
-      "required": false,
-      "property_type": {
-        "Single": { "Text": 1024 }
-      },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "url",
-      "description": "An url pointing to full license content",
-      "required": false,
-      "property_type": {
-        "Single": { "Text": 256 }
-      },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "attributionRequired",
-      "description": "Whether this license requires an attribution",
-      "required": false,
-      "property_type": {
-        "Single": "Bool"
-      },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 20
content-directory-schemas/inputs/schemas/LanguageSchema.json

@@ -1,20 +0,0 @@
-{
-  "className": "Language",
-  "newProperties": [
-    {
-      "name": "name",
-      "description": "The name of the language (ie. English)",
-      "required": true,
-      "property_type": { "Single": { "Text": 64 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "code",
-      "description": "ISO 639-1 code of the language (ie. en)",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Text": 2 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 23
content-directory-schemas/inputs/schemas/LicenseSchema.json

@@ -1,23 +0,0 @@
-{
-  "className": "License",
-  "newProperties": [
-    {
-      "name": "knownLicense",
-      "description": "Reference to a known license",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "KnownLicense" } } }
-    },
-    {
-      "name": "userDefinedLicense",
-      "description": "Reference to user-defined license",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "UserDefinedLicense", "sameOwner": true } } }
-    },
-    {
-      "name": "attribution",
-      "description": "Attribution (if required by the license)",
-      "required": false,
-      "property_type": { "Single": { "Text": 512 } }
-    }
-  ]
-}

+ 0 - 19
content-directory-schemas/inputs/schemas/MediaLocationSchema.json

@@ -1,19 +0,0 @@
-{
-  "className": "MediaLocation",
-  "newProperties": [
-    {
-      "name": "httpMediaLocation",
-      "description": "A reference to HttpMediaLocation",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "HttpMediaLocation", "sameOwner": true } } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "joystreamMediaLocation",
-      "description": "A reference to JoystreamMediaLocation",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "JoystreamMediaLocation", "sameOwner": true } } },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 13
content-directory-schemas/inputs/schemas/UserDefinedLicenseSchema.json

@@ -1,13 +0,0 @@
-{
-  "className": "UserDefinedLicense",
-  "newProperties": [
-    {
-      "name": "content",
-      "description": "Custom license content",
-      "required": true,
-      "property_type": {
-        "Single": { "Text": 4096 }
-      }
-    }
-  ]
-}

+ 0 - 13
content-directory-schemas/inputs/schemas/VideoMediaEncodingSchema.json

@@ -1,13 +0,0 @@
-{
-  "className": "VideoMediaEncoding",
-  "newProperties": [
-    {
-      "name": "name",
-      "description": "The name of the encoding format (ie. H264_mpeg4)",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Text": 32 } },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 40
content-directory-schemas/inputs/schemas/VideoMediaSchema.json

@@ -1,40 +0,0 @@
-{
-  "className": "VideoMedia",
-  "newProperties": [
-    {
-      "name": "encoding",
-      "description": "Encoding of the video media object",
-      "required": true,
-      "property_type": { "Single": { "Reference": { "className": "VideoMediaEncoding" } } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "pixelWidth",
-      "description": "Video media width in pixels",
-      "required": true,
-      "property_type": { "Single": "Uint16" },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "pixelHeight",
-      "description": "Video media height in pixels",
-      "required": true,
-      "property_type": { "Single": "Uint16" },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "size",
-      "description": "Video media size in bytes",
-      "required": false,
-      "property_type": { "Single": "Uint64" },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "location",
-      "description": "Location of the video media object",
-      "required": true,
-      "property_type": { "Single": { "Reference": { "className": "MediaLocation", "sameOwner": true } } },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 99
content-directory-schemas/inputs/schemas/VideoSchema.json

@@ -1,99 +0,0 @@
-{
-  "className": "Video",
-  "newProperties": [
-    {
-      "name": "channel",
-      "description": "Reference to member's channel",
-      "required": true,
-      "property_type": { "Single": { "Reference": { "className": "Channel", "sameOwner": true } } }
-    },
-    {
-      "name": "category",
-      "description": "Reference to a video category",
-      "required": true,
-      "property_type": { "Single": { "Reference": { "className": "ContentCategory" } } }
-    },
-    {
-      "name": "title",
-      "description": "The title of the video",
-      "required": true,
-      "property_type": { "Single": { "Text": 64 } }
-    },
-    {
-      "name": "description",
-      "description": "The description of the Video",
-      "required": true,
-      "property_type": { "Single": { "Text": 1024 } }
-    },
-    {
-      "name": "duration",
-      "description": "Video duration in seconds",
-      "required": true,
-      "property_type": { "Single": "Uint32" }
-    },
-    {
-      "name": "skippableIntroDuration",
-      "description": "Video's kippable intro duration in seconds",
-      "required": false,
-      "property_type": { "Single": "Uint16" }
-    },
-    {
-      "name": "thumbnailUrl",
-      "description": "Video thumbnail url (recommended ratio: 16:9)",
-      "required": true,
-      "property_type": { "Single": { "Text": 256 } }
-    },
-    {
-      "name": "language",
-      "description": "Video's main langauge",
-      "required": false,
-      "property_type": { "Single": { "Reference": { "className": "Language" } } }
-    },
-    {
-      "name": "media",
-      "description": "Reference to VideoMedia",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Reference": { "className": "VideoMedia", "sameOwner": true } } },
-      "locking_policy": { "is_locked_from_controller": true }
-    },
-    {
-      "name": "hasMarketing",
-      "description": "Whether or not Video contains marketing",
-      "required": false,
-      "property_type": { "Single": "Bool" }
-    },
-    {
-      "name": "publishedBeforeJoystream",
-      "description": "If the Video was published on other platform before beeing published on Joystream - the original publication date",
-      "required": false,
-      "property_type": { "Single": "Int32" }
-    },
-    {
-      "name": "isPublic",
-      "description": "Whether the Video is supposed to be publically displayed",
-      "required": true,
-      "property_type": { "Single": "Bool" }
-    },
-    {
-      "name": "isExplicit",
-      "description": "Whether the Video contains explicit material.",
-      "required": true,
-      "property_type": { "Single": "Bool" }
-    },
-    {
-      "name": "license",
-      "description": "A License the Video is published under",
-      "required": true,
-      "unique": true,
-      "property_type": { "Single": { "Reference": { "className": "License", "sameOwner": true } } }
-    },
-    {
-      "name": "isCensored",
-      "description": "Video censorship status set by the Curator.",
-      "required": false,
-      "property_type": { "Single": "Bool" },
-      "locking_policy": { "is_locked_from_controller": true }
-    }
-  ]
-}

+ 0 - 56
content-directory-schemas/package.json

@@ -1,56 +0,0 @@
-{
-  "name": "@joystream/cd-schemas",
-  "version": "0.1.0",
-  "description": "JSON schemas, inputs and related tooling for Joystream content directory 2.0",
-  "author": "Joystream contributors",
-  "main": "lib/index.js",
-  "scripts": {
-    "build": "tsc --build tsconfig.lib.json",
-    "lint": "eslint ./ --ext .ts --ignore-path .gitignore",
-    "ts-check": "tsc --noEmit --pretty",
-    "pretty": "prettier ./ --write --ignore-path .gitignore",
-    "validate": "ts-node ./scripts/validate.ts",
-    "checks": "yarn ts-check && prettier ./ --check --ignore-path .gitignore && yarn validate && yarn lint",
-    "generate:types": "ts-node --files ./scripts/schemasToTS.ts",
-    "generate:entity-schemas": "ts-node ./scripts/inputSchemasToEntitySchemas.ts",
-    "generate:all": "yarn generate:entity-schemas && yarn generate:types",
-    "initialize:lead": "ts-node ./scripts/devInitContentLead.ts",
-    "initialize:content-dir": "ts-node ./scripts/initializeContentDir.ts",
-    "initialize:dev": "yarn initialize:lead && yarn initialize:content-dir",
-    "example:createChannel": "ts-node ./examples/createChannel.ts",
-    "example:createVideo": "ts-node ./examples/createVideo.ts",
-    "example:updateChannelHandle": "ts-node ./examples/updateChannelHandle.ts",
-    "example:createChannelWithoutTransaction": "ts-node ./examples/createChannelWithoutTransaction.ts",
-    "example:updateChannelHandlelWithoutTransaction": "ts-node ./examples/updateChannelHandleWithoutTransaction.ts"
-  },
-  "dependencies": {
-    "ajv": "6.12.5",
-    "@joystream/prettier-config": "*",
-    "@polkadot/api": "1.26.1",
-    "@polkadot/keyring": "^3.0.1",
-    "@joystream/types": "^0.16.0",
-    "@apidevtools/json-schema-ref-parser": "^9.0.6"
-  },
-  "devDependencies": {
-    "ts-node": "^8.8.2",
-    "typescript": "^3.9.7",
-    "json-schema-to-typescript": "^9.1.1"
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/Joystream/joystream.git"
-  },
-  "license": "GPL-3.0-only",
-  "bugs": {
-    "url": "https://github.com/Joystream/joystream/issues"
-  },
-  "homepage": "https://github.com/Joystream/joystream",
-  "volta": {
-    "node": "12.18.2",
-    "yarn": "1.22.4"
-  },
-  "publishConfig": {
-    "access": "public",
-    "registry": "https://registry.npmjs.org"
-  }
-}

+ 0 - 155
content-directory-schemas/schemas/extrinsics/AddClassSchema.schema.json

@@ -1,155 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-07/schema",
-  "$id": "https://joystream.org/AddClassSchema.schema.json",
-  "title": "AddClassSchema",
-  "description": "JSON schema to describe a new schema for a certain class in Joystream network",
-  "type": "object",
-  "additionalProperties": false,
-  "required": ["className", "newProperties"],
-  "properties": {
-    "className": { "type": "string" },
-    "existingProperties": {
-      "type": "array",
-      "uniqueItems": true,
-      "items": { "$ref": "#/definitions/PropertyInSchemIndex" }
-    },
-    "newProperties": {
-      "type": "array",
-      "uniqueItems": true,
-      "items": { "$ref": "#/definitions/Property" }
-    }
-  },
-  "definitions": {
-    "ClassId": {
-      "type": "integer",
-      "minimum": 1
-    },
-    "PropertyInSchemIndex": {
-      "type": "integer",
-      "minimum": 0
-    },
-    "DefaultBoolean": {
-      "type": "boolean",
-      "default": false
-    },
-    "Property": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["name", "property_type"],
-      "properties": {
-        "property_type": {
-          "oneOf": [{ "$ref": "#/definitions/SinglePropertyVariant" }, { "$ref": "#/definitions/VecPropertyVariant" }]
-        },
-        "name": { "$ref": "#/definitions/PropertyName" },
-        "description": { "$ref": "#/definitions/PropertyDescription" },
-        "required": { "$ref": "#/definitions/DefaultBoolean" },
-        "unique": { "$ref": "#/definitions/DefaultBoolean" },
-        "locking_policy": { "$ref": "#/definitions/LockingPolicy" }
-      }
-    },
-    "PropertyName": {
-      "type": "string",
-      "minLength": 1,
-      "maxLength": 49
-    },
-    "PropertyDescription": {
-      "type": "string",
-      "minLength": 1,
-      "maxLength": 500,
-      "default": ""
-    },
-    "SinglePropertyType": {
-      "oneOf": [
-        { "$ref": "#/definitions/PrimitiveProperty", "description": "Primitive property (bool/integer)" },
-        { "$ref": "#/definitions/TextProperty" },
-        { "$ref": "#/definitions/HashProperty" },
-        { "$ref": "#/definitions/ReferenceProperty" }
-      ]
-    },
-    "SinglePropertyVariant": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["Single"],
-      "properties": {
-        "Single": { "$ref": "#/definitions/SinglePropertyType" }
-      }
-    },
-    "VecPropertyType": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["vec_type", "max_length"],
-      "properties": {
-        "vec_type": { "$ref": "#/definitions/SinglePropertyType" },
-        "max_length": { "$ref": "#/definitions/MaxVecItems" }
-      }
-    },
-    "VecPropertyVariant": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["Vector"],
-      "properties": {
-        "Vector": { "$ref": "#/definitions/VecPropertyType" }
-      }
-    },
-    "PrimitiveProperty": {
-      "type": "string",
-      "enum": ["Bool", "Uint16", "Uint32", "Uint64", "Int16", "Int32", "Int64"]
-    },
-    "TextProperty": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["Text"],
-      "properties": {
-        "Text": { "$ref": "#/definitions/MaxTextLength" }
-      }
-    },
-    "HashProperty": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["Hash"],
-      "properties": {
-        "Hash": { "$ref": "#/definitions/MaxTextLength" }
-      }
-    },
-    "MaxTextLength": {
-      "type": "integer",
-      "minimum": 1,
-      "maximum": 65535
-    },
-    "MaxVecItems": {
-      "type": "integer",
-      "minimum": 1,
-      "maximum": 65535
-    },
-    "ReferenceProperty": {
-      "type": "object",
-      "additionalProperties": false,
-      "required": ["Reference"],
-      "properties": {
-        "Reference": {
-          "type": "object",
-          "additionalProperties": false,
-          "required": ["className"],
-          "properties": {
-            "className": {
-              "type": "string",
-              "description": "Referenced class name"
-            },
-            "sameOwner": {
-              "$ref": "#/definitions/DefaultBoolean",
-              "description": "Whether same owner (controller) is required"
-            }
-          }
-        }
-      }
-    },
-    "LockingPolicy": {
-      "type": "object",
-      "additionalProperties": false,
-      "properties": {
-        "is_locked_from_maintainer": { "$ref": "#/definitions/DefaultBoolean" },
-        "is_locked_from_controller": { "$ref": "#/definitions/DefaultBoolean" }
-      }
-    }
-  }
-}

+ 0 - 48
content-directory-schemas/schemas/extrinsics/CreateClass.schema.json

@@ -1,48 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-07/schema",
-  "$id": "https://joystream.org/CreateClass.schema.json",
-  "title": "CreateClass",
-  "description": "JSON schema to describe a new class for Joystream network",
-  "type": "object",
-  "additionalProperties": false,
-  "required": ["name", "description", "maximum_entities_count", "default_entity_creation_voucher_upper_bound"],
-  "properties": {
-    "name": {
-      "type": "string",
-      "description": "Name of this class. Required property.",
-      "minLength": 1,
-      "maxLength": 49
-    },
-    "description": {
-      "type": "string",
-      "description": "Description of this class.",
-      "minLength": 1,
-      "maxLength": 500
-    },
-    "class_permissions": {
-      "type": "object",
-      "additionalProperties": false,
-      "properties": {
-        "any_member": { "$ref": "#/definitions/DefaultBoolean" },
-        "entity_creation_blocked": { "$ref": "#/definitions/DefaultBoolean" },
-        "all_entity_property_values_locked": { "$ref": "#/definitions/DefaultBoolean" },
-        "maintainers": {
-          "type": "array",
-          "uniqueItems": true,
-          "items": {
-            "type": "integer"
-          },
-          "default": []
-        }
-      }
-    },
-    "maximum_entities_count": { "type": "integer" },
-    "default_entity_creation_voucher_upper_bound": { "type": "integer" }
-  },
-  "definitions": {
-    "DefaultBoolean": {
-      "type": "boolean",
-      "default": false
-    }
-  }
-}

+ 0 - 38
content-directory-schemas/schemas/propertyValidationDefs.schema.json

@@ -1,38 +0,0 @@
-{
-  "$schema": "http://json-schema.org/draft-07/schema",
-  "$id": "https://joystream.org/propertyValidationDefs.schema.json",
-  "title": "propertyValidationDefs",
-  "description": "JSON schema containing definitions for different property types input",
-  "definitions": {
-    "Bool": {
-      "type": "boolean"
-    },
-    "Uint16": {
-      "type": "integer",
-      "minimum": 0,
-      "maximum": 65535
-    },
-    "Uint32": {
-      "type": "integer",
-      "minimum": 0,
-      "maximum": 4294967295
-    },
-    "Uint64": {
-      "type": "integer",
-      "minimum": 0
-    },
-    "Int16": {
-      "type": "integer",
-      "minimum": -32768,
-      "maximum": 32767
-    },
-    "Int32": {
-      "type": "integer",
-      "minimum": -2147483648,
-      "maximum": 2147483647
-    },
-    "Int64": {
-      "type": "integer"
-    }
-  }
-}

+ 0 - 105
content-directory-schemas/scripts/devInitContentLead.ts

@@ -1,105 +0,0 @@
-import { types } from '@joystream/types'
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { SubmittableExtrinsic } from '@polkadot/api/types'
-import { ExtrinsicsHelper, getAlicePair, getKeyFromSuri } from '../src/helpers/extrinsics'
-
-async function main() {
-  // Init api
-  const WS_URI = process.env.WS_URI || 'ws://127.0.0.1:9944'
-  console.log(`Initializing the api (${WS_URI})...`)
-  const provider = new WsProvider(WS_URI)
-  const api = await ApiPromise.create({ provider, types })
-
-  const LeadKeyPair = process.env.LEAD_URI ? getKeyFromSuri(process.env.LEAD_URI) : getAlicePair()
-  const SudoKeyPair = process.env.SUDO_URI ? getKeyFromSuri(process.env.SUDO_URI) : getAlicePair()
-
-  const txHelper = new ExtrinsicsHelper(api)
-
-  const sudo = (tx: SubmittableExtrinsic<'promise'>) => api.tx.sudo.sudo(tx)
-
-  // Create membership if not already created
-  let memberId: number | undefined = (await api.query.members.memberIdsByControllerAccountId(LeadKeyPair.address))
-    .toArray()[0]
-    ?.toNumber()
-
-  // Only buy membership if LEAD_URI is not provided
-  if (memberId === undefined && process.env.LEAD_URI) {
-    throw new Error('Make sure Controller key LEAD_URI is for a member')
-  }
-
-  if (memberId === undefined) {
-    console.log('Perparing member account creation extrinsic...')
-    memberId = (await api.query.members.nextMemberId()).toNumber()
-    await txHelper.sendAndCheck(
-      LeadKeyPair,
-      [api.tx.members.buyMembership(0, 'alice', null, null)],
-      'Failed to setup member account'
-    )
-  }
-
-  console.log(`Making member id: ${memberId} the content lead.`)
-
-  // Create a new lead opening
-  if ((await api.query.contentDirectoryWorkingGroup.currentLead()).isNone) {
-    const newOpeningId = (await api.query.contentDirectoryWorkingGroup.nextOpeningId()).toNumber()
-    const newApplicationId = (await api.query.contentDirectoryWorkingGroup.nextApplicationId()).toNumber()
-    // Create curator lead opening
-    console.log('Perparing Create Curator Lead Opening extrinsic...')
-    await txHelper.sendAndCheck(
-      SudoKeyPair,
-      [
-        sudo(
-          api.tx.contentDirectoryWorkingGroup.addOpening(
-            { CurrentBlock: null }, // activate_at
-            { max_review_period_length: 9999 }, // OpeningPolicyCommitment
-            'bootstrap curator opening', // human_readable_text
-            'Leader' // opening_type
-          )
-        ),
-      ],
-      'Failed to create Content Curators Lead opening!'
-    )
-
-    // Apply to lead opening
-    console.log('Perparing Apply to Curator Lead Opening as extrinsic...')
-    await txHelper.sendAndCheck(
-      LeadKeyPair,
-      [
-        api.tx.contentDirectoryWorkingGroup.applyOnOpening(
-          memberId, // member id
-          newOpeningId, // opening id
-          LeadKeyPair.address, // address
-          null, // opt role stake
-          null, // opt appl. stake
-          'bootstrap curator opening' // human_readable_text
-        ),
-      ],
-      'Failed to apply on lead opening!'
-    )
-
-    const extrinsics: SubmittableExtrinsic<'promise'>[] = []
-    // Begin review period
-    console.log('Perparing Begin Applicant Review extrinsic...')
-    extrinsics.push(sudo(api.tx.contentDirectoryWorkingGroup.beginApplicantReview(newOpeningId)))
-
-    // Fill opening
-    console.log('Perparing Fill Opening extrinsic...')
-    extrinsics.push(
-      sudo(
-        api.tx.contentDirectoryWorkingGroup.fillOpening(
-          newOpeningId, // opening id
-          api.createType('ApplicationIdSet', [newApplicationId]), // succesful applicants
-          null // reward policy
-        )
-      )
-    )
-
-    await txHelper.sendAndCheck(SudoKeyPair, extrinsics, 'Failed to initialize Content Curators Lead!')
-  } else {
-    console.log('Curators lead already exists, skipping...')
-  }
-}
-
-main()
-  .then(() => process.exit())
-  .catch((e) => console.error(e))

+ 0 - 65
content-directory-schemas/scripts/initializeContentDir.ts

@@ -1,65 +0,0 @@
-import { types } from '@joystream/types'
-import { ApiPromise, WsProvider } from '@polkadot/api'
-import { getInitializationInputs } from '../src/helpers/inputs'
-import fs from 'fs'
-import path from 'path'
-import { InputParser } from '../src/helpers/InputParser'
-import { ExtrinsicsHelper, getAlicePair, getKeyFromSuri } from '../src/helpers/extrinsics'
-
-// Save entity operations output here for easier debugging
-const ENTITY_OPERATIONS_OUTPUT_PATH = path.join(__dirname, '../operations.json')
-
-const { classInputs, schemaInputs, entityBatchInputs } = getInitializationInputs()
-
-async function main() {
-  // Init api
-  const WS_URI = process.env.WS_URI || 'ws://127.0.0.1:9944'
-  console.log(`Initializing the api (${WS_URI})...`)
-  const provider = new WsProvider(WS_URI)
-  const api = await ApiPromise.create({ provider, types })
-
-  const LeadKeyPair = process.env.LEAD_URI ? getKeyFromSuri(process.env.LEAD_URI) : getAlicePair()
-
-  // Emptiness check
-  if ((await api.query.contentDirectory.classById.keys()).length > 0) {
-    console.log('Content directory is not empty! Skipping...')
-    process.exit()
-  }
-
-  const txHelper = new ExtrinsicsHelper(api)
-  const parser = new InputParser(api, classInputs, schemaInputs, entityBatchInputs)
-
-  console.log(`Initializing classes (${classInputs.length} input files found)...\n`)
-  const classExtrinsics = parser.getCreateClassExntrinsics()
-  await txHelper.sendAndCheck(LeadKeyPair, classExtrinsics, 'Class initialization failed!')
-
-  console.log(`Initializing schemas (${schemaInputs.length} input files found)...\n`)
-  const schemaExtrinsics = await parser.getAddSchemaExtrinsics()
-  await txHelper.sendAndCheck(LeadKeyPair, schemaExtrinsics, 'Schemas initialization failed!')
-
-  console.log(`Initializing entities (${entityBatchInputs.length} input files found)`)
-  const entityOperations = await parser.getEntityBatchOperations()
-  // Save operations in operations.json (for reference in case of errors)
-  console.log(`Saving entity batch operations in ${ENTITY_OPERATIONS_OUTPUT_PATH}...`)
-  fs.writeFileSync(
-    ENTITY_OPERATIONS_OUTPUT_PATH,
-    JSON.stringify(
-      entityOperations.map((o) => o.toJSON()),
-      null,
-      4
-    )
-  )
-  console.log(`Sending Transaction extrinsic (${entityOperations.length} operations)...`)
-  await txHelper.sendAndCheck(
-    LeadKeyPair,
-    [api.tx.contentDirectory.transaction({ Lead: null }, entityOperations)],
-    'Entity initialization failed!'
-  )
-}
-
-main()
-  .then(() => process.exit())
-  .catch((e) => {
-    console.error(e)
-    process.exit(-1)
-  })

+ 0 - 163
content-directory-schemas/scripts/inputSchemasToEntitySchemas.ts

@@ -1,163 +0,0 @@
-import fs from 'fs'
-import path from 'path'
-import {
-  AddClassSchema,
-  HashProperty,
-  Property,
-  ReferenceProperty,
-  SinglePropertyVariant,
-  TextProperty,
-  VecPropertyVariant,
-} from '../types/extrinsics/AddClassSchema'
-import PRIMITIVE_PROPERTY_DEFS from '../schemas/propertyValidationDefs.schema.json'
-import { getInputs } from '../src/helpers/inputs'
-import { getSchemasLocation, SCHEMA_TYPES } from '../src/helpers/schemas'
-import { JSONSchema7, JSONSchema7TypeName } from 'json-schema'
-
-const schemaInputs = getInputs<AddClassSchema>('schemas')
-
-const strictObjectDef = (def: Record<string, any>): JSONSchema7 => ({
-  type: 'object',
-  additionalProperties: false,
-  ...def,
-})
-
-const onePropertyObjectDef = (propertyName: string, propertyDef: Record<string, any>): JSONSchema7 =>
-  strictObjectDef({
-    required: [propertyName],
-    properties: {
-      [propertyName]: propertyDef,
-    },
-  })
-
-const TextPropertyDef = ({ Text: maxLength }: TextProperty): JSONSchema7 => ({
-  type: 'string',
-  maxLength,
-})
-
-const HashPropertyDef = ({ Hash: maxLength }: HashProperty): JSONSchema7 => ({
-  type: 'string',
-  maxLength,
-})
-
-const ReferencePropertyDef = ({ Reference: ref }: ReferenceProperty): JSONSchema7 => ({
-  'oneOf': [
-    onePropertyObjectDef('new', { '$ref': `../entities/${ref.className}Entity.schema.json` }),
-    onePropertyObjectDef('existing', { '$ref': `../entityReferences/${ref.className}Ref.schema.json` }),
-    PRIMITIVE_PROPERTY_DEFS.definitions.Uint64 as JSONSchema7,
-  ],
-})
-
-const SinglePropertyDef = ({ Single: singlePropType }: SinglePropertyVariant): JSONSchema7 => {
-  if (typeof singlePropType === 'string') {
-    return PRIMITIVE_PROPERTY_DEFS.definitions[singlePropType] as JSONSchema7
-  } else if ((singlePropType as TextProperty).Text) {
-    return TextPropertyDef(singlePropType as TextProperty)
-  } else if ((singlePropType as HashProperty).Hash) {
-    return HashPropertyDef(singlePropType as HashProperty)
-  } else if ((singlePropType as ReferenceProperty).Reference) {
-    return ReferencePropertyDef(singlePropType as ReferenceProperty)
-  }
-
-  throw new Error(`Unknown single proprty type: ${JSON.stringify(singlePropType)}`)
-}
-
-const VecPropertyDef = ({ Vector: vec }: VecPropertyVariant): JSONSchema7 => ({
-  type: 'array',
-  maxItems: vec.max_length,
-  'items': SinglePropertyDef({ Single: vec.vec_type }),
-})
-
-const PropertyDef = ({ property_type: propertyType, description, required }: Property): JSONSchema7 => {
-  const def = {
-    ...((propertyType as SinglePropertyVariant).Single
-      ? SinglePropertyDef(propertyType as SinglePropertyVariant)
-      : VecPropertyDef(propertyType as VecPropertyVariant)),
-    description,
-  }
-  // Non-required fields:
-  // Simple fields:
-  if (!required && def.type) {
-    def.type = [def.type as JSONSchema7TypeName, 'null']
-  }
-  // Relationships:
-  else if (!required && def.oneOf) {
-    def.oneOf = [...def.oneOf, { type: 'null' }]
-  }
-
-  return def
-}
-
-// Mkdir entity schemas directories if they do not exist
-SCHEMA_TYPES.forEach((type) => {
-  if (!fs.existsSync(getSchemasLocation(type))) {
-    fs.mkdirSync(getSchemasLocation(type))
-  }
-})
-
-// Run schema conversion:
-schemaInputs.forEach(({ fileName, data: inputData }) => {
-  const schemaName = fileName.replace('Schema.json', '')
-
-  if (inputData.newProperties && !inputData.existingProperties) {
-    const properites = inputData.newProperties
-    const propertiesObj = properites.reduce((pObj, p) => {
-      pObj[p.name] = PropertyDef(p)
-      return pObj
-    }, {} as Record<string, ReturnType<typeof PropertyDef>>)
-
-    const EntitySchema: JSONSchema7 = {
-      $schema: 'http://json-schema.org/draft-07/schema',
-      $id: `https://joystream.org/entities/${schemaName}Entity.schema.json`,
-      title: `${schemaName}Entity`,
-      description: `JSON schema for entities based on ${schemaName} runtime schema`,
-      ...strictObjectDef({
-        required: properites.filter((p) => p.required).map((p) => p.name),
-        properties: propertiesObj,
-      }),
-    }
-
-    const ReferenceSchema: JSONSchema7 = {
-      $schema: 'http://json-schema.org/draft-07/schema',
-      $id: `https://joystream.org/entityReferences/${schemaName}Ref.schema.json`,
-      title: `${schemaName}Reference`,
-      description: `JSON schema for reference to ${schemaName} entity based on runtime schema`,
-      anyOf: [
-        ...properites.filter((p) => p.required && p.unique).map((p) => onePropertyObjectDef(p.name, PropertyDef(p))),
-        PRIMITIVE_PROPERTY_DEFS.definitions.Uint64 as JSONSchema7,
-      ],
-    }
-
-    const BatchSchema: JSONSchema7 = {
-      $schema: 'http://json-schema.org/draft-07/schema',
-      $id: `https://joystream.org/entityBatches/${schemaName}Batch.schema.json`,
-      title: `${schemaName}Batch`,
-      description: `JSON schema for batch of entities based on ${schemaName} runtime schema`,
-      ...strictObjectDef({
-        required: ['className', 'entries'],
-        properties: {
-          className: { type: 'string' },
-          entries: {
-            type: 'array',
-            items: { '$ref': `../entities/${schemaName}Entity.schema.json` },
-          },
-        },
-      }),
-    }
-
-    const entitySchemaPath = path.join(getSchemasLocation('entities'), `${schemaName}Entity.schema.json`)
-    fs.writeFileSync(entitySchemaPath, JSON.stringify(EntitySchema, undefined, 4))
-    console.log(`${entitySchemaPath} succesfully generated!`)
-
-    const entityReferenceSchemaPath = path.join(getSchemasLocation('entityReferences'), `${schemaName}Ref.schema.json`)
-    fs.writeFileSync(entityReferenceSchemaPath, JSON.stringify(ReferenceSchema, undefined, 4))
-    console.log(`${entityReferenceSchemaPath} succesfully generated!`)
-
-    const batchOfEntitiesSchemaPath = path.join(getSchemasLocation('entityBatches'), `${schemaName}Batch.schema.json`)
-    fs.writeFileSync(batchOfEntitiesSchemaPath, JSON.stringify(BatchSchema, undefined, 4))
-    console.log(`${batchOfEntitiesSchemaPath} succesfully generated!`)
-  } else {
-    console.log('WARNING: Schemas with "existingProperties" not supported yet!')
-    console.log('Skipping...')
-  }
-})

+ 0 - 56
content-directory-schemas/scripts/schemasToTS.ts

@@ -1,56 +0,0 @@
-import fs from 'fs'
-import path from 'path'
-import { compileFromFile } from 'json-schema-to-typescript'
-// TODO: This will require publishing @joystream/prettier-config if we want to include it in joystream-js
-import prettierConfig from '@joystream/prettier-config'
-
-const SCHEMAS_LOCATION = path.join(__dirname, '../schemas')
-const OUTPUT_TYPES_LOCATION = path.join(__dirname, '../types')
-
-const SUBDIRS_INCLUDED = ['extrinsics', 'entities'] as const
-
-async function main() {
-  // Create typescript files
-  for (const subdirName of fs.readdirSync(SCHEMAS_LOCATION)) {
-    if (!SUBDIRS_INCLUDED.includes(subdirName as any)) {
-      console.log(`Subdir/filename not included: ${subdirName} - skipping...`)
-      continue
-    }
-    const schemaSubdir = subdirName as typeof SUBDIRS_INCLUDED[number]
-    const indexExportedTypes: string[] = []
-    for (const schemaFilename of fs.readdirSync(path.join(SCHEMAS_LOCATION, schemaSubdir))) {
-      const schemaFilePath = path.join(SCHEMAS_LOCATION, schemaSubdir, schemaFilename)
-      const mainTypeName = schemaFilename.replace('.schema.json', '')
-      const outputFilename = mainTypeName + '.d.ts'
-      indexExportedTypes.push(mainTypeName)
-      const outputDir = path.join(OUTPUT_TYPES_LOCATION, schemaSubdir)
-      if (!fs.existsSync(outputDir)) {
-        fs.mkdirSync(outputDir)
-      }
-      const outputFilePath = path.join(outputDir, outputFilename)
-      try {
-        await compileFromFile(schemaFilePath, {
-          cwd: path.join(SCHEMAS_LOCATION, schemaSubdir),
-          style: prettierConfig,
-        }).then((ts) => {
-          fs.writeFileSync(outputFilePath, ts)
-          console.log(`${outputFilePath} succesfully generated!`)
-        })
-      } catch (e) {
-        console.log(`${outputFilePath} compilation FAILED!`)
-        console.error(e)
-      }
-    }
-    // Generate main index.d.ts export file for entities
-    const indexFilePath = path.join(OUTPUT_TYPES_LOCATION, schemaSubdir, 'index.d.ts')
-    fs.writeFileSync(
-      indexFilePath,
-      indexExportedTypes.reduce((content, typeName) => (content += `export { ${typeName} } from './${typeName}'\n`), '')
-    )
-    console.log(`${indexFilePath} succesfully generated!`)
-  }
-}
-
-main()
-  .then(() => process.exit())
-  .catch((e) => console.error(e))

+ 0 - 85
content-directory-schemas/scripts/validate.ts

@@ -1,85 +0,0 @@
-// TODO: Add entity batches validation
-import Ajv from 'ajv'
-import { FetchedInput, getInputs, InputType, INPUT_TYPES } from '../src/helpers/inputs'
-import path from 'path'
-import fs from 'fs'
-import $RefParser from '@apidevtools/json-schema-ref-parser'
-
-const SCHEMAS_LOCATION = path.join(__dirname, '../schemas')
-
-const ajv = new Ajv({ allErrors: true })
-
-const validateJsonSchema = (jsonSchemaShortPath: string, jsonSchema: Record<string, unknown>) => {
-  if (!ajv.validateSchema(jsonSchema)) {
-    console.log(`\nERROR! ${jsonSchemaShortPath} - schema validation failed!`)
-    console.log(ajv.errorsText(undefined, { separator: '\n' }))
-    console.log('\n')
-    process.exitCode = 100
-
-    return false
-  }
-
-  return true
-}
-
-const validateInputAgainstSchema = (input: FetchedInput, jsonSchema: Record<string, unknown>) => {
-  if (!ajv.validate(jsonSchema, input.data)) {
-    console.log(`\nERROR! ${input.fileName} - validation failed!`)
-    console.log(ajv.errorsText(undefined, { separator: '\n' }))
-    console.log('\n')
-    process.exitCode = 100
-
-    return false
-  }
-
-  return true
-}
-
-const getJsonSchemaForInput = (inputType: InputType, input: FetchedInput) => {
-  let schemaLocation = ''
-  if (inputType === 'classes') {
-    schemaLocation = path.join(SCHEMAS_LOCATION, 'extrinsics', 'CreateClass.schema.json')
-  }
-  if (inputType === 'schemas') {
-    schemaLocation = path.join(SCHEMAS_LOCATION, 'extrinsics', 'AddClassSchema.schema.json')
-  }
-  if (inputType === 'entityBatches') {
-    const jsonSchemaFilename = input.fileName.replace('.json', '.schema.json')
-    schemaLocation = path.join(SCHEMAS_LOCATION, 'entityBatches', jsonSchemaFilename)
-  }
-
-  return {
-    jsonSchemaPath: schemaLocation,
-    jsonSchema: JSON.parse(fs.readFileSync(schemaLocation).toString()),
-  }
-}
-
-async function main() {
-  const alreadyValidatedJsonSchemas = new Map<string, boolean>()
-  for (const inputType of INPUT_TYPES) {
-    console.log(`Validating inputs/${inputType} and related json-schemas...\n`)
-    for (const input of getInputs(inputType)) {
-      let { jsonSchemaPath, jsonSchema } = getJsonSchemaForInput(inputType, input)
-      jsonSchema = await $RefParser.dereference(jsonSchemaPath, jsonSchema)
-      const jsonSchemaShortPath = path.relative(path.join(SCHEMAS_LOCATION, '..'), jsonSchemaPath)
-      // Validate the schema itself
-      let isJsonSchemaValid = alreadyValidatedJsonSchemas.get(jsonSchemaShortPath)
-      if (isJsonSchemaValid === undefined) {
-        console.log(`Validating ${jsonSchemaShortPath}...`)
-        isJsonSchemaValid = validateJsonSchema(jsonSchemaShortPath, jsonSchema)
-        alreadyValidatedJsonSchemas.set(jsonSchemaShortPath, isJsonSchemaValid)
-      }
-      if (!isJsonSchemaValid) {
-        return
-      }
-      console.log(`Validating inputs/${inputType}/${input.fileName}...`)
-      validateInputAgainstSchema(input, jsonSchema)
-    }
-
-    console.log('\n\n')
-  }
-}
-
-main()
-  .then(() => process.exit())
-  .catch((e) => console.error(e))

+ 0 - 435
content-directory-schemas/src/helpers/InputParser.ts

@@ -1,435 +0,0 @@
-import { AddClassSchema, Property } from '../../types/extrinsics/AddClassSchema'
-import { createType } from '@joystream/types'
-import {
-  InputEntityValuesMap,
-  ClassId,
-  OperationType,
-  ParametrizedPropertyValue,
-  PropertyId,
-  PropertyType,
-  EntityId,
-  Entity,
-  ParametrizedClassPropertyValue,
-  InputPropertyValue,
-} from '@joystream/types/content-directory'
-import { blake2AsHex } from '@polkadot/util-crypto'
-import { isSingle, isReference } from './propertyType'
-import { ApiPromise } from '@polkadot/api'
-import { JoyBTreeSet } from '@joystream/types/common'
-import { CreateClass } from '../../types/extrinsics/CreateClass'
-import { EntityBatch } from '../../types/EntityBatch'
-import { getInitializationInputs, getInputs } from './inputs'
-
-type SimpleEntityValue = string | boolean | number | string[] | boolean[] | number[] | undefined | null
-// Input without "new" or "extising" keywords
-type SimpleEntityInput = { [K: string]: SimpleEntityValue }
-
-export class InputParser {
-  private api: ApiPromise
-  private classInputs: CreateClass[]
-  private schemaInputs: AddClassSchema[]
-  private batchInputs: EntityBatch[]
-  private createEntityOperations: OperationType[] = []
-  private addSchemaToEntityOprations: OperationType[] = []
-  private updateEntityPropertyValuesOperations: OperationType[] = []
-  private entityIndexByUniqueQueryMap = new Map<string, number>()
-  private entityIdByUniqueQueryMap = new Map<string, number>()
-  private entityByUniqueQueryCurrentIndex = 0
-  private classIdByNameMap = new Map<string, number>()
-
-  static createWithInitialInputs(api: ApiPromise): InputParser {
-    const { classInputs, schemaInputs, entityBatchInputs } = getInitializationInputs()
-    return new InputParser(api, classInputs, schemaInputs, entityBatchInputs)
-  }
-
-  static createWithKnownSchemas(api: ApiPromise, entityBatches?: EntityBatch[]): InputParser {
-    return new InputParser(
-      api,
-      [],
-      getInputs<AddClassSchema>('schemas').map(({ data }) => data),
-      entityBatches
-    )
-  }
-
-  constructor(
-    api: ApiPromise,
-    classInputs?: CreateClass[],
-    schemaInputs?: AddClassSchema[],
-    batchInputs?: EntityBatch[]
-  ) {
-    this.api = api
-    this.classInputs = classInputs || []
-    this.schemaInputs = schemaInputs || []
-    this.batchInputs = batchInputs || []
-  }
-
-  private async loadClassMap() {
-    this.classIdByNameMap = new Map<string, number>()
-
-    const classEntries = await this.api.query.contentDirectory.classById.entries()
-    classEntries.forEach(([key, aClass]) => {
-      this.classIdByNameMap.set(aClass.name.toString(), (key.args[0] as ClassId).toNumber())
-    })
-  }
-
-  private async loadEntityIdByUniqueQueryMap() {
-    this.entityIdByUniqueQueryMap = new Map<string, number>()
-
-    // Get entity entries
-    const entityEntries: [EntityId, Entity][] = (
-      await this.api.query.contentDirectory.entityById.entries()
-    ).map(([storageKey, entity]) => [storageKey.args[0] as EntityId, entity])
-
-    // Since we use classMap directly we need to make sure it's loaded first
-    if (!this.classIdByNameMap.size) {
-      await this.loadClassMap()
-    }
-
-    entityEntries.forEach(([entityId, entity]) => {
-      const classId = entity.class_id.toNumber()
-      const className = Array.from(this.classIdByNameMap.entries()).find(([, id]) => id === classId)?.[0]
-      if (!className) {
-        // Class not found - skip
-        return
-      }
-      let schema: AddClassSchema
-      try {
-        schema = this.schemaByClassName(className)
-      } catch (e) {
-        // Input schema not found - skip
-        return
-      }
-      const valuesEntries = Array.from(entity.getField('values').entries())
-      schema.newProperties.forEach(({ name, unique }, index) => {
-        if (!unique) {
-          return // Skip non-unique properties
-        }
-        const storedValue = valuesEntries.find(([propertyId]) => propertyId.toNumber() === index)?.[1]
-        if (
-          storedValue === undefined ||
-          // If unique value is Bool, it's almost definitely empty, so we skip it
-          (storedValue.isOfType('Single') && storedValue.asType('Single').isOfType('Bool'))
-        ) {
-          // Skip empty values (not all unique properties are required)
-          return
-        }
-        const simpleValue = storedValue.getValue().toJSON()
-        const hash = this.getUniqueQueryHash({ [name]: simpleValue }, schema.className)
-        this.entityIdByUniqueQueryMap.set(hash, entityId.toNumber())
-      })
-    })
-  }
-
-  private schemaByClassName(className: string) {
-    const foundSchema = this.schemaInputs.find((data) => data.className === className)
-    if (!foundSchema) {
-      throw new Error(`Schema not found by class name: ${className}`)
-    }
-
-    return foundSchema
-  }
-
-  private getUniqueQueryHash(uniquePropVal: Record<string, any>, className: string) {
-    return blake2AsHex(JSON.stringify([className, uniquePropVal]))
-  }
-
-  private findEntityIndexByUniqueQuery(uniquePropVal: Record<string, any>, className: string) {
-    const hash = this.getUniqueQueryHash(uniquePropVal, className)
-    const foundIndex = this.entityIndexByUniqueQueryMap.get(hash)
-    if (foundIndex === undefined) {
-      throw new Error(
-        `findEntityIndexByUniqueQuery failed for class ${className} and query: ${JSON.stringify(uniquePropVal)}`
-      )
-    }
-
-    return foundIndex
-  }
-
-  // Seatch for entity by { [uniquePropName]: [uniquePropVal] } on chain
-  async findEntityIdByUniqueQuery(uniquePropVal: Record<string, any>, className: string): Promise<number> {
-    const hash = this.getUniqueQueryHash(uniquePropVal, className)
-    let foundId = this.entityIdByUniqueQueryMap.get(hash)
-    if (foundId === undefined) {
-      // Try to re-load the map and find again
-      await this.loadEntityIdByUniqueQueryMap()
-      foundId = this.entityIdByUniqueQueryMap.get(hash)
-      if (foundId === undefined) {
-        // If still not found - throw
-        throw new Error(
-          `findEntityIdByUniqueQuery failed for class ${className} and query: ${JSON.stringify(uniquePropVal)}`
-        )
-      }
-    }
-    return foundId
-  }
-
-  async getClassIdByName(className: string): Promise<number> {
-    let classId = this.classIdByNameMap.get(className)
-    if (classId === undefined) {
-      // Try to re-load the map
-      await this.loadClassMap()
-      classId = this.classIdByNameMap.get(className)
-      if (classId === undefined) {
-        // If still not found - throw
-        throw new Error(`Could not find class id by name: "${className}"!`)
-      }
-    }
-    return classId
-  }
-
-  private async parsePropertyType(propertyType: Property['property_type']): Promise<PropertyType> {
-    if (isSingle(propertyType) && isReference(propertyType.Single)) {
-      const { className, sameOwner } = propertyType.Single.Reference
-      const classId = await this.getClassIdByName(className)
-      return createType('PropertyType', { Single: { Reference: [classId, sameOwner] } })
-    }
-    // Types other than reference are fully compatible
-    return createType('PropertyType', propertyType)
-  }
-
-  private includeEntityInputInUniqueQueryMap(entityInput: Record<string, any>, schema: AddClassSchema) {
-    Object.entries(entityInput)
-      .filter(([, pValue]) => pValue !== undefined)
-      .forEach(([propertyName, propertyValue]) => {
-        const schemaPropertyType = schema.newProperties.find((p) => p.name === propertyName)!.property_type
-        // Handle entities "nested" via "new"
-        if (isSingle(schemaPropertyType) && isReference(schemaPropertyType.Single)) {
-          if (propertyValue !== null && Object.keys(propertyValue).includes('new')) {
-            const refEntitySchema = this.schemaByClassName(schemaPropertyType.Single.Reference.className)
-            this.includeEntityInputInUniqueQueryMap(propertyValue.new, refEntitySchema)
-          }
-        }
-      })
-    // Add entries to entityIndexByUniqueQueryMap
-    schema.newProperties
-      .filter((p) => p.unique)
-      .forEach(({ name }) => {
-        if (entityInput[name] === undefined) {
-          // Skip empty values (not all unique properties are required)
-          return
-        }
-        const hash = this.getUniqueQueryHash({ [name]: entityInput[name] }, schema.className)
-        this.entityIndexByUniqueQueryMap.set(hash, this.entityByUniqueQueryCurrentIndex)
-      })
-    ++this.entityByUniqueQueryCurrentIndex
-  }
-
-  private async createParametrizedPropertyValues(
-    entityInput: Record<string, any>,
-    schema: AddClassSchema,
-    customHandler?: (property: Property, value: any) => Promise<ParametrizedPropertyValue | undefined>
-  ): Promise<ParametrizedClassPropertyValue[]> {
-    const filteredInput = Object.entries(entityInput).filter(([, pValue]) => pValue !== undefined)
-    const parametrizedClassPropValues: ParametrizedClassPropertyValue[] = []
-
-    for (const [propertyName, propertyValue] of filteredInput) {
-      const schemaPropertyIndex = schema.newProperties.findIndex((p) => p.name === propertyName)
-      const schemaProperty = schema.newProperties[schemaPropertyIndex]
-
-      let value = customHandler && (await customHandler(schemaProperty, propertyValue))
-      if (value === undefined) {
-        if (propertyValue === null) {
-          // Optional values: (can be cleared by setting them to Bool(false)):
-          value = createType('ParametrizedPropertyValue', { InputPropertyValue: { Single: { Bool: false } } })
-        } else {
-          value = createType('ParametrizedPropertyValue', {
-            InputPropertyValue: (await this.parsePropertyType(schemaProperty.property_type)).toInputPropertyValue(
-              propertyValue
-            ),
-          })
-        }
-      }
-
-      parametrizedClassPropValues.push(
-        createType('ParametrizedClassPropertyValue', {
-          in_class_index: schemaPropertyIndex,
-          value,
-        })
-      )
-    }
-
-    return parametrizedClassPropValues
-  }
-
-  private async existingEntityQueryToParametrizedPropertyValue(className: string, uniquePropVal: Record<string, any>) {
-    try {
-      // First - try to find in existing batches
-      const entityIndex = this.findEntityIndexByUniqueQuery(uniquePropVal, className)
-      return createType('ParametrizedPropertyValue', { InternalEntityJustAdded: entityIndex })
-    } catch (e) {
-      // If not found - fallback to chain search
-      const entityId = await this.findEntityIdByUniqueQuery(uniquePropVal, className)
-      return createType('ParametrizedPropertyValue', {
-        InputPropertyValue: { Single: { Reference: entityId } },
-      })
-    }
-  }
-
-  // parseEntityInput Overloads
-  private parseEntityInput(entityInput: Record<string, any>, schema: AddClassSchema): Promise<number>
-  private parseEntityInput(
-    entityInput: Record<string, any>,
-    schema: AddClassSchema,
-    updatedEntityId: number
-  ): Promise<void>
-
-  // Parse entity input. Speficy "updatedEntityId" only if want to parse into update operation!
-  private async parseEntityInput(
-    entityInput: Record<string, any>,
-    schema: AddClassSchema,
-    updatedEntityId?: number
-  ): Promise<void | number> {
-    const parametrizedPropertyValues = await this.createParametrizedPropertyValues(
-      entityInput,
-      schema,
-      async (property, value) => {
-        // Custom handler for references
-        const { property_type: propertyType } = property
-        if (isSingle(propertyType) && isReference(propertyType.Single)) {
-          const refEntitySchema = this.schemaByClassName(propertyType.Single.Reference.className)
-          if (value !== null && Object.keys(value).includes('new')) {
-            const entityIndex = await this.parseEntityInput(value.new, refEntitySchema)
-            return createType('ParametrizedPropertyValue', { InternalEntityJustAdded: entityIndex })
-          } else if (value !== null && Object.keys(value).includes('existing')) {
-            return this.existingEntityQueryToParametrizedPropertyValue(refEntitySchema.className, value.existing)
-          }
-        }
-        return undefined
-      }
-    )
-
-    if (updatedEntityId) {
-      // Update operation
-      this.updateEntityPropertyValuesOperations.push(
-        createType('OperationType', {
-          UpdatePropertyValues: {
-            entity_id: { ExistingEntity: updatedEntityId },
-            new_parametrized_property_values: parametrizedPropertyValues,
-          },
-        })
-      )
-    } else {
-      // Add operations (createEntity, AddSchemaSupportToEntity)
-      const createEntityOperationIndex = this.createEntityOperations.length
-      const classId = await this.getClassIdByName(schema.className)
-      this.createEntityOperations.push(createType('OperationType', { CreateEntity: { class_id: classId } }))
-      this.addSchemaToEntityOprations.push(
-        createType('OperationType', {
-          AddSchemaSupportToEntity: {
-            schema_id: 0,
-            entity_id: { InternalEntityJustAdded: createEntityOperationIndex },
-            parametrized_property_values: parametrizedPropertyValues,
-          },
-        })
-      )
-
-      // Return CreateEntity operation index
-      return createEntityOperationIndex
-    }
-  }
-
-  private reset() {
-    this.entityIndexByUniqueQueryMap = new Map<string, number>()
-    this.classIdByNameMap = new Map<string, number>()
-
-    this.createEntityOperations = []
-    this.addSchemaToEntityOprations = []
-    this.updateEntityPropertyValuesOperations = []
-
-    this.entityByUniqueQueryCurrentIndex = 0
-  }
-
-  public async getEntityBatchOperations() {
-    // First - create entityUniqueQueryMap to allow referencing any entity at any point
-    this.batchInputs.forEach((batch) => {
-      const entitySchema = this.schemaByClassName(batch.className)
-      batch.entries.forEach((entityInput) => this.includeEntityInputInUniqueQueryMap(entityInput, entitySchema))
-    })
-    // Then - parse into actual operations
-    for (const batch of this.batchInputs) {
-      const entitySchema = this.schemaByClassName(batch.className)
-      for (const entityInput of batch.entries) {
-        await this.parseEntityInput(entityInput, entitySchema)
-      }
-    }
-
-    const operations = [...this.createEntityOperations, ...this.addSchemaToEntityOprations]
-    this.reset()
-
-    return operations
-  }
-
-  public async getEntityUpdateOperations(
-    input: Record<string, any>,
-    className: string,
-    entityId: number
-  ): Promise<OperationType[]> {
-    const schema = this.schemaByClassName(className)
-    await this.parseEntityInput(input, schema, entityId)
-    const operations = [
-      ...this.createEntityOperations,
-      ...this.addSchemaToEntityOprations,
-      ...this.updateEntityPropertyValuesOperations,
-    ]
-    this.reset()
-
-    return operations
-  }
-
-  public async parseAddClassSchemaExtrinsic(inputData: AddClassSchema) {
-    const classId = await this.getClassIdByName(inputData.className)
-    const newProperties = await Promise.all(
-      inputData.newProperties.map(async (p) => ({
-        ...p,
-        // Parse different format for Reference (and potentially other propTypes in the future)
-        property_type: (await this.parsePropertyType(p.property_type)).toJSON(),
-      }))
-    )
-    return this.api.tx.contentDirectory.addClassSchema(
-      classId,
-      new (JoyBTreeSet(PropertyId))(this.api.registry, inputData.existingProperties),
-      newProperties
-    )
-  }
-
-  public parseCreateClassExtrinsic(inputData: CreateClass) {
-    return this.api.tx.contentDirectory.createClass(
-      inputData.name,
-      inputData.description,
-      inputData.class_permissions || {},
-      inputData.maximum_entities_count,
-      inputData.default_entity_creation_voucher_upper_bound
-    )
-  }
-
-  public async getAddSchemaExtrinsics() {
-    return await Promise.all(this.schemaInputs.map((data) => this.parseAddClassSchemaExtrinsic(data)))
-  }
-
-  public getCreateClassExntrinsics() {
-    return this.classInputs.map((data) => this.parseCreateClassExtrinsic(data))
-  }
-
-  // Helper parser for "standalone" extrinsics like addSchemaSupportToEntity / updateEntityPropertyValues
-  public async parseToInputEntityValuesMap(
-    inputData: SimpleEntityInput,
-    className: string
-  ): Promise<InputEntityValuesMap> {
-    await this.parseEntityInput(inputData, this.schemaByClassName(className))
-    const inputPropValMap = new Map<PropertyId, InputPropertyValue>()
-
-    const [operation] = this.addSchemaToEntityOprations
-    operation
-      .asType('AddSchemaSupportToEntity')
-      .parametrized_property_values /* First we need to sort by propertyId, since otherwise there will be issues
-      when encoding the BTreeMap (similar to BTreeSet) */
-      .sort((a, b) => a.in_class_index.toNumber() - b.in_class_index.toNumber())
-      .map((pcpv) => {
-        inputPropValMap.set(pcpv.in_class_index, pcpv.value.asType('InputPropertyValue'))
-      })
-
-    this.reset()
-
-    return createType('InputEntityValuesMap', inputPropValMap)
-  }
-}

+ 0 - 86
content-directory-schemas/src/helpers/extrinsics.ts

@@ -1,86 +0,0 @@
-import { Keyring } from '@polkadot/keyring'
-import { KeyringPair } from '@polkadot/keyring/types'
-import { ApiPromise } from '@polkadot/api'
-import { SubmittableExtrinsic } from '@polkadot/api/types'
-import { DispatchError } from '@polkadot/types/interfaces/system'
-import { TypeRegistry } from '@polkadot/types'
-
-// TODO: Move to @joystream/js soon
-
-export function getAlicePair(): KeyringPair {
-  const keyring = new Keyring({ type: 'sr25519' })
-  keyring.addFromUri('//Alice', { name: 'Alice' })
-  const ALICE = keyring.getPairs()[0]
-
-  return ALICE
-}
-
-export function getKeyFromSuri(suri: string): KeyringPair {
-  const keyring = new Keyring({ type: 'sr25519' })
-
-  // Assume a SURI, add to keyring and return keypair
-  return keyring.addFromUri(suri)
-}
-
-export class ExtrinsicsHelper {
-  api: ApiPromise
-  noncesByAddress: Map<string, number>
-
-  constructor(api: ApiPromise, initialNonces?: [string, number][]) {
-    this.api = api
-    this.noncesByAddress = new Map<string, number>(initialNonces)
-  }
-
-  private async nextNonce(address: string): Promise<number> {
-    const nonce = this.noncesByAddress.get(address) || (await this.api.query.system.account(address)).nonce.toNumber()
-    this.noncesByAddress.set(address, nonce + 1)
-
-    return nonce
-  }
-
-  async sendAndCheck(sender: KeyringPair, extrinsics: SubmittableExtrinsic<'promise'>[], errorMessage: string) {
-    const promises: Promise<void>[] = []
-    for (const tx of extrinsics) {
-      const nonce = await this.nextNonce(sender.address)
-      promises.push(
-        new Promise((resolve, reject) => {
-          tx.signAndSend(sender, { nonce }, (result) => {
-            let txError: string | null = null
-            if (result.isError) {
-              txError = `Transaction failed with status: ${result.status.type}`
-              reject(new Error(`${errorMessage} - ${txError}`))
-            }
-
-            if (result.status.isInBlock) {
-              result.events
-                .filter(({ event }) => event.section === 'system')
-                .forEach(({ event }) => {
-                  if (event.method === 'ExtrinsicFailed') {
-                    const dispatchError = event.data[0] as DispatchError
-                    let errorMsg = dispatchError.toString()
-                    if (dispatchError.isModule) {
-                      try {
-                        // Need to assert that registry is of TypeRegistry type, since Registry intefrace
-                        // seems outdated and doesn't include DispatchErrorModule as possible argument for "findMetaError"
-                        const { name, documentation } = (this.api.registry as TypeRegistry).findMetaError(
-                          dispatchError.asModule
-                        )
-                        errorMsg = `${name} (${documentation})`
-                      } catch (e) {
-                        // This probably means we don't have this error in the metadata
-                        // In this case - continue (we'll just display dispatchError.toString())
-                      }
-                    }
-                    reject(new Error(`${errorMessage} - Extrinsic execution error: ${errorMsg}`))
-                  } else if (event.method === 'ExtrinsicSuccess') {
-                    resolve()
-                  }
-                })
-            }
-          })
-        })
-      )
-    }
-    await Promise.all(promises)
-  }
-}

+ 0 - 19
content-directory-schemas/src/helpers/initialize.ts

@@ -1,19 +0,0 @@
-import { ApiPromise } from '@polkadot/api'
-import { InputParser } from './InputParser'
-import { ExtrinsicsHelper } from './extrinsics'
-import { KeyringPair } from '@polkadot/keyring/types'
-
-export default async function initializeContentDir(api: ApiPromise, leadKey: KeyringPair): Promise<void> {
-  const txHelper = new ExtrinsicsHelper(api)
-  const parser = InputParser.createWithInitialInputs(api)
-
-  // Initialize classes first in order to later be able to get classIdByNameMap
-  const createClassTxs = await parser.getCreateClassExntrinsics()
-  await txHelper.sendAndCheck(leadKey, createClassTxs, 'Classes initialization failed!')
-
-  // Initialize schemas and entities
-  const addSchemaTxs = await parser.getAddSchemaExtrinsics()
-  const entitiesTx = api.tx.contentDirectory.transaction({ Lead: null }, await parser.getEntityBatchOperations())
-  await txHelper.sendAndCheck(leadKey, addSchemaTxs, 'Schemas initialization failed!')
-  await txHelper.sendAndCheck(leadKey, [entitiesTx], 'Entities initialization failed!')
-}

+ 0 - 40
content-directory-schemas/src/helpers/inputs.ts

@@ -1,40 +0,0 @@
-import path from 'path'
-import fs from 'fs'
-import { CreateClass, AddClassSchema } from '../../types/extrinsics'
-import { EntityBatch } from '../../types/EntityBatch'
-
-export const INPUTS_LOCATION = path.join(__dirname, '../../inputs')
-export const INPUT_TYPES = ['classes', 'schemas', 'entityBatches'] as const
-
-export type InputType = typeof INPUT_TYPES[number]
-export type FetchedInput<Schema = any> = { fileName: string; data: Schema }
-
-export const getInputsLocation = (inputType: InputType) => path.join(INPUTS_LOCATION, inputType)
-
-export function getInputs<Schema = any>(
-  inputType: InputType,
-  rootInputsLocation = INPUTS_LOCATION
-): FetchedInput<Schema>[] {
-  const inputs: FetchedInput<Schema>[] = []
-  fs.readdirSync(path.join(rootInputsLocation, inputType)).forEach((fileName) => {
-    const inputFilePath = path.join(rootInputsLocation, inputType, fileName)
-    if (path.extname(inputFilePath) !== '.json') {
-      return
-    }
-    const inputJson = fs.readFileSync(inputFilePath).toString()
-    inputs.push({
-      fileName,
-      data: JSON.parse(inputJson) as Schema,
-    })
-  })
-  return inputs
-}
-
-export function getInitializationInputs(rootInputsLocation = INPUTS_LOCATION) {
-  return {
-    // eslint-disable-next-line @typescript-eslint/no-var-requires
-    classInputs: require('../../inputs/classes/index.js') as CreateClass[],
-    schemaInputs: getInputs<AddClassSchema>('schemas').map(({ data }) => data),
-    entityBatchInputs: getInputs<EntityBatch>('entityBatches').map(({ data }) => data),
-  }
-}

+ 0 - 16
content-directory-schemas/src/helpers/propertyType.ts

@@ -1,16 +0,0 @@
-import {
-  Property,
-  ReferenceProperty,
-  SinglePropertyType,
-  SinglePropertyVariant,
-} from '../../types/extrinsics/AddClassSchema'
-
-type PropertyType = Property['property_type']
-
-export function isSingle(propertyType: PropertyType): propertyType is SinglePropertyVariant {
-  return (propertyType as SinglePropertyVariant).Single !== undefined
-}
-
-export function isReference(propertySubtype: SinglePropertyType): propertySubtype is ReferenceProperty {
-  return (propertySubtype as ReferenceProperty).Reference !== undefined
-}

+ 0 - 8
content-directory-schemas/src/helpers/schemas.ts

@@ -1,8 +0,0 @@
-import path from 'path'
-
-export const SCHEMAS_LOCATION = path.join(__dirname, '../../schemas')
-export const SCHEMA_TYPES = ['entities', 'entityBatches', 'entityReferences', 'extrinsics'] as const
-
-export type SchemaType = typeof SCHEMA_TYPES[number]
-
-export const getSchemasLocation = (schemaType: SchemaType) => path.join(SCHEMAS_LOCATION, schemaType)

+ 0 - 6
content-directory-schemas/src/index.ts

@@ -1,6 +0,0 @@
-export { ExtrinsicsHelper, getAlicePair } from './helpers/extrinsics'
-export { InputParser } from './helpers/InputParser'
-export { getInputs, getInitializationInputs, getInputsLocation } from './helpers/inputs'
-export { isReference, isSingle } from './helpers/propertyType'
-export { getSchemasLocation } from './helpers/schemas'
-export { default as initializeContentDir } from './helpers/initialize'

+ 0 - 27
content-directory-schemas/tsconfig.json

@@ -1,27 +0,0 @@
-{
-  "compilerOptions": {
-    "target": "ES2017",
-    "module": "commonjs",
-    "strict": true,
-    "noImplicitAny": true,
-    "noImplicitReturns": true,
-    "moduleResolution": "node",
-    "allowSyntheticDefaultImports": true,     /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
-    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
-    "declaration": true,
-    "resolveJsonModule": true,
-    "types" : [
-      "node"
-    ],
-    "forceConsistentCasingInFileNames": true,
-    "baseUrl": ".",
-    "typeRoots": [
-      "typings"
-    ],
-    "paths": {
-      "@polkadot/types/augment": ["../types/augment-codec/augment-types.ts"],
-      "@polkadot/api/augment": ["../types/augment-codec/augment-api.ts"]
-    }
-  },
-  "include": [ "src/**/*", "scripts/**/*", "typings/**/*", "examples/**/*" ]
-}

+ 0 - 7
content-directory-schemas/tsconfig.lib.json

@@ -1,7 +0,0 @@
-{
-  "extends": "./tsconfig.json",
-  "include": ["src/**/*"],
-  "compilerOptions": {
-    "outDir": "lib"
-  }
-}

+ 0 - 4
content-directory-schemas/types/EntityBatch.d.ts

@@ -1,4 +0,0 @@
-export interface EntityBatch {
-  className: string
-  entries: Record<string, any>[]
-}

+ 0 - 67
content-directory-schemas/types/extrinsics/AddClassSchema.d.ts

@@ -1,67 +0,0 @@
-/* tslint:disable */
-/**
- * This file was automatically generated by json-schema-to-typescript.
- * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
- * and run json-schema-to-typescript to regenerate this file.
- */
-
-export type PropertyInSchemIndex = number
-export type SinglePropertyType =
-  | ('Bool' | 'Uint16' | 'Uint32' | 'Uint64' | 'Int16' | 'Int32' | 'Int64')
-  | TextProperty
-  | HashProperty
-  | ReferenceProperty
-export type MaxTextLength = number
-export type MaxVecItems = number
-export type PropertyName = string
-export type PropertyDescription = string
-export type DefaultBoolean = boolean
-
-/**
- * JSON schema to describe a new schema for a certain class in Joystream network
- */
-export interface AddClassSchema {
-  className: string
-  existingProperties?: PropertyInSchemIndex[]
-  newProperties: Property[]
-}
-export interface Property {
-  property_type: SinglePropertyVariant | VecPropertyVariant
-  name: PropertyName
-  description?: PropertyDescription
-  required?: DefaultBoolean
-  unique?: DefaultBoolean
-  locking_policy?: LockingPolicy
-}
-export interface SinglePropertyVariant {
-  Single: SinglePropertyType
-}
-export interface TextProperty {
-  Text: MaxTextLength
-}
-export interface HashProperty {
-  Hash: MaxTextLength
-}
-export interface ReferenceProperty {
-  Reference: {
-    /**
-     * Referenced class name
-     */
-    className: string
-    /**
-     * Whether same owner (controller) is required
-     */
-    sameOwner?: boolean
-  }
-}
-export interface VecPropertyVariant {
-  Vector: VecPropertyType
-}
-export interface VecPropertyType {
-  vec_type: SinglePropertyType
-  max_length: MaxVecItems
-}
-export interface LockingPolicy {
-  is_locked_from_maintainer?: DefaultBoolean
-  is_locked_from_controller?: DefaultBoolean
-}

+ 0 - 30
content-directory-schemas/types/extrinsics/CreateClass.d.ts

@@ -1,30 +0,0 @@
-/* tslint:disable */
-/**
- * This file was automatically generated by json-schema-to-typescript.
- * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
- * and run json-schema-to-typescript to regenerate this file.
- */
-
-export type DefaultBoolean = boolean
-
-/**
- * JSON schema to describe a new class for Joystream network
- */
-export interface CreateClass {
-  /**
-   * Name of this class. Required property.
-   */
-  name: string
-  /**
-   * Description of this class.
-   */
-  description: string
-  class_permissions?: {
-    any_member?: DefaultBoolean
-    entity_creation_blocked?: DefaultBoolean
-    all_entity_property_values_locked?: DefaultBoolean
-    maintainers?: number[]
-  }
-  maximum_entities_count: number
-  default_entity_creation_voucher_upper_bound: number
-}

+ 0 - 2
content-directory-schemas/types/extrinsics/index.d.ts

@@ -1,2 +0,0 @@
-export { AddClassSchema } from './AddClassSchema'
-export { CreateClass } from './CreateClass'

+ 0 - 1
content-directory-schemas/types/utility.d.ts

@@ -1 +0,0 @@
-export type FlattenRelations<T> = { [K in keyof T]: Exclude<T[K], { new: any } | { existing: any }> }

+ 0 - 2
content-directory-schemas/typings/@joystream/prettier-config/index.d.ts

@@ -1,2 +0,0 @@
-// Prevent declaration file not found error
-declare module '@joystream/prettier-config'

+ 0 - 60
content-directory-schemas/vscode-recommended.settings.json

@@ -1,60 +0,0 @@
-{
-  "json.schemas": [
-    {
-      "fileMatch": ["*Schema.json"],
-      "url": "/content-directory-schemas/schemas/extrinsics/AddClassSchema.schema.json"
-    },
-    {
-      "fileMatch": ["*Class.json"],
-      "url": "/content-directory-schemas/schemas/extrinsics/CreateClass.schema.json"
-    },
-    {
-      "fileMatch": ["*/LanguageBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/LanguageBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/MediaLocationBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/MediaLocationBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/HttpMediaLocationBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/HttpMediaLocationBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/JoystreamMediaLocationBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/JoystreamMediaLocationBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/ContentCategoryBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/ContentCategoryBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/ChannelBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/ChannelBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/VideoMediaEncodingBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/VideoMediaEncodingBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/KnownLicenseBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/KnownLicenseBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/UserDefinedLicenseBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/UserDefinedLicenseBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/LicenseBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/LicenseBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/VideoMediaBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/VideoMediaBatch.schema.json"
-    },
-    {
-      "fileMatch": ["*/VideoBatch.json"],
-      "url": "/content-directory-schemas/schemas/entityBatches/VideoBatch.schema.json"
-    }
-  ]
-}