Browse Source

query node - mappings code lint

ondratra 3 years ago
parent
commit
124c4d36b2

+ 10 - 0
query-node/mappings/.eslintrc.js

@@ -5,5 +5,15 @@ module.exports = {
   },
   rules: {
     '@typescript-eslint/naming-convention': 'off',
+    '@typescript-eslint/ban-types': ["error",
+      {
+        "types": {
+          // enable usage of `Object` data type in TS; it has it's meaning(!) and it's disabled
+          // by default only beacuse people tend to misuse it
+          "Object": false,
+        },
+        "extendDefaults": true
+      }
+    ]
   },
 }

+ 37 - 39
query-node/mappings/bootstrap/index.ts

@@ -1,11 +1,11 @@
 import { createDBConnection } from '@dzlzv/hydra-processor/lib/db'
 import { DatabaseManager, makeDatabaseManager } from '@dzlzv/hydra-db-utils'
-import { Connection, getManager } from 'typeorm'
+import { Connection, getManager, FindConditions } from 'typeorm'
 
-import { bootMembers, IBootstrapMember } from './members';
-import { bootWorkers, IBootstrapWorker, IBootstrapWorkers } from './workers';
+import { bootMembers, IBootstrapMember } from './members'
+import { bootWorkers, IBootstrapWorker, IBootstrapWorkers } from './workers'
 import { Worker, WorkerType } from 'query-node'
-import { FindConditions } from 'typeorm'
+
 import fs from 'fs'
 import path from 'path'
 
@@ -14,58 +14,56 @@ init()
 
 // bootstrap flow
 async function init() {
-    // prepare database and import data
-    const [databaseManager, connection] = await createDatabaseManager()
+  // prepare database and import data
+  const [databaseManager, connection] = await createDatabaseManager()
 
-    // escape if db is already initialized
-    if (await isDbInitialized(databaseManager)) {
-        await connection.close()
-        return
-    }
+  // escape if db is already initialized
+  if (await isDbInitialized(databaseManager)) {
+    await connection.close()
+    return
+  }
 
-    // load import data
-    const data = loadData()
+  // load import data
+  const data = loadData()
 
-    // bootstrap entities
-    await bootMembers(databaseManager, data.members)
-    await bootWorkers(databaseManager, data.workers)
+  // bootstrap entities
+  await bootMembers(databaseManager, data.members)
+  await bootWorkers(databaseManager, data.workers)
 
-    await connection.close()
+  await connection.close()
 }
 
 async function isDbInitialized(db: DatabaseManager): Promise<boolean> {
-    // simple way to check if db is bootstrapped already - check if there is at least 1 storage provider
-    const membership = await db.get(Worker, {
-        where: {
-          type: WorkerType.STORAGE,
-        } as FindConditions<Worker>
-    })
+  // simple way to check if db is bootstrapped already - check if there is at least 1 storage provider
+  const membership = await db.get(Worker, {
+    where: {
+      type: WorkerType.STORAGE,
+    } as FindConditions<Worker>,
+  })
 
-    return !!membership
+  return !!membership
 }
 
 async function createDatabaseManager(): Promise<[DatabaseManager, Connection]> {
-    // paths in `entities` should be the same as `entities` set in `manifest.yml`
-    const entities = [
-        'generated/graphql-server/dist/**/*.model.js'
-    ]
+  // paths in `entities` should be the same as `entities` set in `manifest.yml`
+  const entities = ['generated/graphql-server/dist/**/*.model.js']
 
-    // connect to db and create manager
-    const connection = await createDBConnection(entities)
-    const entityManager = getManager(connection.name)
-    const databaseManager = makeDatabaseManager(entityManager)
+  // connect to db and create manager
+  const connection = await createDBConnection(entities)
+  const entityManager = getManager(connection.name)
+  const databaseManager = makeDatabaseManager(entityManager)
 
-    return [databaseManager, connection]
+  return [databaseManager, connection]
 }
 
 interface IBootstrapData {
-    members: IBootstrapMember[]
-    workers: IBootstrapWorkers
+  members: IBootstrapMember[]
+  workers: IBootstrapWorkers
 }
 
 function loadData(): IBootstrapData {
-    return {
-        members: JSON.parse(fs.readFileSync(process.env.BOOTSTRAP_DATA_FOLDER + '/members.json').toString()),
-        workers: JSON.parse(fs.readFileSync(process.env.BOOTSTRAP_DATA_FOLDER + '/workers.json').toString()),
-    }
+  return {
+    members: JSON.parse(fs.readFileSync(process.env.BOOTSTRAP_DATA_FOLDER + '/members.json').toString()),
+    workers: JSON.parse(fs.readFileSync(process.env.BOOTSTRAP_DATA_FOLDER + '/workers.json').toString()),
+  }
 }

+ 9 - 11
query-node/mappings/bootstrap/members.ts

@@ -1,21 +1,19 @@
-//import { Connection } from 'typeorm'
+// import { Connection } from 'typeorm'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
-import {
-  logger,
-} from '../src/common'
+import { logger } from '../src/common'
 import { MembershipEntryMethod, Membership } from 'query-node'
 
 export interface IBootstrapMember {
   member_id: number
-  root_account: string,
-  controller_account: string,
-  handle: string,
-  avatar_uri: string,
-  about: string,
+  root_account: string
+  controller_account: string
+  handle: string
+  avatar_uri: string
+  about: string
   registered_at_time: number
 }
 
