inputSchemasToEntitySchemas.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import fs from 'fs'
  2. import path from 'path'
  3. import {
  4. AddClassSchema,
  5. HashProperty,
  6. Property,
  7. ReferenceProperty,
  8. SinglePropertyVariant,
  9. TextProperty,
  10. VecPropertyVariant,
  11. } from '../types/extrinsics/AddClassSchema'
  12. import PRIMITIVE_PROPERTY_DEFS from '../schemas/propertyValidationDefs.schema.json'
  13. import { getInputs } from './helpers/inputs'
  14. import { JSONSchema7 } from 'json-schema'
  15. const SINGLE_ENTITY_SCHEMAS_LOCATION = path.join(__dirname, '../schemas/entities')
  16. const BATCH_OF_ENITIES_SCHEMAS_LOCATION = path.join(__dirname, '../schemas/entityBatches')
  17. const ENTITY_REFERENCE_SCHEMAS_LOCATION = path.join(__dirname, '../schemas/entityReferences')
  18. const schemaInputs = getInputs<AddClassSchema>('schemas')
  19. const strictObjectDef = (def: Record<string, any>): JSONSchema7 => ({
  20. type: 'object',
  21. additionalProperties: false,
  22. ...def,
  23. })
  24. const onePropertyObjectDef = (propertyName: string, propertyDef: Record<string, any>): JSONSchema7 =>
  25. strictObjectDef({
  26. required: [propertyName],
  27. properties: {
  28. [propertyName]: propertyDef,
  29. },
  30. })
  31. const TextPropertyDef = ({ Text: maxLength }: TextProperty): JSONSchema7 => ({
  32. type: 'string',
  33. maxLength,
  34. })
  35. const HashPropertyDef = ({ Hash: maxLength }: HashProperty): JSONSchema7 => ({
  36. type: 'string',
  37. maxLength,
  38. })
  39. const ReferencePropertyDef = ({ Reference: ref }: ReferenceProperty): JSONSchema7 => ({
  40. 'oneOf': [
  41. onePropertyObjectDef('new', { '$ref': `./${ref.className}Entity.schema.json` }),
  42. onePropertyObjectDef('existing', { '$ref': `../entityReferences/${ref.className}Ref.schema.json` }),
  43. ],
  44. })
  45. const SinglePropertyDef = ({ Single: singlePropType }: SinglePropertyVariant): JSONSchema7 => {
  46. if (typeof singlePropType === 'string') {
  47. return PRIMITIVE_PROPERTY_DEFS.definitions[singlePropType] as JSONSchema7
  48. } else if ((singlePropType as TextProperty).Text) {
  49. return TextPropertyDef(singlePropType as TextProperty)
  50. } else if ((singlePropType as HashProperty).Hash) {
  51. return HashPropertyDef(singlePropType as HashProperty)
  52. } else if ((singlePropType as ReferenceProperty).Reference) {
  53. return ReferencePropertyDef(singlePropType as ReferenceProperty)
  54. }
  55. throw new Error(`Unknown single proprty type: ${JSON.stringify(singlePropType)}`)
  56. }
  57. const VecPropertyDef = ({ Vector: vec }: VecPropertyVariant): JSONSchema7 => ({
  58. type: 'array',
  59. maxItems: vec.max_length,
  60. 'items': SinglePropertyDef({ Single: vec.vec_type }),
  61. })
  62. const PropertyDef = ({ property_type: propertyType, description }: Property): JSONSchema7 => ({
  63. ...((propertyType as SinglePropertyVariant).Single
  64. ? SinglePropertyDef(propertyType as SinglePropertyVariant)
  65. : VecPropertyDef(propertyType as VecPropertyVariant)),
  66. description,
  67. })
  68. // Mkdir entity schemas directories if they do not exist
  69. const entitySchemasDirs = [
  70. SINGLE_ENTITY_SCHEMAS_LOCATION,
  71. BATCH_OF_ENITIES_SCHEMAS_LOCATION,
  72. ENTITY_REFERENCE_SCHEMAS_LOCATION,
  73. ]
  74. entitySchemasDirs.forEach((dir) => {
  75. if (!fs.existsSync(dir)) {
  76. fs.mkdirSync(dir)
  77. }
  78. })
  79. // Run schema conversion:
  80. schemaInputs.forEach(({ fileName, data: inputData }) => {
  81. const schemaName = fileName.replace('Schema.json', '')
  82. if (inputData.newProperties && !inputData.existingProperties) {
  83. const properites = inputData.newProperties
  84. const propertiesObj = properites.reduce((pObj, p) => {
  85. pObj[p.name] = PropertyDef(p)
  86. return pObj
  87. }, {} as Record<string, ReturnType<typeof PropertyDef>>)
  88. const EntitySchema: JSONSchema7 = {
  89. $schema: 'http://json-schema.org/draft-07/schema',
  90. $id: `https://joystream.org/entities/${schemaName}Entity.schema.json`,
  91. title: `${schemaName}Entity`,
  92. description: `JSON schema for entities based on ${schemaName} runtime schema`,
  93. ...strictObjectDef({
  94. required: properites.filter((p) => p.required).map((p) => p.name),
  95. properties: propertiesObj,
  96. }),
  97. }
  98. const ReferenceSchema: JSONSchema7 = {
  99. $schema: 'http://json-schema.org/draft-07/schema',
  100. $id: `https://joystream.org/entityReferences/${schemaName}Ref.schema.json`,
  101. title: `${schemaName}Reference`,
  102. description: `JSON schema for reference to ${schemaName} entity based on runtime schema`,
  103. anyOf: [
  104. ...properites.filter((p) => p.required && p.unique).map((p) => onePropertyObjectDef(p.name, PropertyDef(p))),
  105. PRIMITIVE_PROPERTY_DEFS.definitions.Uint64 as JSONSchema7,
  106. ],
  107. }
  108. const BatchSchema: JSONSchema7 = {
  109. $schema: 'http://json-schema.org/draft-07/schema',
  110. $id: `https://joystream.org/entityBatches/${schemaName}Batch.schema.json`,
  111. title: `${schemaName}Batch`,
  112. description: `JSON schema for batch of entities based on ${schemaName} runtime schema`,
  113. ...strictObjectDef({
  114. required: ['className', 'entries'],
  115. properties: {
  116. className: { type: 'string' },
  117. entries: {
  118. type: 'array',
  119. items: { '$ref': `../entities/${schemaName}Entity.schema.json` },
  120. },
  121. },
  122. }),
  123. }
  124. const entitySchemaPath = path.join(SINGLE_ENTITY_SCHEMAS_LOCATION, `${schemaName}Entity.schema.json`)
  125. fs.writeFileSync(entitySchemaPath, JSON.stringify(EntitySchema, undefined, 4))
  126. console.log(`${entitySchemaPath} succesfully generated!`)
  127. const entityReferenceSchemaPath = path.join(ENTITY_REFERENCE_SCHEMAS_LOCATION, `${schemaName}Ref.schema.json`)
  128. fs.writeFileSync(entityReferenceSchemaPath, JSON.stringify(ReferenceSchema, undefined, 4))
  129. console.log(`${entityReferenceSchemaPath} succesfully generated!`)
  130. const batchOfEntitiesSchemaPath = path.join(BATCH_OF_ENITIES_SCHEMAS_LOCATION, `${schemaName}Batch.schema.json`)
  131. fs.writeFileSync(batchOfEntitiesSchemaPath, JSON.stringify(BatchSchema, undefined, 4))
  132. console.log(`${batchOfEntitiesSchemaPath} succesfully generated!`)
  133. } else {
  134. console.log('WARNING: Schemas with "existingProperties" not supported yet!')
  135. console.log('Skipping...')
  136. }
  137. })