@dereekb/dbx-cli 13.15.0 → 13.17.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/eslint/index.cjs.default.js +1 -0
- package/eslint/index.cjs.js +1050 -0
- package/eslint/index.cjs.mjs +2 -0
- package/eslint/index.d.ts +1 -0
- package/eslint/index.esm.js +1046 -0
- package/eslint/package.json +25 -0
- package/eslint/rollup.alias-internal.config.d.ts +11 -0
- package/eslint/src/index.d.ts +1 -0
- package/eslint/src/lib/index.d.ts +2 -0
- package/eslint/src/lib/plugin.d.ts +22 -0
- package/eslint/src/lib/valid-dbx-route-model-tags.rule.d.ts +59 -0
- package/firebase-api-manifest/main.js +318 -228
- package/firebase-api-manifest/package.json +3 -3
- package/generate-firestore-indexes/main.js +37 -24
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/main.js +57 -39
- package/generate-mcp-manifest/package.json +3 -3
- package/generate-route-manifest/main.js +1137 -0
- package/generate-route-manifest/package.json +10 -0
- package/index.cjs.js +4847 -1953
- package/index.esm.js +4827 -1954
- package/lint-cache/package.json +2 -2
- package/manifest-extract/index.cjs.js +175 -240
- package/manifest-extract/index.esm.js +174 -239
- package/manifest-extract/package.json +9 -4
- package/package.json +16 -6
- package/src/lib/index.d.ts +2 -0
- package/src/lib/manifest/types.d.ts +53 -0
- package/src/lib/mcp-scan/manifest/package-root.d.ts +17 -0
- package/src/lib/mcp-scan/manifest/tokens-schema.d.ts +5 -4
- package/src/lib/mcp-scan/scan/extract-models/assemble.d.ts +17 -0
- package/src/lib/route/component-resolve.d.ts +48 -0
- package/src/lib/route/index.d.ts +18 -0
- package/src/lib/route/route-build-tree.d.ts +31 -0
- package/src/lib/route/route-extract.d.ts +46 -0
- package/src/lib/route/route-load-tree.d.ts +17 -0
- package/src/lib/route/route-manifest.d.ts +132 -0
- package/src/lib/route/route-model-tag.d.ts +89 -0
- package/src/lib/route/route-models-extract.d.ts +22 -0
- package/src/lib/route/route-resolve-sources.d.ts +39 -0
- package/src/lib/route/route-types.d.ts +136 -0
- package/src/lib/route/url-match.d.ts +116 -0
- package/src/lib/scan-helpers/firestore-model-extract-utils.d.ts +43 -0
- package/test/index.cjs.js +1 -1
- package/test/index.esm.js +1 -1
- package/test/package.json +9 -9
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Project, Node } from 'ts-morph';
|
|
2
|
+
import { parseFirestoreModelIdentityArgs, resolveExtendsName } from '@dereekb/dbx-cli';
|
|
2
3
|
|
|
3
4
|
function _define_property$1(obj, key, value) {
|
|
4
5
|
if (key in obj) {
|
|
@@ -28,7 +29,7 @@ function _object_spread$1(target) {
|
|
|
28
29
|
}
|
|
29
30
|
return target;
|
|
30
31
|
}
|
|
31
|
-
function ownKeys(object, enumerableOnly) {
|
|
32
|
+
function ownKeys$1(object, enumerableOnly) {
|
|
32
33
|
var keys = Object.keys(object);
|
|
33
34
|
if (Object.getOwnPropertySymbols) {
|
|
34
35
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -36,12 +37,12 @@ function ownKeys(object, enumerableOnly) {
|
|
|
36
37
|
}
|
|
37
38
|
return keys;
|
|
38
39
|
}
|
|
39
|
-
function _object_spread_props(target, source) {
|
|
40
|
+
function _object_spread_props$1(target, source) {
|
|
40
41
|
source = source != null ? source : {};
|
|
41
42
|
if (Object.getOwnPropertyDescriptors) {
|
|
42
43
|
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
43
44
|
} else {
|
|
44
|
-
ownKeys(Object(source)).forEach(function(key) {
|
|
45
|
+
ownKeys$1(Object(source)).forEach(function(key) {
|
|
45
46
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
46
47
|
});
|
|
47
48
|
}
|
|
@@ -293,14 +294,25 @@ function findFunctionsClassName(sourceFile) {
|
|
|
293
294
|
return result;
|
|
294
295
|
}
|
|
295
296
|
function inferGroupName(sourceFile) {
|
|
297
|
+
var _findTypeAliasStem;
|
|
298
|
+
return (_findTypeAliasStem = findTypeAliasStem(sourceFile, 'ModelCrudFunctionsConfig')) !== null && _findTypeAliasStem !== void 0 ? _findTypeAliasStem : findTypeAliasStem(sourceFile, 'FunctionTypeMap');
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Finds the first type alias whose name ends with `ending` and returns the
|
|
302
|
+
* non-empty stem (the name with `ending` stripped).
|
|
303
|
+
*
|
|
304
|
+
* @param sourceFile - The parsed `<model>.api.ts` source.
|
|
305
|
+
* @param ending - The type-alias name suffix to match.
|
|
306
|
+
* @returns The stem preceding `ending`, or `undefined` when no alias matches with a non-empty stem.
|
|
307
|
+
*/ function findTypeAliasStem(sourceFile, ending) {
|
|
296
308
|
var result;
|
|
297
309
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
298
310
|
try {
|
|
299
311
|
for(var _iterator = sourceFile.getTypeAliases()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
300
312
|
var alias = _step.value;
|
|
301
313
|
var name = alias.getName();
|
|
302
|
-
if (name.endsWith(
|
|
303
|
-
var stem = name.slice(0, -
|
|
314
|
+
if (name.endsWith(ending)) {
|
|
315
|
+
var stem = name.slice(0, -ending.length);
|
|
304
316
|
if (stem.length > 0) {
|
|
305
317
|
result = stem;
|
|
306
318
|
break;
|
|
@@ -321,35 +333,6 @@ function inferGroupName(sourceFile) {
|
|
|
321
333
|
}
|
|
322
334
|
}
|
|
323
335
|
}
|
|
324
|
-
if (result === undefined) {
|
|
325
|
-
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
326
|
-
try {
|
|
327
|
-
for(var _iterator1 = sourceFile.getTypeAliases()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
328
|
-
var alias1 = _step1.value;
|
|
329
|
-
var name1 = alias1.getName();
|
|
330
|
-
if (name1.endsWith('FunctionTypeMap')) {
|
|
331
|
-
var stem1 = name1.slice(0, -'FunctionTypeMap'.length);
|
|
332
|
-
if (stem1.length > 0) {
|
|
333
|
-
result = stem1;
|
|
334
|
-
break;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
} catch (err) {
|
|
339
|
-
_didIteratorError1 = true;
|
|
340
|
-
_iteratorError1 = err;
|
|
341
|
-
} finally{
|
|
342
|
-
try {
|
|
343
|
-
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
344
|
-
_iterator1.return();
|
|
345
|
-
}
|
|
346
|
-
} finally{
|
|
347
|
-
if (_didIteratorError1) {
|
|
348
|
-
throw _iteratorError1;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
336
|
return result;
|
|
354
337
|
}
|
|
355
338
|
function isNullLiteralType(node) {
|
|
@@ -471,68 +454,71 @@ function typeNodeName(node) {
|
|
|
471
454
|
return result;
|
|
472
455
|
}
|
|
473
456
|
function readTypeDocs(sourceFile, typeName) {
|
|
474
|
-
var result;
|
|
475
457
|
var interfaceDecl = sourceFile.getInterface(typeName);
|
|
458
|
+
var result;
|
|
476
459
|
if (interfaceDecl) {
|
|
477
|
-
|
|
478
|
-
var hasApiParamsTag = hasJsDocFlag(interfaceDecl, 'dbxModelApiParams');
|
|
479
|
-
var fields = [];
|
|
480
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
481
|
-
try {
|
|
482
|
-
for(var _iterator = interfaceDecl.getProperties()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
483
|
-
var property = _step.value;
|
|
484
|
-
var _ref;
|
|
485
|
-
var fieldName = property.getName();
|
|
486
|
-
var description = readJsDocSummary(property);
|
|
487
|
-
var typeNode = property.getTypeNode();
|
|
488
|
-
var typeText = (_ref = typeNode === null || typeNode === void 0 ? void 0 : typeNode.getText().trim()) !== null && _ref !== void 0 ? _ref : '';
|
|
489
|
-
var adminOnly = hasJsDocFlag(property, 'dbxModelApiAdminOnly');
|
|
490
|
-
var field = _object_spread$1({
|
|
491
|
-
name: fieldName,
|
|
492
|
-
typeText: typeText
|
|
493
|
-
}, description ? {
|
|
494
|
-
description: description
|
|
495
|
-
} : {}, adminOnly ? {
|
|
496
|
-
accessLevel: 'adminOnly'
|
|
497
|
-
} : {});
|
|
498
|
-
fields.push(field);
|
|
499
|
-
}
|
|
500
|
-
} catch (err) {
|
|
501
|
-
_didIteratorError = true;
|
|
502
|
-
_iteratorError = err;
|
|
503
|
-
} finally{
|
|
504
|
-
try {
|
|
505
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
506
|
-
_iterator.return();
|
|
507
|
-
}
|
|
508
|
-
} finally{
|
|
509
|
-
if (_didIteratorError) {
|
|
510
|
-
throw _iteratorError;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
515
|
-
result = _object_spread_props(_object_spread$1({}, typeDescription ? {
|
|
516
|
-
typeDescription: typeDescription
|
|
517
|
-
} : {}, fields.length > 0 ? {
|
|
518
|
-
fields: fields
|
|
519
|
-
} : {}), {
|
|
520
|
-
hasApiParamsTag: hasApiParamsTag
|
|
521
|
-
});
|
|
522
|
-
}
|
|
460
|
+
result = readInterfaceTypeDocs(interfaceDecl);
|
|
523
461
|
} else {
|
|
524
462
|
var typeAlias = sourceFile.getTypeAlias(typeName);
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
463
|
+
result = typeAlias ? readTypeAliasDocs(typeAlias) : undefined;
|
|
464
|
+
}
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Reads the type-level JSDoc (summary, fields, `@dbxModelApiParams` flag) of a
|
|
469
|
+
* resolved interface declaration.
|
|
470
|
+
*
|
|
471
|
+
* @param interfaceDecl - The interface naming a params/result type.
|
|
472
|
+
* @returns The collected docs, or `undefined` when the interface has no description, fields, or marker.
|
|
473
|
+
*/ function readInterfaceTypeDocs(interfaceDecl) {
|
|
474
|
+
var typeDescription = readJsDocSummary(interfaceDecl);
|
|
475
|
+
var hasApiParamsTag = hasJsDocFlag(interfaceDecl, 'dbxModelApiParams');
|
|
476
|
+
var fields = interfaceDecl.getProperties().map(function(property) {
|
|
477
|
+
return readInterfaceField(property);
|
|
478
|
+
});
|
|
479
|
+
var result;
|
|
480
|
+
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
481
|
+
result = _object_spread_props$1(_object_spread$1({}, typeDescription ? {
|
|
482
|
+
typeDescription: typeDescription
|
|
483
|
+
} : {}, fields.length > 0 ? {
|
|
484
|
+
fields: fields
|
|
485
|
+
} : {}), {
|
|
486
|
+
hasApiParamsTag: hasApiParamsTag
|
|
487
|
+
});
|
|
533
488
|
}
|
|
534
489
|
return result;
|
|
535
490
|
}
|
|
491
|
+
/**
|
|
492
|
+
* Reads one interface property into a {@link CrudEntryDocField}, capturing its
|
|
493
|
+
* type text, JSDoc summary, and `@dbxModelApiAdminOnly` access level.
|
|
494
|
+
*
|
|
495
|
+
* @param property - The interface property signature.
|
|
496
|
+
* @returns The doc field for the property.
|
|
497
|
+
*/ function readInterfaceField(property) {
|
|
498
|
+
var _ref;
|
|
499
|
+
var _property_getTypeNode;
|
|
500
|
+
var description = readJsDocSummary(property);
|
|
501
|
+
var adminOnly = hasJsDocFlag(property, 'dbxModelApiAdminOnly');
|
|
502
|
+
return _object_spread$1({
|
|
503
|
+
name: property.getName(),
|
|
504
|
+
typeText: (_ref = (_property_getTypeNode = property.getTypeNode()) === null || _property_getTypeNode === void 0 ? void 0 : _property_getTypeNode.getText().trim()) !== null && _ref !== void 0 ? _ref : ''
|
|
505
|
+
}, description ? {
|
|
506
|
+
description: description
|
|
507
|
+
} : {}, adminOnly ? {
|
|
508
|
+
accessLevel: 'adminOnly'
|
|
509
|
+
} : {});
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Reads the type-level JSDoc summary of a resolved type alias.
|
|
513
|
+
*
|
|
514
|
+
* @param typeAlias - The type alias naming a params/result type.
|
|
515
|
+
* @returns The collected docs, or `undefined` when the alias has no description.
|
|
516
|
+
*/ function readTypeAliasDocs(typeAlias) {
|
|
517
|
+
var typeDescription = readJsDocSummary(typeAlias);
|
|
518
|
+
return typeDescription ? {
|
|
519
|
+
typeDescription: typeDescription
|
|
520
|
+
} : undefined;
|
|
521
|
+
}
|
|
536
522
|
/**
|
|
537
523
|
* Returns `true` when any JSDoc block on `node` carries the bare `@<tagName>` flag.
|
|
538
524
|
*
|
|
@@ -648,8 +634,8 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
648
634
|
function readJsDocSummary(node) {
|
|
649
635
|
var result;
|
|
650
636
|
var docs = node.getJsDocs();
|
|
651
|
-
|
|
652
|
-
|
|
637
|
+
var last = docs.at(-1);
|
|
638
|
+
if (last) {
|
|
653
639
|
var description = last.getDescription().trim();
|
|
654
640
|
if (description.length > 0) {
|
|
655
641
|
result = description;
|
|
@@ -686,6 +672,25 @@ function _object_spread(target) {
|
|
|
686
672
|
}
|
|
687
673
|
return target;
|
|
688
674
|
}
|
|
675
|
+
function ownKeys(object, enumerableOnly) {
|
|
676
|
+
var keys = Object.keys(object);
|
|
677
|
+
if (Object.getOwnPropertySymbols) {
|
|
678
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
679
|
+
keys.push.apply(keys, symbols);
|
|
680
|
+
}
|
|
681
|
+
return keys;
|
|
682
|
+
}
|
|
683
|
+
function _object_spread_props(target, source) {
|
|
684
|
+
source = source != null ? source : {};
|
|
685
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
686
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
687
|
+
} else {
|
|
688
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
689
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
return target;
|
|
693
|
+
}
|
|
689
694
|
var READ_LEVEL_VALUES = new Set([
|
|
690
695
|
'system',
|
|
691
696
|
'owner',
|
|
@@ -696,25 +701,6 @@ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
|
696
701
|
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
697
702
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
698
703
|
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
699
|
-
/**
|
|
700
|
-
* TS utility/structural wrappers that don't change the field surface for
|
|
701
|
-
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
702
|
-
* `NonNullable<T>` preserve every property, and `Pick<T, K>` / `Omit<T, K>`
|
|
703
|
-
* leave the original `T` reachable for long-name resolution. `MaybeMap<T>` is
|
|
704
|
-
* the workspace's own pass-through that decorates each prop with `Maybe<…>`
|
|
705
|
-
* without renaming. `extends` walks need to see through these to find the
|
|
706
|
-
* concrete ancestor interface — `getExpression()` alone returns just the
|
|
707
|
-
* leftmost identifier (`Partial`, `Pick`, …) and silently drops the inner
|
|
708
|
-
* model, leaving every inherited `@dbxModelVariable` tag unreachable.
|
|
709
|
-
*/ var PASSTHROUGH_TYPE_WRAPPERS = new Set([
|
|
710
|
-
'Partial',
|
|
711
|
-
'Required',
|
|
712
|
-
'Readonly',
|
|
713
|
-
'NonNullable',
|
|
714
|
-
'MaybeMap',
|
|
715
|
-
'Pick',
|
|
716
|
-
'Omit'
|
|
717
|
-
]);
|
|
718
704
|
var IDENTITY_FN = 'firestoreModelIdentity';
|
|
719
705
|
var CONVERTER_FN_NAMES = [
|
|
720
706
|
'snapshotConverterFunctions',
|
|
@@ -726,6 +712,7 @@ var OBJECT_ARRAY_FN = 'firestoreObjectArray';
|
|
|
726
712
|
var SNAPSHOT_FN = 'snapshotConverterFunctions';
|
|
727
713
|
var FIELDS_LITERAL_KEY = 'fields';
|
|
728
714
|
var OBJECT_FIELD_KEY = 'objectField';
|
|
715
|
+
var FIRESTORE_FIELD_KEY = 'firestoreField';
|
|
729
716
|
/**
|
|
730
717
|
* Walks a single source file and reports raw model-extraction artifacts.
|
|
731
718
|
* Best-effort: a malformed call shape leaves the corresponding entry out
|
|
@@ -772,7 +759,7 @@ function readIdentities(sourceFile) {
|
|
|
772
759
|
var initializer = decl.getInitializer();
|
|
773
760
|
if (!initializer || !Node.isCallExpression(initializer)) continue;
|
|
774
761
|
if (initializer.getExpression().getText() !== IDENTITY_FN) continue;
|
|
775
|
-
var parsed =
|
|
762
|
+
var parsed = parseFirestoreModelIdentityArgs(initializer.getArguments());
|
|
776
763
|
if (parsed) {
|
|
777
764
|
out.push(_object_spread({
|
|
778
765
|
identityConst: decl.getName()
|
|
@@ -810,48 +797,6 @@ function readIdentities(sourceFile) {
|
|
|
810
797
|
}
|
|
811
798
|
return out;
|
|
812
799
|
}
|
|
813
|
-
function parseIdentityArgs(call) {
|
|
814
|
-
var args = call.getArguments();
|
|
815
|
-
var result;
|
|
816
|
-
if (args.length === 1) {
|
|
817
|
-
var modelType = stringLiteralValue(args[0]);
|
|
818
|
-
if (modelType !== undefined) {
|
|
819
|
-
result = {
|
|
820
|
-
modelType: modelType,
|
|
821
|
-
collectionPrefix: undefined,
|
|
822
|
-
parentIdentityConst: undefined
|
|
823
|
-
};
|
|
824
|
-
}
|
|
825
|
-
} else if (args.length === 2) {
|
|
826
|
-
var first = stringLiteralValue(args[0]);
|
|
827
|
-
if (first === undefined) {
|
|
828
|
-
var modelType1 = stringLiteralValue(args[1]);
|
|
829
|
-
if (modelType1 !== undefined) {
|
|
830
|
-
result = {
|
|
831
|
-
modelType: modelType1,
|
|
832
|
-
collectionPrefix: undefined,
|
|
833
|
-
parentIdentityConst: identifierName(args[0])
|
|
834
|
-
};
|
|
835
|
-
}
|
|
836
|
-
} else {
|
|
837
|
-
result = {
|
|
838
|
-
modelType: first,
|
|
839
|
-
collectionPrefix: stringLiteralValue(args[1]),
|
|
840
|
-
parentIdentityConst: undefined
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
} else if (args.length >= 3) {
|
|
844
|
-
var modelType2 = stringLiteralValue(args[1]);
|
|
845
|
-
if (modelType2 !== undefined) {
|
|
846
|
-
result = {
|
|
847
|
-
modelType: modelType2,
|
|
848
|
-
collectionPrefix: stringLiteralValue(args[2]),
|
|
849
|
-
parentIdentityConst: identifierName(args[0])
|
|
850
|
-
};
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
return result;
|
|
854
|
-
}
|
|
855
800
|
function readInterfaces(sourceFile) {
|
|
856
801
|
var out = [];
|
|
857
802
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1132,48 +1077,6 @@ function readServiceFactoryModelType(jsDocs) {
|
|
|
1132
1077
|
}
|
|
1133
1078
|
return result;
|
|
1134
1079
|
}
|
|
1135
|
-
/**
|
|
1136
|
-
* Resolves an `extends` clause to the concrete ancestor interface name,
|
|
1137
|
-
* peeling any leading {@link PASSTHROUGH_TYPE_WRAPPERS}. Returns the leftmost
|
|
1138
|
-
* identifier of the unwrapped expression so the inheritance walker can chain
|
|
1139
|
-
* through utility-wrapped declarations like
|
|
1140
|
-
* `extends Partial<MaybeMap<Omit<Base, '…'>>>`.
|
|
1141
|
-
*
|
|
1142
|
-
* @param expr - The `ExpressionWithTypeArguments` produced by `getExtends()`
|
|
1143
|
-
* @returns The resolved interface name, or the original leftmost identifier when no inner reference is reachable.
|
|
1144
|
-
*/ function resolveExtendsName(expr) {
|
|
1145
|
-
var head = expr.getExpression().getText();
|
|
1146
|
-
var result = head;
|
|
1147
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(head)) {
|
|
1148
|
-
var typeArgs = expr.getTypeArguments();
|
|
1149
|
-
if (typeArgs.length > 0) {
|
|
1150
|
-
var peeled = peelTypeNode(typeArgs[0]);
|
|
1151
|
-
if (peeled !== undefined) {
|
|
1152
|
-
result = peeled;
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
return result;
|
|
1157
|
-
}
|
|
1158
|
-
function peelTypeNode(node) {
|
|
1159
|
-
var current = node;
|
|
1160
|
-
while(Node.isParenthesizedTypeNode(current)){
|
|
1161
|
-
current = current.getTypeNode();
|
|
1162
|
-
}
|
|
1163
|
-
var result;
|
|
1164
|
-
if (Node.isTypeReference(current)) {
|
|
1165
|
-
var name = current.getTypeName().getText();
|
|
1166
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(name)) {
|
|
1167
|
-
var inner = current.getTypeArguments();
|
|
1168
|
-
if (inner.length > 0) {
|
|
1169
|
-
result = peelTypeNode(inner[0]);
|
|
1170
|
-
}
|
|
1171
|
-
} else {
|
|
1172
|
-
result = name;
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
return result;
|
|
1176
|
-
}
|
|
1177
1080
|
function readConverters(sourceFile) {
|
|
1178
1081
|
var out = [];
|
|
1179
1082
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1311,41 +1214,87 @@ function readNestedFromExpression(expr) {
|
|
|
1311
1214
|
if (Node.isCallExpression(expr)) {
|
|
1312
1215
|
var fnName = expr.getExpression().getText();
|
|
1313
1216
|
if (fnName === SUB_OBJECT_FN || fnName === OBJECT_ARRAY_FN) {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1217
|
+
result = readNestedConverterCall(expr, fnName);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
return result;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Reads the `objectField` (or `firestoreField`) argument of a
|
|
1224
|
+
* `firestoreSubObject` / `firestoreObjectArray` call into a
|
|
1225
|
+
* {@link NestedConverterMatch}.
|
|
1226
|
+
*
|
|
1227
|
+
* `firestoreObjectArray`'s config is a union: `{ objectField }` describes the
|
|
1228
|
+
* element shape directly, while `{ firestoreField }` points the element decode
|
|
1229
|
+
* at another field converter (a sub-object const or an inline
|
|
1230
|
+
* `firestoreSubObject(...)`). Both carriers resolve through the same nested path
|
|
1231
|
+
* — the `firestoreField` variant is what the timesheet day-level form uses.
|
|
1232
|
+
*
|
|
1233
|
+
* @param call - The nested-converter call expression.
|
|
1234
|
+
* @param fnName - The resolved factory name (`firestoreSubObject` or `firestoreObjectArray`).
|
|
1235
|
+
* @returns The nested-converter match, or `undefined` when the call shape is malformed.
|
|
1236
|
+
*/ function readNestedConverterCall(call, fnName) {
|
|
1237
|
+
var result;
|
|
1238
|
+
var args = call.getArguments();
|
|
1239
|
+
if (args.length > 0) {
|
|
1240
|
+
var config = args[0];
|
|
1241
|
+
if (Node.isObjectLiteralExpression(config)) {
|
|
1242
|
+
var _readPropertyValue;
|
|
1243
|
+
var valueNode = (_readPropertyValue = readPropertyValue(config, OBJECT_FIELD_KEY)) !== null && _readPropertyValue !== void 0 ? _readPropertyValue : readPropertyValue(config, FIRESTORE_FIELD_KEY);
|
|
1244
|
+
if (valueNode) {
|
|
1245
|
+
result = buildNestedConverterMatch({
|
|
1246
|
+
objectField: valueNode,
|
|
1247
|
+
call: call,
|
|
1248
|
+
fnName: fnName
|
|
1249
|
+
});
|
|
1344
1250
|
}
|
|
1345
1251
|
}
|
|
1346
1252
|
}
|
|
1347
1253
|
return result;
|
|
1348
1254
|
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Builds a {@link NestedConverterMatch} from a resolved value node:
|
|
1257
|
+
* an identifier yields a converter `ref`, an object literal yields an `inline`
|
|
1258
|
+
* converter parsed from its `fields`, and a nested
|
|
1259
|
+
* `firestoreSubObject(...)` / `firestoreObjectArray(...)` call (the inline
|
|
1260
|
+
* `firestoreField: firestoreSubObject<T>({...})` form) is resolved recursively —
|
|
1261
|
+
* the outer factory still decides array-ness.
|
|
1262
|
+
*
|
|
1263
|
+
* @param input - The resolved value node, owning call expression, and factory name.
|
|
1264
|
+
* @returns The nested-converter match, or `undefined` when no shape applies.
|
|
1265
|
+
*/ function buildNestedConverterMatch(input) {
|
|
1266
|
+
var objectField = input.objectField, call = input.call, fnName = input.fnName;
|
|
1267
|
+
var isArray = fnName === OBJECT_ARRAY_FN;
|
|
1268
|
+
var result;
|
|
1269
|
+
if (Node.isIdentifier(objectField)) {
|
|
1270
|
+
result = {
|
|
1271
|
+
ref: objectField.getText(),
|
|
1272
|
+
isArray: isArray
|
|
1273
|
+
};
|
|
1274
|
+
} else if (Node.isObjectLiteralExpression(objectField)) {
|
|
1275
|
+
var fieldsLiteral = readObjectProperty(objectField, FIELDS_LITERAL_KEY);
|
|
1276
|
+
if (fieldsLiteral) {
|
|
1277
|
+
result = {
|
|
1278
|
+
inline: {
|
|
1279
|
+
converterConst: undefined,
|
|
1280
|
+
factory: fnName,
|
|
1281
|
+
interfaceName: readGenericInterfaceName(call),
|
|
1282
|
+
fields: readFieldEntries(fieldsLiteral),
|
|
1283
|
+
line: call.getStartLineNumber()
|
|
1284
|
+
},
|
|
1285
|
+
isArray: isArray
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
} else if (Node.isCallExpression(objectField)) {
|
|
1289
|
+
var nested = readNestedFromExpression(objectField);
|
|
1290
|
+
if (nested) {
|
|
1291
|
+
result = _object_spread_props(_object_spread({}, nested), {
|
|
1292
|
+
isArray: isArray
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return result;
|
|
1297
|
+
}
|
|
1349
1298
|
function readPropertyValue(literal, key) {
|
|
1350
1299
|
var property = literal.getProperty(key);
|
|
1351
1300
|
var result;
|
|
@@ -1636,19 +1585,5 @@ function firstParagraph(text) {
|
|
|
1636
1585
|
}
|
|
1637
1586
|
return collected.join(' ').trim();
|
|
1638
1587
|
}
|
|
1639
|
-
function stringLiteralValue(node) {
|
|
1640
|
-
var result;
|
|
1641
|
-
if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
1642
|
-
result = node.getLiteralText();
|
|
1643
|
-
}
|
|
1644
|
-
return result;
|
|
1645
|
-
}
|
|
1646
|
-
function identifierName(node) {
|
|
1647
|
-
var result;
|
|
1648
|
-
if (Node.isIdentifier(node)) {
|
|
1649
|
-
result = node.getText();
|
|
1650
|
-
}
|
|
1651
|
-
return result;
|
|
1652
|
-
}
|
|
1653
1588
|
|
|
1654
1589
|
export { extractCrudEntries, extractModelsFromSource };
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli/manifest-extract",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.17.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
+
"@dereekb/date": "13.15.0",
|
|
7
|
+
"@dereekb/dbx-cli": "13.17.0",
|
|
8
|
+
"@dereekb/firebase": "13.15.0",
|
|
9
|
+
"@dereekb/model": "13.15.0",
|
|
10
|
+
"@dereekb/nestjs": "13.15.0",
|
|
11
|
+
"@dereekb/rxjs": "13.15.0",
|
|
12
|
+
"@dereekb/util": "13.15.0",
|
|
13
|
+
"@dereekb/util-fetch": "13.15.0",
|
|
6
14
|
"ts-morph": "^21.0.0"
|
|
7
15
|
},
|
|
8
|
-
"devDependencies": {
|
|
9
|
-
"@dereekb/firebase": "13.15.0"
|
|
10
|
-
},
|
|
11
16
|
"exports": {
|
|
12
17
|
"./package.json": "./package.json",
|
|
13
18
|
".": {
|
package/package.json
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.17.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"bin": {
|
|
7
7
|
"dbx-cli-generate-firebase-api-manifest": "firebase-api-manifest/main.js",
|
|
8
8
|
"dbx-cli-generate-firestore-indexes": "generate-firestore-indexes/main.js",
|
|
9
9
|
"dbx-cli-generate-mcp-manifest": "generate-mcp-manifest/main.js",
|
|
10
|
+
"dbx-cli-generate-route-manifest": "generate-route-manifest/main.js",
|
|
10
11
|
"dbx-cli-lint-cache": "lint-cache/main.js"
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
14
|
+
"./eslint": {
|
|
15
|
+
"module": "./eslint/index.esm.js",
|
|
16
|
+
"types": "./eslint/index.d.ts",
|
|
17
|
+
"import": "./eslint/index.cjs.mjs",
|
|
18
|
+
"default": "./eslint/index.cjs.js"
|
|
19
|
+
},
|
|
13
20
|
"./firebase-api-manifest": {
|
|
14
21
|
"default": "./firebase-api-manifest/main.js"
|
|
15
22
|
},
|
|
@@ -19,6 +26,9 @@
|
|
|
19
26
|
"./generate-mcp-manifest": {
|
|
20
27
|
"default": "./generate-mcp-manifest/main.js"
|
|
21
28
|
},
|
|
29
|
+
"./generate-route-manifest": {
|
|
30
|
+
"default": "./generate-route-manifest/main.js"
|
|
31
|
+
},
|
|
22
32
|
"./lint-cache": {
|
|
23
33
|
"default": "./lint-cache/main.js"
|
|
24
34
|
},
|
|
@@ -50,11 +60,11 @@
|
|
|
50
60
|
}
|
|
51
61
|
},
|
|
52
62
|
"peerDependencies": {
|
|
53
|
-
"@dereekb/date": "13.
|
|
54
|
-
"@dereekb/firebase": "13.
|
|
55
|
-
"@dereekb/model": "13.
|
|
56
|
-
"@dereekb/nestjs": "13.
|
|
57
|
-
"@dereekb/util": "13.
|
|
63
|
+
"@dereekb/date": "13.17.0",
|
|
64
|
+
"@dereekb/firebase": "13.17.0",
|
|
65
|
+
"@dereekb/model": "13.17.0",
|
|
66
|
+
"@dereekb/nestjs": "13.17.0",
|
|
67
|
+
"@dereekb/util": "13.17.0",
|
|
58
68
|
"@nestjs/common": "^11.1.19",
|
|
59
69
|
"arktype": "^2.2.0",
|
|
60
70
|
"jiti": "2.6.1",
|
package/src/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './mcp-scan';
|
|
|
10
10
|
export * from './middleware';
|
|
11
11
|
export * from './scan-helpers/scan-io.js';
|
|
12
12
|
export * from './scan-helpers/scan-extract-utils.js';
|
|
13
|
+
export * from './scan-helpers/firestore-model-extract-utils.js';
|
|
13
14
|
export * from './output';
|
|
15
|
+
export * from './route';
|
|
14
16
|
export * from './runner';
|
|
15
17
|
export * from './util';
|