@confect/cli 9.0.0-next.2 → 9.0.0-next.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @confect/cli
2
2
 
3
+ ## 9.0.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 6d85210: Resolve `FunctionImpl` / `GroupImpl` group paths via an immutable `paths` map on `Spec` instead of identity-walking the assembled tree.
8
+
9
+ ### Why
10
+
11
+ Since `9.0.0-next.1`, codegen has wrapped every parent leaf that has sibling subdirectory specs in `<parent>.addGroupAt("child", <child>)`. Because `GroupSpec.addGroupAt` is immutable, that produced a fresh object in the assembled tree, while the parent's `*.impl.ts` continued to hold a reference to the original imported leaf. The runtime resolver compared by `===`, so every such impl failed `validateImpl` with "Could not resolve group path for the provided GroupSpec." Child impls happened to work only because `GroupSpec.withName` was secretly mutating its argument in place to keep the child's identity stable — an asymmetry that was load-bearing for one half of the API and broken for the other.
12
+
13
+ ### What changed
14
+ - `@confect/core/Spec` carries a new `readonly paths: ReadonlyMap<GroupSpec.AnyWithProps, string>` field and exposes a chainable `Spec#addPath(group, path)` builder. `add` / `addAt` / `merge` propagate `paths` unchanged; `merge` re-prefixes a node spec's entries with `"node."` to match the merged tree.
15
+ - `@confect/core/GroupSpec.withName` is now pure: it returns a fresh copy when the name differs and no longer rewrites the input in place. No new identity-tracking machinery is introduced.
16
+ - `@confect/server/FunctionImpl.make` and `GroupImpl.make` resolve their group path via `api.spec.paths.get(group)` — an O(1) map lookup instead of a tree walk — and throw a clearer error pointing at `Spec.addPath` when the spec hasn't been registered.
17
+ - `@confect/server/GroupPath` (the old identity-based resolver) is deleted.
18
+ - `@confect/cli` codegen emits one `.addPath(<binding>, "<dot.path>")` call per leaf in `_generated/spec.ts` (and `_generated/nodeSpec.ts`) so the imported leaves carry their full paths into the assembled spec value.
19
+
20
+ ### User-facing impact
21
+ - Spec authoring (`*.spec.ts`) and impl authoring (`*.impl.ts`) APIs are unchanged. `FunctionImpl.make(api, spec, name, handler)` and `GroupImpl.make(api, spec)` keep their exact signatures.
22
+ - Generated `_generated/spec.ts` (and `_generated/nodeSpec.ts`) pick up one `.addPath(...)` chain entry per leaf on the next `confect codegen` run. The shape is fully immutable — no module-load mutation, no hidden side effects.
23
+ - Hand-rolled tests that construct a `Spec` and pass it to `Api.make` must now also call `.addPath(spec, "dot.path")` for any group they intend to look up.
24
+
25
+ ### Fixes
26
+
27
+ This eliminates the runtime regression introduced in `9.0.0-next.1` for any project layout where a `confect/{path}.spec.ts` declares functions alongside a sibling `confect/{path}/` subdirectory of further specs.
28
+
29
+ - Updated dependencies [6d85210]
30
+ - @confect/core@9.0.0-next.3
31
+ - @confect/server@9.0.0-next.3
32
+
3
33
  ## 9.0.0-next.2
4
34
 
5
35
  ### Patch Changes
@@ -28,7 +28,25 @@ const importBindingsForNode = (node) => pipe(node.children, Array.flatMap(import
28
28
  onSome: (binding) => Array.prepend(childBindings, binding)
29
29
  }));
30
30
  const collectImportBindings = (nodes) => pipe(Array.flatMap(nodes, importBindingsForNode), (bindings) => Record.fromIterableBy(bindings, (binding) => binding.importPath), Record.toEntries, Array.map(([, binding]) => binding), Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)));
31
+ const leafPathsForNode = (node, ancestorSegments) => {
32
+ const segments = [...ancestorSegments, node.segment];
33
+ const childPaths = Array.flatMap(node.children, (child) => leafPathsForNode(child, segments));
34
+ return Option.match(node.importBinding, {
35
+ onNone: () => childPaths,
36
+ onSome: (binding) => Array.prepend(childPaths, {
37
+ binding,
38
+ dotPath: segments.join(".")
39
+ })
40
+ });
41
+ };
42
+ /**
43
+ * Walk the assembly tree and produce one entry per leaf spec, pairing its
44
+ * import binding with the full dot-path codegen will register via
45
+ * `Spec.addPath`. Ordering matches `collectImportBindings` (sorted by the
46
+ * binding's local name) so the generated file is stable across runs.
47
+ */
48
+ const collectLeafPaths = (nodes) => pipe(Array.flatMap(nodes, (node) => leafPathsForNode(node, [])), Array.sortBy(Order.mapInput(Order.string, (entry) => entry.binding.localName)));
31
49
 
32
50
  //#endregion
