@dereekb/dbx-cli 13.11.18 → 13.12.1

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.
Files changed (156) hide show
  1. package/firebase-api-manifest/main.js +70 -9
  2. package/firebase-api-manifest/package.json +1 -1
  3. package/firestore-indexes/src/firestore-indexes-generate.d.ts +125 -0
  4. package/firestore-indexes/src/firestore-model-identity-resolver.d.ts +93 -0
  5. package/firestore-indexes/src/firestore-query-helpers.d.ts +108 -0
  6. package/firestore-indexes/src/generate-firestore-indexes-cli.d.ts +94 -0
  7. package/firestore-indexes/src/index.d.ts +7 -0
  8. package/firestore-indexes/src/model-firebase-index-analyze.d.ts +68 -0
  9. package/firestore-indexes/src/model-firebase-index-build-manifest.d.ts +123 -0
  10. package/firestore-indexes/src/model-firebase-index-extract.d.ts +246 -0
  11. package/firestore-indexes/src/model-firebase-index-runtime.d.ts +126 -0
  12. package/firestore-indexes/src/model-firebase-index-scan-config-schema.d.ts +58 -0
  13. package/firestore-indexes/src/model-firebase-index-schema.d.ts +366 -0
  14. package/generate-firestore-indexes/main.js +1 -1
  15. package/generate-firestore-indexes/package.json +1 -1
  16. package/generate-mcp-manifest/main.js +1314 -0
  17. package/generate-mcp-manifest/package.json +6 -0
  18. package/generated/firebase-models.generated.d.ts +3 -0
  19. package/index.cjs.js +45614 -640
  20. package/index.esm.js +45321 -643
  21. package/lint-cache/main.js +32 -28
  22. package/lint-cache/package.json +2 -2
  23. package/manifest-extract/index.cjs.js +169 -4
  24. package/manifest-extract/index.esm.js +169 -4
  25. package/manifest-extract/package.json +1 -1
  26. package/manifest-extract/src/lib/types.d.ts +26 -1
  27. package/package.json +14 -10
  28. package/src/lib/index.d.ts +3 -0
  29. package/src/lib/manifest/types.d.ts +155 -0
  30. package/src/lib/mcp-scan/config/config-schema.d.ts +226 -0
  31. package/src/lib/mcp-scan/config/load-config.d.ts +63 -0
  32. package/src/lib/mcp-scan/index.d.ts +16 -0
  33. package/src/lib/mcp-scan/manifest/actions-loader.d.ts +49 -0
  34. package/src/lib/mcp-scan/manifest/actions-schema.d.ts +328 -0
  35. package/src/lib/mcp-scan/manifest/core-topics.d.ts +38 -0
  36. package/src/lib/mcp-scan/manifest/css-utilities-loader.d.ts +55 -0
  37. package/src/lib/mcp-scan/manifest/css-utilities-schema.d.ts +168 -0
  38. package/src/lib/mcp-scan/manifest/dbx-docs-ui-examples-loader.d.ts +33 -0
  39. package/src/lib/mcp-scan/manifest/dbx-docs-ui-examples-schema.d.ts +133 -0
  40. package/src/lib/mcp-scan/manifest/filters-loader.d.ts +61 -0
  41. package/src/lib/mcp-scan/manifest/filters-schema.d.ts +190 -0
  42. package/src/lib/mcp-scan/manifest/forge-fields-loader.d.ts +53 -0
  43. package/src/lib/mcp-scan/manifest/forge-fields-schema.d.ts +170 -0
  44. package/src/lib/mcp-scan/manifest/index.d.ts +43 -0
  45. package/src/lib/mcp-scan/manifest/load-actions-registry.d.ts +38 -0
  46. package/src/lib/mcp-scan/manifest/load-auth-registry.d.ts +82 -0
  47. package/src/lib/mcp-scan/manifest/load-css-utilities-registry.d.ts +67 -0
  48. package/src/lib/mcp-scan/manifest/load-dbx-docs-ui-examples-registry.d.ts +45 -0
  49. package/src/lib/mcp-scan/manifest/load-filters-registry.d.ts +69 -0
  50. package/src/lib/mcp-scan/manifest/load-forge-fields-registry.d.ts +70 -0
  51. package/src/lib/mcp-scan/manifest/load-model-firebase-index-registry.d.ts +61 -0
  52. package/src/lib/mcp-scan/manifest/load-model-snapshot-fields-registry.d.ts +74 -0
  53. package/src/lib/mcp-scan/manifest/load-pipes-registry.d.ts +69 -0
  54. package/src/lib/mcp-scan/manifest/load-registry.d.ts +76 -0
  55. package/src/lib/mcp-scan/manifest/load-tokens-registry.d.ts +69 -0
  56. package/src/lib/mcp-scan/manifest/load-ui-components-registry.d.ts +70 -0
  57. package/src/lib/mcp-scan/manifest/load-utils-registry.d.ts +73 -0
  58. package/src/lib/mcp-scan/manifest/loader.d.ts +120 -0
  59. package/src/lib/mcp-scan/manifest/manifest-loader-base.d.ts +130 -0
  60. package/src/lib/mcp-scan/manifest/model-firebase-index-loader.d.ts +53 -0
  61. package/src/lib/mcp-scan/manifest/model-snapshot-fields-loader.d.ts +54 -0
  62. package/src/lib/mcp-scan/manifest/model-snapshot-fields-schema.d.ts +127 -0
  63. package/src/lib/mcp-scan/manifest/pipes-loader.d.ts +54 -0
  64. package/src/lib/mcp-scan/manifest/pipes-schema.d.ts +125 -0
  65. package/src/lib/mcp-scan/manifest/semantic-types-schema.d.ts +108 -0
  66. package/src/lib/mcp-scan/manifest/tokens-loader.d.ts +55 -0
  67. package/src/lib/mcp-scan/manifest/tokens-schema.d.ts +116 -0
  68. package/src/lib/mcp-scan/manifest/ui-components-loader.d.ts +54 -0
  69. package/src/lib/mcp-scan/manifest/ui-components-schema.d.ts +149 -0
  70. package/src/lib/mcp-scan/manifest/utils-loader.d.ts +54 -0
  71. package/src/lib/mcp-scan/manifest/utils-schema.d.ts +120 -0
  72. package/src/lib/mcp-scan/registry/actions-runtime.d.ts +173 -0
  73. package/src/lib/mcp-scan/registry/archetypes.d.ts +235 -0
  74. package/src/lib/mcp-scan/registry/auth-builtin.d.ts +59 -0
  75. package/src/lib/mcp-scan/registry/auth-runtime.d.ts +343 -0
  76. package/src/lib/mcp-scan/registry/css-utilities-runtime.d.ts +133 -0
  77. package/src/lib/mcp-scan/registry/dbx-docs-ui-examples-runtime.d.ts +58 -0
  78. package/src/lib/mcp-scan/registry/downstream-models-runtime.d.ts +93 -0
  79. package/src/lib/mcp-scan/registry/filters-runtime.d.ts +128 -0
  80. package/src/lib/mcp-scan/registry/firebase-models.d.ts +387 -0
  81. package/src/lib/mcp-scan/registry/forge-fields.d.ts +101 -0
  82. package/src/lib/mcp-scan/registry/form-fields.d.ts +203 -0
  83. package/src/lib/mcp-scan/registry/index.d.ts +165 -0
  84. package/src/lib/mcp-scan/registry/model-snapshot-fields-runtime.d.ts +138 -0
  85. package/src/lib/mcp-scan/registry/pipes-runtime.d.ts +136 -0
  86. package/src/lib/mcp-scan/registry/reserved-model-folders.d.ts +29 -0
  87. package/src/lib/mcp-scan/registry/semantic-types.d.ts +81 -0
  88. package/src/lib/mcp-scan/registry/tokens-runtime.d.ts +96 -0
  89. package/src/lib/mcp-scan/registry/ui-components-runtime.d.ts +90 -0
  90. package/src/lib/mcp-scan/registry/utils-runtime.d.ts +136 -0
  91. package/src/lib/mcp-scan/scan/_jsdoc-tagged-export/extract-base.d.ts +245 -0
  92. package/src/lib/mcp-scan/scan/actions-build-manifest.d.ts +58 -0
  93. package/src/lib/mcp-scan/scan/actions-cli.d.ts +38 -0
  94. package/src/lib/mcp-scan/scan/actions-extract.d.ts +99 -0
  95. package/src/lib/mcp-scan/scan/actions-scan-config-schema.d.ts +42 -0
  96. package/src/lib/mcp-scan/scan/auth-extract.d.ts +127 -0
  97. package/src/lib/mcp-scan/scan/build-manifest.d.ts +76 -0
  98. package/src/lib/mcp-scan/scan/cli.d.ts +60 -0
  99. package/src/lib/mcp-scan/scan/css-utilities-build-manifest.d.ts +76 -0
  100. package/src/lib/mcp-scan/scan/css-utilities-cli.d.ts +36 -0
  101. package/src/lib/mcp-scan/scan/css-utilities-extract.d.ts +187 -0
  102. package/src/lib/mcp-scan/scan/css-utilities-scan-config-schema.d.ts +57 -0
  103. package/src/lib/mcp-scan/scan/dbx-docs-ui-examples-build-manifest.d.ts +68 -0
  104. package/src/lib/mcp-scan/scan/dbx-docs-ui-examples-cli.d.ts +20 -0
  105. package/src/lib/mcp-scan/scan/dbx-docs-ui-examples-extract.d.ts +160 -0
  106. package/src/lib/mcp-scan/scan/dbx-docs-ui-examples-scan-config-schema.d.ts +56 -0
  107. package/src/lib/mcp-scan/scan/discover-downstream-packages.d.ts +76 -0
  108. package/src/lib/mcp-scan/scan/discover-firebase-packages.d.ts +58 -0
  109. package/src/lib/mcp-scan/scan/extract-models/assemble.d.ts +105 -0
  110. package/src/lib/mcp-scan/scan/extract-models/collect-inherited.d.ts +22 -0
  111. package/src/lib/mcp-scan/scan/extract-models/find-converters.d.ts +19 -0
  112. package/src/lib/mcp-scan/scan/extract-models/find-enums.d.ts +19 -0
  113. package/src/lib/mcp-scan/scan/extract-models/find-identities.d.ts +25 -0
  114. package/src/lib/mcp-scan/scan/extract-models/find-interfaces.d.ts +31 -0
  115. package/src/lib/mcp-scan/scan/extract-models/find-model-groups.d.ts +21 -0
  116. package/src/lib/mcp-scan/scan/extract-models/find-service-factories.d.ts +19 -0
  117. package/src/lib/mcp-scan/scan/extract-models/find-sub-object-consts.d.ts +20 -0
  118. package/src/lib/mcp-scan/scan/extract-models/index.d.ts +74 -0
  119. package/src/lib/mcp-scan/scan/extract-models/infer-collection-kind.d.ts +22 -0
  120. package/src/lib/mcp-scan/scan/extract-models/service-factory-constants.d.ts +6 -0
  121. package/src/lib/mcp-scan/scan/extract-models/types.d.ts +171 -0
  122. package/src/lib/mcp-scan/scan/extract.d.ts +82 -0
  123. package/src/lib/mcp-scan/scan/filters-build-manifest.d.ts +78 -0
  124. package/src/lib/mcp-scan/scan/filters-cli.d.ts +37 -0
  125. package/src/lib/mcp-scan/scan/filters-extract.d.ts +101 -0
  126. package/src/lib/mcp-scan/scan/filters-scan-config-schema.d.ts +56 -0
  127. package/src/lib/mcp-scan/scan/forge-fields-build-manifest.d.ts +78 -0
  128. package/src/lib/mcp-scan/scan/forge-fields-cli.d.ts +37 -0
  129. package/src/lib/mcp-scan/scan/forge-fields-extract.d.ts +165 -0
  130. package/src/lib/mcp-scan/scan/forge-fields-scan-config-schema.d.ts +61 -0
  131. package/src/lib/mcp-scan/scan/index.d.ts +60 -0
  132. package/src/lib/mcp-scan/scan/model-firebase-index-cli.d.ts +22 -0
  133. package/src/lib/mcp-scan/scan/model-firebase-index-dispatcher-credit.d.ts +47 -0
  134. package/src/lib/mcp-scan/scan/model-firebase-index-reference-scan.d.ts +100 -0
  135. package/src/lib/mcp-scan/scan/model-snapshot-fields-build-manifest.d.ts +79 -0
  136. package/src/lib/mcp-scan/scan/model-snapshot-fields-cli.d.ts +37 -0
  137. package/src/lib/mcp-scan/scan/model-snapshot-fields-extract.d.ts +115 -0
  138. package/src/lib/mcp-scan/scan/model-snapshot-fields-scan-config-schema.d.ts +59 -0
  139. package/src/lib/mcp-scan/scan/pipes-build-manifest.d.ts +78 -0
  140. package/src/lib/mcp-scan/scan/pipes-cli.d.ts +37 -0
  141. package/src/lib/mcp-scan/scan/pipes-extract.d.ts +90 -0
  142. package/src/lib/mcp-scan/scan/pipes-scan-config-schema.d.ts +56 -0
  143. package/src/lib/mcp-scan/scan/scan-angular-io.d.ts +89 -0
  144. package/src/lib/mcp-scan/scan/scan-cli-base.d.ts +162 -0
  145. package/src/lib/mcp-scan/scan/scan-config-schema.d.ts +44 -0
  146. package/src/lib/mcp-scan/scan/ui-components-build-manifest.d.ts +78 -0
  147. package/src/lib/mcp-scan/scan/ui-components-cli.d.ts +37 -0
  148. package/src/lib/mcp-scan/scan/ui-components-extract.d.ts +124 -0
  149. package/src/lib/mcp-scan/scan/ui-components-scan-config-schema.d.ts +62 -0
  150. package/src/lib/mcp-scan/scan/utils-build-manifest.d.ts +78 -0
  151. package/src/lib/mcp-scan/scan/utils-cli.d.ts +37 -0
  152. package/src/lib/mcp-scan/scan/utils-extract.d.ts +103 -0
  153. package/src/lib/mcp-scan/scan/utils-scan-config-schema.d.ts +57 -0
  154. package/test/package.json +9 -9
  155. package/index.cjs.default.js +0 -1
  156. package/index.cjs.mjs +0 -2
