@apso/cli 0.5.0 → 0.7.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/README.md +510 -1
- package/dist/commands/server/new.js +1 -1
- package/dist/commands/server/scaffold.js +19 -10
- package/dist/lib/apsorc-parser.d.ts +3 -0
- package/dist/lib/apsorc-parser.js +11 -6
- package/dist/lib/controller.js +3 -1
- package/dist/lib/dto.js +9 -9
- package/dist/lib/entity.js +6 -5
- package/dist/lib/guards.d.ts +4 -3
- package/dist/lib/guards.js +64 -25
- package/dist/lib/module.js +3 -1
- package/dist/lib/templates/guards/auth.guard.eta +228 -0
- package/dist/lib/templates/guards/guards.module.eta +73 -13
- package/dist/lib/templates/guards/index.eta +18 -0
- package/dist/lib/templates/guards/scope.guard.eta +12 -4
- package/dist/lib/types/auth.d.ts +203 -0
- package/dist/lib/types/auth.js +60 -0
- package/dist/lib/types/entity.d.ts +2 -2
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +8 -0
- package/dist/lib/types/relationship.d.ts +1 -1
- package/dist/lib/utils/casing.js +5 -5
- package/dist/lib/utils/field.js +2 -1
- package/dist/lib/utils/file-system.js +1 -1
- package/dist/lib/utils/relationships/parse-v1.js +2 -1
- package/dist/lib/utils/relationships/parse.js +117 -32
- package/dist/lib/utils/relationships/parse.spec.js +168 -141
- package/dist/test-nested-relationships.js +10 -10
- package/dist/tests/templates/entities/types/array-template.spec.js +45 -45
- package/dist/tests/templates/entities/types/bigint-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/boolean-template.spec.js +44 -44
- package/dist/tests/templates/entities/types/bytea-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/char-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/date-template.spec.js +29 -29
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +46 -46
- package/dist/tests/templates/entities/types/decimal-template.spec.js +46 -46
- package/dist/tests/templates/entities/types/double-template.spec.js +37 -34
- package/dist/tests/templates/entities/types/enum-template.spec.js +42 -42
- package/dist/tests/templates/entities/types/float-template.spec.js +37 -34
- package/dist/tests/templates/entities/types/geometry-template.spec.js +31 -31
- package/dist/tests/templates/entities/types/inet-template.spec.js +36 -36
- package/dist/tests/templates/entities/types/int4range-template.spec.js +45 -33
- package/dist/tests/templates/entities/types/integer-template.spec.js +40 -40
- package/dist/tests/templates/entities/types/interval-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/json-plain-template.spec.js +27 -27
- package/dist/tests/templates/entities/types/json-template.spec.js +19 -19
- package/dist/tests/templates/entities/types/jsonb-template.spec.js +19 -19
- package/dist/tests/templates/entities/types/money-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/numeric-template.spec.js +44 -44
- package/dist/tests/templates/entities/types/point-template.spec.js +37 -31
- package/dist/tests/templates/entities/types/polygon-template.spec.js +43 -31
- package/dist/tests/templates/entities/types/real-template.spec.js +34 -34
- package/dist/tests/templates/entities/types/serial-template.spec.js +62 -62
- package/dist/tests/templates/entities/types/smallint-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/string-template.spec.js +59 -59
- package/dist/tests/templates/entities/types/text-template.spec.js +37 -37
- package/dist/tests/templates/entities/types/time-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/timestamp-template.spec.js +39 -39
- package/dist/tests/templates/entities/types/timetz-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/tsvector-template.spec.js +28 -28
- package/dist/tests/templates/entities/types/uuid-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/varchar-template.spec.js +59 -56
- package/dist/tests/templates/entities/types/xml-template.spec.js +28 -28
- package/dist/tests/templates/entities/utils/template-test-utils.d.ts +1 -1
- package/dist/tests/templates/entities/utils/template-test-utils.js +3 -3
- package/dist/tests/templates/entities/uuid-entity-template.spec.js +138 -138
- package/dist/tests/utils/relationship-deduplication.spec.js +11 -11
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -13,8 +13,27 @@ const casing_1 = require("../casing");
|
|
|
13
13
|
*/
|
|
14
14
|
const parseOneToMany = (relationship) => {
|
|
15
15
|
return {
|
|
16
|
-
[relationship.from]: [
|
|
17
|
-
|
|
16
|
+
[relationship.from]: [
|
|
17
|
+
{
|
|
18
|
+
name: relationship.to,
|
|
19
|
+
type: "OneToMany",
|
|
20
|
+
biDirectional: true,
|
|
21
|
+
referenceName: relationship.to_name || relationship.to,
|
|
22
|
+
inverseReferenceName: relationship.from,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
[relationship.to]: [
|
|
26
|
+
{
|
|
27
|
+
name: relationship.from,
|
|
28
|
+
type: "ManyToOne",
|
|
29
|
+
nullable: relationship.nullable || false,
|
|
30
|
+
biDirectional: true,
|
|
31
|
+
index: relationship.index || false,
|
|
32
|
+
cascadeDelete: relationship.cascadeDelete || false,
|
|
33
|
+
referenceName: relationship.from,
|
|
34
|
+
inverseReferenceName: relationship.to_name || relationship.to,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
18
37
|
};
|
|
19
38
|
};
|
|
20
39
|
exports.parseOneToMany = parseOneToMany;
|
|
@@ -51,9 +70,9 @@ exports.parseManytoOne = parseManytoOne;
|
|
|
51
70
|
*/
|
|
52
71
|
const parseManyToMany = (relationship, allRelationships) => {
|
|
53
72
|
// Find the inverse relationship definition (if exists)
|
|
54
|
-
const inverseDefinition = allRelationships.find(def => def.from === relationship.to &&
|
|
73
|
+
const inverseDefinition = allRelationships.find((def) => def.from === relationship.to &&
|
|
55
74
|
def.to === relationship.from &&
|
|
56
|
-
def.type ===
|
|
75
|
+
def.type === "ManyToMany");
|
|
57
76
|
// Determine if the relationship should be treated as bidirectional
|
|
58
77
|
const isEffectivelyBiDirectional = Boolean(relationship.bi_directional || (inverseDefinition === null || inverseDefinition === void 0 ? void 0 : inverseDefinition.bi_directional));
|
|
59
78
|
// For self-referencing relationships, find the matching inverse by to_name
|
|
@@ -61,19 +80,22 @@ const parseManyToMany = (relationship, allRelationships) => {
|
|
|
61
80
|
let selfRefInverse = null;
|
|
62
81
|
if (isSelfReferencing && relationship.bi_directional) {
|
|
63
82
|
// Find the other relationship that completes the pair
|
|
64
|
-
selfRefInverse = allRelationships.find(def => def.from === relationship.from &&
|
|
83
|
+
selfRefInverse = allRelationships.find((def) => def.from === relationship.from &&
|
|
65
84
|
def.to === relationship.to &&
|
|
66
|
-
def.type ===
|
|
85
|
+
def.type === "ManyToMany" &&
|
|
67
86
|
def.bi_directional &&
|
|
68
87
|
def.to_name !== relationship.to_name);
|
|
69
88
|
}
|
|
70
|
-
let isOwningSide = relationship.joinTableName ||
|
|
89
|
+
let isOwningSide = relationship.joinTableName ||
|
|
90
|
+
relationship.joinColumnName ||
|
|
91
|
+
relationship.inverseJoinColumnName
|
|
71
92
|
? true
|
|
72
93
|
: undefined;
|
|
73
94
|
if (isOwningSide === undefined && inverseDefinition) {
|
|
74
95
|
// If current doesn't have details, check if inverse does
|
|
75
|
-
isOwningSide =
|
|
76
|
-
|
|
96
|
+
isOwningSide = !(inverseDefinition.joinTableName ||
|
|
97
|
+
inverseDefinition.joinColumnName ||
|
|
98
|
+
inverseDefinition.inverseJoinColumnName);
|
|
77
99
|
}
|
|
78
100
|
if (isOwningSide === undefined) {
|
|
79
101
|
// If neither has details, default to the current definition being the owner
|
|
@@ -113,10 +135,18 @@ const parseManyToMany = (relationship, allRelationships) => {
|
|
|
113
135
|
referenceName: fromSideRefName,
|
|
114
136
|
join: isOwningSide,
|
|
115
137
|
biDirectional: isEffectivelyBiDirectional,
|
|
116
|
-
joinTableName: isOwningSide
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
138
|
+
joinTableName: isOwningSide
|
|
139
|
+
? relationship.joinTableName || undefined
|
|
140
|
+
: undefined,
|
|
141
|
+
joinColumnName: isOwningSide
|
|
142
|
+
? relationship.joinColumnName || undefined
|
|
143
|
+
: undefined,
|
|
144
|
+
inverseJoinColumnName: isOwningSide
|
|
145
|
+
? relationship.inverseJoinColumnName || undefined
|
|
146
|
+
: undefined,
|
|
147
|
+
inverseReferenceName: isEffectivelyBiDirectional
|
|
148
|
+
? toSideRefName
|
|
149
|
+
: undefined, // Only add inverse name if bidirectional
|
|
120
150
|
};
|
|
121
151
|
const response = {
|
|
122
152
|
[relationship.from]: [fromSideRelationship],
|
|
@@ -135,14 +165,20 @@ const parseManyToMany = (relationship, allRelationships) => {
|
|
|
135
165
|
join: isInverseOwningSide,
|
|
136
166
|
biDirectional: true,
|
|
137
167
|
// Add join details ONLY if the inverse side IS the owner
|
|
138
|
-
joinTableName: isInverseOwningSide
|
|
139
|
-
|
|
140
|
-
|
|
168
|
+
joinTableName: isInverseOwningSide
|
|
169
|
+
? (inverseDefinition === null || inverseDefinition === void 0 ? void 0 : inverseDefinition.joinTableName) || undefined
|
|
170
|
+
: undefined,
|
|
171
|
+
joinColumnName: isInverseOwningSide
|
|
172
|
+
? (inverseDefinition === null || inverseDefinition === void 0 ? void 0 : inverseDefinition.joinColumnName) || undefined
|
|
173
|
+
: undefined,
|
|
174
|
+
inverseJoinColumnName: isInverseOwningSide
|
|
175
|
+
? (inverseDefinition === null || inverseDefinition === void 0 ? void 0 : inverseDefinition.inverseJoinColumnName) || undefined
|
|
176
|
+
: undefined,
|
|
141
177
|
inverseReferenceName: fromSideRefName, // The reference name of the other side
|
|
142
178
|
};
|
|
143
179
|
response[relationship.to] = [
|
|
144
180
|
...(response[relationship.to] || []),
|
|
145
|
-
toSideRelationship
|
|
181
|
+
toSideRelationship,
|
|
146
182
|
];
|
|
147
183
|
}
|
|
148
184
|
return response;
|
|
@@ -205,13 +241,40 @@ const parseRelationship = (relationship, allRelationships) => {
|
|
|
205
241
|
const fromSideRefName = relationship.to_name || relationship.to;
|
|
206
242
|
const toSideRefName = relationship.from;
|
|
207
243
|
return {
|
|
208
|
-
[relationship.from]: [
|
|
209
|
-
|
|
244
|
+
[relationship.from]: [
|
|
245
|
+
{
|
|
246
|
+
name: relationship.to,
|
|
247
|
+
type: "OneToMany",
|
|
248
|
+
biDirectional: true,
|
|
249
|
+
referenceName: fromSideRefName,
|
|
250
|
+
inverseReferenceName: toSideRefName,
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
[relationship.to]: [
|
|
254
|
+
{
|
|
255
|
+
name: relationship.from,
|
|
256
|
+
type: "ManyToOne",
|
|
257
|
+
nullable: relationship.nullable || false,
|
|
258
|
+
biDirectional: true,
|
|
259
|
+
index: relationship.index || false,
|
|
260
|
+
cascadeDelete: relationship.cascadeDelete || false,
|
|
261
|
+
referenceName: toSideRefName,
|
|
262
|
+
inverseReferenceName: fromSideRefName,
|
|
263
|
+
},
|
|
264
|
+
],
|
|
210
265
|
};
|
|
211
266
|
}
|
|
212
267
|
case "ManyToOne":
|
|
213
268
|
return {
|
|
214
|
-
[relationship.from]: [
|
|
269
|
+
[relationship.from]: [
|
|
270
|
+
{
|
|
271
|
+
name: relationship.to,
|
|
272
|
+
type: "ManyToOne",
|
|
273
|
+
referenceName: relationship.to_name || relationship.to,
|
|
274
|
+
nullable: relationship.nullable || false,
|
|
275
|
+
index: relationship.index || false,
|
|
276
|
+
},
|
|
277
|
+
],
|
|
215
278
|
};
|
|
216
279
|
case "OneToOne": {
|
|
217
280
|
const inverseOnetoOneDef = allRelationships.find((def) => def.from === relationship.to &&
|
|
@@ -243,7 +306,7 @@ const parseRelationship = (relationship, allRelationships) => {
|
|
|
243
306
|
biDirectional: true,
|
|
244
307
|
join: !(fromRel.join || false),
|
|
245
308
|
referenceName: relationship.from,
|
|
246
|
-
inverseReferenceName: fromRel.referenceName || undefined // Reference the 'from' side's name, default to undefined if null
|
|
309
|
+
inverseReferenceName: fromRel.referenceName || undefined, // Reference the 'from' side's name, default to undefined if null
|
|
247
310
|
};
|
|
248
311
|
responseMap[relationship.to] = [
|
|
249
312
|
...(responseMap[relationship.to] || []),
|
|
@@ -300,7 +363,7 @@ exports.getRelationshipIdField = getRelationshipIdField;
|
|
|
300
363
|
*/
|
|
301
364
|
const calculateInversePropertyName = (relationship, entityName, relationshipName, needsPluralInverse) => {
|
|
302
365
|
const isSelfReferencing = relationship.name === entityName;
|
|
303
|
-
if (isSelfReferencing && relationship.type ===
|
|
366
|
+
if (isSelfReferencing && relationship.type === "ManyToMany") {
|
|
304
367
|
if (relationship.inverseReferenceName) {
|
|
305
368
|
return (0, casing_1.camelCase)(relationship.inverseReferenceName);
|
|
306
369
|
}
|
|
@@ -314,9 +377,25 @@ const calculateInversePropertyName = (relationship, entityName, relationshipName
|
|
|
314
377
|
}
|
|
315
378
|
// Check for special plural terms
|
|
316
379
|
const specialPlurals = [
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
380
|
+
"children",
|
|
381
|
+
"people",
|
|
382
|
+
"men",
|
|
383
|
+
"women",
|
|
384
|
+
"mice",
|
|
385
|
+
"geese",
|
|
386
|
+
"teeth",
|
|
387
|
+
"feet",
|
|
388
|
+
"oxen",
|
|
389
|
+
"cacti",
|
|
390
|
+
"indices",
|
|
391
|
+
"vertices",
|
|
392
|
+
"analyses",
|
|
393
|
+
"crises",
|
|
394
|
+
"diagnoses",
|
|
395
|
+
"media",
|
|
396
|
+
"criteria",
|
|
397
|
+
"data",
|
|
398
|
+
"parents",
|
|
320
399
|
];
|
|
321
400
|
if (specialPlurals.includes(relationship.inverseReferenceName)) {
|
|
322
401
|
return relationship.inverseReferenceName;
|
|
@@ -341,7 +420,7 @@ const getRelationshipForTemplate = (entityName, relationships, entities) => {
|
|
|
341
420
|
// Create entity map for looking up primary key types
|
|
342
421
|
const entityMap = new Map();
|
|
343
422
|
if (entities) {
|
|
344
|
-
entities.forEach(entity => {
|
|
423
|
+
entities.forEach((entity) => {
|
|
345
424
|
entityMap.set(entity.name, entity);
|
|
346
425
|
});
|
|
347
426
|
}
|
|
@@ -353,7 +432,8 @@ const getRelationshipForTemplate = (entityName, relationships, entities) => {
|
|
|
353
432
|
const refName = relationship.referenceName || "default";
|
|
354
433
|
const key = `${name}:${refName}`;
|
|
355
434
|
// Use the relationship with join=true if there are duplicates (this is the owning side)
|
|
356
|
-
if (!processedRefs.has(key) ||
|
|
435
|
+
if (!processedRefs.has(key) ||
|
|
436
|
+
(relationship.join && !((_a = processedRefs.get(key)) === null || _a === void 0 ? void 0 : _a.join))) {
|
|
357
437
|
processedRefs.set(key, relationship);
|
|
358
438
|
}
|
|
359
439
|
});
|
|
@@ -361,7 +441,7 @@ const getRelationshipForTemplate = (entityName, relationships, entities) => {
|
|
|
361
441
|
return [...processedRefs.values()].map((relationship) => {
|
|
362
442
|
const thisReferenceName = relationship.referenceName;
|
|
363
443
|
const relationshipName = (0, casing_1.camelCase)(thisReferenceName || relationship.name);
|
|
364
|
-
const needsPluralInverse = relationship.type ===
|
|
444
|
+
const needsPluralInverse = relationship.type === "ManyToOne" || relationship.type === "ManyToMany";
|
|
365
445
|
// DEBUG LOGGING
|
|
366
446
|
// if (process.env.DEBUG) {
|
|
367
447
|
// console.log(
|
|
@@ -373,13 +453,16 @@ const getRelationshipForTemplate = (entityName, relationships, entities) => {
|
|
|
373
453
|
// );
|
|
374
454
|
// }
|
|
375
455
|
const inverseSidePropertyName = calculateInversePropertyName(relationship, entityName, relationshipName, needsPluralInverse);
|
|
376
|
-
if (relationship.biDirectional &&
|
|
377
|
-
|
|
456
|
+
if (relationship.biDirectional &&
|
|
457
|
+
!relationship.inverseReferenceName &&
|
|
458
|
+
(relationship.type === "ManyToMany" ||
|
|
459
|
+
relationship.type === "OneToMany" ||
|
|
460
|
+
relationship.type === "OneToOne")) {
|
|
378
461
|
console.info(`[APSO INFO] Using default property name '${inverseSidePropertyName}' for ${relationship.name}->${entityName}. To customize, add 'to_name' in your relationship definition.`);
|
|
379
462
|
}
|
|
380
463
|
// Look up the referenced entity's primary key type
|
|
381
464
|
const referencedEntity = entityMap.get(relationship.name);
|
|
382
|
-
const referencedEntityPrimaryKeyType = (referencedEntity === null || referencedEntity === void 0 ? void 0 : referencedEntity.primaryKeyType) ||
|
|
465
|
+
const referencedEntityPrimaryKeyType = (referencedEntity === null || referencedEntity === void 0 ? void 0 : referencedEntity.primaryKeyType) || "serial"; // Default to 'serial' if not specified
|
|
383
466
|
return {
|
|
384
467
|
...relationship,
|
|
385
468
|
relationshipName,
|
|
@@ -477,7 +560,9 @@ function* generateNestedRelationships(entityName, relationshipMap, maxDepth = 4,
|
|
|
477
560
|
exports.generateNestedRelationships = generateNestedRelationships;
|
|
478
561
|
// In-memory collector
|
|
479
562
|
function getNestedRelationships(entityName, relationshipMap, maxDepth) {
|
|
480
|
-
return [
|
|
563
|
+
return [
|
|
564
|
+
...generateNestedRelationships(entityName, relationshipMap, maxDepth),
|
|
565
|
+
];
|
|
481
566
|
}
|
|
482
567
|
exports.getNestedRelationships = getNestedRelationships;
|
|
483
568
|
// Streaming function
|