33
- export { assemblyNodesFromLeaves, collectImportBindings, partitionByRuntime };
51
+ export { assemblyNodesFromLeaves, collectImportBindings, collectLeafPaths, partitionByRuntime };
34
52
  //# sourceMappingURL=SpecAssemblyNode.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpecAssemblyNode.mjs","names":[],"sources":["../src/SpecAssemblyNode.ts"],"sourcesContent":["import type { LeafModule } from \"./LeafModule\";\nimport { Array, Option, Order, pipe, Record } from \"effect\";\n\nexport interface SpecImportBinding {\n readonly importPath: string;\n readonly exportName: string;\n readonly localName: string;\n}\n\nexport interface SpecAssemblyNode {\n readonly segment: string;\n readonly importBinding: Option.Option<SpecImportBinding>;\n readonly children: ReadonlyArray<SpecAssemblyNode>;\n}\n\nconst importBindingFromLeaf = (leaf: LeafModule): SpecImportBinding => ({\n importPath: leaf.specImportPath,\n exportName: leaf.exportName,\n localName: leaf.pathSegments.join(\"_\"),\n});\n\nconst assemblyNodesAtDepth = (\n leaves: ReadonlyArray<LeafModule>,\n depth: number,\n): ReadonlyArray<SpecAssemblyNode> =>\n pipe(\n Array.groupBy(leaves, (leaf) => leaf.pathSegments[depth]!),\n Record.toEntries,\n Array.sortBy(Order.mapInput(Order.string, ([segment]) => segment)),\n Array.map(([segment, groupLeaves]) => {\n const terminal = Array.findFirst(\n groupLeaves,\n (leaf) => leaf.pathSegments.length === depth + 1,\n );\n const descendants = Array.filter(\n groupLeaves,\n (leaf) => leaf.pathSegments.length > depth + 1,\n );\n return {\n segment,\n importBinding: Option.map(terminal, importBindingFromLeaf),\n children: assemblyNodesAtDepth(descendants, depth + 1),\n };\n }),\n );\n\nexport const assemblyNodesFromLeaves = (\n leaves: ReadonlyArray<LeafModule>,\n): ReadonlyArray<SpecAssemblyNode> => assemblyNodesAtDepth(leaves, 0);\n\nexport const partitionByRuntime = (\n leaves: ReadonlyArray<LeafModule>,\n): {\n readonly convex: ReadonlyArray<LeafModule>;\n readonly node: ReadonlyArray<LeafModule>;\n} => {\n const [node, convex] = Array.partition(\n leaves,\n (leaf) => leaf.runtime === \"Convex\",\n );\n return { convex, node };\n};\n\nconst importBindingsForNode = (\n node: SpecAssemblyNode,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(node.children, Array.flatMap(importBindingsForNode), (childBindings) =>\n Option.match(node.importBinding, {\n onNone: () => childBindings,\n onSome: (binding) => Array.prepend(childBindings, binding),\n }),\n );\n\nexport const collectImportBindings = (\n nodes: ReadonlyArray<SpecAssemblyNode>,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(\n Array.flatMap(nodes, importBindingsForNode),\n (bindings) =>\n Record.fromIterableBy(bindings, (binding) => binding.importPath),\n Record.toEntries,\n Array.map(([, binding]) => binding),\n Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)),\n );\n"],"mappings":";;;AAeA,MAAM,yBAAyB,UAAyC;CACtE,YAAY,KAAK;CACjB,YAAY,KAAK;CACjB,WAAW,KAAK,aAAa,KAAK,IAAI;CACvC;AAED,MAAM,wBACJ,QACA,UAEA,KACE,MAAM,QAAQ,SAAS,SAAS,KAAK,aAAa,OAAQ,EAC1D,OAAO,WACP,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,CAAC,aAAa,QAAQ,CAAC,EAClE,MAAM,KAAK,CAAC,SAAS,iBAAiB;CACpC,MAAM,WAAW,MAAM,UACrB,cACC,SAAS,KAAK,aAAa,WAAW,QAAQ,EAChD;CACD,MAAM,cAAc,MAAM,OACxB,cACC,SAAS,KAAK,aAAa,SAAS,QAAQ,EAC9C;AACD,QAAO;EACL;EACA,eAAe,OAAO,IAAI,UAAU,sBAAsB;EAC1D,UAAU,qBAAqB,aAAa,QAAQ,EAAE;EACvD;EACD,CACH;AAEH,MAAa,2BACX,WACoC,qBAAqB,QAAQ,EAAE;AAErE,MAAa,sBACX,WAIG;CACH,MAAM,CAAC,MAAM,UAAU,MAAM,UAC3B,SACC,SAAS,KAAK,YAAY,SAC5B;AACD,QAAO;EAAE;EAAQ;EAAM;;AAGzB,MAAM,yBACJ,SAEA,KAAK,KAAK,UAAU,MAAM,QAAQ,sBAAsB,GAAG,kBACzD,OAAO,MAAM,KAAK,eAAe;CAC/B,cAAc;CACd,SAAS,YAAY,MAAM,QAAQ,eAAe,QAAQ;CAC3D,CAAC,CACH;AAEH,MAAa,yBACX,UAEA,KACE,MAAM,QAAQ,OAAO,sBAAsB,GAC1C,aACC,OAAO,eAAe,WAAW,YAAY,QAAQ,WAAW,EAClE,OAAO,WACP,MAAM,KAAK,GAAG,aAAa,QAAQ,EACnC,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,UAAU,CAAC,CAC3E"}
