Browse Source

Merge branch 'sumer' of https://github.com/Joystream/joystream into content_videos

iorveth 4 years ago
parent
commit
d1eb0f73c5
75 changed files with 72 additions and 2690 deletions
  1. 1 3
      .github/workflows/run-network-tests.yml
  2. 0 1
      cli/package.json
  3. 0 10
      content-directory-schemas/.gitignore
  4. 0 1
      content-directory-schemas/.npmignore
  5. 0 279
      content-directory-schemas/README.md
  6. 0 52
      content-directory-schemas/examples/createChannel.ts
  7. 0 68
      content-directory-schemas/examples/createChannelWithoutTransaction.ts
  8. 0 76
      content-directory-schemas/examples/createVideo.ts
  9. 0 47
      content-directory-schemas/examples/updateChannelTitle.ts
  10. 0 47
      content-directory-schemas/examples/updateChannelTitleWithoutTransaction.ts
  11. 0 7
      content-directory-schemas/inputs/classes/ChannelClass.json
  12. 0 6
      content-directory-schemas/inputs/classes/ContentCategoryClass.json
  13. 0 6
      content-directory-schemas/inputs/classes/FeaturedVideoClass.json
  14. 0 7
      content-directory-schemas/inputs/classes/HttpMediaLocationClass.json
  15. 0 7
      content-directory-schemas/inputs/classes/JoystreamMediaLocationClass.json
  16. 0 6
      content-directory-schemas/inputs/classes/KnownLicenseClass.json
  17. 0 6
      content-directory-schemas/inputs/classes/LanguageClass.json
  18. 0 7
      content-directory-schemas/inputs/classes/LicenseClass.json
  19. 0 7
      content-directory-schemas/inputs/classes/MediaLocationClass.json
  20. 0 7
      content-directory-schemas/inputs/classes/UserDefinedLicenseClass.json
  21. 0 7
      content-directory-schemas/inputs/classes/VideoClass.json
  22. 0 7
      content-directory-schemas/inputs/classes/VideoMediaClass.json
  23. 0 6
      content-directory-schemas/inputs/classes/VideoMediaEncodingClass.json
  24. 0 18
      content-directory-schemas/inputs/classes/index.js
  25. 0 20
      content-directory-schemas/inputs/entityBatches/ContentCategoryBatch.json
  26. 0 61
      content-directory-schemas/inputs/entityBatches/KnownLicenseBatch.json
  27. 0 43
      content-directory-schemas/inputs/entityBatches/LanguageBatch.json
  28. 0 27
      content-directory-schemas/inputs/entityBatches/VideoMediaEncodingBatch.json
  29. 0 49
      content-directory-schemas/inputs/schemas/ChannelSchema.json
  30. 0 20
      content-directory-schemas/inputs/schemas/ContentCategorySchema.json
  31. 0 12
      content-directory-schemas/inputs/schemas/FeaturedVideoSchema.json
  32. 0 20
      content-directory-schemas/inputs/schemas/HttpMediaLocationSchema.json
  33. 0 13
      content-directory-schemas/inputs/schemas/JoystreamMediaLocationSchema.json
  34. 0 52
      content-directory-schemas/inputs/schemas/KnownLicenseSchema.json
  35. 0 20
      content-directory-schemas/inputs/schemas/LanguageSchema.json
  36. 0 23
      content-directory-schemas/inputs/schemas/LicenseSchema.json
  37. 0 19
      content-directory-schemas/inputs/schemas/MediaLocationSchema.json
  38. 0 13
      content-directory-schemas/inputs/schemas/UserDefinedLicenseSchema.json
  39. 0 13
      content-directory-schemas/inputs/schemas/VideoMediaEncodingSchema.json
  40. 0 40
      content-directory-schemas/inputs/schemas/VideoMediaSchema.json
  41. 0 99
      content-directory-schemas/inputs/schemas/VideoSchema.json
  42. 0 56
      content-directory-schemas/package.json
  43. 0 155
      content-directory-schemas/schemas/extrinsics/AddClassSchema.schema.json
  44. 0 48
      content-directory-schemas/schemas/extrinsics/CreateClass.schema.json
  45. 0 38
      content-directory-schemas/schemas/propertyValidationDefs.schema.json
  46. 0 65
      content-directory-schemas/scripts/initializeContentDir.ts
  47. 0 163
      content-directory-schemas/scripts/inputSchemasToEntitySchemas.ts
  48. 0 56
      content-directory-schemas/scripts/schemasToTS.ts
  49. 0 85
      content-directory-schemas/scripts/validate.ts
  50. 0 435
      content-directory-schemas/src/helpers/InputParser.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
  65. 0 1
      package.json
  66. 0 2
      start.sh
  67. 0 2
      tests/network-tests/run-storage-node-tests.sh
  68. 1 10
      tests/network-tests/src/Api.ts
  69. 0 9
      tests/network-tests/src/flows/contentDirectory/contentDirectoryInitialization.ts
  70. 0 2
      tests/network-tests/src/scenarios/content-directory.ts
  71. 18 6
      utils/api-scripts/README.md
  72. 1 0
      utils/api-scripts/package.json
  73. 0 0
      utils/api-scripts/src/helpers/extrinsics.ts
  74. 6 7
      utils/api-scripts/src/initialize-content-lead.ts
  75. 45 29
      yarn.lock

