@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
package/lint-cache/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli-lint-cache",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.17.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"devDependencies": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"eslint": "10.4.0"
|
|
9
9
|
},
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@dereekb/util": "13.
|
|
11
|
+
"@dereekb/util": "13.17.0",
|
|
12
12
|
"yargs": "^18.0.0"
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var tsMorph = require('ts-morph');
|
|
4
|
+
var dbxCli = require('@dereekb/dbx-cli');
|
|
4
5
|
|
|
5
6
|
function _define_property$1(obj, key, value) {
|
|
6
7
|
if (key in obj) {
|
|
@@ -30,7 +31,7 @@ function _object_spread$1(target) {
|
|
|
30
31
|
}
|
|
31
32
|
return target;
|
|
32
33
|
}
|
|
33
|
-
function ownKeys(object, enumerableOnly) {
|
|
34
|
+
function ownKeys$1(object, enumerableOnly) {
|
|
34
35
|
var keys = Object.keys(object);
|
|
35
36
|
if (Object.getOwnPropertySymbols) {
|
|
36
37
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -38,12 +39,12 @@ function ownKeys(object, enumerableOnly) {
|
|
|
38
39
|
}
|
|
39
40
|
return keys;
|
|
40
41
|
}
|
|
41
|
-
function _object_spread_props(target, source) {
|
|
42
|
+
function _object_spread_props$1(target, source) {
|
|
42
43
|
source = source != null ? source : {};
|
|
43
44
|
if (Object.getOwnPropertyDescriptors) {
|
|
44
45
|
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
45
46
|
} else {
|
|
46
|
-
ownKeys(Object(source)).forEach(function(key) {
|
|
47
|
+
ownKeys$1(Object(source)).forEach(function(key) {
|
|
47
48
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
48
49
|
});
|
|
49
50
|
}
|
|
@@ -295,14 +296,25 @@ function findFunctionsClassName(sourceFile) {
|
|
|
295
296
|
return result;
|
|
296
297
|
}
|
|
297
298
|
function inferGroupName(sourceFile) {
|
|
299
|
+
var _findTypeAliasStem;
|
|
300
|
+
return (_findTypeAliasStem = findTypeAliasStem(sourceFile, 'ModelCrudFunctionsConfig')) !== null && _findTypeAliasStem !== void 0 ? _findTypeAliasStem : findTypeAliasStem(sourceFile, 'FunctionTypeMap');
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Finds the first type alias whose name ends with `ending` and returns the
|
|
304
|
+
* non-empty stem (the name with `ending` stripped).
|
|
305
|
+
*
|
|
306
|
+
* @param sourceFile - The parsed `<model>.api.ts` source.
|
|
307
|
+
* @param ending - The type-alias name suffix to match.
|
|
308
|
+
* @returns The stem preceding `ending`, or `undefined` when no alias matches with a non-empty stem.
|
|
309
|
+
*/ function findTypeAliasStem(sourceFile, ending) {
|
|
298
310
|
var result;
|
|
299
311
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
300
312
|
try {
|
|
301
313
|
for(var _iterator = sourceFile.getTypeAliases()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
302
314
|
var alias = _step.value;
|
|
303
315
|
var name = alias.getName();
|
|
304
|
-
if (name.endsWith(
|
|
305
|
-
var stem = name.slice(0, -
|
|
316
|
+
if (name.endsWith(ending)) {
|
|
317
|
+
var stem = name.slice(0, -ending.length);
|
|
306
318
|
if (stem.length > 0) {
|
|
307
319
|
result = stem;
|
|
308
320
|
break;
|
|
@@ -323,35 +335,6 @@ function inferGroupName(sourceFile) {
|
|
|
323
335
|
}
|
|
324
336
|
}
|
|
325
337
|
}
|
|
326
|
-
if (result === undefined) {
|
|
327
|
-
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
328
|
-
try {
|
|
329
|
-
for(var _iterator1 = sourceFile.getTypeAliases()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
330
|
-
var alias1 = _step1.value;
|
|
331
|
-
var name1 = alias1.getName();
|
|
332
|
-
if (name1.endsWith('FunctionTypeMap')) {
|
|
333
|
-
var stem1 = name1.slice(0, -'FunctionTypeMap'.length);
|
|
334
|
-
if (stem1.length > 0) {
|
|
335
|
-
result = stem1;
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
} catch (err) {
|
|
341
|
-
_didIteratorError1 = true;
|
|
342
|
-
_iteratorError1 = err;
|
|
343
|
-
} finally{
|
|
344
|
-
try {
|
|
345
|
-
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
346
|
-
_iterator1.return();
|
|
347
|
-
}
|
|
348
|
-
} finally{
|
|
349
|
-
if (_didIteratorError1) {
|
|
350
|
-
throw _iteratorError1;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
338
|
return result;
|
|
356
339
|
}
|
|
357
340
|
function isNullLiteralType(node) {
|
|
@@ -473,68 +456,71 @@ function typeNodeName(node) {
|
|
|
473
456
|
return result;
|
|
474
457
|
}
|
|
475
458
|
function readTypeDocs(sourceFile, typeName) {
|
|
476
|
-
var result;
|
|
477
459
|
var interfaceDecl = sourceFile.getInterface(typeName);
|
|
460
|
+
var result;
|
|
478
461
|
if (interfaceDecl) {
|
|
479
|
-
|
|
480
|
-
var hasApiParamsTag = hasJsDocFlag(interfaceDecl, 'dbxModelApiParams');
|
|
481
|
-
var fields = [];
|
|
482
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
483
|
-
try {
|
|
484
|
-
for(var _iterator = interfaceDecl.getProperties()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
485
|
-
var property = _step.value;
|
|
486
|
-
var _ref;
|
|
487
|
-
var fieldName = property.getName();
|
|
488
|
-
var description = readJsDocSummary(property);
|
|
489
|
-
var typeNode = property.getTypeNode();
|
|
490
|
-
var typeText = (_ref = typeNode === null || typeNode === void 0 ? void 0 : typeNode.getText().trim()) !== null && _ref !== void 0 ? _ref : '';
|
|
491
|
-
var adminOnly = hasJsDocFlag(property, 'dbxModelApiAdminOnly');
|
|
492
|
-
var field = _object_spread$1({
|
|
493
|
-
name: fieldName,
|
|
494
|
-
typeText: typeText
|
|
495
|
-
}, description ? {
|
|
496
|
-
description: description
|
|
497
|
-
} : {}, adminOnly ? {
|
|
498
|
-
accessLevel: 'adminOnly'
|
|
499
|
-
} : {});
|
|
500
|
-
fields.push(field);
|
|
501
|
-
}
|
|
502
|
-
} catch (err) {
|
|
503
|
-
_didIteratorError = true;
|
|
504
|
-
_iteratorError = err;
|
|
505
|
-
} finally{
|
|
506
|
-
try {
|
|
507
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
508
|
-
_iterator.return();
|
|
509
|
-
}
|
|
510
|
-
} finally{
|
|
511
|
-
if (_didIteratorError) {
|
|
512
|
-
throw _iteratorError;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
517
|
-
result = _object_spread_props(_object_spread$1({}, typeDescription ? {
|
|
518
|
-
typeDescription: typeDescription
|
|
519
|
-
} : {}, fields.length > 0 ? {
|
|
520
|
-
fields: fields
|
|
521
|
-
} : {}), {
|
|
522
|
-
hasApiParamsTag: hasApiParamsTag
|
|
523
|
-
});
|
|
524
|
-
}
|
|
462
|
+
result = readInterfaceTypeDocs(interfaceDecl);
|
|
525
463
|
} else {
|
|
526
464
|
var typeAlias = sourceFile.getTypeAlias(typeName);
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
465
|
+
result = typeAlias ? readTypeAliasDocs(typeAlias) : undefined;
|
|
466
|
+
}
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Reads the type-level JSDoc (summary, fields, `@dbxModelApiParams` flag) of a
|
|
471
|
+
* resolved interface declaration.
|
|
472
|
+
*
|
|
473
|
+
* @param interfaceDecl - The interface naming a params/result type.
|
|
474
|
+
* @returns The collected docs, or `undefined` when the interface has no description, fields, or marker.
|
|
475
|
+
*/ function readInterfaceTypeDocs(interfaceDecl) {
|
|
476
|
+
var typeDescription = readJsDocSummary(interfaceDecl);
|
|
477
|
+
var hasApiParamsTag = hasJsDocFlag(interfaceDecl, 'dbxModelApiParams');
|
|
478
|
+
var fields = interfaceDecl.getProperties().map(function(property) {
|
|
479
|
+
return readInterfaceField(property);
|
|
480
|
+
});
|
|
481
|
+
var result;
|
|
482
|
+
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
483
|
+
result = _object_spread_props$1(_object_spread$1({}, typeDescription ? {
|
|
484
|
+
typeDescription: typeDescription
|
|
485
|
+
} : {}, fields.length > 0 ? {
|
|
486
|
+
fields: fields
|
|
487
|
+
} : {}), {
|
|
488
|
+
hasApiParamsTag: hasApiParamsTag
|
|
489
|
+
});
|
|
535
490
|
}
|
|
536
491
|
return result;
|
|
537
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Reads one interface property into a {@link CrudEntryDocField}, capturing its
|
|
495
|
+
* type text, JSDoc summary, and `@dbxModelApiAdminOnly` access level.
|
|
496
|
+
*
|
|
497
|
+
* @param property - The interface property signature.
|
|
498
|
+
* @returns The doc field for the property.
|
|
499
|
+
*/ function readInterfaceField(property) {
|
|
500
|
+
var _ref;
|
|
501
|
+
var _property_getTypeNode;
|
|
502
|
+
var description = readJsDocSummary(property);
|
|
503
|
+
var adminOnly = hasJsDocFlag(property, 'dbxModelApiAdminOnly');
|
|
504
|
+
return _object_spread$1({
|
|
505
|
+
name: property.getName(),
|
|
506
|
+
typeText: (_ref = (_property_getTypeNode = property.getTypeNode()) === null || _property_getTypeNode === void 0 ? void 0 : _property_getTypeNode.getText().trim()) !== null && _ref !== void 0 ? _ref : ''
|
|
507
|
+
}, description ? {
|
|
508
|
+
description: description
|
|
509
|
+
} : {}, adminOnly ? {
|
|
510
|
+
accessLevel: 'adminOnly'
|
|
511
|
+
} : {});
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Reads the type-level JSDoc summary of a resolved type alias.
|
|
515
|
+
*
|
|
516
|
+
* @param typeAlias - The type alias naming a params/result type.
|
|
517
|
+
* @returns The collected docs, or `undefined` when the alias has no description.
|
|
518
|
+
*/ function readTypeAliasDocs(typeAlias) {
|
|
519
|
+
var typeDescription = readJsDocSummary(typeAlias);
|
|
520
|
+
return typeDescription ? {
|
|
521
|
+
typeDescription: typeDescription
|
|
522
|
+
} : undefined;
|
|
523
|
+
}
|
|
538
524
|
/**
|
|
539
525
|
* Returns `true` when any JSDoc block on `node` carries the bare `@<tagName>` flag.
|
|
540
526
|
*
|
|
@@ -650,8 +636,8 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
650
636
|
function readJsDocSummary(node) {
|
|
651
637
|
var result;
|
|
652
638
|
var docs = node.getJsDocs();
|
|
653
|
-
|
|
654
|
-
|
|
639
|
+
var last = docs.at(-1);
|
|
640
|
+
if (last) {
|
|
655
641
|
var description = last.getDescription().trim();
|
|
656
642
|
if (description.length > 0) {
|
|
657
643
|
result = description;
|
|
@@ -688,6 +674,25 @@ function _object_spread(target) {
|
|
|
688
674
|
}
|
|
689
675
|
return target;
|
|
690
676
|
}
|
|
677
|
+
function ownKeys(object, enumerableOnly) {
|
|
678
|
+
var keys = Object.keys(object);
|
|
679
|
+
if (Object.getOwnPropertySymbols) {
|
|
680
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
681
|
+
keys.push.apply(keys, symbols);
|
|
682
|
+
}
|
|
683
|
+
return keys;
|
|
684
|
+
}
|
|
685
|
+
function _object_spread_props(target, source) {
|
|
686
|
+
source = source != null ? source : {};
|
|
687
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
688
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
689
|
+
} else {
|
|
690
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
691
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
return target;
|
|
695
|
+
}
|
|
691
696
|
var READ_LEVEL_VALUES = new Set([
|
|
692
697
|
'system',
|
|
693
698
|
'owner',
|
|
@@ -698,25 +703,6 @@ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
|
698
703
|
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
699
704
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
700
705
|
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
701
|
-
/**
|
|
702
|
-
* TS utility/structural wrappers that don't change the field surface for
|
|
703
|
-
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
704
|
-
* `NonNullable<T>` preserve every property, and `Pick<T, K>` / `Omit<T, K>`
|
|
705
|
-
* leave the original `T` reachable for long-name resolution. `MaybeMap<T>` is
|
|
706
|
-
* the workspace's own pass-through that decorates each prop with `Maybe<…>`
|
|
707
|
-
* without renaming. `extends` walks need to see through these to find the
|
|
708
|
-
* concrete ancestor interface — `getExpression()` alone returns just the
|
|
709
|
-
* leftmost identifier (`Partial`, `Pick`, …) and silently drops the inner
|
|
710
|
-
* model, leaving every inherited `@dbxModelVariable` tag unreachable.
|
|
711
|
-
*/ var PASSTHROUGH_TYPE_WRAPPERS = new Set([
|
|
712
|
-
'Partial',
|
|
713
|
-
'Required',
|
|
714
|
-
'Readonly',
|
|
715
|
-
'NonNullable',
|
|
716
|
-
'MaybeMap',
|
|
717
|
-
'Pick',
|
|
718
|
-
'Omit'
|
|
719
|
-
]);
|
|
720
706
|
var IDENTITY_FN = 'firestoreModelIdentity';
|
|
721
707
|
var CONVERTER_FN_NAMES = [
|
|
722
708
|
'snapshotConverterFunctions',
|
|
@@ -728,6 +714,7 @@ var OBJECT_ARRAY_FN = 'firestoreObjectArray';
|
|
|
728
714
|
var SNAPSHOT_FN = 'snapshotConverterFunctions';
|
|
729
715
|
var FIELDS_LITERAL_KEY = 'fields';
|
|
730
716
|
var OBJECT_FIELD_KEY = 'objectField';
|
|
717
|
+
var FIRESTORE_FIELD_KEY = 'firestoreField';
|
|
731
718
|
/**
|
|
732
719
|
* Walks a single source file and reports raw model-extraction artifacts.
|
|
733
720
|
* Best-effort: a malformed call shape leaves the corresponding entry out
|
|
@@ -774,7 +761,7 @@ function readIdentities(sourceFile) {
|
|
|
774
761
|
var initializer = decl.getInitializer();
|
|
775
762
|
if (!initializer || !tsMorph.Node.isCallExpression(initializer)) continue;
|
|
776
763
|
if (initializer.getExpression().getText() !== IDENTITY_FN) continue;
|
|
777
|
-
var parsed =
|
|
764
|
+
var parsed = dbxCli.parseFirestoreModelIdentityArgs(initializer.getArguments());
|
|
778
765
|
if (parsed) {
|
|
779
766
|
out.push(_object_spread({
|
|
780
767
|
identityConst: decl.getName()
|
|
@@ -812,48 +799,6 @@ function readIdentities(sourceFile) {
|
|
|
812
799
|
}
|
|
813
800
|
return out;
|
|
814
801
|
}
|
|
815
|
-
function parseIdentityArgs(call) {
|
|
816
|
-
var args = call.getArguments();
|
|
817
|
-
var result;
|
|
818
|
-
if (args.length === 1) {
|
|
819
|
-
var modelType = stringLiteralValue(args[0]);
|
|
820
|
-
if (modelType !== undefined) {
|
|
821
|
-
result = {
|
|
822
|
-
modelType: modelType,
|
|
823
|
-
collectionPrefix: undefined,
|
|
824
|
-
parentIdentityConst: undefined
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
} else if (args.length === 2) {
|
|
828
|
-
var first = stringLiteralValue(args[0]);
|
|
829
|
-
if (first === undefined) {
|
|
830
|
-
var modelType1 = stringLiteralValue(args[1]);
|
|
831
|
-
if (modelType1 !== undefined) {
|
|
832
|
-
result = {
|
|
833
|
-
modelType: modelType1,
|
|
834
|
-
collectionPrefix: undefined,
|
|
835
|
-
parentIdentityConst: identifierName(args[0])
|
|
836
|
-
};
|
|
837
|
-
}
|
|
838
|
-
} else {
|
|
839
|
-
result = {
|
|
840
|
-
modelType: first,
|
|
841
|
-
collectionPrefix: stringLiteralValue(args[1]),
|
|
842
|
-
parentIdentityConst: undefined
|
|
843
|
-
};
|
|
844
|
-
}
|
|
845
|
-
} else if (args.length >= 3) {
|
|
846
|
-
var modelType2 = stringLiteralValue(args[1]);
|
|
847
|
-
if (modelType2 !== undefined) {
|
|
848
|
-
result = {
|
|
849
|
-
modelType: modelType2,
|
|
850
|
-
collectionPrefix: stringLiteralValue(args[2]),
|
|
851
|
-
parentIdentityConst: identifierName(args[0])
|
|
852
|
-
};
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
return result;
|
|
856
|
-
}
|
|
857
802
|
function readInterfaces(sourceFile) {
|
|
858
803
|
var out = [];
|
|
859
804
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -884,7 +829,7 @@ function buildInterface(decl) {
|
|
|
884
829
|
var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
|
|
885
830
|
var dbxModelRead = readDbxModelReadTag(jsDocs);
|
|
886
831
|
var mcpToolNameSegment = readMcpToolNameSegmentTag(jsDocs);
|
|
887
|
-
var extendsNames = decl.getExtends().map(resolveExtendsName);
|
|
832
|
+
var extendsNames = decl.getExtends().map(dbxCli.resolveExtendsName);
|
|
888
833
|
var props = [];
|
|
889
834
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
890
835
|
try {
|
|
@@ -1134,48 +1079,6 @@ function readServiceFactoryModelType(jsDocs) {
|
|
|
1134
1079
|
}
|
|
1135
1080
|
return result;
|
|
1136
1081
|
}
|
|
1137
|
-
/**
|
|
1138
|
-
* Resolves an `extends` clause to the concrete ancestor interface name,
|
|
1139
|
-
* peeling any leading {@link PASSTHROUGH_TYPE_WRAPPERS}. Returns the leftmost
|
|
1140
|
-
* identifier of the unwrapped expression so the inheritance walker can chain
|
|
1141
|
-
* through utility-wrapped declarations like
|
|
1142
|
-
* `extends Partial<MaybeMap<Omit<Base, '…'>>>`.
|
|
1143
|
-
*
|
|
1144
|
-
* @param expr - The `ExpressionWithTypeArguments` produced by `getExtends()`
|
|
1145
|
-
* @returns The resolved interface name, or the original leftmost identifier when no inner reference is reachable.
|
|
1146
|
-
*/ function resolveExtendsName(expr) {
|
|
1147
|
-
var head = expr.getExpression().getText();
|
|
1148
|
-
var result = head;
|
|
1149
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(head)) {
|
|
1150
|
-
var typeArgs = expr.getTypeArguments();
|
|
1151
|
-
if (typeArgs.length > 0) {
|
|
1152
|
-
var peeled = peelTypeNode(typeArgs[0]);
|
|
1153
|
-
if (peeled !== undefined) {
|
|
1154
|
-
result = peeled;
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
return result;
|
|
1159
|
-
}
|
|
1160
|
-
function peelTypeNode(node) {
|
|
1161
|
-
var current = node;
|
|
1162
|
-
while(tsMorph.Node.isParenthesizedTypeNode(current)){
|
|
1163
|
-
current = current.getTypeNode();
|
|
1164
|
-
}
|
|
1165
|
-
var result;
|
|
1166
|
-
if (tsMorph.Node.isTypeReference(current)) {
|
|
1167
|
-
var name = current.getTypeName().getText();
|
|
1168
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(name)) {
|
|
1169
|
-
var inner = current.getTypeArguments();
|
|
1170
|
-
if (inner.length > 0) {
|
|
1171
|
-
result = peelTypeNode(inner[0]);
|
|
1172
|
-
}
|
|
1173
|
-
} else {
|
|
1174
|
-
result = name;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
return result;
|
|
1178
|
-
}
|
|
1179
1082
|
function readConverters(sourceFile) {
|
|
1180
1083
|
var out = [];
|
|
1181
1084
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1313,41 +1216,87 @@ function readNestedFromExpression(expr) {
|
|
|
1313
1216
|
if (tsMorph.Node.isCallExpression(expr)) {
|
|
1314
1217
|
var fnName = expr.getExpression().getText();
|
|
1315
1218
|
if (fnName === SUB_OBJECT_FN || fnName === OBJECT_ARRAY_FN) {
|
|
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
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1219
|
+
result = readNestedConverterCall(expr, fnName);
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return result;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Reads the `objectField` (or `firestoreField`) argument of a
|
|
1226
|
+
* `firestoreSubObject` / `firestoreObjectArray` call into a
|
|
1227
|
+
* {@link NestedConverterMatch}.
|
|
1228
|
+
*
|
|
1229
|
+
* `firestoreObjectArray`'s config is a union: `{ objectField }` describes the
|
|
1230
|
+
* element shape directly, while `{ firestoreField }` points the element decode
|
|
1231
|
+
* at another field converter (a sub-object const or an inline
|
|
1232
|
+
* `firestoreSubObject(...)`). Both carriers resolve through the same nested path
|
|
1233
|
+
* — the `firestoreField` variant is what the timesheet day-level form uses.
|
|
1234
|
+
*
|
|
1235
|
+
* @param call - The nested-converter call expression.
|
|
1236
|
+
* @param fnName - The resolved factory name (`firestoreSubObject` or `firestoreObjectArray`).
|
|
1237
|
+
* @returns The nested-converter match, or `undefined` when the call shape is malformed.
|
|
1238
|
+
*/ function readNestedConverterCall(call, fnName) {
|
|
1239
|
+
var result;
|
|
1240
|
+
var args = call.getArguments();
|
|
1241
|
+
if (args.length > 0) {
|
|
1242
|
+
var config = args[0];
|
|
1243
|
+
if (tsMorph.Node.isObjectLiteralExpression(config)) {
|
|
1244
|
+
var _readPropertyValue;
|
|
1245
|
+
var valueNode = (_readPropertyValue = readPropertyValue(config, OBJECT_FIELD_KEY)) !== null && _readPropertyValue !== void 0 ? _readPropertyValue : readPropertyValue(config, FIRESTORE_FIELD_KEY);
|
|
1246
|
+
if (valueNode) {
|
|
1247
|
+
result = buildNestedConverterMatch({
|
|
1248
|
+
objectField: valueNode,
|
|
1249
|
+
call: call,
|
|
1250
|
+
fnName: fnName
|
|
1251
|
+
});
|
|
1346
1252
|
}
|
|
1347
1253
|
}
|
|
1348
1254
|
}
|
|
1349
1255
|
return result;
|
|
1350
1256
|
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Builds a {@link NestedConverterMatch} from a resolved value node:
|
|
1259
|
+
* an identifier yields a converter `ref`, an object literal yields an `inline`
|
|
1260
|
+
* converter parsed from its `fields`, and a nested
|
|
1261
|
+
* `firestoreSubObject(...)` / `firestoreObjectArray(...)` call (the inline
|
|
1262
|
+
* `firestoreField: firestoreSubObject<T>({...})` form) is resolved recursively —
|
|
1263
|
+
* the outer factory still decides array-ness.
|
|
1264
|
+
*
|
|
1265
|
+
* @param input - The resolved value node, owning call expression, and factory name.
|
|
1266
|
+
* @returns The nested-converter match, or `undefined` when no shape applies.
|
|
1267
|
+
*/ function buildNestedConverterMatch(input) {
|
|
1268
|
+
var objectField = input.objectField, call = input.call, fnName = input.fnName;
|
|
1269
|
+
var isArray = fnName === OBJECT_ARRAY_FN;
|
|
1270
|
+
var result;
|
|
1271
|
+
if (tsMorph.Node.isIdentifier(objectField)) {
|
|
1272
|
+
result = {
|
|
1273
|
+
ref: objectField.getText(),
|
|
1274
|
+
isArray: isArray
|
|
1275
|
+
};
|
|
1276
|
+
} else if (tsMorph.Node.isObjectLiteralExpression(objectField)) {
|
|
1277
|
+
var fieldsLiteral = readObjectProperty(objectField, FIELDS_LITERAL_KEY);
|
|
1278
|
+
if (fieldsLiteral) {
|
|
1279
|
+
result = {
|
|
1280
|
+
inline: {
|
|
1281
|
+
converterConst: undefined,
|
|
1282
|
+
factory: fnName,
|
|
1283
|
+
interfaceName: readGenericInterfaceName(call),
|
|
1284
|
+
fields: readFieldEntries(fieldsLiteral),
|
|
1285
|
+
line: call.getStartLineNumber()
|
|
1286
|
+
},
|
|
1287
|
+
isArray: isArray
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
} else if (tsMorph.Node.isCallExpression(objectField)) {
|
|
1291
|
+
var nested = readNestedFromExpression(objectField);
|
|
1292
|
+
if (nested) {
|
|
1293
|
+
result = _object_spread_props(_object_spread({}, nested), {
|
|
1294
|
+
isArray: isArray
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
return result;
|
|
1299
|
+
}
|
|
1351
1300
|
function readPropertyValue(literal, key) {
|
|
1352
1301
|
var property = literal.getProperty(key);
|
|
1353
1302
|
var result;
|
|
@@ -1638,20 +1587,6 @@ function firstParagraph(text) {
|
|
|
1638
1587
|
}
|
|
1639
1588
|
return collected.join(' ').trim();
|
|
1640
1589
|
}
|
|
1641
|
-
function stringLiteralValue(node) {
|
|
1642
|
-
var result;
|
|
1643
|
-
if (tsMorph.Node.isStringLiteral(node) || tsMorph.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
1644
|
-
result = node.getLiteralText();
|
|
1645
|
-
}
|
|
1646
|
-
return result;
|
|
1647
|
-
}
|
|
1648
|
-
function identifierName(node) {
|
|
1649
|
-
var result;
|
|
1650
|
-
if (tsMorph.Node.isIdentifier(node)) {
|
|
1651
|
-
result = node.getText();
|
|
1652
|
-
}
|
|
1653
|
-
return result;
|
|
1654
|
-
}
|
|
1655
1590
|
|
|
1656
1591
|
exports.extractCrudEntries = extractCrudEntries;
|
|
1657
1592
|
exports.extractModelsFromSource = extractModelsFromSource;
|