rads-db 3.0.84 → 3.1.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.
@@ -1,603 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.parseSchema = parseSchema;
7
- var _typescript = require("typescript");
8
- var _lodash = _interopRequireDefault(require("lodash"));
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
- const supportedPrimitiveTypes = ["string", "number", "boolean", "Record<string, string>", "Record<string, any>"];
11
- function parseSchema(typescriptFiles) {
12
- const typeNodesMap = getTypeNodesMap(typescriptFiles);
13
- const schema = getSchema(typeNodesMap);
14
- resolveIsExtending(schema);
15
- fillComputedDefinitionsForType(schema);
16
- verifyDefaultValueTypes(schema, typeNodesMap);
17
- verifyRelationFields(schema);
18
- return schema;
19
- }
20
- function resolveIsExtending(schema) {
21
- for (const key in schema) {
22
- const isExtendingType = schema[key].isExtending;
23
- if (!isExtendingType) continue;
24
- if (!schema[isExtendingType]) throw new Error(`Unknown type: "${isExtendingType}"`);
25
- schema[key].fields = {
26
- ...schema[isExtendingType].fields,
27
- ...schema[key].fields
28
- };
29
- schema[key].decorators = {
30
- ...schema[isExtendingType].decorators,
31
- ...schema[key].decorators
32
- };
33
- if (schema[key].decorators.entity && !schema[key].fields?.id) {
34
- throw new Error(`Entity "${key}" must have an id`);
35
- }
36
- }
37
- }
38
- function getSchema(typeNodesMap) {
39
- const result = {};
40
- for (const key in typeNodesMap) {
41
- const {
42
- node,
43
- name
44
- } = typeNodesMap[key];
45
- if (![_typescript.SyntaxKind.ClassDeclaration, _typescript.SyntaxKind.TypeAliasDeclaration].includes(node.kind)) {
46
- throw new Error(`Unexpected type kind - "${name}"`);
47
- }
48
- }
49
- for (const key in typeNodesMap) {
50
- if (result[key]) continue;
51
- const {
52
- node,
53
- sourceFile,
54
- name
55
- } = typeNodesMap[key];
56
- if (node.kind !== _typescript.SyntaxKind.ClassDeclaration) continue;
57
- const parsedClass = parseClassDeclaration(node, name, {
58
- typeNodesMap,
59
- sourceFile,
60
- result
61
- });
62
- result[key] = parsedClass;
63
- }
64
- for (const key in typeNodesMap) {
65
- if (result[key]) continue;
66
- const {
67
- node,
68
- sourceFile,
69
- name
70
- } = typeNodesMap[key];
71
- if (node.kind !== _typescript.SyntaxKind.TypeAliasDeclaration) continue;
72
- const parsedClass = parseTypeAliasDeclaration(node, name, {
73
- typeNodesMap,
74
- sourceFile,
75
- result
76
- });
77
- result[key] = parsedClass;
78
- }
79
- return result;
80
- }
81
- function getTypeNodesMap(typescriptFiles) {
82
- const typeNodesMap = {};
83
- for (const key in typescriptFiles) {
84
- const text = typescriptFiles[key];
85
- const sourceFile = (0, _typescript.createSourceFile)(`${key}.ts`, text, _typescript.ScriptTarget.Latest);
86
- const classDeclarations = getClassDeclarations(sourceFile);
87
- for (const cd of classDeclarations) {
88
- const nameNode = cd.name;
89
- if (!nameNode || nameNode.kind !== _typescript.SyntaxKind.Identifier) throw new Error("Cannot detect class name");
90
- const name = nameNode.text;
91
- typeNodesMap[name] = {
92
- name,
93
- node: cd,
94
- sourceFile
95
- };
96
- }
97
- if (!typeNodesMap[key]) {
98
- throw new Error(`File ${key}.ts must contain class declaration with name "${key}"`);
99
- }
100
- }
101
- return typeNodesMap;
102
- }
103
- function verifyDefaultValueTypes(schema, typeNodesMap) {
104
- for (const key in schema) {
105
- const type = schema[key];
106
- const fields = type.fields;
107
- if (!fields) continue;
108
- for (const fName in fields) {
109
- const field = fields[fName];
110
- if (field.defaultValue) {
111
- verifyDefaultValueType(field, {
112
- typeNodesMap,
113
- result: schema,
114
- sourceFile: typeNodesMap[key]?.sourceFile
115
- });
116
- }
117
- for (const fName2 in fields) {
118
- const field2 = fields[fName2];
119
- if (field2.defaultValueCopyFrom) {
120
- const sourceField = fields[field2.defaultValueCopyFrom];
121
- if (!sourceField) throw new Error(`Cannot find field ${key}.${field2.defaultValueCopyFrom}"`);
122
- verifyDefaultValueTypeCopyFrom(field2, sourceField, {
123
- typeNodesMap,
124
- result: schema,
125
- sourceFile: typeNodesMap[key]?.sourceFile
126
- });
127
- }
128
- }
129
- }
130
- }
131
- }
132
- function fillComputedDefinitionsForType(result) {
133
- for (const key in result) {
134
- const type = result[key];
135
- const fields = type.fields;
136
- if (!fields) continue;
137
- const precomputedFields = _lodash.default.values(fields).filter(f => !!f.decorators?.precomputed).sort((f1, f2) => getOrder(f1) - getOrder(f2)).map(f => f.name);
138
- const computedFields = _lodash.default.values(fields).filter(f => !!f.decorators?.computed).sort((f1, f2) => getOrder(f1) - getOrder(f2)).map(f => f.name);
139
- const nestedTypeFields = _lodash.default.values(fields).filter(f => result[f.type] && result[f.type].fields && !result[f.type].decorators.entity).map(f => f.name);
140
- const keepHistoryFields = _lodash.default.values(fields).filter(f => !!f.decorators?.keepHistory).map(f => f.name);
141
- if (precomputedFields.length) type.precomputedFields = precomputedFields;
142
- if (computedFields.length) type.computedFields = computedFields;
143
- if (nestedTypeFields.length) type.nestedTypeFields = nestedTypeFields;
144
- if (keepHistoryFields.length) type.keepHistoryFields = keepHistoryFields;
145
- }
146
- }
147
- function getOrder(f) {
148
- const decorator = f.decorators.computed || f.decorators.precomputed;
149
- const defaultOrders = {
150
- createdAt: -1e5,
151
- updatedAt: -9e4
152
- };
153
- return decorator.order ?? defaultOrders[decorator.preset] ?? 0;
154
- }
155
- function parseClassOrTypeDeclaration(typeDeclaration, typeName, ctx2) {
156
- if (typeDeclaration.kind === _typescript.SyntaxKind.ClassDeclaration) return parseClassDeclaration(typeDeclaration, typeName, ctx2);
157
- if (typeDeclaration.kind === _typescript.SyntaxKind.TypeAliasDeclaration) return parseTypeAliasDeclaration(typeDeclaration, typeName, ctx2);
158
- throw new Error(`Unexpected type definition - ${typeName}`);
159
- }
160
- function parseClassDeclaration(typeDeclaration, typeName, ctx2) {
161
- if (ctx2.result[typeName]) return ctx2.result[typeName];
162
- const {
163
- modifiers
164
- } = typeDeclaration;
165
- const nameNode = typeDeclaration.name;
166
- if (!nameNode || nameNode.kind !== _typescript.SyntaxKind.Identifier) throw new Error("Cannot detect class name");
167
- const name = nameNode.text;
168
- const comment = getCommentFromJsdocNode(typeDeclaration.jsDoc);
169
- const decorators = parseDecorators(modifiers, ctx2);
170
- const classDeclaration = typeDeclaration;
171
- const {
172
- members,
173
- heritageClauses
174
- } = classDeclaration;
175
- const isExtendingExpr = heritageClauses?.[0]?.types?.[0]?.expression;
176
- const isExtending = isExtendingExpr?.text;
177
- for (const m of members) {
178
- if (m.kind !== _typescript.SyntaxKind.PropertyDeclaration) {
179
- throw new Error(`Unexpected class member - only properties are allowed("${m.getText(ctx2.sourceFile)}")`);
180
- }
181
- }
182
- const fields = {};
183
- for (const m of members) {
184
- const field = parseClassMember(m, fields, name, ctx2);
185
- fields[field.name] = field;
186
- }
187
- const handle = _lodash.default.lowerFirst(name);
188
- const handlePlural = `${handle}/list`;
189
- const result = {
190
- name,
191
- handle,
192
- handlePlural,
193
- decorators,
194
- fields,
195
- isExtending,
196
- comment,
197
- sourceFile: ctx2.sourceFile.fileName
198
- };
199
- return result;
200
- }
201
- function parseTypeAliasDeclaration(typeDeclaration, typeName, ctx2) {
202
- if (ctx2.result[typeName]) return ctx2.result[typeName];
203
- const nameNode = typeDeclaration.name;
204
- if (!nameNode || nameNode.kind !== _typescript.SyntaxKind.Identifier) throw new Error("Cannot detect class name");
205
- const name = nameNode.text;
206
- const comment = getCommentFromJsdocNode(typeDeclaration.jsDoc);
207
- const typeAliasDeclaration = typeDeclaration;
208
- const typeAliasType = typeAliasDeclaration.type;
209
- if (typeAliasType.kind === _typescript.SyntaxKind.UnionType) {
210
- const typeAliasValue = typeAliasDeclaration.type;
211
- const enumValues = getEnumValues(typeAliasValue, typeDeclaration, ctx2);
212
- return {
213
- name,
214
- enumValues,
215
- comment,
216
- decorators: {},
217
- sourceFile: ctx2.sourceFile.fileName
218
- };
219
- }
220
- if (typeAliasType.kind === _typescript.SyntaxKind.TypeOperator && typeAliasType.operator === _typescript.SyntaxKind.KeyOfKeyword) {
221
- const enumValues = getEnumValuesFromKeyOf(typeAliasType, ctx2);
222
- return {
223
- name,
224
- enumValues,
225
- comment,
226
- decorators: {},
227
- sourceFile: ctx2.sourceFile.fileName
228
- };
229
- }
230
- throw new Error(`Unexpected type definition - ${typeDeclaration.getText(ctx2.sourceFile)}. Did you mean 'class'?`);
231
- }
232
- function parseDecorators(modifiers, ctx2) {
233
- if (!modifiers) return {};
234
- const decoratorNodes = modifiers?.filter(x => x.kind === _typescript.SyntaxKind.Decorator) || [];
235
- const decoratorsArray = decoratorNodes?.map(x => parseDecorator(x, ctx2)) || [];
236
- const decorators = {};
237
- for (const d of decoratorsArray) {
238
- decorators[d.name] = d.args;
239
- }
240
- return decorators;
241
- }
242
- function getEnumValues(node, parentNode, ctx2) {
243
- const enumValuesArray = node.types.map(node2 => {
244
- if (node2.kind !== _typescript.SyntaxKind.LiteralType) {
245
- throw new Error(`Unexpected type definition - ${parentNode.getText(ctx2.sourceFile)}`);
246
- }
247
- const {
248
- literal
249
- } = node2;
250
- if (literal.kind !== _typescript.SyntaxKind.StringLiteral) throw new Error(`Unexpected type definition - ${parentNode.getText(ctx2.sourceFile)}`);
251
- return {
252
- name: literal.text
253
- };
254
- });
255
- return _lodash.default.keyBy(enumValuesArray, "name");
256
- }
257
- function parseClassMember(node, parentFields, parentName, ctx2) {
258
- const name = node.name.getText(ctx2.sourceFile);
259
- const {
260
- defaultValue: defaultValue2,
261
- defaultValueCopyFrom,
262
- defaultValueClass
263
- } = parseDefaultValueExpression(node.initializer, ctx2);
264
- const isRequired = !node.questionToken;
265
- const comment = getCommentFromJsdocNode(node.jsDoc);
266
- const decorators = parseDecorators(node.modifiers, ctx2);
267
- let defaultValueType = defaultValueClass || getPrimitiveTypeFromDefaultValue(defaultValue2);
268
- if (defaultValueCopyFrom) {
269
- const parentField = parentFields[defaultValueCopyFrom];
270
- if (!parentField) throw new Error(`Cannot find field ${parentName}.${defaultValueCopyFrom}"`);
271
- defaultValueType = parentField.type;
272
- }
273
- const parsedType = parseFieldType(ctx2, parentName, name, node, defaultValueType);
274
- const result = {
275
- ...parsedType,
276
- defaultValue: defaultValue2,
277
- defaultValueCopyFrom,
278
- name,
279
- isRequired,
280
- comment
281
- };
282
- if (!_lodash.default.isEmpty(decorators)) result.decorators = decorators;
283
- if (defaultValueClass) result.defaultValueClass = defaultValueClass;
284
- return result;
285
- }
286
- function getCommentFromJsdocNode(jsDoc) {
287
- const comment = jsDoc?.[0]?.comment;
288
- const tags = jsDoc?.[0]?.tags;
289
- const tagsStr = tags?.map(tag => [`@${tag.tagName.text}`, tag.comment || ""].filter(x => x).join(" "))?.join("\n") || "";
290
- return [comment, tagsStr].filter(x => x).join("\n") || void 0;
291
- }
292
- function getPrimitiveTypeFromDefaultValue(value) {
293
- if (_lodash.default.isString(value)) return "string";
294
- if (_lodash.default.isNumber(value)) return "number";
295
- if (_lodash.default.isBoolean(value)) return "boolean";
296
- if (_lodash.default.isArray(value)) return "array";
297
- if (_lodash.default.isObject(value)) return "object";
298
- return void 0;
299
- }
300
- function parseFieldType(ctx2, parentName, fieldName, node, defaultValueType) {
301
- const parsedType = {
302
- isArray: false,
303
- isRelation: false,
304
- isChange: false,
305
- relationDenormFields: void 0,
306
- type: void 0,
307
- nodeType: node.type,
308
- node
309
- };
310
- parseFieldTypeArray(parsedType, parentName);
311
- parseFieldTypeRelation(parsedType, parentName, ctx2);
312
- parseFieldTypeInverseRelation(parsedType, parentName, ctx2);
313
- parseFieldTypeInlineEnum(parsedType, parentName, fieldName, ctx2);
314
- parseFieldTypeKeyofEnum(parsedType, parentName, fieldName, ctx2);
315
- parseFieldTypeRecordEnum(parsedType, parentName, fieldName, ctx2);
316
- parsedType.type = parsedType.type ?? parsedType.nodeType?.getText(ctx2.sourceFile) ?? defaultValueType;
317
- if (!parsedType.type) throw new Error(`Cannot detect property type: '${node.getText(ctx2.sourceFile)}'`);
318
- if (parsedType.type.startsWith("Change<")) {
319
- parsedType.type = parsedType.type.slice(7, -1);
320
- if (!ctx2.typeNodesMap[parsedType.type]) throw new Error(`Unexpected property type: '${parsedType.type}'`);
321
- parsedType.isChange = true;
322
- } else {
323
- if (!supportedPrimitiveTypes.includes(parsedType.type) && !ctx2.typeNodesMap[parsedType.type] && !ctx2.result[parsedType.type]) {
324
- throw new Error(`Unexpected property type: '${parsedType.type}'`);
325
- }
326
- }
327
- return {
328
- isArray: parsedType.isArray || void 0,
329
- isRelation: parsedType.isRelation || void 0,
330
- isInverseRelation: parsedType.isInverseRelation || void 0,
331
- isChange: parsedType.isChange || void 0,
332
- relationDenormFields: parsedType.relationDenormFields,
333
- inverseRelationField: parsedType.inverseRelationField,
334
- type: parsedType.type
335
- };
336
- }
337
- function parseFieldTypeRecordEnum(parsedType, parentName, fieldName, ctx2) {
338
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.TypeReference) return;
339
- const nt = parsedType.nodeType;
340
- if (nt.typeName.getText(ctx2.sourceFile) !== "Record") return;
341
- if (nt.typeArguments?.length !== 2) return;
342
- const keyTypeName = nt.typeArguments[0].getText(ctx2.sourceFile);
343
- const valueTypeName = nt.typeArguments[1].getText(ctx2.sourceFile);
344
- const keyType = ctx2.typeNodesMap[keyTypeName];
345
- if (!keyType) return;
346
- if (!ctx2.result[keyTypeName]) ctx2.result[keyTypeName] = parseClassOrTypeDeclaration(keyType.node, keyTypeName, ctx2);
347
- const enumValues = ctx2.result[keyTypeName].enumValues;
348
- if (!enumValues) throw new Error(`Unexpected type - ${keyTypeName}`);
349
- const newTypeName = `${parentName}_${_lodash.default.upperFirst(fieldName)}`;
350
- const fieldsArray = _lodash.default.values(enumValues).map(v => ({
351
- name: v.name,
352
- type: valueTypeName,
353
- isRequired: true
354
- }));
355
- ctx2.result[newTypeName] = {
356
- name: newTypeName,
357
- decorators: {},
358
- fields: _lodash.default.keyBy(fieldsArray, "name"),
359
- sourceFile: ctx2.sourceFile.fileName
360
- };
361
- parsedType.type = newTypeName;
362
- }
363
- function parseFieldTypeArray(parsedType, parentName) {
364
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.ArrayType) return;
365
- parsedType.isArray = true;
366
- parsedType.nodeType = parsedType.nodeType.elementType;
367
- if (parsedType.nodeType?.kind === _typescript.SyntaxKind.ParenthesizedType) {
368
- parsedType.nodeType = parsedType.nodeType.type;
369
- }
370
- if (parsedType.nodeType?.kind === _typescript.SyntaxKind.ArrayType) {
371
- throw new Error(`Nested arrays are not supported (${parentName})`);
372
- }
373
- }
374
- function parseFieldTypeRelation(parsedType, parentName, ctx2) {
375
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.TypeReference) return;
376
- const nt = parsedType.nodeType;
377
- if (nt.typeName.getText(ctx2.sourceFile) === "Relation") {
378
- if (!nt.typeArguments?.length) throw new Error(`Missing type argument for Relation<>: '${parentName}'`);
379
- parsedType.nodeType = nt.typeArguments[0];
380
- parsedType.isRelation = true;
381
- if (nt.typeArguments[1]) {
382
- const ta = nt.typeArguments[1];
383
- parsedType.relationDenormFields = getRelationDenormFields(ctx2, ta);
384
- }
385
- }
386
- }
387
- function parseFieldTypeInverseRelation(parsedType, parentName, ctx2) {
388
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.TypeReference) return;
389
- const nt = parsedType.nodeType;
390
- if (nt.typeName.getText(ctx2.sourceFile) === "InverseRelation") {
391
- if (!nt.typeArguments?.length) throw new Error(`Missing type argument for Relation<>: '${parentName}'`);
392
- parsedType.type = parseStringField(ctx2, nt.typeArguments[0]);
393
- parsedType.isInverseRelation = true;
394
- if (nt.typeArguments[1]) {
395
- const taNode = nt.typeArguments[1];
396
- parsedType.inverseRelationField = parseStringField(ctx2, taNode);
397
- }
398
- }
399
- }
400
- function parseStringField(ctx2, node) {
401
- if (node.kind === _typescript.SyntaxKind.LiteralType) {
402
- const literal = node.literal;
403
- if (literal.kind === _typescript.SyntaxKind.StringLiteral) {
404
- return literal.text;
405
- }
406
- }
407
- throw new Error(`Unexpected type - ${node.getText(ctx2.sourceFile)}`);
408
- }
409
- function parseFieldTypeInlineEnum(parsedType, parentName, fieldName, ctx2) {
410
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.UnionType) return;
411
- const nt = parsedType.nodeType;
412
- const enumValues = getEnumValues(nt, parsedType.node, ctx2);
413
- const newTypeName = `${parentName}_${_lodash.default.upperFirst(fieldName)}`;
414
- ctx2.result[newTypeName] = {
415
- name: newTypeName,
416
- decorators: {},
417
- enumValues,
418
- sourceFile: ctx2.sourceFile.fileName
419
- };
420
- parsedType.type = newTypeName;
421
- }
422
- function parseFieldTypeKeyofEnum(parsedType, parentName, fieldName, ctx2) {
423
- if (parsedType.nodeType?.kind !== _typescript.SyntaxKind.TypeOperator) return;
424
- const nt = parsedType.nodeType;
425
- if (nt.operator !== _typescript.SyntaxKind.KeyOfKeyword) return;
426
- const enumValues = getEnumValuesFromKeyOf(nt, ctx2);
427
- const newTypeName = `${parentName}_${_lodash.default.upperFirst(fieldName)}`;
428
- ctx2.result[newTypeName] = {
429
- name: newTypeName,
430
- decorators: {},
431
- enumValues,
432
- sourceFile: ctx2.sourceFile.fileName
433
- };
434
- parsedType.type = newTypeName;
435
- }
436
- function getEnumValuesFromKeyOf(nodeType, ctx2) {
437
- if (nodeType.type.kind !== _typescript.SyntaxKind.TypeReference) {
438
- throw new Error(`Unexpected type - ${nodeType.type.getText(ctx2.sourceFile)}`);
439
- }
440
- const typeReferenceNode = nodeType.type;
441
- if (typeReferenceNode.typeName.kind !== _typescript.SyntaxKind.Identifier) {
442
- throw new Error(`Unexpected type - ${typeReferenceNode.getText(ctx2.sourceFile)}`);
443
- }
444
- const typeName = typeReferenceNode.typeName.text;
445
- const type = ctx2.typeNodesMap[typeName];
446
- if (!type) {
447
- throw new Error(`Unexpected type - ${typeName}`);
448
- }
449
- if (!ctx2.result[typeName]) ctx2.result[typeName] = parseClassOrTypeDeclaration(type.node, typeName, ctx2);
450
- if (!ctx2.result[typeName].fields) throw new Error(`Unexpected type - ${typeName}`);
451
- return _lodash.default.mapValues(ctx2.result[typeName].fields || {}, v => ({
452
- name: v.name,
453
- comment: v.comment,
454
- decorators: v.decorators
455
- }));
456
- }
457
- function getRelationDenormFields(ctx2, node) {
458
- if (node.kind === _typescript.SyntaxKind.LiteralType) {
459
- const literal = node.literal;
460
- if (literal.kind === _typescript.SyntaxKind.StringLiteral) {
461
- return [literal.text];
462
- }
463
- throw new Error(`Unexpected type - ${literal.getText(ctx2.sourceFile)}`);
464
- }
465
- if (node.kind === _typescript.SyntaxKind.UnionType) {
466
- const union = node;
467
- return union.types.flatMap(t => getRelationDenormFields(ctx2, t));
468
- }
469
- throw new Error(`Unexpected type - ${node.getText(ctx2.sourceFile)}`);
470
- }
471
- function verifyDefaultValueType(field, ctx2) {
472
- const {
473
- isArray,
474
- defaultValue: defaultValue2,
475
- type
476
- } = field;
477
- if (isArray) {
478
- if (!_lodash.default.isArray(defaultValue2)) {
479
- throw new TypeError(`Default value type is different from field type: '${type}'`);
480
- }
481
- } else {
482
- if (supportedPrimitiveTypes.includes(type) && getPrimitiveTypeFromDefaultValue(defaultValue2) !== type) {
483
- throw new Error(`Default value type is different from field type: '${type}'`);
484
- }
485
- if (!ctx2.result[type] && ctx2.typeNodesMap[type]) ctx2.result[type] = parseClassOrTypeDeclaration(ctx2.typeNodesMap[type].node, type, ctx2);
486
- const enumValues = ctx2.result[type]?.enumValues;
487
- if (enumValues && !enumValues[defaultValue2]) {
488
- const enumValuesStr = _lodash.default.keys(enumValues).map(x => `'x'`).join(", ");
489
- throw new Error(`Default value must be one of: ${enumValuesStr}`);
490
- }
491
- }
492
- }
493
- function verifyDefaultValueTypeCopyFrom(field, sourceField, ctx2) {
494
- const {
495
- isArray,
496
- type
497
- } = field;
498
- if (isArray) {
499
- if (!sourceField.isArray) {
500
- throw new TypeError(`Default value type is not an array: '${field.name}'`);
501
- }
502
- } else {
503
- if (sourceField.type !== type) {
504
- throw new Error(`Default value type is different from field type: '${field.name}'`);
505
- }
506
- }
507
- }
508
- function parseDecorator(decoratorNode, ctx2) {
509
- const expr2 = decoratorNode.expression;
510
- if (expr2.kind !== _typescript.SyntaxKind.CallExpression) throw new Error(`Unexpected decorator format: "${expr2.getText(ctx2.sourceFile)}"`);
511
- const nameNode = expr2.expression;
512
- if (nameNode.kind !== _typescript.SyntaxKind.Identifier) throw new Error(`Unexpected decorator format: "${nameNode.getText(ctx2.sourceFile)}"`);
513
- return {
514
- name: nameNode.text,
515
- args: parseDecoratorArguments(expr2, ctx2)
516
- };
517
- }
518
- function parseDecoratorArguments(expr2, ctx2) {
519
- const args = expr2.arguments;
520
- if (args.length === 0) return {};
521
- if (args.length > 1) throw new Error(`Too many arguments - one expected: "${expr2.getText(ctx2.sourceFile)}"`);
522
- const arg = args[0];
523
- return parseLiteralNode(arg, ctx2) ?? {};
524
- }
525
- function parseDefaultValueExpression(expr2, ctx2) {
526
- if (!expr2) return {};
527
- if (expr2.kind === _typescript.SyntaxKind.NewExpression) {
528
- const identifier = expr2.expression;
529
- const type = identifier?.text;
530
- if (type) {
531
- return {
532
- defaultValueClass: type,
533
- defaultValue: {}
534
- };
535
- }
536
- } else if (expr2.kind === _typescript.SyntaxKind.PropertyAccessExpression && expr2.expression.kind === _typescript.SyntaxKind.ThisKeyword) {
537
- return {
538
- defaultValueCopyFrom: expr2.name?.text
539
- };
540
- }
541
- return {
542
- defaultValue: parseLiteralNode(expr2, ctx2)
543
- };
544
- }
545
- function parseLiteralNode(expr, ctx) {
546
- if (!expr) return void 0;
547
- if (expr.kind === _typescript.SyntaxKind.StringLiteral) return expr.text;
548
- if (expr.kind === _typescript.SyntaxKind.FalseKeyword) return false;
549
- if (expr.kind === _typescript.SyntaxKind.TrueKeyword) return true;
550
- if (expr.kind === _typescript.SyntaxKind.NumericLiteral) return Number.parseFloat(expr.text);
551
- if (expr.kind === _typescript.SyntaxKind.ObjectLiteralExpression) return parseObjectLiteral(expr, ctx);
552
- if (expr.kind === _typescript.SyntaxKind.ArrayLiteralExpression) {
553
- const defaultValueStr = expr.getText(ctx.sourceFile);
554
- let defaultValue;
555
- try {
556
- defaultValue = eval(defaultValueStr);
557
- } catch (e) {
558
- throw new Error("Value must be valid array");
559
- }
560
- if (!_lodash.default.isArray(defaultValue)) throw new Error("Value must be valid array");
561
- return defaultValue;
562
- }
563
- throw new Error(`Unexpected property expression: "${expr.getText(ctx.sourceFile)}"`);
564
- }
565
- function parseObjectLiteral(arg, ctx2) {
566
- const result = {};
567
- for (const p of arg.properties) {
568
- if (!p.name || ![_typescript.SyntaxKind.Identifier, _typescript.SyntaxKind.StringLiteral].includes(p.name.kind)) throw new Error(`Unexpected property name: "${p.getText(ctx2.sourceFile)}"`);
569
- const nameNode = p.name;
570
- const name = nameNode.text;
571
- if (p.kind !== _typescript.SyntaxKind.PropertyAssignment) throw new Error(`Unexpected property value: "${p.getText(ctx2.sourceFile)}"`);
572
- const p2 = p;
573
- const valueExpression = p2.initializer;
574
- const value = parseLiteralNode(valueExpression, ctx2);
575
- result[name] = value;
576
- }
577
- return result;
578
- }
579
- function getClassDeclarations(sourceFile) {
580
- const children = sourceFile.getChildren();
581
- const syntaxListNode = children.find(c => c.kind === _typescript.SyntaxKind.SyntaxList);
582
- const result = syntaxListNode?.getChildren().filter(c => [_typescript.SyntaxKind.ClassDeclaration, _typescript.SyntaxKind.TypeAliasDeclaration].includes(c.kind));
583
- return result || [];
584
- }
585
- function verifyRelationFields(result) {
586
- for (const key in result) {
587
- const type = result[key];
588
- for (const fieldName in type.fields) {
589
- const field = type.fields[fieldName];
590
- if (field.isRelation && !result[field.type]?.decorators?.entity) {
591
- throw new Error(`${key}.${fieldName}: Relation must point to an entity. Got "${field.type}" instead.`);
592
- }
593
- if (field.isInverseRelation) {
594
- if (!result[field.type]?.decorators?.entity) throw new Error(`${key}.${fieldName}: InverseRelation must point to an entity. Got "${field.type}" instead.`);
595
- if (field.isRequired) throw new Error(`${key}.${fieldName}: InverseRelation cannot be required. Please, add "?" to the field name.`);
596
- if (!field.isArray) throw new Error(`${key}.${fieldName}: InverseRelation must be an array.`);
597
- if (!field.inverseRelationField) throw new Error(`${key}.${fieldName}: InverseRelation must have a field name.`);
598
- if (!result[field.type]?.fields?.[field.inverseRelationField]?.isRelation) throw new Error(`${key}.${fieldName}: InverseRelation field must point to relation field. Got "${field.inverseRelationField}" instead.`);
599
- if (result[field.type]?.fields?.[field.inverseRelationField]?.type !== key) throw new Error(`${key}.${fieldName}: InverseRelation field must point to the current entity. Got "${field.inverseRelationField}" instead.`);
600
- }
601
- }
602
- }
603
- }
@@ -1 +0,0 @@
1
- export declare function parseSchema(typescriptFiles: Record<string, string>): Record<string, TypeDefinition>;