@dereekb/dbx-components-mcp 14.5.1 → 14.7.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.
@@ -10,7 +10,7 @@ var __export = (target, all) => {
10
10
  // packages/dbx-components-mcp/package.json
11
11
  var package_default = {
12
12
  name: "@dereekb/dbx-components-mcp",
13
- version: "14.5.1",
13
+ version: "14.7.0",
14
14
  sideEffects: false,
15
15
  type: "module",
16
16
  bin: {
@@ -22,8 +22,8 @@ var package_default = {
22
22
  "ts-morph": "^21.0.0"
23
23
  },
24
24
  peerDependencies: {
25
- "@dereekb/dbx-cli": "14.5.1",
26
- "@dereekb/util": "14.5.1"
25
+ "@dereekb/dbx-cli": "14.7.0",
26
+ "@dereekb/util": "14.7.0"
27
27
  }
28
28
  };
29
29
 
@@ -2337,6 +2337,10 @@ var FIREBASE_MODELS = [
2337
2337
  description: "Root notification container for a model. The document ID is the two-way flat key of the model it represents (see {@link notificationBoxIdForModel} in `notification.id.ts`).",
2338
2338
  modelGroup: "Notification",
2339
2339
  collectionKind: "root",
2340
+ compositeKey: {
2341
+ from: "*",
2342
+ encoding: "two-way"
2343
+ },
2340
2344
  archetypes: ["composite-key-root"]
2341
2345
  },
2342
2346
  {
@@ -2417,6 +2421,10 @@ var FIREBASE_MODELS = [
2417
2421
  description: "Aggregated notification feed for a specific model. Holds embedded {@link NotificationItem} entries that summarize recent notifications, similar to an activity feed.",
2418
2422
  modelGroup: "Notification",
2419
2423
  collectionKind: "root",
2424
+ compositeKey: {
2425
+ from: "*",
2426
+ encoding: "two-way"
2427
+ },
2420
2428
  archetypes: ["root-singleton-aggregate", "composite-key-root"]
2421
2429
  },
2422
2430
  {
@@ -15996,7 +16004,15 @@ async function loadUtilManifests(input) {
15996
16004
  }
15997
16005
 
15998
16006
  // packages/dbx-cli/src/lib/mcp-scan/manifest/load-utils-registry.ts
15999
- var DEFAULT_BUNDLED_FILENAMES12 = ["dereekb-util.utils.mcp.generated.json", "dereekb-date.utils.mcp.generated.json", "dereekb-rxjs.utils.mcp.generated.json", "dereekb-model.utils.mcp.generated.json"];
16007
+ var DEFAULT_BUNDLED_FILENAMES12 = [
16008
+ "dereekb-util.utils.mcp.generated.json",
16009
+ "dereekb-util-fetch.utils.mcp.generated.json",
16010
+ "dereekb-date.utils.mcp.generated.json",
16011
+ "dereekb-rxjs.utils.mcp.generated.json",
16012
+ "dereekb-model.utils.mcp.generated.json",
16013
+ "dereekb-firebase.utils.mcp.generated.json",
16014
+ "dereekb-firebase-server.utils.mcp.generated.json"
16015
+ ];
16000
16016
  var DEFAULT_BUNDLED_PATHS12 = () => {
16001
16017
  const packageRoot = findPackageRoot(import.meta.url);
16002
16018
  return DEFAULT_BUNDLED_FILENAMES12.map((name) => resolve33(packageRoot, "generated", name));
@@ -29467,6 +29483,7 @@ var SERVICE_FACTORY_TAG = "dbxModelServiceFactory";
29467
29483
  var MCP_TOOL_NAME_SEGMENT_TAG = "dbxModelMcpToolNameSegment";
29468
29484
  var MODEL_TYPE_VALUE_PATTERN2 = /^[a-z][A-Za-z0-9_$]*$/;
29469
29485
  var TOOL_NAME_SEGMENT_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
29486
+ var COMPOSITE_KEY_MODEL_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9_$]*$/;
29470
29487
  var IDENTITY_FN = "firestoreModelIdentity";
29471
29488
  var IDENTITY_TYPE = "FirestoreModelIdentity";
29472
29489
  var ROOT_IDENTITY_TYPE = "RootFirestoreModelIdentity";
@@ -29583,6 +29600,7 @@ function buildInterface2(decl) {
29583
29600
  const dbxModelRead = readDbxModelReadTag(jsDocs);
29584
29601
  const dbxModelServerOnly = jsDocsHaveTag(jsDocs, "dbxModelServerOnly");
29585
29602
  const mcpToolNameSegment = readMcpToolNameSegmentTag(jsDocs);
29603
+ const compositeKey2 = readDbxModelCompositeKeyTag2(jsDocs);
29586
29604
  const extendsNames = decl.getExtends().map(resolveExtendsName);
29587
29605
  const props = [];
29588
29606
  for (const prop of decl.getProperties()) {
@@ -29608,7 +29626,8 @@ function buildInterface2(decl) {
29608
29626
  props,
29609
29627
  ...dbxModelRead === void 0 ? {} : { dbxModelRead },
29610
29628
  ...dbxModelServerOnly ? { dbxModelServerOnly: true } : {},
29611
- ...mcpToolNameSegment === void 0 ? {} : { mcpToolNameSegment }
29629
+ ...mcpToolNameSegment === void 0 ? {} : { mcpToolNameSegment },
29630
+ ...compositeKey2 === void 0 ? {} : { compositeKey: compositeKey2 }
29612
29631
  };
29613
29632
  }
29614
29633
  function readMcpToolNameSegmentTag(jsDocs) {
@@ -29643,6 +29662,43 @@ function readDbxModelReadTag(jsDocs) {
29643
29662
  }
29644
29663
  return result;
29645
29664
  }
29665
+ function readDbxModelCompositeKeyTag2(jsDocs) {
29666
+ let result;
29667
+ for (const doc of jsDocs) {
29668
+ for (const tag of doc.getTags()) {
29669
+ if (tag.getTagName() !== "dbxModelCompositeKey") continue;
29670
+ if (result !== void 0) continue;
29671
+ result = parseCompositeKeyTagValue2(tag.getCommentText() ?? "");
29672
+ }
29673
+ }
29674
+ return result;
29675
+ }
29676
+ function parseCompositeKeyTagValue2(raw) {
29677
+ let from;
29678
+ let encoding;
29679
+ for (const token of raw.trim().split(/\s+/)) {
29680
+ const eq = token.indexOf("=");
29681
+ if (eq <= 0) continue;
29682
+ const key = token.slice(0, eq);
29683
+ const value = token.slice(eq + 1);
29684
+ if (key === "from") {
29685
+ from = parseCompositeKeyFromValue3(value);
29686
+ } else if (key === "encoding" && (value === "one-way" || value === "two-way")) {
29687
+ encoding = value;
29688
+ }
29689
+ }
29690
+ return from !== void 0 && encoding !== void 0 ? { from, encoding } : void 0;
29691
+ }
29692
+ function parseCompositeKeyFromValue3(value) {
29693
+ let result;
29694
+ if (value === "*") {
29695
+ result = "*";
29696
+ } else {
29697
+ const names = value.split(",").map((x) => x.trim()).filter((x) => COMPOSITE_KEY_MODEL_NAME_PATTERN.test(x));
29698
+ result = names.length > 0 ? names : void 0;
29699
+ }
29700
+ return result;
29701
+ }
29646
29702
  function readServiceFactories(sourceFile) {
29647
29703
  const out = [];
29648
29704
  for (const statement of sourceFile.getVariableStatements()) {
@@ -40781,7 +40837,7 @@ var DBX_MODEL_DECODE_TOOL = {
40781
40837
  "",
40782
40838
  'Document mode \u2014 pass `data` as a JSON string (copied straight from the Firestore console) or an already-parsed object to identify the model, expand abbreviated field names, decode enum integer values, and surface foreign-key relationships. Optionally pass `model` to skip detection and target a specific model by interface name (`"StorageFile"`), identity constant (`"storageFileIdentity"`), `modelType` (`"storageFile"`), or collection prefix (`"sf"`).',
40783
40839
  "",
40784
- 'Key mode \u2014 pass just `key` (e.g. `"jwr/hkzQa9W6MpaP99RTlQJcImbWdZm2"`) to resolve the model identity and id from the collection prefix alone, no document required. Subcollection paths like `"nb/abc/nbn/def"` are walked end-to-end so the leaf model is reported alongside its parent chain.',
40840
+ 'Key mode \u2014 pass just `key` (e.g. `"jwr/hkzQa9W6MpaP99RTlQJcImbWdZm2"`) to resolve the model identity and id from the collection prefix alone, no document required. Subcollection paths like `"nb/abc/nbn/def"` are walked end-to-end so the leaf model is reported alongside its parent chain. Composite-key models derived from the key (`@dbxModelCompositeKey from=\u2026`) are listed with their ready-to-use flattened keys, and a two-way composite-key leaf reports the source key recovered from its id.',
40785
40841
  "",
40786
40842
  "At least one of `data` or `key` is required."
40787
40843
  ].join("\n"),
@@ -40905,6 +40961,29 @@ function buildPrefixMap() {
40905
40961
  }
40906
40962
  return out;
40907
40963
  }
40964
+ function findDerivedCompositeKeys(rawKey, leafModel) {
40965
+ const out = [];
40966
+ for (const model of FIREBASE_MODELS) {
40967
+ const compositeKey2 = model.compositeKey;
40968
+ if (!compositeKey2 || model.modelType === leafModel.modelType) continue;
40969
+ const matches = compositeKey2.from === "*" || compositeKey2.from.some((name) => name === leafModel.name || name === leafModel.identityConst || name === leafModel.modelType);
40970
+ if (!matches) continue;
40971
+ const flatId = compositeKey2.encoding === "two-way" ? rawKey.replaceAll("/", "_") : rawKey.replaceAll("/", "");
40972
+ out.push({ key: `${model.collectionPrefix}/${flatId}`, model, encoding: compositeKey2.encoding });
40973
+ }
40974
+ return out;
40975
+ }
40976
+ function decodeCompositeSource(leaf) {
40977
+ let result;
40978
+ if (leaf.model?.compositeKey?.encoding === "two-way" && leaf.id.includes("_")) {
40979
+ const sourceKey = leaf.id.replaceAll("_", "/");
40980
+ const decoded = decodeKeyPath(sourceKey, void 0);
40981
+ if (!("error" in decoded)) {
40982
+ result = { key: sourceKey, path: decoded };
40983
+ }
40984
+ }
40985
+ return result;
40986
+ }
40908
40987
  function decodeKeyPath(key, hint) {
40909
40988
  const trimmed = key.trim();
40910
40989
  if (trimmed.length === 0) {
@@ -40971,8 +41050,24 @@ function formatUnresolved(unresolvedPrefixes) {
40971
41050
  const list = unresolvedPrefixes.map((p) => `\`${p}\``).join(", ");
40972
41051
  return ["", `_Unresolved ${label}: ${list}. Run \`dbx_model_lookup\` to browse known models._`];
40973
41052
  }
41053
+ function formatCompositeSource(source) {
41054
+ if (!source) return [];
41055
+ const sourceModel = source.path.leaf.model ? source.path.leaf.model.name : `_unknown_ (prefix \`${source.path.leaf.prefix}\`)`;
41056
+ return ["", `**Composite source (two-way):** \`${source.key}\` \u2192 ${sourceModel}`];
41057
+ }
41058
+ function formatDerivedKeys(derived) {
41059
+ if (derived.length === 0) return [];
41060
+ const out = ["", "**Derived keys:**"];
41061
+ for (const entry of derived) {
41062
+ out.push(`- ${entry.model.name} (${entry.encoding}) \u2014 \`${entry.key}\``);
41063
+ }
41064
+ return out;
41065
+ }
40974
41066
  function formatKeyDecode(input, rawKey) {
40975
- const lines = ["_Model decoded from key prefix._", "", ...formatLeaf(input.leaf), ...formatAncestors(input.ancestors), ...formatUnresolved(input.unresolvedPrefixes), "", `_Key:_ \`${rawKey}\``];
41067
+ const trimmedKey = rawKey.trim();
41068
+ const derived = input.leaf.model ? findDerivedCompositeKeys(trimmedKey, input.leaf.model) : [];
41069
+ const compositeSource = decodeCompositeSource(input.leaf);
41070
+ const lines = ["_Model decoded from key prefix._", "", ...formatLeaf(input.leaf), ...formatAncestors(input.ancestors), ...formatUnresolved(input.unresolvedPrefixes), ...formatCompositeSource(compositeSource), ...formatDerivedKeys(derived), "", `_Key:_ \`${rawKey}\``];
40976
41071
  return lines.join("\n");
40977
41072
  }
40978
41073
  function runModelDecode(rawArgs) {
@@ -0,0 +1,221 @@
1
+ {
2
+ "version": 1,
3
+ "source": "@dereekb/util/fetch",
4
+ "module": "@dereekb/util/fetch",
5
+ "generatedAt": "1970-01-01T00:00:00.000Z",
6
+ "generator": "@dereekb/dbx-components-mcp/scripts/generate-manifests.mjs",
7
+ "entries": [
8
+ {
9
+ "slug": "to-bracket-notation-search-param-tuples",
10
+ "name": "toBracketNotationSearchParamTuples",
11
+ "kind": "function",
12
+ "category": "url",
13
+ "module": "@dereekb/util/fetch",
14
+ "subpath": "fetch.url",
15
+ "signature": "toBracketNotationSearchParamTuples(input: Maybe<object>): UrlSearchParamsKeyValueTuple[]",
16
+ "description": "Expands a potentially nested object into bracket-notation query key/value tuples.\n\nArrays are addressed by index and object properties by key, recursively, so every leaf\ngets its own fully-qualified parameter. Nullish leaves are omitted rather than emitted\nas the strings `\"null\"`/`\"undefined\"`; all other leaves are stringified.",
17
+ "params": [
18
+ {
19
+ "name": "input",
20
+ "type": "Maybe<object>",
21
+ "description": "- The object to expand.",
22
+ "optional": false
23
+ }
24
+ ],
25
+ "returns": "The bracket-notation key/value tuples.",
26
+ "tags": [
27
+ "url",
28
+ "query",
29
+ "search",
30
+ "params",
31
+ "bracket",
32
+ "notation",
33
+ "nested",
34
+ "expand",
35
+ "tuples",
36
+ "encode",
37
+ "to",
38
+ "param",
39
+ "tobracketnotationsearchparamtuples"
40
+ ],
41
+ "example": "toBracketNotationSearchParamTuples({ calendarsToLoad: [{ credentialId: 1, externalId: 'a@b.com' }] });\n// => [['calendarsToLoad[0][credentialId]', '1'], ['calendarsToLoad[0][externalId]', 'a@b.com']]",
42
+ "relatedSlugs": [
43
+ "make-url-search-params",
44
+ "make-url-search-params-string"
45
+ ]
46
+ },
47
+ {
48
+ "slug": "make-url-search-params",
49
+ "name": "makeUrlSearchParams",
50
+ "kind": "function",
51
+ "category": "url",
52
+ "module": "@dereekb/util/fetch",
53
+ "subpath": "fetch.url",
54
+ "signature": "makeUrlSearchParams(input: Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>, options?: Maybe<MakeUrlSearchParamsOptions>): URLSearchParams",
55
+ "description": "Creates URLSearchParams from the input objects. The input objects are merged together.",
56
+ "params": [
57
+ {
58
+ "name": "input",
59
+ "type": "Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>",
60
+ "description": "- One or more objects (or nullish values) whose key-value pairs become search parameters.",
61
+ "optional": false
62
+ },
63
+ {
64
+ "name": "options",
65
+ "type": "Maybe<MakeUrlSearchParamsOptions>",
66
+ "description": "- Optional configuration for filtering, omitting keys, and space encoding.",
67
+ "optional": true
68
+ }
69
+ ],
70
+ "returns": "A URLSearchParams instance built from the merged and filtered input.",
71
+ "tags": [
72
+ "url",
73
+ "query",
74
+ "search",
75
+ "params",
76
+ "urlsearchparams",
77
+ "encode",
78
+ "merge",
79
+ "filter",
80
+ "omit",
81
+ "querystring",
82
+ "make",
83
+ "makeurlsearchparams"
84
+ ],
85
+ "relatedSlugs": [
86
+ "make-url-search-params-string",
87
+ "update-url-search-params",
88
+ "to-bracket-notation-search-param-tuples",
89
+ "merge-make-url-search-params-options"
90
+ ]
91
+ },
92
+ {
93
+ "slug": "make-url-search-params-string",
94
+ "name": "makeUrlSearchParamsString",
95
+ "kind": "function",
96
+ "category": "url",
97
+ "module": "@dereekb/util/fetch",
98
+ "subpath": "fetch.url",
99
+ "signature": "makeUrlSearchParamsString(input: Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>, options?: Maybe<MakeUrlSearchParamsOptions>): string",
100
+ "description": "Creates a URL query string from the input objects.\n\nEquivalent to `makeUrlSearchParams(...).toString()`, but respects the\n{@link MakeUrlSearchParamsOptions.useUrlSearchSpaceHandling} option to produce\nRFC 3986 percent-encoded output (`%20` for spaces) instead of the\n`application/x-www-form-urlencoded` default (`+` for spaces).",
101
+ "params": [
102
+ {
103
+ "name": "input",
104
+ "type": "Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>",
105
+ "description": "- Objects to encode as query parameters.",
106
+ "optional": false
107
+ },
108
+ {
109
+ "name": "options",
110
+ "type": "Maybe<MakeUrlSearchParamsOptions>",
111
+ "description": "- Encoding options.",
112
+ "optional": true
113
+ }
114
+ ],
115
+ "returns": "The encoded query string (without a leading `?`)",
116
+ "tags": [
117
+ "url",
118
+ "query",
119
+ "search",
120
+ "params",
121
+ "string",
122
+ "querystring",
123
+ "encode",
124
+ "percent",
125
+ "space",
126
+ "stringify",
127
+ "make",
128
+ "makeurlsearchparamsstring"
129
+ ],
130
+ "relatedSlugs": [
131
+ "make-url-search-params",
132
+ "update-url-search-params"
133
+ ]
134
+ },
135
+ {
136
+ "slug": "update-url-search-params",
137
+ "name": "updateUrlSearchParams",
138
+ "kind": "function",
139
+ "category": "url",
140
+ "module": "@dereekb/util/fetch",
141
+ "subpath": "fetch.url",
142
+ "signature": "updateUrlSearchParams(url: string, params: Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>, options?: Maybe<MakeUrlSearchParamsOptions>): string",
143
+ "description": "Updates or adds query parameters on an existing URL string.\n\nParses the URL's existing query string, merges in the new parameters (new values\noverride existing keys), and returns the rebuilt URL. Respects all\n{@link MakeUrlSearchParamsOptions} such as `omitKeys`, `filterEmptyValues`, and\n`useUrlSearchSpaceHandling`.",
144
+ "params": [
145
+ {
146
+ "name": "url",
147
+ "type": "string",
148
+ "description": "- The URL string to update.",
149
+ "optional": false
150
+ },
151
+ {
152
+ "name": "params",
153
+ "type": "Maybe<ArrayOrValue<Maybe<object | Record<string, string | number>>>>",
154
+ "description": "- New search parameters to merge into the URL.",
155
+ "optional": false
156
+ },
157
+ {
158
+ "name": "options",
159
+ "type": "Maybe<MakeUrlSearchParamsOptions>",
160
+ "description": "- Optional configuration for filtering, omitting keys, and space encoding.",
161
+ "optional": true
162
+ }
163
+ ],
164
+ "returns": "The URL string with updated query parameters.",
165
+ "tags": [
166
+ "url",
167
+ "query",
168
+ "search",
169
+ "params",
170
+ "update",
171
+ "merge",
172
+ "append",
173
+ "override",
174
+ "querystring",
175
+ "encode",
176
+ "updateurlsearchparams"
177
+ ],
178
+ "example": "// Add params to a URL with no query string\nupdateUrlSearchParams('https://example.com/form', { name: 'Alice', age: 30 });\n// => 'https://example.com/form?name=Alice&age=30'\n\n// Override an existing param\nupdateUrlSearchParams('https://example.com?page=1&sort=asc', { page: 2 });\n// => 'https://example.com?page=2&sort=asc'\n\n// Use percent-encoded spaces for redirect URLs\nupdateUrlSearchParams('https://example.com', { scope: 'openid profile' }, { useUrlSearchSpaceHandling: true });\n// => 'https://example.com?scope=openid%20profile'",
179
+ "relatedSlugs": [
180
+ "make-url-search-params",
181
+ "make-url-search-params-string",
182
+ "merge-slash-paths"
183
+ ]
184
+ },
185
+ {
186
+ "slug": "merge-make-url-search-params-options",
187
+ "name": "mergeMakeUrlSearchParamsOptions",
188
+ "kind": "function",
189
+ "category": "url",
190
+ "module": "@dereekb/util/fetch",
191
+ "subpath": "fetch.url",
192
+ "signature": "mergeMakeUrlSearchParamsOptions(options: ArrayOrValue<Maybe<MakeUrlSearchParamsOptions>>): MakeUrlSearchParamsOptions",
193
+ "description": "Merges an array of MakeUrlSearchParamsOptions into a single MakeUrlSearchParamsOptions value.",
194
+ "params": [
195
+ {
196
+ "name": "options",
197
+ "type": "ArrayOrValue<Maybe<MakeUrlSearchParamsOptions>>",
198
+ "description": "- One or more options objects whose omitKeys sets are combined.",
199
+ "optional": false
200
+ }
201
+ ],
202
+ "returns": "A single MakeUrlSearchParamsOptions with the union of all omitKeys.",
203
+ "tags": [
204
+ "url",
205
+ "query",
206
+ "search",
207
+ "params",
208
+ "options",
209
+ "merge",
210
+ "omit",
211
+ "keys",
212
+ "config",
213
+ "make",
214
+ "mergemakeurlsearchparamsoptions"
215
+ ],
216
+ "relatedSlugs": [
217
+ "make-url-search-params"
218
+ ]
219
+ }
220
+ ]
221
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-components-mcp",
3
- "version": "14.5.1",
3
+ "version": "14.7.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "ts-morph": "^21.0.0"
13
13
  },
14
14
  "peerDependencies": {
15
- "@dereekb/dbx-cli": "14.5.1",
16
- "@dereekb/util": "14.5.1"
15
+ "@dereekb/dbx-cli": "14.7.0",
16
+ "@dereekb/util": "14.7.0"
17
17
  }
18
18
  }