-//export async function bootMembers(members: IBootstrapMember[], db: Connection): Promise<void> {
+// export async function bootMembers(members: IBootstrapMember[], db: Connection): Promise<void> {
 export async function bootMembers(db: DatabaseManager, members: IBootstrapMember[]): Promise<void> {
   for (const rawMember of members) {
     // create new membership
@@ -39,6 +37,6 @@ export async function bootMembers(db: DatabaseManager, members: IBootstrapMember
     await db.save<Membership>(member)
 
     // emit log event
-    logger.info('Member has been bootstrapped', {id: rawMember.member_id})
+    logger.info('Member has been bootstrapped', { id: rawMember.member_id })
   }
 }

+ 6 - 2
query-node/mappings/bootstrap/workers.ts

@@ -17,7 +17,11 @@ export async function bootWorkers(db: DatabaseManager, workers: IBootstrapWorker
   await bootWorkersInGroup(db, workers.gateway, WorkerType.GATEWAY)
 }
 
-export async function bootWorkersInGroup(db: DatabaseManager, workers: IBootstrapWorker[], workerType: WorkerType): Promise<void> {
+export async function bootWorkersInGroup(
+  db: DatabaseManager,
+  workers: IBootstrapWorker[],
+  workerType: WorkerType
+): Promise<void> {
   if (!workers) {
     return
   }
@@ -39,6 +43,6 @@ export async function bootWorkersInGroup(db: DatabaseManager, workers: IBootstra
     await db.save<Worker>(worker)
 
     // emit log event
-    logger.info('Worker has been bootstrapped', {id: rawWorker.id, workerType})
+    logger.info('Worker has been bootstrapped', { id: rawWorker.id, workerType })
   }
 }

+ 30 - 36
query-node/mappings/src/common.ts

@@ -1,20 +1,11 @@
-import { SubstrateEvent } from '@dzlzv/hydra-common'
+import { SubstrateEvent, SubstrateExtrinsic, ExtrinsicArg } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
 import { u64 } from '@polkadot/types/primitive'
 import { fixBlockTimestamp } from './eventFix'
-import { SubstrateExtrinsic, ExtrinsicArg } from '@dzlzv/hydra-common'
 
 // Asset
-import {
-  DataObjectOwner,
-  DataObject,
-  LiaisonJudgement,
-  Network,
-  NextEntityId,
-} from 'query-node'
-import {
-  ContentParameters,
-} from '@joystream/types/augment'
+import { DataObjectOwner, DataObject, LiaisonJudgement, Network, NextEntityId } from 'query-node'
+import { ContentParameters } from '@joystream/types/augment'
 
 import { ContentParameters as Custom_ContentParameters } from '@joystream/types/storage'
 import { registry } from '@joystream/types'
@@ -30,7 +21,7 @@ export function inconsistentState(extraInfo: string, data?: unknown): never {
   // log error
   logger.error(errorMessage, data)
 
-  throw errorMessage
+  throw new Error(errorMessage)
 }
 
 /*
@@ -48,7 +39,7 @@ export function invalidMetadata(extraInfo: string, data?: unknown): void {
 */
 export async function createPredictableId(db: DatabaseManager): Promise<string> {
   // load or create record
-  const existingRecord = await db.get(NextEntityId, {}) || new NextEntityId({id: '0', nextId: 0})
+  const existingRecord = (await db.get(NextEntityId, {})) || new NextEntityId({ id: '0', nextId: 0 })
 
   // remember id
   const entityId = existingRecord.nextId
@@ -69,7 +60,7 @@ export async function prepareDataObject(
   db: DatabaseManager,
   contentParameters: ContentParameters,
   event: SubstrateEvent,
-  owner: typeof DataObjectOwner,
+  owner: typeof DataObjectOwner
 ): Promise<DataObject> {
   // convert generic content parameters coming from processor to custom Joystream data type
   const customContentParameters = new Custom_ContentParameters(registry, contentParameters.toJSON() as any)
@@ -94,7 +85,7 @@ export async function prepareDataObject(
   return dataObject
 }
 
-/////////////////// Sudo extrinsic calls ///////////////////////////////////////
+/// ///////////////// Sudo extrinsic calls ///////////////////////////////////////
 
 // soft-peg interface for typegen-generated `*Call` types
 export interface IGenericExtrinsicObject<T> {
@@ -118,16 +109,18 @@ export function extractExtrinsicArgs<DataParams, EventObject extends IGenericExt
 
   // in ideal world this parameter would not be needed, but there is no way to associate parameters
   // used in sudo to extrinsic parameters without it
-  argsIndeces: Record<keyof DataParams, number>,
-): EventObject['args'] { // this is equal to DataParams but only this notation works properly
+  argsIndeces: Record<keyof DataParams, number>
+): EventObject['args'] {
+  // this is equal to DataParams but only this notation works properly
   // escape when extrinsic info is not available
   if (!rawEvent.extrinsic) {
-    throw 'Invalid event - no extrinsic set' // this should never happen
+    throw new Error('Invalid event - no extrinsic set') // this should never happen
   }
 
   // regural extrinsic call?
-  if (rawEvent.extrinsic.section != 'sudo') {
-    return (new callFactory(rawEvent)).args
+  if (rawEvent.extrinsic.section !== 'sudo') {
+    // eslint-disable-next-line new-cap
+    return new callFactory(rawEvent).args
   }
 
   // sudo extrinsic call
@@ -136,7 +129,7 @@ export function extractExtrinsicArgs<DataParams, EventObject extends IGenericExt
 
   // convert naming convention (underscore_names to camelCase)
   const clearArgs = Object.keys(callArgs.args).reduce((acc, key) => {
-    const formattedName = key.replace(/_([a-z])/g, tmp => tmp[1].toUpperCase())
+    const formattedName = key.replace(/_([a-z])/g, (tmp) => tmp[1].toUpperCase())
 
     acc[formattedName] = callArgs.args[key]
 
@@ -145,19 +138,20 @@ export function extractExtrinsicArgs<DataParams, EventObject extends IGenericExt
 
   // prepare partial event object
   const partialEvent = {
-    extrinsic: {
+    extrinsic: ({
       args: Object.keys(argsIndeces).reduce((acc, key) => {
-        acc[(argsIndeces)[key]] = {
-          value: clearArgs[key]
+        acc[argsIndeces[key]] = {
+          value: clearArgs[key],
         }
 
         return acc
       }, [] as unknown[]),
-    } as unknown as SubstrateExtrinsic
+    } as unknown) as SubstrateExtrinsic,
   } as SubstrateEvent
 
   // create event object and extract processed args
-  const finalArgs = (new callFactory(partialEvent)).args
+  // eslint-disable-next-line new-cap
+  const finalArgs = new callFactory(partialEvent).args
 
   return finalArgs
 }
@@ -167,28 +161,29 @@ export function extractExtrinsicArgs<DataParams, EventObject extends IGenericExt
 */
 export function extractSudoCallParameters<DataParams>(rawEvent: SubstrateEvent): ISudoCallArgs<DataParams> {
   if (!rawEvent.extrinsic) {
-    throw 'Invalid event - no extrinsic set' // this should never happen
+    throw new Error('Invalid event - no extrinsic set') // this should never happen
   }
 
   // see Substrate's sudo frame for more info about sudo extrinsics and `call` argument index
-  const argIndex = false
-    || (rawEvent.extrinsic.method == 'sudoAs' && 1) // who, *call*
-    || (rawEvent.extrinsic.method == 'sudo' && 0) // *call*
-    || (rawEvent.extrinsic.method == 'sudoUncheckedWeight' && 0) // *call*, _weight
+  const argIndex =
+    false ||
+    (rawEvent.extrinsic.method === 'sudoAs' && 1) || // who, *call*
+    (rawEvent.extrinsic.method === 'sudo' && 0) || // *call*
+    (rawEvent.extrinsic.method === 'sudoUncheckedWeight' && 0) // *call*, _weight
 
   // ensure `call` argument was found
   if (argIndex === false) {
     // this could possibly happen in sometime in future if new sudo options are introduced in Substrate
-    throw 'Not implemented situation with sudo'
+    throw new Error('Not implemented situation with sudo')
   }
 
   // typecast call arguments
-  const callArgs = rawEvent.extrinsic.args[argIndex].value as unknown as ISudoCallArgs<DataParams>
+  const callArgs = (rawEvent.extrinsic.args[argIndex].value as unknown) as ISudoCallArgs<DataParams>
 
   return callArgs
 }
 
-/////////////////// Logger /////////////////////////////////////////////////////
+/// ///////////////// Logger /////////////////////////////////////////////////////
 
 /*
   Simple logger enabling error and informational reporting.
@@ -197,7 +192,6 @@ export function extractSudoCallParameters<DataParams>(rawEvent: SubstrateEvent):
   Hydra will provide logger instance and relevant code using `Logger` should be refactored.
 */
 class Logger {
-
   /*
     Log significant event.
   */

+ 72 - 114
query-node/mappings/src/content/channel.ts

@@ -1,11 +1,11 @@
 import { fixBlockTimestamp } from '../eventFix'
 import { SubstrateEvent } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
-import ISO6391 from 'iso-639-1';
+import ISO6391 from 'iso-639-1'
 import { FindConditions, In } from 'typeorm'
 
-import { AccountId } from "@polkadot/types/interfaces";
-import { Option } from '@polkadot/types/codec';
+import { AccountId } from '@polkadot/types/interfaces'
+import { Option } from '@polkadot/types/codec'
 import { Content } from '../../../generated/types'
 import {
   readProtobuf,
@@ -14,36 +14,22 @@ import {
   convertContentActorToDataObjectOwner,
 } from './utils'
 
-import {
-  Channel,
-  ChannelCategory,
-  DataObject,
-} from 'query-node'
-import {
-  inconsistentState,
-  logger,
-} from '../common'
-
-import {
-  AssetAvailability,
-} from 'query-node'
+import { Channel, ChannelCategory, DataObject, AssetAvailability } from 'query-node'
+import { inconsistentState, logger } from '../common'
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function content_ChannelCreated(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {channelId, channelCreationParameters, contentActor} = new Content.ChannelCreatedEvent(event).data
+  const { channelId, channelCreationParameters, contentActor } = new Content.ChannelCreatedEvent(event).data
 
   // read metadata
-  const protobufContent = await readProtobufWithAssets(
-    new Channel(),
-    {
-      metadata: channelCreationParameters.meta,
-      db,
-      event,
-      assets: channelCreationParameters.assets,
-      contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
-    }
-  )
+  const protobufContent = await readProtobufWithAssets(new Channel(), {
+    metadata: channelCreationParameters.meta,
+    db,
+    event,
+    assets: channelCreationParameters.assets,
+    contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
+  })
 
   // create entity
   const channel = new Channel({
@@ -64,30 +50,23 @@ export async function content_ChannelCreated(db: DatabaseManager, event: Substra
     updatedAt: new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
 
     // prepare channel owner (handles fields `ownerMember` and `ownerCuratorGroup`)
-    ...await convertContentActorToChannelOwner(db, contentActor),
+    ...(await convertContentActorToChannelOwner(db, contentActor)),
 
     // integrate metadata
-    ...protobufContent
+    ...protobufContent,
   })
 
   // save entity
   await db.save<Channel>(channel)
 
   // emit log event
-  logger.info('Channel has been created', {id: channel.id})
+  logger.info('Channel has been created', { id: channel.id })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_ChannelUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    channelId,
-    channelUpdateParameters,
-    contentActor,
-  } = new Content.ChannelUpdatedEvent(event).data
+  const { channelId, channelUpdateParameters, contentActor } = new Content.ChannelUpdatedEvent(event).data
 
   // load channel
   const channel = await db.get(Channel, { where: { id: channelId.toString() } as FindConditions<Channel> })
@@ -102,19 +81,16 @@ export async function content_ChannelUpdated(
 
   //  update metadata if it was changed
   if (newMetadata) {
-    const protobufContent = await readProtobufWithAssets(
-      new Channel(),
-      {
-        metadata: newMetadata,
-        db,
-        event,
-        assets: channelUpdateParameters.assets.unwrapOr([]),
-        contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
-      }
-    )
+    const protobufContent = await readProtobufWithAssets(new Channel(), {
+      metadata: newMetadata,
+      db,
+      event,
+      assets: channelUpdateParameters.assets.unwrapOr([]),
+      contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
+    })
 
     // update all fields read from protobuf
-    for (let [key, value] of Object.entries(protobufContent)) {
+    for (const [key, value] of Object.entries(protobufContent)) {
       channel[key] = value
     }
   }
@@ -135,20 +111,19 @@ export async function content_ChannelUpdated(
   await db.save<Channel>(channel)
 
   // emit log event
-  logger.info('Channel has been updated', {id: channel.id})
+  logger.info('Channel has been updated', { id: channel.id })
 }
 
-export async function content_ChannelAssetsRemoved(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelAssetsRemoved(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {contentId: contentIds} = new Content.ChannelAssetsRemovedEvent(event).data
+  const { contentId: contentIds } = new Content.ChannelAssetsRemovedEvent(event).data
 
   // load channel
-  const assets = await db.getMany(DataObject, { where: {
-    id: In(contentIds.toArray().map(item => item.toString()))
-  } as FindConditions<DataObject>})
+  const assets = await db.getMany(DataObject, {
+    where: {
+      id: In(contentIds.toArray().map((item) => item.toString())),
+    } as FindConditions<DataObject>,
+  })
 
   // delete assets
   for (const asset of assets) {
@@ -156,16 +131,13 @@ export async function content_ChannelAssetsRemoved(
   }
 
   // emit log event
-  logger.info('Channel assets have been removed', {ids: contentIds})
+  logger.info('Channel assets have been removed', { ids: contentIds })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_ChannelCensorshipStatusUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelCensorshipStatusUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {channelId, isCensored} = new Content.ChannelCensorshipStatusUpdatedEvent(event).data
+  const { channelId, isCensored } = new Content.ChannelCensorshipStatusUpdatedEvent(event).data
 
   // load event
   const channel = await db.get(Channel, { where: { id: channelId.toString() } as FindConditions<Channel> })
@@ -176,7 +148,7 @@ export async function content_ChannelCensorshipStatusUpdated(
   }
 
   // update channel
-  channel.isCensored = isCensored.isTrue;
+  channel.isCensored = isCensored.isTrue
 
   // set last update time
   channel.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
@@ -185,28 +157,22 @@ export async function content_ChannelCensorshipStatusUpdated(
   await db.save<Channel>(channel)
 
   // emit log event
-  logger.info('Channel censorship status has been updated', {id: channelId, isCensored: isCensored.isTrue})
+  logger.info('Channel censorship status has been updated', { id: channelId, isCensored: isCensored.isTrue })
 }
 
-/////////////////// ChannelCategory ////////////////////////////////////////////
+/// ///////////////// ChannelCategory ////////////////////////////////////////////
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_ChannelCategoryCreated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelCategoryCreated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {channelCategoryCreationParameters, channelCategoryId} = new Content.ChannelCategoryCreatedEvent(event).data
+  const { channelCategoryCreationParameters, channelCategoryId } = new Content.ChannelCategoryCreatedEvent(event).data
 
   // read metadata
-  const protobufContent = await readProtobuf(
-    new ChannelCategory(),
-    {
-      metadata: channelCategoryCreationParameters.meta,
-      db,
-      event,
-    }
-  )
+  const protobufContent = await readProtobuf(new ChannelCategory(), {
+    metadata: channelCategoryCreationParameters.meta,
+    db,
+    event,
+  })
 
   // create new channel category
   const channelCategory = new ChannelCategory({
@@ -220,31 +186,27 @@ export async function content_ChannelCategoryCreated(
     updatedAt: new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
 
     // integrate metadata
-    ...protobufContent
+    ...protobufContent,
   })
 
   // save channel
   await db.save<ChannelCategory>(channelCategory)
 
   // emit log event
-  logger.info('Channel category has been created', {id: channelCategory.id})
+  logger.info('Channel category has been created', { id: channelCategory.id })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_ChannelCategoryUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelCategoryUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    channelCategoryId,
-    channelCategoryUpdateParameters,
-  } = new Content.ChannelCategoryUpdatedEvent(event).data
+  const { channelCategoryId, channelCategoryUpdateParameters } = new Content.ChannelCategoryUpdatedEvent(event).data
 
   // load channel category
-  const channelCategory = await db.get(ChannelCategory, { where: {
-    id: channelCategoryId.toString()
-  } as FindConditions<ChannelCategory> })
+  const channelCategory = await db.get(ChannelCategory, {
+    where: {
+      id: channelCategoryId.toString(),
+    } as FindConditions<ChannelCategory>,
+  })
 
   // ensure channel exists
   if (!channelCategory) {
@@ -252,17 +214,14 @@ export async function content_ChannelCategoryUpdated(
   }
 
   // read metadata
-  const protobufContent = await readProtobuf(
-    new ChannelCategory(),
-    {
-      metadata: channelCategoryUpdateParameters.new_meta,
-      db,
-      event,
-    }
-  )
+  const protobufContent = await readProtobuf(new ChannelCategory(), {
+    metadata: channelCategoryUpdateParameters.new_meta,
+    db,
+    event,
+  })
 
   // update all fields read from protobuf
-  for (let [key, value] of Object.entries(protobufContent)) {
+  for (const [key, value] of Object.entries(protobufContent)) {
     channelCategory[key] = value
   }
 
@@ -273,21 +232,20 @@ export async function content_ChannelCategoryUpdated(
   await db.save<ChannelCategory>(channelCategory)
 
   // emit log event
-  logger.info('Channel category has been updated', {id: channelCategory.id})
+  logger.info('Channel category has been updated', { id: channelCategory.id })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_ChannelCategoryDeleted(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_ChannelCategoryDeleted(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {channelCategoryId} = new Content.ChannelCategoryDeletedEvent(event).data
+  const { channelCategoryId } = new Content.ChannelCategoryDeletedEvent(event).data
 
   // load channel category
-  const channelCategory = await db.get(ChannelCategory, { where: {
-    id: channelCategoryId.toString()
-  } as FindConditions<ChannelCategory> })
+  const channelCategory = await db.get(ChannelCategory, {
+    where: {
+      id: channelCategoryId.toString(),
+    } as FindConditions<ChannelCategory>,
+  })
 
   // ensure channel category exists
   if (!channelCategory) {
@@ -298,10 +256,10 @@ export async function content_ChannelCategoryDeleted(
   await db.remove<ChannelCategory>(channelCategory)
 
   // emit log event
-  logger.info('Channel category has been deleted', {id: channelCategory.id})
+  logger.info('Channel category has been deleted', { id: channelCategory.id })
 }
 
-/////////////////// Helpers ////////////////////////////////////////////////////
+/// ///////////////// Helpers ////////////////////////////////////////////////////
 
 function handleChannelRewardAccountChange(
   channel: Channel, // will be modified inside of the function!

+ 23 - 32
query-node/mappings/src/content/curatorGroup.ts

@@ -6,17 +6,11 @@ import { FindConditions } from 'typeorm'
 import { CuratorGroup } from 'query-node'
 import { Content } from '../../../generated/types'
 
-import {
-  inconsistentState,
-  logger,
-} from '../common'
-
-export async function content_CuratorGroupCreated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+import { inconsistentState, logger } from '../common'
+
+export async function content_CuratorGroupCreated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {curatorGroupId} = new Content.CuratorGroupCreatedEvent(event).data
+  const { curatorGroupId } = new Content.CuratorGroupCreatedEvent(event).data
 
   // create new curator group
   const curatorGroup = new CuratorGroup({
@@ -34,18 +28,17 @@ export async function content_CuratorGroupCreated(
   await db.save<CuratorGroup>(curatorGroup)
 
   // emit log event
-  logger.info('Curator group has been created', {id: curatorGroupId})
+  logger.info('Curator group has been created', { id: curatorGroupId })
 }
 
-export async function content_CuratorGroupStatusSet(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_CuratorGroupStatusSet(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {curatorGroupId, bool: isActive} = new Content.CuratorGroupStatusSetEvent(event).data
+  const { curatorGroupId, bool: isActive } = new Content.CuratorGroupStatusSetEvent(event).data
 
   // load curator group
-  const curatorGroup = await db.get(CuratorGroup, { where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>})
+  const curatorGroup = await db.get(CuratorGroup, {
+    where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>,
+  })
 
   // ensure curator group exists
   if (!curatorGroup) {
@@ -62,18 +55,17 @@ export async function content_CuratorGroupStatusSet(
   await db.save<CuratorGroup>(curatorGroup)
 
   // emit log event
-  logger.info('Curator group status has been set', {id: curatorGroupId, isActive})
+  logger.info('Curator group status has been set', { id: curatorGroupId, isActive })
 }
 
-export async function content_CuratorAdded(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_CuratorAdded(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {curatorGroupId, curatorId} = new Content.CuratorAddedEvent(event).data
+  const { curatorGroupId, curatorId } = new Content.CuratorAddedEvent(event).data
 
   // load curator group
-  const curatorGroup = await db.get(CuratorGroup, { where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>})
+  const curatorGroup = await db.get(CuratorGroup, {
+    where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>,
+  })
 
   // ensure curator group exists
   if (!curatorGroup) {
@@ -90,18 +82,17 @@ export async function content_CuratorAdded(
   await db.save<CuratorGroup>(curatorGroup)
 
   // emit log event
-  logger.info('Curator has been added to curator group', {id: curatorGroupId, curatorId})
+  logger.info('Curator has been added to curator group', { id: curatorGroupId, curatorId })
 }
 
-export async function content_CuratorRemoved(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_CuratorRemoved(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {curatorGroupId, curatorId} = new Content.CuratorAddedEvent(event).data
+  const { curatorGroupId, curatorId } = new Content.CuratorAddedEvent(event).data
 
   // load curator group
-  const curatorGroup = await db.get(CuratorGroup, { where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>})
+  const curatorGroup = await db.get(CuratorGroup, {
+    where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>,
+  })
 
   // ensure curator group exists
   if (!curatorGroup) {
@@ -122,5 +113,5 @@ export async function content_CuratorRemoved(
   await db.save<CuratorGroup>(curatorGroup)
 
   // emit log event
-  logger.info('Curator has been removed from curator group', {id: curatorGroupId, curatorId})
+  logger.info('Curator has been removed from curator group', { id: curatorGroupId, curatorId })
 }

+ 92 - 86
query-node/mappings/src/content/utils.ts

@@ -12,7 +12,7 @@ import { Bytes } from '@polkadot/types'
 import ISO6391 from 'iso-639-1'
 import { u64 } from '@polkadot/types/primitive'
 import { FindConditions } from 'typeorm'
-import * as jspb from "google-protobuf"
+import * as jspb from 'google-protobuf'
 import { fixBlockTimestamp } from '../eventFix'
 
 // protobuf definitions
@@ -26,18 +26,9 @@ import {
   VideoCategoryMetadata,
 } from '@joystream/content-metadata-protobuf'
 
-import {
-  Content,
-} from '../../../generated/types'
-
-import {
-  invalidMetadata,
-  inconsistentState,
-  logger,
-  prepareDataObject,
-  createPredictableId,
-} from '../common'
+import { Content } from '../../../generated/types'
 
+import { invalidMetadata, inconsistentState, logger, prepareDataObject, createPredictableId } from '../common'
 
 import {
   // primary entities
@@ -60,17 +51,11 @@ import {
   DataObject,
   LiaisonJudgement,
   AssetAvailability,
-
   Membership,
 } from 'query-node'
 
 // Joystream types
-import {
-  ChannelId,
-  ContentParameters,
-  NewAsset,
-  ContentActor,
-} from '@joystream/types/augment'
+import { ChannelId, ContentParameters, NewAsset, ContentActor } from '@joystream/types/augment'
 
 import { ContentParameters as Custom_ContentParameters } from '@joystream/types/storage'
 import { registry } from '@joystream/types'
@@ -109,7 +94,6 @@ export interface IReadProtobufArgumentsWithAssets extends IReadProtobufArguments
   Change - set the new value
 */
 export class PropertyChange<T> {
-
   static newUnset<T>(): PropertyChange<T> {
     return new PropertyChange<T>('unset')
   }
@@ -125,11 +109,10 @@ export class PropertyChange<T> {
   /*
     Determines property change from the given object property.
   */
-  static fromObjectProperty<
-    T,
-    Key extends string,
-    ChangedObject extends {[key in Key]?: T}
-  >(object: ChangedObject, key: Key): PropertyChange<T> {
+  static fromObjectProperty<T, Key extends string, ChangedObject extends { [key in Key]?: T }>(
+    object: ChangedObject,
+    key: Key
+  ): PropertyChange<T> {
     if (!(key in object)) {
       return PropertyChange.newNoChange<T>()
     }
@@ -150,21 +133,19 @@ export class PropertyChange<T> {
   }
 
   public isUnset(): boolean {
-    return this.type == 'unset'
+    return this.type === 'unset'
   }
 
   public isNoChange(): boolean {
-    return this.type == 'nochange'
+    return this.type === 'nochange'
   }
 
   public isValue(): boolean {
-    return this.type == 'change'
+    return this.type === 'change'
   }
 
   public getValue(): T | undefined {
-    return this.type == 'change'
-      ? this.value
-      : undefined
+    return this.type === 'change' ? this.value : undefined
   }
 
   /*
@@ -200,7 +181,7 @@ export interface RawVideoMetadata {
 */
 export async function readProtobuf<T extends ChannelCategory | VideoCategory>(
   type: T,
-  parameters: IReadProtobufArguments,
+  parameters: IReadProtobufArguments
 ): Promise<Partial<T>> {
   // true option here is crucial, it indicates that we want just the underlying bytes (by default it will also include bytes encoding the length)
   const metaU8a = parameters.metadata.toU8a(true)
@@ -222,8 +203,8 @@ export async function readProtobuf<T extends ChannelCategory | VideoCategory>(
   }
 
   // this should never happen
-  logger.error('Not implemented metadata type', {type})
-  throw `Not implemented metadata type`
+  logger.error('Not implemented metadata type', { type })
+  throw new Error(`Not implemented metadata type`)
 }
 
 /*
@@ -233,7 +214,7 @@ export async function readProtobuf<T extends ChannelCategory | VideoCategory>(
 
 export async function readProtobufWithAssets<T extends Channel | Video>(
   type: T,
-  parameters: IReadProtobufArgumentsWithAssets,
+  parameters: IReadProtobufArgumentsWithAssets
 ): Promise<Partial<T>> {
   // true option here is crucial, it indicates that we want just the underlying bytes (by default it will also include bytes encoding the length)
   const metaU8a = parameters.metadata.toU8a(true)
@@ -242,7 +223,7 @@ export async function readProtobufWithAssets<T extends Channel | Video>(
   if (type instanceof Channel) {
     const meta = ChannelMetadata.deserializeBinary(metaU8a)
     const metaAsObject = convertMetadataToObject<ChannelMetadata.AsObject>(meta)
-    const result = metaAsObject as any as Partial<Channel>
+    const result = (metaAsObject as any) as Partial<Channel>
 
     // prepare cover photo asset if needed
     if ('coverPhoto' in metaAsObject) {
@@ -284,7 +265,7 @@ export async function readProtobufWithAssets<T extends Channel | Video>(
   if (type instanceof Video) {
     const meta = VideoMetadata.deserializeBinary(metaU8a)
     const metaAsObject = convertMetadataToObject<VideoMetadata.AsObject>(meta)
-    const result = metaAsObject as any as Partial<Video>
+    const result = (metaAsObject as any) as Partial<Video>
 
     // prepare video category if needed
     if ('category' in metaAsObject) {
@@ -300,11 +281,11 @@ export async function readProtobufWithAssets<T extends Channel | Video>(
 
       // NOTE: type hack - `RawVideoMetadata` is inserted instead of VideoMediaMetadata - it should be edited in `video.ts`
       //       see `integrateVideoMetadata()` in `video.ts` for more info
-      result.mediaMetadata = prepareVideoMetadata(
+      result.mediaMetadata = (prepareVideoMetadata(
         metaAsObject,
         videoSize,
-        parameters.event.blockNumber,
-      ) as unknown as VideoMediaMetadata
+        parameters.event.blockNumber
+      ) as unknown) as VideoMediaMetadata
 
       // remove extra values
       delete metaAsObject.mediaType
@@ -345,11 +326,7 @@ export async function readProtobufWithAssets<T extends Channel | Video>(
 
     // prepare language if needed
     if ('language' in metaAsObject) {
-      const language = await prepareLanguage(
-        metaAsObject.language,
-        parameters.db,
-        parameters.event,
-      )
+      const language = await prepareLanguage(metaAsObject.language, parameters.db, parameters.event)
       delete metaAsObject.language // make sure temporary value will not interfere
       language.integrateInto(result, 'language')
     }
@@ -364,13 +341,16 @@ export async function readProtobufWithAssets<T extends Channel | Video>(
   }
 
   // this should never happen
-  logger.error('Not implemented metadata type', {type})
-  throw `Not implemented metadata type`
+  logger.error('Not implemented metadata type', { type })
+  throw new Error(`Not implemented metadata type`)
 }
 
-export async function convertContentActorToChannelOwner(db: DatabaseManager, contentActor: ContentActor): Promise<{
-  ownerMember?: Membership,
-  ownerCuratorGroup?: CuratorGroup,
+export async function convertContentActorToChannelOwner(
+  db: DatabaseManager,
+  contentActor: ContentActor
+): Promise<{
+  ownerMember?: Membership
+  ownerCuratorGroup?: CuratorGroup
 }> {
   if (contentActor.isMember) {
     const memberId = contentActor.asMember.toNumber()
@@ -389,7 +369,9 @@ export async function convertContentActorToChannelOwner(db: DatabaseManager, con
 
   if (contentActor.isCurator) {
     const curatorGroupId = contentActor.asCurator[0].toNumber()
-    const curatorGroup = await db.get(CuratorGroup, { where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup> })
+    const curatorGroup = await db.get(CuratorGroup, {
+      where: { id: curatorGroupId.toString() } as FindConditions<CuratorGroup>,
+    })
 
     // ensure curator group exists
     if (!curatorGroup) {
@@ -404,11 +386,14 @@ export async function convertContentActorToChannelOwner(db: DatabaseManager, con
 
   // TODO: contentActor.isLead
 
-  logger.error('Not implemented ContentActor type', {contentActor: contentActor.toString()})
-  throw 'Not-implemented ContentActor type used'
+  logger.error('Not implemented ContentActor type', { contentActor: contentActor.toString() })
+  throw new Error('Not-implemented ContentActor type used')
 }
 
-export function convertContentActorToDataObjectOwner(contentActor: ContentActor, channelId: number): typeof DataObjectOwner {
+export function convertContentActorToDataObjectOwner(
+  contentActor: ContentActor,
+  channelId: number
+): typeof DataObjectOwner {
   const owner = new DataObjectOwnerChannel()
   owner.channel = channelId
 
@@ -430,25 +415,26 @@ export function convertContentActorToDataObjectOwner(contentActor: ContentActor,
   }
 
   logger.error('Not implemented ContentActor type', {contentActor: contentActor.toString()})
-  throw 'Not-implemented ContentActor type used'
+  throw new Error('Not-implemented ContentActor type used')
   */
 }
 
-function handlePublishedBeforeJoystream(video: Partial<Video>, metadata: PublishedBeforeJoystreamMetadata.AsObject): PropertyChange<Date> {
+function handlePublishedBeforeJoystream(
+  video: Partial<Video>,
+  metadata: PublishedBeforeJoystreamMetadata.AsObject
+): PropertyChange<Date> {
   // is publish being unset
   if ('isPublished' in metadata && !metadata.isPublished) {
     return PropertyChange.newUnset()
   }
 
   // try to parse timestamp from publish date
-  const timestamp = metadata.date
-    ? Date.parse(metadata.date)
-    : NaN
+  const timestamp = metadata.date ? Date.parse(metadata.date) : NaN
 
   // ensure date is valid
   if (isNaN(timestamp)) {
     invalidMetadata(`Invalid date used for publishedBeforeJoystream`, {
-      timestamp
+      timestamp,
     })
     return PropertyChange.newNoChange()
   }
@@ -470,7 +456,7 @@ interface IConvertAssetParameters {
 async function convertAsset(parameters: IConvertAssetParameters): Promise<AssetStorageOrUrls> {
   // is asset describing list of URLs?
   if (parameters.rawAsset.isUrls) {
-    const urls = parameters.rawAsset.asUrls.toArray().map(item => item.toString())
+    const urls = parameters.rawAsset.asUrls.toArray().map((item) => item.toString())
 
     return urls
   }
@@ -483,7 +469,7 @@ async function convertAsset(parameters: IConvertAssetParameters): Promise<AssetS
     parameters.db,
     contentParameters,
     parameters.event,
-    parameters.contentOwner,
+    parameters.contentOwner
   )
 
   return dataObject
@@ -584,7 +570,7 @@ function extractVideoSize(assets: NewAsset[], assetIndex: number | undefined): n
 
   // ensure asset index is valid
   if (assetIndex > assets.length) {
-    invalidMetadata(`Non-existing asset video size extraction requested`, {assetsProvided: assets.length, assetIndex})
+    invalidMetadata(`Non-existing asset video size extraction requested`, { assetsProvided: assets.length, assetIndex })
     return undefined
   }
 
@@ -608,7 +594,7 @@ function extractVideoSize(assets: NewAsset[], assetIndex: number | undefined): n
 async function prepareLanguage(
   languageIso: string | undefined,
   db: DatabaseManager,
-  event: SubstrateEvent,
+  event: SubstrateEvent
 ): Promise<PropertyChange<Language>> {
   // is language being unset?
   if (languageIso === undefined) {
@@ -632,7 +618,6 @@ async function prepareLanguage(
     return PropertyChange.newChange(language)
   }
 
-
   // create new language
   const newLanguage = new Language({
     id: await createPredictableId(db),
@@ -655,7 +640,7 @@ async function prepareLanguage(
 async function prepareLicense(
   db: DatabaseManager,
   licenseProtobuf: LicenseMetadata.AsObject | undefined,
-  event: SubstrateEvent,
+  event: SubstrateEvent
 ): Promise<License | undefined> {
   // NOTE: Deletion of any previous license should take place in appropriate event handling function
   //       and not here even it might appear so.
@@ -690,39 +675,60 @@ async function prepareLicense(
   Empty object means deletion is requested.
 */
 function isLicenseEmpty(licenseObject: LicenseMetadata.AsObject): boolean {
-    let somePropertySet = Object.entries(licenseObject).reduce((acc, [key, value]) => {
-        return acc || value !== undefined
-    }, false)
+  const somePropertySet = Object.entries(licenseObject).reduce((acc, [key, value]) => {
+    return acc || value !== undefined
+  }, false)
 
-    return !somePropertySet
+  return !somePropertySet
 }
 
-
-function prepareVideoMetadata(videoProtobuf: VideoMetadata.AsObject, videoSize: number | undefined, blockNumber: number): RawVideoMetadata {
+function prepareVideoMetadata(
+  videoProtobuf: VideoMetadata.AsObject,
+  videoSize: number | undefined,
+  blockNumber: number
+): RawVideoMetadata {
   const rawMeta = {
     encoding: {
-      codecName: PropertyChange.fromObjectProperty<string, 'codecName', MediaTypeMetadata.AsObject>(videoProtobuf.mediaType || {}, 'codecName'),
-      container: PropertyChange.fromObjectProperty<string, 'container', MediaTypeMetadata.AsObject>(videoProtobuf.mediaType || {}, 'container'),
-      mimeMediaType: PropertyChange.fromObjectProperty<string, 'mimeMediaType', MediaTypeMetadata.AsObject>(videoProtobuf.mediaType || {}, 'mimeMediaType'),
+      codecName: PropertyChange.fromObjectProperty<string, 'codecName', MediaTypeMetadata.AsObject>(
+        videoProtobuf.mediaType || {},
+        'codecName'
+      ),
+      container: PropertyChange.fromObjectProperty<string, 'container', MediaTypeMetadata.AsObject>(
+        videoProtobuf.mediaType || {},
+        'container'
+      ),
+      mimeMediaType: PropertyChange.fromObjectProperty<string, 'mimeMediaType', MediaTypeMetadata.AsObject>(
+        videoProtobuf.mediaType || {},
+        'mimeMediaType'
+      ),
     },
-    pixelWidth: PropertyChange.fromObjectProperty<number, 'mediaPixelWidth', VideoMetadata.AsObject>(videoProtobuf, 'mediaPixelWidth'),
-    pixelHeight: PropertyChange.fromObjectProperty<number, 'mediaPixelHeight', VideoMetadata.AsObject>(videoProtobuf, 'mediaPixelHeight'),
-    size: videoSize === undefined
-      ? PropertyChange.newNoChange()
-      : PropertyChange.newChange(videoSize)
+    pixelWidth: PropertyChange.fromObjectProperty<number, 'mediaPixelWidth', VideoMetadata.AsObject>(
+      videoProtobuf,
+      'mediaPixelWidth'
+    ),
+    pixelHeight: PropertyChange.fromObjectProperty<number, 'mediaPixelHeight', VideoMetadata.AsObject>(
+      videoProtobuf,
+      'mediaPixelHeight'
+    ),
+    size: videoSize === undefined ? PropertyChange.newNoChange() : PropertyChange.newChange(videoSize),
   } as RawVideoMetadata
 
   return rawMeta
 }
 
-async function prepareVideoCategory(categoryId: number | undefined, db: DatabaseManager): Promise<PropertyChange<VideoCategory>> {
+async function prepareVideoCategory(
+  categoryId: number | undefined,
+  db: DatabaseManager
+): Promise<PropertyChange<VideoCategory>> {
   // is category being unset?
   if (categoryId === undefined) {
     return PropertyChange.newUnset()
   }
 
   // load video category
-  const category = await db.get(VideoCategory, { where: { id: categoryId.toString() } as FindConditions<VideoCategory> })
+  const category = await db.get(VideoCategory, {
+    where: { id: categoryId.toString() } as FindConditions<VideoCategory>,
+  })
 
   // ensure video category exists
   if (!category) {
@@ -740,15 +746,15 @@ function convertMetadataToObject<T extends Object>(metadata: jspb.Message): T {
   for (const key in metaAsObject) {
     const funcNameBase = key.charAt(0).toUpperCase() + key.slice(1)
     const hasFuncName = 'has' + funcNameBase
-    const isSet = funcNameBase == 'PersonsList' // there is no `VideoMetadata.hasPersonsList` method from unkown reason -> create exception
-      ? true
-      : metadata[hasFuncName]()
+    const isSet =
+      funcNameBase === 'PersonsList' // there is no `VideoMetadata.hasPersonsList` method from unkown reason -> create exception
+        ? true
+        : metadata[hasFuncName]()
 
     if (!isSet) {
       continue
     }
 
-
     const getFuncName = 'get' + funcNameBase
     const value = metadata[getFuncName]()
 

+ 137 - 190
query-node/mappings/src/content/video.ts

@@ -4,62 +4,38 @@ import { SubstrateEvent } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
 import { FindConditions, In } from 'typeorm'
 
-import {
-  Content,
-} from '../../../generated/types'
+import { Content } from '../../../generated/types'
 
-import {
-  inconsistentState,
-  logger,
-  createPredictableId,
-} from '../common'
+import { inconsistentState, logger, createPredictableId } from '../common'
 
-import {
-  convertContentActorToDataObjectOwner,
-  readProtobuf,
-  readProtobufWithAssets,
-  RawVideoMetadata,
-} from './utils'
+import { convertContentActorToDataObjectOwner, readProtobuf, readProtobufWithAssets, RawVideoMetadata } from './utils'
 
-// primary entities
 import {
   AssetAvailability,
   Channel,
+  License,
   Video,
   VideoCategory,
   VideoMediaEncoding,
   VideoMediaMetadata,
 } from 'query-node'
 
-// secondary entities
-import { License } from 'query-node'
-
 // Joystream types
-import {
-  ChannelId,
-} from '@joystream/types/augment'
+import { ChannelId } from '@joystream/types/augment'
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoCategoryCreated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoCategoryCreated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    videoCategoryId,
-    videoCategoryCreationParameters,
-    contentActor,
-  } = new Content.VideoCategoryCreatedEvent(event).data
+  const { videoCategoryId, videoCategoryCreationParameters, contentActor } = new Content.VideoCategoryCreatedEvent(
+    event
+  ).data
 
   // read metadata
-  const protobufContent = await readProtobuf(
-    new VideoCategory(),
-    {
-      metadata: videoCategoryCreationParameters.meta,
-      db,
-      event,
-    }
-  )
+  const protobufContent = await readProtobuf(new VideoCategory(), {
+    metadata: videoCategoryCreationParameters.meta,
+    db,
+    event,
+  })
 
   // create new video category
   const videoCategory = new VideoCategory({
@@ -73,30 +49,27 @@ export async function content_VideoCategoryCreated(
     updatedAt: new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
 
     // integrate metadata
-    ...protobufContent
+    ...protobufContent,
   })
 
   // save video category
   await db.save<VideoCategory>(videoCategory)
 
   // emit log event
-  logger.info('Video category has been created', {id: videoCategoryId})
+  logger.info('Video category has been created', { id: videoCategoryId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoCategoryUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoCategoryUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    videoCategoryId,
-    videoCategoryUpdateParameters,
-    contentActor,
-  } = new Content.VideoCategoryUpdatedEvent(event).data
+  const { videoCategoryId, videoCategoryUpdateParameters, contentActor } = new Content.VideoCategoryUpdatedEvent(
+    event
+  ).data
 
   // load video category
-  const videoCategory = await db.get(VideoCategory, { where: { id: videoCategoryId.toString() } as FindConditions<VideoCategory> })
+  const videoCategory = await db.get(VideoCategory, {
+    where: { id: videoCategoryId.toString() } as FindConditions<VideoCategory>,
+  })
 
   // ensure video category exists
   if (!videoCategory) {
@@ -104,17 +77,14 @@ export async function content_VideoCategoryUpdated(
   }
 
   // read metadata
-  const protobufContent = await readProtobuf(
-    new VideoCategory(),
-    {
-      metadata: videoCategoryUpdateParameters.new_meta,
-      db,
-      event,
-    }
-  )
+  const protobufContent = await readProtobuf(new VideoCategory(), {
+    metadata: videoCategoryUpdateParameters.new_meta,
+    db,
+    event,
+  })
 
   // update all fields read from protobuf
-  for (let [key, value] of Object.entries(protobufContent)) {
+  for (const [key, value] of Object.entries(protobufContent)) {
     videoCategory[key] = value
   }
 
@@ -125,19 +95,18 @@ export async function content_VideoCategoryUpdated(
   await db.save<VideoCategory>(videoCategory)
 
   // emit log event
-  logger.info('Video category has been updated', {id: videoCategoryId})
+  logger.info('Video category has been updated', { id: videoCategoryId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoCategoryDeleted(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoCategoryDeleted(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {videoCategoryId} = new Content.VideoCategoryDeletedEvent(event).data
+  const { videoCategoryId } = new Content.VideoCategoryDeletedEvent(event).data
 
   // load video category
-  const videoCategory = await db.get(VideoCategory, { where: { id: videoCategoryId.toString() } as FindConditions<VideoCategory> })
+  const videoCategory = await db.get(VideoCategory, {
+    where: { id: videoCategoryId.toString() } as FindConditions<VideoCategory>,
+  })
 
   // ensure video category exists
   if (!videoCategory) {
@@ -148,35 +117,24 @@ export async function content_VideoCategoryDeleted(
   await db.remove<VideoCategory>(videoCategory)
 
   // emit log event
-  logger.info('Video category has been deleted', {id: videoCategoryId})
+  logger.info('Video category has been deleted', { id: videoCategoryId })
 }
 
-/////////////////// Video //////////////////////////////////////////////////////
+/// ///////////////// Video //////////////////////////////////////////////////////
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoCreated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoCreated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    channelId,
-    videoId,
-    videoCreationParameters,
-    contentActor,
-  } = new Content.VideoCreatedEvent(event).data
+  const { channelId, videoId, videoCreationParameters, contentActor } = new Content.VideoCreatedEvent(event).data
 
   // read metadata
-  const protobufContent = await readProtobufWithAssets(
-    new Video(),
-    {
-      metadata: videoCreationParameters.meta,
-      db,
-      event,
-      assets: videoCreationParameters.assets,
-      contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
-    }
-  )
+  const protobufContent = await readProtobufWithAssets(new Video(), {
+    metadata: videoCreationParameters.meta,
+    db,
+    event,
+    assets: videoCreationParameters.assets,
+    contentOwner: convertContentActorToDataObjectOwner(contentActor, channelId.toNumber()),
+  })
 
   // load channel
   const channel = await db.get(Channel, { where: { id: channelId.toString() } as FindConditions<Channel> })
@@ -190,7 +148,8 @@ export async function content_VideoCreated(
   const fixedProtobuf = await integrateVideoMediaMetadata(db, null, protobufContent, event)
 
   const licenseIsEmpty = fixedProtobuf.license && !Object.keys(fixedProtobuf.license).length
-  if (licenseIsEmpty) { // license deletion was requested - ignore it and consider it empty
+  if (licenseIsEmpty) {
+    // license deletion was requested - ignore it and consider it empty
     delete fixedProtobuf.license
   }
 
@@ -209,36 +168,31 @@ export async function content_VideoCreated(
     mediaUrls: [],
     mediaAvailability: AssetAvailability.INVALID,
 
-
     // fill in auto-generated fields
     createdAt: new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
     updatedAt: new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
 
     // integrate metadata
-    ...fixedProtobuf
+    ...fixedProtobuf,
   })
 
   // save video
   await db.save<Video>(video)
 
   // emit log event
-  logger.info('Video has been created', {id: videoId})
+  logger.info('Video has been created', { id: videoId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {
-    videoId,
-    videoUpdateParameters,
-    contentActor,
-  } = new Content.VideoUpdatedEvent(event).data
+  const { videoId, videoUpdateParameters, contentActor } = new Content.VideoUpdatedEvent(event).data
 
   // load video
-  const video = await db.get(Video, { where: { id: videoId.toString() } as FindConditions<Video>, relations: ['channel', 'license'] })
+  const video = await db.get(Video, {
+    where: { id: videoId.toString() } as FindConditions<Video>,
+    relations: ['channel', 'license'],
+  })
 
   // ensure video exists
   if (!video) {
@@ -253,16 +207,13 @@ export async function content_VideoUpdated(
 
   // update metadata if it was changed
   if (newMetadata) {
-    const protobufContent = await readProtobufWithAssets(
-      new Video(),
-      {
-        metadata: newMetadata,
-        db,
-        event,
-        assets: videoUpdateParameters.assets.unwrapOr([]),
-        contentOwner: convertContentActorToDataObjectOwner(contentActor, (new BN(video.channel.id)).toNumber()),
-      }
-    )
+    const protobufContent = await readProtobufWithAssets(new Video(), {
+      metadata: newMetadata,
+      db,
+      event,
+      assets: videoUpdateParameters.assets.unwrapOr([]),
+      contentOwner: convertContentActorToDataObjectOwner(contentActor, new BN(video.channel.id).toNumber()),
+    })
 
     // prepare video media metadata (if any)
     const fixedProtobuf = await integrateVideoMediaMetadata(db, video, protobufContent, event)
@@ -271,14 +222,15 @@ export async function content_VideoUpdated(
     const originalLicense = video.license
 
     // update all fields read from protobuf
-    for (let [key, value] of Object.entries(fixedProtobuf)) {
+    for (const [key, value] of Object.entries(fixedProtobuf)) {
       video[key] = value
     }
 
     // license has changed - plan old license delete
-    if (originalLicense && video.license != originalLicense) {
-      ([video.license, licenseToDelete] = handleLicenseUpdate(originalLicense, video.license))
-    } else if (!Object.keys(video.license || {}).length) { // license deletion was requested event no license exists?
+    if (originalLicense && video.license !== originalLicense) {
+      ;[video.license, licenseToDelete] = handleLicenseUpdate(originalLicense, video.license)
+    } else if (!Object.keys(video.license || {}).length) {
+      // license deletion was requested event no license exists?
       delete video.license // ensure license is empty
     }
   }
@@ -295,16 +247,13 @@ export async function content_VideoUpdated(
   }
 
   // emit log event
-  logger.info('Video has been updated', {id: videoId})
+  logger.info('Video has been updated', { id: videoId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoDeleted(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoDeleted(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {videoId} = new Content.VideoDeletedEvent(event).data
+  const { videoId } = new Content.VideoDeletedEvent(event).data
 
   // load video
   const video = await db.get(Video, { where: { id: videoId.toString() } as FindConditions<Video> })
@@ -318,17 +267,13 @@ export async function content_VideoDeleted(
   await db.remove<Video>(video)
 
   // emit log event
-  logger.info('Video has been deleted', {id: videoId})
+  logger.info('Video has been deleted', { id: videoId })
 }
 
-
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_VideoCensorshipStatusUpdated(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_VideoCensorshipStatusUpdated(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {videoId, isCensored} = new Content.VideoCensorshipStatusUpdatedEvent(event).data
+  const { videoId, isCensored } = new Content.VideoCensorshipStatusUpdatedEvent(event).data
 
   // load video
   const video = await db.get(Video, { where: { id: videoId.toString() } as FindConditions<Video> })
@@ -339,7 +284,7 @@ export async function content_VideoCensorshipStatusUpdated(
   }
 
   // update video
-  video.isCensored = isCensored.isTrue;
+  video.isCensored = isCensored.isTrue
 
   // set last update time
   video.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
@@ -348,38 +293,29 @@ export async function content_VideoCensorshipStatusUpdated(
   await db.save<Video>(video)
 
   // emit log event
-  logger.info('Video censorship status has been updated', {id: videoId, isCensored: isCensored.isTrue})
+  logger.info('Video censorship status has been updated', { id: videoId, isCensored: isCensored.isTrue })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
-export async function content_FeaturedVideosSet(
-  db: DatabaseManager,
-  event: SubstrateEvent
-) {
+export async function content_FeaturedVideosSet(db: DatabaseManager, event: SubstrateEvent) {
   // read event data
-  const {videoId: videoIds} = new Content.FeaturedVideosSetEvent(event).data
+  const { videoId: videoIds } = new Content.FeaturedVideosSetEvent(event).data
 
   // load old featured videos
   const existingFeaturedVideos = await db.getMany(Video, { where: { isFeatured: true } as FindConditions<Video> })
 
   // comparsion utility
-  const isSame = (videoIdA: string) => (videoIdB: string) => videoIdA == videoIdB
+  const isSame = (videoIdA: string) => (videoIdB: string) => videoIdA === videoIdB
 
   // calculate diff sets
-  const toRemove = existingFeaturedVideos.filter(existingFV =>
-    !videoIds
-      .map(item => item.toHex())
-      .some(isSame(existingFV.id))
-  )
-  const toAdd = videoIds.filter(video =>
-    !existingFeaturedVideos
-      .map(item => item.id)
-      .some(isSame(video.toHex()))
+  const toRemove = existingFeaturedVideos.filter(
+    (existingFV) => !videoIds.map((item) => item.toHex()).some(isSame(existingFV.id))
   )
+  const toAdd = videoIds.filter((video) => !existingFeaturedVideos.map((item) => item.id).some(isSame(video.toHex())))
 
   // mark previously featured videos as not-featured
-  for (let video of toRemove) {
-    video.isFeatured = false;
+  for (const video of toRemove) {
+    video.isFeatured = false
 
     // set last update time
     video.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
@@ -396,17 +332,19 @@ export async function content_FeaturedVideosSet(
   }
 
   // read videos previously not-featured videos that are meant to be featured
-  const videosToAdd = await db.getMany(Video, { where: {
-    id: In(toAdd.map(item => item.toString()))
-  } as FindConditions<Video> })
+  const videosToAdd = await db.getMany(Video, {
+    where: {
+      id: In(toAdd.map((item) => item.toString())),
+    } as FindConditions<Video>,
+  })
 
-  if (videosToAdd.length != toAdd.length) {
+  if (videosToAdd.length !== toAdd.length) {
     return inconsistentState('At least one non-existing video featuring requested', toAdd)
   }
 
   // mark previously not-featured videos as featured
-  for (let video of videosToAdd) {
-    video.isFeatured = true;
+  for (const video of videosToAdd) {
+    video.isFeatured = true
 
     // set last update time
     video.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
@@ -415,10 +353,10 @@ export async function content_FeaturedVideosSet(
   }
 
   // emit log event
-  logger.info('New featured videos have been set', {videoIds})
+  logger.info('New featured videos have been set', { videoIds })
 }
 
-/////////////////// Helpers ////////////////////////////////////////////////////
+/// ///////////////// Helpers ////////////////////////////////////////////////////
 
 /*
   Integrates video metadata-related data into existing data (if any) or creates a new record.
@@ -430,7 +368,7 @@ async function integrateVideoMediaMetadata(
   db: DatabaseManager,
   existingRecord: Video | null,
   metadata: Partial<Video>,
-  event: SubstrateEvent,
+  event: SubstrateEvent
 ): Promise<Partial<Video>> {
   if (!metadata.mediaMetadata) {
     return metadata
@@ -439,17 +377,18 @@ async function integrateVideoMediaMetadata(
   const now = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
 
   // fix TS type
-  const rawMediaMetadata = metadata.mediaMetadata as unknown as RawVideoMetadata
+  const rawMediaMetadata = (metadata.mediaMetadata as unknown) as RawVideoMetadata
 
   // ensure encoding object
-  const encoding = (existingRecord && existingRecord.mediaMetadata && existingRecord.mediaMetadata.encoding)
-    || new VideoMediaEncoding({
-        createdAt: now,
-        updatedAt: now,
+  const encoding =
+    (existingRecord && existingRecord.mediaMetadata && existingRecord.mediaMetadata.encoding) ||
+    new VideoMediaEncoding({
+      createdAt: now,
+      updatedAt: now,
 
-        createdById: '1',
-        updatedById: '1',
-      })
+      createdById: '1',
+      updatedById: '1',
+    })
 
   // integrate media encoding-related data
   rawMediaMetadata.encoding.codecName.integrateInto(encoding, 'codecName')
@@ -457,15 +396,17 @@ async function integrateVideoMediaMetadata(
   rawMediaMetadata.encoding.mimeMediaType.integrateInto(encoding, 'mimeMediaType')
 
   // ensure media metadata object
-  const mediaMetadata = (existingRecord && existingRecord.mediaMetadata) || new VideoMediaMetadata({
-    createdInBlock: event.blockNumber,
+  const mediaMetadata =
+    (existingRecord && existingRecord.mediaMetadata) ||
+    new VideoMediaMetadata({
+      createdInBlock: event.blockNumber,
 
-    createdAt: now,
-    updatedAt: now,
+      createdAt: now,
+      updatedAt: now,
 
-    createdById: '1',
-    updatedById: '1',
-  })
+      createdById: '1',
+      updatedById: '1',
+    })
 
   // integrate media-related data
   rawMediaMetadata.pixelWidth.integrateInto(mediaMetadata, 'pixelWidth')
@@ -483,29 +424,33 @@ async function integrateVideoMediaMetadata(
     mediaMetadata.id = await createPredictableId(db)
   }
 
-  /////////////////// update updatedAt if needed ///////////////////////////////
-
-  const encodingNoChange = true
-    && rawMediaMetadata.encoding.codecName.isNoChange()
-    && rawMediaMetadata.encoding.container.isNoChange()
-    && rawMediaMetadata.encoding.mimeMediaType.isNoChange()
-  const mediaMetadataNoChange = encodingNoChange
-    && rawMediaMetadata.encoding.codecName.isNoChange()
-    && rawMediaMetadata.encoding.container.isNoChange()
-    && rawMediaMetadata.encoding.mimeMediaType.isNoChange()
-
-  if (!encodingNoChange) { // encoding changed?
+  /// ///////////////// update updatedAt if needed ///////////////////////////////
+
+  const encodingNoChange =
+    true &&
+    rawMediaMetadata.encoding.codecName.isNoChange() &&
+    rawMediaMetadata.encoding.container.isNoChange() &&
+    rawMediaMetadata.encoding.mimeMediaType.isNoChange()
+  const mediaMetadataNoChange =
+    encodingNoChange &&
+    rawMediaMetadata.encoding.codecName.isNoChange() &&
+    rawMediaMetadata.encoding.container.isNoChange() &&
+    rawMediaMetadata.encoding.mimeMediaType.isNoChange()
+
+  if (!encodingNoChange) {
+    // encoding changed?
     mediaMetadata.encoding.updatedAt = now
   }
-  if (!mediaMetadataNoChange) { // metadata changed?
+  if (!mediaMetadataNoChange) {
+    // metadata changed?
     mediaMetadata.updatedAt = now
   }
 
-  //////////////////////////////////////////////////////////////////////////////
+  /// ////////////////////////////////////////////////////////////////////////////
 
   return {
     ...metadata,
-    mediaMetadata
+    mediaMetadata,
   }
 }
 
@@ -517,17 +462,19 @@ function handleLicenseUpdate(originalLicense, newLicense): [License | undefined,
     return [undefined, null]
   }
 
-  if (!originalLicense) { // && !isNewEmpty
+  if (!originalLicense) {
+    // && !isNewEmpty
     return [newLicense, null]
   }
 
-  if (!isNewEmpty) { // && originalLicense
+  if (!isNewEmpty) {
+    // && originalLicense
     return [
       new License({
         ...originalLicense,
         ...newLicense,
       }),
-      null
+      null,
     ]
   }
 

+ 1 - 1
query-node/mappings/src/eventFix.ts

@@ -2,5 +2,5 @@ import BN from 'bn.js'
 
 // Workaround for https://github.com/Joystream/hydra/issues/326 . This file can be removed after it's fixed
 export function fixBlockTimestamp(blockTimestamp: unknown): BN {
-    return new BN(blockTimestamp as string)
+  return new BN(blockTimestamp as string)
 }

+ 37 - 43
query-node/mappings/src/membership.ts

@@ -6,12 +6,7 @@ import { SubstrateEvent } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
 import { FindConditions } from 'typeorm'
 
-import {
-  inconsistentState,
-  logger,
-  extractExtrinsicArgs,
-  extractSudoCallParameters,
-} from './common'
+import { inconsistentState, logger, extractExtrinsicArgs, extractSudoCallParameters } from './common'
 import { Members } from '../../generated/types'
 import { MembershipEntryMethod, Membership } from 'query-node'
 import { EntryMethod } from '@joystream/types/augment'
@@ -20,15 +15,11 @@ import { EntryMethod } from '@joystream/types/augment'
 export async function members_MemberRegistered(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
   const { accountId, memberId, entryMethod } = new Members.MemberRegisteredEvent(event).data
-  const { avatarUri, about, handle } = extractExtrinsicArgs(
-    event,
-    Members.BuyMembershipCall,
-    {
-      handle: 1,
-      avatarUri: 2,
-      about: 3,
-    },
-  )
+  const { avatarUri, about, handle } = extractExtrinsicArgs(event, Members.BuyMembershipCall, {
+    handle: 1,
+    avatarUri: 2,
+    about: 3,
+  })
 
   // create new membership
   const member = new Membership({
@@ -51,7 +42,7 @@ export async function members_MemberRegistered(db: DatabaseManager, event: Subst
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info('Member has been registered', {ids: memberId})
+  logger.info('Member has been registered', { ids: memberId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -59,9 +50,9 @@ export async function members_MemberUpdatedAboutText(db: DatabaseManager, event:
   // read event data
   const { text, memberId } = isUpdateMembershipExtrinsic(event)
     ? unpackUpdateMembershipOptions(
-        extractExtrinsicArgs(event, Members.UpdateMembershipCall, {memberId: 0, about: 3})
+        extractExtrinsicArgs(event, Members.UpdateMembershipCall, { memberId: 0, about: 3 })
       )
-    : extractExtrinsicArgs(event, Members.ChangeMemberAboutTextCall, {memberId: 0, text: 1})
+    : extractExtrinsicArgs(event, Members.ChangeMemberAboutTextCall, { memberId: 0, text: 1 })
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -81,7 +72,7 @@ export async function members_MemberUpdatedAboutText(db: DatabaseManager, event:
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info("Member's about text has been updated", {ids: memberId})
+  logger.info("Member's about text has been updated", { ids: memberId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -89,9 +80,9 @@ export async function members_MemberUpdatedAvatar(db: DatabaseManager, event: Su
   // read event data
   const { uri, memberId } = isUpdateMembershipExtrinsic(event)
     ? unpackUpdateMembershipOptions(
-        extractExtrinsicArgs(event, Members.UpdateMembershipCall, {memberId: 0, avatarUri: 2})
+        extractExtrinsicArgs(event, Members.UpdateMembershipCall, { memberId: 0, avatarUri: 2 })
       )
-    : extractExtrinsicArgs(event, Members.ChangeMemberAvatarCall, {memberId: 0, uri: 1})
+    : extractExtrinsicArgs(event, Members.ChangeMemberAvatarCall, { memberId: 0, uri: 1 })
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -111,7 +102,7 @@ export async function members_MemberUpdatedAvatar(db: DatabaseManager, event: Su
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info("Member's avatar has been updated", {ids: memberId})
+  logger.info("Member's avatar has been updated", { ids: memberId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -119,9 +110,9 @@ export async function members_MemberUpdatedHandle(db: DatabaseManager, event: Su
   // read event data
   const { handle, memberId } = isUpdateMembershipExtrinsic(event)
     ? unpackUpdateMembershipOptions(
-        extractExtrinsicArgs(event, Members.UpdateMembershipCall, {memberId: 0, handle: 1})
+        extractExtrinsicArgs(event, Members.UpdateMembershipCall, { memberId: 0, handle: 1 })
       )
-    : extractExtrinsicArgs(event, Members.ChangeMemberHandleCall, {memberId: 0, handle: 1})
+    : extractExtrinsicArgs(event, Members.ChangeMemberHandleCall, { memberId: 0, handle: 1 })
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -141,13 +132,16 @@ export async function members_MemberUpdatedHandle(db: DatabaseManager, event: Su
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info("Member's avatar has been updated", {ids: memberId})
+  logger.info("Member's avatar has been updated", { ids: memberId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberSetRootAccount(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { newRootAccount, memberId } = extractExtrinsicArgs(event, Members.SetRootAccountCall, {memberId: 0, newRootAccount: 1})
+  const { newRootAccount, memberId } = extractExtrinsicArgs(event, Members.SetRootAccountCall, {
+    memberId: 0,
+    newRootAccount: 1,
+  })
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -167,17 +161,16 @@ export async function members_MemberSetRootAccount(db: DatabaseManager, event: S
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info("Member's root has been updated", {ids: memberId})
+  logger.info("Member's root has been updated", { ids: memberId })
 }
 
 // eslint-disable-next-line @typescript-eslint/naming-convention
 export async function members_MemberSetControllerAccount(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const { newControllerAccount, memberId } = extractExtrinsicArgs(
-    event,
-    Members.SetControllerAccountCall,
-    {memberId: 0, newControllerAccount: 1},
-  )
+  const { newControllerAccount, memberId } = extractExtrinsicArgs(event, Members.SetControllerAccountCall, {
+    memberId: 0,
+    newControllerAccount: 1,
+  })
 
   // load member
   const member = await db.get(Membership, { where: { id: memberId.toString() } as FindConditions<Membership> })
@@ -197,10 +190,10 @@ export async function members_MemberSetControllerAccount(db: DatabaseManager, ev
   await db.save<Membership>(member)
 
   // emit log event
-  logger.info("Member's controller has been updated", {ids: memberId})
+  logger.info("Member's controller has been updated", { ids: memberId })
 }
 
-/////////////////// Helpers ////////////////////////////////////////////////////
+/// ///////////////// Helpers ////////////////////////////////////////////////////
 
 /*
   Helper for converting Bytes type to string
@@ -211,9 +204,9 @@ function convertBytesToString(b: Bytes | null): string {
   }
 
   const result = Buffer.from(b.toU8a(true))
-      .toString()
-      // eslint-disable-next-line no-control-regex
-      .replace(/\u0000/g, '')
+    .toString()
+    // eslint-disable-next-line no-control-regex
+    .replace(/\u0000/g, '')
 
   return result
 }
@@ -235,31 +228,32 @@ function convertEntryMethod(entryMethod: EntryMethod): MembershipEntryMethod {
   }
 
   // should never happen
-  logger.error('Not implemented entry method', {entryMethod: entryMethod.toString()})
-  throw 'Not implemented entry method'
+  logger.error('Not implemented entry method', { entryMethod: entryMethod.toString() })
+  throw new Error('Not implemented entry method')
 }
 
 /*
   Returns true if event is emitted inside of `update_membership` extrinsic.
 */
 function isUpdateMembershipExtrinsic(event: SubstrateEvent): boolean {
-  if (!event.extrinsic) { // this should never happen
+  if (!event.extrinsic) {
+    // this should never happen
     return false
   }
 
-  if (event.extrinsic.method == 'updateMembership') {
+  if (event.extrinsic.method === 'updateMembership') {
     return true
   }
 
   // no sudo was used to update membership -> this is not updateMembership
-  if (event.extrinsic.section != 'sudo') {
+  if (event.extrinsic.section !== 'sudo') {
     return false
   }
 
   const sudoCallParameters = extractSudoCallParameters<unknown[]>(event)
 
   // very trivial check if update_membership extrinsic was used
-  return sudoCallParameters.args.length == 4 // memberId, handle, avatarUri, about
+  return sudoCallParameters.args.length === 4 // memberId, handle, avatarUri, about
 }
 
 interface IUnpackedUpdateMembershipOptions {

+ 59 - 55
query-node/mappings/src/storage.ts

@@ -3,20 +3,10 @@ import { SubstrateEvent } from '@dzlzv/hydra-common'
 import { DatabaseManager } from '@dzlzv/hydra-db-utils'
 import { FindConditions, In } from 'typeorm'
 
-import {
-  inconsistentState,
-  logger,
-  prepareDataObject,
-} from './common'
+import { inconsistentState, logger, prepareDataObject } from './common'
 
-import {
-  DataDirectory,
-} from '../../generated/types'
-import {
-  ContentId,
-  ContentParameters,
-  StorageObjectOwner,
-} from '@joystream/types/augment'
+import { DataDirectory } from '../../generated/types'
+import { ContentId, ContentParameters, StorageObjectOwner } from '@joystream/types/augment'
 
 import { ContentId as Custom_ContentId, ContentParameters as Custom_ContentParameters } from '@joystream/types/storage'
 import { registry } from '@joystream/types'
@@ -25,7 +15,6 @@ import {
   Channel,
   Video,
   AssetAvailability,
-
   DataObject,
   DataObjectOwner,
   DataObjectOwnerMember,
@@ -40,10 +29,10 @@ import {
 
 export async function dataDirectory_ContentAdded(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {contentParameters, storageObjectOwner} = new DataDirectory.ContentAddedEvent(event).data
+  const { contentParameters, storageObjectOwner } = new DataDirectory.ContentAddedEvent(event).data
 
   // save all content objects
-  for (let parameters of contentParameters) {
+  for (const parameters of contentParameters) {
     const owner = convertStorageObjectOwner(storageObjectOwner)
     const dataObject = await prepareDataObject(db, parameters, event, owner)
 
@@ -55,23 +44,27 @@ export async function dataDirectory_ContentAdded(db: DatabaseManager, event: Sub
   }
 
   // emit log event
-  logger.info("Storage content has beed added", {ids: contentParameters.map(item => encodeContentId(item.content_id))})
+  logger.info('Storage content has beed added', {
+    ids: contentParameters.map((item) => encodeContentId(item.content_id)),
+  })
 }
 
 export async function dataDirectory_ContentRemoved(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {contentId: contentIds} = new DataDirectory.ContentRemovedEvent(event).data
+  const { contentId: contentIds } = new DataDirectory.ContentRemovedEvent(event).data
 
   // load assets
-  const dataObjects = await db.getMany(DataObject, { where: {
-    joystreamContentId: In(contentIds.map(item => encodeContentId(item)))
-  } as FindConditions<DataObject> })
+  const dataObjects = await db.getMany(DataObject, {
+    where: {
+      joystreamContentId: In(contentIds.map((item) => encodeContentId(item))),
+    } as FindConditions<DataObject>,
+  })
 
   // store dataObject ids before they are deleted (for logging purposes)
-  const dataObjectIds = dataObjects.map(item => item.id)
+  const dataObjectIds = dataObjects.map((item) => item.id)
 
   // remove assets from database
-  for (let item of dataObjects) {
+  for (const item of dataObjects) {
     // ensure dataObject is nowhere used to prevent db constraint error
     await disconnectDataObjectRelations(db, item)
 
@@ -80,16 +73,18 @@ export async function dataDirectory_ContentRemoved(db: DatabaseManager, event: S
   }
 
   // emit log event
-  logger.info("Storage content have been removed", {id: contentIds, dataObjectIds})
+  logger.info('Storage content have been removed', { id: contentIds, dataObjectIds })
 }
 
 export async function dataDirectory_ContentAccepted(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {contentId, storageProviderId} = new DataDirectory.ContentAcceptedEvent(event).data
+  const { contentId, storageProviderId } = new DataDirectory.ContentAcceptedEvent(event).data
   const encodedContentId = encodeContentId(contentId)
 
   // load asset
-  const dataObject = await db.get(DataObject, { where: { joystreamContentId: encodedContentId } as FindConditions<DataObject>})
+  const dataObject = await db.get(DataObject, {
+    where: { joystreamContentId: encodedContentId } as FindConditions<DataObject>,
+  })
 
   // ensure object exists
   if (!dataObject) {
@@ -101,7 +96,7 @@ export async function dataDirectory_ContentAccepted(db: DatabaseManager, event:
     where: {
       workerId: storageProviderId.toString(),
       type: WorkerType.STORAGE,
-    } as FindConditions<Worker>
+    } as FindConditions<Worker>,
   })
 
   // ensure object exists
@@ -120,14 +115,14 @@ export async function dataDirectory_ContentAccepted(db: DatabaseManager, event:
   await db.save<DataObject>(dataObject)
 
   // emit log event
-  logger.info("Storage content has been accepted", {id: encodedContentId})
+  logger.info('Storage content has been accepted', { id: encodedContentId })
 
   // update asset availability for all connected channels and videos
   // this will not be needed after redudant AssetAvailability will be removed (after some Hydra upgrades)
   await updateConnectedAssets(db, dataObject)
 }
 
-/////////////////// Updating connected entities ////////////////////////////////
+/// ///////////////// Updating connected entities ////////////////////////////////
 
 async function updateConnectedAssets(db: DatabaseManager, dataObject: DataObject) {
   await updateSingleConnectedAsset(db, new Channel(), 'avatarPhoto', dataObject)
@@ -137,22 +132,25 @@ async function updateConnectedAssets(db: DatabaseManager, dataObject: DataObject
   await updateSingleConnectedAsset(db, new Video(), 'media', dataObject)
 }
 
-//async function updateSingleConnectedAsset(db: DatabaseManager, type: typeof Channel | typeof Video, propertyName: string, dataObject: DataObject) {
-async function updateSingleConnectedAsset<T extends Channel | Video>(db: DatabaseManager, type: T, propertyName: string, dataObject: DataObject) {
+// async function updateSingleConnectedAsset(db: DatabaseManager, type: typeof Channel | typeof Video, propertyName: string, dataObject: DataObject) {
+async function updateSingleConnectedAsset<T extends Channel | Video>(
+  db: DatabaseManager,
+  type: T,
+  propertyName: string,
+  dataObject: DataObject
+) {
   // prepare lookup condition
   const condition = {
     where: {
-      [propertyName + 'DataObject']: dataObject
-    }
+      [propertyName + 'DataObject']: dataObject,
+    },
   } // as FindConditions<T>
 
   // NOTE: we don't need to retrieve multiple channels/videos via `db.getMany()` because dataObject
   //       is allowed to be associated only with one channel/video in runtime
 
   // in therory the following condition(s) can be generalized `... db.get(type, ...` but in practice it doesn't work :-\
-  const item = type instanceof Channel
-    ? await db.get(Channel, condition)
-    : await db.get(Video, condition)
+  const item = type instanceof Channel ? await db.get(Channel, condition) : await db.get(Video, condition)
 
   // escape when no dataObject association found
   if (!item) {
@@ -165,17 +163,17 @@ async function updateSingleConnectedAsset<T extends Channel | Video>(db: Databas
     await db.save<Channel>(item)
 
     // emit log event
-    logger.info("Channel using Content has been accepted", {
+    logger.info('Channel using Content has been accepted', {
       channelId: item.id.toString(),
-      joystreamContentId: dataObject.joystreamContentId
+      joystreamContentId: dataObject.joystreamContentId,
     })
   } else {
     await db.save<Video>(item)
 
     // emit log event
-    logger.info("Video using Content has been accepted", {
+    logger.info('Video using Content has been accepted', {
       videoId: item.id.toString(),
-      joystreamContentId: dataObject.joystreamContentId
+      joystreamContentId: dataObject.joystreamContentId,
     })
   }
 }
@@ -189,21 +187,24 @@ async function disconnectDataObjectRelations(db: DatabaseManager, dataObject: Da
   await disconnectSingleDataObjectRelation(db, new Video(), 'media', dataObject)
 }
 
-async function disconnectSingleDataObjectRelation<T extends Channel | Video>(db: DatabaseManager, type: T, propertyName: string, dataObject: DataObject) {
+async function disconnectSingleDataObjectRelation<T extends Channel | Video>(
+  db: DatabaseManager,
+  type: T,
+  propertyName: string,
+  dataObject: DataObject
+) {
   // prepare lookup condition
   const condition = {
     where: {
-      [propertyName + 'DataObject']: dataObject
-    }
+      [propertyName + 'DataObject']: dataObject,
+    },
   } // as FindConditions<T>
 
   // NOTE: we don't need to retrieve multiple channels/videos via `db.getMany()` because dataObject
   //       is allowed to be associated only with one channel/video in runtime
 
   // in therory the following condition(s) can be generalized `... db.get(type, ...` but in practice it doesn't work :-\
-  const item = type instanceof Channel
-    ? await db.get(Channel, condition)
-    : await db.get(Video, condition)
+  const item = type instanceof Channel ? await db.get(Channel, condition) : await db.get(Video, condition)
 
   // escape when no dataObject association found
   if (!item) {
@@ -217,20 +218,23 @@ async function disconnectSingleDataObjectRelation<T extends Channel | Video>(db:
     await db.save<Channel>(item)
 
     // emit log event
-    logger.info("Content has been disconnected from Channel", {
+    logger.info('Content has been disconnected from Channel', {
       channelId: item.id.toString(),
-      joystreamContentId: dataObject.joystreamContentId})
-  } else { // type instanceof Video
+      joystreamContentId: dataObject.joystreamContentId,
+    })
+  } else {
+    // type instanceof Video
     await db.save<Video>(item)
 
     // emit log event
-    logger.info("Content has been disconnected from Video", {
+    logger.info('Content has been disconnected from Video', {
       videoId: item.id.toString(),
-      joystreamContentId: dataObject.joystreamContentId})
+      joystreamContentId: dataObject.joystreamContentId,
+    })
   }
 }
 
-/////////////////// Helpers ////////////////////////////////////////////////////
+/// ///////////////// Helpers ////////////////////////////////////////////////////
 
 function convertStorageObjectOwner(objectOwner: StorageObjectOwner): typeof DataObjectOwner {
   if (objectOwner.isMember) {
@@ -265,12 +269,12 @@ function convertStorageObjectOwner(objectOwner: StorageObjectOwner): typeof Data
     return owner
   }
 
-  logger.error('Not implemented StorageObjectOwner type', {objectOwner: objectOwner.toString()})
-  throw 'Not implemented StorageObjectOwner type'
+  logger.error('Not implemented StorageObjectOwner type', { objectOwner: objectOwner.toString() })
+  throw new Error('Not implemented StorageObjectOwner type')
 }
 
 function encodeContentId(contentId: ContentId) {
-  const customContentId = new Custom_ContentId(registry, contentId);
+  const customContentId = new Custom_ContentId(registry, contentId)
 
   return customContentId.encode()
 }

+ 68 - 52
query-node/mappings/src/workingGroup.ts

@@ -4,40 +4,28 @@ import { FindConditions } from 'typeorm'
 import { Bytes } from '@polkadot/types'
 import { fixBlockTimestamp } from './eventFix'
 
-import {
-  inconsistentState,
-  logger,
-  createPredictableId,
-} from './common'
-
-import {
-  Channel,
-  Worker,
-  WorkerType,
-} from 'query-node'
-import {
-  GatewayWorkingGroup,
-  StorageWorkingGroup,
-} from '../../generated/types'
-import {
-  ApplicationId,
-  ApplicationIdToWorkerIdMap,
-  WorkerId,
-} from "@joystream/types/augment";
-
-/////////////////// Storage working group //////////////////////////////////////
+import { inconsistentState, logger, createPredictableId } from './common'
+
+import { Channel, Worker, WorkerType } from 'query-node'
+import { GatewayWorkingGroup, StorageWorkingGroup } from '../../generated/types'
+import { ApplicationId, ApplicationIdToWorkerIdMap, WorkerId } from '@joystream/types/augment'
+
+/// ///////////////// Storage working group //////////////////////////////////////
 
 export async function storageWorkingGroup_OpeningFilled(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {applicationIdToWorkerIdMap} = new StorageWorkingGroup.OpeningFilledEvent(event).data
+  const { applicationIdToWorkerIdMap } = new StorageWorkingGroup.OpeningFilledEvent(event).data
 
   // call generic processing
   await workingGroup_OpeningFilled(db, WorkerType.STORAGE, applicationIdToWorkerIdMap, event)
 }
 
-export async function storageWorkingGroup_WorkerStorageUpdated(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
+export async function storageWorkingGroup_WorkerStorageUpdated(
+  db: DatabaseManager,
+  event: SubstrateEvent
+): Promise<void> {
   // read event data
-  const {workerId, bytes: newMetadata} = new StorageWorkingGroup.WorkerStorageUpdatedEvent(event).data
+  const { workerId, bytes: newMetadata } = new StorageWorkingGroup.WorkerStorageUpdatedEvent(event).data
 
   // call generic processing
   await workingGroup_WorkerStorageUpdated(db, WorkerType.STORAGE, workerId, newMetadata)
@@ -45,7 +33,7 @@ export async function storageWorkingGroup_WorkerStorageUpdated(db: DatabaseManag
 
 export async function storageWorkingGroup_TerminatedWorker(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new StorageWorkingGroup.TerminatedWorkerEvent(event).data
+  const { workerId } = new StorageWorkingGroup.TerminatedWorkerEvent(event).data
 
   // call generic processing
   await workingGroup_TerminatedWorker(db, event, WorkerType.STORAGE, workerId)
@@ -53,7 +41,7 @@ export async function storageWorkingGroup_TerminatedWorker(db: DatabaseManager,
 
 export async function storageWorkingGroup_WorkerExited(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new StorageWorkingGroup.WorkerExitedEvent(event).data
+  const { workerId } = new StorageWorkingGroup.WorkerExitedEvent(event).data
 
   // call generic processing
   await workingGroup_WorkerExited(db, event, WorkerType.STORAGE, workerId)
@@ -61,25 +49,28 @@ export async function storageWorkingGroup_WorkerExited(db: DatabaseManager, even
 
 export async function storageWorkingGroup_TerminatedLeader(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new StorageWorkingGroup.TerminatedLeaderEvent(event).data
+  const { workerId } = new StorageWorkingGroup.TerminatedLeaderEvent(event).data
 
   // call generic processing
   await workingGroup_TerminatedLeader(db, event, WorkerType.STORAGE, workerId)
 }
 
-/////////////////// Gateway working group //////////////////////////////////////
+/// ///////////////// Gateway working group //////////////////////////////////////
 
 export async function gatewayWorkingGroup_OpeningFilled(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {applicationIdToWorkerIdMap} = new GatewayWorkingGroup.OpeningFilledEvent(event).data
+  const { applicationIdToWorkerIdMap } = new GatewayWorkingGroup.OpeningFilledEvent(event).data
 
   // call generic processing
   await workingGroup_OpeningFilled(db, WorkerType.GATEWAY, applicationIdToWorkerIdMap, event)
 }
 
-export async function gatewayWorkingGroup_WorkerStorageUpdated(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
+export async function gatewayWorkingGroup_WorkerStorageUpdated(
+  db: DatabaseManager,
+  event: SubstrateEvent
+): Promise<void> {
   // read event data
-  const {workerId, bytes: newMetadata} = new GatewayWorkingGroup.WorkerStorageUpdatedEvent(event).data
+  const { workerId, bytes: newMetadata } = new GatewayWorkingGroup.WorkerStorageUpdatedEvent(event).data
 
   // call generic processing
   await workingGroup_WorkerStorageUpdated(db, WorkerType.GATEWAY, workerId, newMetadata)
@@ -87,7 +78,7 @@ export async function gatewayWorkingGroup_WorkerStorageUpdated(db: DatabaseManag
 
 export async function gatewayWorkingGroup_TerminatedWorker(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new GatewayWorkingGroup.TerminatedWorkerEvent(event).data
+  const { workerId } = new GatewayWorkingGroup.TerminatedWorkerEvent(event).data
 
   // call generic processing
   await workingGroup_TerminatedWorker(db, event, WorkerType.GATEWAY, workerId)
@@ -95,7 +86,7 @@ export async function gatewayWorkingGroup_TerminatedWorker(db: DatabaseManager,
 
 export async function gatewayWorkingGroup_WorkerExited(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new GatewayWorkingGroup.WorkerExitedEvent(event).data
+  const { workerId } = new GatewayWorkingGroup.WorkerExitedEvent(event).data
 
   // call generic processing
   await workingGroup_WorkerExited(db, event, WorkerType.GATEWAY, workerId)
@@ -103,19 +94,19 @@ export async function gatewayWorkingGroup_WorkerExited(db: DatabaseManager, even
 
 export async function gatewayWorkingGroup_TerminatedLeader(db: DatabaseManager, event: SubstrateEvent): Promise<void> {
   // read event data
-  const {workerId} = new GatewayWorkingGroup.TerminatedLeaderEvent(event).data
+  const { workerId } = new GatewayWorkingGroup.TerminatedLeaderEvent(event).data
 
   // call generic processing
   await workingGroup_TerminatedLeader(db, event, WorkerType.GATEWAY, workerId)
 }
 
-/////////////////// Generic working group processing ///////////////////////////
+/// ///////////////// Generic working group processing ///////////////////////////
 
 export async function workingGroup_OpeningFilled(
   db: DatabaseManager,
   workerType: WorkerType,
   applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap,
-  event: SubstrateEvent,
+  event: SubstrateEvent
 ): Promise<void> {
   const workerIds = [...applicationIdToWorkerIdMap.values()]
 
@@ -124,16 +115,21 @@ export async function workingGroup_OpeningFilled(
   }
 
   // emit log event
-  logger.info("Workers have been created", {ids: workerIds.map(item => item.toString()), workerType})
+  logger.info('Workers have been created', { ids: workerIds.map((item) => item.toString()), workerType })
 }
 
-export async function workingGroup_WorkerStorageUpdated(db: DatabaseManager, workerType: WorkerType, workerId: WorkerId, newMetadata: Bytes): Promise<void> {
+export async function workingGroup_WorkerStorageUpdated(
+  db: DatabaseManager,
+  workerType: WorkerType,
+  workerId: WorkerId,
+  newMetadata: Bytes
+): Promise<void> {
   // load worker
   const worker = await db.get(Worker, {
     where: {
       workerId: workerId.toString(),
       type: workerType,
-    } as FindConditions<Worker>
+    } as FindConditions<Worker>,
   })
 
   // ensure worker exists
@@ -146,40 +142,55 @@ export async function workingGroup_WorkerStorageUpdated(db: DatabaseManager, wor
   await db.save<Worker>(worker)
 
   // emit log event
-  logger.info("Worker has been updated", {workerId, workerType})
+  logger.info('Worker has been updated', { workerId, workerType })
 }
 
-export async function workingGroup_TerminatedWorker(db: DatabaseManager, event: SubstrateEvent, workerType: WorkerType, workerId: WorkerId): Promise<void> {
+export async function workingGroup_TerminatedWorker(
+  db: DatabaseManager,
+  event: SubstrateEvent,
+  workerType: WorkerType,
+  workerId: WorkerId
+): Promise<void> {
   // do removal logic
   await deactivateWorker(db, event, workerType, workerId)
 
   // emit log event
-  logger.info("Worker has been removed (worker terminated)", {workerId, workerType})
+  logger.info('Worker has been removed (worker terminated)', { workerId, workerType })
 }
 
-export async function workingGroup_WorkerExited(db: DatabaseManager, event: SubstrateEvent, workerType: WorkerType, workerId: WorkerId): Promise<void> {
+export async function workingGroup_WorkerExited(
+  db: DatabaseManager,
+  event: SubstrateEvent,
+  workerType: WorkerType,
+  workerId: WorkerId
+): Promise<void> {
   // do removal logic
   await deactivateWorker(db, event, workerType, workerId)
 
   // emit log event
-  logger.info("Worker has been removed (worker exited)", {workerId, workerType})
+  logger.info('Worker has been removed (worker exited)', { workerId, workerType })
 }
 
-export async function workingGroup_TerminatedLeader(db: DatabaseManager, event: SubstrateEvent, workerType: WorkerType, workerId: WorkerId): Promise<void> {
+export async function workingGroup_TerminatedLeader(
+  db: DatabaseManager,
+  event: SubstrateEvent,
+  workerType: WorkerType,
+  workerId: WorkerId
+): Promise<void> {
   // do removal logic
   await deactivateWorker(db, event, workerType, workerId)
 
   // emit log event
-  logger.info("Working group leader has been removed (worker exited)", {workerId, workerType})
+  logger.info('Working group leader has been removed (worker exited)', { workerId, workerType })
 }
 
-/////////////////// Helpers ////////////////////////////////////////////////////
+/// ///////////////// Helpers ////////////////////////////////////////////////////
 
 async function createWorker(
   db: DatabaseManager,
   workerId: WorkerId,
   workerType: WorkerType,
-  event: SubstrateEvent,
+  event: SubstrateEvent
 ): Promise<void> {
   // create entity
   const newWorker = new Worker({
@@ -196,13 +207,18 @@ async function createWorker(
   await db.save<Worker>(newWorker)
 }
 
-async function deactivateWorker(db: DatabaseManager, event: SubstrateEvent, workerType: WorkerType, workerId: WorkerId) {
+async function deactivateWorker(
+  db: DatabaseManager,
+  event: SubstrateEvent,
+  workerType: WorkerType,
+  workerId: WorkerId
+) {
   // load worker
   const worker = await db.get(Worker, {
     where: {
       workerId: workerId.toString(),
       type: workerType,
-    } as FindConditions<Worker>
+    } as FindConditions<Worker>,
   })
 
   // ensure worker exists
@@ -214,7 +230,7 @@ async function deactivateWorker(db: DatabaseManager, event: SubstrateEvent, work
   worker.isActive = false
 
   // set last update time
-  worker.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber()),
+  worker.updatedAt = new Date(fixBlockTimestamp(event.blockTimestamp).toNumber())
 
   // save worker
   await db.save<Worker>(worker)