1
+ {"version":3,"file":"SpecAssemblyNode.mjs","names":[],"sources":["../src/SpecAssemblyNode.ts"],"sourcesContent":["import type { LeafModule } from \"./LeafModule\";\nimport { Array, Option, Order, pipe, Record } from \"effect\";\n\nexport interface SpecImportBinding {\n readonly importPath: string;\n readonly exportName: string;\n readonly localName: string;\n}\n\nexport interface SpecAssemblyNode {\n readonly segment: string;\n readonly importBinding: Option.Option<SpecImportBinding>;\n readonly children: ReadonlyArray<SpecAssemblyNode>;\n}\n\nconst importBindingFromLeaf = (leaf: LeafModule): SpecImportBinding => ({\n importPath: leaf.specImportPath,\n exportName: leaf.exportName,\n localName: leaf.pathSegments.join(\"_\"),\n});\n\nconst assemblyNodesAtDepth = (\n leaves: ReadonlyArray<LeafModule>,\n depth: number,\n): ReadonlyArray<SpecAssemblyNode> =>\n pipe(\n Array.groupBy(leaves, (leaf) => leaf.pathSegments[depth]!),\n Record.toEntries,\n Array.sortBy(Order.mapInput(Order.string, ([segment]) => segment)),\n Array.map(([segment, groupLeaves]) => {\n const terminal = Array.findFirst(\n groupLeaves,\n (leaf) => leaf.pathSegments.length === depth + 1,\n );\n const descendants = Array.filter(\n groupLeaves,\n (leaf) => leaf.pathSegments.length > depth + 1,\n );\n return {\n segment,\n importBinding: Option.map(terminal, importBindingFromLeaf),\n children: assemblyNodesAtDepth(descendants, depth + 1),\n };\n }),\n );\n\nexport const assemblyNodesFromLeaves = (\n leaves: ReadonlyArray<LeafModule>,\n): ReadonlyArray<SpecAssemblyNode> => assemblyNodesAtDepth(leaves, 0);\n\nexport const partitionByRuntime = (\n leaves: ReadonlyArray<LeafModule>,\n): {\n readonly convex: ReadonlyArray<LeafModule>;\n readonly node: ReadonlyArray<LeafModule>;\n} => {\n const [node, convex] = Array.partition(\n leaves,\n (leaf) => leaf.runtime === \"Convex\",\n );\n return { convex, node };\n};\n\nconst importBindingsForNode = (\n node: SpecAssemblyNode,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(node.children, Array.flatMap(importBindingsForNode), (childBindings) =>\n Option.match(node.importBinding, {\n onNone: () => childBindings,\n onSome: (binding) => Array.prepend(childBindings, binding),\n }),\n );\n\nexport const collectImportBindings = (\n nodes: ReadonlyArray<SpecAssemblyNode>,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(\n Array.flatMap(nodes, importBindingsForNode),\n (bindings) =>\n Record.fromIterableBy(bindings, (binding) => binding.importPath),\n Record.toEntries,\n Array.map(([, binding]) => binding),\n Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)),\n );\n\nexport interface SpecLeafPath {\n readonly binding: SpecImportBinding;\n readonly dotPath: string;\n}\n\nconst leafPathsForNode = (\n node: SpecAssemblyNode,\n ancestorSegments: ReadonlyArray<string>,\n): ReadonlyArray<SpecLeafPath> => {\n const segments = [...ancestorSegments, node.segment];\n const childPaths = Array.flatMap(node.children, (child) =>\n leafPathsForNode(child, segments),\n );\n return Option.match(node.importBinding, {\n onNone: () => childPaths,\n onSome: (binding) =>\n Array.prepend(childPaths, { binding, dotPath: segments.join(\".\") }),\n });\n};\n\n/**\n * Walk the assembly tree and produce one entry per leaf spec, pairing its\n * import binding with the full dot-path codegen will register via\n * `Spec.addPath`. Ordering matches `collectImportBindings` (sorted by the\n * binding's local name) so the generated file is stable across runs.\n */\nexport const collectLeafPaths = (\n nodes: ReadonlyArray<SpecAssemblyNode>,\n): ReadonlyArray<SpecLeafPath> =>\n pipe(\n Array.flatMap(nodes, (node) => leafPathsForNode(node, [])),\n Array.sortBy(\n Order.mapInput(Order.string, (entry) => entry.binding.localName),\n ),\n );\n"],"mappings":";;;AAeA,MAAM,yBAAyB,UAAyC;CACtE,YAAY,KAAK;CACjB,YAAY,KAAK;CACjB,WAAW,KAAK,aAAa,KAAK,IAAI;CACvC;AAED,MAAM,wBACJ,QACA,UAEA,KACE,MAAM,QAAQ,SAAS,SAAS,KAAK,aAAa,OAAQ,EAC1D,OAAO,WACP,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,CAAC,aAAa,QAAQ,CAAC,EAClE,MAAM,KAAK,CAAC,SAAS,iBAAiB;CACpC,MAAM,WAAW,MAAM,UACrB,cACC,SAAS,KAAK,aAAa,WAAW,QAAQ,EAChD;CACD,MAAM,cAAc,MAAM,OACxB,cACC,SAAS,KAAK,aAAa,SAAS,QAAQ,EAC9C;AACD,QAAO;EACL;EACA,eAAe,OAAO,IAAI,UAAU,sBAAsB;EAC1D,UAAU,qBAAqB,aAAa,QAAQ,EAAE;EACvD;EACD,CACH;AAEH,MAAa,2BACX,WACoC,qBAAqB,QAAQ,EAAE;AAErE,MAAa,sBACX,WAIG;CACH,MAAM,CAAC,MAAM,UAAU,MAAM,UAC3B,SACC,SAAS,KAAK,YAAY,SAC5B;AACD,QAAO;EAAE;EAAQ;EAAM;;AAGzB,MAAM,yBACJ,SAEA,KAAK,KAAK,UAAU,MAAM,QAAQ,sBAAsB,GAAG,kBACzD,OAAO,MAAM,KAAK,eAAe;CAC/B,cAAc;CACd,SAAS,YAAY,MAAM,QAAQ,eAAe,QAAQ;CAC3D,CAAC,CACH;AAEH,MAAa,yBACX,UAEA,KACE,MAAM,QAAQ,OAAO,sBAAsB,GAC1C,aACC,OAAO,eAAe,WAAW,YAAY,QAAQ,WAAW,EAClE,OAAO,WACP,MAAM,KAAK,GAAG,aAAa,QAAQ,EACnC,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,UAAU,CAAC,CAC3E;AAOH,MAAM,oBACJ,MACA,qBACgC;CAChC,MAAM,WAAW,CAAC,GAAG,kBAAkB,KAAK,QAAQ;CACpD,MAAM,aAAa,MAAM,QAAQ,KAAK,WAAW,UAC/C,iBAAiB,OAAO,SAAS,CAClC;AACD,QAAO,OAAO,MAAM,KAAK,eAAe;EACtC,cAAc;EACd,SAAS,YACP,MAAM,QAAQ,YAAY;GAAE;GAAS,SAAS,SAAS,KAAK,IAAI;GAAE,CAAC;EACtE,CAAC;;;;;;;;AASJ,MAAa,oBACX,UAEA,KACE,MAAM,QAAQ,QAAQ,SAAS,iBAAiB,MAAM,EAAE,CAAC,CAAC,EAC1D,MAAM,OACJ,MAAM,SAAS,MAAM,SAAS,UAAU,MAAM,QAAQ,UAAU,CACjE,CACF"}
package/dist/package.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "9.0.0-next.2";
2
+ var version = "9.0.0-next.3";
3
3
 
4
4
  //#endregion
5
5
  export { version };
