Просмотр исходного кода

Merge pull request #2242 from metmirr/qnode-entity-default-schema

Add default schema to all newly created entities
Mokhtar Naamani 4 лет назад
Родитель
Сommit
656fa3412d

+ 302 - 0
query-node/mappings/content-directory/default-schemas.ts

@@ -0,0 +1,302 @@
+import Debug from 'debug'
+import { nanoid } from 'nanoid'
+
+import { DB } from '../../generated/indexer'
+import { Channel } from '../../generated/graphql-server/src/modules/channel/channel.model'
+import { Language } from '../../generated/graphql-server/src/modules/language/language.model'
+import { ClassEntity } from '../../generated/graphql-server/src/modules/class-entity/class-entity.model'
+import { Video } from '../../generated/graphql-server/src/modules/video/video.model'
+import { Category } from '../../generated/graphql-server/src/modules/category/category.model'
+import { VideoMedia } from '../../generated/graphql-server/src/modules/video-media/video-media.model'
+import { LicenseEntity } from '../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { VideoMediaEncoding } from '../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
+import { MediaLocationEntity } from '../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
+import { JoystreamMediaLocationEntity } from '../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { KnownLicenseEntity } from '../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
+import { FeaturedVideo } from '../../generated/graphql-server/src/modules/featured-video/featured-video.model'
+import { JoystreamMediaLocation } from '../../generated/graphql-server/src/modules/variants/variants.model'
+
+import { contentDirectoryClassNamesWithId, ContentDirectoryKnownClasses } from './content-dir-consts'
+
+const debug = Debug('mappings:default-schema')
+
+/**
+ * Inserts a default schema for every newly created entity
+ * @param db DB
+ * @param ce ClassEntity
+ */
+export async function createDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const knownClass = contentDirectoryClassNamesWithId.find((k) => k.classId === ce.classId)
+  // Its not a known class for query node so we simply return
+  if (!knownClass) {
+    debug(`Not a known class. ClassId: ${ce.classId} EntityId: ${ce.id}`)
+    return
+  }
+
+  switch (knownClass.name) {
+    case ContentDirectoryKnownClasses.CHANNEL:
+      await channelDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.CATEGORY:
+      await categoryDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
+      await httpMediaLocationDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
+      await joystreamMediaLocationDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.KNOWNLICENSE:
+      await knownLicenseDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.LANGUAGE:
+      await languageDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.LICENSE:
+      await licenseDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.MEDIALOCATION:
+      await mediaLocationDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
+      await userDefinedLicenseDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
+      await videoMediaEncodingDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+      await featuredVideoDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.VIDEO:
+      await videoDefaultSchema(db, ce)
+      break
+    case ContentDirectoryKnownClasses.VIDEOMEDIA:
+      await videoMediaDefaultSchema(db, ce)
+      break
+
+    default:
+      break
+  }
+}
+
+function commonProperties(ce: ClassEntity) {
+  return { id: ce.id, happenedIn: ce.happenedIn, version: ce.happenedIn.block }
+}
+
+export async function categoryDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  await db.save<Category>(
+    new Category({
+      ...commonProperties(ce),
+      name: ce.id,
+    })
+  )
+}
+
+export async function channelDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(Channel, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`Channel(0) not found`)
+
+  const c = new Channel({
+    ...commonProperties(ce),
+    handle: `${ce.id} - ${nanoid()}`,
+    description: `${ce.id}`,
+    isPublic: defaultSchemaFromDb.isPublic,
+    isCurated: defaultSchemaFromDb.isCurated,
+  })
+  await db.save<Channel>(c)
+}
+
+export async function httpMediaLocationDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(HttpMediaLocationEntity, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`HttpMediaLocationEntity(0) not found`)
+
+  await db.save<HttpMediaLocationEntity>(
+    new HttpMediaLocationEntity({
+      ...commonProperties(ce),
+      url: defaultSchemaFromDb.url,
+    })
+  )
+}
+
+export async function joystreamMediaLocationDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(JoystreamMediaLocationEntity, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`JoystreamMediaLocationEntity(0) not found`)
+
+  await db.save<JoystreamMediaLocationEntity>(
+    new JoystreamMediaLocationEntity({
+      ...commonProperties(ce),
+      dataObjectId: defaultSchemaFromDb.dataObjectId,
+    })
+  )
+}
+
+export async function knownLicenseDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(KnownLicenseEntity, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`KnownLicenseEntity(0) not found`)
+
+  await db.save<KnownLicenseEntity>(
+    new KnownLicenseEntity({
+      ...commonProperties(ce),
+      code: `${ce.id}-${defaultSchemaFromDb.code}`,
+      name: defaultSchemaFromDb.name,
+    })
+  )
+}
+
+export async function userDefinedLicenseDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  await db.save<UserDefinedLicenseEntity>(
+    new UserDefinedLicenseEntity({
+      ...commonProperties(ce),
+      content: `${ce.id}`,
+    })
+  )
+}
+
+export async function languageDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  await db.save<Language>(
+    new Language({
+      ...commonProperties(ce),
+      code: `${ce.id}`,
+      name: `${ce.id}`,
+    })
+  )
+}
+
+export async function licenseDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(LicenseEntity, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`LicenseEntity(0) not found`)
+
+  await db.save<LicenseEntity>(
+    new LicenseEntity({
+      ...commonProperties(ce),
+      type: defaultSchemaFromDb.type,
+    })
+  )
+}
+
+export async function mediaLocationDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(MediaLocationEntity, {
+    where: { id: '0' },
+    relations: ['joystreamMediaLocation'],
+  })
+  if (!defaultSchemaFromDb) throw Error(`MediaLocationEntity(0) not found`)
+
+  const m = new MediaLocationEntity()
+  m.joystreamMediaLocation = defaultSchemaFromDb.joystreamMediaLocation
+  await db.save<MediaLocationEntity>(
+    new MediaLocationEntity({
+      ...commonProperties(ce),
+      joystreamMediaLocation: defaultSchemaFromDb.joystreamMediaLocation,
+    })
+  )
+}
+
+export async function videoMediaEncodingDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(VideoMediaEncoding, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`VideoMediaEncoding(0) not found`)
+
+  await db.save<VideoMediaEncoding>(
+    new VideoMediaEncoding({
+      ...commonProperties(ce),
+      name: defaultSchemaFromDb.name,
+    })
+  )
+}
+
+export async function featuredVideoDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const video = await db.get(Video, { where: { id: '0' } })
+  if (!video) throw Error(`Video(0) not found for FeaturedVideo(${ce.id}) creation`)
+
+  await db.save<FeaturedVideo>(
+    new FeaturedVideo({
+      ...commonProperties(ce),
+      video,
+    })
+  )
+}
+
+export async function videoDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const defaultSchemaFromDb = await db.get(Video, { where: { id: '0' } })
+  if (!defaultSchemaFromDb) throw Error(`Video(0) not found`)
+
+  const v = new Video({
+    ...commonProperties(ce),
+  })
+
+  // ///// default relations ///////
+  /* eslint-disable @typescript-eslint/no-non-null-assertion */
+  const filmAnimation = await db.get(Category, { where: { name: 'Film & Animation' } })
+  v.category = filmAnimation || (await db.get(Category, { where: { id: '0' } }))!
+  v.channel = (await db.get(Channel, { where: { id: '0' } }))!
+  v.license = (await db.get(LicenseEntity, { where: { id: '0' } }))!
+
+  // const media = (await db.get(VideoMedia, { where: { id: '0' } }))!
+
+  // const encoding = new VideoMediaEncoding({
+  //   name: `${Date.now()}`,
+  //   ...commonProperties(ce),
+  //   id: `${Date.now()}`,
+  // })
+  // await db.save<VideoMediaEncoding>(encoding)
+  const encoding = await db.get(VideoMediaEncoding, { where: { id: 0 } })
+
+  const mediaLoc = await db.get(MediaLocationEntity, { where: { id: '0' }, relations: ['joystreamMediaLocation'] })
+  if (!mediaLoc) throw Error(`MediaLocationEntity(0) not found while creating default schema for video`)
+  const location = new JoystreamMediaLocation()
+  location.dataObjectId = mediaLoc.joystreamMediaLocation!.dataObjectId
+
+  const media = await db.get(VideoMedia, { where: { id: '0' } })
+  if (!media) throw Error(`VideoMedia(0) not found while creating default schema for video`)
+
+  const newMedia = new VideoMedia({
+    ...commonProperties(ce),
+    location,
+    encoding,
+    id: `${Date.now()}`, // override id
+    pixelHeight: media.pixelHeight,
+    pixelWidth: media.pixelWidth,
+  })
+  await db.save<VideoMedia>(newMedia)
+
+  v.media = newMedia
+  // ///// default relations ///////
+
+  // Get default schema for video entity
+  // const defaultSchemaFromDb = (await db.get(Video, { where: { id: '0' } }))!
+  /* eslint-enable @typescript-eslint/no-non-null-assertion */
+
+  v.title = ce.id
+  v.description = ce.id
+  v.duration = defaultSchemaFromDb.duration
+  v.thumbnailUrl = defaultSchemaFromDb.thumbnailUrl
+  v.isPublic = defaultSchemaFromDb.isPublic
+  v.isCurated = defaultSchemaFromDb.isCurated
+  v.isExplicit = defaultSchemaFromDb.isExplicit
+  v.isFeatured = defaultSchemaFromDb.isFeatured
+
+  await db.save<Video>(v)
+}
+
+export async function videoMediaDefaultSchema(db: DB, ce: ClassEntity): Promise<void> {
+  const media = await db.get(VideoMedia, { where: { id: '0' } })
+  if (!media) throw Error(`VideoMedia(0) not found`)
+
+  const encoding = await db.get(VideoMediaEncoding, { where: { id: '0' } })
+
+  const mediaLoc = await db.get(MediaLocationEntity, { where: { id: '0' }, relations: ['joystreamMediaLocation'] })
+  if (!mediaLoc) throw Error(`MediaLocationEntity(0) not found while creating default schema for video`)
+  const location = new JoystreamMediaLocation()
+  location.dataObjectId = mediaLoc.joystreamMediaLocation!.dataObjectId
+
+  const vm = new VideoMedia({
+    ...commonProperties(ce),
+    pixelHeight: media.pixelHeight,
+    pixelWidth: media.pixelWidth,
+    encoding,
+    location,
+  })
+
+  await db.save<VideoMedia>(vm)
+}

