@tsofist/schema-forge 2.8.0 → 2.10.0
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/lib/generator/schema-generator.js +20 -0
- package/lib/generator.spec.js +45 -0
- package/lib/types/db.types.d.ts +33 -1
- package/lib/util/format.error.js +1 -0
- package/lib/validator.js +11 -0
- package/package.json +6 -6
|
@@ -37,6 +37,7 @@ async function generateSchemaByDraftTypes(options) {
|
|
|
37
37
|
const parser = (0, ts_json_schema_generator_1.createParser)(generatorProgram, options.sourcesTypesGeneratorConfig, (parser) => {
|
|
38
38
|
parser.addNodeParser(new TupleTypeParser(parser, allowUseFallbackDescription));
|
|
39
39
|
parser.addNodeParser(new ArrayLiteralExpressionIdentifierParser(typeChecker));
|
|
40
|
+
parser.addNodeParser(new TypeofNodeParserEx(typeChecker, parser));
|
|
40
41
|
});
|
|
41
42
|
const formatter = (0, ts_json_schema_generator_1.createFormatter)(options.sourcesTypesGeneratorConfig);
|
|
42
43
|
const generator = new ts_json_schema_generator_1.SchemaGenerator(generatorProgram, parser, formatter, generatorConfig);
|
|
@@ -96,6 +97,25 @@ async function generateSchemaByDraftTypes(options) {
|
|
|
96
97
|
function escapeDefinitionNameForJSONPath(value) {
|
|
97
98
|
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
98
99
|
}
|
|
100
|
+
class TypeofNodeParserEx extends ts_json_schema_generator_1.TypeofNodeParser {
|
|
101
|
+
createType(node, context, reference) {
|
|
102
|
+
const tc = this.typeChecker;
|
|
103
|
+
let symbol = tc.getSymbolAtLocation(node.exprName);
|
|
104
|
+
if (symbol && symbol.flags & typescript_1.SymbolFlags.Alias) {
|
|
105
|
+
symbol = tc.getAliasedSymbol(symbol);
|
|
106
|
+
const declaration = symbol.valueDeclaration;
|
|
107
|
+
if (declaration &&
|
|
108
|
+
(0, typescript_1.isSourceFile)(declaration) &&
|
|
109
|
+
declaration.fileName.endsWith('.json')) {
|
|
110
|
+
const statement = declaration.statements.at(0);
|
|
111
|
+
if (statement && (0, typescript_1.isExpressionStatement)(statement)) {
|
|
112
|
+
return this.childNodeParser.createType(statement.expression, context, reference);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return super.createType(node, context, reference);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
99
119
|
class TupleTypeParser {
|
|
100
120
|
constructor(childNodeParser, allowUseFallbackDescription) {
|
|
101
121
|
Object.defineProperty(this, "childNodeParser", {
|
package/lib/generator.spec.js
CHANGED
|
@@ -10,6 +10,51 @@ const validator_1 = require("./validator");
|
|
|
10
10
|
const KEEP_ARTEFACTS = false;
|
|
11
11
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
12
12
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
13
|
+
describe('generator for a8', () => {
|
|
14
|
+
const outputSchemaFile = './a8.generated.schema.tmp.json';
|
|
15
|
+
const outputSchemaMetadataFile = './a8.generated.definitions.tmp.json';
|
|
16
|
+
const schemaMetadata = {
|
|
17
|
+
title: 'Generator TEST',
|
|
18
|
+
version: '1.0.0',
|
|
19
|
+
$comment: 'WARN: This is a test schema.',
|
|
20
|
+
};
|
|
21
|
+
let forgeSchemaResult;
|
|
22
|
+
let validator;
|
|
23
|
+
let loadedSchema;
|
|
24
|
+
beforeAll(async () => {
|
|
25
|
+
forgeSchemaResult = await (0, generator_1.forgeSchema)({
|
|
26
|
+
schemaId: 'test',
|
|
27
|
+
allowUseFallbackDescription: true,
|
|
28
|
+
tsconfigFrom: './tsconfig.build-test.json',
|
|
29
|
+
sourcesDirectoryPattern: 'test-sources/a8',
|
|
30
|
+
sourcesFilesPattern: ['service-api.ts', 'types.ts'],
|
|
31
|
+
outputSchemaFile,
|
|
32
|
+
outputSchemaMetadataFile,
|
|
33
|
+
expose: 'all',
|
|
34
|
+
explicitPublic: true,
|
|
35
|
+
schemaMetadata,
|
|
36
|
+
});
|
|
37
|
+
validator = (0, validator_1.createSchemaForgeValidator)({}, true);
|
|
38
|
+
loadedSchema = await (0, generator_1.loadJSONSchema)([outputSchemaFile]);
|
|
39
|
+
validator.addSchema(loadedSchema);
|
|
40
|
+
});
|
|
41
|
+
afterAll(async () => {
|
|
42
|
+
if (!KEEP_ARTEFACTS) {
|
|
43
|
+
await (0, promises_1.unlink)(outputSchemaFile).catch(noop_1.noop);
|
|
44
|
+
await (0, promises_1.unlink)(outputSchemaMetadataFile).catch(noop_1.noop);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
it('generated schema should have correct metadata', () => {
|
|
48
|
+
expect(forgeSchemaResult).toBeTruthy();
|
|
49
|
+
const schema = forgeSchemaResult.schema;
|
|
50
|
+
expect((0, pick_1.pickProps)(schema, Object.keys(schemaMetadata))).toStrictEqual(schemaMetadata);
|
|
51
|
+
});
|
|
52
|
+
it('generated schema should be valid', () => {
|
|
53
|
+
expect(forgeSchemaResult).toBeTruthy();
|
|
54
|
+
const schema = validator.getSchema('test#/definitions/TypeFromJSON');
|
|
55
|
+
expect(schema).toBeTruthy();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
13
58
|
describe('generator for a7', () => {
|
|
14
59
|
const outputSchemaFile = './a7.generated.schema.tmp.json';
|
|
15
60
|
const outputSchemaMetadataFile = './a7.generated.definitions.tmp.json';
|
package/lib/types/db.types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayMay } from '@tsofist/stem';
|
|
1
|
+
import { ArrayMay, HexString } from '@tsofist/stem';
|
|
2
2
|
/**
|
|
3
3
|
* Database index types.
|
|
4
4
|
*
|
|
@@ -38,10 +38,22 @@ export type DBIndexOptions = {
|
|
|
38
38
|
* @default false
|
|
39
39
|
*/
|
|
40
40
|
pk?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Any important notes.
|
|
43
|
+
* Can be used in DDL.
|
|
44
|
+
*/
|
|
45
|
+
note?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Any important developer comments.
|
|
48
|
+
* Can't be used in DDL.
|
|
49
|
+
*/
|
|
50
|
+
comment?: string;
|
|
41
51
|
};
|
|
42
52
|
export type DBIndexOptionsDef<B extends boolean = boolean> = ArrayMay<DBIndexOptions | string | B>;
|
|
43
53
|
/**
|
|
44
54
|
* Database entity options.
|
|
55
|
+
*
|
|
56
|
+
* @see https://dbml.dbdiagram.io/docs/#table-definition dbml spec
|
|
45
57
|
*/
|
|
46
58
|
export type DBEntityOptions = {
|
|
47
59
|
/**
|
|
@@ -60,5 +72,25 @@ export type DBEntityOptions = {
|
|
|
60
72
|
indexes?: {
|
|
61
73
|
[field: string]: DBIndexOptionsDef<true>;
|
|
62
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Any important notes.
|
|
77
|
+
* Can be used in DDL.
|
|
78
|
+
*/
|
|
79
|
+
note?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Any important developer comments.
|
|
82
|
+
* Can't be used in DDL.
|
|
83
|
+
*/
|
|
84
|
+
comment?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Table name alias.
|
|
87
|
+
*/
|
|
88
|
+
alias?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Settings.
|
|
91
|
+
*/
|
|
92
|
+
settings?: {
|
|
93
|
+
headercolor: HexString;
|
|
94
|
+
};
|
|
63
95
|
};
|
|
64
96
|
export type DBEntityOptionsDef = DBEntityOptions | string;
|
package/lib/util/format.error.js
CHANGED
|
@@ -5,6 +5,7 @@ const ts_json_schema_generator_1 = require("ts-json-schema-generator");
|
|
|
5
5
|
const typescript_1 = require("typescript");
|
|
6
6
|
function formatSchemaForgeError(error, dir = '') {
|
|
7
7
|
if (error instanceof ts_json_schema_generator_1.BaseError) {
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-argument
|
|
8
9
|
return (0, typescript_1.formatDiagnostics)(error.diagnostic.relatedInformation || [], {
|
|
9
10
|
getCanonicalFileName: (fileName) => fileName,
|
|
10
11
|
getCurrentDirectory: () => dir,
|
package/lib/validator.js
CHANGED
|
@@ -339,6 +339,8 @@ function addJSDocKeywords(engine) {
|
|
|
339
339
|
type: 'string',
|
|
340
340
|
enum: db_types_1.DBIndexTypeList,
|
|
341
341
|
},
|
|
342
|
+
note: { type: 'string' },
|
|
343
|
+
comment: { type: 'string' },
|
|
342
344
|
};
|
|
343
345
|
const DBIndexSchema = {
|
|
344
346
|
type: ['string', 'boolean', 'object', 'array'],
|
|
@@ -374,6 +376,15 @@ function addJSDocKeywords(engine) {
|
|
|
374
376
|
pattern: NestedPropertyNamePattern,
|
|
375
377
|
},
|
|
376
378
|
},
|
|
379
|
+
note: { type: 'string' },
|
|
380
|
+
comment: { type: 'string' },
|
|
381
|
+
alias: { type: 'string' },
|
|
382
|
+
settings: {
|
|
383
|
+
type: 'object',
|
|
384
|
+
properties: {
|
|
385
|
+
headercolor: { type: 'string' },
|
|
386
|
+
},
|
|
387
|
+
},
|
|
377
388
|
},
|
|
378
389
|
},
|
|
379
390
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsofist/schema-forge",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
4
4
|
"description": "Generate JSON schema from TypeScript types",
|
|
5
5
|
"author": "Andrew Berdnikov <tsofistgudmen@gmail.com>",
|
|
6
6
|
"license": "LGPL-3.0",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"test:watch": "jest --watch"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@faker-js/faker": "^9.
|
|
24
|
-
"@tsofist/stem": "^4.0.
|
|
23
|
+
"@faker-js/faker": "^9.8.0",
|
|
24
|
+
"@tsofist/stem": "^4.0.3",
|
|
25
25
|
"ajv": "^8.17.1",
|
|
26
26
|
"ajv-formats": "^3.0.1",
|
|
27
27
|
"json-schema-faker": "^0.5.9",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@tsofist/web-buddy": "^1.21.0",
|
|
34
34
|
"@types/jest": "^29.5.14",
|
|
35
|
-
"@types/node": "^20.17.
|
|
35
|
+
"@types/node": "^20.17.48",
|
|
36
36
|
"@types/supertest": "^6.0.3",
|
|
37
37
|
"jest": "~29.7.0",
|
|
38
38
|
"rimraf": "^6.0.1",
|
|
39
|
-
"supertest": "^7.1.
|
|
40
|
-
"ts-jest": "~29.3.
|
|
39
|
+
"supertest": "^7.1.1",
|
|
40
|
+
"ts-jest": "~29.3.4",
|
|
41
41
|
"typescript": "~5.8.3"
|
|
42
42
|
},
|
|
43
43
|
"publishConfig": {
|