@dereekb/dbx-cli 14.8.0 → 14.10.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.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/eslint",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "peerDependencies": {
7
- "@dereekb/dbx-cli": "14.8.0",
8
- "@dereekb/util": "14.8.0",
7
+ "@dereekb/dbx-cli": "14.10.0",
8
+ "@dereekb/util": "14.10.0",
9
9
  "@typescript-eslint/utils": "8.69.0",
10
10
  "typescript": "6.0.3"
11
11
  },
@@ -1902,13 +1902,13 @@ function renderModelField(field, emitConverters) {
1902
1902
  // packages/dbx-cli/firebase-api-manifest/package.json
1903
1903
  var package_default = {
1904
1904
  name: "@dereekb/dbx-cli-firebase-api-manifest",
1905
- version: "14.8.0",
1905
+ version: "14.10.0",
1906
1906
  sideEffects: false,
1907
1907
  private: true,
1908
1908
  type: "module",
1909
1909
  peerDependencies: {
1910
- "@dereekb/dbx-cli": "14.8.0",
1911
- "@dereekb/util": "14.8.0",
1910
+ "@dereekb/dbx-cli": "14.10.0",
1911
+ "@dereekb/util": "14.10.0",
1912
1912
  oxfmt: "^0.66.0",
1913
1913
  "ts-morph": "^28.0.0"
1914
1914
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-firebase-api-manifest",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
7
7
  "peerDependencies": {
8
- "@dereekb/dbx-cli": "14.8.0",
9
- "@dereekb/util": "14.8.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
+ "@dereekb/util": "14.10.0",
10
10
  "oxfmt": "^0.66.0",
11
11
  "ts-morph": "^28.0.0"
12
12
  }
@@ -4,12 +4,12 @@ const require = __createRequire(import.meta.url);
4
4
 
5
5
  // packages/dbx-cli/firestore-query-manifest/src/main.ts
6
6
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
7
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "node:path";
7
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve5 } from "node:path";
8
8
 
9
9
  // packages/dbx-cli/firestore-query-manifest/package.json
10
10
  var package_default = {
11
11
  name: "@dereekb/dbx-cli-firestore-query-manifest",
12
- version: "14.8.0",
12
+ version: "14.10.0",
13
13
  sideEffects: false,
14
14
  private: true,
15
15
  type: "module",
@@ -17,8 +17,8 @@ var package_default = {
17
17
  eslint: "10.9.1"
18
18
  },
19
19
  peerDependencies: {
20
- "@dereekb/dbx-cli": "14.8.0",
21
- "@dereekb/util": "14.8.0"
20
+ "@dereekb/dbx-cli": "14.10.0",
21
+ "@dereekb/util": "14.10.0"
22
22
  }
23
23
  };
24
24
 
@@ -325,6 +325,10 @@ function parentPathsForCollection(scan, collection) {
325
325
  return Array.from(parents);
326
326
  }
327
327
 
328
+ // packages/dbx-cli/firestore-query-manifest/src/bind-factories.ts
329
+ import { createRequire } from "node:module";
330
+ import { dirname as dirname3, resolve as resolve2 } from "node:path";
331
+
328
332
  // packages/dbx-cli/src/lib/scan-helpers/exported-from-package.ts
329
333
  import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "node:fs";
330
334
  import { dirname as dirname2, isAbsolute, join as join2, resolve } from "node:path";
@@ -447,6 +451,34 @@ function bindQueryFactories(input) {
447
451
  }
448
452
  return { bound, warnings };
449
453
  }
454
+ var defaultQueryFactoryPackageRootResolver = ({ cwd, module }) => {
455
+ let result;
456
+ try {
457
+ result = dirname3(createRequire(resolve2(cwd, "noop.js")).resolve(module));
458
+ } catch {
459
+ result = null;
460
+ }
461
+ return result;
462
+ };
463
+ function bindPackageQueryFactories(input) {
464
+ const { cwd, entries, resolvePackageRoot = defaultQueryFactoryPackageRootResolver, isExported = isExportedFromPackage } = input;
465
+ const packageRoots = /* @__PURE__ */ new Map();
466
+ const bound = [];
467
+ const warnings = [];
468
+ for (const entry of entries) {
469
+ let packageRoot = packageRoots.get(entry.module);
470
+ if (packageRoot === void 0) {
471
+ packageRoot = resolvePackageRoot({ cwd, module: entry.module });
472
+ packageRoots.set(entry.module, packageRoot);
473
+ }
474
+ const found = packageRoot != null && isExported({ packageRoot, identifier: entry.name });
475
+ if (!found) {
476
+ warnings.push(packageRoot == null ? `[no-factory] ${entry.module} \xB7 ${entry.slug} \u2192 ${entry.module} is not installed` : `[no-factory] ${entry.module} \xB7 ${entry.slug} \u2192 ${entry.name} not exported`);
477
+ }
478
+ bound.push({ entry, bound: found });
479
+ }
480
+ return { bound, warnings };
481
+ }
450
482
 
451
483
  // packages/dbx-cli/firestore-query-manifest/src/emit.ts
452
484
  async function renderQueryManifest(input) {
@@ -513,9 +545,155 @@ function renderParams(params) {
513
545
  return `[${items.join(", ")}]`;
514
546
  }
515
547
 
516
- // packages/dbx-cli/firestore-indexes/src/model-firebase-index-build-manifest.ts
517
- import { relative, resolve as resolve2 } from "node:path";
518
- import { type as type3 } from "arktype";
548
+ // packages/dbx-cli/firestore-indexes/src/model-firebase-index-package-manifests.ts
549
+ import { type as type2 } from "arktype";
550
+ import { readdir as nodeReadDir } from "node:fs/promises";
551
+ import { createRequire as createRequire2 } from "node:module";
552
+ import { dirname as dirname4, resolve as resolve3 } from "node:path";
553
+
554
+ // packages/dbx-cli/src/lib/scan-helpers/scan-io.ts
555
+ import { glob as fsGlob, readFile as nodeReadFile } from "node:fs/promises";
556
+ import { resolve as resolvePath } from "node:path";
557
+ import { Project } from "ts-morph";
558
+ var defaultReadFile = (path) => nodeReadFile(path, "utf-8");
559
+ var defaultGlobber = async (input) => {
560
+ const { projectRoot, include, exclude } = input;
561
+ const excludeMatchers = exclude.map(globToRegex);
562
+ const seen = /* @__PURE__ */ new Set();
563
+ const matches = [];
564
+ for (const pattern of include) {
565
+ for await (const match of fsGlob(pattern, { cwd: projectRoot })) {
566
+ if (excludeMatchers.some((rx) => rx.test(match))) {
567
+ continue;
568
+ }
569
+ if (!seen.has(match)) {
570
+ seen.add(match);
571
+ matches.push(match);
572
+ }
573
+ }
574
+ }
575
+ return matches;
576
+ };
577
+ async function loadPackageName(packagePath, readFile) {
578
+ let raw = null;
579
+ try {
580
+ raw = await readFile(packagePath);
581
+ } catch {
582
+ raw = null;
583
+ }
584
+ let result;
585
+ if (raw === null) {
586
+ result = { kind: "fail", outcome: { kind: "no-package", packagePath } };
587
+ } else {
588
+ let parsed;
589
+ let parseError = null;
590
+ try {
591
+ parsed = JSON.parse(raw);
592
+ } catch (err) {
593
+ parseError = err instanceof Error ? err.message : String(err);
594
+ }
595
+ if (parseError === null) {
596
+ const name = parsed?.name;
597
+ if (typeof name !== "string" || name.length === 0) {
598
+ result = { kind: "fail", outcome: { kind: "invalid-package", packagePath, error: "package.json is missing a non-empty `name` field" } };
599
+ } else {
600
+ result = { kind: "ok", packageName: name };
601
+ }
602
+ } else {
603
+ result = { kind: "fail", outcome: { kind: "invalid-package", packagePath, error: parseError } };
604
+ }
605
+ }
606
+ return result;
607
+ }
608
+ async function loadScanSection(input) {
609
+ const { configPath, readFile, parseSection } = input;
610
+ const readResult = await readScanConfigRaw(configPath, readFile);
611
+ let result;
612
+ if (readResult.kind === "error") {
613
+ result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: `failed to read config: ${readResult.error}` } };
614
+ } else if (readResult.kind === "enoent") {
615
+ result = { kind: "fail", outcome: { kind: "no-config", configPath } };
616
+ } else {
617
+ result = parseScanSectionFromRaw(readResult.raw, configPath, parseSection);
618
+ }
619
+ return result;
620
+ }
621
+ async function readScanConfigRaw(configPath, readFile) {
622
+ let result;
623
+ try {
624
+ const raw = await readFile(configPath);
625
+ result = { kind: "ok", raw };
626
+ } catch (err) {
627
+ const code = err?.code;
628
+ if (code === "ENOENT") {
629
+ result = { kind: "enoent" };
630
+ } else {
631
+ result = { kind: "error", error: err instanceof Error ? err.message : String(err) };
632
+ }
633
+ }
634
+ return result;
635
+ }
636
+ function parseScanSectionFromRaw(raw, configPath, parseSection) {
637
+ const jsonResult = parseJsonString(raw);
638
+ let result;
639
+ if (jsonResult.ok) {
640
+ const sectionResult = parseSection(jsonResult.value);
641
+ if (sectionResult.ok) {
642
+ result = { kind: "ok", section: sectionResult.section };
643
+ } else {
644
+ result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: sectionResult.error } };
645
+ }
646
+ } else {
647
+ result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: jsonResult.error } };
648
+ }
649
+ return result;
650
+ }
651
+ function parseJsonString(raw) {
652
+ let result;
653
+ try {
654
+ result = { ok: true, value: JSON.parse(raw) };
655
+ } catch (err) {
656
+ result = { ok: false, error: err instanceof Error ? err.message : String(err) };
657
+ }
658
+ return result;
659
+ }
660
+ async function buildScanProject(input) {
661
+ const { projectRoot, filePaths, readFile } = input;
662
+ const project = new Project({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
663
+ for (const relPath of filePaths) {
664
+ const absolute = resolvePath(projectRoot, relPath);
665
+ const text = await readFile(absolute);
666
+ project.createSourceFile(absolute, text, { overwrite: true });
667
+ }
668
+ return project;
669
+ }
670
+ function globToRegex(pattern) {
671
+ let body = "";
672
+ let index = 0;
673
+ while (index < pattern.length) {
674
+ const char = pattern[index];
675
+ if (char === "*" && pattern[index + 1] === "*") {
676
+ body += ".*";
677
+ index += 2;
678
+ if (pattern[index] === "/") {
679
+ index += 1;
680
+ }
681
+ } else if (char === "*") {
682
+ body += "[^/]*";
683
+ index += 1;
684
+ } else if (char === "?") {
685
+ body += "[^/]";
686
+ index += 1;
687
+ } else if (".+^${}()|[]\\".includes(char)) {
688
+ body += `\\${char}`;
689
+ index += 1;
690
+ } else {
691
+ body += char;
692
+ index += 1;
693
+ }
694
+ }
695
+ return new RegExp(`^${body}$`);
696
+ }
519
697
 
520
698
  // packages/dbx-cli/firestore-indexes/src/model-firebase-index-schema.ts
521
699
  import { type } from "arktype";
@@ -596,6 +774,110 @@ var ModelFirebaseIndexManifest = type({
596
774
  entries: ModelFirebaseIndexEntry.array()
597
775
  });
598
776
 
777
+ // packages/dbx-cli/firestore-indexes/src/model-firebase-index-package-manifests.ts
778
+ var MODEL_FIREBASE_INDEX_MANIFEST_FILENAME_SUFFIX = ".model-firebase-index.mcp.generated.json";
779
+ var BUNDLED_MODEL_FIREBASE_INDEX_MANIFEST_PACKAGE = "@dereekb/dbx-components-mcp";
780
+ var BUNDLED_MANIFEST_DIRECTORY_NAME = "generated";
781
+ var defaultBundledManifestDirectoryResolver = (cwd) => {
782
+ let result;
783
+ try {
784
+ const requireFromCwd = createRequire2(resolve3(cwd, "noop.js"));
785
+ const packageJsonPath = requireFromCwd.resolve(`${BUNDLED_MODEL_FIREBASE_INDEX_MANIFEST_PACKAGE}/package.json`);
786
+ result = resolve3(dirname4(packageJsonPath), BUNDLED_MANIFEST_DIRECTORY_NAME);
787
+ } catch {
788
+ result = null;
789
+ }
790
+ return result;
791
+ };
792
+ var defaultReadDir = (path) => nodeReadDir(path);
793
+ async function loadModelFirebaseIndexPackageManifests(input) {
794
+ const { cwd, manifestPaths = [], discoverBundled = false, readFile = defaultReadFile, readDir = defaultReadDir, resolveBundledDirectory = defaultBundledManifestDirectoryResolver } = input;
795
+ const paths = manifestPaths.map((path) => resolve3(cwd, path));
796
+ let failure = null;
797
+ if (discoverBundled) {
798
+ const bundledDirectory = resolveBundledDirectory(cwd);
799
+ if (bundledDirectory == null) {
800
+ failure = { kind: "no-bundled-package", packageName: BUNDLED_MODEL_FIREBASE_INDEX_MANIFEST_PACKAGE };
801
+ } else {
802
+ paths.push(...await readBundledManifestPaths(bundledDirectory, readDir));
803
+ }
804
+ }
805
+ const loaded = [];
806
+ for (const path of paths) {
807
+ if (failure != null) {
808
+ break;
809
+ }
810
+ const readResult = await readManifestFile(path, readFile);
811
+ if (readResult.kind === "ok") {
812
+ loaded.push({ path, manifest: readResult.manifest });
813
+ } else {
814
+ failure = readResult.outcome;
815
+ }
816
+ }
817
+ return failure ?? { kind: "success", loaded };
818
+ }
819
+ function formatModelFirebaseIndexPackageManifestFailure(outcome) {
820
+ let result;
821
+ switch (outcome.kind) {
822
+ case "unreadable-manifest":
823
+ result = `could not read manifest at ${outcome.path} \u2014 ${outcome.error}`;
824
+ break;
825
+ case "invalid-manifest":
826
+ result = `manifest at ${outcome.path} failed validation \u2014 ${outcome.error}`;
827
+ break;
828
+ default:
829
+ result = `${outcome.packageName} is not installed, so no bundled index manifests could be discovered. Install it, or pass --manifest <path> explicitly.`;
830
+ break;
831
+ }
832
+ return result;
833
+ }
834
+ async function readBundledManifestPaths(directory, readDir) {
835
+ let result;
836
+ try {
837
+ const names = await readDir(directory);
838
+ result = names.filter((name) => name.endsWith(MODEL_FIREBASE_INDEX_MANIFEST_FILENAME_SUFFIX)).toSorted().map((name) => resolve3(directory, name));
839
+ } catch {
840
+ result = [];
841
+ }
842
+ return result;
843
+ }
844
+ async function readManifestFile(path, readFile) {
845
+ let raw = null;
846
+ let readError = null;
847
+ try {
848
+ raw = await readFile(path);
849
+ } catch (err) {
850
+ readError = err instanceof Error ? err.message : String(err);
851
+ }
852
+ let result;
853
+ if (raw == null) {
854
+ result = { kind: "fail", outcome: { kind: "unreadable-manifest", path, error: readError ?? "unknown error" } };
855
+ } else {
856
+ let parsed;
857
+ let parseError = null;
858
+ try {
859
+ parsed = JSON.parse(raw);
860
+ } catch (err) {
861
+ parseError = err instanceof Error ? err.message : String(err);
862
+ }
863
+ if (parseError == null) {
864
+ const validated = ModelFirebaseIndexManifest(parsed);
865
+ if (validated instanceof type2.errors) {
866
+ result = { kind: "fail", outcome: { kind: "invalid-manifest", path, error: validated.summary } };
867
+ } else {
868
+ result = { kind: "ok", manifest: validated };
869
+ }
870
+ } else {
871
+ result = { kind: "fail", outcome: { kind: "invalid-manifest", path, error: parseError } };
872
+ }
873
+ }
874
+ return result;
875
+ }
876
+
877
+ // packages/dbx-cli/firestore-indexes/src/model-firebase-index-build-manifest.ts
878
+ import { relative, resolve as resolve4 } from "node:path";
879
+ import { type as type4 } from "arktype";
880
+
599
881
  // packages/dbx-cli/firestore-indexes/src/model-firebase-index-analyze.ts
600
882
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["==", "in"]);
601
883
  var RANGE_OPERATORS = /* @__PURE__ */ new Set(["<", "<=", ">", ">=", "!=", "not-in"]);
@@ -1329,10 +1611,10 @@ function collectParams(decl, descriptions) {
1329
1611
  for (const param of params) {
1330
1612
  const name = param.getName();
1331
1613
  const typeNode = param.getTypeNode()?.getText();
1332
- const type4 = typeNode ?? param.getType().getText() ?? "unknown";
1614
+ const type5 = typeNode ?? param.getType().getText() ?? "unknown";
1333
1615
  const description = descriptions.get(name) ?? "";
1334
1616
  const optional = param.isOptional() || param.hasInitializer();
1335
- out.push({ name, type: type4, description, optional });
1617
+ out.push({ name, type: type5, description, optional });
1336
1618
  }
1337
1619
  return out;
1338
1620
  }
@@ -1879,178 +2161,34 @@ function toCamelCase(typeName) {
1879
2161
  }
1880
2162
 
1881
2163
  // packages/dbx-cli/firestore-indexes/src/model-firebase-index-scan-config-schema.ts
1882
- import { type as type2 } from "arktype";
1883
- var ModelFirebaseIndexScanSection = type2({
2164
+ import { type as type3 } from "arktype";
2165
+ var ModelFirebaseIndexScanSection = type3({
1884
2166
  "source?": "string",
1885
2167
  "module?": "string",
1886
2168
  include: "string[] >= 1",
1887
2169
  "exclude?": "string[]",
1888
2170
  "out?": "string"
1889
2171
  });
1890
- var ModelFirebaseIndexScanConfig = type2({
2172
+ var ModelFirebaseIndexScanConfig = type3({
1891
2173
  version: "1",
1892
2174
  modelFirebaseIndex: ModelFirebaseIndexScanSection
1893
2175
  });
1894
2176
  var DEFAULT_MODEL_FIREBASE_INDEX_SCAN_OUT_PATH = "model-firebase-index.mcp.generated.json";
1895
2177
  var MODEL_FIREBASE_INDEX_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
1896
2178
 
1897
- // packages/dbx-cli/src/lib/scan-helpers/scan-io.ts
1898
- import { glob as fsGlob, readFile as nodeReadFile } from "node:fs/promises";
1899
- import { resolve as resolvePath } from "node:path";
1900
- import { Project } from "ts-morph";
1901
- var defaultReadFile = (path) => nodeReadFile(path, "utf-8");
1902
- var defaultGlobber = async (input) => {
1903
- const { projectRoot, include, exclude } = input;
1904
- const excludeMatchers = exclude.map(globToRegex);
1905
- const seen = /* @__PURE__ */ new Set();
1906
- const matches = [];
1907
- for (const pattern of include) {
1908
- for await (const match of fsGlob(pattern, { cwd: projectRoot })) {
1909
- if (excludeMatchers.some((rx) => rx.test(match))) {
1910
- continue;
1911
- }
1912
- if (!seen.has(match)) {
1913
- seen.add(match);
1914
- matches.push(match);
1915
- }
1916
- }
1917
- }
1918
- return matches;
1919
- };
1920
- async function loadPackageName(packagePath, readFile) {
1921
- let raw = null;
1922
- try {
1923
- raw = await readFile(packagePath);
1924
- } catch {
1925
- raw = null;
1926
- }
1927
- let result;
1928
- if (raw === null) {
1929
- result = { kind: "fail", outcome: { kind: "no-package", packagePath } };
1930
- } else {
1931
- let parsed;
1932
- let parseError = null;
1933
- try {
1934
- parsed = JSON.parse(raw);
1935
- } catch (err) {
1936
- parseError = err instanceof Error ? err.message : String(err);
1937
- }
1938
- if (parseError === null) {
1939
- const name = parsed?.name;
1940
- if (typeof name !== "string" || name.length === 0) {
1941
- result = { kind: "fail", outcome: { kind: "invalid-package", packagePath, error: "package.json is missing a non-empty `name` field" } };
1942
- } else {
1943
- result = { kind: "ok", packageName: name };
1944
- }
1945
- } else {
1946
- result = { kind: "fail", outcome: { kind: "invalid-package", packagePath, error: parseError } };
1947
- }
1948
- }
1949
- return result;
1950
- }
1951
- async function loadScanSection(input) {
1952
- const { configPath, readFile, parseSection } = input;
1953
- const readResult = await readScanConfigRaw(configPath, readFile);
1954
- let result;
1955
- if (readResult.kind === "error") {
1956
- result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: `failed to read config: ${readResult.error}` } };
1957
- } else if (readResult.kind === "enoent") {
1958
- result = { kind: "fail", outcome: { kind: "no-config", configPath } };
1959
- } else {
1960
- result = parseScanSectionFromRaw(readResult.raw, configPath, parseSection);
1961
- }
1962
- return result;
1963
- }
1964
- async function readScanConfigRaw(configPath, readFile) {
1965
- let result;
1966
- try {
1967
- const raw = await readFile(configPath);
1968
- result = { kind: "ok", raw };
1969
- } catch (err) {
1970
- const code = err?.code;
1971
- if (code === "ENOENT") {
1972
- result = { kind: "enoent" };
1973
- } else {
1974
- result = { kind: "error", error: err instanceof Error ? err.message : String(err) };
1975
- }
1976
- }
1977
- return result;
1978
- }
1979
- function parseScanSectionFromRaw(raw, configPath, parseSection) {
1980
- const jsonResult = parseJsonString(raw);
1981
- let result;
1982
- if (jsonResult.ok) {
1983
- const sectionResult = parseSection(jsonResult.value);
1984
- if (sectionResult.ok) {
1985
- result = { kind: "ok", section: sectionResult.section };
1986
- } else {
1987
- result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: sectionResult.error } };
1988
- }
1989
- } else {
1990
- result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: jsonResult.error } };
1991
- }
1992
- return result;
1993
- }
1994
- function parseJsonString(raw) {
1995
- let result;
1996
- try {
1997
- result = { ok: true, value: JSON.parse(raw) };
1998
- } catch (err) {
1999
- result = { ok: false, error: err instanceof Error ? err.message : String(err) };
2000
- }
2001
- return result;
2002
- }
2003
- async function buildScanProject(input) {
2004
- const { projectRoot, filePaths, readFile } = input;
2005
- const project = new Project({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
2006
- for (const relPath of filePaths) {
2007
- const absolute = resolvePath(projectRoot, relPath);
2008
- const text = await readFile(absolute);
2009
- project.createSourceFile(absolute, text, { overwrite: true });
2010
- }
2011
- return project;
2012
- }
2013
- function globToRegex(pattern) {
2014
- let body = "";
2015
- let index = 0;
2016
- while (index < pattern.length) {
2017
- const char = pattern[index];
2018
- if (char === "*" && pattern[index + 1] === "*") {
2019
- body += ".*";
2020
- index += 2;
2021
- if (pattern[index] === "/") {
2022
- index += 1;
2023
- }
2024
- } else if (char === "*") {
2025
- body += "[^/]*";
2026
- index += 1;
2027
- } else if (char === "?") {
2028
- body += "[^/]";
2029
- index += 1;
2030
- } else if (".+^${}()|[]\\".includes(char)) {
2031
- body += `\\${char}`;
2032
- index += 1;
2033
- } else {
2034
- body += char;
2035
- index += 1;
2036
- }
2037
- }
2038
- return new RegExp(`^${body}$`);
2039
- }
2040
-
2041
2179
  // packages/dbx-cli/firestore-indexes/src/model-firebase-index-build-manifest.ts
2042
2180
  var DEFAULT_READ_FILE = defaultReadFile;
2043
2181
  var DEFAULT_GLOBBER = defaultGlobber;
2044
2182
  async function buildModelFirebaseIndexManifest(input) {
2045
2183
  const { projectRoot, generator, readFile = DEFAULT_READ_FILE, globber = DEFAULT_GLOBBER, now = () => /* @__PURE__ */ new Date() } = input;
2046
- const configPath = resolve2(projectRoot, MODEL_FIREBASE_INDEX_SCAN_CONFIG_FILENAME);
2047
- const packagePath = resolve2(projectRoot, "package.json");
2184
+ const configPath = resolve4(projectRoot, MODEL_FIREBASE_INDEX_SCAN_CONFIG_FILENAME);
2185
+ const packagePath = resolve4(projectRoot, "package.json");
2048
2186
  const configOutcome = await loadScanSection({
2049
2187
  configPath,
2050
2188
  readFile,
2051
2189
  parseSection: (parsed) => {
2052
2190
  const validated2 = ModelFirebaseIndexScanConfig(parsed);
2053
- if (validated2 instanceof type3.errors) {
2191
+ if (validated2 instanceof type4.errors) {
2054
2192
  return { ok: false, error: validated2.summary };
2055
2193
  }
2056
2194
  return { ok: true, section: validated2.modelFirebaseIndex };
@@ -2096,10 +2234,10 @@ async function buildModelFirebaseIndexManifest(input) {
2096
2234
  };
2097
2235
  const validated = ModelFirebaseIndexManifest(manifest);
2098
2236
  let outcome;
2099
- if (validated instanceof type3.errors) {
2237
+ if (validated instanceof type4.errors) {
2100
2238
  outcome = { kind: "invalid-manifest", error: validated.summary };
2101
2239
  } else {
2102
- const outPath = resolve2(projectRoot, scanSection.out ?? DEFAULT_MODEL_FIREBASE_INDEX_SCAN_OUT_PATH);
2240
+ const outPath = resolve4(projectRoot, scanSection.out ?? DEFAULT_MODEL_FIREBASE_INDEX_SCAN_OUT_PATH);
2103
2241
  const entryFilePathsBySlug = /* @__PURE__ */ new Map();
2104
2242
  const dispatcherSummaries = [];
2105
2243
  for (const analyzedEntry of analyzed) {
@@ -2186,38 +2324,40 @@ async function findQueryEntries(input) {
2186
2324
  let result;
2187
2325
  if (outcome.kind === "success") {
2188
2326
  const dispatcherNames = new Set(outcome.dispatcherSummaries.map((x) => x.name));
2189
- const all = outcome.manifest.entries;
2190
- const kept = all.filter((x) => x.specOnly !== true);
2191
- result = {
2192
- kind: "success",
2193
- droppedSpecOnly: all.length - kept.length,
2194
- entries: kept.map((entry) => ({
2195
- slug: entry.slug,
2196
- name: entry.name,
2197
- module: entry.module,
2198
- subpath: entry.subpath,
2199
- model: entry.model,
2200
- collection: entry.collection,
2201
- isNested: entry.isNested,
2202
- scope: entry.scope,
2203
- signature: entry.signature,
2204
- params: entry.params.map((p) => ({ name: p.name, type: p.type, optional: p.optional, ...p.description ? { description: p.description } : {} })),
2205
- ...entry.description ? { description: entry.description } : {},
2206
- ...entry.category ? { category: entry.category } : {},
2207
- ...entry.tags.length > 0 ? { tags: entry.tags } : {},
2208
- ...entry.example ? { example: entry.example } : {},
2209
- ...entry.relatedSlugs && entry.relatedSlugs.length > 0 ? { relatedSlugs: entry.relatedSlugs } : {},
2210
- ...entry.manual ? { manual: true } : {},
2211
- ...entry.skip ? { skip: true } : {},
2212
- ...entry.excluded ? { excluded: true } : {},
2213
- ...dispatcherNames.has(entry.name) ? { dispatcher: true } : {}
2214
- }))
2215
- };
2327
+ result = { kind: "success", ...collectQueryEntries({ entries: outcome.manifest.entries, dispatcherNames }) };
2216
2328
  } else {
2217
2329
  result = { kind: "failure", message: describeFailure(componentRoot, outcome) };
2218
2330
  }
2219
2331
  return result;
2220
2332
  }
2333
+ function collectQueryEntries(input) {
2334
+ const { entries: all, dispatcherNames = /* @__PURE__ */ new Set() } = input;
2335
+ const kept = all.filter((x) => x.specOnly !== true);
2336
+ return {
2337
+ droppedSpecOnly: all.length - kept.length,
2338
+ entries: kept.map((entry) => ({
2339
+ slug: entry.slug,
2340
+ name: entry.name,
2341
+ module: entry.module,
2342
+ subpath: entry.subpath,
2343
+ model: entry.model,
2344
+ collection: entry.collection,
2345
+ isNested: entry.isNested,
2346
+ scope: entry.scope,
2347
+ signature: entry.signature,
2348
+ params: entry.params.map((p) => ({ name: p.name, type: p.type, optional: p.optional, ...p.description ? { description: p.description } : {} })),
2349
+ ...entry.description ? { description: entry.description } : {},
2350
+ ...entry.category ? { category: entry.category } : {},
2351
+ ...entry.tags.length > 0 ? { tags: entry.tags } : {},
2352
+ ...entry.example ? { example: entry.example } : {},
2353
+ ...entry.relatedSlugs && entry.relatedSlugs.length > 0 ? { relatedSlugs: entry.relatedSlugs } : {},
2354
+ ...entry.manual ? { manual: true } : {},
2355
+ ...entry.skip ? { skip: true } : {},
2356
+ ...entry.excluded ? { excluded: true } : {},
2357
+ ...dispatcherNames.has(entry.name) ? { dispatcher: true } : {}
2358
+ }))
2359
+ };
2360
+ }
2221
2361
  function describeFailure(componentRoot, outcome) {
2222
2362
  let result;
2223
2363
  switch (outcome.kind) {
@@ -2240,12 +2380,32 @@ function describeFailure(componentRoot, outcome) {
2240
2380
  return result;
2241
2381
  }
2242
2382
 
2383
+ // packages/dbx-cli/firestore-query-manifest/src/find-package-query-entries.ts
2384
+ async function findPackageQueryEntries(input) {
2385
+ const { cwd, loadManifests = loadModelFirebaseIndexPackageManifests } = input;
2386
+ const outcome = await loadManifests({ cwd, discoverBundled: true });
2387
+ let result;
2388
+ if (outcome.kind === "success") {
2389
+ const entries = [];
2390
+ let droppedSpecOnly = 0;
2391
+ for (const loaded of outcome.loaded) {
2392
+ const collected = collectQueryEntries({ entries: loaded.manifest.entries });
2393
+ entries.push(...collected.entries);
2394
+ droppedSpecOnly += collected.droppedSpecOnly;
2395
+ }
2396
+ result = { kind: "success", entries, droppedSpecOnly, manifestPaths: outcome.loaded.map((x) => x.path) };
2397
+ } else {
2398
+ result = { kind: "failure", message: `[packages] ${formatModelFirebaseIndexPackageManifestFailure(outcome)}` };
2399
+ }
2400
+ return result;
2401
+ }
2402
+
2243
2403
  // packages/dbx-cli/firestore-query-manifest/src/main.ts
2244
2404
  var WORKSPACE_ROOT = process.cwd();
2245
2405
  var GENERATOR = `@dereekb/dbx-cli-firestore-query-manifest@${package_default.version}`;
2246
2406
  async function main() {
2247
2407
  const flags = parseFlags(process.argv.slice(2));
2248
- if (flags.components.length === 0 || !flags.output) {
2408
+ if (flags.components.length === 0 && !flags.packages || !flags.output) {
2249
2409
  printUsageAndExit();
2250
2410
  return;
2251
2411
  }
@@ -2268,6 +2428,22 @@ async function main() {
2268
2428
  collected.push(...bound.bound);
2269
2429
  warnings.push(...bound.warnings);
2270
2430
  }
2431
+ let packageEntryCount = 0;
2432
+ if (flags.packages) {
2433
+ const found = await findPackageQueryEntries({ cwd: WORKSPACE_ROOT });
2434
+ if (found.kind === "failure") {
2435
+ console.error(found.message);
2436
+ process.exit(1);
2437
+ return;
2438
+ }
2439
+ droppedSpecOnly += found.droppedSpecOnly;
2440
+ const collectedKeys = new Set(collected.map((x) => queryEntryKey(x.entry)));
2441
+ const packageEntries = found.entries.filter((x) => !collectedKeys.has(queryEntryKey(x)));
2442
+ const bound = bindPackageQueryFactories({ cwd: WORKSPACE_ROOT, entries: packageEntries });
2443
+ collected.push(...bound.bound);
2444
+ warnings.push(...bound.warnings);
2445
+ packageEntryCount = packageEntries.length;
2446
+ }
2271
2447
  for (const warning of warnings) {
2272
2448
  console.warn(warning);
2273
2449
  }
@@ -2295,7 +2471,7 @@ async function main() {
2295
2471
  console.log(`[${outcome}] ${relOutput}`);
2296
2472
  }
2297
2473
  const boundCount = collected.filter((x) => x.bound).length;
2298
- console.log(`Summary: ${flags.components.length} component(s) \xB7 ${collected.length} entries \xB7 ${boundCount} bound \xB7 ${collected.length - boundCount} unbound \xB7 ${droppedSpecOnly} spec-only dropped \xB7 rules: ${queryModes.summary}`);
2474
+ console.log(`Summary: ${flags.components.length} component(s) \xB7 ${flags.packages ? `${packageEntryCount} package entries \xB7 ` : ""}${collected.length} entries \xB7 ${boundCount} bound \xB7 ${collected.length - boundCount} unbound \xB7 ${droppedSpecOnly} spec-only dropped \xB7 rules: ${queryModes.summary}`);
2299
2475
  if (flags.strict && boundCount < collected.length) {
2300
2476
  console.error(`[strict] ${collected.length - boundCount} factor(y|ies) failed to bind \u2014 failing build.`);
2301
2477
  process.exit(1);
@@ -2327,8 +2503,11 @@ function applyQueryModes(input) {
2327
2503
  }
2328
2504
  return result;
2329
2505
  }
2506
+ function queryEntryKey(entry) {
2507
+ return `${entry.module}#${entry.name}`;
2508
+ }
2330
2509
  function resolveWorkspacePath(value) {
2331
- return isAbsolute2(value) ? value : resolve3(WORKSPACE_ROOT, value);
2510
+ return isAbsolute2(value) ? value : resolve5(WORKSPACE_ROOT, value);
2332
2511
  }
2333
2512
  function deriveNamespace(projectName) {
2334
2513
  const base = (projectName ?? "cli").replaceAll(/[^a-zA-Z0-9]+/g, "_");
@@ -2339,10 +2518,13 @@ function parseFlags(argv) {
2339
2518
  let output;
2340
2519
  let project;
2341
2520
  let rules;
2521
+ let packages = false;
2342
2522
  let strict = false;
2343
2523
  let check = false;
2344
2524
  for (const arg of argv) {
2345
- if (arg === "--strict") {
2525
+ if (arg === "--packages") {
2526
+ packages = true;
2527
+ } else if (arg === "--strict") {
2346
2528
  strict = true;
2347
2529
  } else if (arg === "--check") {
2348
2530
  check = true;
@@ -2358,7 +2540,7 @@ function parseFlags(argv) {
2358
2540
  if (value) rules = value;
2359
2541
  }
2360
2542
  }
2361
- return { components, output, project, rules, strict, check };
2543
+ return { components, packages, output, project, rules, strict, check };
2362
2544
  }
2363
2545
  function printUsageAndExit() {
2364
2546
  console.error(String.raw`generate-firestore-query-manifest
@@ -2366,12 +2548,16 @@ function printUsageAndExit() {
2366
2548
  Usage:
2367
2549
  node dist/packages/dbx-cli/firestore-query-manifest/main.js \
2368
2550
  --project=<name> \
2369
- --component=<component-dir> [--component=<component-dir> ...] \
2551
+ [--component=<component-dir> ...] [--packages] \
2370
2552
  --output=<path-to-query.manifest.generated.ts> \
2371
2553
  [--rules=<path-to-firestore.rules>] [--strict] [--check]
2372
2554
 
2373
2555
  Required flags:
2374
2556
  --component=<dir> A "-firebase" component root to scan. Repeatable.
2557
+ --packages Also merge the framework query manifests bundled in the installed
2558
+ @dereekb/dbx-components-mcp (e.g. the @dereekb/firebase notification queries),
2559
+ which a published package ships no scannable source for.
2560
+ At least one of --component / --packages is required.
2375
2561
  --output=<path> Path to the manifest TS file to write (workspace-relative ok).
2376
2562
 
2377
2563
  Optional:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-firestore-query-manifest",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
@@ -8,7 +8,7 @@
8
8
  "eslint": "10.9.1"
9
9
  },
10
10
  "peerDependencies": {
11
- "@dereekb/dbx-cli": "14.8.0",
12
- "@dereekb/util": "14.8.0"
11
+ "@dereekb/dbx-cli": "14.10.0",
12
+ "@dereekb/util": "14.10.0"
13
13
  }
14
14
  }
@@ -5,7 +5,7 @@ const require = __createRequire(import.meta.url);
5
5
  // packages/dbx-cli/generate-firestore-indexes/package.json
6
6
  var package_default = {
7
7
  name: "@dereekb/dbx-cli-generate-firestore-indexes",
8
- version: "14.8.0",
8
+ version: "14.10.0",
9
9
  sideEffects: false,
10
10
  private: true,
11
11
  type: "module",
@@ -13,7 +13,7 @@ var package_default = {
13
13
  eslint: "10.9.1"
14
14
  },
15
15
  peerDependencies: {
16
- "@dereekb/dbx-cli": "14.8.0"
16
+ "@dereekb/dbx-cli": "14.10.0"
17
17
  }
18
18
  };
19
19
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-generate-firestore-indexes",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
@@ -8,6 +8,6 @@
8
8
  "eslint": "10.9.1"
9
9
  },
10
10
  "peerDependencies": {
11
- "@dereekb/dbx-cli": "14.8.0"
11
+ "@dereekb/dbx-cli": "14.10.0"
12
12
  }
13
13
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-generate-mcp-manifest",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
7
7
  "peerDependencies": {
8
- "@dereekb/dbx-cli": "14.8.0",
9
- "@dereekb/model": "14.8.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
+ "@dereekb/model": "14.10.0",
10
10
  "arktype": "^2.2.0",
11
11
  "jiti": "2.7.0"
12
12
  }
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-generate-route-manifest",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
7
7
  "peerDependencies": {
8
- "@dereekb/dbx-cli": "14.8.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
9
  "ts-morph": "^28.0.0"
10
10
  }
11
11
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-lint-cache",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  "eslint": "10.9.1"
10
10
  },
11
11
  "peerDependencies": {
12
- "@dereekb/util": "14.8.0",
12
+ "@dereekb/util": "14.10.0",
13
13
  "yargs": "^18.0.0"
14
14
  }
15
15
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/manifest-extract",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.8.0",
8
- "@dereekb/dbx-cli": "14.8.0",
9
- "@dereekb/firebase": "14.8.0",
10
- "@dereekb/model": "14.8.0",
11
- "@dereekb/nestjs": "14.8.0",
12
- "@dereekb/oauth-resource": "14.8.0",
13
- "@dereekb/rxjs": "14.8.0",
14
- "@dereekb/util": "14.8.0",
7
+ "@dereekb/date": "14.10.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
+ "@dereekb/firebase": "14.10.0",
10
+ "@dereekb/model": "14.10.0",
11
+ "@dereekb/nestjs": "14.10.0",
12
+ "@dereekb/oauth-resource": "14.10.0",
13
+ "@dereekb/rxjs": "14.10.0",
14
+ "@dereekb/util": "14.10.0",
15
15
  "ts-morph": "^28.0.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@dereekb/firebase": "14.8.0"
18
+ "@dereekb/firebase": "14.10.0"
19
19
  },
20
20
  "exports": {
21
21
  "./package.json": "./package.json",
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/model-test",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/util": "14.8.0",
7
+ "@dereekb/util": "14.10.0",
8
8
  "ts-morph": "^28.0.0"
9
9
  },
10
10
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "bin": {
@@ -66,12 +66,12 @@
66
66
  }
67
67
  },
68
68
  "peerDependencies": {
69
- "@dereekb/date": "14.8.0",
70
- "@dereekb/firebase": "14.8.0",
71
- "@dereekb/model": "14.8.0",
72
- "@dereekb/nestjs": "14.8.0",
73
- "@dereekb/oauth-resource": "14.8.0",
74
- "@dereekb/util": "14.8.0",
69
+ "@dereekb/date": "14.10.0",
70
+ "@dereekb/firebase": "14.10.0",
71
+ "@dereekb/model": "14.10.0",
72
+ "@dereekb/nestjs": "14.10.0",
73
+ "@dereekb/oauth-resource": "14.10.0",
74
+ "@dereekb/util": "14.10.0",
75
75
  "@nestjs/common": "^12.0.1",
76
76
  "arktype": "^2.2.0",
77
77
  "firebase": "^12.18.0",
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/route",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.8.0",
8
- "@dereekb/dbx-cli": "14.8.0",
9
- "@dereekb/firebase": "14.8.0",
10
- "@dereekb/model": "14.8.0",
11
- "@dereekb/nestjs": "14.8.0",
12
- "@dereekb/oauth-resource": "14.8.0",
13
- "@dereekb/util": "14.8.0"
7
+ "@dereekb/date": "14.10.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
+ "@dereekb/firebase": "14.10.0",
10
+ "@dereekb/model": "14.10.0",
11
+ "@dereekb/nestjs": "14.10.0",
12
+ "@dereekb/oauth-resource": "14.10.0",
13
+ "@dereekb/util": "14.10.0"
14
14
  },
15
15
  "exports": {
16
16
  "./package.json": "./package.json",
package/test/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/test",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.8.0",
8
- "@dereekb/dbx-cli": "14.8.0",
9
- "@dereekb/firebase": "14.8.0",
10
- "@dereekb/firebase-server/test": "14.7.0",
11
- "@dereekb/model": "14.8.0",
12
- "@dereekb/nestjs": "14.8.0",
13
- "@dereekb/oauth-resource": "14.8.0",
14
- "@dereekb/rxjs": "14.8.0",
15
- "@dereekb/util": "14.8.0",
7
+ "@dereekb/date": "14.10.0",
8
+ "@dereekb/dbx-cli": "14.10.0",
9
+ "@dereekb/firebase": "14.10.0",
10
+ "@dereekb/firebase-server/test": "14.9.0",
11
+ "@dereekb/model": "14.10.0",
12
+ "@dereekb/nestjs": "14.10.0",
13
+ "@dereekb/oauth-resource": "14.10.0",
14
+ "@dereekb/rxjs": "14.10.0",
15
+ "@dereekb/util": "14.10.0",
16
16
  "@nestjs/common": "^12.0.1",
17
17
  "arktype": "^2.2.0",
18
18
  "vitest": "4.1.11",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/validate",
3
- "version": "14.8.0",
3
+ "version": "14.10.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/dbx-cli": "14.8.0",
8
- "@dereekb/util": "14.8.0",
7
+ "@dereekb/dbx-cli": "14.10.0",
8
+ "@dereekb/util": "14.10.0",
9
9
  "ts-morph": "^28.0.0"
10
10
  }
11
11
  }