@@ -1,5 +1,5 @@
1
1
  import { CodeBlockWriter } from "./CodeBlockWriter.mjs";
2
- import { collectImportBindings } from "./SpecAssemblyNode.mjs";
2
+ import { collectImportBindings, collectLeafPaths } from "./SpecAssemblyNode.mjs";
3
3
  import { Array, Effect, Option } from "effect";
4
4
 
5
5
  //#region src/templates.ts
@@ -211,6 +211,11 @@ const assembledSpec = ({ nodes, runtime }) => Effect.gen(function* () {
211
211
  const specFactory = runtime === "Convex" ? "Spec.make()" : "Spec.makeNode()";
212
212
  const groupFactory = runtime === "Convex" ? "GroupSpec.makeAt" : "GroupSpec.makeNodeAt";
213
213
  yield* cbw.write(`export default ${specFactory}`);
214
+ yield* Effect.forEach(collectLeafPaths(nodes), (leaf) => Effect.gen(function* () {
215
+ yield* cbw.write(`.addPath(${leaf.binding.localName}, `);
216
+ yield* cbw.quote(leaf.dotPath);
217
+ yield* cbw.write(")");
218
+ }));
214
219
  yield* Effect.forEach(nodes, (node) => writeRootAddAt(cbw, node, groupFactory));
215
220
  yield* cbw.write(";");
216
221
  yield* cbw.newLine();
@@ -1 +1 @@
1
- {"version":3,"file":"templates.mjs","names":[],"sources":["../src/templates.ts"],"sourcesContent":["import { Array, Effect, Option } from \"effect\";\nimport { CodeBlockWriter } from \"./CodeBlockWriter\";\nimport {\n collectImportBindings,\n type SpecAssemblyNode,\n} from \"./SpecAssemblyNode\";\n\nexport const functions = ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n functionNames: string[];\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n if (useNode) {\n yield* cbw.writeLine(`\"use node\";`);\n yield* cbw.blankLine();\n }\n\n yield* cbw.writeLine(\n `import registeredFunctions from \"${registeredFunctionsImportPath}\";`,\n );\n yield* cbw.newLine();\n yield* Effect.forEach(functionNames, (functionName) =>\n cbw.writeLine(\n `export const ${functionName} = registeredFunctions.${functionName};`,\n ),\n );\n\n return yield* cbw.toString();\n });\n\nexport const schema = ({ schemaImportPath }: { schemaImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import schemaDefinition from \"${schemaImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(\n `export default schemaDefinition.convexSchemaDefinition;`,\n );\n\n return yield* cbw.toString();\n });\n\nexport const http = ({ httpImportPath }: { httpImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import http from \"${httpImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default http;`);\n\n return yield* cbw.toString();\n });\n\nexport const crons = ({ cronsImportPath }: { cronsImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import crons from \"${cronsImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default crons.convexCronJobs;`);\n\n return yield* cbw.toString();\n });\n\nexport const authConfig = ({ authImportPath }: { authImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import auth from \"${authImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default auth;`);\n\n return yield* cbw.toString();\n });\n\nexport const refs = ({\n specImportPath,\n nodeSpecImportPath,\n}: {\n specImportPath: string;\n nodeSpecImportPath: Option.Option<string>;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Refs } from \"@confect/core\";`);\n yield* cbw.writeLine(`import spec from \"${specImportPath}\";`);\n yield* Option.match(nodeSpecImportPath, {\n onNone: () => Effect.void,\n onSome: (nodeSpecImportPath_) =>\n cbw.writeLine(`import nodeSpec from \"${nodeSpecImportPath_}\";`),\n });\n yield* cbw.blankLine();\n yield* cbw.writeLine(\n Option.match(nodeSpecImportPath, {\n onSome: () => `export default Refs.make(spec, nodeSpec);`,\n onNone: () => `export default Refs.make(spec);`,\n }),\n );\n\n return yield* cbw.toString();\n });\n\nexport const api = ({\n schemaImportPath,\n specImportPath,\n}: {\n schemaImportPath: string;\n specImportPath: string;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Api } from \"@confect/server\";`);\n yield* cbw.writeLine(`import schema from \"${schemaImportPath}\";`);\n yield* cbw.writeLine(`import spec from \"${specImportPath}\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`export default Api.make(schema, spec);`);\n\n return yield* cbw.toString();\n });\n\nexport const nodeApi = ({\n schemaImportPath,\n nodeSpecImportPath,\n}: {\n schemaImportPath: string;\n nodeSpecImportPath: string;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Api } from \"@confect/server\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`import schema from \"${schemaImportPath}\";`);\n yield* cbw.writeLine(`import nodeSpec from \"${nodeSpecImportPath}\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`export default Api.make(schema, nodeSpec);`);\n\n return yield* cbw.toString();\n });\n\nexport const registeredFunctionsForGroup = ({\n apiImportPath,\n groupPathDot,\n implImportPath,\n layerExportName,\n useNode = false,\n}: {\n apiImportPath: string;\n groupPathDot: string;\n implImportPath: string;\n layerExportName: string;\n useNode?: boolean;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n if (useNode) {\n yield* cbw.writeLine(\n `import { RegisteredFunctions } from \"@confect/server\";`,\n );\n yield* cbw.writeLine(\n `import { RegisteredNodeFunction } from \"@confect/server/node\";`,\n );\n } else {\n yield* cbw.writeLine(\n `import { RegisteredConvexFunction, RegisteredFunctions } from \"@confect/server\";`,\n );\n }\n\n yield* cbw.writeLine(`import api from \"${apiImportPath}\";`);\n yield* cbw.writeLine(`import ${layerExportName} from \"${implImportPath}\";`);\n yield* cbw.blankLine();\n const quotedGroupPath = `\"${groupPathDot.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n yield* cbw.writeLine(\n useNode\n ? `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredNodeFunction.make);`\n : `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredConvexFunction.make);`,\n );\n\n return yield* cbw.toString();\n });\n\nexport const services = ({ schemaImportPath }: { schemaImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n // Imports\n yield* cbw.writeLine(\"import {\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"ActionCtx as ActionCtx_,\");\n yield* cbw.writeLine(\"ActionRunner as ActionRunner_,\");\n yield* cbw.writeLine(\"Auth as Auth_,\");\n yield* cbw.writeLine(\"type DataModel,\");\n yield* cbw.writeLine(\"DatabaseReader as DatabaseReader_,\");\n yield* cbw.writeLine(\"DatabaseWriter as DatabaseWriter_,\");\n yield* cbw.writeLine(\"MutationCtx as MutationCtx_,\");\n yield* cbw.writeLine(\"MutationRunner as MutationRunner_,\");\n yield* cbw.writeLine(\"QueryCtx as QueryCtx_,\");\n yield* cbw.writeLine(\"QueryRunner as QueryRunner_,\");\n yield* cbw.writeLine(\"Scheduler as Scheduler_,\");\n yield* cbw.writeLine(\"StorageActionWriter as StorageActionWriter_,\");\n yield* cbw.writeLine(\"StorageReader as StorageReader_,\");\n yield* cbw.writeLine(\"StorageWriter as StorageWriter_,\");\n yield* cbw.writeLine(\"VectorSearch as VectorSearch_,\");\n }),\n );\n yield* cbw.writeLine(`} from \"@confect/server\";`);\n yield* cbw.writeLine(\n `import type schemaDefinition from \"${schemaImportPath}\";`,\n );\n yield* cbw.blankLine();\n\n // Auth\n yield* cbw.writeLine(\"export const Auth = Auth_.Auth;\");\n yield* cbw.writeLine(\"export type Auth = typeof Auth.Identifier;\");\n yield* cbw.blankLine();\n\n // Scheduler\n yield* cbw.writeLine(\"export const Scheduler = Scheduler_.Scheduler;\");\n yield* cbw.writeLine(\n \"export type Scheduler = typeof Scheduler.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageReader\n yield* cbw.writeLine(\n \"export const StorageReader = StorageReader_.StorageReader;\",\n );\n yield* cbw.writeLine(\n \"export type StorageReader = typeof StorageReader.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageWriter\n yield* cbw.writeLine(\n \"export const StorageWriter = StorageWriter_.StorageWriter;\",\n );\n yield* cbw.writeLine(\n \"export type StorageWriter = typeof StorageWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageActionWriter\n yield* cbw.writeLine(\n \"export const StorageActionWriter = StorageActionWriter_.StorageActionWriter;\",\n );\n yield* cbw.writeLine(\n \"export type StorageActionWriter = typeof StorageActionWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // VectorSearch\n yield* cbw.writeLine(\"export const VectorSearch =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"VectorSearch_.VectorSearch<DataModel.FromSchema<typeof schemaDefinition>>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type VectorSearch = typeof VectorSearch.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // DatabaseReader\n yield* cbw.writeLine(\"export const DatabaseReader =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DatabaseReader_.DatabaseReader<typeof schemaDefinition>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type DatabaseReader = typeof DatabaseReader.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // DatabaseWriter\n yield* cbw.writeLine(\"export const DatabaseWriter =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DatabaseWriter_.DatabaseWriter<typeof schemaDefinition>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type DatabaseWriter = typeof DatabaseWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // QueryRunner\n yield* cbw.writeLine(\n \"export const QueryRunner = QueryRunner_.QueryRunner;\",\n );\n yield* cbw.writeLine(\n \"export type QueryRunner = typeof QueryRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // MutationRunner\n yield* cbw.writeLine(\n \"export const MutationRunner = MutationRunner_.MutationRunner;\",\n );\n yield* cbw.writeLine(\n \"export type MutationRunner = typeof MutationRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // ActionRunner\n yield* cbw.writeLine(\n \"export const ActionRunner = ActionRunner_.ActionRunner;\",\n );\n yield* cbw.writeLine(\n \"export type ActionRunner = typeof ActionRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // QueryCtx\n yield* cbw.writeLine(\"export const QueryCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"QueryCtx_.QueryCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\"export type QueryCtx = typeof QueryCtx.Identifier;\");\n yield* cbw.blankLine();\n\n // MutationCtx\n yield* cbw.writeLine(\"export const MutationCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"MutationCtx_.MutationCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\n \"export type MutationCtx = typeof MutationCtx.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // ActionCtx\n yield* cbw.writeLine(\"export const ActionCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"ActionCtx_.ActionCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\n \"export type ActionCtx = typeof ActionCtx.Identifier;\",\n );\n\n return yield* cbw.toString();\n });\n\nconst writeChildAddGroupAt = (\n cbw: CodeBlockWriter,\n child: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(\".addGroupAt(\");\n yield* cbw.quote(child.segment);\n yield* cbw.write(\", \");\n yield* writeGroupAssembly(cbw, child, groupFactory);\n yield* cbw.write(\")\");\n });\n\nconst writeGroupFactoryCall = (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(groupFactory);\n yield* cbw.write(\"(\");\n yield* cbw.quote(node.segment);\n yield* cbw.write(\")\");\n\n yield* Effect.forEach(node.children, (child) =>\n writeChildAddGroupAt(cbw, child, groupFactory),\n );\n });\n\nconst writeGroupAssembly: (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n) => Effect.Effect<void> = (cbw, node, groupFactory) =>\n Option.match(node.importBinding, {\n onNone: () => writeGroupFactoryCall(cbw, node, groupFactory),\n onSome: (binding) =>\n Effect.gen(function* () {\n yield* cbw.write(binding.localName);\n yield* Effect.forEach(node.children, (child) =>\n writeChildAddGroupAt(cbw, child, groupFactory),\n );\n }),\n });\n\nconst writeRootAddAt = (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(\".addAt(\");\n yield* cbw.quote(node.segment);\n yield* cbw.write(\", \");\n\n yield* writeGroupAssembly(cbw, node, groupFactory);\n\n yield* cbw.write(\")\");\n });\n\nexport const assembledSpec = ({\n nodes,\n runtime,\n}: {\n nodes: ReadonlyArray<SpecAssemblyNode>;\n runtime: \"Convex\" | \"Node\";\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n const nodeRequiresGroupFactory = (node: SpecAssemblyNode): boolean =>\n Option.isNone(node.importBinding) ||\n Array.some(node.children, nodeRequiresGroupFactory);\n\n const needsGroupSpec = Array.some(nodes, nodeRequiresGroupFactory);\n yield* cbw.writeLine(\n needsGroupSpec\n ? `import { GroupSpec, Spec } from \"@confect/core\";`\n : `import { Spec } from \"@confect/core\";`,\n );\n\n yield* Effect.forEach(collectImportBindings(nodes), (binding) =>\n cbw.writeLine(\n `import ${binding.localName} from \"${binding.importPath}\";`,\n ),\n );\n\n yield* cbw.blankLine();\n\n const specFactory =\n runtime === \"Convex\" ? \"Spec.make()\" : \"Spec.makeNode()\";\n const groupFactory =\n runtime === \"Convex\" ? \"GroupSpec.makeAt\" : \"GroupSpec.makeNodeAt\";\n\n yield* cbw.write(`export default ${specFactory}`);\n yield* Effect.forEach(nodes, (node) =>\n writeRootAddAt(cbw, node, groupFactory),\n );\n yield* cbw.write(\";\");\n yield* cbw.newLine();\n\n return yield* cbw.toString();\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"templates.mjs","names":[],"sources":["../src/templates.ts"],"sourcesContent":["import { Array, Effect, Option } from \"effect\";\nimport { CodeBlockWriter } from \"./CodeBlockWriter\";\nimport {\n collectImportBindings,\n collectLeafPaths,\n type SpecAssemblyNode,\n} from \"./SpecAssemblyNode\";\n\nexport const functions = ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n functionNames: string[];\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n if (useNode) {\n yield* cbw.writeLine(`\"use node\";`);\n yield* cbw.blankLine();\n }\n\n yield* cbw.writeLine(\n `import registeredFunctions from \"${registeredFunctionsImportPath}\";`,\n );\n yield* cbw.newLine();\n yield* Effect.forEach(functionNames, (functionName) =>\n cbw.writeLine(\n `export const ${functionName} = registeredFunctions.${functionName};`,\n ),\n );\n\n return yield* cbw.toString();\n });\n\nexport const schema = ({ schemaImportPath }: { schemaImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import schemaDefinition from \"${schemaImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(\n `export default schemaDefinition.convexSchemaDefinition;`,\n );\n\n return yield* cbw.toString();\n });\n\nexport const http = ({ httpImportPath }: { httpImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import http from \"${httpImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default http;`);\n\n return yield* cbw.toString();\n });\n\nexport const crons = ({ cronsImportPath }: { cronsImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import crons from \"${cronsImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default crons.convexCronJobs;`);\n\n return yield* cbw.toString();\n });\n\nexport const authConfig = ({ authImportPath }: { authImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import auth from \"${authImportPath}\";`);\n yield* cbw.newLine();\n yield* cbw.writeLine(`export default auth;`);\n\n return yield* cbw.toString();\n });\n\nexport const refs = ({\n specImportPath,\n nodeSpecImportPath,\n}: {\n specImportPath: string;\n nodeSpecImportPath: Option.Option<string>;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Refs } from \"@confect/core\";`);\n yield* cbw.writeLine(`import spec from \"${specImportPath}\";`);\n yield* Option.match(nodeSpecImportPath, {\n onNone: () => Effect.void,\n onSome: (nodeSpecImportPath_) =>\n cbw.writeLine(`import nodeSpec from \"${nodeSpecImportPath_}\";`),\n });\n yield* cbw.blankLine();\n yield* cbw.writeLine(\n Option.match(nodeSpecImportPath, {\n onSome: () => `export default Refs.make(spec, nodeSpec);`,\n onNone: () => `export default Refs.make(spec);`,\n }),\n );\n\n return yield* cbw.toString();\n });\n\nexport const api = ({\n schemaImportPath,\n specImportPath,\n}: {\n schemaImportPath: string;\n specImportPath: string;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Api } from \"@confect/server\";`);\n yield* cbw.writeLine(`import schema from \"${schemaImportPath}\";`);\n yield* cbw.writeLine(`import spec from \"${specImportPath}\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`export default Api.make(schema, spec);`);\n\n return yield* cbw.toString();\n });\n\nexport const nodeApi = ({\n schemaImportPath,\n nodeSpecImportPath,\n}: {\n schemaImportPath: string;\n nodeSpecImportPath: string;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n yield* cbw.writeLine(`import { Api } from \"@confect/server\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`import schema from \"${schemaImportPath}\";`);\n yield* cbw.writeLine(`import nodeSpec from \"${nodeSpecImportPath}\";`);\n yield* cbw.blankLine();\n yield* cbw.writeLine(`export default Api.make(schema, nodeSpec);`);\n\n return yield* cbw.toString();\n });\n\nexport const registeredFunctionsForGroup = ({\n apiImportPath,\n groupPathDot,\n implImportPath,\n layerExportName,\n useNode = false,\n}: {\n apiImportPath: string;\n groupPathDot: string;\n implImportPath: string;\n layerExportName: string;\n useNode?: boolean;\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n if (useNode) {\n yield* cbw.writeLine(\n `import { RegisteredFunctions } from \"@confect/server\";`,\n );\n yield* cbw.writeLine(\n `import { RegisteredNodeFunction } from \"@confect/server/node\";`,\n );\n } else {\n yield* cbw.writeLine(\n `import { RegisteredConvexFunction, RegisteredFunctions } from \"@confect/server\";`,\n );\n }\n\n yield* cbw.writeLine(`import api from \"${apiImportPath}\";`);\n yield* cbw.writeLine(`import ${layerExportName} from \"${implImportPath}\";`);\n yield* cbw.blankLine();\n const quotedGroupPath = `\"${groupPathDot.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n yield* cbw.writeLine(\n useNode\n ? `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredNodeFunction.make);`\n : `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredConvexFunction.make);`,\n );\n\n return yield* cbw.toString();\n });\n\nexport const services = ({ schemaImportPath }: { schemaImportPath: string }) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n // Imports\n yield* cbw.writeLine(\"import {\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"ActionCtx as ActionCtx_,\");\n yield* cbw.writeLine(\"ActionRunner as ActionRunner_,\");\n yield* cbw.writeLine(\"Auth as Auth_,\");\n yield* cbw.writeLine(\"type DataModel,\");\n yield* cbw.writeLine(\"DatabaseReader as DatabaseReader_,\");\n yield* cbw.writeLine(\"DatabaseWriter as DatabaseWriter_,\");\n yield* cbw.writeLine(\"MutationCtx as MutationCtx_,\");\n yield* cbw.writeLine(\"MutationRunner as MutationRunner_,\");\n yield* cbw.writeLine(\"QueryCtx as QueryCtx_,\");\n yield* cbw.writeLine(\"QueryRunner as QueryRunner_,\");\n yield* cbw.writeLine(\"Scheduler as Scheduler_,\");\n yield* cbw.writeLine(\"StorageActionWriter as StorageActionWriter_,\");\n yield* cbw.writeLine(\"StorageReader as StorageReader_,\");\n yield* cbw.writeLine(\"StorageWriter as StorageWriter_,\");\n yield* cbw.writeLine(\"VectorSearch as VectorSearch_,\");\n }),\n );\n yield* cbw.writeLine(`} from \"@confect/server\";`);\n yield* cbw.writeLine(\n `import type schemaDefinition from \"${schemaImportPath}\";`,\n );\n yield* cbw.blankLine();\n\n // Auth\n yield* cbw.writeLine(\"export const Auth = Auth_.Auth;\");\n yield* cbw.writeLine(\"export type Auth = typeof Auth.Identifier;\");\n yield* cbw.blankLine();\n\n // Scheduler\n yield* cbw.writeLine(\"export const Scheduler = Scheduler_.Scheduler;\");\n yield* cbw.writeLine(\n \"export type Scheduler = typeof Scheduler.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageReader\n yield* cbw.writeLine(\n \"export const StorageReader = StorageReader_.StorageReader;\",\n );\n yield* cbw.writeLine(\n \"export type StorageReader = typeof StorageReader.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageWriter\n yield* cbw.writeLine(\n \"export const StorageWriter = StorageWriter_.StorageWriter;\",\n );\n yield* cbw.writeLine(\n \"export type StorageWriter = typeof StorageWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // StorageActionWriter\n yield* cbw.writeLine(\n \"export const StorageActionWriter = StorageActionWriter_.StorageActionWriter;\",\n );\n yield* cbw.writeLine(\n \"export type StorageActionWriter = typeof StorageActionWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // VectorSearch\n yield* cbw.writeLine(\"export const VectorSearch =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"VectorSearch_.VectorSearch<DataModel.FromSchema<typeof schemaDefinition>>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type VectorSearch = typeof VectorSearch.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // DatabaseReader\n yield* cbw.writeLine(\"export const DatabaseReader =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DatabaseReader_.DatabaseReader<typeof schemaDefinition>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type DatabaseReader = typeof DatabaseReader.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // DatabaseWriter\n yield* cbw.writeLine(\"export const DatabaseWriter =\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DatabaseWriter_.DatabaseWriter<typeof schemaDefinition>();\",\n ),\n );\n yield* cbw.writeLine(\n \"export type DatabaseWriter = typeof DatabaseWriter.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // QueryRunner\n yield* cbw.writeLine(\n \"export const QueryRunner = QueryRunner_.QueryRunner;\",\n );\n yield* cbw.writeLine(\n \"export type QueryRunner = typeof QueryRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // MutationRunner\n yield* cbw.writeLine(\n \"export const MutationRunner = MutationRunner_.MutationRunner;\",\n );\n yield* cbw.writeLine(\n \"export type MutationRunner = typeof MutationRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // ActionRunner\n yield* cbw.writeLine(\n \"export const ActionRunner = ActionRunner_.ActionRunner;\",\n );\n yield* cbw.writeLine(\n \"export type ActionRunner = typeof ActionRunner.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // QueryCtx\n yield* cbw.writeLine(\"export const QueryCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"QueryCtx_.QueryCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\"export type QueryCtx = typeof QueryCtx.Identifier;\");\n yield* cbw.blankLine();\n\n // MutationCtx\n yield* cbw.writeLine(\"export const MutationCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"MutationCtx_.MutationCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\n \"export type MutationCtx = typeof MutationCtx.Identifier;\",\n );\n yield* cbw.blankLine();\n\n // ActionCtx\n yield* cbw.writeLine(\"export const ActionCtx =\");\n yield* cbw.indent(\n Effect.gen(function* () {\n yield* cbw.writeLine(\"ActionCtx_.ActionCtx<\");\n yield* cbw.indent(\n cbw.writeLine(\n \"DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>\",\n ),\n );\n yield* cbw.writeLine(\">();\");\n }),\n );\n yield* cbw.writeLine(\n \"export type ActionCtx = typeof ActionCtx.Identifier;\",\n );\n\n return yield* cbw.toString();\n });\n\nconst writeChildAddGroupAt = (\n cbw: CodeBlockWriter,\n child: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(\".addGroupAt(\");\n yield* cbw.quote(child.segment);\n yield* cbw.write(\", \");\n yield* writeGroupAssembly(cbw, child, groupFactory);\n yield* cbw.write(\")\");\n });\n\nconst writeGroupFactoryCall = (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(groupFactory);\n yield* cbw.write(\"(\");\n yield* cbw.quote(node.segment);\n yield* cbw.write(\")\");\n\n yield* Effect.forEach(node.children, (child) =>\n writeChildAddGroupAt(cbw, child, groupFactory),\n );\n });\n\nconst writeGroupAssembly: (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n) => Effect.Effect<void> = (cbw, node, groupFactory) =>\n Option.match(node.importBinding, {\n onNone: () => writeGroupFactoryCall(cbw, node, groupFactory),\n onSome: (binding) =>\n Effect.gen(function* () {\n yield* cbw.write(binding.localName);\n yield* Effect.forEach(node.children, (child) =>\n writeChildAddGroupAt(cbw, child, groupFactory),\n );\n }),\n });\n\nconst writeRootAddAt = (\n cbw: CodeBlockWriter,\n node: SpecAssemblyNode,\n groupFactory: string,\n): Effect.Effect<void> =>\n Effect.gen(function* () {\n yield* cbw.write(\".addAt(\");\n yield* cbw.quote(node.segment);\n yield* cbw.write(\", \");\n\n yield* writeGroupAssembly(cbw, node, groupFactory);\n\n yield* cbw.write(\")\");\n });\n\nexport const assembledSpec = ({\n nodes,\n runtime,\n}: {\n nodes: ReadonlyArray<SpecAssemblyNode>;\n runtime: \"Convex\" | \"Node\";\n}) =>\n Effect.gen(function* () {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n const nodeRequiresGroupFactory = (node: SpecAssemblyNode): boolean =>\n Option.isNone(node.importBinding) ||\n Array.some(node.children, nodeRequiresGroupFactory);\n\n const needsGroupSpec = Array.some(nodes, nodeRequiresGroupFactory);\n yield* cbw.writeLine(\n needsGroupSpec\n ? `import { GroupSpec, Spec } from \"@confect/core\";`\n : `import { Spec } from \"@confect/core\";`,\n );\n\n yield* Effect.forEach(collectImportBindings(nodes), (binding) =>\n cbw.writeLine(\n `import ${binding.localName} from \"${binding.importPath}\";`,\n ),\n );\n\n yield* cbw.blankLine();\n\n const specFactory =\n runtime === \"Convex\" ? \"Spec.make()\" : \"Spec.makeNode()\";\n const groupFactory =\n runtime === \"Convex\" ? \"GroupSpec.makeAt\" : \"GroupSpec.makeNodeAt\";\n\n yield* cbw.write(`export default ${specFactory}`);\n yield* Effect.forEach(collectLeafPaths(nodes), (leaf) =>\n Effect.gen(function* () {\n yield* cbw.write(`.addPath(${leaf.binding.localName}, `);\n yield* cbw.quote(leaf.dotPath);\n yield* cbw.write(\")\");\n }),\n );\n yield* Effect.forEach(nodes, (node) =>\n writeRootAddAt(cbw, node, groupFactory),\n );\n yield* cbw.write(\";\");\n yield* cbw.newLine();\n\n return yield* cbw.toString();\n });\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@confect/cli",
3
- "version": "9.0.0-next.2",
3
+ "version": "9.0.0-next.3",
4
4
  "description": "Developer tooling for codegen and sync",
5
5
  "repository": {
6
6
  "type": "git",
@@ -65,8 +65,8 @@
65
65
  },
66
66
  "peerDependencies": {
67
67
  "effect": "^3.21.2",
68
- "@confect/core": "^9.0.0-next.2",
69
- "@confect/server": "^9.0.0-next.2"
68
+ "@confect/core": "^9.0.0-next.3",
69
+ "@confect/server": "^9.0.0-next.3"
70
70
  },
71
71
  "engines": {
72
72
  "node": ">=22",
@@ -82,3 +82,39 @@ export const collectImportBindings = (
82
82
  Array.map(([, binding]) => binding),
83
83
  Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)),
84
84
  );
85
+
86
+ export interface SpecLeafPath {
87
+ readonly binding: SpecImportBinding;
88
+ readonly dotPath: string;
89
+ }
90
+
91
+ const leafPathsForNode = (
92
+ node: SpecAssemblyNode,
93
+ ancestorSegments: ReadonlyArray<string>,
94
+ ): ReadonlyArray<SpecLeafPath> => {
95
+ const segments = [...ancestorSegments, node.segment];
96
+ const childPaths = Array.flatMap(node.children, (child) =>
97
+ leafPathsForNode(child, segments),
98
+ );
99
+ return Option.match(node.importBinding, {
100
+ onNone: () => childPaths,
101
+ onSome: (binding) =>
102
+ Array.prepend(childPaths, { binding, dotPath: segments.join(".") }),
103
+ });
104
+ };
105
+
106
+ /**
107
+ * Walk the assembly tree and produce one entry per leaf spec, pairing its
108
+ * import binding with the full dot-path codegen will register via
109
+ * `Spec.addPath`. Ordering matches `collectImportBindings` (sorted by the
110
+ * binding's local name) so the generated file is stable across runs.
111
+ */
112
+ export const collectLeafPaths = (
113
+ nodes: ReadonlyArray<SpecAssemblyNode>,
114
+ ): ReadonlyArray<SpecLeafPath> =>
115
+ pipe(
116
+ Array.flatMap(nodes, (node) => leafPathsForNode(node, [])),
117
+ Array.sortBy(
118
+ Order.mapInput(Order.string, (entry) => entry.binding.localName),
119
+ ),
120
+ );
package/src/templates.ts CHANGED
@@ -2,6 +2,7 @@ import { Array, Effect, Option } from "effect";
2
2
  import { CodeBlockWriter } from "./CodeBlockWriter";
3
3
  import {
4
4
  collectImportBindings,
5
+ collectLeafPaths,
5
6
  type SpecAssemblyNode,
6
7
  } from "./SpecAssemblyNode";
7
8
 
@@ -472,6 +473,13 @@ export const assembledSpec = ({
472
473
  runtime === "Convex" ? "GroupSpec.makeAt" : "GroupSpec.makeNodeAt";
473
474
 
474
475
  yield* cbw.write(`export default ${specFactory}`);
476
+ yield* Effect.forEach(collectLeafPaths(nodes), (leaf) =>
477
+ Effect.gen(function* () {
478
+ yield* cbw.write(`.addPath(${leaf.binding.localName}, `);
479
+ yield* cbw.quote(leaf.dotPath);
480
+ yield* cbw.write(")");
481
+ }),
482
+ );
475
483
  yield* Effect.forEach(nodes, (node) =>
476
484
  writeRootAddAt(cbw, node, groupFactory),
477
485
  );