@dereekb/dbx-components-mcp 13.11.15 → 13.11.16
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/dbx-components-mcp.js
CHANGED
|
@@ -5,7 +5,7 @@ const require = __createRequire(import.meta.url);
|
|
|
5
5
|
// packages/dbx-components-mcp/package.json
|
|
6
6
|
var package_default = {
|
|
7
7
|
name: "@dereekb/dbx-components-mcp",
|
|
8
|
-
version: "13.11.
|
|
8
|
+
version: "13.11.16",
|
|
9
9
|
type: "module",
|
|
10
10
|
bin: {
|
|
11
11
|
"dbx-components-mcp": "dbx-components-mcp.js"
|
|
@@ -20,20 +20,20 @@ var package_default = {
|
|
|
20
20
|
"@angular/core": "21.2.11",
|
|
21
21
|
"@angular/forms": "21.2.11",
|
|
22
22
|
"@angular/material": "^21.2.9",
|
|
23
|
-
"@dereekb/dbx-cli": "13.11.
|
|
24
|
-
"@dereekb/dbx-core": "13.11.
|
|
25
|
-
"@dereekb/dbx-firebase": "13.11.
|
|
26
|
-
"@dereekb/dbx-form": "13.11.
|
|
27
|
-
"@dereekb/dbx-web": "13.11.
|
|
28
|
-
"@dereekb/firebase": "13.11.
|
|
29
|
-
"@dereekb/firebase-server": "13.11.
|
|
30
|
-
"@dereekb/rxjs": "13.11.
|
|
31
|
-
"@dereekb/util": "13.11.
|
|
23
|
+
"@dereekb/dbx-cli": "13.11.16",
|
|
24
|
+
"@dereekb/dbx-core": "13.11.16",
|
|
25
|
+
"@dereekb/dbx-firebase": "13.11.16",
|
|
26
|
+
"@dereekb/dbx-form": "13.11.16",
|
|
27
|
+
"@dereekb/dbx-web": "13.11.16",
|
|
28
|
+
"@dereekb/firebase": "13.11.16",
|
|
29
|
+
"@dereekb/firebase-server": "13.11.16",
|
|
30
|
+
"@dereekb/rxjs": "13.11.16",
|
|
31
|
+
"@dereekb/util": "13.11.16",
|
|
32
32
|
"@uirouter/angular": "21.0.0",
|
|
33
33
|
rxjs: "^7.8.2"
|
|
34
34
|
},
|
|
35
35
|
devDependencies: {
|
|
36
|
-
"@dereekb/model": "13.11.
|
|
36
|
+
"@dereekb/model": "13.11.16"
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
39
|
|
|
@@ -89,7 +89,7 @@ var ForgeFieldManifest = type({
|
|
|
89
89
|
import { type as type2 } from "arktype";
|
|
90
90
|
import { Node as Node2 } from "ts-morph";
|
|
91
91
|
|
|
92
|
-
// packages/dbx-
|
|
92
|
+
// packages/dbx-cli/src/lib/scan-helpers/scan-extract-utils.ts
|
|
93
93
|
import { Node, SyntaxKind } from "ts-morph";
|
|
94
94
|
function unwrapFenced(text) {
|
|
95
95
|
const trimmed = text.trim();
|
|
@@ -833,7 +833,7 @@ var ForgeFieldsScanConfig = type3({
|
|
|
833
833
|
var DEFAULT_FORGE_FIELDS_SCAN_OUT_PATH = "forge-fields.mcp.generated.json";
|
|
834
834
|
var FORGE_FIELDS_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
835
835
|
|
|
836
|
-
// packages/dbx-
|
|
836
|
+
// packages/dbx-cli/src/lib/scan-helpers/scan-io.ts
|
|
837
837
|
import { glob as fsGlob, readFile as nodeReadFile } from "node:fs/promises";
|
|
838
838
|
import { resolve as resolvePath } from "node:path";
|
|
839
839
|
import { Project } from "ts-morph";
|
|
@@ -3291,11 +3291,11 @@ function formatExtractWarning3(warning) {
|
|
|
3291
3291
|
return result;
|
|
3292
3292
|
}
|
|
3293
3293
|
|
|
3294
|
-
// packages/dbx-
|
|
3294
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-build-manifest.ts
|
|
3295
3295
|
import { relative as relative2, resolve as resolve7 } from "node:path";
|
|
3296
3296
|
import { type as type18 } from "arktype";
|
|
3297
3297
|
|
|
3298
|
-
// packages/dbx-
|
|
3298
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-schema.ts
|
|
3299
3299
|
import { type as type16 } from "arktype";
|
|
3300
3300
|
var DEFAULT_FIRESTORE_INDEX_DENSITY = "SPARSE_ALL";
|
|
3301
3301
|
var FIRESTORE_WHERE_OPERATORS = ["==", "!=", "<", "<=", ">", ">=", "in", "not-in", "array-contains", "array-contains-any"];
|
|
@@ -3374,7 +3374,7 @@ var ModelFirebaseIndexManifest = type16({
|
|
|
3374
3374
|
entries: ModelFirebaseIndexEntry.array()
|
|
3375
3375
|
});
|
|
3376
3376
|
|
|
3377
|
-
// packages/dbx-
|
|
3377
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-analyze.ts
|
|
3378
3378
|
var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["==", "in"]);
|
|
3379
3379
|
var RANGE_OPERATORS = /* @__PURE__ */ new Set(["<", "<=", ">", ">=", "!=", "not-in"]);
|
|
3380
3380
|
var ARRAY_OPERATORS = /* @__PURE__ */ new Set(["array-contains", "array-contains-any"]);
|
|
@@ -3593,10 +3593,10 @@ function fieldOverrideVariantEquals(a, b) {
|
|
|
3593
3593
|
return a.queryScope === b.queryScope && a.order === b.order && a.arrayConfig === b.arrayConfig;
|
|
3594
3594
|
}
|
|
3595
3595
|
|
|
3596
|
-
// packages/dbx-
|
|
3596
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-extract.ts
|
|
3597
3597
|
import { Node as Node6, SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
3598
3598
|
|
|
3599
|
-
// packages/dbx-
|
|
3599
|
+
// packages/dbx-cli/firestore-indexes/src/firestore-query-helpers.ts
|
|
3600
3600
|
var FIRESTORE_QUERY_HELPERS = [
|
|
3601
3601
|
// Inequality helpers — single base where, no orderBy.
|
|
3602
3602
|
{ name: "whereDateIsBefore", fieldArgIndex: 0, parts: [{ kind: "where", operator: "<" }] },
|
|
@@ -3729,7 +3729,7 @@ function expandFirestoreQueryHelper(input) {
|
|
|
3729
3729
|
return out;
|
|
3730
3730
|
}
|
|
3731
3731
|
|
|
3732
|
-
// packages/dbx-
|
|
3732
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-extract.ts
|
|
3733
3733
|
var INDEX_MARKER = "dbxModelFirebaseIndex";
|
|
3734
3734
|
var INDEX_DISPATCHER_TAG = "dbxModelFirebaseIndexDispatcher";
|
|
3735
3735
|
var INDEX_MODEL_TAG = "dbxModelFirebaseIndexModel";
|
|
@@ -4009,7 +4009,7 @@ function composeEntry(input) {
|
|
|
4009
4009
|
const example = tags.examples.length > 0 ? tags.examples[0] : "";
|
|
4010
4010
|
const category = tags.category && tags.category.length > 0 ? tags.category : "misc";
|
|
4011
4011
|
const tagSet = buildTagSet({ name, slug, summary: tags.summary, explicit: tags.explicitTags, category, model: modelTag });
|
|
4012
|
-
const constraintSequences = resolveConstraintSequences({ candidate, tags, name, line, filePath, warnings });
|
|
4012
|
+
const { constraintSequences, dispatcherDelegates } = resolveConstraintSequences({ candidate, tags, name, line, filePath, warnings });
|
|
4013
4013
|
if (tags.excluded) {
|
|
4014
4014
|
warnings.push({ kind: "excluded-factory", severity: "warning", name, filePath, line });
|
|
4015
4015
|
}
|
|
@@ -4024,6 +4024,8 @@ function composeEntry(input) {
|
|
|
4024
4024
|
skip: tags.skip,
|
|
4025
4025
|
specOnly: tags.specOnly,
|
|
4026
4026
|
excluded: tags.excluded,
|
|
4027
|
+
dispatcher: tags.dispatcher,
|
|
4028
|
+
dispatcherDelegates,
|
|
4027
4029
|
allowArrayContainsAny: tags.allowArrayContainsAny,
|
|
4028
4030
|
category,
|
|
4029
4031
|
signature,
|
|
@@ -4048,9 +4050,9 @@ function resolveConstraintSequences(input) {
|
|
|
4048
4050
|
warnings.push(warning);
|
|
4049
4051
|
}
|
|
4050
4052
|
if (tags.skip || tags.specOnly || tags.dispatcher || bodyResult.skipped) {
|
|
4051
|
-
return [];
|
|
4053
|
+
return { constraintSequences: [], dispatcherDelegates: bodyResult.dispatcherDelegates };
|
|
4052
4054
|
}
|
|
4053
|
-
|
|
4055
|
+
const constraintSequences = buildConstraintSequences({
|
|
4054
4056
|
bodyEntries: bodyResult.entries,
|
|
4055
4057
|
conditionalFields: bodyResult.conditionalFields,
|
|
4056
4058
|
paths: tags.paths,
|
|
@@ -4059,6 +4061,7 @@ function resolveConstraintSequences(input) {
|
|
|
4059
4061
|
line,
|
|
4060
4062
|
warnings
|
|
4061
4063
|
});
|
|
4064
|
+
return { constraintSequences, dispatcherDelegates: [] };
|
|
4062
4065
|
}
|
|
4063
4066
|
function resolveScope2(input) {
|
|
4064
4067
|
const { tags, resolved, name, filePath, line, warnings } = input;
|
|
@@ -4133,13 +4136,14 @@ function extractConstraintsFromBody(input) {
|
|
|
4133
4136
|
if (violation !== void 0) {
|
|
4134
4137
|
warnings.push({ kind: "non-delegating-dispatcher", severity: "error", name: factoryName, callee: violation.callee, filePath, line: violation.line });
|
|
4135
4138
|
}
|
|
4136
|
-
|
|
4139
|
+
const dispatcherDelegates = body === void 0 ? [] : collectDispatcherDelegates(body);
|
|
4140
|
+
return { entries, conditionalFields: [], warnings, skipped: true, dispatcherDelegates };
|
|
4137
4141
|
}
|
|
4138
4142
|
if (body !== void 0) {
|
|
4139
4143
|
const branch = findFirstBranchNode(body);
|
|
4140
4144
|
if (branch !== void 0) {
|
|
4141
4145
|
warnings.push({ kind: "complex-query-body", severity: "error", name: factoryName, branchKind: branch.branchKind, filePath, line: branch.line });
|
|
4142
|
-
return { entries, conditionalFields: [], warnings, skipped: true };
|
|
4146
|
+
return { entries, conditionalFields: [], warnings, skipped: true, dispatcherDelegates: [] };
|
|
4143
4147
|
}
|
|
4144
4148
|
}
|
|
4145
4149
|
const initialVisited = /* @__PURE__ */ new Set([buildDeclKey(decl)]);
|
|
@@ -4161,7 +4165,29 @@ function extractConstraintsFromBody(input) {
|
|
|
4161
4165
|
conditionalFields.push(entry.fieldPath);
|
|
4162
4166
|
}
|
|
4163
4167
|
}
|
|
4164
|
-
return { entries, conditionalFields, warnings, skipped: false };
|
|
4168
|
+
return { entries, conditionalFields, warnings, skipped: false, dispatcherDelegates: [] };
|
|
4169
|
+
}
|
|
4170
|
+
function collectDispatcherDelegates(bodyNode) {
|
|
4171
|
+
const calls = bodyNode.getDescendantsOfKind(SyntaxKind3.CallExpression);
|
|
4172
|
+
calls.sort((a, b) => a.getStart() - b.getStart());
|
|
4173
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4174
|
+
const out = [];
|
|
4175
|
+
for (const call of calls) {
|
|
4176
|
+
const expression = call.getExpression();
|
|
4177
|
+
if (!Node6.isIdentifier(expression)) {
|
|
4178
|
+
continue;
|
|
4179
|
+
}
|
|
4180
|
+
const name = expression.getText();
|
|
4181
|
+
if (name.length === 0 || seen.has(name)) {
|
|
4182
|
+
continue;
|
|
4183
|
+
}
|
|
4184
|
+
if (name === "where" || name === "orderBy" || getFirestoreQueryHelperDescriptor(name) !== void 0) {
|
|
4185
|
+
continue;
|
|
4186
|
+
}
|
|
4187
|
+
seen.add(name);
|
|
4188
|
+
out.push(name);
|
|
4189
|
+
}
|
|
4190
|
+
return out;
|
|
4165
4191
|
}
|
|
4166
4192
|
function walkBodyInto(input) {
|
|
4167
4193
|
const { decl, forcedConditional } = input;
|
|
@@ -4491,7 +4517,7 @@ function buildTagSet(input) {
|
|
|
4491
4517
|
return out;
|
|
4492
4518
|
}
|
|
4493
4519
|
|
|
4494
|
-
// packages/dbx-
|
|
4520
|
+
// packages/dbx-cli/firestore-indexes/src/firestore-model-identity-resolver.ts
|
|
4495
4521
|
import { Node as Node7, SyntaxKind as SyntaxKind4 } from "ts-morph";
|
|
4496
4522
|
function buildIdentityResolverFromProject(project) {
|
|
4497
4523
|
const records = [];
|
|
@@ -4602,7 +4628,7 @@ function toCamelCase(typeName) {
|
|
|
4602
4628
|
return result;
|
|
4603
4629
|
}
|
|
4604
4630
|
|
|
4605
|
-
// packages/dbx-
|
|
4631
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-scan-config-schema.ts
|
|
4606
4632
|
import { type as type17 } from "arktype";
|
|
4607
4633
|
var ModelFirebaseIndexScanSection = type17({
|
|
4608
4634
|
"source?": "string",
|
|
@@ -4618,7 +4644,7 @@ var ModelFirebaseIndexScanConfig = type17({
|
|
|
4618
4644
|
var DEFAULT_MODEL_FIREBASE_INDEX_SCAN_OUT_PATH = "model-firebase-index.mcp.generated.json";
|
|
4619
4645
|
var MODEL_FIREBASE_INDEX_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
4620
4646
|
|
|
4621
|
-
// packages/dbx-
|
|
4647
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-build-manifest.ts
|
|
4622
4648
|
var DEFAULT_READ_FILE7 = defaultReadFile;
|
|
4623
4649
|
var DEFAULT_GLOBBER5 = defaultGlobber;
|
|
4624
4650
|
async function buildModelFirebaseIndexManifest(input) {
|
|
@@ -4681,8 +4707,13 @@ async function buildModelFirebaseIndexManifest(input) {
|
|
|
4681
4707
|
} else {
|
|
4682
4708
|
const outPath = resolve7(projectRoot, scanSection.out ?? DEFAULT_MODEL_FIREBASE_INDEX_SCAN_OUT_PATH);
|
|
4683
4709
|
const entryFilePathsBySlug = /* @__PURE__ */ new Map();
|
|
4710
|
+
const dispatcherSummaries = [];
|
|
4684
4711
|
for (const analyzedEntry of analyzed) {
|
|
4685
|
-
|
|
4712
|
+
const extracted = analyzedEntry.extractedEntry;
|
|
4713
|
+
entryFilePathsBySlug.set(extracted.slug, extracted.filePath);
|
|
4714
|
+
if (extracted.dispatcher) {
|
|
4715
|
+
dispatcherSummaries.push({ slug: extracted.slug, name: extracted.name, delegates: [...extracted.dispatcherDelegates] });
|
|
4716
|
+
}
|
|
4686
4717
|
}
|
|
4687
4718
|
outcome = {
|
|
4688
4719
|
kind: "success",
|
|
@@ -4690,7 +4721,8 @@ async function buildModelFirebaseIndexManifest(input) {
|
|
|
4690
4721
|
outPath,
|
|
4691
4722
|
scannedFileCount: filePaths.length,
|
|
4692
4723
|
extractWarnings: buildWarnings,
|
|
4693
|
-
entryFilePathsBySlug
|
|
4724
|
+
entryFilePathsBySlug,
|
|
4725
|
+
dispatcherSummaries
|
|
4694
4726
|
};
|
|
4695
4727
|
}
|
|
4696
4728
|
return outcome;
|
|
@@ -8193,111 +8225,7 @@ function formatExtractWarning9(warning) {
|
|
|
8193
8225
|
return result;
|
|
8194
8226
|
}
|
|
8195
8227
|
|
|
8196
|
-
// packages/dbx-
|
|
8197
|
-
import { readFile as nodeReadFile4, writeFile as nodeWriteFile3 } from "node:fs/promises";
|
|
8198
|
-
import { resolve as resolve15 } from "node:path";
|
|
8199
|
-
|
|
8200
|
-
// packages/dbx-components-mcp/src/registry/model-firebase-index-runtime.ts
|
|
8201
|
-
// @__NO_SIDE_EFFECTS__
|
|
8202
|
-
function createModelFirebaseIndexRegistry(loaded) {
|
|
8203
|
-
const entries = Array.from(loaded.entries.values()).map(toModelFirebaseIndexEntryInfo);
|
|
8204
|
-
return /* @__PURE__ */ createModelFirebaseIndexRegistryFromEntries({ entries, loadedSources: loaded.loadedSources });
|
|
8205
|
-
}
|
|
8206
|
-
// @__NO_SIDE_EFFECTS__
|
|
8207
|
-
function createModelFirebaseIndexRegistryFromEntries(input) {
|
|
8208
|
-
const all = [...input.entries];
|
|
8209
|
-
const bySlug = /* @__PURE__ */ new Map();
|
|
8210
|
-
const byName = /* @__PURE__ */ new Map();
|
|
8211
|
-
const byCollection = /* @__PURE__ */ new Map();
|
|
8212
|
-
const byModel = /* @__PURE__ */ new Map();
|
|
8213
|
-
const byModule = /* @__PURE__ */ new Map();
|
|
8214
|
-
const byCategory = /* @__PURE__ */ new Map();
|
|
8215
|
-
const byTag = /* @__PURE__ */ new Map();
|
|
8216
|
-
const collectionSet = /* @__PURE__ */ new Set();
|
|
8217
|
-
const modelSet = /* @__PURE__ */ new Set();
|
|
8218
|
-
const moduleSet = /* @__PURE__ */ new Set();
|
|
8219
|
-
const categorySet = /* @__PURE__ */ new Set();
|
|
8220
|
-
for (const entry of all) {
|
|
8221
|
-
if (!bySlug.has(entry.slug)) {
|
|
8222
|
-
bySlug.set(entry.slug, entry);
|
|
8223
|
-
}
|
|
8224
|
-
if (!byName.has(entry.name)) {
|
|
8225
|
-
byName.set(entry.name, entry);
|
|
8226
|
-
}
|
|
8227
|
-
pushInto(byCollection, entry.collection, entry);
|
|
8228
|
-
pushInto(byModel, entry.model, entry);
|
|
8229
|
-
pushInto(byModule, entry.module, entry);
|
|
8230
|
-
pushInto(byCategory, entry.category, entry);
|
|
8231
|
-
for (const tag of entry.tags) {
|
|
8232
|
-
pushInto(byTag, tag.toLowerCase(), entry);
|
|
8233
|
-
}
|
|
8234
|
-
collectionSet.add(entry.collection);
|
|
8235
|
-
modelSet.add(entry.model);
|
|
8236
|
-
moduleSet.add(entry.module);
|
|
8237
|
-
categorySet.add(entry.category);
|
|
8238
|
-
}
|
|
8239
|
-
const collections = Array.from(collectionSet).sort((a, b) => a.localeCompare(b));
|
|
8240
|
-
const models = Array.from(modelSet).sort((a, b) => a.localeCompare(b));
|
|
8241
|
-
const modules = Array.from(moduleSet).sort((a, b) => a.localeCompare(b));
|
|
8242
|
-
const categories = Array.from(categorySet).sort((a, b) => a.localeCompare(b));
|
|
8243
|
-
return {
|
|
8244
|
-
all,
|
|
8245
|
-
loadedSources: [...input.loadedSources],
|
|
8246
|
-
collections,
|
|
8247
|
-
models,
|
|
8248
|
-
modules,
|
|
8249
|
-
categories,
|
|
8250
|
-
findBySlug: (slug) => bySlug.get(slug),
|
|
8251
|
-
findByName: (name) => byName.get(name),
|
|
8252
|
-
findByCollection: (collection) => byCollection.get(collection) ?? [],
|
|
8253
|
-
findByModel: (model) => byModel.get(model) ?? [],
|
|
8254
|
-
findByModule: (module) => byModule.get(module) ?? [],
|
|
8255
|
-
findByCategory: (category) => byCategory.get(category) ?? [],
|
|
8256
|
-
findByTag: (tag) => byTag.get(tag.toLowerCase()) ?? []
|
|
8257
|
-
};
|
|
8258
|
-
}
|
|
8259
|
-
var EMPTY_MODEL_FIREBASE_INDEX_REGISTRY = /* @__PURE__ */ createModelFirebaseIndexRegistryFromEntries({ entries: [], loadedSources: [] });
|
|
8260
|
-
function toModelFirebaseIndexEntryInfo(entry) {
|
|
8261
|
-
return {
|
|
8262
|
-
slug: entry.slug,
|
|
8263
|
-
name: entry.name,
|
|
8264
|
-
module: entry.module,
|
|
8265
|
-
subpath: entry.subpath,
|
|
8266
|
-
signature: entry.signature,
|
|
8267
|
-
description: entry.description,
|
|
8268
|
-
model: entry.model,
|
|
8269
|
-
collection: entry.collection,
|
|
8270
|
-
isNested: entry.isNested,
|
|
8271
|
-
scope: entry.scope,
|
|
8272
|
-
manual: entry.manual,
|
|
8273
|
-
skip: entry.skip,
|
|
8274
|
-
category: entry.category,
|
|
8275
|
-
params: entry.params.map((p) => ({ ...p })),
|
|
8276
|
-
returns: entry.returns,
|
|
8277
|
-
tags: [...entry.tags],
|
|
8278
|
-
constraintSequences: entry.constraintSequences.map((s) => ({
|
|
8279
|
-
...s.pathLabel === void 0 ? {} : { pathLabel: s.pathLabel },
|
|
8280
|
-
entries: s.entries.map((e) => ({ ...e }))
|
|
8281
|
-
})),
|
|
8282
|
-
derivedComposites: entry.derivedComposites.map((c) => ({ ...c, fields: c.fields.map((f) => ({ ...f })) })),
|
|
8283
|
-
derivedFieldOverrides: entry.derivedFieldOverrides.map((f) => ({ ...f, variants: f.variants.map((v) => ({ ...v })) })),
|
|
8284
|
-
example: entry.example ?? "",
|
|
8285
|
-
relatedSlugs: entry.relatedSlugs ?? [],
|
|
8286
|
-
skillRefs: entry.skillRefs ?? [],
|
|
8287
|
-
deprecated: entry.deprecated ?? false,
|
|
8288
|
-
since: entry.since ?? ""
|
|
8289
|
-
};
|
|
8290
|
-
}
|
|
8291
|
-
function pushInto(map, key, entry) {
|
|
8292
|
-
const existing = map.get(key);
|
|
8293
|
-
if (existing === void 0) {
|
|
8294
|
-
map.set(key, [entry]);
|
|
8295
|
-
} else {
|
|
8296
|
-
existing.push(entry);
|
|
8297
|
-
}
|
|
8298
|
-
}
|
|
8299
|
-
|
|
8300
|
-
// packages/dbx-components-mcp/src/scan/firestore-indexes-generate.ts
|
|
8228
|
+
// packages/dbx-cli/firestore-indexes/src/firestore-indexes-generate.ts
|
|
8301
8229
|
function generateFirestoreIndexesJson(input) {
|
|
8302
8230
|
const { entries, existingJson } = input;
|
|
8303
8231
|
const { generatedComposites, overrideVariants } = collectDerivedEntries(entries);
|
|
@@ -8523,34 +8451,142 @@ function computeDiff(input) {
|
|
|
8523
8451
|
};
|
|
8524
8452
|
}
|
|
8525
8453
|
|
|
8526
|
-
// packages/dbx-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
]
|
|
8454
|
+
// packages/dbx-cli/firestore-indexes/src/generate-firestore-indexes-cli.ts
|
|
8455
|
+
import { readFile as nodeReadFile4, writeFile as nodeWriteFile3 } from "node:fs/promises";
|
|
8456
|
+
import { resolve as resolve15 } from "node:path";
|
|
8457
|
+
|
|
8458
|
+
// packages/dbx-cli/firestore-indexes/src/model-firebase-index-runtime.ts
|
|
8459
|
+
// @__NO_SIDE_EFFECTS__
|
|
8460
|
+
function createModelFirebaseIndexRegistry(loaded) {
|
|
8461
|
+
const entries = Array.from(loaded.entries.values()).map(toModelFirebaseIndexEntryInfo);
|
|
8462
|
+
return /* @__PURE__ */ createModelFirebaseIndexRegistryFromEntries({ entries, loadedSources: loaded.loadedSources });
|
|
8463
|
+
}
|
|
8464
|
+
// @__NO_SIDE_EFFECTS__
|
|
8465
|
+
function createModelFirebaseIndexRegistryFromEntries(input) {
|
|
8466
|
+
const all = [...input.entries];
|
|
8467
|
+
const bySlug = /* @__PURE__ */ new Map();
|
|
8468
|
+
const byName = /* @__PURE__ */ new Map();
|
|
8469
|
+
const byCollection = /* @__PURE__ */ new Map();
|
|
8470
|
+
const byModel = /* @__PURE__ */ new Map();
|
|
8471
|
+
const byModule = /* @__PURE__ */ new Map();
|
|
8472
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
8473
|
+
const byTag = /* @__PURE__ */ new Map();
|
|
8474
|
+
const collectionSet = /* @__PURE__ */ new Set();
|
|
8475
|
+
const modelSet = /* @__PURE__ */ new Set();
|
|
8476
|
+
const moduleSet = /* @__PURE__ */ new Set();
|
|
8477
|
+
const categorySet = /* @__PURE__ */ new Set();
|
|
8478
|
+
for (const entry of all) {
|
|
8479
|
+
if (!bySlug.has(entry.slug)) {
|
|
8480
|
+
bySlug.set(entry.slug, entry);
|
|
8481
|
+
}
|
|
8482
|
+
if (!byName.has(entry.name)) {
|
|
8483
|
+
byName.set(entry.name, entry);
|
|
8484
|
+
}
|
|
8485
|
+
pushInto(byCollection, entry.collection, entry);
|
|
8486
|
+
pushInto(byModel, entry.model, entry);
|
|
8487
|
+
pushInto(byModule, entry.module, entry);
|
|
8488
|
+
pushInto(byCategory, entry.category, entry);
|
|
8489
|
+
for (const tag of entry.tags) {
|
|
8490
|
+
pushInto(byTag, tag.toLowerCase(), entry);
|
|
8491
|
+
}
|
|
8492
|
+
collectionSet.add(entry.collection);
|
|
8493
|
+
modelSet.add(entry.model);
|
|
8494
|
+
moduleSet.add(entry.module);
|
|
8495
|
+
categorySet.add(entry.category);
|
|
8496
|
+
}
|
|
8497
|
+
const collections = Array.from(collectionSet).sort((a, b) => a.localeCompare(b));
|
|
8498
|
+
const models = Array.from(modelSet).sort((a, b) => a.localeCompare(b));
|
|
8499
|
+
const modules = Array.from(moduleSet).sort((a, b) => a.localeCompare(b));
|
|
8500
|
+
const categories = Array.from(categorySet).sort((a, b) => a.localeCompare(b));
|
|
8501
|
+
return {
|
|
8502
|
+
all,
|
|
8503
|
+
loadedSources: [...input.loadedSources],
|
|
8504
|
+
collections,
|
|
8505
|
+
models,
|
|
8506
|
+
modules,
|
|
8507
|
+
categories,
|
|
8508
|
+
findBySlug: (slug) => bySlug.get(slug),
|
|
8509
|
+
findByName: (name) => byName.get(name),
|
|
8510
|
+
findByCollection: (collection) => byCollection.get(collection) ?? [],
|
|
8511
|
+
findByModel: (model) => byModel.get(model) ?? [],
|
|
8512
|
+
findByModule: (module) => byModule.get(module) ?? [],
|
|
8513
|
+
findByCategory: (category) => byCategory.get(category) ?? [],
|
|
8514
|
+
findByTag: (tag) => byTag.get(tag.toLowerCase()) ?? []
|
|
8515
|
+
};
|
|
8516
|
+
}
|
|
8517
|
+
var EMPTY_MODEL_FIREBASE_INDEX_REGISTRY = /* @__PURE__ */ createModelFirebaseIndexRegistryFromEntries({ entries: [], loadedSources: [] });
|
|
8518
|
+
function toModelFirebaseIndexEntryInfo(entry) {
|
|
8519
|
+
return {
|
|
8520
|
+
slug: entry.slug,
|
|
8521
|
+
name: entry.name,
|
|
8522
|
+
module: entry.module,
|
|
8523
|
+
subpath: entry.subpath,
|
|
8524
|
+
signature: entry.signature,
|
|
8525
|
+
description: entry.description,
|
|
8526
|
+
model: entry.model,
|
|
8527
|
+
collection: entry.collection,
|
|
8528
|
+
isNested: entry.isNested,
|
|
8529
|
+
scope: entry.scope,
|
|
8530
|
+
manual: entry.manual,
|
|
8531
|
+
skip: entry.skip,
|
|
8532
|
+
category: entry.category,
|
|
8533
|
+
params: entry.params.map((p) => ({ ...p })),
|
|
8534
|
+
returns: entry.returns,
|
|
8535
|
+
tags: [...entry.tags],
|
|
8536
|
+
constraintSequences: entry.constraintSequences.map((s) => ({
|
|
8537
|
+
...s.pathLabel === void 0 ? {} : { pathLabel: s.pathLabel },
|
|
8538
|
+
entries: s.entries.map((e) => ({ ...e }))
|
|
8539
|
+
})),
|
|
8540
|
+
derivedComposites: entry.derivedComposites.map((c) => ({ ...c, fields: c.fields.map((f) => ({ ...f })) })),
|
|
8541
|
+
derivedFieldOverrides: entry.derivedFieldOverrides.map((f) => ({ ...f, variants: f.variants.map((v) => ({ ...v })) })),
|
|
8542
|
+
example: entry.example ?? "",
|
|
8543
|
+
relatedSlugs: entry.relatedSlugs ?? [],
|
|
8544
|
+
skillRefs: entry.skillRefs ?? [],
|
|
8545
|
+
deprecated: entry.deprecated ?? false,
|
|
8546
|
+
since: entry.since ?? ""
|
|
8547
|
+
};
|
|
8548
|
+
}
|
|
8549
|
+
function pushInto(map, key, entry) {
|
|
8550
|
+
const existing = map.get(key);
|
|
8551
|
+
if (existing === void 0) {
|
|
8552
|
+
map.set(key, [entry]);
|
|
8553
|
+
} else {
|
|
8554
|
+
existing.push(entry);
|
|
8555
|
+
}
|
|
8556
|
+
}
|
|
8557
|
+
|
|
8558
|
+
// packages/dbx-cli/firestore-indexes/src/generate-firestore-indexes-cli.ts
|
|
8559
|
+
var DEFAULT_BIN_NAME = "dbx-cli-generate-firestore-indexes";
|
|
8560
|
+
function buildUsage(binName) {
|
|
8561
|
+
return [
|
|
8562
|
+
`Usage: ${binName} --component <dir> [--output <path>] [--check] [--json] [--help]`,
|
|
8563
|
+
"",
|
|
8564
|
+
"Generates `firestore.indexes.json` from `@dbxModelFirebaseIndex`-tagged factories.",
|
|
8565
|
+
"",
|
|
8566
|
+
"Options:",
|
|
8567
|
+
" --component <dir> Required. Relative path to the `-firebase` component package.",
|
|
8568
|
+
" --output <path> Output path. Defaults to `firestore.indexes.json` at the cwd.",
|
|
8569
|
+
" --check Compare against the on-disk file; exit 1 on drift, do not write.",
|
|
8570
|
+
" --json Print the diff summary as JSON instead of human-readable text.",
|
|
8571
|
+
" --help Show this message."
|
|
8572
|
+
].join("\n");
|
|
8573
|
+
}
|
|
8539
8574
|
async function runGenerateFirestoreIndexesCli(input) {
|
|
8540
|
-
const { argv, cwd, generator, readFile: readFile26 = (path) => nodeReadFile4(path, "utf-8"), writeFile: writeFile2 = nodeWriteFile3, stdout = (m) => console.log(m), stderr = (m) => console.error(m) } = input;
|
|
8575
|
+
const { argv, cwd, generator, binName = DEFAULT_BIN_NAME, readFile: readFile26 = (path) => nodeReadFile4(path, "utf-8"), writeFile: writeFile2 = nodeWriteFile3, stdout = (m) => console.log(m), stderr = (m) => console.error(m) } = input;
|
|
8576
|
+
const usage = buildUsage(binName);
|
|
8541
8577
|
const parsed = parseArgv(argv);
|
|
8542
8578
|
if (parsed.help) {
|
|
8543
|
-
stdout(
|
|
8579
|
+
stdout(usage);
|
|
8544
8580
|
return { exitCode: 0 };
|
|
8545
8581
|
}
|
|
8546
8582
|
if (parsed.error !== void 0) {
|
|
8547
8583
|
stderr(parsed.error);
|
|
8548
|
-
stderr(
|
|
8584
|
+
stderr(usage);
|
|
8549
8585
|
return { exitCode: 2 };
|
|
8550
8586
|
}
|
|
8551
8587
|
if (parsed.component === void 0) {
|
|
8552
8588
|
stderr("generate-firestore-indexes: --component is required");
|
|
8553
|
-
stderr(
|
|
8589
|
+
stderr(usage);
|
|
8554
8590
|
return { exitCode: 2 };
|
|
8555
8591
|
}
|
|
8556
8592
|
const componentAbs = resolve15(cwd, parsed.component);
|
|
@@ -22229,7 +22265,7 @@ var RULE_CATALOG = [
|
|
|
22229
22265
|
whatItFlags: "A composite index required by tagged factories is missing from the committed `firestore.indexes.json`.",
|
|
22230
22266
|
whenItApplies: "Every entry in the generated composite set that has no equal entry in the committed JSON.",
|
|
22231
22267
|
whenItDoesNotApply: "Factories tagged `@dbxModelFirebaseIndexManual` \u2014 their shapes are author-managed and excluded from drift.",
|
|
22232
|
-
canonicalFix: "Run the `scan-model-firebase-indexes`
|
|
22268
|
+
canonicalFix: "Run `dbx-cli-generate-firestore-indexes --component <dir>` (and the `scan-model-firebase-indexes` CLI if the manifest is also stale) and commit the regenerated `firestore.indexes.json`."
|
|
22233
22269
|
},
|
|
22234
22270
|
{
|
|
22235
22271
|
code: "MODEL_FIREBASE_INDEX_COMPOSITE_REMOVED",
|
|
@@ -43964,6 +44000,24 @@ function toSubpath(absolutePath, projectRoot) {
|
|
|
43964
44000
|
return result;
|
|
43965
44001
|
}
|
|
43966
44002
|
|
|
44003
|
+
// packages/dbx-components-mcp/src/scan/model-firebase-index-dispatcher-credit.ts
|
|
44004
|
+
function buildDispatcherCreditByName(dispatcherSummaries, references) {
|
|
44005
|
+
const out = /* @__PURE__ */ new Map();
|
|
44006
|
+
for (const dispatcher of dispatcherSummaries) {
|
|
44007
|
+
const refs = references.get(dispatcher.slug);
|
|
44008
|
+
const productionCount = refs?.productionCount ?? 0;
|
|
44009
|
+
const specCount = refs?.specCount ?? 0;
|
|
44010
|
+
if (productionCount === 0 && specCount === 0) continue;
|
|
44011
|
+
for (const delegate of dispatcher.delegates) {
|
|
44012
|
+
const existing = out.get(delegate) ?? { productionCount: 0, specCount: 0 };
|
|
44013
|
+
existing.productionCount += productionCount;
|
|
44014
|
+
existing.specCount += specCount;
|
|
44015
|
+
out.set(delegate, existing);
|
|
44016
|
+
}
|
|
44017
|
+
}
|
|
44018
|
+
return out;
|
|
44019
|
+
}
|
|
44020
|
+
|
|
43967
44021
|
// packages/dbx-components-mcp/src/tools/list-app-model-firebase-index.tool.ts
|
|
43968
44022
|
var ListAppArgsType4 = type82({
|
|
43969
44023
|
componentDir: "string",
|
|
@@ -44076,7 +44130,8 @@ async function resolveBuildOutcome(input) {
|
|
|
44076
44130
|
include: WORKSPACE_FACTORY_SCAN_INCLUDE,
|
|
44077
44131
|
exclude: WORKSPACE_FACTORY_SCAN_EXCLUDE
|
|
44078
44132
|
});
|
|
44079
|
-
const
|
|
44133
|
+
const dispatcherCreditByName = buildDispatcherCreditByName(buildOutcome.dispatcherSummaries, references);
|
|
44134
|
+
const taggedAll = buildOutcome.manifest.entries.map((entry) => toTaggedFactoryUsage(entry, references.get(entry.slug), dispatcherCreditByName.get(entry.name)));
|
|
44080
44135
|
const tagged = applyTaggedFilters(taggedAll, filters);
|
|
44081
44136
|
const untagged = filters.includeUntagged ? await collectUntaggedCandidates({ componentAbs, tagged: buildOutcome.manifest.entries }) : [];
|
|
44082
44137
|
const compositeCount = tagged.reduce((acc, t) => acc + t.composites.length, 0);
|
|
@@ -44142,10 +44197,12 @@ function isUnused(t) {
|
|
|
44142
44197
|
if (t.skip || t.manual) {
|
|
44143
44198
|
return false;
|
|
44144
44199
|
}
|
|
44200
|
+
const totalProduction = t.productionReferenceCount + t.dispatcherCreditedProductionCount;
|
|
44201
|
+
const totalSpec = t.specReferenceCount + t.dispatcherCreditedSpecCount;
|
|
44145
44202
|
if (t.specOnly) {
|
|
44146
|
-
return
|
|
44203
|
+
return totalProduction === 0 && totalSpec === 0;
|
|
44147
44204
|
}
|
|
44148
|
-
return
|
|
44205
|
+
return totalProduction === 0;
|
|
44149
44206
|
}
|
|
44150
44207
|
function isSpecOnlyViolation(t) {
|
|
44151
44208
|
return t.specOnly && t.productionReferenceCount > 0;
|
|
@@ -44162,7 +44219,7 @@ function applyTaggedFilters(tagged, filters) {
|
|
|
44162
44219
|
});
|
|
44163
44220
|
}
|
|
44164
44221
|
var MAX_REFERENCE_SAMPLES = 10;
|
|
44165
|
-
function toTaggedFactoryUsage(entry, references) {
|
|
44222
|
+
function toTaggedFactoryUsage(entry, references, dispatcherCredit) {
|
|
44166
44223
|
const referenceCount = references?.count ?? 0;
|
|
44167
44224
|
const productionReferenceCount = references?.productionCount ?? 0;
|
|
44168
44225
|
const specReferenceCount = references?.specCount ?? 0;
|
|
@@ -44185,6 +44242,8 @@ function toTaggedFactoryUsage(entry, references) {
|
|
|
44185
44242
|
productionReferenceCount,
|
|
44186
44243
|
specReferenceCount,
|
|
44187
44244
|
referencedBy,
|
|
44245
|
+
dispatcherCreditedProductionCount: dispatcherCredit?.productionCount ?? 0,
|
|
44246
|
+
dispatcherCreditedSpecCount: dispatcherCredit?.specCount ?? 0,
|
|
44188
44247
|
composites: entry.derivedComposites.map((c) => ({ ...c, fields: c.fields.map((f) => ({ ...f })) })),
|
|
44189
44248
|
fieldOverrides: entry.derivedFieldOverrides.map((f) => ({ ...f, variants: f.variants.map((v) => ({ ...v })) }))
|
|
44190
44249
|
};
|
|
@@ -44813,11 +44872,14 @@ function pushDiffViolation(input) {
|
|
|
44813
44872
|
}
|
|
44814
44873
|
var MAX_PRODUCTION_SAMPLES = 5;
|
|
44815
44874
|
function pushFactoryCallerViolations(input) {
|
|
44816
|
-
const { buffer, entry, references, filePath } = input;
|
|
44875
|
+
const { buffer, entry, references, dispatcherCreditByName, filePath } = input;
|
|
44817
44876
|
if (entry.skip || entry.manual) return;
|
|
44818
44877
|
const refs = references.get(entry.slug);
|
|
44819
|
-
const
|
|
44820
|
-
const
|
|
44878
|
+
const directProduction = refs?.productionCount ?? 0;
|
|
44879
|
+
const directSpec = refs?.specCount ?? 0;
|
|
44880
|
+
const credit = dispatcherCreditByName.get(entry.name);
|
|
44881
|
+
const productionCount = directProduction + (credit?.productionCount ?? 0);
|
|
44882
|
+
const specCount = directSpec + (credit?.specCount ?? 0);
|
|
44821
44883
|
if (entry.specOnly === true) {
|
|
44822
44884
|
pushSpecOnlyCallerViolations({ buffer, entry, refs, productionCount, specCount, filePath });
|
|
44823
44885
|
return;
|
|
@@ -44899,8 +44961,9 @@ async function buildValidateAppReport(input) {
|
|
|
44899
44961
|
include: WORKSPACE_FACTORY_SCAN_INCLUDE,
|
|
44900
44962
|
exclude: WORKSPACE_FACTORY_SCAN_EXCLUDE
|
|
44901
44963
|
});
|
|
44964
|
+
const dispatcherCreditByName = buildDispatcherCreditByName(buildOutcome.dispatcherSummaries, references);
|
|
44902
44965
|
for (const entry of buildOutcome.manifest.entries) {
|
|
44903
|
-
pushFactoryCallerViolations({ buffer, entry, references, filePath: buildOutcome.entryFilePathsBySlug.get(entry.slug) });
|
|
44966
|
+
pushFactoryCallerViolations({ buffer, entry, references, dispatcherCreditByName, filePath: buildOutcome.entryFilePathsBySlug.get(entry.slug) });
|
|
44904
44967
|
}
|
|
44905
44968
|
if (readError !== void 0) {
|
|
44906
44969
|
pushViolation10(buffer, {
|
|
@@ -45060,7 +45123,7 @@ function formatReportAsMarkdown9(report) {
|
|
|
45060
45123
|
if (report.indexesFileExists) {
|
|
45061
45124
|
lines.push(`Indexes file: \`${report.indexesFile}\``, "");
|
|
45062
45125
|
} else {
|
|
45063
|
-
lines.push(`> \`${report.indexesFile}\` does not exist. Run \`dbx-
|
|
45126
|
+
lines.push(`> \`${report.indexesFile}\` does not exist. Run \`dbx-cli-generate-firestore-indexes --component ${report.componentDir}\` to create it.`, "");
|
|
45064
45127
|
}
|
|
45065
45128
|
if (report.drift) {
|
|
45066
45129
|
lines.push("## \u274C Drift detected", "");
|
|
@@ -52205,7 +52268,8 @@ async function main() {
|
|
|
52205
52268
|
const result = await runGenerateFirestoreIndexesCli({
|
|
52206
52269
|
argv: argv.slice(1),
|
|
52207
52270
|
cwd: process.cwd(),
|
|
52208
|
-
generator: `@dereekb/dbx-components-mcp@${package_default.version}
|
|
52271
|
+
generator: `@dereekb/dbx-components-mcp@${package_default.version}`,
|
|
52272
|
+
binName: "dbx-components-mcp generate-firestore-indexes"
|
|
52209
52273
|
});
|
|
52210
52274
|
exitCode = result.exitCode;
|
|
52211
52275
|
} else {
|
|
@@ -866,6 +866,146 @@
|
|
|
866
866
|
"date-cell-index-range"
|
|
867
867
|
]
|
|
868
868
|
},
|
|
869
|
+
{
|
|
870
|
+
"slug": "date-cell-schedule-encoded-week-regex",
|
|
871
|
+
"name": "DATE_CELL_SCHEDULE_ENCODED_WEEK_REGEX",
|
|
872
|
+
"kind": "const",
|
|
873
|
+
"category": "date",
|
|
874
|
+
"module": "@dereekb/date",
|
|
875
|
+
"subpath": "date/date.cell.schedule",
|
|
876
|
+
"signature": "const DATE_CELL_SCHEDULE_ENCODED_WEEK_REGEX: RegExp",
|
|
877
|
+
"description": "Regex that loosely validates a {@link DateCellScheduleEncodedWeek}.\n\nMatches zero-to-nine digit characters (any of `0-9`). Does not enforce ascending order or uniqueness of\ndigits — use {@link isDateCellScheduleEncodedWeek} for a runtime check that mirrors the type, or\n{@link dateCellScheduleEncodedWeek} to build a guaranteed-valid encoding from {@link DateCellScheduleDayCode}\nvalues.",
|
|
878
|
+
"params": [],
|
|
879
|
+
"returns": "RegExp",
|
|
880
|
+
"tags": [
|
|
881
|
+
"date",
|
|
882
|
+
"schedule",
|
|
883
|
+
"encoded",
|
|
884
|
+
"week",
|
|
885
|
+
"regex",
|
|
886
|
+
"validate",
|
|
887
|
+
"days",
|
|
888
|
+
"cell",
|
|
889
|
+
"date_cell_schedule_encoded_week_regex"
|
|
890
|
+
],
|
|
891
|
+
"relatedSlugs": [
|
|
892
|
+
"is-date-cell-schedule-encoded-week",
|
|
893
|
+
"date-cell-schedule-encoded-week"
|
|
894
|
+
]
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
"slug": "is-date-cell-schedule-encoded-week",
|
|
898
|
+
"name": "isDateCellScheduleEncodedWeek",
|
|
899
|
+
"kind": "function",
|
|
900
|
+
"category": "date",
|
|
901
|
+
"module": "@dereekb/date",
|
|
902
|
+
"subpath": "date/date.cell.schedule",
|
|
903
|
+
"signature": "isDateCellScheduleEncodedWeek(input: string): input is DateCellScheduleEncodedWeek",
|
|
904
|
+
"description": "Type guard that returns true if the input matches the {@link DATE_CELL_SCHEDULE_ENCODED_WEEK_REGEX} encoded-week format.\n\nThe regex check is loose — it allows duplicate digits and any digit ordering. To produce a canonically simplified\nencoding, use {@link dateCellScheduleEncodedWeek}.",
|
|
905
|
+
"params": [
|
|
906
|
+
{
|
|
907
|
+
"name": "input",
|
|
908
|
+
"type": "string",
|
|
909
|
+
"description": "- String to validate against the encoded week regex.",
|
|
910
|
+
"optional": false
|
|
911
|
+
}
|
|
912
|
+
],
|
|
913
|
+
"returns": "Whether the string matches the encoded week format.",
|
|
914
|
+
"tags": [
|
|
915
|
+
"date",
|
|
916
|
+
"schedule",
|
|
917
|
+
"encoded",
|
|
918
|
+
"week",
|
|
919
|
+
"type-guard",
|
|
920
|
+
"validate",
|
|
921
|
+
"check",
|
|
922
|
+
"days",
|
|
923
|
+
"is",
|
|
924
|
+
"cell",
|
|
925
|
+
"isdatecellscheduleencodedweek"
|
|
926
|
+
],
|
|
927
|
+
"example": "isDateCellScheduleEncodedWeek('24'); // true (Mon + Wed)\nisDateCellScheduleEncodedWeek('8'); // true (WEEKDAY shorthand)\nisDateCellScheduleEncodedWeek(''); // true (no days)\nisDateCellScheduleEncodedWeek('abc'); // false",
|
|
928
|
+
"relatedSlugs": [
|
|
929
|
+
"date-cell-schedule-encoded-week-regex",
|
|
930
|
+
"is-empty-date-cell-schedule-encoded-week",
|
|
931
|
+
"date-cell-schedule-encoded-week"
|
|
932
|
+
]
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
"slug": "is-empty-date-cell-schedule-encoded-week",
|
|
936
|
+
"name": "isEmptyDateCellScheduleEncodedWeek",
|
|
937
|
+
"kind": "function",
|
|
938
|
+
"category": "date",
|
|
939
|
+
"module": "@dereekb/date",
|
|
940
|
+
"subpath": "date/date.cell.schedule",
|
|
941
|
+
"signature": "isEmptyDateCellScheduleEncodedWeek(input: string): input is DateCellScheduleEncodedWeek",
|
|
942
|
+
"description": "Returns true if the input represents an empty (no days selected) {@link DateCellScheduleEncodedWeek}.\n\nBoth the empty string `''` and `'0'` are treated as empty since `0` corresponds to\n{@link DateCellScheduleDayCode.NONE}, the no-op day code.",
|
|
943
|
+
"params": [
|
|
944
|
+
{
|
|
945
|
+
"name": "input",
|
|
946
|
+
"type": "string",
|
|
947
|
+
"description": "- String to check for emptiness.",
|
|
948
|
+
"optional": false
|
|
949
|
+
}
|
|
950
|
+
],
|
|
951
|
+
"returns": "Whether the encoded week represents no selected days.",
|
|
952
|
+
"tags": [
|
|
953
|
+
"date",
|
|
954
|
+
"schedule",
|
|
955
|
+
"encoded",
|
|
956
|
+
"week",
|
|
957
|
+
"empty",
|
|
958
|
+
"check",
|
|
959
|
+
"type-guard",
|
|
960
|
+
"days",
|
|
961
|
+
"is",
|
|
962
|
+
"cell",
|
|
963
|
+
"isemptydatecellscheduleencodedweek"
|
|
964
|
+
],
|
|
965
|
+
"example": "isEmptyDateCellScheduleEncodedWeek(''); // true\nisEmptyDateCellScheduleEncodedWeek('0'); // true (NONE code)\nisEmptyDateCellScheduleEncodedWeek('8'); // false (WEEKDAY)\nisEmptyDateCellScheduleEncodedWeek('24'); // false (Mon + Wed)",
|
|
966
|
+
"relatedSlugs": [
|
|
967
|
+
"is-date-cell-schedule-encoded-week",
|
|
968
|
+
"date-cell-schedule-encoded-week"
|
|
969
|
+
]
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
"slug": "date-cell-schedule-encoded-week",
|
|
973
|
+
"name": "dateCellScheduleEncodedWeek",
|
|
974
|
+
"kind": "function",
|
|
975
|
+
"category": "date",
|
|
976
|
+
"module": "@dereekb/date",
|
|
977
|
+
"subpath": "date/date.cell.schedule",
|
|
978
|
+
"signature": "dateCellScheduleEncodedWeek(codes: Iterable<DateCellScheduleDayCode>): DateCellScheduleEncodedWeek",
|
|
979
|
+
"description": "Creates a simplified {@link DateCellScheduleEncodedWeek} from an iterable of {@link DateCellScheduleDayCode} values.\n\nCodes are passed through {@link simplifyDateCellScheduleDayCodes} so redundant individual day codes are collapsed\ninto shorthand (e.g. Mon-Fri becomes WEEKDAY `8`, Sat+Sun becomes WEEKEND `9`) and digits are emitted in ascending order.",
|
|
980
|
+
"params": [
|
|
981
|
+
{
|
|
982
|
+
"name": "codes",
|
|
983
|
+
"type": "Iterable<DateCellScheduleDayCode>",
|
|
984
|
+
"description": "- Day codes to encode into the compact string representation.",
|
|
985
|
+
"optional": false
|
|
986
|
+
}
|
|
987
|
+
],
|
|
988
|
+
"returns": "The encoded week string.",
|
|
989
|
+
"tags": [
|
|
990
|
+
"date",
|
|
991
|
+
"schedule",
|
|
992
|
+
"encoded",
|
|
993
|
+
"week",
|
|
994
|
+
"encode",
|
|
995
|
+
"days",
|
|
996
|
+
"simplify",
|
|
997
|
+
"weekday",
|
|
998
|
+
"weekend",
|
|
999
|
+
"cell",
|
|
1000
|
+
"datecellscheduleencodedweek"
|
|
1001
|
+
],
|
|
1002
|
+
"example": "// Encode weekdays only — collapses into the WEEKDAY shorthand\ndateCellScheduleEncodedWeek([DateCellScheduleDayCode.MONDAY, DateCellScheduleDayCode.TUESDAY, DateCellScheduleDayCode.WEDNESDAY, DateCellScheduleDayCode.THURSDAY, DateCellScheduleDayCode.FRIDAY]);\n// Returns '8'\n\n// Encode specific days\ndateCellScheduleEncodedWeek([DateCellScheduleDayCode.MONDAY, DateCellScheduleDayCode.WEDNESDAY]);\n// Returns '24'\n\n// Encode the full week\ndateCellScheduleEncodedWeek([DateCellScheduleDayCode.WEEKDAY, DateCellScheduleDayCode.WEEKEND]);\n// Returns '89'",
|
|
1003
|
+
"relatedSlugs": [
|
|
1004
|
+
"is-date-cell-schedule-encoded-week",
|
|
1005
|
+
"simplify-date-cell-schedule-day-codes",
|
|
1006
|
+
"expand-date-cell-schedule-day-codes"
|
|
1007
|
+
]
|
|
1008
|
+
},
|
|
869
1009
|
{
|
|
870
1010
|
"slug": "time-duration-data-is-empty",
|
|
871
1011
|
"name": "timeDurationDataIsEmpty",
|
|
@@ -1928,6 +1928,170 @@
|
|
|
1928
1928
|
"example": "<dbx-bar>\n <span>Title</span>\n <dbx-spacer></dbx-spacer>\n <button mat-button>Action</button>\n</dbx-bar>",
|
|
1929
1929
|
"minimalExample": "<dbx-spacer></dbx-spacer>"
|
|
1930
1930
|
},
|
|
1931
|
+
{
|
|
1932
|
+
"slug": "style-body",
|
|
1933
|
+
"category": "layout",
|
|
1934
|
+
"kind": "directive",
|
|
1935
|
+
"selector": "[dbxStyleBody]",
|
|
1936
|
+
"className": "DbxStyleBodyDirective",
|
|
1937
|
+
"module": "@dereekb/dbx-web",
|
|
1938
|
+
"description": "Applies the current application style class from {@link DbxStyleService} to the document `<body>` element.\n\nPlace this directive on a root-level element so that the body tag receives the active style class.",
|
|
1939
|
+
"inputs": [],
|
|
1940
|
+
"outputs": [],
|
|
1941
|
+
"relatedSlugs": [
|
|
1942
|
+
"style",
|
|
1943
|
+
"style-service",
|
|
1944
|
+
"set-style"
|
|
1945
|
+
],
|
|
1946
|
+
"example": "<div dbxStyleBody></div>",
|
|
1947
|
+
"minimalExample": "<div dbxStyleBody></div>"
|
|
1948
|
+
},
|
|
1949
|
+
{
|
|
1950
|
+
"slug": "color",
|
|
1951
|
+
"category": "layout",
|
|
1952
|
+
"kind": "directive",
|
|
1953
|
+
"selector": "[dbxColor]",
|
|
1954
|
+
"className": "DbxColorDirective",
|
|
1955
|
+
"module": "@dereekb/dbx-web",
|
|
1956
|
+
"description": "Applies a themed background color to the host element.\n\nAccepts either a {@link DbxThemeColor} string (e.g. `'primary'`, `'success'`) or a {@link DbxColorConfig}\nobject carrying arbitrary CSS color values (any hex, `rgb()`, `hsl()`, `var(...)`, `color-mix(...)`, etc.).\n\nOptionally set {@link dbxColorTone} (0-100) to control background opacity for a tonal/muted appearance.\nWhen tonal mode is active, the `dbx-color-tonal` CSS class is added and a CSS rule overrides the text\ncolor to the vibrant color (via `--dbx-bg-color-current`).\n\nThe standalone `[dbxColorTone]` input wins over `config.tone` when both are set; the same precedence\napplies to tonal mode.",
|
|
1957
|
+
"inputs": [
|
|
1958
|
+
{
|
|
1959
|
+
"name": "dbxColor",
|
|
1960
|
+
"type": "Maybe<DbxColorInput>",
|
|
1961
|
+
"description": "",
|
|
1962
|
+
"required": false
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
"name": "dbxColorTone",
|
|
1966
|
+
"type": "Maybe<DbxColorTone>",
|
|
1967
|
+
"description": "Background tone level (0-100). When set, the background becomes semi-transparent\nand text color switches to the vibrant theme color for a tonal appearance.",
|
|
1968
|
+
"required": false
|
|
1969
|
+
}
|
|
1970
|
+
],
|
|
1971
|
+
"outputs": [],
|
|
1972
|
+
"relatedSlugs": [
|
|
1973
|
+
"text-color",
|
|
1974
|
+
"color-service"
|
|
1975
|
+
],
|
|
1976
|
+
"example": "<div [dbxColor]=\"'primary'\">Themed background</div>\n<div [dbxColor]=\"'primary'\" [dbxColorTone]=\"18\">Tonal themed</div>\n<div [dbxColor]=\"{ color: '#ff0066', contrast: 'white' }\">Custom hex</div>\n<div [dbxColor]=\"{ color: 'var(--mat-sys-tertiary)', contrast: 'var(--mat-sys-on-tertiary)', tone: 18 }\">Custom tonal</div>",
|
|
1977
|
+
"minimalExample": "<div [dbxColor]=\"'primary'\"></div>"
|
|
1978
|
+
},
|
|
1979
|
+
{
|
|
1980
|
+
"slug": "color-service",
|
|
1981
|
+
"category": "layout",
|
|
1982
|
+
"kind": "service",
|
|
1983
|
+
"selector": "",
|
|
1984
|
+
"className": "DbxColorService",
|
|
1985
|
+
"module": "@dereekb/dbx-web",
|
|
1986
|
+
"description": "Service that registers named {@link DbxColorConfigTemplate} entries and expands\n{@link DbxColorConfig} values that reference a template by key.\n\nSeeded via `provideDbxStyleService({ dbxColorServiceConfig: { templates: [...] } })`,\nthen injected by {@link DbxColorDirective} and {@link DbxTextColorDirective} to resolve\ntemplate references at render time.",
|
|
1987
|
+
"inputs": [],
|
|
1988
|
+
"outputs": [],
|
|
1989
|
+
"relatedSlugs": [
|
|
1990
|
+
"color",
|
|
1991
|
+
"text-color",
|
|
1992
|
+
"style-service"
|
|
1993
|
+
],
|
|
1994
|
+
"example": "const colorService = inject(DbxColorService);\ncolorService.register({ key: 'brand-positive', config: { color: '#1f9b59', contrast: 'white', tone: 18 } });\ncolorService.expandColorConfig({ template: 'brand-positive' });\n// -> { template: 'brand-positive', color: '#1f9b59', contrast: 'white', tone: 18 }"
|
|
1995
|
+
},
|
|
1996
|
+
{
|
|
1997
|
+
"slug": "style",
|
|
1998
|
+
"category": "layout",
|
|
1999
|
+
"kind": "directive",
|
|
2000
|
+
"selector": "dbx-style, [dbxStyle], .dbx-style",
|
|
2001
|
+
"className": "DbxStyleDirective",
|
|
2002
|
+
"module": "@dereekb/dbx-web",
|
|
2003
|
+
"description": "Applies the current application style class from {@link DbxStyleService} to the host element.\n\nUse this directive to propagate the active style class onto any element or component.",
|
|
2004
|
+
"inputs": [],
|
|
2005
|
+
"outputs": [],
|
|
2006
|
+
"relatedSlugs": [
|
|
2007
|
+
"style-service",
|
|
2008
|
+
"style-body",
|
|
2009
|
+
"set-style"
|
|
2010
|
+
],
|
|
2011
|
+
"example": "<div dbxStyle>Styled content</div>",
|
|
2012
|
+
"minimalExample": "<div dbxStyle></div>"
|
|
2013
|
+
},
|
|
2014
|
+
{
|
|
2015
|
+
"slug": "style-service",
|
|
2016
|
+
"category": "layout",
|
|
2017
|
+
"kind": "service",
|
|
2018
|
+
"selector": "",
|
|
2019
|
+
"className": "DbxStyleService",
|
|
2020
|
+
"module": "@dereekb/dbx-web",
|
|
2021
|
+
"description": "Manages application-wide style classes and suffix modes (e.g., dark mode).\n\nConsumers can set a default style config, override it with an observable config,\nand toggle style suffixes to switch between style variants at runtime.\n\nProvided via `provideDbxStyleService()` from `style.providers`.",
|
|
2022
|
+
"inputs": [],
|
|
2023
|
+
"outputs": [],
|
|
2024
|
+
"relatedSlugs": [
|
|
2025
|
+
"style",
|
|
2026
|
+
"set-style",
|
|
2027
|
+
"style-body",
|
|
2028
|
+
"color-service"
|
|
2029
|
+
],
|
|
2030
|
+
"example": "const styleService = inject(DbxStyleService);\nstyleService.toggleDarkSuffix(); // toggle dark mode on/off\nstyleService.setStyleClassSuffix('dark'); // force dark mode"
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
"slug": "set-style",
|
|
2034
|
+
"category": "layout",
|
|
2035
|
+
"kind": "directive",
|
|
2036
|
+
"selector": "[dbxSetStyle]",
|
|
2037
|
+
"className": "DbxSetStyleDirective",
|
|
2038
|
+
"module": "@dereekb/dbx-web",
|
|
2039
|
+
"description": "Sets the active application style for child elements and/or the global {@link DbxStyleService}.\n\nAccepts a {@link DbxStyleName} and optional suffixes, then applies the computed style class\ndepending on the configured {@link DbxSetStyleMode}.",
|
|
2040
|
+
"inputs": [
|
|
2041
|
+
{
|
|
2042
|
+
"name": "setStyleMode",
|
|
2043
|
+
"type": "DbxSetStyleMode",
|
|
2044
|
+
"description": "The mode for the style.\n\n- global: The style will be set on the parent DbxStyleService.\n- self: The style will be applied to the host element.",
|
|
2045
|
+
"required": false,
|
|
2046
|
+
"default": "'self'"
|
|
2047
|
+
},
|
|
2048
|
+
{
|
|
2049
|
+
"name": "dbxSetStyle",
|
|
2050
|
+
"type": "DbxStyleName",
|
|
2051
|
+
"description": "The input DbxStyleName to style the host element with.",
|
|
2052
|
+
"required": false
|
|
2053
|
+
},
|
|
2054
|
+
{
|
|
2055
|
+
"name": "suffixes",
|
|
2056
|
+
"type": "Maybe<string>",
|
|
2057
|
+
"description": "The input suffixes to allow to be applied to the",
|
|
2058
|
+
"required": false,
|
|
2059
|
+
"default": "undefined"
|
|
2060
|
+
}
|
|
2061
|
+
],
|
|
2062
|
+
"outputs": [],
|
|
2063
|
+
"relatedSlugs": [
|
|
2064
|
+
"style",
|
|
2065
|
+
"style-service",
|
|
2066
|
+
"style-body"
|
|
2067
|
+
],
|
|
2068
|
+
"example": "<div [dbxSetStyle]=\"'my-app'\" [setStyleMode]=\"'both'\" [suffixes]=\"'dark'\">\n <!-- Children inherit 'my-app' or 'my-app-dark' styling -->\n</div>",
|
|
2069
|
+
"minimalExample": "<div [dbxSetStyle]=\"'my-app'\"></div>"
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
"slug": "text-color",
|
|
2073
|
+
"category": "layout",
|
|
2074
|
+
"kind": "directive",
|
|
2075
|
+
"selector": "[dbxTextColor]",
|
|
2076
|
+
"className": "DbxTextColorDirective",
|
|
2077
|
+
"module": "@dereekb/dbx-web",
|
|
2078
|
+
"description": "Applies a themed text color to the host element.\n\nAccepts either a {@link DbxThemeColor} string (e.g. `'primary'`, `'warn'`) or a {@link DbxColorConfig}\nobject carrying an arbitrary CSS color value. Unlike {@link DbxColorDirective} which sets the background,\nthis directive only sets the foreground text color.",
|
|
2079
|
+
"inputs": [
|
|
2080
|
+
{
|
|
2081
|
+
"name": "dbxTextColor",
|
|
2082
|
+
"type": "Maybe<DbxColorInput>",
|
|
2083
|
+
"description": "",
|
|
2084
|
+
"required": false
|
|
2085
|
+
}
|
|
2086
|
+
],
|
|
2087
|
+
"outputs": [],
|
|
2088
|
+
"relatedSlugs": [
|
|
2089
|
+
"color",
|
|
2090
|
+
"color-service"
|
|
2091
|
+
],
|
|
2092
|
+
"example": "<mat-icon [dbxTextColor]=\"'warn'\">error</mat-icon>\n<span [dbxTextColor]=\"'primary'\">Themed text</span>\n<span [dbxTextColor]=\"{ color: '#0066ff' }\">Custom hex text</span>",
|
|
2093
|
+
"minimalExample": "<span [dbxTextColor]=\"'primary'\"></span>"
|
|
2094
|
+
},
|
|
1931
2095
|
{
|
|
1932
2096
|
"slug": "click-to-copy-text",
|
|
1933
2097
|
"category": "text",
|
|
@@ -264,7 +264,7 @@
|
|
|
264
264
|
"whatItFlags": "A composite index required by tagged factories is missing from the committed `firestore.indexes.json`.",
|
|
265
265
|
"whenItApplies": "Every entry in the generated composite set that has no equal entry in the committed JSON.",
|
|
266
266
|
"whenItDoesNotApply": "Factories tagged `@dbxModelFirebaseIndexManual` — their shapes are author-managed and excluded from drift.",
|
|
267
|
-
"canonicalFix": "Run the `scan-model-firebase-indexes`
|
|
267
|
+
"canonicalFix": "Run `dbx-cli-generate-firestore-indexes --component <dir>` (and the `scan-model-firebase-indexes` CLI if the manifest is also stale) and commit the regenerated `firestore.indexes.json`."
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
270
|
"code": "MODEL_FIREBASE_INDEX_COMPOSITE_REMOVED",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-components-mcp",
|
|
3
|
-
"version": "13.11.
|
|
3
|
+
"version": "13.11.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dbx-components-mcp": "dbx-components-mcp.js"
|
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
"@angular/core": "21.2.11",
|
|
16
16
|
"@angular/forms": "21.2.11",
|
|
17
17
|
"@angular/material": "^21.2.9",
|
|
18
|
-
"@dereekb/dbx-cli": "13.11.
|
|
19
|
-
"@dereekb/dbx-core": "13.11.
|
|
20
|
-
"@dereekb/dbx-firebase": "13.11.
|
|
21
|
-
"@dereekb/dbx-form": "13.11.
|
|
22
|
-
"@dereekb/dbx-web": "13.11.
|
|
23
|
-
"@dereekb/firebase": "13.11.
|
|
24
|
-
"@dereekb/firebase-server": "13.11.
|
|
25
|
-
"@dereekb/rxjs": "13.11.
|
|
26
|
-
"@dereekb/util": "13.11.
|
|
18
|
+
"@dereekb/dbx-cli": "13.11.16",
|
|
19
|
+
"@dereekb/dbx-core": "13.11.16",
|
|
20
|
+
"@dereekb/dbx-firebase": "13.11.16",
|
|
21
|
+
"@dereekb/dbx-form": "13.11.16",
|
|
22
|
+
"@dereekb/dbx-web": "13.11.16",
|
|
23
|
+
"@dereekb/firebase": "13.11.16",
|
|
24
|
+
"@dereekb/firebase-server": "13.11.16",
|
|
25
|
+
"@dereekb/rxjs": "13.11.16",
|
|
26
|
+
"@dereekb/util": "13.11.16",
|
|
27
27
|
"@uirouter/angular": "21.0.0",
|
|
28
28
|
"rxjs": "^7.8.2"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@dereekb/model": "13.11.
|
|
31
|
+
"@dereekb/model": "13.11.16"
|
|
32
32
|
}
|
|
33
33
|
}
|