@dereekb/dbx-components-mcp 13.12.4 → 13.12.6

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.
@@ -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.12.4",
8
+ version: "13.12.6",
9
9
  type: "module",
10
10
  bin: {
11
11
  "dbx-components-mcp": "dbx-components-mcp.js"
@@ -16,24 +16,8 @@ var package_default = {
16
16
  "ts-morph": "^21.0.0"
17
17
  },
18
18
  peerDependencies: {
19
- "@angular/common": "21.2.11",
20
- "@angular/core": "21.2.11",
21
- "@angular/forms": "21.2.11",
22
- "@angular/material": "^21.2.9",
23
- "@dereekb/dbx-cli": "13.12.4",
24
- "@dereekb/dbx-core": "13.12.4",
25
- "@dereekb/dbx-firebase": "13.12.4",
26
- "@dereekb/dbx-form": "13.12.4",
27
- "@dereekb/dbx-web": "13.12.4",
28
- "@dereekb/firebase": "13.12.4",
29
- "@dereekb/firebase-server": "13.12.4",
30
- "@dereekb/rxjs": "13.12.4",
31
- "@dereekb/util": "13.12.4",
32
- "@uirouter/angular": "21.0.0",
33
- rxjs: "^7.8.2"
34
- },
35
- devDependencies: {
36
- "@dereekb/model": "13.12.4"
19
+ "@dereekb/dbx-cli": "13.12.6",
20
+ "@dereekb/util": "13.12.6"
37
21
  }
38
22
  };
39
23
 
@@ -130,6 +114,89 @@ var DASH_CHARACTER_PREFIX_INSTANCE = characterPrefixSuffixInstance({
130
114
  prefix: "-"
131
115
  });
132
116
 
117
+ // packages/util/src/lib/test/spec-file-conventions.ts
118
+ var CANONICAL_KINDS = ["crud", "crud-subgroup", "scenario", "scenario-subgroup"];
119
+ var SPEC_SUFFIX = ".spec.ts";
120
+ function classifySpecFile(config) {
121
+ const { filename, parentFolderName } = config;
122
+ let result;
123
+ if (!filename.endsWith(SPEC_SUFFIX)) {
124
+ result = { filename, group: "", kind: "non-spec", subgroups: [], isCanonical: false };
125
+ } else {
126
+ const stem = filename.slice(0, -SPEC_SUFFIX.length);
127
+ const parts = stem.split(".");
128
+ const group = parts[0] ?? "";
129
+ if (group !== parentFolderName) {
130
+ result = { filename, group, kind: "non-group", subgroups: [], isCanonical: false };
131
+ } else {
132
+ const rest = parts.slice(1);
133
+ result = classifyRemainingSegments({ filename, group, rest });
134
+ }
135
+ }
136
+ return result;
137
+ }
138
+ function classifyRemainingSegments(config) {
139
+ const { filename, group, rest } = config;
140
+ let result;
141
+ const crudIdx = rest.indexOf("crud");
142
+ const scenarioIdx = rest.indexOf("scenario");
143
+ if (crudIdx === 0) {
144
+ if (rest.length === 1) {
145
+ result = { filename, group, kind: "crud", subgroups: [], isCanonical: true };
146
+ } else {
147
+ result = { filename, group, kind: "crud-subgroup", subgroups: rest.slice(1), isCanonical: true };
148
+ }
149
+ } else if (scenarioIdx === 0) {
150
+ if (rest.length === 1) {
151
+ result = { filename, group, kind: "scenario", subgroups: [], isCanonical: true };
152
+ } else {
153
+ result = { filename, group, kind: "scenario-subgroup", subgroups: rest.slice(1), isCanonical: true };
154
+ }
155
+ } else if (crudIdx > 0) {
156
+ const subgroups = rest.filter((_, i) => i !== crudIdx);
157
+ const recommendedRename = buildCanonicalFilename({ group, bucket: "crud", subgroups });
158
+ result = { filename, group, kind: "crud-misplaced", subgroups, isCanonical: false, recommendedRename, driftReason: "`crud` segment is not directly after the group name." };
159
+ } else if (scenarioIdx > 0) {
160
+ const subgroups = rest.filter((_, i) => i !== scenarioIdx);
161
+ const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups });
162
+ result = { filename, group, kind: "scenario-misplaced", subgroups, isCanonical: false, recommendedRename, driftReason: "`scenario` segment is not directly after the group name." };
163
+ } else if (rest.length === 0) {
164
+ const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups: [] });
165
+ result = { filename, group, kind: "no-bucket", subgroups: [], isCanonical: false, recommendedRename, driftReason: "Missing `crud` or `scenario` segment." };
166
+ } else {
167
+ const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups: rest });
168
+ result = { filename, group, kind: "no-bucket", subgroups: rest, isCanonical: false, recommendedRename, driftReason: "Missing `crud` or `scenario` segment \u2014 defaulting suggestion to `scenario`." };
169
+ }
170
+ return result;
171
+ }
172
+ function buildCanonicalFilename(config) {
173
+ const { group, bucket, subgroups } = config;
174
+ const tail = subgroups.length === 0 ? "" : `.${subgroups.join(".")}`;
175
+ return `${group}.${bucket}${tail}.spec.ts`;
176
+ }
177
+ function recommendSpecPath(config) {
178
+ const filename = buildCanonicalFilename({ group: config.group, bucket: config.bucket, subgroups: config.subgroups });
179
+ return `${config.apiDir}/src/app/function/${config.group}/${filename}`;
180
+ }
181
+ function recommendBucketsForGroup(config) {
182
+ const crudPath = recommendSpecPath({ apiDir: config.apiDir, group: config.group, bucket: "crud", subgroups: [] });
183
+ const scenarioPath = recommendSpecPath({ apiDir: config.apiDir, group: config.group, bucket: "scenario", subgroups: [] });
184
+ return [
185
+ {
186
+ bucket: "crud",
187
+ label: "CRUD",
188
+ canonicalPath: crudPath,
189
+ summary: "Non-scenario tests of the CRUD function map \u2014 create/read/update/delete + permission/error paths. Add focused buckets as `" + config.group + ".crud.<sub>.spec.ts`."
190
+ },
191
+ {
192
+ bucket: "scenario",
193
+ label: "Scenario",
194
+ canonicalPath: scenarioPath,
195
+ summary: "Multi-step scenarios using fixture chains (mirrors real workflows). Add focused buckets as `" + config.group + ".scenario.<sub>.spec.ts` (chain subgroups freely, e.g. `.scenario.requirement.worker.spec.ts`)."
196
+ }
197
+ ];
198
+ }
199
+
133
200
  // packages/firebase/src/lib/common/auth/oidc/oidc.error.ts
