@typicalday/firegraph 0.10.0 → 0.11.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.
Files changed (40) hide show
  1. package/README.md +93 -90
  2. package/bin/firegraph.mjs +21 -7
  3. package/dist/{backend-BrqFkbid.d.ts → backend-U-MLShlg.d.ts} +1 -1
  4. package/dist/{backend-73p5Blx7.d.cts → backend-np4gEVhB.d.cts} +1 -1
  5. package/dist/backend.d.cts +3 -3
  6. package/dist/backend.d.ts +3 -3
  7. package/dist/{chunk-LZOIQHYN.js → chunk-6SB34IPQ.js} +20 -7
  8. package/dist/chunk-6SB34IPQ.js.map +1 -0
  9. package/dist/{chunk-SU4FNLC3.js → chunk-EEKWRX5E.js} +1 -1
  10. package/dist/{chunk-SU4FNLC3.js.map → chunk-EEKWRX5E.js.map} +1 -1
  11. package/dist/{chunk-YLGXLEUE.js → chunk-GJVVRTQT.js} +5 -14
  12. package/dist/chunk-GJVVRTQT.js.map +1 -0
  13. package/dist/cloudflare/index.cjs +151 -27
  14. package/dist/cloudflare/index.cjs.map +1 -1
  15. package/dist/cloudflare/index.d.cts +78 -3
  16. package/dist/cloudflare/index.d.ts +78 -3
  17. package/dist/cloudflare/index.js +135 -23
  18. package/dist/cloudflare/index.js.map +1 -1
  19. package/dist/codegen/index.cjs +4 -13
  20. package/dist/codegen/index.cjs.map +1 -1
  21. package/dist/codegen/index.d.cts +1 -1
  22. package/dist/codegen/index.d.ts +1 -1
  23. package/dist/codegen/index.js +1 -1
  24. package/dist/index.cjs +89 -132
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.cts +106 -21
  27. package/dist/index.d.ts +106 -21
  28. package/dist/index.js +70 -116
  29. package/dist/index.js.map +1 -1
  30. package/dist/query-client/index.cjs.map +1 -1
  31. package/dist/query-client/index.js +1 -1
  32. package/dist/{types-DOemdlVA.d.ts → types-BGWxcpI_.d.cts} +75 -1
  33. package/dist/{types-DOemdlVA.d.cts → types-BGWxcpI_.d.ts} +75 -1
  34. package/package.json +35 -27
  35. package/dist/chunk-LZOIQHYN.js.map +0 -1
  36. package/dist/chunk-YLGXLEUE.js.map +0 -1
  37. package/dist/editor/client/assets/index-Bq2bfzeY.js +0 -411
  38. package/dist/editor/client/assets/index-CJ4m_EOL.css +0 -1
  39. package/dist/editor/client/index.html +0 -16
  40. package/dist/editor/server/index.mjs +0 -51566
package/dist/index.cjs CHANGED
@@ -159,6 +159,7 @@ var index_exports = {};
159
159
  __export(index_exports, {
160
160
  BOOTSTRAP_ENTRIES: () => BOOTSTRAP_ENTRIES,
161
161
  CrossBackendTransactionError: () => CrossBackendTransactionError,
162
+ DEFAULT_CORE_INDEXES: () => DEFAULT_CORE_INDEXES,
162
163
  DEFAULT_QUERY_LIMIT: () => DEFAULT_QUERY_LIMIT,
163
164
  DiscoveryError: () => DiscoveryError,
164
165
  DynamicRegistryError: () => DynamicRegistryError,
@@ -573,9 +574,7 @@ async function migrateRecord(record, registry, globalWriteBack = "off") {
573
574
  };
574
575
  }
575
576
  async function migrateRecords(records, registry, globalWriteBack = "off") {
576
- return Promise.all(
577
- records.map((r) => migrateRecord(r, registry, globalWriteBack))
578
- );
577
+ return Promise.all(records.map((r) => migrateRecord(r, registry, globalWriteBack)));
579
578
  }
580
579
 
581
580
  // src/scope.ts
@@ -783,7 +782,8 @@ function discoveryToEntries(discovery) {
783
782
  subtitleField: entity.subtitleField,
784
783
  allowedIn: entity.allowedIn,
785
784
  migrations: entity.migrations,
786
- migrationWriteBack: entity.migrationWriteBack
785
+ migrationWriteBack: entity.migrationWriteBack,
786
+ indexes: entity.indexes
787
787
  });