+ 1 - 3
.github/workflows/run-network-tests.yml

@@ -145,12 +145,10 @@ jobs:
           docker images
       - name: Install packages and dependencies
         run: yarn install --frozen-lockfile
-      - name: Ensure tests are runnable
-        run: yarn workspace @joystream/cd-schemas checks --quiet
       - name: Start chain
         run: docker-compose up -d joystream-node
       - name: Initialize the content directory
-        run: yarn workspace @joystream/cd-schemas initialize:dev
+        run: yarn workspace api-scripts initialize-content-lead
 
   query_node:
     name: Query Node Integration Tests

+ 0 - 1
cli/package.json

@@ -11,7 +11,6 @@
     "@apidevtools/json-schema-ref-parser": "^9.0.6",
     "@ffprobe-installer/ffprobe": "^1.1.0",
     "@joystream/types": "^0.16.0",
-    "@joystream/cd-schemas": "^0.1.0",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/plugin-autocomplete": "^0.2.0",

+ 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 - 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 - 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"
-    }
-  ]
-}

+ 0 - 1
package.json

@@ -21,7 +21,6 @@
     "pioneer",
     "pioneer/packages/*",
     "utils/api-scripts",
-    "content-directory-schemas",
     "query-node",
     "query-node/generated/*",
     "content-metadata-protobuf"

+ 0 - 2
start.sh

@@ -26,8 +26,6 @@ docker-compose up -d joystream-node
 # Configure a dev storage node and start storage node
 DEBUG=joystream:storage-cli:dev yarn storage-cli dev-init
 docker-compose up -d colossus
-# Initialise the content directory with standard classes, schemas and initial entities
-yarn workspace @joystream/cd-schemas initialize:dev
 
 ## Query Node Infrastructure
 # Initialize a new database for the query node infrastructure

+ 0 - 2
tests/network-tests/run-storage-node-tests.sh

@@ -34,8 +34,6 @@ docker-compose up -d graphql-server
 # Starting up processor will bring up all services it depends on
 docker-compose up -d processor
 
-yarn workspace @joystream/cd-schemas initialize:dev
-
 # Fixes Error: No active storage providers available
 echo "Waiting for ipfs name registration"
 sleep 120

+ 1 - 10
tests/network-tests/src/Api.ts

@@ -32,7 +32,7 @@ import { FillOpeningParameters, ProposalId } from '@joystream/types/proposals'
 import { v4 as uuid } from 'uuid'
 import { ChannelEntity } from '@joystream/cd-schemas/types/entities/ChannelEntity'
 import { VideoEntity } from '@joystream/cd-schemas/types/entities/VideoEntity'
-import { initializeContentDir, InputParser } from '@joystream/cd-schemas'
+import { InputParser } from '@joystream/cd-schemas'
 import { OperationType } from '@joystream/types/content-directory'
 import { ContentId, DataObject } from '@joystream/types/storage'
 import Debugger from 'debug'
@@ -1794,13 +1794,4 @@ export class Api {
     const dataObject = await this.api.query.dataDirectory.dataByContentId<Option<DataObject>>(contentId)
     return dataObject.unwrapOr(null)
   }
-
-  public async initializeContentDirectory(): Promise<void> {
-    const lead = await this.getGroupLead(WorkingGroups.ContentDirectoryWorkingGroup)
-    if (!lead) {
-      throw new Error('No Lead is set for storage wokring group')
-    }
-    const leadKeyPair = this.keyring.getPair(lead.role_account_id.toString())
-    return initializeContentDir(this.api, leadKeyPair)
-  }
 }

+ 0 - 9
tests/network-tests/src/flows/contentDirectory/contentDirectoryInitialization.ts

@@ -1,9 +0,0 @@
-import { FlowProps } from '../../Flow'
-import Debugger from 'debug'
-const debug = Debugger('initializeContentDirectory')
-
-export default async function initializeContentDirectory({ api }: FlowProps): Promise<void> {
-  debug('Started')
-  await api.initializeContentDirectory()
-  debug('Done')
-}