@@ -20,15 +20,21 @@ import { join as join2 } from "node:path";
20
20
  // packages/dbx-cli/lint-cache/src/project-lookup.ts
21
21
  import { existsSync, readdirSync, readFileSync } from "node:fs";
22
22
  import { join, relative } from "node:path";
23
- var TOP_LEVEL_DIRS = ["apps", "packages", "tools"];
24
23
  var SKIP_DIR_NAMES = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", ".nx", ".angular", ".next"]);
24
+ function discoverTopLevelDirs(workspaceRoot) {
25
+ let dirs;
26
+ try {
27
+ dirs = readdirSync(workspaceRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && !SKIP_DIR_NAMES.has(e.name) && !e.name.startsWith(".")).map((e) => e.name).sort((a, b) => a.localeCompare(b));
28
+ } catch {
29
+ dirs = [];
30
+ }
31
+ return dirs;
32
+ }
25
33
  function findProject(workspaceRoot, projectName) {
26
34
  let result = null;
27
- for (const dir of TOP_LEVEL_DIRS) {
35
+ for (const dir of discoverTopLevelDirs(workspaceRoot)) {
28
36
  if (result) break;
29
- const base = join(workspaceRoot, dir);
30
- if (!existsSync(base)) continue;
31
- result = walkForProject(workspaceRoot, base, projectName);
37
+ result = walkForProject(workspaceRoot, join(workspaceRoot, dir), projectName);
32
38
  }
33
39
  if (!result) {
34
40
  const rootProject = readProjectJson(join(workspaceRoot, "project.json"));
@@ -60,10 +66,8 @@ function walkForProject(workspaceRoot, dir, projectName) {
60
66
  }
61
67
  function listProjects(workspaceRoot) {
62
68
  const out = [];
63
- for (const dir of TOP_LEVEL_DIRS) {
64
- const base = join(workspaceRoot, dir);
65
- if (!existsSync(base)) continue;
66
- collectProjects(workspaceRoot, base, out);
69
+ for (const dir of discoverTopLevelDirs(workspaceRoot)) {
70
+ collectProjects(workspaceRoot, join(workspaceRoot, dir), out);
67
71
  }
68
72
  const rootProject = readProjectJson(join(workspaceRoot, "project.json"));
69
73
  if (rootProject) out.push(toProjectInfo(workspaceRoot, workspaceRoot, rootProject));
@@ -495,30 +499,30 @@ function runQuery(cachePath, filters) {
495
499
  throw new Error(`lint cache not found: ${cachePath} \u2014 run \`build\` first`);
496
500
  }
497
501
  const cache = JSON.parse(readFileSync4(cachePath, "utf8"));
498
- const ruleSet = filters.rule && filters.rule.length > 0 ? new Set(filters.rule) : null;
499
- const fileNeedle = filters.file && filters.file.length > 0 ? filters.file : null;
500
- const fileMatcher = fileNeedle && isGlobPattern(fileNeedle) ? globToRegExp2(fileNeedle) : null;
501
- const messageNeedle = filters.message && filters.message.length > 0 ? filters.message.toLowerCase() : null;
502
- const severity = filters.severity;
503
- const matched = [];
504
- for (const m of cache.messages) {
505
- if (ruleSet && (m.ruleId == null || !ruleSet.has(m.ruleId))) continue;
506
- if (severity && m.severity !== severity) continue;
507
- if (fileNeedle) {
508
- if (fileMatcher) {
509
- if (!fileMatcher.test(m.filePath)) continue;
510
- } else if (!m.filePath.includes(fileNeedle)) {
511
- continue;
512
- }
513
- }
514
- if (messageNeedle && !m.message.toLowerCase().includes(messageNeedle)) continue;
515
- matched.push(m);
516
- }
502
+ const compiled = compileFilters(filters);
503
+ const matched = cache.messages.filter((m) => matchesFilters(m, compiled));
517
504
  const totalMatched = matched.length;
518
505
  const truncated = filters.limit != null && totalMatched > filters.limit;
519
506
  const limited = filters.limit == null ? matched : matched.slice(0, filters.limit);
520
507
  return { cache, matched: limited, totalMatched, truncated };
521
508
  }
509
+ function compileFilters(filters) {
510
+ const ruleSet = filters.rule && filters.rule.length > 0 ? new Set(filters.rule) : null;
511
+ const fileNeedle = filters.file && filters.file.length > 0 ? filters.file : null;
512
+ const fileMatcher = fileNeedle && isGlobPattern(fileNeedle) ? globToRegExp2(fileNeedle) : null;
513
+ const messageNeedle = filters.message && filters.message.length > 0 ? filters.message.toLowerCase() : null;
514
+ return { ruleSet, severity: filters.severity ?? void 0, fileNeedle, fileMatcher, messageNeedle };
515
+ }
516
+ function matchesFilters(m, c) {
517
+ if (c.ruleSet && (m.ruleId == null || !c.ruleSet.has(m.ruleId))) return false;
518
+ if (c.severity && m.severity !== c.severity) return false;
519
+ if (c.fileNeedle && !matchesFile(m.filePath, c.fileNeedle, c.fileMatcher)) return false;
520
+ if (c.messageNeedle && !m.message.toLowerCase().includes(c.messageNeedle)) return false;
521
+ return true;
522
+ }
523
+ function matchesFile(filePath, needle, matcher) {
524
+ return matcher ? matcher.test(filePath) : filePath.includes(needle);
525
+ }
522
526
  function isGlobPattern(s) {
523
527
  return s.includes("*") || s.includes("?");
524
528
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-lint-cache",
3
- "version": "13.11.18",
3
+ "version": "13.12.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "devDependencies": {
7
- "@dereekb/util": "13.11.18",
7
+ "@dereekb/util": "13.12.1",
8
8
  "eslint": "10.4.0",
9
9
  "yargs": "^18.0.0",
10
10
  "@types/yargs": "^17.0.35"
@@ -7,7 +7,8 @@ var SUPPORTED_VERBS = new Set([
7
7
  'read',
8
8
  'update',
9
9
  'delete',
10
- 'query'
10
+ 'query',
11
+ 'invoke'
11
12
  ]);
12
13
  /**
13
14
  * Walks a `<model>.api.ts` source and returns one {@link CrudEntry} per
@@ -500,6 +501,14 @@ function _object_spread(target) {
500
501
  }
501
502
  return target;
502
503
  }
504
+ var READ_LEVEL_VALUES = new Set([
505
+ 'system',
506
+ 'owner',
507
+ 'admin-only',
508
+ 'permissions'
509
+ ]);
510
+ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
511
+ var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
503
512
  /**
504
513
  * TS utility/structural wrappers that don't change the field surface for
505
514
  * inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
@@ -552,12 +561,14 @@ var OBJECT_FIELD_KEY = 'objectField';
552
561
  var converters = readConverters(sourceFile);
553
562
  var enums = readEnums(sourceFile);
554
563
  var modelGroups = readModelGroups(sourceFile);
564
+ var serviceFactories = readServiceFactories(sourceFile);
555
565
  return {
556
566
  identities: identities,
557
567
  interfaces: interfaces,
558
568
  converters: converters,
559
569
  enums: enums,
560
- modelGroups: modelGroups
570
+ modelGroups: modelGroups,
571
+ serviceFactories: serviceFactories
561
572
  };
562
573
  }
563
574
  function readIdentities(sourceFile) {
@@ -682,6 +693,7 @@ function readInterfaces(sourceFile) {
682
693
  function buildInterface(decl) {
683
694
  var jsDocs = decl.getJsDocs();
684
695
  var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
696
+ var dbxModelRead = readDbxModelReadTag(jsDocs);
685
697
  var extendsNames = decl.getExtends().map(resolveExtendsName);
686
698
  var props = [];
687
699
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -718,13 +730,166 @@ function buildInterface(decl) {
718
730
  }
719
731
  }
720
732
  }
721
- return {
733
+ return _object_spread({
722
734
  name: decl.getName(),
723
735
  description: readJsDocDescription(jsDocs),
724
736
  hasDbxModelTag: hasDbxModelTag,
725
737
  extendsNames: extendsNames,
726
738
  props: props
727
- };
739
+ }, dbxModelRead === undefined ? {} : {
740
+ dbxModelRead: dbxModelRead
741
+ });
742
+ }
743
+ function readDbxModelReadTag(jsDocs) {
744
+ var result;
745
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
746
+ try {
747
+ for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
748
+ var doc = _step.value;
749
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
750
+ try {
751
+ for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
752
+ var tag = _step1.value;
753
+ var _tag_getCommentText;
754
+ if (tag.getTagName() !== 'dbxModelRead') continue;
755
+ if (result !== undefined) continue;
756
+ var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
757
+ if (raw === undefined || raw.length === 0) continue;
758
+ var firstToken = raw.split(/\s+/)[0];
759
+ if (READ_LEVEL_VALUES.has(firstToken)) {
760
+ result = firstToken;
761
+ }
762
+ }
763
+ } catch (err) {
764
+ _didIteratorError1 = true;
765
+ _iteratorError1 = err;
766
+ } finally{
767
+ try {
768
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
769
+ _iterator1.return();
770
+ }
771
+ } finally{
772
+ if (_didIteratorError1) {
773
+ throw _iteratorError1;
774
+ }
775
+ }
776
+ }
777
+ }
778
+ } catch (err) {
779
+ _didIteratorError = true;
780
+ _iteratorError = err;
781
+ } finally{
782
+ try {
783
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
784
+ _iterator.return();
785
+ }
786
+ } finally{
787
+ if (_didIteratorError) {
788
+ throw _iteratorError;
789
+ }
790
+ }
791
+ }
792
+ return result;
793
+ }
794
+ function readServiceFactories(sourceFile) {
795
+ var out = [];
796
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
797
+ try {
798
+ for(var _iterator = sourceFile.getVariableStatements()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
799
+ var statement = _step.value;
800
+ if (!statement.isExported()) continue;
801
+ var modelType = readServiceFactoryModelType(statement.getJsDocs());
802
+ if (modelType === undefined) continue;
803
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
804
+ try {
805
+ for(var _iterator1 = statement.getDeclarations()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
806
+ var decl = _step1.value;
807
+ out.push({
808
+ modelType: modelType,
809
+ exportName: decl.getName()
810
+ });
811
+ }
812
+ } catch (err) {
813
+ _didIteratorError1 = true;
814
+ _iteratorError1 = err;
815
+ } finally{
816
+ try {
817
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
818
+ _iterator1.return();
819
+ }
820
+ } finally{
821
+ if (_didIteratorError1) {
822
+ throw _iteratorError1;
823
+ }
824
+ }
825
+ }
826
+ }
827
+ } catch (err) {
828
+ _didIteratorError = true;
829
+ _iteratorError = err;
830
+ } finally{
831
+ try {
832
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
833
+ _iterator.return();
834
+ }
835
+ } finally{
836
+ if (_didIteratorError) {
837
+ throw _iteratorError;
838
+ }
839
+ }
840
+ }
841
+ return out;
842
+ }
843
+ function readServiceFactoryModelType(jsDocs) {
844
+ var result;
845
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
846
+ try {
847
+ for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
848
+ var doc = _step.value;
849
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
850
+ try {
851
+ for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
852
+ var tag = _step1.value;
853
+ var _tag_getCommentText;
854
+ if (tag.getTagName() !== SERVICE_FACTORY_TAG) continue;
855
+ if (result !== undefined) continue;
856
+ var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
857
+ if (raw === undefined || raw.length === 0) continue;
858
+ var firstToken = raw.split(/\s+/)[0];
859
+ if (MODEL_TYPE_VALUE_PATTERN.test(firstToken)) {
860
+ result = firstToken;
861
+ }
862
+ }
863
+ } catch (err) {
864
+ _didIteratorError1 = true;
865
+ _iteratorError1 = err;
866
+ } finally{
867
+ try {
868
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
869
+ _iterator1.return();
870
+ }
871
+ } finally{
872
+ if (_didIteratorError1) {
873
+ throw _iteratorError1;
874
+ }
875
+ }
876
+ }
877
+ }
878
+ } catch (err) {
879
+ _didIteratorError = true;
880
+ _iteratorError = err;
881
+ } finally{
882
+ try {
883
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
884
+ _iterator.return();
885
+ }
886
+ } finally{
887
+ if (_didIteratorError) {
888
+ throw _iteratorError;
889
+ }
890
+ }
891
+ }
892
+ return result;
728
893
  }
729
894
  /**
730
895
  * Resolves an `extends` clause to the concrete ancestor interface name,
@@ -5,7 +5,8 @@ var SUPPORTED_VERBS = new Set([
5
5
  'read',
6
6
  'update',
7
7
  'delete',
8
- 'query'
8
+ 'query',
9
+ 'invoke'
9
10
  ]);
10
11
  /**
11
12
  * Walks a `<model>.api.ts` source and returns one {@link CrudEntry} per
@@ -498,6 +499,14 @@ function _object_spread(target) {
498
499
  }
499
500
  return target;
500
501
  }
502
+ var READ_LEVEL_VALUES = new Set([
503
+ 'system',
504
+ 'owner',
505
+ 'admin-only',
506
+ 'permissions'
507
+ ]);
508
+ var SERVICE_FACTORY_TAG = 'dbxModelServiceFactory';
509
+ var MODEL_TYPE_VALUE_PATTERN = /^[a-z][A-Za-z0-9_$]*$/;
501
510
  /**
502
511
  * TS utility/structural wrappers that don't change the field surface for
503
512
  * inheritance walks — `Partial<T>`, `Required<T>`, `Readonly<T>`,
@@ -550,12 +559,14 @@ var OBJECT_FIELD_KEY = 'objectField';
550
559
  var converters = readConverters(sourceFile);
551
560
  var enums = readEnums(sourceFile);
552
561
  var modelGroups = readModelGroups(sourceFile);
562
+ var serviceFactories = readServiceFactories(sourceFile);
553
563
  return {
554
564
  identities: identities,
555
565
  interfaces: interfaces,
556
566
  converters: converters,
557
567
  enums: enums,
558
- modelGroups: modelGroups
568
+ modelGroups: modelGroups,
569
+ serviceFactories: serviceFactories
559
570
  };
560
571
  }
561
572
  function readIdentities(sourceFile) {
@@ -680,6 +691,7 @@ function readInterfaces(sourceFile) {
680
691
  function buildInterface(decl) {
681
692
  var jsDocs = decl.getJsDocs();
682
693
  var hasDbxModelTag = jsDocsHaveTag(jsDocs, 'dbxModel');
694
+ var dbxModelRead = readDbxModelReadTag(jsDocs);
683
695
  var extendsNames = decl.getExtends().map(resolveExtendsName);
684
696
  var props = [];
685
697
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -716,13 +728,166 @@ function buildInterface(decl) {
716
728
  }
717
729
  }
718
730
  }
719
- return {
731
+ return _object_spread({
720
732
  name: decl.getName(),
721
733
  description: readJsDocDescription(jsDocs),
722
734
  hasDbxModelTag: hasDbxModelTag,
723
735
  extendsNames: extendsNames,
724
736
  props: props
725
- };
737
+ }, dbxModelRead === undefined ? {} : {
738
+ dbxModelRead: dbxModelRead
739
+ });
740
+ }
741
+ function readDbxModelReadTag(jsDocs) {
742
+ var result;
743
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
744
+ try {
745
+ for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
746
+ var doc = _step.value;
747
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
748
+ try {
749
+ for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
750
+ var tag = _step1.value;
751
+ var _tag_getCommentText;
752
+ if (tag.getTagName() !== 'dbxModelRead') continue;
753
+ if (result !== undefined) continue;
754
+ var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
755
+ if (raw === undefined || raw.length === 0) continue;
756
+ var firstToken = raw.split(/\s+/)[0];
757
+ if (READ_LEVEL_VALUES.has(firstToken)) {
758
+ result = firstToken;
759
+ }
760
+ }
761
+ } catch (err) {
762
+ _didIteratorError1 = true;
763
+ _iteratorError1 = err;
764
+ } finally{
765
+ try {
766
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
767
+ _iterator1.return();
768
+ }
769
+ } finally{
770
+ if (_didIteratorError1) {
771
+ throw _iteratorError1;
772
+ }
773
+ }
774
+ }
775
+ }
776
+ } catch (err) {
777
+ _didIteratorError = true;
778
+ _iteratorError = err;
779
+ } finally{
780
+ try {
781
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
782
+ _iterator.return();
783
+ }
784
+ } finally{
785
+ if (_didIteratorError) {
786
+ throw _iteratorError;
787
+ }
788
+ }
789
+ }
790
+ return result;
791
+ }
792
+ function readServiceFactories(sourceFile) {
793
+ var out = [];
794
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
795
+ try {
796
+ for(var _iterator = sourceFile.getVariableStatements()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
797
+ var statement = _step.value;
798
+ if (!statement.isExported()) continue;
799
+ var modelType = readServiceFactoryModelType(statement.getJsDocs());
800
+ if (modelType === undefined) continue;
801
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
802
+ try {
803
+ for(var _iterator1 = statement.getDeclarations()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
804
+ var decl = _step1.value;
805
+ out.push({
806
+ modelType: modelType,
807
+ exportName: decl.getName()
808
+ });
809
+ }
810
+ } catch (err) {
811
+ _didIteratorError1 = true;
812
+ _iteratorError1 = err;
813
+ } finally{
814
+ try {
815
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
816
+ _iterator1.return();
817
+ }
818
+ } finally{
819
+ if (_didIteratorError1) {
820
+ throw _iteratorError1;
821
+ }
822
+ }
823
+ }
824
+ }
825
+ } catch (err) {
826
+ _didIteratorError = true;
827
+ _iteratorError = err;
828
+ } finally{
829
+ try {
830
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
831
+ _iterator.return();
832
+ }
833
+ } finally{
834
+ if (_didIteratorError) {
835
+ throw _iteratorError;
836
+ }
837
+ }
838
+ }
839
+ return out;
840
+ }
841
+ function readServiceFactoryModelType(jsDocs) {
842
+ var result;
843
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
844
+ try {
845
+ for(var _iterator = jsDocs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
846
+ var doc = _step.value;
847
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
848
+ try {
849
+ for(var _iterator1 = doc.getTags()[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
850
+ var tag = _step1.value;
851
+ var _tag_getCommentText;
852
+ if (tag.getTagName() !== SERVICE_FACTORY_TAG) continue;
853
+ if (result !== undefined) continue;
854
+ var raw = (_tag_getCommentText = tag.getCommentText()) === null || _tag_getCommentText === void 0 ? void 0 : _tag_getCommentText.trim();
855
+ if (raw === undefined || raw.length === 0) continue;
856
+ var firstToken = raw.split(/\s+/)[0];
857
+ if (MODEL_TYPE_VALUE_PATTERN.test(firstToken)) {
858
+ result = firstToken;
859
+ }
860
+ }
861
+ } catch (err) {
862
+ _didIteratorError1 = true;
863
+ _iteratorError1 = err;
864
+ } finally{
865
+ try {
866
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
867
+ _iterator1.return();
868
+ }
869
+ } finally{
870
+ if (_didIteratorError1) {
871
+ throw _iteratorError1;
872
+ }
873
+ }
874
+ }
875
+ }
876
+ } catch (err) {
877
+ _didIteratorError = true;
878
+ _iteratorError = err;
879
+ } finally{
880
+ try {
881
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
882
+ _iterator.return();
883
+ }
884
+ } finally{
885
+ if (_didIteratorError) {
886
+ throw _iteratorError;
887
+ }
888
+ }
889
+ }
890
+ return result;
726
891
  }
727
892
  /**
728
893
  * Resolves an `extends` clause to the concrete ancestor interface name,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/manifest-extract",
3
- "version": "13.11.18",
3
+ "version": "13.12.1",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "ts-morph": "^21.0.0"
@@ -9,7 +9,7 @@
9
9
  * `dbx-cli-firebase-api-manifest` build CLI. Re-exported under
10
10
  * `@dereekb/dbx-cli/manifest-extract`.
11
11
  */
12
- export type CrudVerb = 'create' | 'read' | 'update' | 'delete' | 'query' | 'standalone';
12
+ export type CrudVerb = 'create' | 'read' | 'update' | 'delete' | 'query' | 'invoke' | 'standalone';
13
13
  export interface CrudEntryDocField {
14
14
  readonly name: string;
15
15
  readonly typeText: string;
@@ -125,6 +125,11 @@ export interface ModelExtractionInterface {
125
125
  readonly hasDbxModelTag: boolean;
126
126
  readonly extendsNames: readonly string[];
127
127
  readonly props: readonly ModelExtractionInterfaceProp[];
128
+ /**
129
+ * Closed-enum read posture from `@dbxModelRead <level>` (`system` / `owner` / `admin-only`
130
+ * / `permissions`). Absent when the interface omits the tag or declares an invalid value.
131
+ */
132
+ readonly dbxModelRead?: 'system' | 'owner' | 'admin-only' | 'permissions';
128
133
  }
129
134
  /**
130
135
  * One field inside a converter's `fields` map.
@@ -231,4 +236,24 @@ export interface ModelExtraction {
231
236
  readonly converters: readonly ModelExtractionConverter[];
232
237
  readonly enums: readonly ModelExtractionEnum[];
233
238
  readonly modelGroups: readonly ModelExtractionGroup[];
239
+ /**
240
+ * `@dbxModelServiceFactory <modelType>`-tagged variable exports found in this file. The
241
+ * orchestrator joins these onto matching model entries by `modelType` so the runtime
242
+ * manifest can surface the implementing factory alongside each model.
243
+ */
244
+ readonly serviceFactories: readonly ModelExtractionServiceFactory[];
245
+ }
246
+ /**
247
+ * One `@dbxModelServiceFactory <modelType>`-tagged variable export.
248
+ */
249
+ export interface ModelExtractionServiceFactory {
250
+ /**
251
+ * Canonical model-type string from the tag value (camelCase, e.g. `guestbook`).
252
+ * Invalid values are silently dropped at scan time.
253
+ */
254
+ readonly modelType: string;
255
+ /**
256
+ * Name of the exported binding (e.g. `guestbookFirebaseModelServiceFactory`).
257
+ */
258
+ readonly exportName: string;
234
259
  }
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli",
3
- "version": "13.11.18",
3
+ "version": "13.12.1",
4
+ "type": "module",
4
5
  "sideEffects": false,
5
6
  "bin": {
6
7
  "dbx-cli-generate-firebase-api-manifest": "firebase-api-manifest/main.js",
7
8
  "dbx-cli-generate-firestore-indexes": "generate-firestore-indexes/main.js",
9
+ "dbx-cli-generate-mcp-manifest": "generate-mcp-manifest/main.js",
8
10
  "dbx-cli-lint-cache": "lint-cache/main.js"
9
11
  },
10
12
  "exports": {
@@ -14,6 +16,9 @@
14
16
  "./generate-firestore-indexes": {
15
17
  "default": "./generate-firestore-indexes/main.js"
16
18
  },
19
+ "./generate-mcp-manifest": {
20
+ "default": "./generate-mcp-manifest/main.js"
21
+ },
17
22
  "./lint-cache": {
18
23
  "default": "./lint-cache/main.js"
19
24
  },
@@ -31,18 +36,17 @@
31
36
  },
32
37
  "./package.json": "./package.json",
33
38
  ".": {
34
- "module": "./index.esm.js",
35
- "types": "./index.d.ts",
36
- "import": "./index.cjs.mjs",
37
- "default": "./index.cjs.js"
39
+ "import": "./index.esm.js",
40
+ "types": "./index.d.ts"
38
41
  }
39
42
  },
40
43
  "peerDependencies": {
41
- "@dereekb/date": "13.11.18",
42
- "@dereekb/firebase": "13.11.18",
43
- "@dereekb/nestjs": "13.11.18",
44
- "@dereekb/util": "13.11.18",
44
+ "@dereekb/date": "13.12.1",
45
+ "@dereekb/firebase": "13.12.1",
46
+ "@dereekb/nestjs": "13.12.1",
47
+ "@dereekb/util": "13.12.1",
45
48
  "arktype": "^2.2.0",
49
+ "ts-morph": "^21.0.0",
46
50
  "yargs": "^18.0.0"
47
51
  },
48
52
  "devDependencies": {
@@ -50,6 +54,6 @@
50
54
  "eslint": "10.4.0"
51
55
  },
52
56
  "module": "./index.esm.js",
53
- "main": "./index.cjs.js",
57
+ "main": "./index.esm.js",
54
58
  "types": "./index.d.ts"
55
59
  }
@@ -6,7 +6,10 @@ export * from './context';
6
6
  export * from './doctor';
7
7
  export * from './env';
8
8
  export * from './manifest';
9
+ export * from './mcp-scan';
9
10
  export * from './middleware';
11
+ export * from './scan-helpers/scan-io.js';
12
+ export * from './scan-helpers/scan-extract-utils.js';
10
13
  export * from './output';
11
14
  export * from './runner';
12
15
  export * from './util';