@mat3ra/esse 2026.8.18-0 → 2026.8.18-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/js/esse/JSONSchemasGenerator.d.ts +21 -0
- package/dist/js/esse/JSONSchemasGenerator.js +72 -0
- package/dist/js/esse/JSONSchemasInterface.d.ts +48 -0
- package/dist/js/esse/JSONSchemasInterface.js +80 -0
- package/dist/js/esse/JSONSchemasInterfaceServer.d.ts +9 -0
- package/dist/js/esse/JSONSchemasInterfaceServer.js +45 -0
- package/dist/js/esse/schemaUtils.d.ts +4 -0
- package/dist/js/esse/schemaUtils.js +16 -0
- package/dist/js/esse/server/utils.d.ts +12 -0
- package/dist/js/esse/server/utils.js +67 -0
- package/dist/js/esse/settings.d.ts +3 -0
- package/dist/js/esse/settings.js +10 -0
- package/dist/js/esse/types.d.ts +3 -0
- package/dist/js/esse/types.js +2 -0
- package/dist/js/esse/utils.d.ts +5 -0
- package/dist/js/esse/utils.js +51 -0
- package/dist/js/json_include/index.d.ts +22 -0
- package/dist/js/json_include/index.js +75 -0
- package/dist/js/json_include/settings.d.ts +3 -0
- package/dist/js/json_include/settings.js +6 -0
- package/dist/js/scripts/compileTs.d.ts +1 -0
- package/dist/js/scripts/compileTs.js +80 -0
- package/dist/js/scripts/createEnumsFromYaml.d.ts +1 -0
- package/dist/js/scripts/createEnumsFromYaml.js +28 -0
- package/dist/js/scripts/setSchemaIds.d.ts +5 -0
- package/dist/js/scripts/setSchemaIds.js +30 -0
- package/dist/js/types.d.ts +80178 -0
- package/dist/js/types.js +91 -0
- package/dist/js/utils/ajv.d.ts +34 -0
- package/dist/js/utils/ajv.js +125 -0
- package/dist/js/utils/ajvKeywords/jsonSchemaToTypescriptKeywords.d.ts +7 -0
- package/dist/js/utils/ajvKeywords/jsonSchemaToTypescriptKeywords.js +21 -0
- package/dist/js/utils/common.d.ts +6 -0
- package/dist/js/utils/common.js +14 -0
- package/dist/js/utils/filesystem.d.ts +2 -0
- package/dist/js/utils/filesystem.js +37 -0
- package/dist/js/utils/removeEmptyAndNullProperties.d.ts +9 -0
- package/dist/js/utils/removeEmptyAndNullProperties.js +29 -0
- package/package.json +3 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { JSONSchemaWithPath } from "./server/utils";
|
|
2
|
+
import type { JSONSchema } from "./utils";
|
|
3
|
+
interface JSONSchemasGeneratorConfig {
|
|
4
|
+
schemasDir: string;
|
|
5
|
+
examplesDir?: string;
|
|
6
|
+
propertiesManifestDir?: string;
|
|
7
|
+
}
|
|
8
|
+
export default class JSONSchemasGenerator implements JSONSchemasGeneratorConfig {
|
|
9
|
+
readonly schemas: JSONSchema[];
|
|
10
|
+
readonly examples?: JSONSchema[];
|
|
11
|
+
readonly wrappedExamples: JSONSchemaWithPath[];
|
|
12
|
+
readonly propertiesManifest: object;
|
|
13
|
+
readonly results: object;
|
|
14
|
+
readonly schemasDir: string;
|
|
15
|
+
readonly examplesDir?: string;
|
|
16
|
+
readonly propertiesManifestDir?: string;
|
|
17
|
+
constructor(config?: JSONSchemasGeneratorConfig);
|
|
18
|
+
writeResolvedSchemas(subfolder: string, skipMergeAllOff?: boolean): void;
|
|
19
|
+
writeResolvedExamples(subfolder: string): void;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
9
|
+
const json_schema_merge_allof_1 = __importDefault(require("json-schema-merge-allof"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const utils_1 = require("./server/utils");
|
|
12
|
+
const settings_1 = require("./settings");
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
schemasDir: settings_1.SCHEMAS_DIR,
|
|
15
|
+
examplesDir: settings_1.EXAMPLES_DIR,
|
|
16
|
+
propertiesManifestDir: settings_1.PROPERTIES_MANIFEST_PATH,
|
|
17
|
+
};
|
|
18
|
+
class JSONSchemasGenerator {
|
|
19
|
+
constructor(config = DEFAULT_CONFIG) {
|
|
20
|
+
this.schemasDir = config.schemasDir;
|
|
21
|
+
this.examplesDir = config.examplesDir;
|
|
22
|
+
this.propertiesManifestDir = config.propertiesManifestDir;
|
|
23
|
+
this.schemas = (0, utils_1.parseIncludeReferenceStatementsByDir)(this.schemasDir);
|
|
24
|
+
this.wrappedExamples = this.examplesDir
|
|
25
|
+
? (0, utils_1.parseIncludeReferenceStatementsByDir)(this.examplesDir, true)
|
|
26
|
+
: [];
|
|
27
|
+
this.examples = this.wrappedExamples.map((example) => example.data);
|
|
28
|
+
this.propertiesManifest = this.propertiesManifestDir
|
|
29
|
+
? js_yaml_1.default.load(fs_1.default.readFileSync(this.propertiesManifestDir, "utf-8"))
|
|
30
|
+
: {};
|
|
31
|
+
this.results = Object.entries(this.propertiesManifest)
|
|
32
|
+
.map((k) => (k[1].isResult ? k[0] : null))
|
|
33
|
+
.filter((x) => x);
|
|
34
|
+
}
|
|
35
|
+
writeResolvedSchemas(subfolder, skipMergeAllOff = false) {
|
|
36
|
+
const schemasFolder = `${subfolder}/schema`;
|
|
37
|
+
fs_1.default.rmSync(schemasFolder, { recursive: true, force: true });
|
|
38
|
+
const mergeAllOfConfig = {
|
|
39
|
+
resolvers: { defaultResolver: json_schema_merge_allof_1.default.options.resolvers.title },
|
|
40
|
+
};
|
|
41
|
+
const schemas = this.schemas.map((schema) => {
|
|
42
|
+
console.log(`Resolving schema: ${schema.$id}`);
|
|
43
|
+
const mergedSchema = skipMergeAllOff ? schema : (0, json_schema_merge_allof_1.default)(schema, mergeAllOfConfig);
|
|
44
|
+
let idAsPath = mergedSchema.$id;
|
|
45
|
+
if (!idAsPath) {
|
|
46
|
+
throw new Error(`Schema ID is missing:
|
|
47
|
+
${JSON.stringify(mergedSchema)}`);
|
|
48
|
+
}
|
|
49
|
+
const schemaHasDash = idAsPath.includes("-");
|
|
50
|
+
if (schemaHasDash) {
|
|
51
|
+
// replace dashes with underscores
|
|
52
|
+
idAsPath = idAsPath.replace(/-/g, "_");
|
|
53
|
+
}
|
|
54
|
+
const fullPath = `${schemasFolder}/${idAsPath}.json`;
|
|
55
|
+
fs_1.default.mkdirSync(path_1.default.dirname(fullPath), { recursive: true });
|
|
56
|
+
fs_1.default.writeFileSync(fullPath, JSON.stringify(mergedSchema, null, 4), "utf8");
|
|
57
|
+
return mergedSchema;
|
|
58
|
+
});
|
|
59
|
+
fs_1.default.writeFileSync(`${subfolder}/schemas.json`, `${JSON.stringify(schemas)}`);
|
|
60
|
+
}
|
|
61
|
+
writeResolvedExamples(subfolder) {
|
|
62
|
+
const examplesFolder = `${subfolder}/example`;
|
|
63
|
+
fs_1.default.rmSync(`${examplesFolder}`, { recursive: true, force: true });
|
|
64
|
+
this.wrappedExamples.forEach((e) => {
|
|
65
|
+
const idAsPath = e.path.replace(/-/g, "_");
|
|
66
|
+
const fullPath = `${examplesFolder}/${idAsPath}.json`;
|
|
67
|
+
fs_1.default.mkdirSync(path_1.default.dirname(fullPath), { recursive: true });
|
|
68
|
+
fs_1.default.writeFileSync(fullPath, JSON.stringify(e.data, null, 4), "utf8");
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.default = JSONSchemasGenerator;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type JSONSchema } from "./utils";
|
|
2
|
+
export type JSONSchemasInterfaceQuery = {
|
|
3
|
+
[key in keyof JSONSchema]: {
|
|
4
|
+
$regex: string;
|
|
5
|
+
};
|
|
6
|
+
};
|
|
7
|
+
export default class JSONSchemasInterface {
|
|
8
|
+
static schemasCache: Map<string, import("json-schema").JSONSchema7>;
|
|
9
|
+
static setSchemas(schema: JSONSchema[]): void;
|
|
10
|
+
static addSchema(schema: JSONSchema): void;
|
|
11
|
+
static getSchemaById(schemaId: string): import("json-schema").JSONSchema7 | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Like {@link getSchemaById}, but throws if the schema is not registered.
|
|
14
|
+
*/
|
|
15
|
+
static getRequiredSchemaById(schemaId: string): JSONSchema;
|
|
16
|
+
/**
|
|
17
|
+
* @example <caption>Search by $id regex</caption>
|
|
18
|
+
* JSONSchemasInterface.matchSchema({
|
|
19
|
+
* $id: {
|
|
20
|
+
* $regex: 'software-application'
|
|
21
|
+
* }
|
|
22
|
+
* })
|
|
23
|
+
*
|
|
24
|
+
* @example <caption>Search by $id and title regex</caption>
|
|
25
|
+
* JSONSchemasInterface.matchSchema({
|
|
26
|
+
* $id: {
|
|
27
|
+
* $regex: 'software-application'
|
|
28
|
+
* },
|
|
29
|
+
* title: {
|
|
30
|
+
* $regex: 'application'
|
|
31
|
+
* }
|
|
32
|
+
* })
|
|
33
|
+
*/
|
|
34
|
+
static matchSchema(query: JSONSchemasInterfaceQuery): import("json-schema").JSONSchema7 | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Get a patched copy of a schema without modifying the cached version
|
|
37
|
+
* @param schemaId - The ID of the schema to patch
|
|
38
|
+
* @param propertyPatches - Object with property names as keys and patch objects as values
|
|
39
|
+
* @returns A new schema with patched properties
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* JSONSchemasInterface.getPatchedSchema("boundary-conditions-provider", {
|
|
43
|
+
* type: { default: "pbc" },
|
|
44
|
+
* offset: { default: 0 }
|
|
45
|
+
* });
|
|
46
|
+
*/
|
|
47
|
+
static getPatchedSchemaById(schemaId: string, patchConfig: Record<string, unknown>): JSONSchema | undefined;
|
|
48
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("./utils");
|
|
4
|
+
class JSONSchemasInterface {
|
|
5
|
+
static setSchemas(schema) {
|
|
6
|
+
schema.forEach((schema) => this.addSchema(schema));
|
|
7
|
+
}
|
|
8
|
+
static addSchema(schema) {
|
|
9
|
+
if (schema.$id) {
|
|
10
|
+
this.schemasCache.set(schema.$id, schema);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
static getSchemaById(schemaId) {
|
|
14
|
+
return this.schemasCache.get(schemaId);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Like {@link getSchemaById}, but throws if the schema is not registered.
|
|
18
|
+
*/
|
|
19
|
+
static getRequiredSchemaById(schemaId) {
|
|
20
|
+
const schema = this.getSchemaById(schemaId);
|
|
21
|
+
if (!schema) {
|
|
22
|
+
throw new Error(`ESSE schema not found: ${schemaId}`);
|
|
23
|
+
}
|
|
24
|
+
return schema;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @example <caption>Search by $id regex</caption>
|
|
28
|
+
* JSONSchemasInterface.matchSchema({
|
|
29
|
+
* $id: {
|
|
30
|
+
* $regex: 'software-application'
|
|
31
|
+
* }
|
|
32
|
+
* })
|
|
33
|
+
*
|
|
34
|
+
* @example <caption>Search by $id and title regex</caption>
|
|
35
|
+
* JSONSchemasInterface.matchSchema({
|
|
36
|
+
* $id: {
|
|
37
|
+
* $regex: 'software-application'
|
|
38
|
+
* },
|
|
39
|
+
* title: {
|
|
40
|
+
* $regex: 'application'
|
|
41
|
+
* }
|
|
42
|
+
* })
|
|
43
|
+
*/
|
|
44
|
+
static matchSchema(query) {
|
|
45
|
+
const searchFields = Object.keys(query);
|
|
46
|
+
return Array.from(this.schemasCache.values()).find((schema) => {
|
|
47
|
+
return searchFields.every((field) => {
|
|
48
|
+
const queryField = query[field];
|
|
49
|
+
const schemaField = schema[field];
|
|
50
|
+
if (!queryField || typeof schemaField !== "string") {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
return new RegExp(queryField.$regex).test(schemaField);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get a patched copy of a schema without modifying the cached version
|
|
59
|
+
* @param schemaId - The ID of the schema to patch
|
|
60
|
+
* @param propertyPatches - Object with property names as keys and patch objects as values
|
|
61
|
+
* @returns A new schema with patched properties
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* JSONSchemasInterface.getPatchedSchema("boundary-conditions-provider", {
|
|
65
|
+
* type: { default: "pbc" },
|
|
66
|
+
* offset: { default: 0 }
|
|
67
|
+
* });
|
|
68
|
+
*/
|
|
69
|
+
static getPatchedSchemaById(schemaId, patchConfig) {
|
|
70
|
+
const baseSchema = this.getSchemaById(schemaId);
|
|
71
|
+
if (!baseSchema) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const patchedSchema = JSON.parse(JSON.stringify(baseSchema));
|
|
75
|
+
(0, utils_1.applyPatchTree)(patchedSchema, patchConfig, []);
|
|
76
|
+
return patchedSchema;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
JSONSchemasInterface.schemasCache = new Map();
|
|
80
|
+
exports.default = JSONSchemasInterface;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SchemaObject } from "ajv";
|
|
2
|
+
import JSONSchemasInterface from "./JSONSchemasInterface";
|
|
3
|
+
export declare function readSchemaFolderSync(folderPath: string): SchemaObject[];
|
|
4
|
+
export default class JSONSchemasInterfaceServer extends JSONSchemasInterface {
|
|
5
|
+
static schemaFolder: string;
|
|
6
|
+
static setSchemaFolder(schemaFolder: string): void;
|
|
7
|
+
static readSchemaFolder(): void;
|
|
8
|
+
static getSchemaById(schemaId: string): import("json-schema").JSONSchema7 | undefined;
|
|
9
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.readSchemaFolderSync = readSchemaFolderSync;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const filesystem_1 = require("../utils/filesystem");
|
|
10
|
+
const JSONSchemasInterface_1 = __importDefault(require("./JSONSchemasInterface"));
|
|
11
|
+
function readSchemaFolderSync(folderPath) {
|
|
12
|
+
const schemas = [];
|
|
13
|
+
(0, filesystem_1.walkDirSync)(folderPath, (filePath) => {
|
|
14
|
+
if (path_1.default.extname(filePath) !== ".json") {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const schema = JSON.parse(fs_1.default.readFileSync(filePath).toString());
|
|
18
|
+
schemas.push(schema);
|
|
19
|
+
});
|
|
20
|
+
return schemas;
|
|
21
|
+
}
|
|
22
|
+
class JSONSchemasInterfaceServer extends JSONSchemasInterface_1.default {
|
|
23
|
+
static setSchemaFolder(schemaFolder) {
|
|
24
|
+
if (this.schemaFolder !== schemaFolder) {
|
|
25
|
+
this.schemaFolder = schemaFolder;
|
|
26
|
+
this.readSchemaFolder();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
static readSchemaFolder() {
|
|
30
|
+
const schemas = readSchemaFolderSync(this.schemaFolder);
|
|
31
|
+
schemas.forEach((schema) => {
|
|
32
|
+
if (schema.$id) {
|
|
33
|
+
this.schemasCache.set(schema.$id, schema);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
static getSchemaById(schemaId) {
|
|
38
|
+
if (this.schemasCache.size === 0) {
|
|
39
|
+
this.readSchemaFolder();
|
|
40
|
+
}
|
|
41
|
+
return super.getSchemaById(schemaId);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
JSONSchemasInterfaceServer.schemaFolder = path_1.default.resolve(__dirname, "./../schema");
|
|
45
|
+
exports.default = JSONSchemasInterfaceServer;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { JSONSchema, JSONSchemaDefinition } from "./utils";
|
|
2
|
+
export type MapSchema = (prop: JSONSchemaDefinition) => JSONSchemaDefinition | undefined;
|
|
3
|
+
export declare function mapObjectDeep(object: JSONSchemaDefinition, mapValue: MapSchema): JSONSchema;
|
|
4
|
+
export declare function mapObjectDeep(object: JSONSchemaDefinition[], mapValue: MapSchema): JSONSchema[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapObjectDeep = mapObjectDeep;
|
|
4
|
+
function mapObjectDeep(object, mapValue) {
|
|
5
|
+
if (typeof object !== "object" || object === null) {
|
|
6
|
+
return object;
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(object)) {
|
|
9
|
+
return object.map((innerValue) => mapObjectDeep(innerValue, mapValue));
|
|
10
|
+
}
|
|
11
|
+
const mappedObject = mapValue(object) || object;
|
|
12
|
+
const entries = Object.entries(mappedObject).map(([key, value]) => {
|
|
13
|
+
return [key, mapObjectDeep(value, mapValue)];
|
|
14
|
+
});
|
|
15
|
+
return Object.fromEntries(entries);
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { JSONSchema } from "../utils";
|
|
2
|
+
export interface JSONSchemaWithPath {
|
|
3
|
+
data: JSONSchema;
|
|
4
|
+
path: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Resolves `include` and `$ref` statements.
|
|
8
|
+
* @param filePath {String} file to parse.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseIncludeReferenceStatements(filePath: string): JSONSchema;
|
|
11
|
+
export declare function parseIncludeReferenceStatementsByDir(dirPath: string, wrapInDataAndPath: true): JSONSchemaWithPath[];
|
|
12
|
+
export declare function parseIncludeReferenceStatementsByDir(dirPath: string, wrapInDataAndPath?: false): JSONSchema[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseIncludeReferenceStatements = parseIncludeReferenceStatements;
|
|
7
|
+
exports.parseIncludeReferenceStatementsByDir = parseIncludeReferenceStatementsByDir;
|
|
8
|
+
/**
|
|
9
|
+
* Server-side schema parsing utilities.
|
|
10
|
+
*
|
|
11
|
+
* Use this module only in Node/server contexts where the filesystem is available.
|
|
12
|
+
* It walks directories and reads JSON schema files from disk; do not import it in
|
|
13
|
+
* browser bundles.
|
|
14
|
+
*/
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
const json_schema_deref_sync_1 = __importDefault(require("json-schema-deref-sync"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const json_include_1 = require("../../json_include");
|
|
19
|
+
const filesystem_1 = require("../../utils/filesystem");
|
|
20
|
+
/**
|
|
21
|
+
* Resolves `include` and `$ref` statements.
|
|
22
|
+
* @param filePath {String} file to parse.
|
|
23
|
+
*/
|
|
24
|
+
function parseIncludeReferenceStatements(filePath) {
|
|
25
|
+
const jsonResolver = new json_include_1.JSONInclude();
|
|
26
|
+
const parsed = jsonResolver.parseIncludeStatements(filePath);
|
|
27
|
+
const dirPath = path_1.default.dirname(filePath);
|
|
28
|
+
// Store the original $id before dereferencing
|
|
29
|
+
const originalId = parsed.$id;
|
|
30
|
+
let dereferenced = (0, json_schema_deref_sync_1.default)(parsed, { baseFolder: dirPath, removeIds: true });
|
|
31
|
+
// handle circular references and use non-dereferenced source
|
|
32
|
+
if (dereferenced instanceof Error && dereferenced.message === "Circular self reference") {
|
|
33
|
+
dereferenced = parsed;
|
|
34
|
+
}
|
|
35
|
+
// Restore the original $id after dereferencing
|
|
36
|
+
if (originalId) {
|
|
37
|
+
dereferenced.$id = originalId;
|
|
38
|
+
}
|
|
39
|
+
return dereferenced;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolves `include` and `$ref` statements for all the JSON files inside a given directory.
|
|
43
|
+
* @param dirPath directory to parse.
|
|
44
|
+
*/
|
|
45
|
+
function parseIncludeReferenceStatementsByDir(dirPath, wrapInDataAndPath = false) {
|
|
46
|
+
const schemas = [];
|
|
47
|
+
const schemasWithPath = [];
|
|
48
|
+
const topDir = path_1.default.resolve(__dirname, "../../../../");
|
|
49
|
+
(0, filesystem_1.walkDirSync)(dirPath, (filePath) => {
|
|
50
|
+
if (filePath.endsWith(".json")) {
|
|
51
|
+
const config = parseIncludeReferenceStatements(filePath);
|
|
52
|
+
if (wrapInDataAndPath) {
|
|
53
|
+
const _path = path_1.default.join(
|
|
54
|
+
// remove leading slashes and "example" from path
|
|
55
|
+
path_1.default
|
|
56
|
+
.dirname(filePath)
|
|
57
|
+
.replace(path_1.default.join(topDir, "example"), "")
|
|
58
|
+
.replace(/^\/+/, ""), path_1.default.basename(filePath).replace(".json", ""));
|
|
59
|
+
schemasWithPath.push({ data: config, path: _path });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
schemas.push(config);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return wrapInDataAndPath ? schemasWithPath : schemas;
|
|
67
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PROPERTIES_MANIFEST_PATH = exports.EXAMPLES_DIR = exports.SCHEMAS_DIR = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
exports.SCHEMAS_DIR = path_1.default.resolve(__dirname, "../../../schema");
|
|
9
|
+
exports.EXAMPLES_DIR = path_1.default.resolve(__dirname, "../../../example");
|
|
10
|
+
exports.PROPERTIES_MANIFEST_PATH = path_1.default.resolve(__dirname, "../../../manifest/properties.yaml");
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { JSONSchema7, JSONSchema7Definition } from "json-schema";
|
|
2
|
+
export type JSONSchema = JSONSchema7;
|
|
3
|
+
export type JSONSchemaDefinition = JSONSchema7Definition;
|
|
4
|
+
export declare function applyPatchWithDotNotation(target: Record<string, unknown>, path: string, patchValue: unknown): void;
|
|
5
|
+
export declare function applyPatchTree(schema: Record<string, unknown>, patchNode: Record<string, unknown>, pathPrefix: string[]): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyPatchWithDotNotation = applyPatchWithDotNotation;
|
|
4
|
+
exports.applyPatchTree = applyPatchTree;
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function applyPatchWithDotNotation(target, path, patchValue) {
|
|
9
|
+
const keys = path.split(".");
|
|
10
|
+
let current = target;
|
|
11
|
+
// Navigate to parent of final key
|
|
12
|
+
for (let index = 0; index < keys.length - 1; index += 1) {
|
|
13
|
+
const key = keys[index];
|
|
14
|
+
if (!isPlainObject(current[key])) {
|
|
15
|
+
// Path does not exist or is not an object → skip patch
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
current = current[key];
|
|
19
|
+
}
|
|
20
|
+
const finalKey = keys[keys.length - 1];
|
|
21
|
+
const existingValue = current[finalKey];
|
|
22
|
+
if (isPlainObject(existingValue) && isPlainObject(patchValue)) {
|
|
23
|
+
// Merge object into existing object
|
|
24
|
+
Object.assign(existingValue, patchValue);
|
|
25
|
+
}
|
|
26
|
+
else if (existingValue !== undefined) {
|
|
27
|
+
// Overwrite leaf value
|
|
28
|
+
current[finalKey] = patchValue;
|
|
29
|
+
}
|
|
30
|
+
// If existingValue is undefined, we skip;
|
|
31
|
+
}
|
|
32
|
+
function applyPatchTree(schema, patchNode, pathPrefix) {
|
|
33
|
+
Object.entries(patchNode).forEach(([key, value]) => {
|
|
34
|
+
if (key.includes(".")) {
|
|
35
|
+
// Dot notation relative to current prefix
|
|
36
|
+
const fullPathSegments = [...pathPrefix, ...key.split(".")];
|
|
37
|
+
const fullPath = fullPathSegments.join(".");
|
|
38
|
+
applyPatchWithDotNotation(schema, fullPath, value);
|
|
39
|
+
}
|
|
40
|
+
else if (isPlainObject(value)) {
|
|
41
|
+
// Nested subtree → recurse with extended prefix
|
|
42
|
+
applyPatchTree(schema, value, [...pathPrefix, key]);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Leaf patch (primitive / array) → treat as direct field patch
|
|
46
|
+
const fullPathSegments = [...pathPrefix, key];
|
|
47
|
+
const fullPath = fullPathSegments.join(".");
|
|
48
|
+
applyPatchWithDotNotation(schema, fullPath, value);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CacheObject {
|
|
2
|
+
[key: string]: CacheObject | CacheObject[];
|
|
3
|
+
}
|
|
4
|
+
export declare class JSONInclude {
|
|
5
|
+
JSON_INCLUDE_CACHE: CacheObject;
|
|
6
|
+
/**
|
|
7
|
+
* Extracts file name(path) from the include statement.
|
|
8
|
+
* @param value string to extract the file name from.
|
|
9
|
+
*/
|
|
10
|
+
_getIncludeFileName: (value: unknown) => string | null | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Walks a nested object to resolve include statements.
|
|
13
|
+
* @param obj Object to traverse.
|
|
14
|
+
* @param dirpath directory from which `obj` is obtained. Include statements are relative to `obj` path.
|
|
15
|
+
*/
|
|
16
|
+
_walkObjectToInclude(obj: CacheObject | CacheObject[], dirpath: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves `include` statements.
|
|
19
|
+
* @param filePath file to parse.
|
|
20
|
+
*/
|
|
21
|
+
parseIncludeStatements(filePath: string): CacheObject[];
|
|
22
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.JSONInclude = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const common_1 = require("../utils/common");
|
|
10
|
+
const settings_1 = require("./settings");
|
|
11
|
+
class JSONInclude {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.JSON_INCLUDE_CACHE = {};
|
|
14
|
+
/**
|
|
15
|
+
* Extracts file name(path) from the include statement.
|
|
16
|
+
* @param value string to extract the file name from.
|
|
17
|
+
*/
|
|
18
|
+
this._getIncludeFileName = (value) => {
|
|
19
|
+
if (typeof value === "string" && value.search(settings_1.INCLUDE_VALUE_REGEX) !== -1) {
|
|
20
|
+
const matched = value.match(settings_1.INCLUDE_VALUE_REGEX);
|
|
21
|
+
return matched && matched[1];
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Walks a nested object to resolve include statements.
|
|
27
|
+
* @param obj Object to traverse.
|
|
28
|
+
* @param dirpath directory from which `obj` is obtained. Include statements are relative to `obj` path.
|
|
29
|
+
*/
|
|
30
|
+
_walkObjectToInclude(obj, dirpath) {
|
|
31
|
+
if ((0, common_1.isInstanceOf)(obj, "Array")) {
|
|
32
|
+
for (let i = 0; i < obj.length; i++) {
|
|
33
|
+
if ((0, common_1.isInstanceOf)(obj[i], "Object") || (0, common_1.isInstanceOf)(obj[i], "Array")) {
|
|
34
|
+
this._walkObjectToInclude(obj[i], dirpath);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if ((0, common_1.isInstanceOf)(obj, "Object")) {
|
|
39
|
+
if (settings_1.INCLUDE_KEY in obj) {
|
|
40
|
+
const includeName = this._getIncludeFileName(obj[settings_1.INCLUDE_KEY]);
|
|
41
|
+
if (includeName) {
|
|
42
|
+
delete obj[settings_1.INCLUDE_KEY];
|
|
43
|
+
if (!(includeName in this.JSON_INCLUDE_CACHE)) {
|
|
44
|
+
const filePath = path_1.default.join(dirpath, includeName);
|
|
45
|
+
this.JSON_INCLUDE_CACHE[includeName] =
|
|
46
|
+
this.parseIncludeStatements(filePath);
|
|
47
|
+
}
|
|
48
|
+
Object.keys(this.JSON_INCLUDE_CACHE[includeName]).forEach((attr) => {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
obj[attr] = this.JSON_INCLUDE_CACHE[includeName][attr];
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
Object.keys(obj).forEach((key) => {
|
|
55
|
+
if ((0, common_1.isInstanceOf)(obj[key], "Object") || (0, common_1.isInstanceOf)(obj[key], "Array")) {
|
|
56
|
+
this._walkObjectToInclude(obj[key], dirpath);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolves `include` statements.
|
|
63
|
+
* @param filePath file to parse.
|
|
64
|
+
*/
|
|
65
|
+
parseIncludeStatements(filePath) {
|
|
66
|
+
const data = (0, common_1.safeParseJSON)(fs_1.default.readFileSync(filePath, "utf8"));
|
|
67
|
+
console.log("Parsing file: ", filePath);
|
|
68
|
+
if (settings_1.OBJECT_ONLY && !(0, common_1.isInstanceOf)(data, "Object")) {
|
|
69
|
+
throw new Error("The JSON file being included should always be a dict rather than a list");
|
|
70
|
+
}
|
|
71
|
+
this._walkObjectToInclude(data, path_1.default.dirname(filePath));
|
|
72
|
+
return data;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.JSONInclude = JSONInclude;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OBJECT_ONLY = exports.INCLUDE_VALUE_REGEX = exports.INCLUDE_KEY = void 0;
|
|
4
|
+
exports.INCLUDE_KEY = "...";
|
|
5
|
+
exports.INCLUDE_VALUE_REGEX = /^include\((.+)\)$/;
|
|
6
|
+
exports.OBJECT_ONLY = false; // whether to only include Object, and not Array.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function compileTS(schemaPath: string, savePath: string): Promise<void>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = compileTS;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const json_schema_to_typescript_1 = require("json-schema-to-typescript");
|
|
9
|
+
const schemaUtils_1 = require("../esse/schemaUtils");
|
|
10
|
+
const filesystem_1 = require("../utils/filesystem");
|
|
11
|
+
/**
|
|
12
|
+
* By definition, the "compile" function will generate 2 schemas based on the following input:
|
|
13
|
+
* {
|
|
14
|
+
* "title": "schema1",
|
|
15
|
+
* "type": "object",
|
|
16
|
+
* "properties": {
|
|
17
|
+
* "prop": {
|
|
18
|
+
* "title": "schema2",
|
|
19
|
+
* "type": "string"
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* Result:
|
|
25
|
+
* type schema2 = string;
|
|
26
|
+
*
|
|
27
|
+
* interface schema1 {
|
|
28
|
+
* prop: schema2
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* To disable this behavior we need to remove "title" property from the "prop":
|
|
32
|
+
* {
|
|
33
|
+
* "title": "schema1",
|
|
34
|
+
* "type": "object",
|
|
35
|
+
* "properties": {
|
|
36
|
+
* "prop": {
|
|
37
|
+
* "type": "string"
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* New result:
|
|
43
|
+
* interface schema1 {
|
|
44
|
+
* prop: string;
|
|
45
|
+
* }
|
|
46
|
+
* @returns Clean schema
|
|
47
|
+
*/
|
|
48
|
+
function cleanSchema(schema) {
|
|
49
|
+
let firstRun = true;
|
|
50
|
+
return (0, schemaUtils_1.mapObjectDeep)(schema, (object) => {
|
|
51
|
+
if (typeof object === "object" && (object === null || object === void 0 ? void 0 : object.title) && !firstRun) {
|
|
52
|
+
firstRun = false;
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
|
+
const { title, $schema, ...restObject } = object;
|
|
55
|
+
return restObject;
|
|
56
|
+
}
|
|
57
|
+
firstRun = false;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function compileTS(schemaPath, savePath) {
|
|
61
|
+
try {
|
|
62
|
+
await fs_1.default.promises.unlink(savePath);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.log("File with types not exists");
|
|
66
|
+
}
|
|
67
|
+
await (0, filesystem_1.walkDir)(schemaPath, async (filePath) => {
|
|
68
|
+
const data = await fs_1.default.promises.readFile(filePath, "utf8");
|
|
69
|
+
const schema = cleanSchema(JSON.parse(data));
|
|
70
|
+
console.log(`Compiling Typescript: ${filePath}`);
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
const compiledSchema = await (0, json_schema_to_typescript_1.compile)(schema, schema.title || "", {
|
|
73
|
+
unreachableDefinitions: true,
|
|
74
|
+
additionalProperties: false,
|
|
75
|
+
enableConstEnums: false,
|
|
76
|
+
bannerComment: `/** Schema ${filePath} */`,
|
|
77
|
+
});
|
|
78
|
+
await fs_1.default.promises.appendFile(savePath, `${compiledSchema} \n`, { flag: "a+" });
|
|
79
|
+
});
|
|
80
|
+
}
|