@dereekb/dbx-cli 13.41.0 → 13.43.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/package.json +3 -3
- package/firebase-api-manifest/main.js +177 -21
- package/firebase-api-manifest/package.json +3 -3
- package/firestore-indexes/src/generate-firestore-indexes-cli.d.ts +12 -4
- package/firestore-indexes/src/model-firebase-index-analyze.d.ts +12 -2
- package/firestore-query-manifest/main.js +26 -14
- package/firestore-query-manifest/package.json +3 -3
- package/generate-firestore-indexes/main.js +118 -20
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/main.js +5 -2
- package/generate-mcp-manifest/package.json +3 -3
- package/generate-route-manifest/main.js +1 -1
- package/generate-route-manifest/package.json +2 -2
- package/index.esm.js +2651 -1387
- package/lint-cache/package.json +2 -2
- package/manifest-extract/index.esm.js +148 -2
- package/manifest-extract/package.json +2 -2
- package/manifest-extract/src/lib/extract-models.d.ts +4 -2
- package/manifest-extract/src/lib/types.d.ts +65 -0
- package/model-test/index.esm.js +4 -54
- package/model-test/package.json +2 -2
- package/package.json +6 -6
- package/route/package.json +7 -7
- package/src/lib/doctor/build-drift.check.d.ts +21 -0
- package/src/lib/doctor/doctor.command.factory.d.ts +21 -2
- package/src/lib/doctor/firestore-session.check.d.ts +7 -1
- package/src/lib/doctor/index.d.ts +1 -0
- package/src/lib/firestore/firestore.sdk-identity.d.ts +193 -0
- package/src/lib/firestore/index.d.ts +1 -0
- package/src/lib/manifest/types.d.ts +73 -2
- package/src/lib/mcp-scan/manifest/css-utilities-schema.d.ts +2 -2
- package/src/lib/mcp-scan/manifest/tokens-schema.d.ts +2 -2
- package/src/lib/runner/build-stamp.d.ts +138 -0
- package/src/lib/runner/index.d.ts +1 -0
- package/src/lib/runner/run.d.ts +13 -0
- package/test/package.json +9 -9
- package/validate/index.js +17 -7
- package/validate/package.json +3 -3
|
@@ -5,14 +5,14 @@ const require = __createRequire(import.meta.url);
|
|
|
5
5
|
// packages/dbx-cli/generate-firestore-indexes/package.json
|
|
6
6
|
var package_default = {
|
|
7
7
|
name: "@dereekb/dbx-cli-generate-firestore-indexes",
|
|
8
|
-
version: "13.
|
|
8
|
+
version: "13.43.0",
|
|
9
9
|
private: true,
|
|
10
10
|
type: "module",
|
|
11
11
|
devDependencies: {
|
|
12
12
|
eslint: "10.4.0"
|
|
13
13
|
},
|
|
14
14
|
peerDependencies: {
|
|
15
|
-
"@dereekb/dbx-cli": "13.
|
|
15
|
+
"@dereekb/dbx-cli": "13.43.0"
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
|
|
@@ -438,11 +438,18 @@ function analyzeSequence(input) {
|
|
|
438
438
|
if (isSingleFieldQuery(buckets)) {
|
|
439
439
|
return analyzeSingleField({ buckets, collection, scope, warnings });
|
|
440
440
|
}
|
|
441
|
+
if (scope === "COLLECTION" && isEqualityOnlySequence(buckets)) {
|
|
442
|
+
warnings.push({ kind: "equality-only-composite-skipped", factoryName, fields: buckets.equalities.map((e) => e.fieldPath) });
|
|
443
|
+
return { kind: "auto", warnings };
|
|
444
|
+
}
|
|
441
445
|
return analyzeMultiField({ buckets, sequenceEntries: sequence.entries, collection, scope, factoryName, warnings });
|
|
442
446
|
}
|
|
443
447
|
function isSingleFieldQuery(buckets) {
|
|
444
448
|
return buckets.distinctFieldCount === 1;
|
|
445
449
|
}
|
|
450
|
+
function isEqualityOnlySequence(buckets) {
|
|
451
|
+
return buckets.ranges.length === 0 && buckets.arrays.length === 0 && buckets.orderBys.length === 0 && buckets.equalities.length > 0 && buckets.equalities.every((e) => (e.operator ?? "==") === "==");
|
|
452
|
+
}
|
|
446
453
|
function analyzeSingleField(input) {
|
|
447
454
|
const { buckets, collection, scope, warnings } = input;
|
|
448
455
|
if (scope === "COLLECTION") {
|
|
@@ -537,7 +544,7 @@ function collectOrderByDirections(input) {
|
|
|
537
544
|
}
|
|
538
545
|
}
|
|
539
546
|
for (const [field, dirs] of conflicts) {
|
|
540
|
-
warnings.push({ kind: "orderby-conflict", factoryName, field, directions:
|
|
547
|
+
warnings.push({ kind: "orderby-conflict", factoryName, field, directions: Array.from(dirs) });
|
|
541
548
|
}
|
|
542
549
|
return out;
|
|
543
550
|
}
|
|
@@ -1018,7 +1025,7 @@ function composeEntry(input) {
|
|
|
1018
1025
|
}
|
|
1019
1026
|
function resolveConstraintSequences(input) {
|
|
1020
1027
|
const { candidate, tags, name, line, filePath, warnings } = input;
|
|
1021
|
-
const bodyResult = extractConstraintsFromBody({ decl: candidate.decl, factoryName: name, filePath, dispatcher: tags.dispatcher });
|
|
1028
|
+
const bodyResult = extractConstraintsFromBody({ decl: candidate.decl, factoryName: name, filePath, dispatcher: tags.dispatcher, suppressed: tags.skip || tags.specOnly });
|
|
1022
1029
|
for (const warning of bodyResult.warnings) {
|
|
1023
1030
|
warnings.push(warning);
|
|
1024
1031
|
}
|
|
@@ -1099,11 +1106,14 @@ function buildConstraintSequences(input) {
|
|
|
1099
1106
|
return sequences;
|
|
1100
1107
|
}
|
|
1101
1108
|
function extractConstraintsFromBody(input) {
|
|
1102
|
-
const { decl, factoryName, filePath, dispatcher } = input;
|
|
1109
|
+
const { decl, factoryName, filePath, dispatcher, suppressed } = input;
|
|
1103
1110
|
const entries = [];
|
|
1104
1111
|
const conditionalFieldSet = /* @__PURE__ */ new Set();
|
|
1105
1112
|
const warnings = [];
|
|
1106
1113
|
const body = decl.getBody();
|
|
1114
|
+
if (suppressed) {
|
|
1115
|
+
return { entries, conditionalFields: [], warnings, skipped: true, dispatcherDelegates: [] };
|
|
1116
|
+
}
|
|
1107
1117
|
if (dispatcher) {
|
|
1108
1118
|
const violation = body === void 0 ? void 0 : findFirstConstraintCall(body);
|
|
1109
1119
|
if (violation !== void 0) {
|
|
@@ -1901,6 +1911,76 @@ function assembleEntry(input) {
|
|
|
1901
1911
|
};
|
|
1902
1912
|
return out;
|
|
1903
1913
|
}
|
|
1914
|
+
function formatModelFirebaseIndexBuildWarning(warning) {
|
|
1915
|
+
let result2;
|
|
1916
|
+
if (warning.stage === "extract") {
|
|
1917
|
+
const w = warning.warning;
|
|
1918
|
+
switch (w.kind) {
|
|
1919
|
+
case "missing-name":
|
|
1920
|
+
result2 = `(anonymous) (${w.filePath}:${w.line}) tagged export has no resolvable name`;
|
|
1921
|
+
break;
|
|
1922
|
+
case "missing-model-tag":
|
|
1923
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) missing required @dbxModelFirebaseIndexModel tag`;
|
|
1924
|
+
break;
|
|
1925
|
+
case "unresolved-model":
|
|
1926
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) could not resolve model "${w.model}" to a Firestore identity`;
|
|
1927
|
+
break;
|
|
1928
|
+
case "unsupported-scope":
|
|
1929
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) unsupported @dbxModelFirebaseIndexScope value "${w.scope}"`;
|
|
1930
|
+
break;
|
|
1931
|
+
case "duplicate-slug":
|
|
1932
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) duplicate slug "${w.slug}" \u2014 already used by ${w.previousName}`;
|
|
1933
|
+
break;
|
|
1934
|
+
case "unknown-helper":
|
|
1935
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) unknown constraint helper "${w.helper}"`;
|
|
1936
|
+
break;
|
|
1937
|
+
case "unresolved-field":
|
|
1938
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) could not resolve field-path argument to "${w.callee}"`;
|
|
1939
|
+
break;
|
|
1940
|
+
case "missing-paths":
|
|
1941
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) missing path coverage for conditional fields [${w.conditionalFields.join(", ")}]`;
|
|
1942
|
+
break;
|
|
1943
|
+
case "unknown-path-field":
|
|
1944
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) @dbxModelFirebaseIndexPath references unknown field "${w.field}"`;
|
|
1945
|
+
break;
|
|
1946
|
+
case "unannotated-query-helper":
|
|
1947
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) calls query helper "${w.callee}" (${w.calleeFilePath}:${w.calleeLine}) that is not tagged with @dbxModelFirebaseIndexHelper`;
|
|
1948
|
+
break;
|
|
1949
|
+
case "transitive-cycle":
|
|
1950
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) transitive constraint resolution hit a cycle through "${w.callee}"`;
|
|
1951
|
+
break;
|
|
1952
|
+
case "unresolvable-transitive-callee":
|
|
1953
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) could not resolve transitive callee "${w.callee}"`;
|
|
1954
|
+
break;
|
|
1955
|
+
case "complex-query-body":
|
|
1956
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) tagged query body contains a "${w.branchKind}" construct \u2014 split into one factory per target index or mark as @dbxModelFirebaseIndexDispatcher`;
|
|
1957
|
+
break;
|
|
1958
|
+
case "non-delegating-dispatcher":
|
|
1959
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) @dbxModelFirebaseIndexDispatcher calls "${w.callee}" directly \u2014 dispatchers must only delegate to other tagged query functions`;
|
|
1960
|
+
break;
|
|
1961
|
+
case "excluded-factory":
|
|
1962
|
+
result2 = `${w.name} (${w.filePath}:${w.line}) tagged @dbxModelFirebaseIndexExclude \u2014 analyzer is suppressing composites + fieldOverrides for this factory`;
|
|
1963
|
+
break;
|
|
1964
|
+
}
|
|
1965
|
+
} else {
|
|
1966
|
+
const w = warning.warning;
|
|
1967
|
+
switch (w.kind) {
|
|
1968
|
+
case "multiple-range-fields":
|
|
1969
|
+
result2 = `${w.factoryName} multiple range-field constraints on [${w.fields.join(", ")}] \u2014 Firestore allows only one range field per query`;
|
|
1970
|
+
break;
|
|
1971
|
+
case "orderby-conflict":
|
|
1972
|
+
result2 = `${w.factoryName} field "${w.field}" has conflicting orderBy directions [${w.directions.join(", ")}]`;
|
|
1973
|
+
break;
|
|
1974
|
+
case "unsupported-array-contains-any":
|
|
1975
|
+
result2 = `${w.factoryName} field "${w.field}" uses array-contains-any \u2014 index support is partial`;
|
|
1976
|
+
break;
|
|
1977
|
+
case "equality-only-composite-skipped":
|
|
1978
|
+
result2 = `${w.factoryName} is equality-only on [${w.fields.join(", ")}] \u2014 no composite emitted, Firestore serves this by merging the automatic single-field indexes`;
|
|
1979
|
+
break;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return result2;
|
|
1983
|
+
}
|
|
1904
1984
|
|
|
1905
1985
|
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-runtime.ts
|
|
1906
1986
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -2000,12 +2080,13 @@ function pushInto(map, key, entry) {
|
|
|
2000
2080
|
var DEFAULT_BIN_NAME = "dbx-cli-generate-firestore-indexes";
|
|
2001
2081
|
function buildUsage(binName) {
|
|
2002
2082
|
return [
|
|
2003
|
-
`Usage: ${binName} --component <dir> [--output <path>] [--check] [--json] [--help]`,
|
|
2083
|
+
`Usage: ${binName} --component <dir> [--component <dir> ...] [--output <path>] [--check] [--json] [--help]`,
|
|
2004
2084
|
"",
|
|
2005
2085
|
"Generates `firestore.indexes.json` from `@dbxModelFirebaseIndex`-tagged factories.",
|
|
2006
2086
|
"",
|
|
2007
2087
|
"Options:",
|
|
2008
|
-
" --component <dir> Required. Relative path to
|
|
2088
|
+
" --component <dir> Required, repeatable. Relative path to a `-firebase` component or package.",
|
|
2089
|
+
" Repeat to derive one indexes file from several packages at once.",
|
|
2009
2090
|
" --output <path> Output path. Defaults to `firestore.indexes.json` at the cwd.",
|
|
2010
2091
|
" --check Compare against the on-disk file; exit 1 on drift, do not write.",
|
|
2011
2092
|
" --json Print the diff summary as JSON instead of human-readable text.",
|
|
@@ -2025,23 +2106,40 @@ async function runGenerateFirestoreIndexesCli(input) {
|
|
|
2025
2106
|
stderr(usage);
|
|
2026
2107
|
return { exitCode: 2 };
|
|
2027
2108
|
}
|
|
2028
|
-
if (parsed.
|
|
2109
|
+
if (parsed.components.length === 0) {
|
|
2029
2110
|
stderr("generate-firestore-indexes: --component is required");
|
|
2030
2111
|
stderr(usage);
|
|
2031
2112
|
return { exitCode: 2 };
|
|
2032
2113
|
}
|
|
2033
|
-
const componentAbs = resolve2(cwd, parsed.component);
|
|
2034
2114
|
const outputAbs = resolve2(cwd, parsed.output);
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2115
|
+
const entries = [];
|
|
2116
|
+
const loadedSources = [];
|
|
2117
|
+
let sawUnresolvedModel = false;
|
|
2118
|
+
for (const component of parsed.components) {
|
|
2119
|
+
const buildOutcome = await buildModelFirebaseIndexManifest({
|
|
2120
|
+
projectRoot: resolve2(cwd, component),
|
|
2121
|
+
generator
|
|
2122
|
+
});
|
|
2123
|
+
if (buildOutcome.kind !== "success") {
|
|
2124
|
+
stderr(formatBuildFailure(buildOutcome));
|
|
2125
|
+
return { exitCode: 1 };
|
|
2126
|
+
}
|
|
2127
|
+
for (const warning of buildOutcome.extractWarnings) {
|
|
2128
|
+
stderr(`${warning.stage}-warning: ${formatModelFirebaseIndexBuildWarning(warning)}`);
|
|
2129
|
+
if (warning.stage === "extract" && warning.warning.kind === "unresolved-model") {
|
|
2130
|
+
sawUnresolvedModel = true;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
for (const entry of buildOutcome.manifest.entries) {
|
|
2134
|
+
entries.push(toModelFirebaseIndexEntryInfo(entry));
|
|
2135
|
+
}
|
|
2136
|
+
loadedSources.push(buildOutcome.manifest.source);
|
|
2137
|
+
}
|
|
2138
|
+
if (sawUnresolvedModel) {
|
|
2139
|
+
stderr("generate-firestore-indexes: one or more @dbxModelFirebaseIndexModel tags could not be resolved, so their indexes were dropped. Add the missing identity file to the component\u2019s `dbx-mcp.scan.json` include globs.");
|
|
2041
2140
|
return { exitCode: 1 };
|
|
2042
2141
|
}
|
|
2043
|
-
const
|
|
2044
|
-
const registry = createModelFirebaseIndexRegistryFromEntries({ entries, loadedSources: [buildOutcome.manifest.source] });
|
|
2142
|
+
const registry = createModelFirebaseIndexRegistryFromEntries({ entries, loadedSources });
|
|
2045
2143
|
const existingJson = await readExistingIndexes({ outputAbs, readFile, stderr });
|
|
2046
2144
|
const { json, diff } = generateFirestoreIndexesJson({ entries: registry.all, existingJson });
|
|
2047
2145
|
const serialized = serializeFirestoreIndexesJson(json);
|
|
@@ -2064,7 +2162,7 @@ async function runGenerateFirestoreIndexesCli(input) {
|
|
|
2064
2162
|
return { exitCode: 0 };
|
|
2065
2163
|
}
|
|
2066
2164
|
function parseArgv(argv) {
|
|
2067
|
-
|
|
2165
|
+
const components = [];
|
|
2068
2166
|
let output = "firestore.indexes.json";
|
|
2069
2167
|
let check = false;
|
|
2070
2168
|
let json = false;
|
|
@@ -2079,7 +2177,7 @@ function parseArgv(argv) {
|
|
|
2079
2177
|
if (i >= argv.length) {
|
|
2080
2178
|
error = "generate-firestore-indexes: --component requires a value";
|
|
2081
2179
|
} else {
|
|
2082
|
-
|
|
2180
|
+
components.push(argv[i]);
|
|
2083
2181
|
}
|
|
2084
2182
|
break;
|
|
2085
2183
|
case "--output":
|
|
@@ -2106,7 +2204,7 @@ function parseArgv(argv) {
|
|
|
2106
2204
|
}
|
|
2107
2205
|
i += 1;
|
|
2108
2206
|
}
|
|
2109
|
-
return {
|
|
2207
|
+
return { components, output, check, json, help, error };
|
|
2110
2208
|
}
|
|
2111
2209
|
async function readExistingIndexes(input) {
|
|
2112
2210
|
const text = await readExistingIndexesText(input);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli-generate-firestore-indexes",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.43.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"eslint": "10.4.0"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"@dereekb/dbx-cli": "13.
|
|
10
|
+
"@dereekb/dbx-cli": "13.43.0"
|
|
11
11
|
}
|
|
12
12
|
}
|
|
@@ -909,13 +909,13 @@ async function discoverClaimsFiles(cwd) {
|
|
|
909
909
|
} catch {
|
|
910
910
|
}
|
|
911
911
|
}
|
|
912
|
-
return
|
|
912
|
+
return Array.from(found).sort((a, b) => a.localeCompare(b));
|
|
913
913
|
}
|
|
914
914
|
function mergeAndNormalisePaths(discovered, extra) {
|
|
915
915
|
const out = /* @__PURE__ */ new Set();
|
|
916
916
|
for (const p of discovered) out.add(p);
|
|
917
917
|
for (const p of extra) out.add(toPosix(p));
|
|
918
|
-
return
|
|
918
|
+
return Array.from(out).sort((a, b) => a.localeCompare(b));
|
|
919
919
|
}
|
|
920
920
|
function toPosix(value) {
|
|
921
921
|
return value.split(sep).join("/");
|
|
@@ -1131,6 +1131,9 @@ function projectModelEntry(entry) {
|
|
|
1131
1131
|
fields: entry.fields.map(projectModelField),
|
|
1132
1132
|
...entry.modelGroup == null ? {} : { modelGroup: entry.modelGroup },
|
|
1133
1133
|
...entry.parentIdentityConst == null ? {} : { parentIdentityConst: entry.parentIdentityConst },
|
|
1134
|
+
...entry.singleton == null ? {} : { singleton: entry.singleton },
|
|
1135
|
+
...entry.singleItemIdentifier == null ? {} : { singleItemIdentifier: entry.singleItemIdentifier },
|
|
1136
|
+
...entry.exampleKey == null ? {} : { exampleKey: entry.exampleKey },
|
|
1134
1137
|
...entry.description == null ? {} : { description: entry.description },
|
|
1135
1138
|
...entry.mcpToolNameSegment == null ? {} : { mcpToolNameSegment: entry.mcpToolNameSegment },
|
|
1136
1139
|
...entry.read == null ? {} : { read: entry.read },
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli-generate-mcp-manifest",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.43.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/dbx-cli": "13.
|
|
8
|
-
"@dereekb/model": "13.
|
|
7
|
+
"@dereekb/dbx-cli": "13.43.0",
|
|
8
|
+
"@dereekb/model": "13.43.0",
|
|
9
9
|
"arktype": "^2.2.0",
|
|
10
10
|
"jiti": "2.6.1"
|
|
11
11
|
}
|
|
@@ -845,7 +845,7 @@ function warnDroppedFutureStates(tree, realNames, warnings) {
|
|
|
845
845
|
continue;
|
|
846
846
|
}
|
|
847
847
|
const prefix = node.data.name.slice(0, -3);
|
|
848
|
-
const hasRealSubtree = realNames.has(prefix) ||
|
|
848
|
+
const hasRealSubtree = realNames.has(prefix) || Array.from(realNames).some((name) => name.startsWith(`${prefix}.`));
|
|
849
849
|
if (!hasRealSubtree) {
|
|
850
850
|
warnings.push({ kind: "dropped-future-state", severity: "warning", message: `Future state \`${node.data.name}\` was dropped and has no real subtree under \`${prefix}\`; its page will not match any URL.`, stateName: node.data.name });
|
|
851
851
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli-generate-route-manifest",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.43.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/dbx-cli": "13.
|
|
7
|
+
"@dereekb/dbx-cli": "13.43.0",
|
|
8
8
|
"ts-morph": "^21.0.0"
|
|
9
9
|
}
|
|
10
10
|
}
|