+ 299 - 0
query-node/mappings/content-directory/entity/addSchema.ts

@@ -0,0 +1,299 @@
+import { DB } from '../../../generated/indexer'
+import { Channel } from '../../../generated/graphql-server/src/modules/channel/channel.model'
+import { Category } from '../../../generated/graphql-server/src/modules/category/category.model'
+import { KnownLicenseEntity } from '../../../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { UserDefinedLicenseEntity } from '../../../generated/graphql-server/src/modules/user-defined-license-entity/user-defined-license-entity.model'
+import { JoystreamMediaLocationEntity } from '../../../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+import { HttpMediaLocationEntity } from '../../../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
+import { VideoMedia } from '../../../generated/graphql-server/src/modules/video-media/video-media.model'
+import { Video } from '../../../generated/graphql-server/src/modules/video/video.model'
+import { Language } from '../../../generated/graphql-server/src/modules/language/language.model'
+import { VideoMediaEncoding } from '../../../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
+import { LicenseEntity } from '../../../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { MediaLocationEntity } from '../../../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { FeaturedVideo } from '../../../generated/graphql-server/src/modules/featured-video/featured-video.model'
+
+import {
+  ICategory,
+  IChannel,
+  IFeaturedVideo,
+  IHttpMediaLocation,
+  IJoystreamMediaLocation,
+  IKnownLicense,
+  ILanguage,
+  ILicense,
+  IMediaLocation,
+  IReference,
+  IUserDefinedLicense,
+  IVideo,
+  IVideoMedia,
+  IVideoMediaEncoding,
+} from '../../types'
+import {
+  HttpMediaLocation,
+  JoystreamMediaLocation,
+  KnownLicense,
+  UserDefinedLicense,
+} from '../../../generated/graphql-server/src/modules/variants/variants.model'
+
+type SchemaSupport<T> = { db: DB; entityId: number; props: T; nextEntityId: number }
+
+function getEntityIdFromRef(ref: IReference, nextEntityId: number) {
+  const { entityId, existing } = ref
+  return (existing ? entityId : entityId + nextEntityId).toString()
+}
+
+export async function addSchemaToChannel(param: SchemaSupport<IChannel>): Promise<void> {
+  const { entityId, nextEntityId, props, db } = param
+  const c = await db.get(Channel, { where: { id: entityId.toString() } })
+  if (!c) throw Error(`Channel(${entityId}) has never been created!`)
+
+  c.handle = props.handle || c.handle
+  c.description = props.description || c.description
+  c.isCurated = !!props.isCurated
+  c.isPublic = props.isPublic || c.isPublic
+  c.coverPhotoUrl = props.coverPhotoUrl || c.coverPhotoUrl
+  c.avatarPhotoUrl = props.avatarPhotoUrl || c.avatarPhotoUrl
+
+  const { language } = props
+  if (language) {
+    c.language = await db.get(Language, { where: { id: getEntityIdFromRef(language, nextEntityId) } })
+  }
+  await db.save<Channel>(c)
+}
+
+export async function addSchemaToCategory(param: SchemaSupport<ICategory>): Promise<void> {
+  const { entityId, props, db } = param
+  const c = await db.get(Category, { where: { id: entityId.toString() } })
+  if (!c) throw Error(`Category(${entityId}) has never been created!`)
+
+  c.name = props.name || c.name
+  c.description = props.description || c.description
+  await db.save<Category>(c)
+}
+
+export async function addSchemaToHttpMediaLocation(param: SchemaSupport<IHttpMediaLocation>): Promise<void> {
+  const { entityId, props, db } = param
+  const c = await db.get(HttpMediaLocationEntity, { where: { id: entityId.toString() } })
+  if (!c) throw Error(`HttpMediaLocationEntity(${entityId}) has never been created!`)
+
+  c.url = props.url || c.url
+  c.port = props.port || c.port
+
+  await db.save<HttpMediaLocationEntity>(c)
+}
+
+export async function addSchemaToJoystreamMediaLocation(param: SchemaSupport<IJoystreamMediaLocation>): Promise<void> {
+  const { entityId, props, db } = param
+  const j = await db.get(JoystreamMediaLocationEntity, { where: { id: entityId.toString() } })
+  if (!j) throw Error(`JoystreamMediaLocationEntity(${entityId}) has never been created!`)
+
+  j.dataObjectId = props.dataObjectId || j.dataObjectId
+  await db.save<JoystreamMediaLocationEntity>(j)
+}
+
+export async function addSchemaToKnownLicense(param: SchemaSupport<IKnownLicense>): Promise<void> {
+  const { entityId, props, db } = param
+  const k = await db.get(KnownLicenseEntity, { where: { id: entityId.toString() } })
+  if (!k) throw Error(`KnownLicenseEntity(${entityId}) has never been created!`)
+
+  k.code = props.code || k.code
+  k.description = props.description || k.description
+  k.name = props.name || k.name
+  k.url = props.url || k.url
+
+  await db.save<KnownLicenseEntity>(k)
+}
+
+export async function addSchemaToLanguage(param: SchemaSupport<ILanguage>): Promise<void> {
+  const { entityId, props, db } = param
+  const l = await db.get(Language, { where: { id: entityId.toString() } })
+  if (!l) throw Error(`Language(${entityId}) has never been created!`)
+
+  l.code = props.code || l.code
+  l.name = props.name || l.name
+
+  await db.save<Language>(l)
+}
+
+export async function addSchemaToLicense(param: SchemaSupport<ILicense>): Promise<void> {
+  const { entityId, props, db, nextEntityId } = param
+  const l = await db.get(LicenseEntity, { where: { id: entityId.toString() } })
+  if (!l) throw Error(`LicenseEntity(${entityId}) has never been created!`)
+
+  const { knownLicense, userDefinedLicense } = props
+
+  let licenseEntityId
+
+  if (knownLicense) {
+    licenseEntityId = getEntityIdFromRef(knownLicense, nextEntityId)
+    const k = await db.get(KnownLicenseEntity, { where: { id: licenseEntityId } })
+    if (!k) throw Error(`KnownLicenseEntity(${licenseEntityId}) not found`)
+
+    const licenseType = new KnownLicense()
+    licenseType.code = k.code
+    licenseType.description = k.description
+    licenseType.name = k.name
+    licenseType.url = k.url
+    l.type = licenseType
+  }
+
+  if (userDefinedLicense) {
+    licenseEntityId = getEntityIdFromRef(userDefinedLicense, nextEntityId)
+    const u = await db.get(UserDefinedLicenseEntity, {
+      where: { id: licenseEntityId },
+    })
+    if (!u) throw Error(`UserDefinedLicenseEntity(${licenseEntityId}) not found`)
+    const licenseType = new UserDefinedLicense()
+    licenseType.content = u.content
+    l.type = licenseType
+  }
+
+  l.attribution = props.attribution || l.attribution
+  await db.save<LicenseEntity>(l)
+}
+
+export async function addSchemaToMediaLocation(param: SchemaSupport<IMediaLocation>): Promise<void> {
+  const { entityId, props, db, nextEntityId } = param
+  const m = await db.get(MediaLocationEntity, { where: { id: entityId.toString() } })
+  if (!m) throw Error(`MediaLocationEntity(${entityId}) has never been created!`)
+
+  const { httpMediaLocation, joystreamMediaLocation } = props
+
+  if (httpMediaLocation) {
+    m.httpMediaLocation =
+      (await db.get(HttpMediaLocationEntity, {
+        where: { id: getEntityIdFromRef(httpMediaLocation, nextEntityId) },
+      })) || m.httpMediaLocation
+  }
+  if (joystreamMediaLocation) {
+    m.joystreamMediaLocation =
+      (await db.get(JoystreamMediaLocationEntity, {
+        where: { id: getEntityIdFromRef(joystreamMediaLocation, nextEntityId) },
+      })) || m.joystreamMediaLocation
+  }
+  await db.save<MediaLocationEntity>(m)
+}
+
+export async function addSchemaToUserDefinedLicense(param: SchemaSupport<IUserDefinedLicense>): Promise<void> {
+  const { entityId, props, db } = param
+  const u = await db.get(UserDefinedLicenseEntity, { where: { id: entityId.toString() } })
+  if (!u) throw Error(`UserDefinedLicenseEntity(${entityId}) has never been created!`)
+
+  u.content = props.content || u.content
+  await db.save<UserDefinedLicenseEntity>(u)
+}
+
+export async function addSchemaToVideoMedia(param: SchemaSupport<IVideoMedia>): Promise<void> {
+  const { entityId, props, db, nextEntityId } = param
+  const v = await db.get(VideoMedia, { where: { id: entityId.toString() } })
+  if (!v) throw Error(`VideoMedia(${entityId}) has never been created!`)
+
+  v.pixelHeight = props.pixelHeight || v.pixelHeight
+  v.pixelWidth = props.pixelWidth || v.pixelWidth
+  v.size = props.size || v.size
+
+  const { location, encoding } = props
+
+  if (encoding) {
+    const encodingId = getEntityIdFromRef(encoding, nextEntityId)
+    const encod = await db.get(VideoMediaEncoding, { where: { id: encodingId } })
+    if (!encod) throw Error(`VideoMediaEncoding(${encodingId}) has never been created!`)
+    v.encoding = encod
+  }
+
+  if (location) {
+    const mediaLocation = await db.get(MediaLocationEntity, {
+      where: { id: getEntityIdFromRef(location, nextEntityId) },
+      relations: ['httpMediaLocation', 'joystreamMediaLocation'],
+    })
+    v.locationEntity = mediaLocation
+
+    if (mediaLocation) {
+      const { httpMediaLocation, joystreamMediaLocation } = mediaLocation
+      if (httpMediaLocation) {
+        const mediaLoc = new HttpMediaLocation()
+        mediaLoc.port = httpMediaLocation.port
+        mediaLoc.url = httpMediaLocation.url
+        v.location = mediaLoc
+      }
+      if (joystreamMediaLocation) {
+        const mediaLoc = new JoystreamMediaLocation()
+        mediaLoc.dataObjectId = joystreamMediaLocation.dataObjectId
+        v.location = mediaLoc
+      }
+    }
+  }
+  await db.save<VideoMedia>(v)
+}
+
+export async function addSchemaToVideoMediaEncoding(param: SchemaSupport<IVideoMediaEncoding>): Promise<void> {
+  const { entityId, props, db } = param
+  const e = await db.get(VideoMediaEncoding, { where: { id: entityId.toString() } })
+  if (!e) throw Error(`VideoMediaEncoding(${entityId}) has never been created!`)
+
+  e.name = props.name || e.name
+  await db.save<VideoMediaEncoding>(e)
+}
+
+export async function addSchemaToFeaturedVideo(param: SchemaSupport<IFeaturedVideo>): Promise<void> {
+  const { entityId, props, db, nextEntityId } = param
+  const f = await db.get(FeaturedVideo, { where: { id: entityId.toString() } })
+  if (!f) throw Error(`FeaturedVideo(${entityId}) has never been created!`)
+
+  if (props.video) {
+    const videoId = getEntityIdFromRef(props.video, nextEntityId)
+    const v = await db.get(Video, { where: { id: videoId } })
+    if (!v) throw Error(`Video(${videoId}) has never been created!`)
+    f.video = v
+  }
+  await db.save<FeaturedVideo>(f)
+}
+
+export async function addSchemaToVideo(param: SchemaSupport<IVideo>): Promise<void> {
+  const { entityId, nextEntityId, props, db } = param
+
+  const v = await db.get(Video, { where: { id: entityId.toString() } })
+  if (!v) throw Error(`Video(${entityId}) has never been created!`)
+
+  v.title = props.title || v.title
+  v.description = props.description || v.description
+  v.duration = props.duration || v.duration
+  v.hasMarketing = props.hasMarketing || v.hasMarketing
+  v.isCurated = !!props.isCurated
+  v.isExplicit = props.isExplicit || v.isExplicit
+  v.isPublic = props.isPublic || v.isPublic
+  v.publishedBeforeJoystream = props.publishedBeforeJoystream || v.publishedBeforeJoystream
+  v.skippableIntroDuration = props.skippableIntroDuration || v.skippableIntroDuration
+  v.thumbnailUrl = props.thumbnailUrl || v.thumbnailUrl
+  v.isFeatured = !!v.isFeatured
+
+  const { language, license, category, channel, media } = props
+
+  if (language) {
+    v.language = await db.get(Language, { where: { id: getEntityIdFromRef(language, nextEntityId) } })
+  }
+  if (license) {
+    const licenseId = getEntityIdFromRef(license, nextEntityId)
+    const l = await db.get(LicenseEntity, { where: { id: licenseId } })
+    if (!l) throw Error(`LicenseEntity(${licenseId}) has never been created!`)
+    v.license = l
+  }
+  if (category) {
+    const categoryId = getEntityIdFromRef(category, nextEntityId)
+    const c = await db.get(Category, { where: { id: categoryId } })
+    if (!c) throw Error(`Category(${categoryId}) has never been created!`)
+    v.category = c
+  }
+  if (channel) {
+    const channelId = getEntityIdFromRef(channel, nextEntityId)
+    const c = await db.get(Channel, { where: { id: channelId } })
+    if (!c) throw Error(`Channel(${channelId}) has never been created!`)
+    v.channel = c
+  }
+  if (media) {
+    v.media = await db.get(VideoMedia, { where: { id: getEntityIdFromRef(media, nextEntityId) } })
+  }
+  /* eslint-enable @typescript-eslint/no-non-null-assertion */
+  await db.save<Video>(v)
+}