+ 0 - 2
tests/network-tests/src/scenarios/content-directory.ts

@@ -1,5 +1,4 @@
 import leaderSetup from '../flows/workingGroup/leaderSetup'
-import initializeContentDirectory from '../flows/contentDirectory/contentDirectoryInitialization'
 import createChannel from '../flows/contentDirectory/creatingChannel'
 import createVideo from '../flows/contentDirectory/creatingVideo'
 import updateChannel from '../flows/contentDirectory/updatingChannel'
@@ -7,7 +6,6 @@ import { scenario } from '../Scenario'
 
 scenario(async ({ job }) => {
   job('setup content lead', leaderSetup.content)
-    .then(job('init-content-dir', initializeContentDirectory))
     .then(job('create-channel', createChannel))
     .then(job('create-video', createVideo))
     .then(job('update-channel', updateChannel))

+ 18 - 6
utils/api-scripts/README.md

@@ -2,14 +2,19 @@
 
 Repo with examples on how to use the @joystream/types package along with @polkadot/api to communicate with a joystream full node.
 
-## Examples
+Some useful utilily commands are also included under `src/`
 
-```
-yarn
-yarn run status
+### Directly Execute src/commands.ts
+
+You can run typescript commands under the `src/` folder simply with:
+
+```sh
+yarn ts-node src/sudo-init-content-lead.ts
 ```
 
-## Example code
+## Adding code to src/
+
+For example you can add a new file `test-command.ts`:
 
 ```javascript
 import { types } from '@joystream/types'
@@ -36,10 +41,17 @@ async function main() {
 
 main()
 ```
+Then run it with:
+
+```sh
+yarn ts-node src/test-command.ts
+```
 
 ### Scripts
 
-You can run scripts that are found in the [./scripts/](./scripts) folder:
+Some examples of how to write "scripts" is available under [./scripts/](./scripts) folder.
+These are "code-snippets" designed primarly for doing queries or very simple transactions.
+If you follow the example format you can also copy/paste them into https://testnet.joystream.org/#/js for execution.
 
 ```sh
 yarn script example

+ 1 - 0
utils/api-scripts/package.json

@@ -5,6 +5,7 @@
   "license": "GPL-3.0-only",
   "scripts": {
     "status": "ts-node src/status",
+    "initialize-content-lead": "ts-node src/sudo-init-content-lead",
     "script": "ts-node src/script",
     "tsnode-strict": "node -r ts-node/register --unhandled-rejections=strict"
   },

+ 0 - 0
content-directory-schemas/src/helpers/extrinsics.ts → utils/api-scripts/src/helpers/extrinsics.ts


+ 6 - 7
content-directory-schemas/scripts/devInitContentLead.ts → utils/api-scripts/src/initialize-content-lead.ts

@@ -1,7 +1,7 @@
 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'
+import { ExtrinsicsHelper, getAlicePair, getKeyFromSuri } from './helpers/extrinsics'
 
 async function main() {
   // Init api
@@ -22,7 +22,7 @@ async function main() {
     .toArray()[0]
     ?.toNumber()
 
-  // Only buy membership if LEAD_URI is not provided
+  // Only buy membership if LEAD_URI is not provided - ie for Alice
   if (memberId === undefined && process.env.LEAD_URI) {
     throw new Error('Make sure Controller key LEAD_URI is for a member')
   }
@@ -37,10 +37,11 @@ async function main() {
     )
   }
 
-  console.log(`Making member id: ${memberId} the content lead.`)
-
   // Create a new lead opening
-  if ((await api.query.contentDirectoryWorkingGroup.currentLead()).isNone) {
+  if ((await api.query.contentDirectoryWorkingGroup.currentLead()).isSome) {
+    console.log('Curators lead already exists, aborting...')
+  } else {
+    console.log(`Making member id: ${memberId} the content lead.`)
     const newOpeningId = (await api.query.contentDirectoryWorkingGroup.nextOpeningId()).toNumber()
     const newApplicationId = (await api.query.contentDirectoryWorkingGroup.nextApplicationId()).toNumber()
     // Create curator lead opening
@@ -95,8 +96,6 @@ async function main() {
     )
 
     await txHelper.sendAndCheck(SudoKeyPair, extrinsics, 'Failed to initialize Content Curators Lead!')
-  } else {
-    console.log('Curators lead already exists, skipping...')
   }
 }
 

+ 45 - 29
yarn.lock

@@ -6324,16 +6324,6 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
   resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
   integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
 
-ajv@6.12.5:
-  version "6.12.5"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
-  integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
-  dependencies:
-    fast-deep-equal "^3.1.1"
-    fast-json-stable-stringify "^2.0.0"
-    json-schema-traverse "^0.4.1"
-    uri-js "^4.2.2"
-
 ajv@^6.1.0, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.12.3:
   version "6.12.3"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
@@ -8816,7 +8806,7 @@ check-error@^1.0.2:
   resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
   integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=
 
-chokidar@3.4.3, chokidar@^3.4.0:
+chokidar@3.4.3:
   version "3.4.3"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b"
   integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==
@@ -8881,6 +8871,21 @@ chokidar@^3.4.1:
   optionalDependencies:
     fsevents "~2.1.2"
 
+chokidar@^3.5.1:
+  version "3.5.1"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
+  integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
+  dependencies:
+    anymatch "~3.1.1"
+    braces "~3.0.2"
+    glob-parent "~5.1.0"
+    is-binary-path "~2.1.0"
+    is-glob "~4.0.1"
+    normalize-path "~3.0.0"
+    readdirp "~3.5.0"
+  optionalDependencies:
+    fsevents "~2.3.1"
+
 chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142"
@@ -10079,6 +10084,11 @@ create-react-context@^0.2.2:
     fbjs "^0.8.0"
     gud "^1.0.0"
 
+create-require@^1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
+  integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
+
 cross-fetch@^3.0.4, cross-fetch@^3.0.6:
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c"
@@ -13619,6 +13629,11 @@ fsevents@^2.1.2, fsevents@~2.1.2:
   resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e"
   integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==
 
+fsevents@~2.3.1:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+  integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
 fstream@^1.0.0, fstream@^1.0.12:
   version "1.0.12"
   resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
@@ -16198,10 +16213,10 @@ is-color-stop@^1.0.0:
     rgb-regex "^1.0.1"
     rgba-regex "^1.0.0"
 
-is-core-module@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946"
-  integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==
+is-core-module@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
+  integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
   dependencies:
     has "^1.0.3"
 
@@ -25221,11 +25236,11 @@ resolve@1.1.7:
   integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
 
 resolve@1.x, resolve@^1.0.0:
-  version "1.19.0"
-  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
-  integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
+  integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
   dependencies:
-    is-core-module "^2.1.0"
+    is-core-module "^2.2.0"
     path-parse "^1.0.6"
 
 resolve@^1.1.6, resolve@^1.1.7, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.17.0, resolve@^1.2.0:
@@ -25286,9 +25301,9 @@ reusify@^1.0.0:
   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
 
 rfdc@^1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
-  integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.2.0.tgz#9e9894258f48f284b43c3143c68070a4f373b949"
+  integrity sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA==
 
 rgb-regex@^1.0.1:
   version "1.0.1"
@@ -27947,11 +27962,11 @@ ts-log@^2.1.4:
   integrity sha512-P1EJSoyV+N3bR/IWFeAqXzKPZwHpnLY6j7j58mAvewHRipo+BQM2Y1f9Y9BjEQznKwgqqZm7H8iuixmssU7tYQ==
 
 ts-node-dev@^1.0.0-pre.40, ts-node-dev@^1.0.0-pre.60:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.0.0.tgz#24a2270d225c29ce269de2a31f88b1b259fc84cb"
-  integrity sha512-leA/3TgGtnVU77fGngBwVZztqyDRXirytR7dMtMWZS5b2hGpLl+VDnB0F/gf3A+HEPSzS/KwxgXFP7/LtgX4MQ==
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.6.tgz#ee2113718cb5a92c1c8f4229123ad6afbeba01f8"
+  integrity sha512-RTUi7mHMNQospArGz07KiraQcdgUVNXKsgO2HAi7FoiyPMdTDqdniB6K1dqyaIxT7c9v/VpSbfBZPS6uVpaFLQ==
   dependencies:
-    chokidar "^3.4.0"
+    chokidar "^3.5.1"
     dateformat "~1.0.4-1.2.3"
     dynamic-dedupe "^0.3.0"
     minimist "^1.2.5"
@@ -28000,11 +28015,12 @@ ts-node@^8.8.1, ts-node@^8.8.2:
     yn "3.1.1"
 
 ts-node@^9.0.0:
-  version "9.0.0"
-  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3"
-  integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==
+  version "9.1.1"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d"
+  integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==
   dependencies:
     arg "^4.1.0"
+    create-require "^1.1.0"
     diff "^4.0.1"
     make-error "^1.1.1"
     source-map-support "^0.5.17"