@typicalday/firegraph 0.8.0 → 0.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.
Files changed (72) hide show
  1. package/dist/backend-73p5Blx7.d.cts +97 -0
  2. package/dist/backend-BrqFkbid.d.ts +97 -0
  3. package/dist/backend.cjs +222 -0
  4. package/dist/backend.cjs.map +1 -0
  5. package/dist/backend.d.cts +122 -0
  6. package/dist/backend.d.ts +122 -0
  7. package/dist/backend.js +136 -0
  8. package/dist/backend.js.map +1 -0
  9. package/dist/{chunk-6OQW5OKO.js → chunk-5753Y42M.js} +12 -4
  10. package/dist/chunk-5753Y42M.js.map +1 -0
  11. package/dist/{chunk-YUXOALMR.js → chunk-LZOIQHYN.js} +69 -92
  12. package/dist/chunk-LZOIQHYN.js.map +1 -0
  13. package/dist/chunk-R7CRGYY4.js +94 -0
  14. package/dist/chunk-R7CRGYY4.js.map +1 -0
  15. package/dist/{chunk-KFA7G37W.js → chunk-SU4FNLC3.js} +32 -30
  16. package/dist/chunk-SU4FNLC3.js.map +1 -0
  17. package/dist/chunk-TYYPRVIE.js +57 -0
  18. package/dist/chunk-TYYPRVIE.js.map +1 -0
  19. package/dist/{do-sqlite.cjs → cloudflare/index.cjs} +1538 -1420
  20. package/dist/cloudflare/index.cjs.map +1 -0
  21. package/dist/cloudflare/index.d.cts +454 -0
  22. package/dist/cloudflare/index.d.ts +454 -0
  23. package/dist/cloudflare/index.js +822 -0
  24. package/dist/cloudflare/index.js.map +1 -0
  25. package/dist/codegen/index.d.cts +1 -1
  26. package/dist/codegen/index.d.ts +1 -1
  27. package/dist/editor/client/assets/index-Bq2bfzeY.js +411 -0
  28. package/dist/editor/client/index.html +1 -1
  29. package/dist/editor/server/index.mjs +6481 -6327
  30. package/dist/index.cjs +165 -44
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +14 -138
  33. package/dist/index.d.ts +14 -138
  34. package/dist/index.js +31 -22
  35. package/dist/index.js.map +1 -1
  36. package/dist/query-client/index.cjs +30 -28
  37. package/dist/query-client/index.cjs.map +1 -1
  38. package/dist/query-client/index.d.cts +2 -2
  39. package/dist/query-client/index.d.ts +2 -2
  40. package/dist/query-client/index.js +1 -1
  41. package/dist/react.cjs +0 -1
  42. package/dist/react.cjs.map +1 -1
  43. package/dist/react.js +0 -1
  44. package/dist/react.js.map +1 -1
  45. package/dist/scope-path-B1G3YiA7.d.cts +139 -0
  46. package/dist/scope-path-B1G3YiA7.d.ts +139 -0
  47. package/dist/{serialization-C6JNNOCS.js → serialization-ZZ7RSDRX.js} +2 -2
  48. package/dist/svelte.cjs +0 -2
  49. package/dist/svelte.cjs.map +1 -1
  50. package/dist/svelte.js +0 -2
  51. package/dist/svelte.js.map +1 -1
  52. package/dist/{types-BVtx9zLv.d.cts → types-DOemdlVA.d.cts} +20 -2
  53. package/dist/{types-BVtx9zLv.d.ts → types-DOemdlVA.d.ts} +20 -2
  54. package/package.json +39 -40
  55. package/dist/chunk-6OQW5OKO.js.map +0 -1
  56. package/dist/chunk-KFA7G37W.js.map +0 -1
  57. package/dist/chunk-WOAJRVHD.js +0 -699
  58. package/dist/chunk-WOAJRVHD.js.map +0 -1
  59. package/dist/chunk-YUXOALMR.js.map +0 -1
  60. package/dist/d1.cjs +0 -2416
  61. package/dist/d1.cjs.map +0 -1
  62. package/dist/d1.d.cts +0 -54
  63. package/dist/d1.d.ts +0 -54
  64. package/dist/d1.js +0 -75
  65. package/dist/d1.js.map +0 -1
  66. package/dist/do-sqlite.cjs.map +0 -1
  67. package/dist/do-sqlite.d.cts +0 -41
  68. package/dist/do-sqlite.d.ts +0 -41
  69. package/dist/do-sqlite.js +0 -78
  70. package/dist/do-sqlite.js.map +0 -1
  71. package/dist/editor/client/assets/index-tyFcX6qG.js +0 -411
  72. /package/dist/{serialization-C6JNNOCS.js.map → serialization-ZZ7RSDRX.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/svelte.ts"],"sourcesContent":["/**\n * Svelte 5 adapter for firegraph views.\n *\n * Wraps a Svelte component into a Web Component (HTMLElement) that satisfies\n * the firegraph `ViewComponentClass` contract. Import from `firegraph/svelte`:\n *\n * @example\n * ```ts\n * import { wrapSvelte } from 'firegraph/svelte';\n * import TaskCard from './TaskCard.svelte';\n *\n * export default [\n * wrapSvelte(TaskCard, { viewName: 'card', description: 'Compact task card' }),\n * ];\n * ```\n */\n\nimport type { ViewComponentClass } from './views.js';\n\n/** Metadata required for every firegraph view. */\nexport interface ViewMeta {\n /** Short identifier (e.g. 'card', 'detail'). */\n viewName: string;\n /** Optional human-readable description. */\n description?: string;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyClass = { new (...args: any[]): any };\n\n/**\n * Get HTMLElement from the runtime environment.\n * Returns a base class for view elements — works in both browser and Node.js\n * (where HTMLElement may be shimmed by the editor server).\n */\nfunction getBaseClass(): AnyClass {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const g = globalThis as any;\n return g.HTMLElement ?? class {};\n}\n\n/**\n * Wrap a Svelte 5 component into a firegraph `ViewComponentClass`.\n *\n * The returned class extends `HTMLElement` and lazily imports `svelte` at\n * mount time. Svelte is resolved from the project's own `node_modules` —\n * firegraph does not bundle or depend on Svelte itself.\n *\n * The Svelte component should accept a `data` prop:\n * ```svelte\n * <script>\n * let { data } = $props();\n * </script>\n * ```\n *\n * Props are updated by mutating the props object — Svelte 5's reactivity\n * system picks up the changes automatically.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function wrapSvelte(Component: any, meta: ViewMeta): ViewComponentClass {\n const Base = getBaseClass();\n\n const Cls = class extends Base {\n static viewName = meta.viewName;\n static description = meta.description;\n\n _data: Record<string, unknown> = {};\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _instance: any = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _props: any = null;\n _mounted = false;\n\n set data(v: Record<string, unknown>) {\n this._data = v;\n if (this._props) {\n // Svelte 5: mutating the props object triggers reactivity\n this._props.data = v;\n } else if (this._mounted) {\n this._mount();\n }\n }\n\n get data() {\n return this._data;\n }\n\n connectedCallback() {\n this._mounted = true;\n this._mount();\n }\n\n disconnectedCallback() {\n this._mounted = false;\n if (this._instance) {\n // Dynamic import — resolved from project's node_modules at runtime\n (Function('return import(\"svelte\")')() as Promise<{ unmount: Function }>).then(\n ({ unmount }) => {\n if (this._instance) {\n unmount(this._instance);\n this._instance = null;\n this._props = null;\n }\n },\n );\n }\n }\n\n async _mount() {\n // Dynamic import — resolved from project's node_modules at runtime\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const svelte: any = await (Function('return import(\"svelte\")')() as Promise<unknown>);\n if (!this._mounted) return; // disconnected while awaiting\n\n // Clean up previous instance\n if (this._instance) {\n svelte.unmount(this._instance);\n }\n\n // Svelte 5: pass a props object — mutating it later triggers re-renders\n this._props = { data: this._data };\n this._instance = svelte.mount(Component, {\n target: this,\n props: this._props,\n });\n }\n };\n\n return Cls as unknown as ViewComponentClass;\n}\n"],"mappings":";AAmCA,SAAS,eAAyB;AAEhC,QAAM,IAAI;AACV,SAAO,EAAE,eAAe,MAAM;AAAA,EAAC;AACjC;AAoBO,SAAS,WAAW,WAAgB,MAAoC;AAC7E,QAAM,OAAO,aAAa;AAE1B,QAAM,MAAM,cAAc,KAAK;AAAA,IAC7B,OAAO,WAAW,KAAK;AAAA,IACvB,OAAO,cAAc,KAAK;AAAA,IAE1B,QAAiC,CAAC;AAAA;AAAA,IAElC,YAAiB;AAAA;AAAA,IAEjB,SAAc;AAAA,IACd,WAAW;AAAA,IAEX,IAAI,KAAK,GAA4B;AACnC,WAAK,QAAQ;AACb,UAAI,KAAK,QAAQ;AAEf,aAAK,OAAO,OAAO;AAAA,MACrB,WAAW,KAAK,UAAU;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,IAEA,IAAI,OAAO;AACT,aAAO,KAAK;AAAA,IACd;AAAA,IAEA,oBAAoB;AAClB,WAAK,WAAW;AAChB,WAAK,OAAO;AAAA,IACd;AAAA,IAEA,uBAAuB;AACrB,WAAK,WAAW;AAChB,UAAI,KAAK,WAAW;AAElB,QAAC,SAAS,yBAAyB,EAAE,EAAqC;AAAA,UACxE,CAAC,EAAE,QAAQ,MAAM;AACf,gBAAI,KAAK,WAAW;AAClB,sBAAQ,KAAK,SAAS;AACtB,mBAAK,YAAY;AACjB,mBAAK,SAAS;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,SAAS;AAGb,YAAM,SAAc,MAAO,SAAS,yBAAyB,EAAE;AAC/D,UAAI,CAAC,KAAK,SAAU;AAGpB,UAAI,KAAK,WAAW;AAClB,eAAO,QAAQ,KAAK,SAAS;AAAA,MAC/B;AAGA,WAAK,SAAS,EAAE,MAAM,KAAK,MAAM;AACjC,WAAK,YAAY,OAAO,MAAM,WAAW;AAAA,QACvC,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/svelte.ts"],"sourcesContent":["/**\n * Svelte 5 adapter for firegraph views.\n *\n * Wraps a Svelte component into a Web Component (HTMLElement) that satisfies\n * the firegraph `ViewComponentClass` contract. Import from `firegraph/svelte`:\n *\n * @example\n * ```ts\n * import { wrapSvelte } from 'firegraph/svelte';\n * import TaskCard from './TaskCard.svelte';\n *\n * export default [\n * wrapSvelte(TaskCard, { viewName: 'card', description: 'Compact task card' }),\n * ];\n * ```\n */\n\nimport type { ViewComponentClass } from './views.js';\n\n/** Metadata required for every firegraph view. */\nexport interface ViewMeta {\n /** Short identifier (e.g. 'card', 'detail'). */\n viewName: string;\n /** Optional human-readable description. */\n description?: string;\n}\n\ntype AnyClass = { new (...args: any[]): any };\n\n/**\n * Get HTMLElement from the runtime environment.\n * Returns a base class for view elements — works in both browser and Node.js\n * (where HTMLElement may be shimmed by the editor server).\n */\nfunction getBaseClass(): AnyClass {\n const g = globalThis as any;\n return g.HTMLElement ?? class {};\n}\n\n/**\n * Wrap a Svelte 5 component into a firegraph `ViewComponentClass`.\n *\n * The returned class extends `HTMLElement` and lazily imports `svelte` at\n * mount time. Svelte is resolved from the project's own `node_modules` —\n * firegraph does not bundle or depend on Svelte itself.\n *\n * The Svelte component should accept a `data` prop:\n * ```svelte\n * <script>\n * let { data } = $props();\n * </script>\n * ```\n *\n * Props are updated by mutating the props object — Svelte 5's reactivity\n * system picks up the changes automatically.\n */\n\nexport function wrapSvelte(Component: any, meta: ViewMeta): ViewComponentClass {\n const Base = getBaseClass();\n\n const Cls = class extends Base {\n static viewName = meta.viewName;\n static description = meta.description;\n\n _data: Record<string, unknown> = {};\n\n _instance: any = null;\n\n _props: any = null;\n _mounted = false;\n\n set data(v: Record<string, unknown>) {\n this._data = v;\n if (this._props) {\n // Svelte 5: mutating the props object triggers reactivity\n this._props.data = v;\n } else if (this._mounted) {\n this._mount();\n }\n }\n\n get data() {\n return this._data;\n }\n\n connectedCallback() {\n this._mounted = true;\n this._mount();\n }\n\n disconnectedCallback() {\n this._mounted = false;\n if (this._instance) {\n // Dynamic import — resolved from project's node_modules at runtime\n (Function('return import(\"svelte\")')() as Promise<{ unmount: Function }>).then(\n ({ unmount }) => {\n if (this._instance) {\n unmount(this._instance);\n this._instance = null;\n this._props = null;\n }\n },\n );\n }\n }\n\n async _mount() {\n // Dynamic import — resolved from project's node_modules at runtime\n\n const svelte: any = await (Function('return import(\"svelte\")')() as Promise<unknown>);\n if (!this._mounted) return; // disconnected while awaiting\n\n // Clean up previous instance\n if (this._instance) {\n svelte.unmount(this._instance);\n }\n\n // Svelte 5: pass a props object — mutating it later triggers re-renders\n this._props = { data: this._data };\n this._instance = svelte.mount(Component, {\n target: this,\n props: this._props,\n });\n }\n };\n\n return Cls as unknown as ViewComponentClass;\n}\n"],"mappings":";AAkCA,SAAS,eAAyB;AAChC,QAAM,IAAI;AACV,SAAO,EAAE,eAAe,MAAM;AAAA,EAAC;AACjC;AAoBO,SAAS,WAAW,WAAgB,MAAoC;AAC7E,QAAM,OAAO,aAAa;AAE1B,QAAM,MAAM,cAAc,KAAK;AAAA,IAC7B,OAAO,WAAW,KAAK;AAAA,IACvB,OAAO,cAAc,KAAK;AAAA,IAE1B,QAAiC,CAAC;AAAA,IAElC,YAAiB;AAAA,IAEjB,SAAc;AAAA,IACd,WAAW;AAAA,IAEX,IAAI,KAAK,GAA4B;AACnC,WAAK,QAAQ;AACb,UAAI,KAAK,QAAQ;AAEf,aAAK,OAAO,OAAO;AAAA,MACrB,WAAW,KAAK,UAAU;AACxB,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,IAEA,IAAI,OAAO;AACT,aAAO,KAAK;AAAA,IACd;AAAA,IAEA,oBAAoB;AAClB,WAAK,WAAW;AAChB,WAAK,OAAO;AAAA,IACd;AAAA,IAEA,uBAAuB;AACrB,WAAK,WAAW;AAChB,UAAI,KAAK,WAAW;AAElB,QAAC,SAAS,yBAAyB,EAAE,EAAqC;AAAA,UACxE,CAAC,EAAE,QAAQ,MAAM;AACf,gBAAI,KAAK,WAAW;AAClB,sBAAQ,KAAK,SAAS;AACtB,mBAAK,YAAY;AACjB,mBAAK,SAAS;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,SAAS;AAGb,YAAM,SAAc,MAAO,SAAS,yBAAyB,EAAE;AAC/D,UAAI,CAAC,KAAK,SAAU;AAGpB,UAAI,KAAK,WAAW;AAClB,eAAO,QAAQ,KAAK,SAAS;AAAA,MAC/B;AAGA,WAAK,SAAS,EAAE,MAAM,KAAK,MAAM;AACjC,WAAK,YAAY,OAAO,MAAM,WAAW;AAAA,QACvC,QAAQ;AAAA,QACR,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -1,4 +1,4 @@
1
- import { Timestamp, FieldValue, WhereFilterOp } from '@google-cloud/firestore';
1
+ import { WhereFilterOp, Timestamp, FieldValue } from '@google-cloud/firestore';
2
2
 
3
3
  /**
4
4
  * Firegraph Configuration — project-level config file support.
@@ -16,6 +16,7 @@ import { Timestamp, FieldValue, WhereFilterOp } from '@google-cloud/firestore';
16
16
  * });
17
17
  * ```
18
18
  */
19
+
19
20
  /** Display contexts where views can appear. */
20
21
  type ViewContext = 'listing' | 'detail' | 'inline';
21
22
  /** View resolution configuration for a single entity type. */
@@ -481,6 +482,23 @@ interface GraphRegistry {
481
482
  lookup(aType: string, axbType: string, bType: string): RegistryEntry | undefined;
482
483
  /** Return all entries matching the given axbType (edge relation name). */
483
484
  lookupByAxbType(axbType: string): ReadonlyArray<RegistryEntry>;
485
+ /**
486
+ * Return every edge entry originating from `aType` that has `targetGraph`
487
+ * set — i.e. the direct subgraph children of nodes of this type.
488
+ *
489
+ * Used by backends that need to enumerate a node's subgraph DOs without
490
+ * walking the graph. Each returned entry carries both `axbType` (the edge
491
+ * label that introduces the subgraph) and `targetGraph` (the subgraph
492
+ * segment name).
493
+ *
494
+ * Entries are deduplicated by `targetGraph` alone — the physical subgraph
495
+ * store is addressed by `(parentUid, targetGraph)`, so multiple edge
496
+ * relations (distinct `axbType` or `bType`) pointing into the same segment
497
+ * collapse to a single representative entry. The first-declared entry
498
+ * wins the collision. Callers only care about the subgraph name, not the
499
+ * originating relation or target node type.
500
+ */
501
+ getSubgraphTopology(aType: string): ReadonlyArray<RegistryEntry>;
484
502
  entries(): ReadonlyArray<RegistryEntry>;
485
503
  }
486
504
  interface GraphReader {
@@ -641,4 +659,4 @@ interface CascadeResult extends BulkResult {
641
659
  nodeDeleted: boolean;
642
660
  }
643
661
 
644
- export { type TraversalOptions as A, type BulkOptions as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, type TraversalResult as I, type ViewDefaultsConfig as J, type ViewResolverConfig as K, defineConfig as L, type MigrationExecutor as M, type NodeTypeData as N, resolveView as O, type QueryFilter as Q, type RegistryEntry as R, type StoredGraphRecord as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type QueryOptions as c, type GraphReader as d, type BulkResult as e, type DiscoveryResult as f, type GraphRegistry as g, type MigrationWriteBack as h, type MigrationStep as i, type QueryPlan as j, type FindNodesParams as k, type GraphRecord as l, type MigrationFn as m, type StoredMigrationStep as n, type BulkBatchError as o, type BulkProgress as p, type DefineTypeOptions as q, type DiscoveredEntity as r, type EdgeTypeData as s, type FiregraphConfig as t, type GraphBatch as u, type GraphTransaction as v, type GraphWriter as w, type HopResult as x, type QueryMode as y, type ScanProtection as z };
662
+ export { type TraversalOptions as A, type BulkBatchError as B, type CascadeResult as C, type DynamicGraphClient as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, type TraversalResult as I, type ViewDefaultsConfig as J, type ViewResolverConfig as K, defineConfig as L, type MigrationExecutor as M, type NodeTypeData as N, resolveView as O, type QueryPlan as Q, type RegistryEntry as R, type StoredGraphRecord as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type GraphClient as a, type DiscoveryResult as b, type GraphRegistry as c, type GraphReader as d, type DynamicRegistryConfig as e, type MigrationWriteBack as f, type MigrationStep as g, type FindNodesParams as h, type QueryFilter as i, type GraphRecord as j, type MigrationFn as k, type StoredMigrationStep as l, type BulkOptions as m, type BulkProgress as n, type BulkResult as o, type DefineTypeOptions as p, type DiscoveredEntity as q, type EdgeTypeData as r, type FiregraphConfig as s, type GraphBatch as t, type GraphTransaction as u, type GraphWriter as v, type HopResult as w, type QueryMode as x, type QueryOptions as y, type ScanProtection as z };
@@ -1,4 +1,4 @@
1
- import { Timestamp, FieldValue, WhereFilterOp } from '@google-cloud/firestore';
1
+ import { WhereFilterOp, Timestamp, FieldValue } from '@google-cloud/firestore';
2
2
 
3
3
  /**
4
4
  * Firegraph Configuration — project-level config file support.
@@ -16,6 +16,7 @@ import { Timestamp, FieldValue, WhereFilterOp } from '@google-cloud/firestore';
16
16
  * });
17
17
  * ```
18
18
  */
19
+
19
20
  /** Display contexts where views can appear. */
20
21
  type ViewContext = 'listing' | 'detail' | 'inline';
21
22
  /** View resolution configuration for a single entity type. */
@@ -481,6 +482,23 @@ interface GraphRegistry {
481
482
  lookup(aType: string, axbType: string, bType: string): RegistryEntry | undefined;
482
483
  /** Return all entries matching the given axbType (edge relation name). */
483
484
  lookupByAxbType(axbType: string): ReadonlyArray<RegistryEntry>;
485
+ /**
486
+ * Return every edge entry originating from `aType` that has `targetGraph`
487
+ * set — i.e. the direct subgraph children of nodes of this type.
488
+ *
489
+ * Used by backends that need to enumerate a node's subgraph DOs without
490
+ * walking the graph. Each returned entry carries both `axbType` (the edge
491
+ * label that introduces the subgraph) and `targetGraph` (the subgraph
492
+ * segment name).
493
+ *
494
+ * Entries are deduplicated by `targetGraph` alone — the physical subgraph
495
+ * store is addressed by `(parentUid, targetGraph)`, so multiple edge
496
+ * relations (distinct `axbType` or `bType`) pointing into the same segment
497
+ * collapse to a single representative entry. The first-declared entry
498
+ * wins the collision. Callers only care about the subgraph name, not the
499
+ * originating relation or target node type.
500
+ */
501
+ getSubgraphTopology(aType: string): ReadonlyArray<RegistryEntry>;
484
502
  entries(): ReadonlyArray<RegistryEntry>;
485
503
  }
486
504
  interface GraphReader {
@@ -641,4 +659,4 @@ interface CascadeResult extends BulkResult {
641
659
  nodeDeleted: boolean;
642
660
  }
643
661
 
644
- export { type TraversalOptions as A, type BulkOptions as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, type TraversalResult as I, type ViewDefaultsConfig as J, type ViewResolverConfig as K, defineConfig as L, type MigrationExecutor as M, type NodeTypeData as N, resolveView as O, type QueryFilter as Q, type RegistryEntry as R, type StoredGraphRecord as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type QueryOptions as c, type GraphReader as d, type BulkResult as e, type DiscoveryResult as f, type GraphRegistry as g, type MigrationWriteBack as h, type MigrationStep as i, type QueryPlan as j, type FindNodesParams as k, type GraphRecord as l, type MigrationFn as m, type StoredMigrationStep as n, type BulkBatchError as o, type BulkProgress as p, type DefineTypeOptions as q, type DiscoveredEntity as r, type EdgeTypeData as s, type FiregraphConfig as t, type GraphBatch as u, type GraphTransaction as v, type GraphWriter as w, type HopResult as x, type QueryMode as y, type ScanProtection as z };
662
+ export { type TraversalOptions as A, type BulkBatchError as B, type CascadeResult as C, type DynamicGraphClient as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, type TraversalResult as I, type ViewDefaultsConfig as J, type ViewResolverConfig as K, defineConfig as L, type MigrationExecutor as M, type NodeTypeData as N, resolveView as O, type QueryPlan as Q, type RegistryEntry as R, type StoredGraphRecord as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type GraphClient as a, type DiscoveryResult as b, type GraphRegistry as c, type GraphReader as d, type DynamicRegistryConfig as e, type MigrationWriteBack as f, type MigrationStep as g, type FindNodesParams as h, type QueryFilter as i, type GraphRecord as j, type MigrationFn as k, type StoredMigrationStep as l, type BulkOptions as m, type BulkProgress as n, type BulkResult as o, type DefineTypeOptions as p, type DiscoveredEntity as q, type EdgeTypeData as r, type FiregraphConfig as s, type GraphBatch as t, type GraphTransaction as u, type GraphWriter as v, type HopResult as w, type QueryMode as x, type QueryOptions as y, type ScanProtection as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typicalday/firegraph",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Generic Firestore adjacency graph client with smart query planning",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -47,24 +47,24 @@
47
47
  "default": "./dist/query-client/index.cjs"
48
48
  }
49
49
  },
50
- "./d1": {
50
+ "./cloudflare": {
51
51
  "import": {
52
- "types": "./dist/d1.d.ts",
53
- "default": "./dist/d1.js"
52
+ "types": "./dist/cloudflare/index.d.ts",
53
+ "default": "./dist/cloudflare/index.js"
54
54
  },
55
55
  "require": {
56
- "types": "./dist/d1.d.cts",
57
- "default": "./dist/d1.cjs"
56
+ "types": "./dist/cloudflare/index.d.cts",
57
+ "default": "./dist/cloudflare/index.cjs"
58
58
  }
59
59
  },
60
- "./do-sqlite": {
60
+ "./backend": {
61
61
  "import": {
62
- "types": "./dist/do-sqlite.d.ts",
63
- "default": "./dist/do-sqlite.js"
62
+ "types": "./dist/backend.d.ts",
63
+ "default": "./dist/backend.js"
64
64
  },
65
65
  "require": {
66
- "types": "./dist/do-sqlite.d.cts",
67
- "default": "./dist/do-sqlite.cjs"
66
+ "types": "./dist/backend.d.cts",
67
+ "default": "./dist/backend.cjs"
68
68
  }
69
69
  }
70
70
  },
@@ -76,33 +76,6 @@
76
76
  "bin",
77
77
  "skills"
78
78
  ],
79
- "scripts": {
80
- "prepare": "husky && tsup && (npm run build:editor || true)",
81
- "format": "prettier --write .",
82
- "format:check": "prettier --check .",
83
- "lint": "eslint .",
84
- "lint:fix": "eslint --fix .",
85
- "build": "tsup",
86
- "build:editor:client": "cd editor && npx vite build",
87
- "build:editor:server": "node editor/build-server.mjs",
88
- "build:editor": "npm run build:editor:client && npm run build:editor:server",
89
- "build:all": "npm run build && npm run build:editor",
90
- "dev:editor": "cd editor && npm run dev",
91
- "typecheck": "tsc --noEmit",
92
- "test": "vitest run",
93
- "test:unit": "vitest run tests/unit/",
94
- "test:integration": "vitest run tests/integration/",
95
- "test:sqlite:integration": "BACKEND=sqlite vitest run tests/integration/",
96
- "test:emulator": "bash tests/scripts/test-with-emulator.sh",
97
- "test:emulator:unit": "bash tests/scripts/test-with-emulator.sh tests/unit/",
98
- "test:emulator:integration": "bash tests/scripts/test-with-emulator.sh tests/integration/",
99
- "test:coverage": "vitest run --coverage",
100
- "test:watch": "vitest",
101
- "emulator:start": "cd tests/emulator && firebase emulators:start -P demo-firegraph",
102
- "emulator:stop": "npx kill-port -y 4188 8188",
103
- "test:pipeline": "vitest run tests/pipeline/ --config tests/pipeline/vitest.config.ts",
104
- "test:pipeline:integration": "vitest run --config tests/integration-pipeline/vitest.config.ts"
105
- },
106
79
  "peerDependencies": {
107
80
  "@google-cloud/firestore": "^8.0.0",
108
81
  "react": "^18.0.0 || ^19.0.0",
@@ -139,6 +112,7 @@
139
112
  "better-sqlite3": "^12.9.0",
140
113
  "eslint": "^10.1.0",
141
114
  "eslint-config-prettier": "^10.1.8",
115
+ "eslint-plugin-react-hooks": "^7.1.0",
142
116
  "eslint-plugin-simple-import-sort": "^12.1.1",
143
117
  "husky": "^9.1.7",
144
118
  "json-schema-to-typescript": "^15.0.4",
@@ -159,5 +133,30 @@
159
133
  "engines": {
160
134
  "node": ">=18"
161
135
  },
162
- "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
163
- }
136
+ "scripts": {
137
+ "format": "prettier --write .",
138
+ "format:check": "prettier --check .",
139
+ "lint": "eslint .",
140
+ "lint:fix": "eslint --fix .",
141
+ "build": "tsup",
142
+ "build:editor:client": "cd editor && npx vite build",
143
+ "build:editor:server": "node editor/build-server.mjs",
144
+ "build:editor": "npm run build:editor:client && npm run build:editor:server",
145
+ "build:all": "npm run build && npm run build:editor",
146
+ "dev:editor": "cd editor && npm run dev",
147
+ "typecheck": "tsc --noEmit",
148
+ "test": "vitest run",
149
+ "test:unit": "vitest run tests/unit/",
150
+ "test:integration": "vitest run tests/integration/",
151
+ "test:sqlite:integration": "BACKEND=sqlite vitest run tests/integration/",
152
+ "test:emulator": "bash tests/scripts/test-with-emulator.sh",
153
+ "test:emulator:unit": "bash tests/scripts/test-with-emulator.sh tests/unit/",
154
+ "test:emulator:integration": "bash tests/scripts/test-with-emulator.sh tests/integration/",
155
+ "test:coverage": "vitest run --coverage",
156
+ "test:watch": "vitest",
157
+ "emulator:start": "cd tests/emulator && firebase emulators:start -P demo-firegraph",
158
+ "emulator:stop": "npx kill-port -y 4188 8188",
159
+ "test:pipeline": "vitest run tests/pipeline/ --config tests/pipeline/vitest.config.ts",
160
+ "test:pipeline:integration": "vitest run --config tests/integration-pipeline/vitest.config.ts"
161
+ }
162
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/serialization.ts"],"sourcesContent":["/**\n * Firestore-aware serialization for the sandbox migration pipeline.\n *\n * Firestore documents can contain special types (Timestamp, GeoPoint,\n * VectorValue, DocumentReference) that don't survive plain JSON\n * round-tripping. This module provides tagged serialization: Firestore\n * types are wrapped in tagged plain objects before JSON marshaling and\n * reconstructed after.\n *\n * Only used by the `defaultExecutor` sandbox path. Static migrations\n * (in-memory functions) receive raw Firestore objects directly.\n */\n\nimport { Timestamp, GeoPoint, FieldValue } from '@google-cloud/firestore';\nimport type { Firestore, DocumentReference } from '@google-cloud/firestore';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Sentinel key used to tag serialized Firestore types. */\nexport const SERIALIZATION_TAG = '__firegraph_ser__' as const;\n\n/** Known discriminator values for tagged types. */\nconst KNOWN_TYPES = new Set(['Timestamp', 'GeoPoint', 'VectorValue', 'DocumentReference']);\n\n// One-time warning for DocumentReference deserialization without db\nlet _docRefWarned = false;\n\n// ---------------------------------------------------------------------------\n// Type guard\n// ---------------------------------------------------------------------------\n\n/** Check if a value is a tagged serialized Firestore type. */\nexport function isTaggedValue(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n const tag = (value as Record<string, unknown>)[SERIALIZATION_TAG];\n return typeof tag === 'string' && KNOWN_TYPES.has(tag);\n}\n\n// ---------------------------------------------------------------------------\n// Detection helpers\n// ---------------------------------------------------------------------------\n\nfunction isTimestamp(value: unknown): value is Timestamp {\n return value instanceof Timestamp;\n}\n\nfunction isGeoPoint(value: unknown): value is GeoPoint {\n return value instanceof GeoPoint;\n}\n\nfunction isDocumentReference(value: unknown): value is DocumentReference {\n // Duck-type check: DocumentReference has path (string) and firestore properties\n if (value === null || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return (\n typeof v.path === 'string' &&\n v.firestore !== undefined &&\n typeof v.id === 'string' &&\n v.constructor?.name === 'DocumentReference'\n );\n}\n\nfunction isVectorValue(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n const v = value as Record<string, unknown>;\n return (\n v.constructor?.name === 'VectorValue' &&\n Array.isArray((v as Record<string, unknown>)._values)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Serialize\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively walk a data object and replace Firestore types with tagged\n * plain objects suitable for JSON serialization.\n *\n * Returns a new object tree — the input is never mutated.\n */\nexport function serializeFirestoreTypes(\n data: Record<string, unknown>,\n): Record<string, unknown> {\n return serializeValue(data) as Record<string, unknown>;\n}\n\nfunction serializeValue(value: unknown): unknown {\n // Primitives\n if (value === null || value === undefined) return value;\n if (typeof value !== 'object') return value;\n\n // Firestore types (check before generic object/array)\n if (isTimestamp(value)) {\n return { [SERIALIZATION_TAG]: 'Timestamp', seconds: value.seconds, nanoseconds: value.nanoseconds };\n }\n if (isGeoPoint(value)) {\n return { [SERIALIZATION_TAG]: 'GeoPoint', latitude: value.latitude, longitude: value.longitude };\n }\n if (isDocumentReference(value)) {\n return { [SERIALIZATION_TAG]: 'DocumentReference', path: (value as DocumentReference).path };\n }\n if (isVectorValue(value)) {\n // Prefer toArray() (public API) over _values (private internal property)\n const v = value as Record<string, unknown>;\n const values = typeof v.toArray === 'function'\n ? (v.toArray as () => number[])()\n : (v._values as number[]);\n return { [SERIALIZATION_TAG]: 'VectorValue', values: [...values] };\n }\n\n // Arrays\n if (Array.isArray(value)) {\n return value.map(serializeValue);\n }\n\n // Plain objects — recurse\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n result[key] = serializeValue((value as Record<string, unknown>)[key]);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Deserialize\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively walk a data object and reconstruct Firestore types from\n * tagged plain objects.\n *\n * @param data - The data to deserialize (typically from JSON.parse)\n * @param db - Optional Firestore instance for DocumentReference reconstruction.\n * If not provided, tagged DocumentReferences are left as-is with a one-time warning.\n *\n * Returns a new object tree — the input is never mutated.\n */\nexport function deserializeFirestoreTypes(\n data: Record<string, unknown>,\n db?: Firestore,\n): Record<string, unknown> {\n return deserializeValue(data, db) as Record<string, unknown>;\n}\n\nfunction deserializeValue(value: unknown, db?: Firestore): unknown {\n if (value === null || value === undefined) return value;\n if (typeof value !== 'object') return value;\n\n // Short-circuit for values that are already real Firestore types.\n // This makes deserializeFirestoreTypes idempotent — safe to call on data\n // that has already been deserialized (e.g., write-back after defaultExecutor\n // already reconstructed types, or static migrations that return raw types).\n if (isTimestamp(value) || isGeoPoint(value) || isDocumentReference(value) || isVectorValue(value)) {\n return value;\n }\n\n // Arrays\n if (Array.isArray(value)) {\n return value.map((v) => deserializeValue(v, db));\n }\n\n const obj = value as Record<string, unknown>;\n\n // Check for tagged Firestore type\n if (isTaggedValue(obj)) {\n const tag = obj[SERIALIZATION_TAG] as string;\n\n switch (tag) {\n case 'Timestamp':\n // Validate expected fields before reconstruction\n if (typeof obj.seconds !== 'number' || typeof obj.nanoseconds !== 'number') return obj;\n return new Timestamp(obj.seconds, obj.nanoseconds);\n\n case 'GeoPoint':\n if (typeof obj.latitude !== 'number' || typeof obj.longitude !== 'number') return obj;\n return new GeoPoint(obj.latitude, obj.longitude);\n\n case 'VectorValue':\n if (!Array.isArray(obj.values)) return obj;\n return FieldValue.vector(obj.values as number[]);\n\n case 'DocumentReference':\n if (typeof obj.path !== 'string') return obj;\n if (db) {\n return db.doc(obj.path);\n }\n // No db available — leave as tagged object with one-time warning\n if (!_docRefWarned) {\n _docRefWarned = true;\n console.warn(\n '[firegraph] DocumentReference encountered during migration deserialization ' +\n 'but no Firestore instance available. The reference will remain as a tagged ' +\n 'object with its path. Enable write-back for full reconstruction.',\n );\n }\n return obj;\n\n default:\n // Unknown tag — leave as-is (forward compatibility)\n return obj;\n }\n }\n\n // Plain object — recurse\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n result[key] = deserializeValue(obj[key], db);\n }\n return result;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/query-client/client.ts","../src/query-client/shaping.ts","../src/query-client/config.ts","../src/query-client/cli.ts"],"sourcesContent":["import http from 'node:http';\nimport type {\n QueryClientOptions,\n SchemaResult,\n GetNodeDetailInput,\n NodeDetailResult,\n GetNodesInput,\n GetNodesResult,\n GetEdgesInput,\n GetEdgesResult,\n TraverseInput,\n TraverseResult,\n TraverseHopResult,\n SearchInput,\n SearchResult,\n SummarizedRecord,\n SummarizedEdge,\n} from './types.js';\nimport { summarizeRecord, summarizeEdge } from './shaping.js';\nimport { readEditorPort } from './config.js';\n\n// --- Error ---\n\nexport type QueryClientErrorCode = 'VALIDATION_ERROR' | 'CONNECTION_FAILED' | 'SERVER_ERROR';\n\nexport class QueryClientError extends Error {\n constructor(\n message: string,\n public readonly code: QueryClientErrorCode,\n ) {\n super(message);\n this.name = 'QueryClientError';\n }\n}\n\n// --- Validation helpers ---\n\nfunction requireString(value: unknown, name: string): asserts value is string {\n if (typeof value !== 'string' || value.length === 0) {\n throw new QueryClientError(`${name} must be a non-empty string`, 'VALIDATION_ERROR');\n }\n}\n\nfunction clampInt(value: number | undefined, min: number, max: number, fallback: number): number {\n if (value == null) return fallback;\n if (!Number.isInteger(value)) {\n throw new QueryClientError(`limit must be an integer`, 'VALIDATION_ERROR');\n }\n return Math.max(min, Math.min(max, value));\n}\n\nfunction validateSortDir(dir: string | undefined): void {\n if (dir != null && dir !== 'asc' && dir !== 'desc') {\n throw new QueryClientError(`sortDir must be 'asc' or 'desc'`, 'VALIDATION_ERROR');\n }\n}\n\n// --- HTTP helpers ---\n\nfunction httpGet(url: string): Promise<string> {\n return new Promise((resolve, reject) => {\n http\n .get(url, (res) => {\n let body = '';\n res.on('data', (c: string) => (body += c));\n res.on('end', () => resolve(body));\n })\n .on('error', (err) => {\n reject(new QueryClientError(`Connection failed: ${err.message}`, 'CONNECTION_FAILED'));\n });\n });\n}\n\nfunction httpPost(url: string, payload: string): Promise<string> {\n const parsed = new URL(url);\n return new Promise((resolve, reject) => {\n const req = http.request(\n {\n hostname: parsed.hostname,\n port: parsed.port,\n path: parsed.pathname,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(payload),\n },\n },\n (res) => {\n let body = '';\n res.on('data', (c: string) => (body += c));\n res.on('end', () => resolve(body));\n },\n );\n req.on('error', (err) => {\n reject(new QueryClientError(`Connection failed: ${err.message}`, 'CONNECTION_FAILED'));\n });\n req.write(payload);\n req.end();\n });\n}\n\nfunction parseTrpcResponse(raw: string, procedure: string): unknown {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new QueryClientError(\n `Invalid JSON from ${procedure}: ${raw.slice(0, 200)}`,\n 'SERVER_ERROR',\n );\n }\n if (parsed.error) {\n const msg =\n typeof parsed.error === 'object' && parsed.error !== null\n ? (parsed.error as Record<string, unknown>).message ?? JSON.stringify(parsed.error)\n : String(parsed.error);\n throw new QueryClientError(`Server error from ${procedure}: ${msg}`, 'SERVER_ERROR');\n }\n return (parsed.result as Record<string, unknown>)?.data ?? parsed;\n}\n\n// --- Client ---\n\nexport class QueryClient {\n private readonly baseUrl: string;\n\n constructor(options?: QueryClientOptions) {\n const host = options?.host ?? 'localhost';\n const port = options?.port ?? readEditorPort();\n this.baseUrl = `http://${host}:${port}/api/trpc`;\n }\n\n private async query(procedure: string, input?: unknown): Promise<unknown> {\n const qs =\n input != null ? `?input=${encodeURIComponent(JSON.stringify(input))}` : '';\n const url = `${this.baseUrl}/${procedure}${qs}`;\n const raw = await httpGet(url);\n return parseTrpcResponse(raw, procedure);\n }\n\n private async mutate(procedure: string, input: unknown): Promise<unknown> {\n const url = `${this.baseUrl}/${procedure}`;\n const raw = await httpPost(url, JSON.stringify(input));\n return parseTrpcResponse(raw, procedure);\n }\n\n // --- Public API ---\n\n async getSchema(): Promise<SchemaResult> {\n const data = (await this.query('getSchema')) as Record<string, unknown>;\n return {\n nodeTypes: ((data.nodeTypes as unknown[]) ?? []).map(\n (t) => (typeof t === 'object' && t !== null ? (t as Record<string, unknown>).type : t) as string,\n ),\n edgeTypes: ((data.edgeTypes as unknown[]) ?? []).map((t) => {\n const e = t as Record<string, unknown>;\n return {\n relation: e.axbType as string,\n from: e.aType as string,\n to: e.bType as string,\n inverseLabel: (e.inverseLabel as string) ?? null,\n };\n }),\n };\n }\n\n async getNodeDetail(input: GetNodeDetailInput): Promise<NodeDetailResult> {\n requireString(input.uid, 'uid');\n const data = (await this.query('getNodeDetail', { uid: input.uid })) as Record<string, unknown>;\n return {\n node: summarizeRecord(data.node as Record<string, unknown> | null),\n outEdges: ((data.outEdges as Record<string, unknown>[]) ?? []).map(summarizeEdge).filter(Boolean) as SummarizedEdge[],\n inEdges: ((data.inEdges as Record<string, unknown>[]) ?? []).map(summarizeEdge).filter(Boolean) as SummarizedEdge[],\n };\n }\n\n async getNodes(input: GetNodesInput): Promise<GetNodesResult> {\n const limit = clampInt(input.limit, 1, 200, 25);\n validateSortDir(input.sortDir);\n const data = (await this.query('getNodes', {\n type: input.type,\n limit,\n startAfter: input.startAfter,\n sortBy: input.sortBy,\n sortDir: input.sortDir,\n where: input.where,\n })) as Record<string, unknown>;\n return {\n nodes: ((data.nodes as Record<string, unknown>[]) ?? []).map(summarizeRecord).filter(Boolean) as SummarizedRecord[],\n hasMore: (data.hasMore as boolean) ?? false,\n nextCursor: data.nextCursor as string | null | undefined,\n };\n }\n\n async getEdges(input: GetEdgesInput): Promise<GetEdgesResult> {\n const hasFilter = input.aType || input.aUid || input.axbType || input.bType || input.bUid || (input.where && input.where.length > 0);\n if (!hasFilter) {\n throw new QueryClientError(\n 'getEdges requires at least one filter field (aType, aUid, axbType, bType, bUid, or where)',\n 'VALIDATION_ERROR',\n );\n }\n const limit = clampInt(input.limit, 1, 200, 25);\n validateSortDir(input.sortDir);\n const data = (await this.query('getEdges', {\n aType: input.aType,\n aUid: input.aUid,\n axbType: input.axbType,\n bType: input.bType,\n bUid: input.bUid,\n limit,\n startAfter: input.startAfter,\n sortBy: input.sortBy,\n sortDir: input.sortDir,\n where: input.where,\n })) as Record<string, unknown>;\n return {\n edges: ((data.edges as Record<string, unknown>[]) ?? []).map(summarizeEdge).filter(Boolean) as SummarizedEdge[],\n hasMore: (data.hasMore as boolean) ?? false,\n nextCursor: data.nextCursor as string | null | undefined,\n };\n }\n\n async traverse(input: TraverseInput): Promise<TraverseResult> {\n requireString(input.startUid, 'startUid');\n if (!input.hops || input.hops.length === 0) {\n throw new QueryClientError('traverse requires at least one hop', 'VALIDATION_ERROR');\n }\n for (let i = 0; i < input.hops.length; i++) {\n const hop = input.hops[i];\n requireString(hop.axbType, `hops[${i}].axbType`);\n if (hop.direction != null && hop.direction !== 'forward' && hop.direction !== 'reverse') {\n throw new QueryClientError(\n `hops[${i}].direction must be 'forward' or 'reverse'`,\n 'VALIDATION_ERROR',\n );\n }\n if (hop.limit != null && (!Number.isInteger(hop.limit) || hop.limit < 1)) {\n throw new QueryClientError(\n `hops[${i}].limit must be a positive integer`,\n 'VALIDATION_ERROR',\n );\n }\n }\n if (input.maxReads != null && (!Number.isInteger(input.maxReads) || input.maxReads < 1)) {\n throw new QueryClientError('maxReads must be a positive integer', 'VALIDATION_ERROR');\n }\n if (input.concurrency != null && (!Number.isInteger(input.concurrency) || input.concurrency < 1)) {\n throw new QueryClientError('concurrency must be a positive integer', 'VALIDATION_ERROR');\n }\n\n const data = (await this.mutate('traverse', input)) as Record<string, unknown>;\n return {\n hops: ((data.hops as Record<string, unknown>[]) ?? []).map((h): TraverseHopResult => ({\n relation: h.axbType as string,\n direction: h.direction as string,\n depth: h.depth as number,\n edgeCount: ((h.edges as unknown[]) ?? []).length,\n edges: ((h.edges as Record<string, unknown>[]) ?? []).map(summarizeEdge).filter(Boolean) as SummarizedEdge[],\n truncated: (h.truncated as boolean) ?? false,\n })),\n totalReads: (data.totalReads as number) ?? 0,\n truncated: (data.truncated as boolean) ?? false,\n };\n }\n\n async search(input: SearchInput): Promise<SearchResult> {\n requireString(input.q, 'q');\n const limit = clampInt(input.limit, 1, 50, 20);\n const data = (await this.query('search', { q: input.q, limit })) as Record<string, unknown>;\n return {\n results: ((data.results as Record<string, unknown>[]) ?? []).map((r) => {\n const base = summarizeRecord(r);\n if (!base) return null;\n return {\n ...base,\n matchType: (r._matchType as string) ?? null,\n };\n }).filter(Boolean) as (SummarizedRecord & { matchType: string | null })[],\n };\n }\n}\n","import type { SummarizedRecord, SummarizedEdge } from './types.js';\n\nexport function summarizeRecord(r: Record<string, unknown> | null): SummarizedRecord | null {\n if (!r) return null;\n const out: SummarizedRecord = { type: r.aType as string, uid: r.aUid as string };\n const data = r.data as Record<string, unknown> | undefined;\n if (data && typeof data === 'object' && Object.keys(data).length > 0) {\n out.data = data;\n }\n return out;\n}\n\nexport function summarizeEdge(r: Record<string, unknown> | null): SummarizedEdge | null {\n if (!r) return null;\n const out: SummarizedEdge = {\n fromType: r.aType as string,\n fromUid: r.aUid as string,\n relation: r.axbType as string,\n toType: r.bType as string,\n toUid: r.bUid as string,\n };\n const data = r.data as Record<string, unknown> | undefined;\n if (data && typeof data === 'object' && Object.keys(data).length > 0) {\n out.data = data;\n }\n return out;\n}\n","import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nconst CONFIG_FILES = ['firegraph.config.ts', 'firegraph.config.js', 'firegraph.config.mjs'];\nconst DEFAULT_PORT = 3884;\n\n/**\n * Read the editor port from firegraph config files using regex.\n * Zero-dependency — no jiti needed.\n */\nexport function readEditorPort(cwd?: string): number {\n const dir = cwd ?? process.cwd();\n for (const name of CONFIG_FILES) {\n try {\n const content = readFileSync(join(dir, name), 'utf8');\n const editorBlock = content.match(/editor\\s*:\\s*\\{[^}]*\\}/s)?.[0] ?? '';\n const portMatch = editorBlock.match(/port\\s*:\\s*(\\d+)/);\n if (portMatch) return parseInt(portMatch[1], 10);\n } catch {\n continue;\n }\n }\n return DEFAULT_PORT;\n}\n","import { QueryClient, QueryClientError } from './client.js';\nimport type { TraverseInput } from './types.js';\n\n// --- Argument parsing ---\n\ninterface ParsedArgs {\n flags: Record<string, string>;\n positional: string[];\n}\n\nfunction parseFlags(args: string[]): ParsedArgs {\n const flags: Record<string, string> = {};\n const positional: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i].startsWith('--')) {\n const key = args[i].slice(2);\n const next = args[i + 1];\n if (next && !next.startsWith('--')) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = 'true';\n }\n } else {\n positional.push(args[i]);\n }\n }\n return { flags, positional };\n}\n\n// --- CLI runner ---\n\nexport async function runQueryCli(argv: string[]): Promise<void> {\n const command = argv[0];\n const rest = argv.slice(1);\n const { flags, positional } = parseFlags(rest);\n\n const port = flags.port ? parseInt(flags.port, 10) : undefined;\n const host = flags.host ?? undefined;\n const client = new QueryClient({ port, host });\n\n try {\n let result: unknown;\n\n switch (command) {\n case 'schema':\n result = await client.getSchema();\n break;\n\n case 'get':\n if (!positional[0]) {\n die('Usage: firegraph query get <uid>');\n }\n result = await client.getNodeDetail({ uid: positional[0] });\n break;\n\n case 'find-nodes': {\n if (!positional[0]) {\n die('Usage: firegraph query find-nodes <type> [--limit N]');\n }\n result = await client.getNodes({\n type: positional[0],\n limit: flags.limit ? parseInt(flags.limit, 10) : undefined,\n });\n break;\n }\n\n case 'find-edges': {\n result = await client.getEdges({\n aType: flags.aType,\n aUid: flags.aUid,\n axbType: flags.axbType,\n bType: flags.bType,\n bUid: flags.bUid,\n limit: flags.limit ? parseInt(flags.limit, 10) : undefined,\n });\n break;\n }\n\n case 'traverse': {\n const jsonStr = positional.join(' ');\n if (!jsonStr) {\n die(\n 'Usage: firegraph query traverse \\'<JSON>\\'\\n\\n' +\n 'JSON shape:\\n' +\n '{\\n' +\n ' \"startUid\": \"nodeUid\",\\n' +\n ' \"hops\": [\\n' +\n ' {\\n' +\n ' \"axbType\": \"relationName\",\\n' +\n ' \"direction\": \"forward\" | \"reverse\",\\n' +\n ' \"limit\": 10,\\n' +\n ' \"aType\": \"filterSourceType\",\\n' +\n ' \"bType\": \"filterTargetType\",\\n' +\n ' \"orderBy\": { \"field\": \"data.name\", \"direction\": \"asc\" },\\n' +\n ' \"where\": [{ \"field\": \"data.status\", \"op\": \"==\", \"value\": \"active\" }]\\n' +\n ' }\\n' +\n ' ],\\n' +\n ' \"maxReads\": 100,\\n' +\n ' \"concurrency\": 5\\n' +\n '}',\n );\n }\n let input: TraverseInput;\n try {\n input = JSON.parse(jsonStr) as TraverseInput;\n } catch {\n die(`Invalid JSON: ${jsonStr.slice(0, 200)}`);\n }\n result = await client.traverse(input!);\n break;\n }\n\n case 'search':\n if (!positional[0]) {\n die('Usage: firegraph query search <query>');\n }\n result = await client.search({ q: positional.join(' ') });\n break;\n\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n return;\n\n default:\n die(\n `Unknown query command: ${command}\\n` +\n 'Commands: schema, get, find-nodes, find-edges, traverse, search',\n );\n }\n\n console.log(JSON.stringify(result, null, 2));\n } catch (err) {\n if (err instanceof QueryClientError) {\n console.error(JSON.stringify({ error: err.message, code: err.code }));\n } else {\n console.error(JSON.stringify({ error: (err as Error).message }));\n }\n process.exit(1);\n }\n}\n\nfunction printHelp(): void {\n console.log('');\n console.log(' Usage: firegraph query <command> [options]');\n console.log('');\n console.log(' Commands:');\n console.log(' schema Get graph schema (node types + edge types)');\n console.log(' get <uid> Get node detail with edges');\n console.log(' find-nodes <type> [--limit N] List nodes of a type');\n console.log(' find-edges [filters] List edges matching filters');\n console.log(' traverse \\'<JSON>\\' Multi-hop graph traversal');\n console.log(' search <query> Search nodes by text');\n console.log('');\n console.log(' Global options:');\n console.log(' --port <number> Editor server port (default: auto-detect from config)');\n console.log(' --host <string> Editor server host (default: localhost)');\n console.log('');\n console.log(' find-edges filters:');\n console.log(' --aType <type> Filter by source type');\n console.log(' --aUid <uid> Filter by source UID');\n console.log(' --axbType <rel> Filter by relation type');\n console.log(' --bType <type> Filter by target type');\n console.log(' --bUid <uid> Filter by target UID');\n console.log(' --limit <N> Max results (1-200, default 25)');\n console.log('');\n console.log(' Examples:');\n console.log(' npx firegraph query schema');\n console.log(' npx firegraph query get Kj7vNq2mP9xR4wL1tY8s3');\n console.log(' npx firegraph query find-nodes task --limit 10');\n console.log(' npx firegraph query find-edges --aUid Kj7vNq2mP9xR4wL1tY8s3 --axbType hasTask');\n console.log(' npx firegraph query search \"John Doe\"');\n console.log('');\n}\n\nfunction die(msg: string): never {\n console.error(msg);\n process.exit(1);\n}\n"],"mappings":"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","names":[]}