+ 139 - 197
query-node/mappings/content-directory/entity/index.ts

@@ -3,21 +3,6 @@ import { DB, SubstrateEvent } from '../../../generated/indexer'
 import { ClassEntity } from '../../../generated/graphql-server/src/modules/class-entity/class-entity.model'
 
 import { decode } from '../decode'
-import {
-  updateCategoryEntityPropertyValues,
-  updateChannelEntityPropertyValues,
-  updateVideoMediaEntityPropertyValues,
-  updateVideoEntityPropertyValues,
-  updateUserDefinedLicenseEntityPropertyValues,
-  updateHttpMediaLocationEntityPropertyValues,
-  updateJoystreamMediaLocationEntityPropertyValues,
-  updateKnownLicenseEntityPropertyValues,
-  updateLanguageEntityPropertyValues,
-  updateVideoMediaEncodingEntityPropertyValues,
-  updateLicenseEntityPropertyValues,
-  updateMediaLocationEntityPropertyValues,
-  updateFeaturedVideoEntityPropertyValues,
-} from './update'
 import {
   removeCategory,
   removeChannel,
@@ -33,20 +18,7 @@ import {
   removeMediaLocation,
   removeFeaturedVideo,
 } from './remove'
-import {
-  createCategory,
-  createChannel,
-  createVideoMedia,
-  createVideo,
-  createUserDefinedLicense,
-  createKnownLicense,
-  createHttpMediaLocation,
-  createJoystreamMediaLocation,
-  createLanguage,
-  createVideoMediaEncoding,
-  createBlockOrGetFromDatabase,
-  createFeaturedVideo,
-} from './create'
+import { createBlockOrGetFromDatabase } from './create'
 import {
   categoryPropertyNamesWithId,
   channelPropertyNamesWithId,
@@ -59,6 +31,8 @@ import {
   videoPropertyNamesWithId,
   ContentDirectoryKnownClasses,
   featuredVideoPropertyNamesWithId,
+  licensePropertyNamesWithId,
+  mediaLocationPropertyNamesWithId,
 } from '../content-dir-consts'
 
 import {
@@ -72,111 +46,177 @@ import {
   IVideo,
   ILanguage,
   IVideoMediaEncoding,
-  IDBBlockId,
   IWhereCond,
-  IEntity,
   ILicense,
   IMediaLocation,
   IFeaturedVideo,
 } from '../../types'
 import { getOrCreate, getKnownClass } from '../get-or-create'
+import { createDefaultSchema } from '../default-schemas'
+import {
+  addSchemaToCategory,
+  addSchemaToChannel,
+  addSchemaToFeaturedVideo,
+  addSchemaToHttpMediaLocation,
+  addSchemaToJoystreamMediaLocation,
+  addSchemaToKnownLicense,
+  addSchemaToLanguage,
+  addSchemaToLicense,
+  addSchemaToMediaLocation,
+  addSchemaToUserDefinedLicense,
+  addSchemaToVideo,
+  addSchemaToVideoMedia,
+  addSchemaToVideoMediaEncoding,
+} from './addSchema'
+import { NextEntityId } from '../../../generated/graphql-server/src/modules/next-entity-id/next-entity-id.model'
 
 const debug = Debug('mappings:content-directory')
 
-// eslint-disable-next-line @typescript-eslint/naming-convention
-async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: SubstrateEvent): Promise<void> {
-  if (event.extrinsic && event.extrinsic.method === 'transaction') return
-  debug(`EntitySchemaSupportAdded event: ${JSON.stringify(event)}`)
-
-  const { blockNumber: block } = event
-  const entityId = decode.stringIfyEntityId(event)
-
-  const [knownClass] = await getKnownClass(db, { where: { id: entityId } })
-  if (!knownClass) return
-
-  const arg: IDBBlockId = { db, block, id: entityId }
-
-  switch (knownClass.name) {
+async function addSchemSupportToEntity(
+  event: SubstrateEvent,
+  className: string,
+  db: DB,
+  entityId: number,
+  nextEntityId = 0
+) {
+  switch (className) {
     case ContentDirectoryKnownClasses.CHANNEL:
-      await createChannel(
-        arg,
-        new Map<string, IEntity[]>(),
-        decode.setProperties<IChannel>(event, channelPropertyNamesWithId),
-        0 // ignored
-      )
+      addSchemaToChannel({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IChannel>(event, channelPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.CATEGORY:
-      await createCategory(arg, decode.setProperties<ICategory>(event, categoryPropertyNamesWithId))
+      await addSchemaToCategory({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<ICategory>(event, categoryPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.KNOWNLICENSE:
-      await createKnownLicense(arg, decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId))
+      await addSchemaToKnownLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId),
+      })
       break
 
     case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
-      await createUserDefinedLicense(
-        arg,
-        decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId)
-      )
+      await addSchemaToUserDefinedLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
-      await createJoystreamMediaLocation(
-        arg,
-        decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId)
-      )
+      await addSchemaToJoystreamMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
-      await createHttpMediaLocation(
-        arg,
-        decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId)
-      )
+      await addSchemaToHttpMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.VIDEOMEDIA:
-      await createVideoMedia(
-        arg,
-        new Map<string, IEntity[]>(),
-        decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
-        0 // ignored
-      )
+      await addSchemaToVideoMedia({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.VIDEO:
-      await createVideo(
-        arg,
-        new Map<string, IEntity[]>(),
-        decode.setProperties<IVideo>(event, videoPropertyNamesWithId),
-        0 // ignored
-      )
+      await addSchemaToVideo({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IVideo>(event, videoPropertyNamesWithId),
+      })
       break
 
     case ContentDirectoryKnownClasses.LANGUAGE:
-      await createLanguage(arg, decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId))
+      await addSchemaToLanguage({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId),
+      })
       break
 
     case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
-      await createVideoMediaEncoding(
-        arg,
-        decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
-      )
+      await addSchemaToVideoMediaEncoding({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId),
+      })
       break
+
     case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
-      await createFeaturedVideo(
-        arg,
-        new Map<string, IEntity[]>(),
-        decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
-        0
-      )
+      await addSchemaToFeaturedVideo({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.LICENSE:
+      await addSchemaToLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<ILicense>(event, licensePropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.MEDIALOCATION:
+      await addSchemaToMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setProperties<IMediaLocation>(event, mediaLocationPropertyNamesWithId),
+      })
       break
 
     default:
-      throw new Error(`Unknown class name: ${knownClass.name}`)
+      debug(`Unknown class name: ${className}`)
+      break
   }
 }
 
+// eslint-disable-next-line @typescript-eslint/naming-convention
+async function contentDirectory_EntitySchemaSupportAdded(db: DB, event: SubstrateEvent): Promise<void> {
+  if (event.extrinsic && event.extrinsic.method === 'transaction') return
+  debug(`EntitySchemaSupportAdded event: ${JSON.stringify(event)}`)
+
+  const { params } = event
+  const entityId = params[1].value as number
+
+  const [knownClass] = await getKnownClass(db, { where: { id: entityId.toString() } })
+  if (!knownClass) return
+
+  await addSchemSupportToEntity(event, knownClass.name, db, entityId)
+}
+
 // eslint-disable-next-line @typescript-eslint/naming-convention
 async function contentDirectory_EntityRemoved(db: DB, event: SubstrateEvent): Promise<void> {
   debug(`EntityRemoved event: ${JSON.stringify(event)}`)
@@ -259,7 +299,11 @@ async function contentDirectory_EntityCreated(db: DB, event: SubstrateEvent): Pr
   classEntity.happenedIn = await createBlockOrGetFromDatabase(db, event.blockNumber)
   await db.save<ClassEntity>(classEntity)
 
-  await getOrCreate.nextEntityId(db, c.entityId + 1)
+  const nextEntityIdFromDb = await getOrCreate.nextEntityId(db)
+  nextEntityIdFromDb.nextId = c.entityId + 1
+  await db.save<NextEntityId>(nextEntityIdFromDb)
+
+  await createDefaultSchema(db, classEntity)
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -271,10 +315,11 @@ async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: Subst
   debug(`EntityPropertyValuesUpdated event: ${JSON.stringify(event)}`)
 
   const { 2: newPropertyValues } = extrinsic.args
-  const entityId = decode.stringIfyEntityId(event)
-  const where: IWhereCond = { where: { id: entityId } }
+  // const entityId = decode.stringIfyEntityId(event)
+  // const where: IWhereCond = { where: { id: entityId } }
+  const entityId = event.params[1].value as number
 
-  const [knownClass] = await getKnownClass(db, where)
+  const [knownClass] = await getKnownClass(db, { where: { id: entityId.toString() } })
   if (!knownClass) return
 
   // TODO: change setProperties method signature to accecpt SubstrateExtrinsic, then remove the following
@@ -282,110 +327,7 @@ async function contentDirectory_EntityPropertyValuesUpdated(db: DB, event: Subst
   // to get properties values
   extrinsic.args.push(newPropertyValues)
 
-  switch (knownClass.name) {
-    case ContentDirectoryKnownClasses.CHANNEL:
-      updateChannelEntityPropertyValues(db, where, decode.setProperties<IChannel>(event, channelPropertyNamesWithId), 0)
-      break
-
-    case ContentDirectoryKnownClasses.CATEGORY:
-      await updateCategoryEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<ICategory>(event, categoryPropertyNamesWithId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.KNOWNLICENSE:
-      await updateKnownLicenseEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IKnownLicense>(event, knownLicensePropertyNamesWIthId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
-      await updateUserDefinedLicenseEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IUserDefinedLicense>(event, userDefinedLicensePropertyNamesWithId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
-      await updateJoystreamMediaLocationEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IJoystreamMediaLocation>(event, joystreamMediaLocationPropertyNamesWithId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
-      await updateHttpMediaLocationEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IHttpMediaLocation>(event, httpMediaLocationPropertyNamesWithId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.VIDEOMEDIA:
-      await updateVideoMediaEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IVideoMedia>(event, videoPropertyNamesWithId),
-        0
-      )
-      break
-
-    case ContentDirectoryKnownClasses.VIDEO:
-      await updateVideoEntityPropertyValues(db, where, decode.setProperties<IVideo>(event, videoPropertyNamesWithId), 0)
-      break
-
-    case ContentDirectoryKnownClasses.LANGUAGE:
-      await updateLanguageEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<ILanguage>(event, languagePropertyNamesWIthId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
-      await updateVideoMediaEncodingEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IVideoMediaEncoding>(event, videoMediaEncodingPropertyNamesWithId)
-      )
-      break
-
-    case ContentDirectoryKnownClasses.LICENSE:
-      await updateLicenseEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<ILicense>(event, videoMediaEncodingPropertyNamesWithId),
-        0
-      )
-      break
-
-    case ContentDirectoryKnownClasses.MEDIALOCATION:
-      await updateMediaLocationEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IMediaLocation>(event, videoMediaEncodingPropertyNamesWithId),
-        0
-      )
-      break
-
-    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
-      await updateFeaturedVideoEntityPropertyValues(
-        db,
-        where,
-        decode.setProperties<IFeaturedVideo>(event, featuredVideoPropertyNamesWithId),
-        0
-      )
-      break
-
-    default:
-      throw new Error(`Unknown class name: ${knownClass.name}`)
-  }
+  await addSchemSupportToEntity(event, knownClass.name, db, entityId)
 }
 
 export {

+ 6 - 4
query-node/mappings/content-directory/get-or-create.ts

@@ -67,11 +67,13 @@ import {
 import { DB } from '../../generated/indexer'
 
 // Keep track of the next entity id
-async function nextEntityId(db: DB, nextEntityId: number): Promise<void> {
+async function nextEntityId(db: DB): Promise<NextEntityId> {
   let e = await db.get(NextEntityId, { where: { id: '1' } })
-  if (!e) e = new NextEntityId({ id: '1' })
-  e.nextId = nextEntityId
-  await db.save<NextEntityId>(e)
+  if (!e) {
+    e = new NextEntityId({ id: '1', nextId: 1 })
+    await db.save<NextEntityId>(e)
+  }
+  return e
 }
 
 function generateEntityIdFromIndex(index: number): string {

+ 3 - 0
query-node/mappings/content-directory/mapping.ts

@@ -5,3 +5,6 @@ export {
   contentDirectory_EntityPropertyValuesUpdated,
 } from './entity'
 export { contentDirectory_TransactionCompleted, contentDirectory_TransactionFailed } from './transaction'
+
+// Only one time to seed the database
+// export { system_ExtrinsicSuccess } from './initializeDefaultSchemas'

+ 171 - 260
query-node/mappings/content-directory/transaction.ts

@@ -20,6 +20,7 @@ import {
   ILanguage,
   ILicense,
   IMediaLocation,
+  IProperty,
   IUserDefinedLicense,
   IVideo,
   IVideoMedia,
@@ -42,40 +43,25 @@ import {
   mediaLocationPropertyNamesWithId,
   featuredVideoPropertyNamesWithId,
 } from './content-dir-consts'
-import {
-  updateCategoryEntityPropertyValues,
-  updateChannelEntityPropertyValues,
-  updateVideoMediaEntityPropertyValues,
-  updateVideoEntityPropertyValues,
-  updateUserDefinedLicenseEntityPropertyValues,
-  updateHttpMediaLocationEntityPropertyValues,
-  updateJoystreamMediaLocationEntityPropertyValues,
-  updateKnownLicenseEntityPropertyValues,
-  updateLanguageEntityPropertyValues,
-  updateVideoMediaEncodingEntityPropertyValues,
-  updateLicenseEntityPropertyValues,
-  updateMediaLocationEntityPropertyValues,
-  updateFeaturedVideoEntityPropertyValues,
-} from './entity/update'
 
-import {
-  createCategory,
-  createChannel,
-  createVideoMedia,
-  createVideo,
-  createUserDefinedLicense,
-  createKnownLicense,
-  createHttpMediaLocation,
-  createJoystreamMediaLocation,
-  createLanguage,
-  createVideoMediaEncoding,
-  getClassName,
-  createLicense,
-  createMediaLocation,
-  createBlockOrGetFromDatabase,
-  createFeaturedVideo,
-} from './entity/create'
+import { getClassName, createBlockOrGetFromDatabase } from './entity/create'
 import { getOrCreate } from './get-or-create'
+import {
+  addSchemaToCategory,
+  addSchemaToChannel,
+  addSchemaToFeaturedVideo,
+  addSchemaToHttpMediaLocation,
+  addSchemaToJoystreamMediaLocation,
+  addSchemaToKnownLicense,
+  addSchemaToLanguage,
+  addSchemaToLicense,
+  addSchemaToMediaLocation,
+  addSchemaToUserDefinedLicense,
+  addSchemaToVideo,
+  addSchemaToVideoMedia,
+  addSchemaToVideoMediaEncoding,
+} from './entity/addSchema'
+import { createDefaultSchema } from './default-schemas'
 
 const debug = Debug('mappings:cd:transaction')
 
@@ -119,21 +105,26 @@ async function applyOperations(operations: IBatchOperation, db: DB, event: Subst
 }
 
 async function batchCreateClassEntities(db: DB, block: number, operations: ICreateEntityOperation[]): Promise<void> {
-  const nId = await db.get(NextEntityId, { where: { id: '1' } })
-  let nextId = nId ? nId.nextId : 1 // start entity id from 1
+  const nextEntityIdFromDb = await getOrCreate.nextEntityId(db)
 
+  let entityId = nextEntityIdFromDb.nextId
   for (const { classId } of operations) {
     const c = new ClassEntity({
-      id: nextId.toString(), // entity id
+      id: entityId.toString(),
       classId: classId,
       version: block,
       happenedIn: await createBlockOrGetFromDatabase(db, block),
     })
     await db.save<ClassEntity>(c)
-    nextId++
+
+    // Create default schema for the entity
+    await createDefaultSchema(db, c)
+    entityId++
   }
 
-  await getOrCreate.nextEntityId(db, nextId)
+  // Update database for next entity id
+  nextEntityIdFromDb.nextId = entityId
+  await db.save<NextEntityId>(nextEntityIdFromDb)
 }
 
 /**
@@ -161,7 +152,7 @@ async function batchAddSchemaSupportToEntity(
 
   // This is a copy of classEntityMap, we will use it to keep track of items.
   // We will remove items from this list whenever we insert them into db
-  const doneList: ClassEntityMap = new Map(classEntityMap.entries())
+  // const doneList: ClassEntityMap = new Map(classEntityMap.entries())
 
   const nextEntityIdBeforeTransaction = (await getNextEntityId(db)) - createEntityOperations.length
 
@@ -170,112 +161,9 @@ async function batchAddSchemaSupportToEntity(
       const { entityId, indexOf, properties } = entity
       // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
       const id = entityId !== undefined ? entityId : indexOf! + nextEntityIdBeforeTransaction
-      const arg: IDBBlockId = { db, block, id: id.toString() }
-
-      switch (className) {
-        case ContentDirectoryKnownClasses.CATEGORY:
-          await createCategory(arg, decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId))
-          break
-
-        case ContentDirectoryKnownClasses.CHANNEL:
-          await createChannel(
-            arg,
-            doneList,
-            decode.setEntityPropertyValues<IChannel>(properties, channelPropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-
-        case ContentDirectoryKnownClasses.KNOWNLICENSE:
-          await createKnownLicense(
-            arg,
-            decode.setEntityPropertyValues<IKnownLicense>(properties, knownLicensePropertyNamesWIthId)
-          )
-          break
-
-        case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
-          await createUserDefinedLicense(
-            arg,
-            decode.setEntityPropertyValues<IUserDefinedLicense>(properties, userDefinedLicensePropertyNamesWithId)
-          )
-          break
-
-        case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
-          await createJoystreamMediaLocation(
-            arg,
-            decode.setEntityPropertyValues<IJoystreamMediaLocation>(
-              properties,
-              joystreamMediaLocationPropertyNamesWithId
-            )
-          )
-          break
-
-        case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
-          await createHttpMediaLocation(
-            arg,
-            decode.setEntityPropertyValues<IHttpMediaLocation>(properties, httpMediaLocationPropertyNamesWithId)
-          )
-          break
-
-        case ContentDirectoryKnownClasses.VIDEOMEDIA:
-          await createVideoMedia(
-            arg,
-            doneList,
-            decode.setEntityPropertyValues<IVideoMedia>(properties, videoMediaPropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-
-        case ContentDirectoryKnownClasses.VIDEO:
-          await createVideo(
-            arg,
-            doneList,
-            decode.setEntityPropertyValues<IVideo>(properties, videoPropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-
-        case ContentDirectoryKnownClasses.LANGUAGE:
-          await createLanguage(arg, decode.setEntityPropertyValues<ILanguage>(properties, languagePropertyNamesWIthId))
-          break
-
-        case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
-          await createVideoMediaEncoding(
-            arg,
-            decode.setEntityPropertyValues<IVideoMediaEncoding>(properties, videoMediaEncodingPropertyNamesWithId)
-          )
-          break
-
-        case ContentDirectoryKnownClasses.LICENSE:
-          await createLicense(
-            arg,
-            classEntityMap,
-            decode.setEntityPropertyValues<ILicense>(properties, licensePropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-        case ContentDirectoryKnownClasses.MEDIALOCATION:
-          await createMediaLocation(
-            arg,
-            classEntityMap,
-            decode.setEntityPropertyValues<IMediaLocation>(properties, mediaLocationPropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-
-        case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
-          await createFeaturedVideo(
-            arg,
-            classEntityMap,
-            decode.setEntityPropertyValues<IFeaturedVideo>(properties, featuredVideoPropertyNamesWithId),
-            nextEntityIdBeforeTransaction
-          )
-          break
-
-        default:
-          console.log(`Unknown class name: ${className}`)
-          break
-      }
+      // const arg: IDBBlockId = { db, block, id: id.toString() }
+
+      await addSchemaSupportToEntity(db, className, id, nextEntityIdBeforeTransaction, properties)
     }
   }
 }
@@ -292,126 +180,149 @@ async function batchUpdatePropertyValue(db: DB, createEntityOperations: ICreateE
   for (const entity of entities) {
     const { entityId, indexOf, properties } = entity
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const id = entityId ? entityId.toString() : entityIdBeforeTransaction - indexOf!
+    const id = entityId !== undefined ? entityId : entityIdBeforeTransaction - indexOf!
 
-    const where: IWhereCond = { where: { id: id.toString() } }
+    // const where: IWhereCond = { where: { id: id.toString() } }
     const className = await getClassName(db, entity, createEntityOperations)
-    if (className === undefined) {
-      console.log(`Can not update entity properties values. Unknown class name`)
+    if (!className) {
+      debug(`Can not update entity properties values. Unknown class name`)
       return
     }
 
-    switch (className) {
-      case ContentDirectoryKnownClasses.CHANNEL:
-        await updateChannelEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IChannel>(properties, channelPropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-
-      case ContentDirectoryKnownClasses.CATEGORY:
-        await updateCategoryEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.KNOWNLICENSE:
-        await updateKnownLicenseEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IKnownLicense>(properties, knownLicensePropertyNamesWIthId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
-        await updateUserDefinedLicenseEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IUserDefinedLicense>(properties, userDefinedLicensePropertyNamesWithId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
-        await updateJoystreamMediaLocationEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IJoystreamMediaLocation>(properties, joystreamMediaLocationPropertyNamesWithId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
-        await updateHttpMediaLocationEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IHttpMediaLocation>(properties, httpMediaLocationPropertyNamesWithId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.VIDEOMEDIA:
-        await updateVideoMediaEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IVideoMedia>(properties, videoPropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-
-      case ContentDirectoryKnownClasses.VIDEO:
-        await updateVideoEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IVideo>(properties, videoPropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-
-      case ContentDirectoryKnownClasses.LANGUAGE:
-        await updateLanguageEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<ILanguage>(properties, languagePropertyNamesWIthId)
-        )
-        break
-
-      case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
-        await updateVideoMediaEncodingEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IVideoMediaEncoding>(properties, videoMediaEncodingPropertyNamesWithId)
-        )
-        break
-      case ContentDirectoryKnownClasses.LICENSE:
-        await updateLicenseEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<ILicense>(properties, licensePropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-      case ContentDirectoryKnownClasses.MEDIALOCATION:
-        await updateMediaLocationEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IMediaLocation>(properties, mediaLocationPropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-      case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
-        await updateFeaturedVideoEntityPropertyValues(
-          db,
-          where,
-          decode.setEntityPropertyValues<IFeaturedVideo>(properties, featuredVideoPropertyNamesWithId),
-          entityIdBeforeTransaction
-        )
-        break
-
-      default:
-        console.log(`Unknown class name: ${className}`)
-        break
-    }
+    await addSchemaSupportToEntity(db, className, id, entityIdBeforeTransaction, properties)
+  }
+}
+
+async function addSchemaSupportToEntity(
+  db: DB,
+  className: string,
+  entityId: number,
+  nextEntityId: number,
+  properties: IProperty[]
+) {
+  switch (className) {
+    case ContentDirectoryKnownClasses.CATEGORY:
+      await addSchemaToCategory({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<ICategory>(properties, categoryPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.CHANNEL:
+      await addSchemaToChannel({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IChannel>(properties, channelPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.KNOWNLICENSE:
+      await addSchemaToKnownLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IKnownLicense>(properties, knownLicensePropertyNamesWIthId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.USERDEFINEDLICENSE:
+      await addSchemaToUserDefinedLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IUserDefinedLicense>(properties, userDefinedLicensePropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.JOYSTREAMMEDIALOCATION:
+      await addSchemaToJoystreamMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IJoystreamMediaLocation>(
+          properties,
+          joystreamMediaLocationPropertyNamesWithId
+        ),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.HTTPMEDIALOCATION:
+      await addSchemaToHttpMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IHttpMediaLocation>(properties, httpMediaLocationPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.VIDEOMEDIA:
+      await addSchemaToVideoMedia({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IVideoMedia>(properties, videoMediaPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.VIDEO:
+      await addSchemaToVideo({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IVideo>(properties, videoPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.LANGUAGE:
+      await addSchemaToLanguage({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<ILanguage>(properties, languagePropertyNamesWIthId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.VIDEOMEDIAENCODING:
+      await addSchemaToVideoMediaEncoding({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IVideoMediaEncoding>(properties, videoMediaEncodingPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.LICENSE:
+      await addSchemaToLicense({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<ILicense>(properties, licensePropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.MEDIALOCATION:
+      await addSchemaToMediaLocation({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IMediaLocation>(properties, mediaLocationPropertyNamesWithId),
+      })
+      break
+
+    case ContentDirectoryKnownClasses.FEATUREDVIDEOS:
+      await addSchemaToFeaturedVideo({
+        db,
+        entityId,
+        nextEntityId,
+        props: decode.setEntityPropertyValues<IFeaturedVideo>(properties, featuredVideoPropertyNamesWithId),
+      })
+      break
+
+    default:
+      debug(`Unknown class name: ${className}`)
+      break
   }
 }

+ 42 - 40
query-node/package.json

@@ -1,42 +1,44 @@
 {
-	"name": "query-node-root",
-	"version": "1.0.0",
-	"description": "GraphQL server and Substrate indexer. Generated with ♥ by Hydra-CLI",
-	"scripts": {
-		"build": "./build.sh",
-		"test": "echo \"Error: no test specified\" && exit 1",
-		"clean": "rm -rf ./generated",
-		"processor:start": "./processor-start.sh",
-		"indexer:start": "(cd ./generated/indexer && yarn && DEBUG=${DEBUG} yarn start:indexer --env ../../../.env)",
-		"server:start:dev": "(cd ./generated/graphql-server && yarn start:dev)",
-		"server:start:prod": "(cd ./generated/graphql-server && yarn start:prod)",
-		"configure": "(cd ./generated/graphql-server && yarn config:dev)",
-		"db:up": "(cd ../ && docker-compose up -d db)",
-		"db:drop": "(cd ./generated/graphql-server && yarn db:drop)",
-		"db:migrate": "./db-migrate.sh",
-		"db:schema:migrate": "(cd ./generated/graphql-server && yarn db:create && yarn db:sync && yarn db:migrate)",
-		"db:indexer:migrate": "(cd ./generated/indexer && yarn db:migrate)",
-		"codegen:indexer": "yarn hydra-cli codegen --no-install --no-graphql && cp indexer-tsconfig.json generated/indexer/tsconfig.json",
-		"codegen:server": "yarn hydra-cli codegen --no-install --no-indexer",
-		"cd-classes": "ts-node scripts/get-class-id-and-name.ts",
-		"integration-tests": "./run-tests.sh"
-	},
-	"author": "",
-	"license": "ISC",
-	"devDependencies": {
-		"@dzlzv/hydra-cli": "^0.0.24"
-	},
-	"dependencies": {
-		"@dzlzv/hydra-indexer-lib": "^0.0.22-legacy.1.26.1",
-		"@joystream/types": "^0.14.0",
-		"@types/bn.js": "^4.11.6",
-		"@types/debug": "^4.1.5",
-		"bn.js": "^5.1.2",
-		"debug": "^4.2.0",
-		"dotenvi": "^0.9.1",
-		"tslib": "^2.0.0"
-	},
-	"volta": {
-		"extends": "../package.json"
-	}
+  "name": "query-node-root",
+  "version": "1.0.0",
+  "description": "GraphQL server and Substrate indexer. Generated with ♥ by Hydra-CLI",
+  "scripts": {
+    "build": "./build.sh",
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "clean": "rm -rf ./generated",
+    "processor:start": "./processor-start.sh",
+    "indexer:start": "(cd ./generated/indexer && yarn && DEBUG=${DEBUG} yarn start:indexer --env ../../../.env)",
+    "server:start:dev": "(cd ./generated/graphql-server && yarn start:dev)",
+    "server:start:prod": "(cd ./generated/graphql-server && yarn start:prod)",
+    "configure": "(cd ./generated/graphql-server && yarn config:dev)",
+    "db:up": "(cd ../ && docker-compose up -d db)",
+    "db:drop": "(cd ./generated/graphql-server && yarn db:drop)",
+    "db:migrate": "./db-migrate.sh",
+    "db:schema:migrate": "(cd ./generated/graphql-server && yarn db:create && yarn db:sync && yarn db:migrate)",
+    "db:indexer:migrate": "(cd ./generated/indexer && yarn db:migrate)",
+    "codegen:indexer": "yarn hydra-cli codegen --no-install --no-graphql && cp indexer-tsconfig.json generated/indexer/tsconfig.json",
+    "codegen:server": "yarn hydra-cli codegen --no-install --no-indexer",
+    "cd-classes": "ts-node scripts/get-class-id-and-name.ts",
+    "integration-tests": "./run-tests.sh",
+    "db:init": "(cd ./generated/graphql-server && TYPEORM_LOGGING=true ts-node ../../scripts/initializeDefaultSchemas.ts)"
+  },
+  "author": "",
+  "license": "ISC",
+  "devDependencies": {
+    "@dzlzv/hydra-cli": "^0.0.24"
+  },
+  "dependencies": {
+    "@dzlzv/hydra-indexer-lib": "^0.0.22-legacy.1.26.1",
+    "@joystream/types": "^0.14.0",
+    "@types/bn.js": "^4.11.6",
+    "@types/debug": "^4.1.5",
+    "bn.js": "^5.1.2",
+    "debug": "^4.2.0",
+    "dotenvi": "^0.9.1",
+    "nanoid": "^3.1.20",
+    "tslib": "^2.0.0"
+  },
+  "volta": {
+    "extends": "../package.json"
+  }
 }

+ 3 - 0
query-node/run-tests.sh

@@ -35,6 +35,9 @@ docker-compose up -d db
 # Migrate the databases
 yarn workspace query-node-root db:migrate
 
+# Seed initial schemas
+yarn workspace query-node-root db:init
+
 docker-compose up -d graphql-server
 
 # Start the joystream-node before the indexer

+ 2 - 2
query-node/schema.graphql

@@ -185,7 +185,7 @@ type JoystreamMediaLocationEntity @entity {
   id: ID!
 
   "Id of the data object in the Joystream runtime dataDirectory module"
-  dataObjectId: String! @unique
+  dataObjectId: String!
 
   happenedIn: Block!
 }
@@ -258,7 +258,7 @@ type Video @entity {
   language: Language
 
   "Reference to VideoMedia"
-  media: VideoMedia!
+  media: VideoMedia
 
   "Whether or not Video contains marketing"
   hasMarketing: Boolean

+ 155 - 0
query-node/scripts/initializeDefaultSchemas.ts

@@ -0,0 +1,155 @@
+/* eslint-disable import/first */
+import 'reflect-metadata'
+
+import { loadConfig } from '../generated/graphql-server/src/config'
+loadConfig()
+
+import BN from 'bn.js'
+import { nanoid } from 'nanoid'
+import { SnakeNamingStrategy } from '@dzlzv/hydra-indexer-lib/lib'
+import { createConnection, ConnectionOptions, getConnection, EntityManager } from 'typeorm'
+
+import { Video } from '../generated/graphql-server/src/modules/video/video.model'
+import { Channel } from '../generated/graphql-server/src/modules/channel/channel.model'
+import { Block, Network } from '../generated/graphql-server/src/modules/block/block.model'
+import { Category } from '../generated/graphql-server/src/modules/category/category.model'
+import { VideoMedia } from '../generated/graphql-server/src/modules/video-media/video-media.model'
+import { LicenseEntity } from '../generated/graphql-server/src/modules/license-entity/license-entity.model'
+import { JoystreamMediaLocation, KnownLicense } from '../generated/graphql-server/src/modules/variants/variants.model'
+import { KnownLicenseEntity } from '../generated/graphql-server/src/modules/known-license-entity/known-license-entity.model'
+import { VideoMediaEncoding } from '../generated/graphql-server/src/modules/video-media-encoding/video-media-encoding.model'
+import { MediaLocationEntity } from '../generated/graphql-server/src/modules/media-location-entity/media-location-entity.model'
+import { HttpMediaLocationEntity } from '../generated/graphql-server/src/modules/http-media-location-entity/http-media-location-entity.model'
+import { JoystreamMediaLocationEntity } from '../generated/graphql-server/src/modules/joystream-media-location-entity/joystream-media-location-entity.model'
+
+function getConnectionOptions() {
+  const connectionConfig: ConnectionOptions = {
+    type: 'postgres',
+    host: process.env.WARTHOG_DB_HOST,
+    port: parseInt(process.env.WARTHOG_DB_PORT!),
+    username: process.env.WARTHOG_DB_USERNAME,
+    password: process.env.WARTHOG_DB_PASSWORD,
+    database: process.env.WARTHOG_DB_DATABASE,
+    entities: [process.env.WARTHOG_DB_ENTITIES!],
+    namingStrategy: new SnakeNamingStrategy(),
+    logging: true,
+  }
+  return connectionConfig
+}
+
+export async function main(): Promise<void> {
+  console.log(`Initializing...`)
+  await createConnection(getConnectionOptions())
+  await getConnection().transaction(async (db: EntityManager) => {
+    const id = '0'
+    const createdAt = new Date()
+    const createdById = '0'
+    const version = 0
+
+    // ///////// Block /////////////////
+    const happenedIn = new Block({
+      createdAt,
+      createdById,
+      version,
+      block: 0,
+      timestamp: new BN(Date.now()),
+      network: Network.BABYLON,
+    })
+    await db.save<Block>(happenedIn)
+    // ///////// Block /////////////////
+
+    const commonProperties = { id, happenedIn, createdAt, createdById, version }
+
+    // ///////// HttpMediaLocationEntity /////////////////
+    const httpMediaLocation = new HttpMediaLocationEntity({
+      ...commonProperties,
+      url: '5FyzfM2YtZa75hHYCAo5evNS8bH8P4Kw8EyXqKkC5upVSDBQ',
+    })
+    await db.save<HttpMediaLocationEntity>(httpMediaLocation)
+    // ///////// HttpMediaLocationEntity /////////////////
+
+    // ///////// JoystreamMediaLocationEntity /////////////////
+    const joyMediaLocation = new JoystreamMediaLocationEntity({
+      ...commonProperties,
+      dataObjectId: '5FyzfM2YtZa75hHYCAo5evNS8bH8P4Kw8EyXqKkC5upVSDBQ',
+    })
+    await db.save<JoystreamMediaLocationEntity>(joyMediaLocation)
+    // ///////// JoystreamMediaLocationEntity /////////////////
+
+    // ///////// KnownLicenseEntity /////////////////
+    const knownLicense = new KnownLicenseEntity({ ...commonProperties, code: 'NA' })
+    await db.save<KnownLicenseEntity>(knownLicense)
+    // ///////// KnownLicenseEntity /////////////////
+
+    // ///////// License /////////////////
+    const k = new KnownLicense()
+    k.code = knownLicense.code
+    const license = new LicenseEntity({ ...commonProperties, type: k })
+    await db.save<LicenseEntity>(license)
+    // ///////// License /////////////////
+
+    // ///////// MediaLocationEntity /////////////////
+    const mediaLocEntity = new MediaLocationEntity({ ...commonProperties, joystreamMediaLocation: joyMediaLocation })
+    await db.save<MediaLocationEntity>(mediaLocEntity)
+    // ///////// MediaLocationEntity /////////////////
+
+    // ///////// Channel /////////////////
+    const channel = new Channel({
+      ...commonProperties,
+      handle: `Channel(0) - ${nanoid()}`,
+      description: `Channel 0`,
+      isPublic: false,
+      isCurated: false,
+    })
+    await db.save<Channel>(channel)
+    // ///////// Channel /////////////////
+
+    // ///////// Category /////////////////
+    const category = new Category({ ...commonProperties, name: `Category(0) ${nanoid()}` })
+    await db.save<Category>(category)
+    // ///////// Category /////////////////
+
+    // ///////// VideoMediaEncoding /////////////////
+    const videoMediaEncod = new VideoMediaEncoding({ ...commonProperties, name: 'NA' })
+    await db.save<VideoMediaEncoding>(videoMediaEncod)
+    // ///////// VideoMediaEncoding /////////////////
+
+    // ///////// VideoMedia /////////////////
+    const location = new JoystreamMediaLocation()
+    location.dataObjectId = joyMediaLocation.dataObjectId
+    const videoMedia = new VideoMedia({
+      ...commonProperties,
+      location,
+      locationEntity: mediaLocEntity,
+      encoding: videoMediaEncod,
+      pixelHeight: 0,
+      pixelWidth: 0,
+    })
+    await db.save<VideoMedia>(videoMedia)
+    // ///////// VideoMedia /////////////////
+
+    // ///////// Video /////////////////
+    const v = new Video({ ...commonProperties })
+    v.category = category
+    v.channel = channel
+    v.media = videoMedia
+    v.license = license
+    v.title = `Video(0)`
+    v.description = `Video(0)`
+    v.duration = 0
+    v.thumbnailUrl = 'https://eu-central-1.linodeobjects.com/joystream/1.png'
+    v.isPublic = false
+    v.isCurated = false
+    v.isExplicit = false
+    v.isFeatured = false
+    await db.save<Video>(v)
+    // ///////// Video /////////////////
+  })
+}
+
+main()
+  .then(() => {
+    console.log(`Done.`)
+    process.exit()
+  })
+  .catch(console.log)

+ 2 - 2
tests/network-tests/src/flows/contentDirectory/creatingChannel.ts

@@ -15,8 +15,8 @@ export function createSimpleChannelFixture(api: Api): CreateChannelFixture {
     // 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: '',
+    coverPhotoUrl: 'url1',
+    avatarPhotoUrl: 'url2',
     isPublic: true,
   }
   return new CreateChannelFixture(api, channelEntity)

+ 18 - 18
tests/network-tests/src/flows/contentDirectory/creatingVideo.ts

@@ -9,8 +9,8 @@ import Debugger from 'debug'
 
 export function createVideoReferencingChannelFixture(api: Api, handle: string): CreateVideoFixture {
   const videoEntity: VideoEntity = {
-    title: 'Example video',
-    description: 'This is an example video',
+    title: 'Example joyjoy',
+    description: 'This is an example joyjoy',
     // 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' } },
@@ -39,9 +39,9 @@ export function createVideoReferencingChannelFixture(api: Api, handle: string):
       },
     },
     duration: 3600,
-    thumbnailUrl: '',
+    thumbnailUrl: 'url3',
     isExplicit: false,
-    isPublic: true,
+    isPublic: false,
   }
   return new CreateVideoFixture(api, videoEntity)
 }
@@ -68,48 +68,48 @@ export default async function createVideo({ api, query }: FlowProps): Promise<vo
   await Utils.wait(120000)
 
   // Perform number of full text searches on Channel title, that is a slight variation on title that one expects would return the video.
-  let channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('video')
+  let channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('joyjoy')
 
-  assert(channelFullTextSearchResult.data.search.length === 1, 'Should contain exactly one entry')
+  assert.equal(channelFullTextSearchResult.data.search.length, 1, 'Should contain exactly one entry')
 
   // Both channel and video title starts with `Example`
   channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('Example')
 
-  assert(channelFullTextSearchResult.data.search.length === 2, 'Should contain two entries')
+  assert.equal(channelFullTextSearchResult.data.search.length, 2, 'Should contain two entries')
 
   // Perform number full text searches on Channel title, that absolutely should NOT return the video.
-  channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('First')
+  channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('DeadBeef')
 
-  assert(channelFullTextSearchResult.data.search.length === 0, 'Should be empty')
+  assert.equal(channelFullTextSearchResult.data.search.length, 0, 'Should be empty')
 
-  channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('vid')
+  channelFullTextSearchResult = await query.performFullTextSearchOnChannelTitle('joy')
 
-  assert(channelFullTextSearchResult.data.search.length === 0, 'Should be empty')
+  assert.equal(channelFullTextSearchResult.data.search.length, 0, 'Should be empty')
 
   // Ensure channel contains only one video with right data
   const channelResult = await query.getChannelbyHandle(channelTitle)
 
-  assert(channelResult.data.channels[0].videos.length === 1, 'Given channel should contain exactly one video')
+  assert.equal(channelResult.data.channels[0].videos.length, 1, 'Given channel should contain exactly one video')
 
   assertVideoMatchQueriedResult(channelResult.data.channels[0].videos[0], createVideoHappyCaseFixture.videoEntity)
 
   // Perform number of full text searches on Video title, that is a slight variation on title that one expects would return the video.
-  let videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('Example')
+  let videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('example')
 
-  assert(videoFullTextSearchResult.data.search.length === 2, 'Should contain two entries')
+  assert.equal(videoFullTextSearchResult.data.search.length, 2, 'Should contain two entries')
 
-  videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('Example video')
+  videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('Example joyjoy')
 
-  assert(videoFullTextSearchResult.data.search.length === 1, 'Should contain exactly one video')
+  assert.equal(videoFullTextSearchResult.data.search.length, 1, 'Should contain exactly one video')
 
   // Perform number full text searches on Video title, that absolutely should NOT return the video.
   videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('unknown')
 
-  assert(videoFullTextSearchResult.data.search.length === 0, 'Should be empty')
+  assert.equal(videoFullTextSearchResult.data.search.length, 0, 'Should be empty')
 
   videoFullTextSearchResult = await query.performFullTextSearchOnVideoTitle('MediaVideo')
 
-  assert(videoFullTextSearchResult.data.search.length === 0, 'Should be empty')
+  assert.equal(videoFullTextSearchResult.data.search.length, 0, 'Should be empty')
 
   debug('Done')
 }

+ 5 - 0
yarn.lock

@@ -20663,6 +20663,11 @@ nanoid@^3.0.2, nanoid@^3.1.3:
   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
   integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
 
+nanoid@^3.1.20:
+  version "3.1.21"
+  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.21.tgz#25bfee7340ac4185866fbfb2c9006d299da1be7f"
+  integrity sha512-A6oZraK4DJkAOICstsGH98dvycPr/4GGDH7ZWKmMdd3vGcOurZ6JmWFUt0DA5bzrrn2FrUjmv6mFNWvv8jpppA==
+
 nanomatch@^1.2.9:
   version "1.2.13"
   resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"