@dereekb/dbx-cli 13.16.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 +177 -102
- package/firebase-api-manifest/package.json +3 -3
- package/generate-firestore-indexes/main.js +2 -2
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/main.js +8 -2
- 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 +4375 -1687
- package/index.esm.js +4355 -1688
- package/lint-cache/package.json +2 -2
- package/manifest-extract/index.cjs.js +54 -132
- package/manifest-extract/index.esm.js +53 -131
- 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/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
|
}
|
|
@@ -479,7 +480,7 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
479
480
|
});
|
|
480
481
|
var result;
|
|
481
482
|
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
482
|
-
result = _object_spread_props(_object_spread$1({}, typeDescription ? {
|
|
483
|
+
result = _object_spread_props$1(_object_spread$1({}, typeDescription ? {
|
|
483
484
|
typeDescription: typeDescription
|
|
484
485
|
} : {}, fields.length > 0 ? {
|
|
485
486
|
fields: fields
|
|
@@ -673,6 +674,25 @@ function _object_spread(target) {
|
|
|
673
674
|
}
|
|
674
675
|
return target;
|
|
675
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
|
+
}
|
|
676
696
|
var READ_LEVEL_VALUES = new Set([
|
|
677
697
|
'system',
|
|
678
698
|
'owner',
|
|
@@ -683,25 +703,6 @@ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
|
683
703
|
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
684
704
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
685
705
|
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
686
|
-
/**
|
|
687
|
-
* TS utility/structural wrappers that don't change the field surface for
|
|
688
|
-
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
689
|
-
* `NonNullable<T>` preserve every property, and `Pick<T, K>` / `Omit<T, K>`
|
|
690
|
-
* leave the original `T` reachable for long-name resolution. `MaybeMap<T>` is
|
|
691
|
-
* the workspace's own pass-through that decorates each prop with `Maybe<…>`
|
|
692
|
-
* without renaming. `extends` walks need to see through these to find the
|
|
693
|
-
* concrete ancestor interface — `getExpression()` alone returns just the
|
|
694
|
-
* leftmost identifier (`Partial`, `Pick`, …) and silently drops the inner
|
|
695
|
-
* model, leaving every inherited `@dbxModelVariable` tag unreachable.
|
|
696
|
-
*/ var PASSTHROUGH_TYPE_WRAPPERS = new Set([
|
|
697
|
-
'Partial',
|
|
698
|
-
'Required',
|
|
699
|
-
'Readonly',
|
|
700
|
-
'NonNullable',
|
|
701
|
-
'MaybeMap',
|
|
702
|
-
'Pick',
|
|
703
|
-
'Omit'
|
|
704
|
-
]);
|
|
705
706
|
var IDENTITY_FN = 'firestoreModelIdentity';
|
|
706
707
|
var CONVERTER_FN_NAMES = [
|
|
707
708
|
'snapshotConverterFunctions',
|
|
@@ -713,6 +714,7 @@ var OBJECT_ARRAY_FN = 'firestoreObjectArray';
|
|
|
713
714
|
var SNAPSHOT_FN = 'snapshotConverterFunctions';
|
|
714
715
|
var FIELDS_LITERAL_KEY = 'fields';
|
|
715
716
|
var OBJECT_FIELD_KEY = 'objectField';
|
|
717
|
+
var FIRESTORE_FIELD_KEY = 'firestoreField';
|
|
716
718
|
/**
|
|
717
719
|
* Walks a single source file and reports raw model-extraction artifacts.
|
|
718
720
|
* Best-effort: a malformed call shape leaves the corresponding entry out
|
|
@@ -759,7 +761,7 @@ function readIdentities(sourceFile) {
|
|
|
759
761
|
var initializer = decl.getInitializer();
|
|
760
762
|
if (!initializer || !tsMorph.Node.isCallExpression(initializer)) continue;
|
|
761
763
|
if (initializer.getExpression().getText() !== IDENTITY_FN) continue;
|
|
762
|
-
var parsed =
|
|
764
|
+
var parsed = dbxCli.parseFirestoreModelIdentityArgs(initializer.getArguments());
|
|
763
765
|
if (parsed) {
|
|
764
766
|
out.push(_object_spread({
|
|
765
767
|
identityConst: decl.getName()
|
|
@@ -797,48 +799,6 @@ function readIdentities(sourceFile) {
|
|
|
797
799
|
}
|
|
798
800
|
return out;
|
|
799
801
|
}
|
|
800
|
-
function parseIdentityArgs(call) {
|
|
801
|
-
var args = call.getArguments();
|
|
802
|
-
var result;
|
|
803
|
-
if (args.length === 1) {
|
|
804
|
-
var modelType = stringLiteralValue(args[0]);
|
|
805
|
-
if (modelType !== undefined) {
|
|
806
|
-
result = {
|
|
807
|
-
modelType: modelType,
|
|
808
|
-
collectionPrefix: undefined,
|
|
809
|
-
parentIdentityConst: undefined
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
} else if (args.length === 2) {
|
|
813
|
-
var first = stringLiteralValue(args[0]);
|
|
814
|
-
if (first === undefined) {
|
|
815
|
-
var modelType1 = stringLiteralValue(args[1]);
|
|
816
|
-
if (modelType1 !== undefined) {
|
|
817
|
-
result = {
|
|
818
|
-
modelType: modelType1,
|
|
819
|
-
collectionPrefix: undefined,
|
|
820
|
-
parentIdentityConst: identifierName(args[0])
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
} else {
|
|
824
|
-
result = {
|
|
825
|
-
modelType: first,
|
|
826
|
-
collectionPrefix: stringLiteralValue(args[1]),
|
|
827
|
-
parentIdentityConst: undefined
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
} else if (args.length >= 3) {
|
|
831
|
-
var modelType2 = stringLiteralValue(args[1]);
|
|
832
|
-
if (modelType2 !== undefined) {
|
|
833
|
-
result = {
|
|
834
|
-
modelType: modelType2,
|
|
835
|
-
collectionPrefix: stringLiteralValue(args[2]),
|
|
836
|
-
parentIdentityConst: identifierName(args[0])
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
return result;
|
|
841
|
-
}
|
|
842
802
|
function readInterfaces(sourceFile) {
|
|
843
803
|
var out = [];
|
|
844
804
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -869,7 +829,7 @@ function buildInterface(decl) {
|
|
|
869
829
|
var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
|
|
870
830
|
var dbxModelRead = readDbxModelReadTag(jsDocs);
|
|
871
831
|
var mcpToolNameSegment = readMcpToolNameSegmentTag(jsDocs);
|
|
872
|
-
var extendsNames = decl.getExtends().map(resolveExtendsName);
|
|
832
|
+
var extendsNames = decl.getExtends().map(dbxCli.resolveExtendsName);
|
|
873
833
|
var props = [];
|
|
874
834
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
875
835
|
try {
|
|
@@ -1119,48 +1079,6 @@ function readServiceFactoryModelType(jsDocs) {
|
|
|
1119
1079
|
}
|
|
1120
1080
|
return result;
|
|
1121
1081
|
}
|
|
1122
|
-
/**
|
|
1123
|
-
* Resolves an `extends` clause to the concrete ancestor interface name,
|
|
1124
|
-
* peeling any leading {@link PASSTHROUGH_TYPE_WRAPPERS}. Returns the leftmost
|
|
1125
|
-
* identifier of the unwrapped expression so the inheritance walker can chain
|
|
1126
|
-
* through utility-wrapped declarations like
|
|
1127
|
-
* `extends Partial<MaybeMap<Omit<Base, '…'>>>`.
|
|
1128
|
-
*
|
|
1129
|
-
* @param expr - The `ExpressionWithTypeArguments` produced by `getExtends()`
|
|
1130
|
-
* @returns The resolved interface name, or the original leftmost identifier when no inner reference is reachable.
|
|
1131
|
-
*/ function resolveExtendsName(expr) {
|
|
1132
|
-
var head = expr.getExpression().getText();
|
|
1133
|
-
var result = head;
|
|
1134
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(head)) {
|
|
1135
|
-
var typeArgs = expr.getTypeArguments();
|
|
1136
|
-
if (typeArgs.length > 0) {
|
|
1137
|
-
var peeled = peelTypeNode(typeArgs[0]);
|
|
1138
|
-
if (peeled !== undefined) {
|
|
1139
|
-
result = peeled;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
return result;
|
|
1144
|
-
}
|
|
1145
|
-
function peelTypeNode(node) {
|
|
1146
|
-
var current = node;
|
|
1147
|
-
while(tsMorph.Node.isParenthesizedTypeNode(current)){
|
|
1148
|
-
current = current.getTypeNode();
|
|
1149
|
-
}
|
|
1150
|
-
var result;
|
|
1151
|
-
if (tsMorph.Node.isTypeReference(current)) {
|
|
1152
|
-
var name = current.getTypeName().getText();
|
|
1153
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(name)) {
|
|
1154
|
-
var inner = current.getTypeArguments();
|
|
1155
|
-
if (inner.length > 0) {
|
|
1156
|
-
result = peelTypeNode(inner[0]);
|
|
1157
|
-
}
|
|
1158
|
-
} else {
|
|
1159
|
-
result = name;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
return result;
|
|
1163
|
-
}
|
|
1164
1082
|
function readConverters(sourceFile) {
|
|
1165
1083
|
var out = [];
|
|
1166
1084
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1304,8 +1222,15 @@ function readNestedFromExpression(expr) {
|
|
|
1304
1222
|
return result;
|
|
1305
1223
|
}
|
|
1306
1224
|
/**
|
|
1307
|
-
* Reads the `objectField` argument of a
|
|
1308
|
-
* `firestoreObjectArray` call into a
|
|
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.
|
|
1309
1234
|
*
|
|
1310
1235
|
* @param call - The nested-converter call expression.
|
|
1311
1236
|
* @param fnName - The resolved factory name (`firestoreSubObject` or `firestoreObjectArray`).
|
|
@@ -1316,10 +1241,11 @@ function readNestedFromExpression(expr) {
|
|
|
1316
1241
|
if (args.length > 0) {
|
|
1317
1242
|
var config = args[0];
|
|
1318
1243
|
if (tsMorph.Node.isObjectLiteralExpression(config)) {
|
|
1319
|
-
var
|
|
1320
|
-
|
|
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) {
|
|
1321
1247
|
result = buildNestedConverterMatch({
|
|
1322
|
-
objectField:
|
|
1248
|
+
objectField: valueNode,
|
|
1323
1249
|
call: call,
|
|
1324
1250
|
fnName: fnName
|
|
1325
1251
|
});
|
|
@@ -1329,12 +1255,15 @@ function readNestedFromExpression(expr) {
|
|
|
1329
1255
|
return result;
|
|
1330
1256
|
}
|
|
1331
1257
|
/**
|
|
1332
|
-
* Builds a {@link NestedConverterMatch} from a resolved
|
|
1258
|
+
* Builds a {@link NestedConverterMatch} from a resolved value node:
|
|
1333
1259
|
* an identifier yields a converter `ref`, an object literal yields an `inline`
|
|
1334
|
-
* converter parsed from its `fields
|
|
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.
|
|
1335
1264
|
*
|
|
1336
|
-
* @param input - The
|
|
1337
|
-
* @returns The nested-converter match, or `undefined` when
|
|
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.
|
|
1338
1267
|
*/ function buildNestedConverterMatch(input) {
|
|
1339
1268
|
var objectField = input.objectField, call = input.call, fnName = input.fnName;
|
|
1340
1269
|
var isArray = fnName === OBJECT_ARRAY_FN;
|
|
@@ -1358,6 +1287,13 @@ function readNestedFromExpression(expr) {
|
|
|
1358
1287
|
isArray: isArray
|
|
1359
1288
|
};
|
|
1360
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
|
+
}
|
|
1361
1297
|
}
|
|
1362
1298
|
return result;
|
|
1363
1299
|
}
|
|
@@ -1651,20 +1587,6 @@ function firstParagraph(text) {
|
|
|
1651
1587
|
}
|
|
1652
1588
|
return collected.join(' ').trim();
|
|
1653
1589
|
}
|
|
1654
|
-
function stringLiteralValue(node) {
|
|
1655
|
-
var result;
|
|
1656
|
-
if (tsMorph.Node.isStringLiteral(node) || tsMorph.Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
1657
|
-
result = node.getLiteralText();
|
|
1658
|
-
}
|
|
1659
|
-
return result;
|
|
1660
|
-
}
|
|
1661
|
-
function identifierName(node) {
|
|
1662
|
-
var result;
|
|
1663
|
-
if (tsMorph.Node.isIdentifier(node)) {
|
|
1664
|
-
result = node.getText();
|
|
1665
|
-
}
|
|
1666
|
-
return result;
|
|
1667
|
-
}
|
|
1668
1590
|
|
|
1669
1591
|
exports.extractCrudEntries = extractCrudEntries;
|
|
1670
1592
|
exports.extractModelsFromSource = extractModelsFromSource;
|
|
@@ -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
|
}
|
|
@@ -477,7 +478,7 @@ function readTypeDocs(sourceFile, typeName) {
|
|
|
477
478
|
});
|
|
478
479
|
var result;
|
|
479
480
|
if (typeDescription || fields.length > 0 || hasApiParamsTag) {
|
|
480
|
-
result = _object_spread_props(_object_spread$1({}, typeDescription ? {
|
|
481
|
+
result = _object_spread_props$1(_object_spread$1({}, typeDescription ? {
|
|
481
482
|
typeDescription: typeDescription
|
|
482
483
|
} : {}, fields.length > 0 ? {
|
|
483
484
|
fields: fields
|
|
@@ -671,6 +672,25 @@ function _object_spread(target) {
|
|
|
671
672
|
}
|
|
672
673
|
return target;
|
|
673
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
|
+
}
|
|
674
694
|
var READ_LEVEL_VALUES = new Set([
|
|
675
695
|
'system',
|
|
676
696
|
'owner',
|
|
@@ -681,25 +701,6 @@ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
|
|
|
681
701
|
var MCP_TOOL_NAME_SEGMENT_TAG = 'dbxModelMcpToolNameSegment';
|
|
682
702
|
var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
|
|
683
703
|
var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
|
|
684
|
-
/**
|
|
685
|
-
* TS utility/structural wrappers that don't change the field surface for
|
|
686
|
-
* inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
|
|
687
|
-
* `NonNullable<T>` preserve every property, and `Pick<T, K>` / `Omit<T, K>`
|
|
688
|
-
* leave the original `T` reachable for long-name resolution. `MaybeMap<T>` is
|
|
689
|
-
* the workspace's own pass-through that decorates each prop with `Maybe<…>`
|
|
690
|
-
* without renaming. `extends` walks need to see through these to find the
|
|
691
|
-
* concrete ancestor interface — `getExpression()` alone returns just the
|
|
692
|
-
* leftmost identifier (`Partial`, `Pick`, …) and silently drops the inner
|
|
693
|
-
* model, leaving every inherited `@dbxModelVariable` tag unreachable.
|
|
694
|
-
*/ var PASSTHROUGH_TYPE_WRAPPERS = new Set([
|
|
695
|
-
'Partial',
|
|
696
|
-
'Required',
|
|
697
|
-
'Readonly',
|
|
698
|
-
'NonNullable',
|
|
699
|
-
'MaybeMap',
|
|
700
|
-
'Pick',
|
|
701
|
-
'Omit'
|
|
702
|
-
]);
|
|
703
704
|
var IDENTITY_FN = 'firestoreModelIdentity';
|
|
704
705
|
var CONVERTER_FN_NAMES = [
|
|
705
706
|
'snapshotConverterFunctions',
|
|
@@ -711,6 +712,7 @@ var OBJECT_ARRAY_FN = 'firestoreObjectArray';
|
|
|
711
712
|
var SNAPSHOT_FN = 'snapshotConverterFunctions';
|
|
712
713
|
var FIELDS_LITERAL_KEY = 'fields';
|
|
713
714
|
var OBJECT_FIELD_KEY = 'objectField';
|
|
715
|
+
var FIRESTORE_FIELD_KEY = 'firestoreField';
|
|
714
716
|
/**
|
|
715
717
|
* Walks a single source file and reports raw model-extraction artifacts.
|
|
716
718
|
* Best-effort: a malformed call shape leaves the corresponding entry out
|
|
@@ -757,7 +759,7 @@ function readIdentities(sourceFile) {
|
|
|
757
759
|
var initializer = decl.getInitializer();
|
|
758
760
|
if (!initializer || !Node.isCallExpression(initializer)) continue;
|
|
759
761
|
if (initializer.getExpression().getText() !== IDENTITY_FN) continue;
|
|
760
|
-
var parsed =
|
|
762
|
+
var parsed = parseFirestoreModelIdentityArgs(initializer.getArguments());
|
|
761
763
|
if (parsed) {
|
|
762
764
|
out.push(_object_spread({
|
|
763
765
|
identityConst: decl.getName()
|
|
@@ -795,48 +797,6 @@ function readIdentities(sourceFile) {
|
|
|
795
797
|
}
|
|
796
798
|
return out;
|
|
797
799
|
}
|
|
798
|
-
function parseIdentityArgs(call) {
|
|
799
|
-
var args = call.getArguments();
|
|
800
|
-
var result;
|
|
801
|
-
if (args.length === 1) {
|
|
802
|
-
var modelType = stringLiteralValue(args[0]);
|
|
803
|
-
if (modelType !== undefined) {
|
|
804
|
-
result = {
|
|
805
|
-
modelType: modelType,
|
|
806
|
-
collectionPrefix: undefined,
|
|
807
|
-
parentIdentityConst: undefined
|
|
808
|
-
};
|
|
809
|
-
}
|
|
810
|
-
} else if (args.length === 2) {
|
|
811
|
-
var first = stringLiteralValue(args[0]);
|
|
812
|
-
if (first === undefined) {
|
|
813
|
-
var modelType1 = stringLiteralValue(args[1]);
|
|
814
|
-
if (modelType1 !== undefined) {
|
|
815
|
-
result = {
|
|
816
|
-
modelType: modelType1,
|
|
817
|
-
collectionPrefix: undefined,
|
|
818
|
-
parentIdentityConst: identifierName(args[0])
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
} else {
|
|
822
|
-
result = {
|
|
823
|
-
modelType: first,
|
|
824
|
-
collectionPrefix: stringLiteralValue(args[1]),
|
|
825
|
-
parentIdentityConst: undefined
|
|
826
|
-
};
|
|
827
|
-
}
|
|
828
|
-
} else if (args.length >= 3) {
|
|
829
|
-
var modelType2 = stringLiteralValue(args[1]);
|
|
830
|
-
if (modelType2 !== undefined) {
|
|
831
|
-
result = {
|
|
832
|
-
modelType: modelType2,
|
|
833
|
-
collectionPrefix: stringLiteralValue(args[2]),
|
|
834
|
-
parentIdentityConst: identifierName(args[0])
|
|
835
|
-
};
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return result;
|
|
839
|
-
}
|
|
840
800
|
function readInterfaces(sourceFile) {
|
|
841
801
|
var out = [];
|
|
842
802
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1117,48 +1077,6 @@ function readServiceFactoryModelType(jsDocs) {
|
|
|
1117
1077
|
}
|
|
1118
1078
|
return result;
|
|
1119
1079
|
}
|
|
1120
|
-
/**
|
|
1121
|
-
* Resolves an `extends` clause to the concrete ancestor interface name,
|
|
1122
|
-
* peeling any leading {@link PASSTHROUGH_TYPE_WRAPPERS}. Returns the leftmost
|
|
1123
|
-
* identifier of the unwrapped expression so the inheritance walker can chain
|
|
1124
|
-
* through utility-wrapped declarations like
|
|
1125
|
-
* `extends Partial<MaybeMap<Omit<Base, '…'>>>`.
|
|
1126
|
-
*
|
|
1127
|
-
* @param expr - The `ExpressionWithTypeArguments` produced by `getExtends()`
|
|
1128
|
-
* @returns The resolved interface name, or the original leftmost identifier when no inner reference is reachable.
|
|
1129
|
-
*/ function resolveExtendsName(expr) {
|
|
1130
|
-
var head = expr.getExpression().getText();
|
|
1131
|
-
var result = head;
|
|
1132
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(head)) {
|
|
1133
|
-
var typeArgs = expr.getTypeArguments();
|
|
1134
|
-
if (typeArgs.length > 0) {
|
|
1135
|
-
var peeled = peelTypeNode(typeArgs[0]);
|
|
1136
|
-
if (peeled !== undefined) {
|
|
1137
|
-
result = peeled;
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return result;
|
|
1142
|
-
}
|
|
1143
|
-
function peelTypeNode(node) {
|
|
1144
|
-
var current = node;
|
|
1145
|
-
while(Node.isParenthesizedTypeNode(current)){
|
|
1146
|
-
current = current.getTypeNode();
|
|
1147
|
-
}
|
|
1148
|
-
var result;
|
|
1149
|
-
if (Node.isTypeReference(current)) {
|
|
1150
|
-
var name = current.getTypeName().getText();
|
|
1151
|
-
if (PASSTHROUGH_TYPE_WRAPPERS.has(name)) {
|
|
1152
|
-
var inner = current.getTypeArguments();
|
|
1153
|
-
if (inner.length > 0) {
|
|
1154
|
-
result = peelTypeNode(inner[0]);
|
|
1155
|
-
}
|
|
1156
|
-
} else {
|
|
1157
|
-
result = name;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
return result;
|
|
1161
|
-
}
|
|
1162
1080
|
function readConverters(sourceFile) {
|
|
1163
1081
|
var out = [];
|
|
1164
1082
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
@@ -1302,8 +1220,15 @@ function readNestedFromExpression(expr) {
|
|
|
1302
1220
|
return result;
|
|
1303
1221
|
}
|
|
1304
1222
|
/**
|
|
1305
|
-
* Reads the `objectField` argument of a
|
|
1306
|
-
* `firestoreObjectArray` call into a
|
|
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.
|
|
1307
1232
|
*
|
|
1308
1233
|
* @param call - The nested-converter call expression.
|
|
1309
1234
|
* @param fnName - The resolved factory name (`firestoreSubObject` or `firestoreObjectArray`).
|
|
@@ -1314,10 +1239,11 @@ function readNestedFromExpression(expr) {
|
|
|
1314
1239
|
if (args.length > 0) {
|
|
1315
1240
|
var config = args[0];
|
|
1316
1241
|
if (Node.isObjectLiteralExpression(config)) {
|
|
1317
|
-
var
|
|
1318
|
-
|
|
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) {
|
|
1319
1245
|
result = buildNestedConverterMatch({
|
|
1320
|
-
objectField:
|
|
1246
|
+
objectField: valueNode,
|
|
1321
1247
|
call: call,
|
|
1322
1248
|
fnName: fnName
|
|
1323
1249
|
});
|
|
@@ -1327,12 +1253,15 @@ function readNestedFromExpression(expr) {
|
|
|
1327
1253
|
return result;
|
|
1328
1254
|
}
|
|
1329
1255
|
/**
|
|
1330
|
-
* Builds a {@link NestedConverterMatch} from a resolved
|
|
1256
|
+
* Builds a {@link NestedConverterMatch} from a resolved value node:
|
|
1331
1257
|
* an identifier yields a converter `ref`, an object literal yields an `inline`
|
|
1332
|
-
* converter parsed from its `fields
|
|
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.
|
|
1333
1262
|
*
|
|
1334
|
-
* @param input - The
|
|
1335
|
-
* @returns The nested-converter match, or `undefined` when
|
|
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.
|
|
1336
1265
|
*/ function buildNestedConverterMatch(input) {
|
|
1337
1266
|
var objectField = input.objectField, call = input.call, fnName = input.fnName;
|
|
1338
1267
|
var isArray = fnName === OBJECT_ARRAY_FN;
|
|
@@ -1356,6 +1285,13 @@ function readNestedFromExpression(expr) {
|
|
|
1356
1285
|
isArray: isArray
|
|
1357
1286
|
};
|
|
1358
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
|
+
}
|
|
1359
1295
|
}
|
|
1360
1296
|
return result;
|
|
1361
1297
|
}
|
|
@@ -1649,19 +1585,5 @@ function firstParagraph(text) {
|
|
|
1649
1585
|
}
|
|
1650
1586
|
return collected.join(' ').trim();
|
|
1651
1587
|
}
|
|
1652
|
-
function stringLiteralValue(node) {
|
|
1653
|
-
var result;
|
|
1654
|
-
if (Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)) {
|
|
1655
|
-
result = node.getLiteralText();
|
|
1656
|
-
}
|
|
1657
|
-
return result;
|
|
1658
|
-
}
|
|
1659
|
-
function identifierName(node) {
|
|
1660
|
-
var result;
|
|
1661
|
-
if (Node.isIdentifier(node)) {
|
|
1662
|
-
result = node.getText();
|
|
1663
|
-
}
|
|
1664
|
-
return result;
|
|
1665
|
-
}
|
|
1666
1588
|
|
|
1667
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.16.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';
|