From 0541ed8f37ec637cd31f586b3cf96323847771c3 Mon Sep 17 00:00:00 2001 From: notaphplover Date: Sat, 16 Sep 2023 12:43:42 +0200 Subject: [PATCH 1/3] feat(ajsttil): rename TypeMetadataKind.indexSignatureType to stringIndexSignatureType --- packages/transformers/ajsttil/src/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/transformers/ajsttil/src/index.ts b/packages/transformers/ajsttil/src/index.ts index ac000ba..eac6e30 100644 --- a/packages/transformers/ajsttil/src/index.ts +++ b/packages/transformers/ajsttil/src/index.ts @@ -6,13 +6,13 @@ export enum TypeMetadataKind { arrayType, booleanType, floatType, - indexSignatureType, integerType, literalType, noneType, objectType, or, propertyType, + stringIndexSignatureType, stringType, xor, } @@ -41,8 +41,6 @@ export type ArrayTypeMetadata = export type BooleanTypeMetadata = BaseTypeMetadata; export type FloatTypeMetadata = BaseTypeMetadata; -export type IndexSignatureType = - OneChildTypeMetadata; export type IntegerTypeMetadata = BaseTypeMetadata; export interface LiteralTypeMetadata @@ -57,6 +55,8 @@ export interface PropertyTypeMetadata isOptional: boolean; property: string; } +export type StringIndexSignatureType = + OneChildTypeMetadata; export type StringTypeMetadata = BaseTypeMetadata; export type XorTypeMetadata = ManyChildrenTypeMetadata; @@ -66,12 +66,12 @@ export type TypeMedatata = | ArrayTypeMetadata | BooleanTypeMetadata | FloatTypeMetadata - | IndexSignatureType | IntegerTypeMetadata | LiteralTypeMetadata | NoneTypeMetadata | ObjectTypeMetadata | OrTypeMetadata | PropertyTypeMetadata + | StringIndexSignatureType | StringTypeMetadata | XorTypeMetadata; From a07c1c78d00284e9685f80b43932a3cc46d6462f Mon Sep 17 00:00:00 2001 From: notaphplover Date: Sat, 16 Sep 2023 12:44:53 +0200 Subject: [PATCH 2/3] chore(json-schema-2-ajsttil): add jest config and test scripts --- .../json-schema-2-ajsttil/jest.config.mjs | 3 +++ .../json-schema-2-ajsttil/jest.js.config.mjs | 3 +++ .../transformers/json-schema-2-ajsttil/package.json | 12 +++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 packages/transformers/json-schema-2-ajsttil/jest.config.mjs create mode 100644 packages/transformers/json-schema-2-ajsttil/jest.js.config.mjs diff --git a/packages/transformers/json-schema-2-ajsttil/jest.config.mjs b/packages/transformers/json-schema-2-ajsttil/jest.config.mjs new file mode 100644 index 0000000..7de2952 --- /dev/null +++ b/packages/transformers/json-schema-2-ajsttil/jest.config.mjs @@ -0,0 +1,3 @@ +import { tsGlobalConfig } from '@cuaklabs/jest-config'; + +export default tsGlobalConfig; diff --git a/packages/transformers/json-schema-2-ajsttil/jest.js.config.mjs b/packages/transformers/json-schema-2-ajsttil/jest.js.config.mjs new file mode 100644 index 0000000..2496a9d --- /dev/null +++ b/packages/transformers/json-schema-2-ajsttil/jest.js.config.mjs @@ -0,0 +1,3 @@ +import { jsGlobalConfig } from '@cuaklabs/jest-config'; + +export default jsGlobalConfig; diff --git a/packages/transformers/json-schema-2-ajsttil/package.json b/packages/transformers/json-schema-2-ajsttil/package.json index 953d0af..ea81953 100644 --- a/packages/transformers/json-schema-2-ajsttil/package.json +++ b/packages/transformers/json-schema-2-ajsttil/package.json @@ -15,8 +15,12 @@ "eslint-plugin-import": "2.26.0", "eslint-plugin-jest": "27.4.0", "eslint-plugin-prettier": "5.0.0", + "jest": "29.6.4", + "jest-mock": "29.6.3", "prettier": "3.0.3", "rimraf": "5.0.1", + "ts-jest": "29.1.1", + "ts-node": "10.9.1", "typescript": "5.2.2" }, "bugs": { @@ -37,7 +41,13 @@ "build:clean": "rimraf lib", "format": "prettier --write ./src/**/*.ts", "lint": "eslint --ext ts --ignore-path .gitignore ./src", - "prebuild": "pnpm run build:clean" + "prebuild": "pnpm run build:clean", + "test:ts": "jest --config=jest.config.mjs --runInBand", + "test:integration": "pnpm run test --selectProjects Integration", + "test": "jest --config=jest.js.config.mjs --runInBand", + "test:coverage": "pnpm run test --coverage", + "test:uncommitted": "pnpm run test:ts --changedSince=HEAD", + "test:unit": "pnpm run test --selectProjects Unit" }, "version": "0.1.0" } From 9788467a22e27546e07c859be28df312c533a772 Mon Sep 17 00:00:00 2001 From: notaphplover Date: Sat, 16 Sep 2023 12:49:58 +0200 Subject: [PATCH 3/3] refactor(json-schema-2-ajsttil): add transformJsonSchema --- .../json-schema-2-ajsttil/CHANGELOG.md | 3 + .../json-schema-2-ajsttil/src/index.ts | 7 +- .../calculations/transformJsonSchema.spec.ts | 491 ++++++++++++++++++ .../calculations/transformJsonSchema.ts | 320 ++++++++++++ .../models/TransformJsonSchemaContext.ts | 10 + 5 files changed, 830 insertions(+), 1 deletion(-) create mode 100644 packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.spec.ts create mode 100644 packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.ts create mode 100644 packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/models/TransformJsonSchemaContext.ts diff --git a/packages/transformers/json-schema-2-ajsttil/CHANGELOG.md b/packages/transformers/json-schema-2-ajsttil/CHANGELOG.md index 6bbf1cf..2b9e8b3 100644 --- a/packages/transformers/json-schema-2-ajsttil/CHANGELOG.md +++ b/packages/transformers/json-schema-2-ajsttil/CHANGELOG.md @@ -21,5 +21,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [UNRELEASED] +### Added +- Added `transformJsonSchema`. + diff --git a/packages/transformers/json-schema-2-ajsttil/src/index.ts b/packages/transformers/json-schema-2-ajsttil/src/index.ts index cb0ff5c..3d9458a 100644 --- a/packages/transformers/json-schema-2-ajsttil/src/index.ts +++ b/packages/transformers/json-schema-2-ajsttil/src/index.ts @@ -1 +1,6 @@ -export {}; +import { transformJsonSchema } from './jsonSchema/202012/calculations/transformJsonSchema'; +import { TransformJsonSchemaContext } from './jsonSchema/202012/models/TransformJsonSchemaContext'; + +export type { TransformJsonSchemaContext }; + +export { transformJsonSchema }; diff --git a/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.spec.ts b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.spec.ts new file mode 100644 index 0000000..d47fad1 --- /dev/null +++ b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.spec.ts @@ -0,0 +1,491 @@ +import { beforeAll, describe, expect, it } from '@jest/globals'; + +import { + AndTypeMetadata, + TypeMedatata, + TypeMetadataKind, +} from '@cuaklabs/ajsttil'; +import { + JsonSchemaBoolean, + JsonSchemaObject, + jsonSchemaTypes, +} from '@cuaklabs/json-schema-types/2020-12'; + +import { TransformJsonSchemaContext } from '../models/TransformJsonSchemaContext'; +import { transformJsonSchema } from './transformJsonSchema'; + +function generateTransformJsonSchemaContext(): TransformJsonSchemaContext { + return { + jsonSchemaToTypeMap: new Map(), + referenceMap: new Map(), + }; +} + +describe(transformJsonSchema.name, () => { + describe.each<[JsonSchemaBoolean, TypeMedatata]>([ + [false, { kind: TypeMetadataKind.noneType }], + [true, { kind: TypeMetadataKind.anyType }], + ])( + 'having a boolean %s schema', + ( + jsonSchemaFixture: JsonSchemaBoolean, + expectedTypeMetadata: TypeMedatata, + ) => { + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + result = transformJsonSchema( + jsonSchemaFixture, + generateTransformJsonSchemaContext(), + ); + }); + + it('should return expected TypeMetadata', () => { + expect(result).toStrictEqual(expectedTypeMetadata); + }); + }); + }, + ); + + describe('having a self referenced JsonSchema', () => { + let uriFixture: string; + let jsonSchemaFixture: JsonSchemaObject; + + beforeAll(() => { + uriFixture = 'sample://uri/fixture'; + jsonSchemaFixture = { + $ref: uriFixture, + }; + }); + + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + const context: TransformJsonSchemaContext = + generateTransformJsonSchemaContext(); + + context.referenceMap.set(uriFixture, jsonSchemaFixture); + + result = transformJsonSchema(jsonSchemaFixture, context); + }); + + it('should return TypeMetadata', () => { + const expected: TypeMedatata = { + kind: TypeMetadataKind.anyType, + }; + + expect(result).toStrictEqual(expected); + }); + }); + }); + + describe('having a circular referenced JsonSchema with no other constraints', () => { + let uriFixture: string; + let childUriFixture: string; + let jsonSchemaFixture: JsonSchemaObject; + let childJsonSchemaFixture: JsonSchemaObject; + + beforeAll(() => { + childUriFixture = 'sample://uri/child'; + uriFixture = 'sample://uri/schema'; + jsonSchemaFixture = { + $ref: childUriFixture, + }; + childJsonSchemaFixture = { + $ref: uriFixture, + }; + }); + + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + const context: TransformJsonSchemaContext = + generateTransformJsonSchemaContext(); + + context.referenceMap.set(uriFixture, jsonSchemaFixture); + context.referenceMap.set(childUriFixture, childJsonSchemaFixture); + + result = transformJsonSchema(jsonSchemaFixture, context); + }); + + it('should return TypeMetadata', () => { + const expected: TypeMedatata = { + kind: TypeMetadataKind.anyType, + }; + + expect(result).toStrictEqual(expected); + }); + }); + }); + + describe('having a circular referenced JsonSchema with child additional constraints', () => { + let uriFixture: string; + let childUriFixture: string; + let jsonSchemaFixture: JsonSchemaObject; + let childJsonSchemaFixture: JsonSchemaObject; + + beforeAll(() => { + childUriFixture = 'sample://uri/child'; + uriFixture = 'sample://uri/schema'; + jsonSchemaFixture = { + $ref: childUriFixture, + }; + childJsonSchemaFixture = { + $ref: uriFixture, + type: jsonSchemaTypes.object, + }; + }); + + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + const context: TransformJsonSchemaContext = + generateTransformJsonSchemaContext(); + + context.referenceMap.set(uriFixture, jsonSchemaFixture); + context.referenceMap.set(childUriFixture, childJsonSchemaFixture); + + result = transformJsonSchema(jsonSchemaFixture, context); + }); + + it('should return TypeMetadata', () => { + const expected: AndTypeMetadata = { + children: [], + kind: TypeMetadataKind.and, + }; + expected.children.push(expected, { + kind: TypeMetadataKind.objectType, + }); + + expect(result).toStrictEqual(expected); + }); + }); + }); + + describe('having a circular referenced JsonSchema with parent and child additional constraints', () => { + let uriFixture: string; + let childUriFixture: string; + let jsonSchemaFixture: JsonSchemaObject; + let childJsonSchemaFixture: JsonSchemaObject; + + beforeAll(() => { + childUriFixture = 'sample://uri/child'; + uriFixture = 'sample://uri/schema'; + jsonSchemaFixture = { + $ref: childUriFixture, + properties: { + foo: { + type: jsonSchemaTypes.string, + }, + }, + type: jsonSchemaTypes.object, + }; + childJsonSchemaFixture = { + $ref: uriFixture, + properties: { + bar: { + type: jsonSchemaTypes.string, + }, + }, + type: jsonSchemaTypes.object, + }; + }); + + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + const context: TransformJsonSchemaContext = + generateTransformJsonSchemaContext(); + + context.referenceMap.set(uriFixture, jsonSchemaFixture); + context.referenceMap.set(childUriFixture, childJsonSchemaFixture); + + result = transformJsonSchema(jsonSchemaFixture, context); + }); + + it('should return TypeMetadata', () => { + const expected: AndTypeMetadata = { + children: [ + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'foo', + }, + ], + kind: TypeMetadataKind.and, + }; + + expected.children.push( + { + children: [ + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'bar', + }, + expected, + { + kind: TypeMetadataKind.objectType, + }, + ], + kind: TypeMetadataKind.and, + }, + { + kind: TypeMetadataKind.objectType, + }, + ); + + expect(result).toStrictEqual(expected); + }); + }); + }); + + describe.each<[string, JsonSchemaObject, TypeMedatata]>([ + ['any schema', {}, { kind: TypeMetadataKind.anyType }], + [ + 'an schema with additional properties', + { + additionalProperties: true, + }, + { + child: { + kind: TypeMetadataKind.anyType, + }, + kind: TypeMetadataKind.stringIndexSignatureType, + }, + ], + [ + 'an schema with allOf properties', + { + allOf: [ + { + properties: { + foo: { + type: jsonSchemaTypes.string, + }, + }, + }, + { + properties: { + bar: { + type: jsonSchemaTypes.string, + }, + }, + }, + ], + }, + { + children: [ + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'foo', + }, + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'bar', + }, + ], + kind: TypeMetadataKind.and, + }, + ], + [ + 'an schema with anyOf properties', + { + anyOf: [ + { + properties: { + foo: { + type: jsonSchemaTypes.string, + }, + }, + }, + { + properties: { + bar: { + type: jsonSchemaTypes.string, + }, + }, + }, + ], + }, + { + children: [ + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'foo', + }, + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'bar', + }, + ], + kind: TypeMetadataKind.or, + }, + ], + [ + 'an schema with oneOf properties', + { + oneOf: [ + { + properties: { + foo: { + type: jsonSchemaTypes.string, + }, + }, + }, + { + properties: { + bar: { + type: jsonSchemaTypes.string, + }, + }, + }, + ], + }, + { + children: [ + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'foo', + }, + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: true, + kind: TypeMetadataKind.propertyType, + property: 'bar', + }, + ], + kind: TypeMetadataKind.xor, + }, + ], + [ + 'an schema with const', + { + const: { foo: 'bar' }, + }, + { + kind: TypeMetadataKind.literalType, + literal: { foo: 'bar' }, + }, + ], + [ + 'an schema with enum', + { + enum: ['foo', 'bar'], + }, + { + children: [ + { + kind: TypeMetadataKind.literalType, + literal: 'foo', + }, + { + kind: TypeMetadataKind.literalType, + literal: 'bar', + }, + ], + kind: TypeMetadataKind.or, + }, + ], + [ + 'an schema with items', + { + items: { + type: jsonSchemaTypes.string, + }, + }, + { + children: [ + { + child: { kind: TypeMetadataKind.stringType }, + kind: TypeMetadataKind.arrayType, + }, + { + kind: TypeMetadataKind.floatType, + }, + { + kind: TypeMetadataKind.objectType, + }, + { + kind: TypeMetadataKind.stringType, + }, + ], + kind: TypeMetadataKind.or, + }, + ], + [ + 'an schema with properties and required', + { + properties: { + foo: { + type: jsonSchemaTypes.string, + }, + }, + required: ['foo'], + }, + { + child: { + kind: TypeMetadataKind.stringType, + }, + isOptional: false, + kind: TypeMetadataKind.propertyType, + property: 'foo', + }, + ], + ])( + 'having %s', + ( + _: string, + jsonSchemaFixture: JsonSchemaObject, + expectedTypeMetadata: TypeMedatata, + ) => { + describe('when called', () => { + let result: unknown; + + beforeAll(() => { + result = transformJsonSchema( + jsonSchemaFixture, + generateTransformJsonSchemaContext(), + ); + }); + + it('should return expected TypeMetadata', () => { + expect(result).toStrictEqual(expectedTypeMetadata); + }); + }); + }, + ); +}); diff --git a/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.ts b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.ts new file mode 100644 index 0000000..96332c6 --- /dev/null +++ b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/calculations/transformJsonSchema.ts @@ -0,0 +1,320 @@ +import { TypeMedatata, TypeMetadataKind } from '@cuaklabs/ajsttil'; +import { JsonValue } from '@cuaklabs/json-schema-types'; +import { + JsonRootSchema, + JsonSchema, + JsonSchemaBoolean, + JsonSchemaObject, + JsonSchemaType, + jsonSchemaTypes, +} from '@cuaklabs/json-schema-types/2020-12'; + +import { TransformJsonSchemaContext } from '../models/TransformJsonSchemaContext'; + +export function transformJsonSchema( + schema: JsonRootSchema | JsonSchema, + context: TransformJsonSchemaContext, +): TypeMedatata { + if (typeof schema === 'boolean') { + return transformBooleanJsonSchema(schema); + } else { + return transformObjectJsonSchema(schema, context); + } +} + +function buildTypeMetadata( + id: string | undefined, + typeMetadataPartial: Partial, + typeConstraints: TypeMedatata[], +): TypeMedatata { + if (id !== undefined) { + typeMetadataPartial.id = id; + } + + let typeMetadata: TypeMedatata; + + if (typeConstraints.length === 0) { + typeMetadata = { + kind: TypeMetadataKind.anyType, + }; + } else { + if (typeConstraints.length === 1) { + const childType: Partial | TypeMedatata = + typeConstraints[0] as TypeMedatata; + + if (childType.kind === undefined) { + /* + * Tricky edge case in which a circular reference is found. + * Any is returned as no constraints were found so far. + */ + typeMetadata = { + kind: TypeMetadataKind.anyType, + }; + } else { + typeMetadata = childType as TypeMedatata; + } + } else { + typeMetadata = { + children: typeConstraints, + kind: TypeMetadataKind.and, + }; + } + } + + const typeMetadataResult: TypeMedatata = Object.assign< + Partial, + TypeMedatata + >(typeMetadataPartial, typeMetadata); + + return typeMetadataResult; +} + +function handleApplicatorVocabularyProperties( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + handleJsonSchemaChildren(schema, context, typeConstraints); + handleJsonSchemaProperties(schema, context, typeConstraints); + handleJsonSchemaSubschemas(schema, context, typeConstraints); +} + +function handleCoreVocabularyProperties( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + handleJsonSchemaRef(schema, context, typeConstraints); +} + +function handleJsonSchemaChildren( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + if (schema.items !== undefined) { + typeConstraints.push({ + children: [ + { + child: transformJsonSchema(schema.items, context), + kind: TypeMetadataKind.arrayType, + }, + { + kind: TypeMetadataKind.floatType, + }, + { + kind: TypeMetadataKind.objectType, + }, + { + kind: TypeMetadataKind.stringType, + }, + ], + kind: TypeMetadataKind.or, + }); + } +} + +function handleJsonSchemaAdditionalProperties( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + if (schema.additionalProperties !== undefined) { + typeConstraints.push({ + child: transformJsonSchema(schema.additionalProperties, context), + kind: TypeMetadataKind.stringIndexSignatureType, + }); + } +} + +function handleJsonSchemaProperties( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + handleJsonSchemaAdditionalProperties(schema, context, typeConstraints); + + if (schema.properties !== undefined) { + for (const propertyName in schema.properties) { + const propertySchema: JsonSchema = schema.properties[ + propertyName + ] as JsonSchema; + + const isOptional: boolean = isPropertyOptional(schema, propertyName); + + typeConstraints.push({ + child: transformJsonSchema(propertySchema, context), + isOptional, + kind: TypeMetadataKind.propertyType, + property: propertyName, + }); + } + } +} + +function handleJsonSchemaRef( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + if (schema.$ref !== undefined) { + const dereferencedSchema: JsonSchema | undefined = context.referenceMap.get( + schema.$ref, + ); + + if (dereferencedSchema === undefined) { + throw new Error(`Unable to resolve "${schema.$ref}" $ref`); + } + + typeConstraints.push(transformJsonSchema(dereferencedSchema, context)); + } +} + +function handleJsonSchemaSubschemas( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, + typeConstraints: TypeMedatata[], +): void { + if (schema.allOf !== undefined) { + typeConstraints.push({ + children: schema.allOf.map((schema: JsonSchema) => + transformJsonSchema(schema, context), + ), + kind: TypeMetadataKind.and, + }); + } + + if (schema.anyOf !== undefined) { + typeConstraints.push({ + children: schema.anyOf.map((schema: JsonSchema) => + transformJsonSchema(schema, context), + ), + kind: TypeMetadataKind.or, + }); + } + + if (schema.oneOf !== undefined) { + typeConstraints.push({ + children: schema.oneOf.map((schema: JsonSchema) => + transformJsonSchema(schema, context), + ), + kind: TypeMetadataKind.xor, + }); + } +} + +function handleValidationVocabularyProperties( + schema: JsonSchemaObject, + typeConstraints: TypeMedatata[], +): void { + if (schema.const !== undefined) { + typeConstraints.push({ + kind: TypeMetadataKind.literalType, + literal: schema.const, + }); + } + + if (schema.enum !== undefined) { + typeConstraints.push({ + children: schema.enum.map((enumValue: JsonValue) => ({ + kind: TypeMetadataKind.literalType, + literal: enumValue, + })), + kind: TypeMetadataKind.or, + }); + } + + if (schema.type !== undefined) { + if (Array.isArray(schema.type)) { + typeConstraints.push({ + children: schema.type.map((schemaType: JsonSchemaType) => + transformJsonSchemaType(schemaType), + ), + kind: TypeMetadataKind.or, + }); + } else { + typeConstraints.push(transformJsonSchemaType(schema.type)); + } + } +} + +function isPropertyOptional( + schema: JsonSchemaObject, + propertyName: string, +): boolean { + return !(schema.required?.includes(propertyName) ?? false); +} + +function transformBooleanJsonSchema(schema: JsonSchemaBoolean): TypeMedatata { + if (schema) { + return { + kind: TypeMetadataKind.anyType, + }; + } else { + return { + kind: TypeMetadataKind.noneType, + }; + } +} + +function transformObjectJsonSchema( + schema: JsonSchemaObject, + context: TransformJsonSchemaContext, +): TypeMedatata { + const existingType: TypeMedatata | undefined = + context.jsonSchemaToTypeMap.get(schema); + + if (existingType !== undefined) { + return existingType; + } + + const typeMetadataPartial: Partial = {}; + context.jsonSchemaToTypeMap.set(schema, typeMetadataPartial as TypeMedatata); + + const id: string | undefined = schema.title; + + const typeConstraints: TypeMedatata[] = []; + + handleApplicatorVocabularyProperties(schema, context, typeConstraints); + handleCoreVocabularyProperties(schema, context, typeConstraints); + handleValidationVocabularyProperties(schema, typeConstraints); + + return buildTypeMetadata(id, typeMetadataPartial, typeConstraints); +} + +function transformJsonSchemaType(schemaType: JsonSchemaType): TypeMedatata { + switch (schemaType) { + case jsonSchemaTypes.array: + return { + child: { + kind: TypeMetadataKind.anyType, + }, + kind: TypeMetadataKind.arrayType, + }; + case jsonSchemaTypes.boolean: + return { + kind: TypeMetadataKind.booleanType, + }; + case jsonSchemaTypes.integer: + return { + kind: TypeMetadataKind.integerType, + }; + case jsonSchemaTypes.null: + return { + kind: TypeMetadataKind.literalType, + literal: null, + }; + case jsonSchemaTypes.number: + return { + kind: TypeMetadataKind.floatType, + }; + case jsonSchemaTypes.object: + return { + kind: TypeMetadataKind.objectType, + }; + case jsonSchemaTypes.string: + return { + kind: TypeMetadataKind.stringType, + }; + } +} diff --git a/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/models/TransformJsonSchemaContext.ts b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/models/TransformJsonSchemaContext.ts new file mode 100644 index 0000000..a552a79 --- /dev/null +++ b/packages/transformers/json-schema-2-ajsttil/src/jsonSchema/202012/models/TransformJsonSchemaContext.ts @@ -0,0 +1,10 @@ +import { TypeMedatata } from '@cuaklabs/ajsttil'; +import { + JsonRootSchema, + JsonSchema, +} from '@cuaklabs/json-schema-types/2020-12'; + +export interface TransformJsonSchemaContext { + jsonSchemaToTypeMap: Map; + referenceMap: Map; +}