788
788
  }
789
789
  for (const [axbType, entity] of discovery.edges) {
@@ -811,7 +811,8 @@ function discoveryToEntries(discovery) {
811
811
  allowedIn: entity.allowedIn,
812
812
  targetGraph: resolvedTargetGraph,
813
813
  migrations: entity.migrations,
814
- migrationWriteBack: entity.migrationWriteBack
814
+ migrationWriteBack: entity.migrationWriteBack,
815
+ indexes: entity.indexes
815
816
  });
816
817
  }
817
818
  }
@@ -1896,26 +1897,17 @@ function createGraphClientFromBackend(backend, options, metaBackend) {
1896
1897
 
1897
1898
  // src/codegen/index.ts
1898
1899
  function pascalCase(s) {
1899
- return s.replace(
1900
- /(^|[^a-zA-Z0-9])([a-zA-Z])/g,
1901
- (_, _sep, ch) => ch.toUpperCase()
1902
- );
1900
+ return s.replace(/(^|[^a-zA-Z0-9])([a-zA-Z])/g, (_, _sep, ch) => ch.toUpperCase());
1903
1901
  }
1904
1902
  async function generateTypes(discovery, options = {}) {
1905
1903
  const { compile } = await import("json-schema-to-typescript");
1906
1904
  const { banner = true } = options;
1907
1905
  const chunks = [];
1908
1906
  if (banner) {
1909
- chunks.push(
1910
- "// Auto-generated by firegraph codegen \u2014 do not edit manually\n"
1911
- );
1907
+ chunks.push("// Auto-generated by firegraph codegen \u2014 do not edit manually\n");
1912
1908
  }
1913
- const sortedNodes = [...discovery.nodes.entries()].sort(
1914
- ([a], [b]) => a.localeCompare(b)
1915
- );
1916
- const sortedEdges = [...discovery.edges.entries()].sort(
1917
- ([a], [b]) => a.localeCompare(b)
1918
- );
1909
+ const sortedNodes = [...discovery.nodes.entries()].sort(([a], [b]) => a.localeCompare(b));
1910
+ const sortedEdges = [...discovery.edges.entries()].sort(([a], [b]) => a.localeCompare(b));
1919
1911
  for (const [name, entity] of sortedNodes) {
1920
1912
  const typeName = `${pascalCase(name)}Data`;
1921
1913
  const ts = await compile(entity.schema, typeName, {
@@ -1970,6 +1962,18 @@ function isAncestorUid(collectionPath, uid) {
1970
1962
  return resolveAncestorCollection(collectionPath, uid) !== null;
1971
1963
  }
1972
1964
 
1965
+ // src/default-indexes.ts
1966
+ var DEFAULT_CORE_INDEXES = Object.freeze([
1967
+ { fields: ["aUid"] },
1968
+ { fields: ["bUid"] },
1969
+ { fields: ["aType"] },
1970
+ { fields: ["bType"] },
1971
+ { fields: ["aUid", "axbType"] },
1972
+ { fields: ["axbType", "bUid"] },
1973
+ { fields: ["aType", "axbType"] },
1974
+ { fields: ["axbType", "bType"] }
1975
+ ]);
1976
+
1973
1977
  // src/discover.ts
1974
1978
  var import_node_fs = require("fs");
1975
1979
  var import_node_module = require("module");
@@ -2091,7 +2095,8 @@ function loadNodeEntity(dir, name) {
2091
2095
  sampleData,
2092
2096
  allowedIn: meta?.allowedIn,
2093
2097
  migrations,
2094
- migrationWriteBack: meta?.migrationWriteBack
2098
+ migrationWriteBack: meta?.migrationWriteBack,
2099
+ indexes: meta?.indexes
2095
2100
  };
2096
2101
  }
2097
2102
  function loadEdgeEntity(dir, name) {
@@ -2128,7 +2133,8 @@ function loadEdgeEntity(dir, name) {
2128
2133
  allowedIn: meta?.allowedIn,
2129
2134
  targetGraph: topology.targetGraph ?? meta?.targetGraph,
2130
2135
  migrations,
2131
- migrationWriteBack: meta?.migrationWriteBack
2136
+ migrationWriteBack: meta?.migrationWriteBack,
2137
+ indexes: meta?.indexes
2132
2138
  };
2133
2139
  }
2134
2140
  function getSubdirectories(dir) {
@@ -2658,124 +2664,74 @@ function generateId() {
2658
2664
  }
2659
2665
 
2660
2666
  // src/indexes.ts
2661
- function baseIndexes(collection) {
2662
- return [
2663
- {
2664
- collectionGroup: collection,
2665
- queryScope: "COLLECTION",
2666
- fields: [
2667
- { fieldPath: "aUid", order: "ASCENDING" },
2668
- { fieldPath: "axbType", order: "ASCENDING" }
2669
- ]
2670
- },
2671
- {
2672
- collectionGroup: collection,
2673
- queryScope: "COLLECTION",
2674
- fields: [
2675
- { fieldPath: "axbType", order: "ASCENDING" },
2676
- { fieldPath: "bUid", order: "ASCENDING" }
2677
- ]
2678
- },
2679
- {
2680
- collectionGroup: collection,
2681
- queryScope: "COLLECTION",
2682
- fields: [
2683
- { fieldPath: "aType", order: "ASCENDING" },
2684
- { fieldPath: "axbType", order: "ASCENDING" }
2685
- ]
2686
- },
2687
- {
2688
- collectionGroup: collection,
2689
- queryScope: "COLLECTION",
2690
- fields: [
2691
- { fieldPath: "axbType", order: "ASCENDING" },
2692
- { fieldPath: "bType", order: "ASCENDING" }
2693
- ]
2694
- }
2695
- ];
2667
+ function normalizeField(f) {
2668
+ return typeof f === "string" ? { path: f, desc: false } : { path: f.path, desc: !!f.desc };
2696
2669
  }
2697
- function extractSchemaFields(schema) {
2698
- const s = schema;
2699
- if (s.type !== "object" || !s.properties) return [];
2700
- return Object.keys(s.properties);
2701
- }
2702
- function collectionGroupIndexes(collectionName) {
2703
- return [
2704
- {
2705
- collectionGroup: collectionName,
2706
- queryScope: "COLLECTION_GROUP",
2707
- fields: [
2708
- { fieldPath: "aUid", order: "ASCENDING" },
2709
- { fieldPath: "axbType", order: "ASCENDING" }
2710
- ]
2711
- },
2712
- {
2713
- collectionGroup: collectionName,
2714
- queryScope: "COLLECTION_GROUP",
2715
- fields: [
2716
- { fieldPath: "axbType", order: "ASCENDING" },
2717
- { fieldPath: "bUid", order: "ASCENDING" }
2718
- ]
2719
- },
2720
- {
2721
- collectionGroup: collectionName,
2722
- queryScope: "COLLECTION_GROUP",
2723
- fields: [
2724
- { fieldPath: "aType", order: "ASCENDING" },
2725
- { fieldPath: "axbType", order: "ASCENDING" }
2726
- ]
2727
- },
2728
- {
2729
- collectionGroup: collectionName,
2730
- queryScope: "COLLECTION_GROUP",
2731
- fields: [
2732
- { fieldPath: "axbType", order: "ASCENDING" },
2733
- { fieldPath: "bType", order: "ASCENDING" }
2734
- ]
2735
- }
2736
- ];
2670
+ function specFingerprint(spec, scope) {
2671
+ const normalized = spec.fields.map(normalizeField);
2672
+ return `${scope}::${JSON.stringify(normalized)}`;
2737
2673
  }
2738
- function generateIndexConfig(collection, entities, registryEntries) {
2739
- const indexes = baseIndexes(collection);
2740
- if (entities) {
2741
- for (const [, entity] of entities.nodes) {
2742
- const fields = extractSchemaFields(entity.schema);
2743
- for (const field of fields) {
2744
- indexes.push({
2745
- collectionGroup: collection,
2746
- queryScope: "COLLECTION",
2747
- fields: [
2748
- { fieldPath: "aType", order: "ASCENDING" },
2749
- { fieldPath: "axbType", order: "ASCENDING" },
2750
- { fieldPath: `data.${field}`, order: "ASCENDING" }
2751
- ]
2752
- });
2753
- }
2754
- }
2755
- for (const [, entity] of entities.edges) {
2756
- const fields = extractSchemaFields(entity.schema);
2757
- for (const field of fields) {
2758
- indexes.push({
2759
- collectionGroup: collection,
2760
- queryScope: "COLLECTION",
2761
- fields: [
2762
- { fieldPath: "aUid", order: "ASCENDING" },
2763
- { fieldPath: "axbType", order: "ASCENDING" },
2764
- { fieldPath: `data.${field}`, order: "ASCENDING" }
2765
- ]
2766
- });
2767
- }
2674
+ function toFirestoreFields(spec) {
2675
+ return spec.fields.map((f) => {
2676
+ const n = normalizeField(f);
2677
+ return {
2678
+ fieldPath: n.path,
2679
+ order: n.desc ? "DESCENDING" : "ASCENDING"
2680
+ };
2681
+ });
2682
+ }
2683
+ var warnedOnPartialIndex = false;
2684
+ function generateIndexConfig(collection, options = {}) {
2685
+ const core = options.coreIndexes ?? [...DEFAULT_CORE_INDEXES];
2686
+ const fromEntries = (options.registryEntries ?? []).flatMap((e) => {
2687
+ if (!e.indexes) return [];
2688
+ return e.indexes;
2689
+ });
2690
+ const targetGraphNames = /* @__PURE__ */ new Set();
2691
+ for (const entry of options.registryEntries ?? []) {
2692
+ if (entry.targetGraph) targetGraphNames.add(entry.targetGraph);
2693
+ }
2694
+ if (options.entities) {
2695
+ for (const [, entity] of options.entities.edges) {
2696
+ const tg = entity.targetGraph ?? entity.topology?.targetGraph;
2697
+ if (tg) targetGraphNames.add(tg);
2768
2698
  }
2769
2699
  }
2770
- if (registryEntries) {
2771
- const targetGraphNames = /* @__PURE__ */ new Set();
2772
- for (const entry of registryEntries) {
2773
- if (entry.targetGraph) {
2774
- targetGraphNames.add(entry.targetGraph);
2700
+ const allSpecs = [...core, ...fromEntries];
2701
+ const seen = /* @__PURE__ */ new Set();
2702
+ const indexes = [];
2703
+ for (const spec of allSpecs) {
2704
+ if (!spec.fields || spec.fields.length < 2) {
2705
+ continue;
2706
+ }
2707
+ if (spec.where) {
2708
+ if (!warnedOnPartialIndex) {
2709
+ warnedOnPartialIndex = true;
2710
+ console.warn(
2711
+ "firegraph: IndexSpec.where is ignored by the Firestore generator \u2014 Firestore composite indexes do not support predicates. The SQLite backends will still honor `where`."
2712
+ );
2775
2713
  }
2714
+ continue;
2776
2715
  }
2777
- for (const name of targetGraphNames) {
2778
- indexes.push(...collectionGroupIndexes(name));
2716
+ const fields = toFirestoreFields(spec);
2717
+ const colKey = specFingerprint(spec, `col:${collection}`);
2718
+ if (!seen.has(colKey)) {
2719
+ seen.add(colKey);
2720
+ indexes.push({
2721
+ collectionGroup: collection,
2722
+ queryScope: "COLLECTION",
2723
+ fields
2724
+ });
2725
+ }
2726
+ for (const tg of targetGraphNames) {
2727
+ const cgKey = specFingerprint(spec, `cg:${tg}`);
2728
+ if (seen.has(cgKey)) continue;
2729
+ seen.add(cgKey);
2730
+ indexes.push({
2731
+ collectionGroup: tg,
2732
+ queryScope: "COLLECTION_GROUP",
2733
+ fields
2734
+ });
2779
2735
  }
2780
2736
  }
2781
2737
  return { indexes, fieldOverrides: [] };
@@ -3433,6 +3389,7 @@ function defineViews(input) {
3433
3389
  0 && (module.exports = {
3434
3390
  BOOTSTRAP_ENTRIES,
3435
3391
  CrossBackendTransactionError,
3392
+ DEFAULT_CORE_INDEXES,
3436
3393
  DEFAULT_QUERY_LIMIT,
3437
3394
  DiscoveryError,
3438
3395
  DynamicRegistryError,