134
201
  var CALL_MODEL_MISSING_OIDC_SCOPE_ERROR_CODE = "CALL_MODEL_MISSING_OIDC_SCOPE";
135
202
 
@@ -27671,6 +27738,7 @@ function extractCrudEntries(source) {
27671
27738
  description: readJsDocSummary(member),
27672
27739
  paramsTypeDescription: paramsDocs?.typeDescription,
27673
27740
  paramsFields: paramsDocs?.fields,
27741
+ paramsHasApiParamsTag: paramsDocs?.hasApiParamsTag,
27674
27742
  resultTypeDescription: resultDocs?.typeDescription,
27675
27743
  resultFields: resultDocs?.fields
27676
27744
  });
@@ -27761,6 +27829,7 @@ function collectVerbEntries(input) {
27761
27829
  description: readJsDocSummary(specMember),
27762
27830
  paramsTypeDescription: paramsDocs2?.typeDescription,
27763
27831
  paramsFields: paramsDocs2?.fields,
27832
+ paramsHasApiParamsTag: paramsDocs2?.hasApiParamsTag,
27764
27833
  resultTypeDescription: resultDocs2?.typeDescription,
27765
27834
  resultFields: resultDocs2?.fields
27766
27835
  });
@@ -27780,6 +27849,7 @@ function collectVerbEntries(input) {
27780
27849
  description: fallbackDescription,
27781
27850
  paramsTypeDescription: paramsDocs?.typeDescription,
27782
27851
  paramsFields: paramsDocs?.fields,
27852
+ paramsHasApiParamsTag: paramsDocs?.hasApiParamsTag,
27783
27853
  resultTypeDescription: resultDocs?.typeDescription,
27784
27854
  resultFields: resultDocs?.fields
27785
27855
  });
