123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- // Creates /augment-codec/augment-types.ts file with api augmentation that allows
- // creating custom Joystream "Codec types" with api.createType
- import common from '../common'
- import members from '../members'
- import council from '../council'
- import roles from '../roles'
- import forum from '../forum'
- import stake from '../stake'
- import mint from '../mint'
- import recurringRewards from '../recurring-rewards'
- import hiring from '../hiring'
- import versionedStore from '../versioned-store'
- import versionedStorePermissions from '../versioned-store/permissions'
- import contentWorkingGroup from '../content-working-group'
- import workingGroup from '../working-group'
- import discovery from '../discovery'
- import media from '../media'
- import proposals from '../proposals'
- import fs from 'fs'
- import path from 'path'
- import * as defaultDefinitions from '@polkadot/types/interfaces/definitions'
- import { generateInterfaceTypes } from '@polkadot/typegen/generate/interfaceRegistry'
- const OUTPUT_PATH = path.join(__dirname, '../../augment-codec/augment-types.ts')
- const IMPORTS_DIR = '..'
- const typesByModule = {
- 'common': common,
- 'members': members,
- 'council': council,
- 'roles': roles,
- 'forum': forum,
- 'stake': stake,
- 'mint': mint,
- 'recurring-rewards': recurringRewards,
- 'hiring': hiring,
- 'versioned-store': versionedStore,
- 'versioned-store/permissions': versionedStorePermissions,
- 'content-working-group': contentWorkingGroup,
- 'working-group': workingGroup,
- 'discovery': discovery,
- 'media': media,
- 'proposals': proposals,
- }
- type Imports = { [moduleName: string]: string[] }
- type AugmentTypes = { [typeName: string]: string }
- const imports: Imports = {}
- const augmentTypes: AugmentTypes = {}
- const CUSTOM_IMPORTS_TAG = 'CUSTOMIMPORTS'
- const CUSTOM_TYPES_TAG = 'CUSTOMTYPES'
- const populateFileByTemplateTag = (fileContent: string, tag: string, insertLines: string[]) => {
- const fileLines = fileContent.split('\n')
- const startIndex = fileLines.findIndex((line) => line.includes(`/** ${tag} **/`))
- const endIndex = fileLines.findIndex((line) => line.includes(`/** /${tag} **/`))
- if (startIndex === -1 || endIndex === -1 || endIndex <= startIndex) {
- throw new Error(`populateFileByTemplateTag: Invalid tag (${tag})`)
- }
- const [whitespace] = fileLines[startIndex].match(/^(\s)+/) || ['']
- fileLines.splice(startIndex + 1, endIndex - (startIndex + 1), ...insertLines.map((line) => `${whitespace}${line}`))
- return fileLines.join('\n')
- }
- const addTagsIfDontExist = (fileContent: string): string => {
- const fileLines = fileContent.split('\n')
- // Custom imports
- if (fileLines.findIndex((line) => line.includes(`/** ${CUSTOM_IMPORTS_TAG} **/`)) === -1) {
- const firstImportIndex = fileLines.findIndex((line) => line.includes('import'))
- fileLines.splice(firstImportIndex, 0, `/** ${CUSTOM_IMPORTS_TAG} **/`, `/** /${CUSTOM_IMPORTS_TAG} **/`)
- }
- // Custom types
- if (fileLines.findIndex((line) => line.includes(`/** ${CUSTOM_TYPES_TAG} **/`)) === -1) {
- const firstTypeIndex = fileLines.findIndex((line) => line.includes('export interface InterfaceTypes')) + 1
- const [whitespace] = fileLines[firstTypeIndex].match(/^(\s)+/) || ['']
- fileLines.splice(
- firstTypeIndex,
- 0,
- `${whitespace}/** ${CUSTOM_TYPES_TAG} **/`,
- `${whitespace}/** /${CUSTOM_TYPES_TAG} **/`
- )
- }
- return fileLines.join('\n')
- }
- const updateAugmentTypesFile = (filePath: string, imports: Imports, augmentTypes: AugmentTypes) => {
- let fileContent = fs.readFileSync(filePath).toString()
- fileContent = addTagsIfDontExist(fileContent)
- fileContent = populateFileByTemplateTag(
- fileContent,
- CUSTOM_IMPORTS_TAG,
- Object.entries(imports).map(
- ([moduleName, importStatements]) =>
- // import as to avoid namespace clashes
- `import { ${importStatements.join(', ')} } from '${IMPORTS_DIR}/${moduleName}'`
- )
- )
- fileContent = populateFileByTemplateTag(
- fileContent,
- CUSTOM_TYPES_TAG,
- Object.entries(augmentTypes).map(([typeName, constructorName]) => `"${typeName}": ${constructorName};`)
- )
- fs.writeFileSync(filePath, fileContent)
- }
- const addAugmentTypes = (typeName: string, constructorName: string) => {
- augmentTypes[typeName] = constructorName
- augmentTypes[`Option<${typeName}>`] = `Option<${constructorName}>`
- augmentTypes[`Vec<${typeName}>`] = `Vec<${constructorName}>`
- }
- console.log('Generating default interface types based on current @polkadot/types definitions...')
- generateInterfaceTypes({ '@polkadot/types/interfaces': defaultDefinitions }, OUTPUT_PATH)
- console.log('Adding custom Joystream types...')
- Object.entries(typesByModule).forEach(([moduleName, types]) => {
- console.log('Module: ', moduleName)
- console.log('Types found:', Object.keys(types))
- Object.entries(types).forEach(([typeName, codecOrName]) => {
- if (typeof codecOrName === 'function') {
- const constructorName = codecOrName.name
- if (!constructorName) {
- throw new Error(`Codec constructor doesn't have a name: ${typeName}`)
- }
- const normalizedTypeName = typeName.replace(/[^A-Za-z0-9_]/g, '_')
- // Add "as" to avoid namespace clashes
- const importStatement = `${constructorName} as ${normalizedTypeName}`
- !imports[moduleName] ? (imports[moduleName] = [importStatement]) : imports[moduleName].push(importStatement)
- addAugmentTypes(typeName, normalizedTypeName)
- } else if (typeof codecOrName === 'string') {
- addAugmentTypes(typeName, codecOrName)
- }
- })
- })
- updateAugmentTypesFile(OUTPUT_PATH, imports, augmentTypes)
|