@@ -27815,17 +27885,28 @@ function readTypeDocs(sourceFile, typeName) {
27815
27885
  const interfaceDecl = sourceFile.getInterface(typeName);
27816
27886
  if (interfaceDecl) {
27817
27887
  const typeDescription = readJsDocSummary(interfaceDecl);
27888
+ const hasApiParamsTag = hasJsDocFlag(interfaceDecl, "dbxModelApiParams");
27818
27889
  const fields = [];
27819
27890
  for (const property of interfaceDecl.getProperties()) {
27820
27891
  const fieldName = property.getName();
27821
27892
  const description = readJsDocSummary(property);
27822
27893
  const typeNode = property.getTypeNode();
27823
27894
  const typeText = typeNode?.getText().trim() ?? "";
27824
- const field = description ? { name: fieldName, typeText, description } : { name: fieldName, typeText };
27895
+ const adminOnly = hasJsDocFlag(property, "dbxModelApiAdminOnly");
27896
+ const field = {
27897
+ name: fieldName,
27898
+ typeText,
27899
+ ...description ? { description } : {},
27900
+ ...adminOnly ? { accessLevel: "adminOnly" } : {}
27901
+ };
27825
27902
  fields.push(field);
27826
27903
  }
27827
- if (typeDescription || fields.length > 0) {
27828
- result = { typeDescription, fields: fields.length > 0 ? fields : void 0 };
27904
+ if (typeDescription || fields.length > 0 || hasApiParamsTag) {
27905
+ result = {
27906
+ ...typeDescription ? { typeDescription } : {},
27907
+ ...fields.length > 0 ? { fields } : {},
27908
+ hasApiParamsTag
27909
+ };
27829
27910
  }
27830
27911
  } else {
27831
27912
  const typeAlias = sourceFile.getTypeAlias(typeName);
@@ -27838,6 +27919,17 @@ function readTypeDocs(sourceFile, typeName) {
27838
27919
  }
27839
27920
  return result;
27840
27921
  }
27922
+ function hasJsDocFlag(node, tagName) {
27923
+ let result = false;
27924
+ for (const doc of node.getJsDocs()) {
27925
+ for (const tag of doc.getTags()) {
27926
+ if (tag.getTagName() === tagName) {
27927
+ result = true;
27928
+ }
27929
+ }
27930
+ }
27931
+ return result;
27932
+ }
27841
27933
  function readJsDocSummary(node) {
27842
27934
  let result;
27843
27935
  const docs = node.getJsDocs();
@@ -28313,6 +28405,7 @@ function mapEntry(entry, sourceFile, actionLookup) {
28313
28405
  sourceFile,
28314
28406
  paramsJsDoc: entry.paramsTypeDescription,
28315
28407
  paramsFields: mapDocFields(entry.paramsFields),
28408
+ paramsApiParamsTag: entry.paramsHasApiParamsTag,
28316
28409
  resultJsDoc: entry.resultTypeDescription,
28317
28410
  resultFields: mapDocFields(entry.resultFields),
28318
28411
  action,
@@ -28320,14 +28413,13 @@ function mapEntry(entry, sourceFile, actionLookup) {
28320
28413
  };
28321
28414
  }
28322
28415
  function mapDocFields(fields) {
28323
- if (!fields) {
28324
- return [];
28325
- }
28326
- return fields.map((field) => ({
28416
+ const result = fields ? fields.map((field) => ({
28327
28417
  name: field.name,
28328
28418
  typeText: field.typeText,
28329
- jsDoc: field.description
28330
- }));
28419
+ jsDoc: field.description,
28420
+ accessLevel: field.accessLevel ?? "public"
28421
+ })) : [];
28422
+ return result;
28331
28423
  }
28332
28424
  async function collectApiSources(componentAbs) {
28333
28425
  const root = join7(componentAbs, COMPONENT_LIB_SUBPATH);
@@ -28454,7 +28546,7 @@ function formatEntry2(entry) {
28454
28546
  const lines = [`## ${heading}`, ""];
28455
28547
  if (entry.description) lines.push(entry.description, "");
28456
28548
  lines.push(`- Wire key: \`${wireKey}\``, `- Params: ${paramsLabel}`, `- Result: ${resultLabel}`, `- Source: \`${entry.sourceFile}:${entry.line}\``, "");
28457
- appendFieldsSection({ lines, label: "Params", jsDoc: entry.paramsJsDoc, fields: entry.paramsFields });
28549
+ appendFieldsSection({ lines, label: "Params", jsDoc: entry.paramsJsDoc, fields: entry.paramsFields, missingApiParamsTag: entry.paramsApiParamsTag === false });
28458
28550
  appendFieldsSection({ lines, label: "Result", jsDoc: entry.resultJsDoc, fields: entry.resultFields });
28459
28551
  appendActionMethodSection(lines, entry.action);
28460
28552
  appendActionFactorySection(lines, entry.factory);
@@ -28464,10 +28556,11 @@ function formatEntry2(entry) {
28464
28556
  return lines.join("\n").trimEnd();
28465
28557
  }
28466
28558
  function appendFieldsSection(input) {
28467
- const { lines, label, jsDoc, fields } = input;
28468
- if (!jsDoc && fields.length === 0) return;
28559
+ const { lines, label, jsDoc, fields, missingApiParamsTag } = input;
28560
+ if (!jsDoc && fields.length === 0 && !missingApiParamsTag) return;
28469
28561
  lines.push(`### ${label}`);
28470
28562
  if (jsDoc) lines.push("", jsDoc);
28563
+ if (missingApiParamsTag) lines.push("", "_Missing `@dbxModelApiParams` marker on the params interface._");
28471
28564
  if (fields.length > 0) {
28472
28565
  lines.push("");
28473
28566
  for (const field of fields) lines.push(formatField(field));
@@ -28496,8 +28589,9 @@ function formatWireKey(entry) {
28496
28589
  return `${entry.verb}:${entry.specifier}`;
28497
28590
  }
28498
28591
  function formatField(field) {
28592
+ const adminBadge = field.accessLevel === "adminOnly" ? " _(admin only)_" : "";
28499
28593
  const doc = field.jsDoc ? ` \u2014 ${field.jsDoc.split("\n")[0]}` : "";
28500
- return `- \`${field.name}: ${field.typeText}\`${doc}`;
28594
+ return `- \`${field.name}: ${field.typeText}\`${adminBadge}${doc}`;
28501
28595
  }
28502
28596
 
28503
28597
  // packages/dbx-components-mcp/src/tools/model-api-lookup/index.ts
@@ -32590,89 +32684,6 @@ function parseDescribePath2(value) {
32590
32684
  return value.split(">").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
32591
32685
  }
32592
32686
 
32593
- // packages/dbx-components-mcp/src/tools/model-test-shared/conventions.ts
32594
- var CANONICAL_KINDS = ["crud", "crud-subgroup", "scenario", "scenario-subgroup"];
32595
- var SPEC_SUFFIX = ".spec.ts";
32596
- function classifySpecFile(config) {
32597
- const { filename, parentFolderName } = config;
32598
- let result;
32599
- if (!filename.endsWith(SPEC_SUFFIX)) {
32600
- result = { filename, group: "", kind: "non-spec", subgroups: [], isCanonical: false };
32601
- } else {
32602
- const stem = filename.slice(0, -SPEC_SUFFIX.length);
32603
- const parts = stem.split(".");
32604
- const group = parts[0] ?? "";
32605
- if (group !== parentFolderName) {
32606
- result = { filename, group, kind: "non-group", subgroups: [], isCanonical: false };
32607
- } else {
32608
- const rest = parts.slice(1);
32609
- result = classifyRemainingSegments({ filename, group, rest });
32610
- }
32611
- }
32612
- return result;
32613
- }
32614
- function classifyRemainingSegments(config) {
32615
- const { filename, group, rest } = config;
32616
- let result;
32617
- const crudIdx = rest.indexOf("crud");
32618
- const scenarioIdx = rest.indexOf("scenario");
32619
- if (crudIdx === 0) {
32620
- if (rest.length === 1) {
32621
- result = { filename, group, kind: "crud", subgroups: [], isCanonical: true };
32622
- } else {
32623
- result = { filename, group, kind: "crud-subgroup", subgroups: rest.slice(1), isCanonical: true };
32624
- }
32625
- } else if (scenarioIdx === 0) {
32626
- if (rest.length === 1) {
32627
- result = { filename, group, kind: "scenario", subgroups: [], isCanonical: true };
32628
- } else {
32629
- result = { filename, group, kind: "scenario-subgroup", subgroups: rest.slice(1), isCanonical: true };
32630
- }
32631
- } else if (crudIdx > 0) {
32632
- const subgroups = rest.filter((p, i) => i !== crudIdx);
32633
- const recommendedRename = buildCanonicalFilename({ group, bucket: "crud", subgroups });
32634
- result = { filename, group, kind: "crud-misplaced", subgroups, isCanonical: false, recommendedRename, driftReason: "`crud` segment is not directly after the group name." };
32635
- } else if (scenarioIdx > 0) {
32636
- const subgroups = rest.filter((p, i) => i !== scenarioIdx);
32637
- const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups });
32638
- result = { filename, group, kind: "scenario-misplaced", subgroups, isCanonical: false, recommendedRename, driftReason: "`scenario` segment is not directly after the group name." };
32639
- } else if (rest.length === 0) {
32640
- const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups: [] });
32641
- result = { filename, group, kind: "no-bucket", subgroups: [], isCanonical: false, recommendedRename, driftReason: "Missing `crud` or `scenario` segment." };
32642
- } else {
32643
- const recommendedRename = buildCanonicalFilename({ group, bucket: "scenario", subgroups: rest });
32644
- result = { filename, group, kind: "no-bucket", subgroups: rest, isCanonical: false, recommendedRename, driftReason: "Missing `crud` or `scenario` segment \u2014 defaulting suggestion to `scenario`." };
32645
- }
32646
- return result;
32647
- }
32648
- function buildCanonicalFilename(config) {
32649
- const { group, bucket, subgroups } = config;
32650
- const tail = subgroups.length === 0 ? "" : `.${subgroups.join(".")}`;
32651
- return `${group}.${bucket}${tail}.spec.ts`;
32652
- }
32653
- function recommendSpecPath(config) {
32654
- const filename = buildCanonicalFilename({ group: config.group, bucket: config.bucket, subgroups: config.subgroups });
32655
- return `${config.apiDir}/src/app/function/${config.group}/${filename}`;
32656
- }
32657
- function recommendBucketsForGroup(config) {
32658
- const crudPath = recommendSpecPath({ apiDir: config.apiDir, group: config.group, bucket: "crud", subgroups: [] });
32659
- const scenarioPath = recommendSpecPath({ apiDir: config.apiDir, group: config.group, bucket: "scenario", subgroups: [] });
32660
- return [
32661
- {
32662
- bucket: "crud",
32663
- label: "CRUD",
32664
- canonicalPath: crudPath,
32665
- summary: "Non-scenario tests of the CRUD function map \u2014 create/read/update/delete + permission/error paths. Add focused buckets as `" + config.group + ".crud.<sub>.spec.ts`."
32666
- },
32667
- {
32668
- bucket: "scenario",
32669
- label: "Scenario",
32670
- canonicalPath: scenarioPath,
32671
- summary: "Multi-step scenarios using fixture chains (mirrors real workflows). Add focused buckets as `" + config.group + ".scenario.<sub>.spec.ts` (chain subgroups freely, e.g. `.scenario.requirement.worker.spec.ts`)."
32672
- }
32673
- ];
32674
- }
32675
-
32676
32687
  // packages/dbx-components-mcp/src/tools/model-test-shared/discover.ts
32677
32688
  import { readdir as readdir7, stat as stat11 } from "node:fs/promises";
32678
32689
  import { join as join15, relative as relative13, sep as sep11 } from "node:path";
@@ -0,0 +1,272 @@
1
+ {
2
+ "version": 1,
3
+ "source": "@dereekb/firebase-server",
4
+ "module": "@dereekb/firebase-server",
5
+ "generatedAt": "1970-01-01T00:00:00.000Z",
6
+ "generator": "@dereekb/dbx-components-mcp/scripts/generate-manifests.mjs",
7
+ "entries": [
8
+ {
9
+ "slug": "is-firebase-https-error",
10
+ "name": "isFirebaseHttpsError",
11
+ "kind": "function",
12
+ "category": "firebase-error",
13
+ "module": "@dereekb/firebase-server",
14
+ "subpath": "function/error",
15
+ "signature": "isFirebaseHttpsError(input: unknown | HttpsError): input is HttpsError",
16
+ "description": "Type guard for Firebase {@link HttpsError} instances.",
17
+ "params": [
18
+ {
19
+ "name": "input",
20
+ "type": "unknown | HttpsError",
21
+ "description": "- The value to check.",
22
+ "optional": false
23
+ }
24
+ ],
25
+ "returns": "`true` if the input is a Firebase {@link HttpsError }.",
26
+ "tags": [
27
+ "firebase",
28
+ "https",
29
+ "error",
30
+ "type-guard",
31
+ "server",
32
+ "callable",
33
+ "firebase-error",
34
+ "is",
35
+ "isfirebasehttpserror"
36
+ ],
37
+ "relatedSlugs": [
38
+ "is-firebase-error",
39
+ "firebase-server-error-info"
40
+ ]
41
+ },
42
+ {
43
+ "slug": "is-firebase-error",
44
+ "name": "isFirebaseError",
45
+ "kind": "function",
46
+ "category": "firebase-error",
47
+ "module": "@dereekb/firebase-server",
48
+ "subpath": "function/error",
49
+ "signature": "isFirebaseError(input: unknown | admin.FirebaseError): input is admin.FirebaseError",
50
+ "description": "Type guard for Firebase Admin {@link admin.FirebaseError} instances.",
51
+ "params": [
52
+ {
53
+ "name": "input",
54
+ "type": "unknown | admin.FirebaseError",
55
+ "description": "- The value to check.",
56
+ "optional": false
57
+ }
58
+ ],
59
+ "returns": "`true` if the input is a Firebase Admin {@link admin.FirebaseError }.",
60
+ "tags": [
61
+ "firebase",
62
+ "admin",
63
+ "error",
64
+ "type-guard",
65
+ "server",
66
+ "firebase-error",
67
+ "is",
68
+ "isfirebaseerror"
69
+ ],
70
+ "relatedSlugs": [
71
+ "is-firebase-https-error",
72
+ "firebase-server-error-info"
73
+ ]
74
+ },
75
+ {
76
+ "slug": "firebase-server-error-info",
77
+ "name": "firebaseServerErrorInfo",
78
+ "kind": "function",
79
+ "category": "firebase-error",
80
+ "module": "@dereekb/firebase-server",
81
+ "subpath": "function/error",
82
+ "signature": "firebaseServerErrorInfo(e: unknown): FirebaseServerErrorInfo",
83
+ "description": "Analyzes a caught error and extracts structured Firebase error information.\n\nClassifies the error as an {@link HttpsError}, {@link admin.FirebaseError}, or unknown,\nand extracts any embedded error codes and {@link ServerError} details.",
84
+ "params": [
85
+ {
86
+ "name": "e",
87
+ "type": "unknown",
88
+ "description": "- The caught error to analyze.",
89
+ "optional": false
90
+ }
91
+ ],
92
+ "returns": "Structured {@link FirebaseServerErrorInfo } with classified error details.",
93
+ "tags": [
94
+ "firebase",
95
+ "error",
96
+ "decode",
97
+ "analyze",
98
+ "https",
99
+ "admin",
100
+ "server",
101
+ "classify",
102
+ "server-error",
103
+ "firebase-error",
104
+ "info",
105
+ "firebaseservererrorinfo"
106
+ ],
107
+ "example": "try {\n await someFirebaseOperation();\n} catch (e) {\n const info = firebaseServerErrorInfo(e);\n if (info.serverErrorCode === 'MODEL_NOT_AVAILABLE') { ... }\n}",
108
+ "relatedSlugs": [
109
+ "firebase-server-error-info-code-pair",
110
+ "firebase-server-error-info-server-error-pair",
111
+ "firebase-server-error-info-server-error-code-pair",
112
+ "is-firebase-https-error",
113
+ "is-firebase-error"
114
+ ]
115
+ },
116
+ {
117
+ "slug": "firebase-server-error-info-code-pair",
118
+ "name": "firebaseServerErrorInfoCodePair",
119
+ "kind": "function",
120
+ "category": "firebase-error",
121
+ "module": "@dereekb/firebase-server",
122
+ "subpath": "function/error",
123
+ "signature": "firebaseServerErrorInfoCodePair(e: unknown): [Maybe<FirebaseErrorCode>, FirebaseServerErrorInfo]",
124
+ "description": "Returns a tuple of [firebaseErrorCode, errorInfo] for pattern-matching on Firebase error codes.",
125
+ "params": [
126
+ {
127
+ "name": "e",
128
+ "type": "unknown",
129
+ "description": "- The caught error to analyze.",
130
+ "optional": false
131
+ }
132
+ ],
133
+ "returns": "A tuple of the Firebase error code (if present) and the full error info.",
134
+ "tags": [
135
+ "firebase",
136
+ "error",
137
+ "code",
138
+ "pair",
139
+ "tuple",
140
+ "pattern-match",
141
+ "decode",
142
+ "firebase-error",
143
+ "server",
144
+ "info",
145
+ "firebaseservererrorinfocodepair"
146
+ ],
147
+ "relatedSlugs": [
148
+ "firebase-server-error-info",
149
+ "firebase-server-error-info-server-error-pair",
150
+ "firebase-server-error-info-server-error-code-pair"
151
+ ]
152
+ },
153
+ {
154
+ "slug": "firebase-server-error-info-server-error-pair",
155
+ "name": "firebaseServerErrorInfoServerErrorPair",
156
+ "kind": "function",
157
+ "category": "firebase-error",
158
+ "module": "@dereekb/firebase-server",
159
+ "subpath": "function/error",
160
+ "signature": "firebaseServerErrorInfoServerErrorPair(e: unknown): [Maybe<ServerError>, FirebaseServerErrorInfo]",
161
+ "description": "Returns a tuple of [serverError, errorInfo] for pattern-matching on embedded server error details.",
162
+ "params": [
163
+ {
164
+ "name": "e",
165
+ "type": "unknown",
166
+ "description": "- The caught error to analyze.",
167
+ "optional": false
168
+ }
169
+ ],
170
+ "returns": "A tuple of the server error (if present) and the full error info.",
171
+ "tags": [
172
+ "firebase",
173
+ "error",
174
+ "server-error",
175
+ "pair",
176
+ "tuple",
177
+ "pattern-match",
178
+ "decode",
179
+ "details",
180
+ "firebase-error",
181
+ "server",
182
+ "info",
183
+ "firebaseservererrorinfoservererrorpair"
184
+ ],
185
+ "relatedSlugs": [
186
+ "firebase-server-error-info",
187
+ "firebase-server-error-info-code-pair",
188
+ "firebase-server-error-info-server-error-code-pair"
189
+ ]
190
+ },
191
+ {
192
+ "slug": "firebase-server-error-info-server-error-code-pair",
193
+ "name": "firebaseServerErrorInfoServerErrorCodePair",
194
+ "kind": "function",
195
+ "category": "firebase-error",
196
+ "module": "@dereekb/firebase-server",
197
+ "subpath": "function/error",
198
+ "signature": "firebaseServerErrorInfoServerErrorCodePair(e: unknown): [Maybe<StringErrorCode>, FirebaseServerErrorInfo]",
199
+ "description": "Returns a tuple of [serverErrorCode, errorInfo] for pattern-matching on server error string codes.",
200
+ "params": [
201
+ {
202
+ "name": "e",
203
+ "type": "unknown",
204
+ "description": "- The caught error to analyze.",
205
+ "optional": false
206
+ }
207
+ ],
208
+ "returns": "A tuple of the server error code (if present) and the full error info.",
209
+ "tags": [
210
+ "firebase",
211
+ "error",
212
+ "server-error",
213
+ "code",
214
+ "string-code",
215
+ "pair",
216
+ "tuple",
217
+ "pattern-match",
218
+ "decode",
219
+ "firebase-error",
220
+ "server",
221
+ "info",
222
+ "firebaseservererrorinfoservererrorcodepair"
223
+ ],
224
+ "relatedSlugs": [
225
+ "firebase-server-error-info",
226
+ "firebase-server-error-info-code-pair",
227
+ "firebase-server-error-info-server-error-pair"
228
+ ]
229
+ },
230
+ {
231
+ "slug": "handle-firebase-error",
232
+ "name": "handleFirebaseError",
233
+ "kind": "function",
234
+ "category": "firebase-error",
235
+ "module": "@dereekb/firebase-server",
236
+ "subpath": "function/error",
237
+ "signature": "handleFirebaseError(e: unknown, handleFirebaseErrorFn: ThrowErrorFunction<admin.FirebaseError>): never | void",
238
+ "description": "Handles a caught error if it is a Firebase Admin error, passing it to the given handler function.\n\nIf the error is not a Firebase error (no `code` property), this is a no-op.",
239
+ "params": [
240
+ {
241
+ "name": "e",
242
+ "type": "unknown",
243
+ "description": "- The caught error.",
244
+ "optional": false
245
+ },
246
+ {
247
+ "name": "handleFirebaseErrorFn",
248
+ "type": "ThrowErrorFunction<admin.FirebaseError>",
249
+ "description": "- Handler that receives the typed {@link admin.FirebaseError }.",
250
+ "optional": false
251
+ }
252
+ ],
253
+ "returns": "never | void",
254
+ "tags": [
255
+ "firebase",
256
+ "admin",
257
+ "error",
258
+ "handler",
259
+ "catch",
260
+ "conditional",
261
+ "rethrow",
262
+ "firebase-error",
263
+ "handle",
264
+ "handlefirebaseerror"
265
+ ],
266
+ "relatedSlugs": [
267
+ "is-firebase-error",
268
+ "firebase-server-error-info"
269
+ ]
270
+ }
271
+ ]
272
+ }
@@ -5,6 +5,264 @@
5
5
  "generatedAt": "1970-01-01T00:00:00.000Z",
6
6
  "generator": "@dereekb/dbx-components-mcp/scripts/generate-manifests.mjs",
7
7
  "entries": [
8
+ {
9
+ "slug": "is-client-firebase-error",
10
+ "name": "isClientFirebaseError",
11
+ "kind": "function",
12
+ "category": "firebase-error",
13
+ "module": "@dereekb/firebase",
14
+ "subpath": "client/error/error",
15
+ "signature": "isClientFirebaseError(error: unknown): error is FirebaseError",
16
+ "description": "Type guard that checks whether an error is a client-side {@link FirebaseError} from the `firebase/app` package.\n\nDistinguishes client Firebase errors from server-side errors or generic errors by checking\nfor the `FirebaseError` name and a string `code` property. Used by {@link convertHttpsCallableErrorToReadableError}\nto determine the appropriate error wrapping strategy.",
17
+ "params": [
18
+ {
19
+ "name": "error",
20
+ "type": "unknown",
21
+ "description": "- The value to check.",
22
+ "optional": false
23
+ }
24
+ ],
25
+ "returns": "`true` if the input matches the shape of a client-side `FirebaseError`",
26
+ "tags": [
27
+ "firebase",
28
+ "client",
29
+ "error",
30
+ "type-guard",
31
+ "callable",
32
+ "firebase-error",
33
+ "is",
34
+ "isclientfirebaseerror"
35
+ ],
36
+ "example": "try {\n await someFirebaseOperation();\n} catch (e) {\n if (isClientFirebaseError(e)) {\n console.log(e.code); // e.g., 'auth/user-not-found'\n }\n}",
37
+ "relatedSlugs": [
38
+ "convert-https-callable-error-to-readable-error",
39
+ "firebase-server-error"
40
+ ]
41
+ },
42
+ {
43
+ "slug": "firebase-server-error",
44
+ "name": "FirebaseServerError",
45
+ "kind": "class",
46
+ "category": "firebase-error",
47
+ "module": "@dereekb/firebase",
48
+ "subpath": "client/function/error",
49
+ "signature": "class FirebaseServerError",
50
+ "description": "Client-side representation of an error originating from a Firebase Cloud Function.\n\nWraps a {@link FirebaseError} with structured server error details (status, message, code)\nextracted from the error's `details` property. Extends {@link ServerErrorResponse} for\nconsistent error handling across the application.\n\nTypically created via {@link convertHttpsCallableErrorToReadableError} when an `HttpsCallable`\ninvocation fails with a server-side error that includes structured details.",
51
+ "params": [
52
+ {
53
+ "name": "firebaseError",
54
+ "type": "FirebaseError",
55
+ "description": "",
56
+ "optional": false
57
+ },
58
+ {
59
+ "name": "serverError",
60
+ "type": "ServerError<T>",
61
+ "description": "",
62
+ "optional": false
63
+ }
64
+ ],
65
+ "returns": "FirebaseServerError",
66
+ "tags": [
67
+ "firebase",
68
+ "https",
69
+ "callable",
70
+ "error",
71
+ "server-error",
72
+ "client",
73
+ "response",
74
+ "details",
75
+ "firebase-error",
76
+ "server",
77
+ "firebaseservererror"
78
+ ],
79
+ "example": "try {\n await callableFunction(data);\n} catch (e) {\n if (e instanceof FirebaseServerError) {\n console.log(e.code, e.message, e.firebaseError.code);\n }\n}",
80
+ "relatedSlugs": [
81
+ "convert-https-callable-error-to-readable-error",
82
+ "is-client-firebase-error"
83
+ ]
84
+ },
85
+ {
86
+ "slug": "convert-https-callable-error-to-readable-error",
87
+ "name": "convertHttpsCallableErrorToReadableError",
88
+ "kind": "function",
89
+ "category": "firebase-error",
90
+ "module": "@dereekb/firebase",
91
+ "subpath": "client/function/function.callable",
92
+ "signature": "convertHttpsCallableErrorToReadableError(error: unknown): unknown",
93
+ "description": "Converts errors from `HttpsCallable` calls into more readable error types.\n\nIf the error is a client-side {@link FirebaseError} with `details`, wraps it as a {@link FirebaseServerError}\nto preserve server-side error context. Otherwise, converts it to a generic readable error via `toReadableError`.",
94
+ "params": [
95
+ {
96
+ "name": "error",
97
+ "type": "unknown",
98
+ "description": "- The caught error from an `HttpsCallable` invocation.",
99
+ "optional": false
100
+ }
101
+ ],
102
+ "returns": "A {@link FirebaseServerError } if the error has structured details, or a generic readable error otherwise.",
103
+ "tags": [
104
+ "firebase",
105
+ "https",
106
+ "callable",
107
+ "error",
108
+ "decode",
109
+ "convert",
110
+ "readable",
111
+ "client",
112
+ "server",
113
+ "firebase-error",
114
+ "to",
115
+ "converthttpscallableerrortoreadableerror"
116
+ ],
117
+ "relatedSlugs": [
118
+ "firebase-server-error",
119
+ "is-client-firebase-error",
120
+ "firebase-auth-error-to-readable-error"
121
+ ]
122
+ },
123
+ {
124
+ "slug": "firebase-auth-error-to-readable-error",
125
+ "name": "firebaseAuthErrorToReadableError",
126
+ "kind": "function",
127
+ "category": "firebase-auth",
128
+ "module": "@dereekb/firebase",
129
+ "subpath": "common/auth/auth.error",
130
+ "signature": "firebaseAuthErrorToReadableError(inputError: FirebaseAuthError): ReadableError",
131
+ "description": "Converts a {@link FirebaseAuthError} into a user-friendly {@link ReadableError} with a human-readable message.\n\nMaps known error codes (wrong password, user not found, network errors) to contextual messages\nsuitable for display in the UI.",
132
+ "params": [
133
+ {
134
+ "name": "inputError",
135
+ "type": "FirebaseAuthError",
136
+ "description": "- The Firebase Auth error to convert.",
137
+ "optional": false
138
+ }
139
+ ],
140
+ "returns": "A {@link ReadableError } with a human-readable message suitable for display.",
141
+ "tags": [
142
+ "firebase",
143
+ "auth",
144
+ "error",
145
+ "readable",
146
+ "convert",
147
+ "decode",
148
+ "message",
149
+ "login",
150
+ "signin",
151
+ "firebase-auth",
152
+ "to",
153
+ "firebaseautherrortoreadableerror"
154
+ ],
155
+ "example": "try {\n await signIn(email, password);\n} catch (e) {\n const readable = firebaseAuthErrorToReadableError(e as FirebaseAuthError);\n showToast(readable.message);\n}",
156
+ "relatedSlugs": [
157
+ "convert-https-callable-error-to-readable-error",
158
+ "firebase-server-error"
159
+ ]
160
+ },
161
+ {
162
+ "slug": "firebase-auth-oob-code-data-pair-delimiter",
163
+ "name": "FIREBASE_AUTH_OOB_CODE_DATA_PAIR_DELIMITER",
164
+ "kind": "const",
165
+ "category": "firebase-auth",
166
+ "module": "@dereekb/firebase",
167
+ "subpath": "common/auth/auth",
168
+ "signature": "const FIREBASE_AUTH_OOB_CODE_DATA_PAIR_DELIMITER: \"-\"",
169
+ "description": "Delimiter used when encoding a {@link FirebaseAuthOobCodeDataPair} into a {@link FirebaseAuthOobCode}.\n\nThe encoded form is `${code}-${uid}` and splitting happens on the first delimiter occurrence,\nso this only requires that the generated code/password not contain `-`. The uid is unrestricted\nand may itself contain `-`.",
170
+ "params": [],
171
+ "returns": "\"-\"",
172
+ "tags": [
173
+ "firebase",
174
+ "auth",
175
+ "oob",
176
+ "code",
177
+ "delimiter",
178
+ "constant",
179
+ "firebase-auth",
180
+ "data",
181
+ "pair",
182
+ "firebase_auth_oob_code_data_pair_delimiter"
183
+ ],
184
+ "relatedSlugs": [
185
+ "encode-firebase-auth-oob-code",
186
+ "decode-firebase-auth-oob-code"
187
+ ]
188
+ },
189
+ {
190
+ "slug": "encode-firebase-auth-oob-code",
191
+ "name": "encodeFirebaseAuthOobCode",
192
+ "kind": "function",
193
+ "category": "firebase-auth",
194
+ "module": "@dereekb/firebase",
195
+ "subpath": "common/auth/auth",
196
+ "signature": "encodeFirebaseAuthOobCode(pair: FirebaseAuthOobCodeDataPair): FirebaseAuthOobCode",
197
+ "description": "Encodes a {@link FirebaseAuthOobCodeDataPair} into a URL-safe {@link FirebaseAuthOobCode}.\n\nThe encoded form is `${code}-${uid}` — code first so that splitting on the first delimiter\nstill works even when the uid itself contains `-` (Firebase uids occasionally do).",
198
+ "params": [
199
+ {
200
+ "name": "pair",
201
+ "type": "FirebaseAuthOobCodeDataPair",
202
+ "description": "",
203
+ "optional": false
204
+ }
205
+ ],
206
+ "returns": "FirebaseAuthOobCode",
207
+ "tags": [
208
+ "firebase",
209
+ "auth",
210
+ "oob",
211
+ "code",
212
+ "encode",
213
+ "uid",
214
+ "password",
215
+ "reset",
216
+ "setup",
217
+ "serialize",
218
+ "firebase-auth",
219
+ "encodefirebaseauthoobcode"
220
+ ],
221
+ "example": "encodeFirebaseAuthOobCode({ uid: 'abc-123', code: 'xyz789' }); // 'xyz789-abc-123'",
222
+ "relatedSlugs": [
223
+ "decode-firebase-auth-oob-code",
224
+ "firebase-auth-oob-code-data-pair-delimiter"
225
+ ]
226
+ },
227
+ {
228
+ "slug": "decode-firebase-auth-oob-code",
229
+ "name": "decodeFirebaseAuthOobCode",
230
+ "kind": "function",
231
+ "category": "firebase-auth",
232
+ "module": "@dereekb/firebase",
233
+ "subpath": "common/auth/auth",
234
+ "signature": "decodeFirebaseAuthOobCode(oobCode: FirebaseAuthOobCode): Maybe<FirebaseAuthOobCodeDataPair>",
235
+ "description": "Decodes a {@link FirebaseAuthOobCode} back into its {@link FirebaseAuthOobCodeDataPair}.\n\nSplits on the first `-` so uids containing additional `-` characters survive the round-trip\nintact. Returns null when the input is missing the delimiter or has empty parts.",
236
+ "params": [
237
+ {
238
+ "name": "oobCode",
239
+ "type": "FirebaseAuthOobCode",
240
+ "description": "",
241
+ "optional": false
242
+ }
243
+ ],
244
+ "returns": "Maybe<FirebaseAuthOobCodeDataPair>",
245
+ "tags": [
246
+ "firebase",
247
+ "auth",
248
+ "oob",
249
+ "code",
250
+ "decode",
251
+ "parse",
252
+ "uid",
253
+ "password",
254
+ "reset",
255
+ "setup",
256
+ "deserialize",
257
+ "firebase-auth",
258
+ "decodefirebaseauthoobcode"
259
+ ],
260
+ "example": "decodeFirebaseAuthOobCode('xyz789-abc-123'); // { uid: 'abc-123', code: 'xyz789' }\ndecodeFirebaseAuthOobCode('invalid'); // null",
261
+ "relatedSlugs": [
262
+ "encode-firebase-auth-oob-code",
263
+ "firebase-auth-oob-code-data-pair-delimiter"
264
+ ]
265
+ },
8
266
  {
9
267
  "slug": "new-documents",
10
268
  "name": "newDocuments",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-components-mcp",
3
- "version": "13.12.4",
3
+ "version": "13.12.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "dbx-components-mcp": "dbx-components-mcp.js"
@@ -11,23 +11,7 @@
11
11
  "ts-morph": "^21.0.0"
12
12
  },
13
13
  "peerDependencies": {
14
- "@angular/common": "21.2.11",
15
- "@angular/core": "21.2.11",
16
- "@angular/forms": "21.2.11",
17
- "@angular/material": "^21.2.9",
18
- "@dereekb/dbx-cli": "13.12.4",
19
- "@dereekb/dbx-core": "13.12.4",
20
- "@dereekb/dbx-firebase": "13.12.4",
21
- "@dereekb/dbx-form": "13.12.4",
22
- "@dereekb/dbx-web": "13.12.4",
23
- "@dereekb/firebase": "13.12.4",
24
- "@dereekb/firebase-server": "13.12.4",
25
- "@dereekb/rxjs": "13.12.4",
26
- "@dereekb/util": "13.12.4",
27
- "@uirouter/angular": "21.0.0",
28
- "rxjs": "^7.8.2"
29
- },
30
- "devDependencies": {
31
- "@dereekb/model": "13.12.4"
14
+ "@dereekb/dbx-cli": "13.12.6",
15
+ "@dereekb/util": "13.12.6"
32
16
  }
33
17
  }