@gaganref/confect-cli 10.3.1-fork.2 → 10.3.1-fork.20

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 (48) hide show
  1. package/dist/Bundler.mjs +22 -1
  2. package/dist/Bundler.mjs.map +1 -1
  3. package/dist/CodegenError.mjs +11 -2
  4. package/dist/CodegenError.mjs.map +1 -1
  5. package/dist/ConfectDirectory.mjs.map +1 -1
  6. package/dist/ConvexConfig.mjs.map +1 -1
  7. package/dist/ConvexDirectory.mjs.map +1 -1
  8. package/dist/DirectoryOptions.mjs.map +1 -1
  9. package/dist/EntryPoint.mjs.map +1 -1
  10. package/dist/Evaluation.mjs +39 -13
  11. package/dist/Evaluation.mjs.map +1 -1
  12. package/dist/EvaluationWorker.mjs +13 -1
  13. package/dist/EvaluationWorker.mjs.map +1 -1
  14. package/dist/FunctionModule.mjs +81 -13
  15. package/dist/FunctionModule.mjs.map +1 -1
  16. package/dist/FunctionPath.mjs.map +1 -1
  17. package/dist/FunctionPaths.mjs.map +1 -1
  18. package/dist/GenerationSnapshot.mjs.map +1 -1
  19. package/dist/GroupPaths.mjs.map +1 -1
  20. package/dist/ImplModulePath.mjs.map +1 -1
  21. package/dist/LeafModule.mjs +17 -17
  22. package/dist/LeafModule.mjs.map +1 -1
  23. package/dist/Remove.mjs.map +1 -1
  24. package/dist/Rollback.mjs.map +1 -1
  25. package/dist/SpecAssemblyNode.mjs.map +1 -1
  26. package/dist/SpecModulePath.mjs.map +1 -1
  27. package/dist/SyncState.mjs.map +1 -1
  28. package/dist/TableModule.mjs.map +1 -1
  29. package/dist/TableModulePath.mjs.map +1 -1
  30. package/dist/WatchBuild.mjs.map +1 -1
  31. package/dist/WatchTopology.mjs.map +1 -1
  32. package/dist/Watcher.mjs +57 -55
  33. package/dist/Watcher.mjs.map +1 -1
  34. package/dist/cliApp.mjs.map +1 -1
  35. package/dist/confect/codegen.mjs +75 -23
  36. package/dist/confect/codegen.mjs.map +1 -1
  37. package/dist/confect/declaration.mjs +4 -3
  38. package/dist/confect/declaration.mjs.map +1 -1
  39. package/dist/confect/dev.mjs +9 -4
  40. package/dist/confect/dev.mjs.map +1 -1
  41. package/dist/confect.mjs.map +1 -1
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/log.mjs.map +1 -1
  44. package/dist/templates.mjs +16 -12
  45. package/dist/templates.mjs.map +1 -1
  46. package/dist/utils.mjs +1 -1
  47. package/dist/utils.mjs.map +1 -1
  48. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"DirectoryOptions.mjs","names":["ProjectRoot.layer","ProjectRoot.ProjectRoot","ProjectRoot.findProjectRootFrom","ConvexDirectory.layer","ConvexDirectory.ConvexDirectory","ConvexDirectory.ConvexDirectoryNotFoundError"],"sources":["../src/DirectoryOptions.ts"],"sourcesContent":["import { IdScope } from \"@confect/core\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Schema from \"effect/Schema\";\nimport * as Flag from \"effect/cli/Flag\";\nimport * as ConfectDirectory from \"./ConfectDirectory\";\nimport * as ConvexDirectory from \"./ConvexDirectory\";\nimport * as ProjectRoot from \"./ProjectRoot\";\n\nexport const flags = {\n componentDir: Flag.String(\"component-dir\").pipe(\n Flag.withDescription(\n \"Generate a component instead of the application; its sibling confect/ directory contains the source.\",\n ),\n Flag.optional,\n ),\n};\n\nexport const layer = ({\n componentDir,\n}: {\n componentDir: Option.Option<string>;\n}) => {\n const projectRootLayer = Option.match(componentDir, {\n onNone: () => ProjectRoot.layer,\n onSome: (directory) =>\n Layer.effect(\n ProjectRoot.ProjectRoot,\n Effect.map(ProjectRoot.findProjectRootFrom(directory), (root) =>\n ProjectRoot.ProjectRoot.of({\n get: Effect.succeed(root),\n }),\n ),\n ),\n });\n const convex: Layer.Layer<\n ConvexDirectory.ConvexDirectory,\n Layer.Error<typeof ConvexDirectory.layer> | Schema.SchemaError,\n FileSystem.FileSystem | Path.Path\n > = Option.match(componentDir, {\n onNone: () => ConvexDirectory.layer,\n onSome: (directory) =>\n Layer.effect(\n ConvexDirectory.ConvexDirectory,\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const fs = yield* FileSystem.FileSystem;\n const projectRoot = yield* ProjectRoot.ProjectRoot.get;\n const absolute = path.resolve(directory);\n // A declared component's `convex.config.ts` is codegen output, so\n // its sibling `confect/app.ts` also marks the directory.\n if (\n !(yield* fs.exists(path.join(absolute, \"convex.config.ts\"))) &&\n !(yield* fs.exists(\n path.join(path.dirname(absolute), \"confect\", \"app.ts\"),\n ))\n ) {\n return yield* new ConvexDirectory.ConvexDirectoryNotFoundError();\n }\n const pkg = yield* fs\n .readFileString(path.join(projectRoot, \"package.json\"))\n .pipe(\n Effect.flatMap(\n Schema.decodeEffect(\n Schema.fromJsonString(Schema.Struct({ name: Schema.String })),\n ),\n ),\n );\n const definition = `${pkg.name}:${path.relative(projectRoot, absolute).split(path.sep).join(\"/\")}`;\n return ConvexDirectory.ConvexDirectory.of({\n get: Effect.succeed(absolute),\n target: {\n kind: \"component\",\n scope: IdScope.component(definition),\n },\n });\n }),\n ).pipe(Layer.provide(projectRootLayer)),\n });\n return Layer.mergeAll(\n projectRootLayer,\n ConfectDirectory.layerFromConvexDirectory.pipe(Layer.provideMerge(convex)),\n );\n};\n"],"mappings":";;;;;;;;;;;;AAYA,MAAa,QAAQ,EACnB,cAAc,KAAK,OAAO,eAAe,CAAC,CAAC,KACzC,KAAK,gBACH,sGACF,GACA,KAAK,QACP,EACF;AAEA,MAAa,SAAS,EACpB,mBAGI;CACJ,MAAM,mBAAmB,OAAO,MAAM,cAAc;EAClD,cAAcA;EACd,SAAS,cACP,MAAM,OACJC,aACA,OAAO,IAAIC,oBAAgC,SAAS,IAAI,SAAA,YAC9B,GAAG,EACzB,KAAK,OAAO,QAAQ,IAAI,EAC1B,CAAC,CACH,CACF;CACJ,CAAC;CACD,MAAM,SAIF,OAAO,MAAM,cAAc;EAC7B,cAAcC;EACd,SAAS,cACP,MAAM,OACJC,iBACA,OAAO,IAAI,aAAa;GACtB,MAAM,OAAO,OAAO,KAAK;GACzB,MAAM,KAAK,OAAO,WAAW;GAC7B,MAAM,cAAc,OAAA,YAA+B;GACnD,MAAM,WAAW,KAAK,QAAQ,SAAS;GAGvC,IACE,EAAE,OAAO,GAAG,OAAO,KAAK,KAAK,UAAU,kBAAkB,CAAC,MAC1D,EAAE,OAAO,GAAG,OACV,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG,WAAW,QAAQ,CACvD,IAEA,OAAO,OAAO,IAAIC,6BAA6C;GAWjE,MAAM,aAAa,IAAG,OATH,GAChB,eAAe,KAAK,KAAK,aAAa,cAAc,CAAC,CAAC,CACtD,KACC,OAAO,QACL,OAAO,aACL,OAAO,eAAe,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,CAC9D,CACF,CACF,EAAA,CACwB,KAAK,GAAG,KAAK,SAAS,aAAa,QAAQ,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;GAC/F,OAAA,gBAAuC,GAAG;IACxC,KAAK,OAAO,QAAQ,QAAQ;IAC5B,QAAQ;KACN,MAAM;KACN,OAAO,QAAQ,UAAU,UAAU;IACrC;GACF,CAAC;EACH,CAAC,CACH,CAAC,CAAC,KAAK,MAAM,QAAQ,gBAAgB,CAAC;CAC1C,CAAC;CACD,OAAO,MAAM,SACX,kBAAA,yBAC0C,KAAK,MAAM,aAAa,MAAM,CAAC,CAC3E;AACF"}
1
+ {"version":3,"file":"DirectoryOptions.mjs","names":["ProjectRoot.layer","ProjectRoot.ProjectRoot","ProjectRoot.findProjectRootFrom","ConvexDirectory.layer","ConvexDirectory.ConvexDirectory","ConvexDirectory.ConvexDirectoryNotFoundError"],"sources":["../src/DirectoryOptions.ts"],"sourcesContent":["import { IdScope } from \"@confect/core\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Schema from \"effect/Schema\";\nimport * as Flag from \"effect/cli/Flag\";\nimport * as ConfectDirectory from \"./ConfectDirectory.js\";\nimport * as ConvexDirectory from \"./ConvexDirectory.js\";\nimport * as ProjectRoot from \"./ProjectRoot.js\";\n\nexport const flags = {\n componentDir: Flag.String(\"component-dir\").pipe(\n Flag.withDescription(\n \"Generate a component instead of the application; its sibling confect/ directory contains the source.\",\n ),\n Flag.optional,\n ),\n};\n\nexport const layer = ({\n componentDir,\n}: {\n componentDir: Option.Option<string>;\n}) => {\n const projectRootLayer = Option.match(componentDir, {\n onNone: () => ProjectRoot.layer,\n onSome: (directory) =>\n Layer.effect(\n ProjectRoot.ProjectRoot,\n Effect.map(ProjectRoot.findProjectRootFrom(directory), (root) =>\n ProjectRoot.ProjectRoot.of({\n get: Effect.succeed(root),\n }),\n ),\n ),\n });\n const convex: Layer.Layer<\n ConvexDirectory.ConvexDirectory,\n Layer.Error<typeof ConvexDirectory.layer> | Schema.SchemaError,\n FileSystem.FileSystem | Path.Path\n > = Option.match(componentDir, {\n onNone: () => ConvexDirectory.layer,\n onSome: (directory) =>\n Layer.effect(\n ConvexDirectory.ConvexDirectory,\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const fs = yield* FileSystem.FileSystem;\n const projectRoot = yield* ProjectRoot.ProjectRoot.get;\n const absolute = path.resolve(directory);\n // A declared component's `convex.config.ts` is codegen output, so\n // its sibling `confect/app.ts` also marks the directory.\n if (\n !(yield* fs.exists(path.join(absolute, \"convex.config.ts\"))) &&\n !(yield* fs.exists(\n path.join(path.dirname(absolute), \"confect\", \"app.ts\"),\n ))\n ) {\n return yield* new ConvexDirectory.ConvexDirectoryNotFoundError();\n }\n const pkg = yield* fs\n .readFileString(path.join(projectRoot, \"package.json\"))\n .pipe(\n Effect.flatMap(\n Schema.decodeEffect(\n Schema.fromJsonString(Schema.Struct({ name: Schema.String })),\n ),\n ),\n );\n const definition = `${pkg.name}:${path.relative(projectRoot, absolute).split(path.sep).join(\"/\")}`;\n return ConvexDirectory.ConvexDirectory.of({\n get: Effect.succeed(absolute),\n target: {\n kind: \"component\",\n scope: IdScope.component(definition),\n },\n });\n }),\n ).pipe(Layer.provide(projectRootLayer)),\n });\n return Layer.mergeAll(\n projectRootLayer,\n ConfectDirectory.layerFromConvexDirectory.pipe(Layer.provideMerge(convex)),\n );\n};\n"],"mappings":";;;;;;;;;;;;AAYA,MAAa,QAAQ,EACnB,cAAc,KAAK,OAAO,eAAe,CAAC,CAAC,KACzC,KAAK,gBACH,sGACF,GACA,KAAK,QACP,EACF;AAEA,MAAa,SAAS,EACpB,mBAGI;CACJ,MAAM,mBAAmB,OAAO,MAAM,cAAc;EAClD,cAAcA;EACd,SAAS,cACP,MAAM,OACJC,aACA,OAAO,IAAIC,oBAAgC,SAAS,IAAI,SAAA,YAC9B,GAAG,EACzB,KAAK,OAAO,QAAQ,IAAI,EAC1B,CAAC,CACH,CACF;CACJ,CAAC;CACD,MAAM,SAIF,OAAO,MAAM,cAAc;EAC7B,cAAcC;EACd,SAAS,cACP,MAAM,OACJC,iBACA,OAAO,IAAI,aAAa;GACtB,MAAM,OAAO,OAAO,KAAK;GACzB,MAAM,KAAK,OAAO,WAAW;GAC7B,MAAM,cAAc,OAAA,YAA+B;GACnD,MAAM,WAAW,KAAK,QAAQ,SAAS;GAGvC,IACE,EAAE,OAAO,GAAG,OAAO,KAAK,KAAK,UAAU,kBAAkB,CAAC,MAC1D,EAAE,OAAO,GAAG,OACV,KAAK,KAAK,KAAK,QAAQ,QAAQ,GAAG,WAAW,QAAQ,CACvD,IAEA,OAAO,OAAO,IAAIC,6BAA6C;GAWjE,MAAM,aAAa,IAAG,OATH,GAChB,eAAe,KAAK,KAAK,aAAa,cAAc,CAAC,CAAC,CACtD,KACC,OAAO,QACL,OAAO,aACL,OAAO,eAAe,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC,CAAC,CAC9D,CACF,CACF,EAAA,CACwB,KAAK,GAAG,KAAK,SAAS,aAAa,QAAQ,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;GAC/F,OAAA,gBAAuC,GAAG;IACxC,KAAK,OAAO,QAAQ,QAAQ;IAC5B,QAAQ;KACN,MAAM;KACN,OAAO,QAAQ,UAAU,UAAU;IACrC;GACF,CAAC;EACH,CAAC,CACH,CAAC,CAAC,KAAK,MAAM,QAAQ,gBAAgB,CAAC;CAC1C,CAAC;CACD,OAAO,MAAM,SACX,kBAAA,yBAC0C,KAAK,MAAM,aAAa,MAAM,CAAC,CAC3E;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"EntryPoint.mjs","names":["SpecModulePath.SpecModulePath","SpecModulePath.toImpl"],"sources":["../src/EntryPoint.ts"],"sourcesContent":["import * as Array from \"effect/Array\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\nimport { ImplModulePath } from \"./ImplModulePath\";\nimport * as SpecModulePath from \"./SpecModulePath\";\nimport { TableModulePath } from \"./TableModulePath\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport { CONVEX_CONFIG_FILENAME } from \"./ConvexConfig\";\nimport { discoverLeafImplFiles, discoverLeafSpecFiles } from \"./LeafModule\";\nimport { discoverTableFiles, type TableModule } from \"./TableModule\";\n\nexport type Kind = Data.TaggedEnum<{\n Env: { readonly relativePath: \"env.ts\" };\n App: { readonly relativePath: \"app.ts\" };\n Callbacks: { readonly relativePath: \"callbacks.ts\" };\n Spec: { readonly relativePath: SpecModulePath.SpecModulePath };\n Impl: { readonly relativePath: ImplModulePath };\n Table: { readonly relativePath: TableModulePath };\n Http: { readonly relativePath: \"http.ts\" };\n Crons: { readonly relativePath: \"crons.ts\" };\n Auth: { readonly relativePath: \"auth.ts\" };\n Config: {};\n}>;\n\nexport const Kind = Data.taggedEnum<Kind>();\nexport const Declaration = Schema.TaggedUnion({\n Spec: { relativePath: SpecModulePath.SpecModulePath },\n Table: { relativePath: TableModulePath },\n});\nexport type Declaration = typeof Declaration.Type;\n\nexport const planDeclarations = (\n declarations: Array.NonEmptyReadonlyArray<Declaration>,\n affectedImpls: ReadonlyArray<ImplModulePath>,\n path: Path.Path,\n): {\n readonly tables: ReadonlyArray<TableModule>;\n readonly paths: ReadonlyArray<ImplModulePath>;\n} => {\n const plan = Array.reduce(\n declarations,\n {\n tables: Chunk.empty<TableModule>(),\n paths: HashSet.fromIterable(affectedImpls),\n },\n (state, declaration) =>\n Declaration.match(declaration, {\n Spec: ({ relativePath }) => ({\n ...state,\n paths: HashSet.add(state.paths, SpecModulePath.toImpl(relativePath)),\n }),\n Table: ({ relativePath }) => ({\n ...state,\n tables: Chunk.append(state.tables, {\n relativePath,\n tableName: path.parse(relativePath).name,\n }),\n }),\n }),\n );\n return {\n tables: Chunk.toReadonlyArray(plan.tables),\n paths: Array.fromIterable(plan.paths),\n };\n};\n\nexport type EntryPoint = Kind & {\n readonly absolutePath: string;\n readonly inputPath: string;\n};\nexport type OptionalFile = \"Http\" | \"Crons\" | \"Auth\";\n\nexport const isOptional = Predicate.or(\n Kind.$is(\"Http\"),\n Predicate.or(Kind.$is(\"Crons\"), Kind.$is(\"Auth\")),\n);\n\nexport const parse = (\n relativePath: string,\n): Option.Option<Exclude<Kind, { readonly _tag: \"Config\" }>> => {\n if (relativePath === \"env.ts\") return Option.some(Kind.Env({ relativePath }));\n if (relativePath === \"app.ts\") return Option.some(Kind.App({ relativePath }));\n if (relativePath === \"callbacks.ts\")\n return Option.some(Kind.Callbacks({ relativePath }));\n if (relativePath === \"http.ts\")\n return Option.some(Kind.Http({ relativePath }));\n if (relativePath === \"crons.ts\")\n return Option.some(Kind.Crons({ relativePath }));\n if (relativePath === \"auth.ts\")\n return Option.some(Kind.Auth({ relativePath }));\n const tablePath = Schema.decodeOption(TableModulePath)(relativePath);\n if (Option.isSome(tablePath))\n return Option.some(Kind.Table({ relativePath: tablePath.value }));\n const specPath = Schema.decodeOption(SpecModulePath.SpecModulePath)(\n relativePath,\n );\n if (Option.isSome(specPath))\n return Option.some(Kind.Spec({ relativePath: specPath.value }));\n return Schema.decodeOption(ImplModulePath)(relativePath).pipe(\n Option.map((implPath) => Kind.Impl({ relativePath: implPath })),\n );\n};\n\nexport const discover = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const tryEntry = Effect.fnUntraced(function* (\n kind: Exclude<Kind, { readonly _tag: \"Config\" }>,\n ) {\n const absolutePath = path.join(confectDirectory, kind.relativePath);\n if (!(yield* fs.exists(absolutePath))) {\n return Option.none<EntryPoint>();\n }\n return Option.some<EntryPoint>({\n ...kind,\n absolutePath,\n inputPath: yield* fs\n .realPath(absolutePath)\n .pipe(Effect.orElseSucceed(() => absolutePath)),\n });\n });\n\n const declaration = yield* tryEntry(Kind.App({ relativePath: \"app.ts\" }));\n const fixedEntryOptions = yield* Effect.all([\n tryEntry(Kind.Env({ relativePath: \"env.ts\" })),\n Effect.succeed(declaration),\n (yield* ConvexDirectory.target).kind === \"component\"\n ? tryEntry(Kind.Callbacks({ relativePath: \"callbacks.ts\" }))\n : Effect.succeedNone,\n tryEntry(Kind.Http({ relativePath: \"http.ts\" })),\n tryEntry(Kind.Crons({ relativePath: \"crons.ts\" })),\n tryEntry(Kind.Auth({ relativePath: \"auth.ts\" })),\n ]);\n\n const moduleRelativePaths = yield* Effect.all([\n discoverLeafSpecFiles,\n discoverLeafImplFiles,\n discoverTableFiles,\n ]).pipe(Effect.map(Array.flatten));\n const moduleEntryOptions = yield* Effect.forEach(\n Array.getSomes(moduleRelativePaths.map(parse)),\n tryEntry,\n );\n\n // `convex/convex.config.ts` feeds the generated components registry, so\n // edits to it (or to a locally-defined component definition it imports—npm component definitions are externalized and not watched) must re-run\n // codegen.\n const convexDirectory = yield* ConvexDirectory.get;\n const convexConfigEntryOption = yield* Effect.gen(function* () {\n const absolutePath = path.join(convexDirectory, CONVEX_CONFIG_FILENAME);\n // A declared backend's `convex.config.ts` is codegen output, not input.\n if (Option.isSome(declaration) || !(yield* fs.exists(absolutePath))) {\n return Option.none<EntryPoint>();\n }\n return Option.some<EntryPoint>({\n ...Kind.Config(),\n absolutePath,\n inputPath: yield* fs\n .realPath(absolutePath)\n .pipe(Effect.orElseSucceed(() => absolutePath)),\n });\n });\n\n return Array.getSomes([\n ...fixedEntryOptions,\n convexConfigEntryOption,\n ...moduleEntryOptions,\n ]);\n}).pipe(\n Effect.retry({\n times: 3,\n while: (error) =>\n error._tag === \"PlatformError\" && error.reason._tag === \"NotFound\",\n }),\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"EntryPoint.mjs","names":["SpecModulePath.SpecModulePath","SpecModulePath.toImpl"],"sources":["../src/EntryPoint.ts"],"sourcesContent":["import * as Array from \"effect/Array\";\nimport * as Chunk from \"effect/Chunk\";\nimport * as Data from \"effect/Data\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\nimport { ImplModulePath } from \"./ImplModulePath.js\";\nimport * as SpecModulePath from \"./SpecModulePath.js\";\nimport { TableModulePath } from \"./TableModulePath.js\";\nimport { ConfectDirectory } from \"./ConfectDirectory.js\";\nimport { ConvexDirectory } from \"./ConvexDirectory.js\";\nimport { CONVEX_CONFIG_FILENAME } from \"./ConvexConfig.js\";\nimport { discoverLeafImplFiles, discoverLeafSpecFiles } from \"./LeafModule.js\";\nimport { discoverTableFiles, type TableModule } from \"./TableModule.js\";\n\nexport type Kind = Data.TaggedEnum<{\n Env: { readonly relativePath: \"env.ts\" };\n App: { readonly relativePath: \"app.ts\" };\n Callbacks: { readonly relativePath: \"callbacks.ts\" };\n Spec: { readonly relativePath: SpecModulePath.SpecModulePath };\n Impl: { readonly relativePath: ImplModulePath };\n Table: { readonly relativePath: TableModulePath };\n Http: { readonly relativePath: \"http.ts\" };\n Crons: { readonly relativePath: \"crons.ts\" };\n Auth: { readonly relativePath: \"auth.ts\" };\n Config: {};\n}>;\n\nexport const Kind = Data.taggedEnum<Kind>();\nexport const Declaration = Schema.TaggedUnion({\n Spec: { relativePath: SpecModulePath.SpecModulePath },\n Table: { relativePath: TableModulePath },\n});\nexport type Declaration = typeof Declaration.Type;\n\nexport const planDeclarations = (\n declarations: Array.NonEmptyReadonlyArray<Declaration>,\n affectedImpls: ReadonlyArray<ImplModulePath>,\n path: Path.Path,\n): {\n readonly tables: ReadonlyArray<TableModule>;\n readonly paths: ReadonlyArray<ImplModulePath>;\n} => {\n const plan = Array.reduce(\n declarations,\n {\n tables: Chunk.empty<TableModule>(),\n paths: HashSet.fromIterable(affectedImpls),\n },\n (state, declaration) =>\n Declaration.match(declaration, {\n Spec: ({ relativePath }) => ({\n ...state,\n paths: HashSet.add(state.paths, SpecModulePath.toImpl(relativePath)),\n }),\n Table: ({ relativePath }) => ({\n ...state,\n tables: Chunk.append(state.tables, {\n relativePath,\n tableName: path.parse(relativePath).name,\n }),\n }),\n }),\n );\n return {\n tables: Chunk.toReadonlyArray(plan.tables),\n paths: Array.fromIterable(plan.paths),\n };\n};\n\nexport type EntryPoint = Kind & {\n readonly absolutePath: string;\n readonly inputPath: string;\n};\nexport type OptionalFile = \"Http\" | \"Crons\" | \"Auth\";\n\nexport const isOptional = Predicate.or(\n Kind.$is(\"Http\"),\n Predicate.or(Kind.$is(\"Crons\"), Kind.$is(\"Auth\")),\n);\n\nexport const parse = (\n relativePath: string,\n): Option.Option<Exclude<Kind, { readonly _tag: \"Config\" }>> => {\n if (relativePath === \"env.ts\") return Option.some(Kind.Env({ relativePath }));\n if (relativePath === \"app.ts\") return Option.some(Kind.App({ relativePath }));\n if (relativePath === \"callbacks.ts\")\n return Option.some(Kind.Callbacks({ relativePath }));\n if (relativePath === \"http.ts\")\n return Option.some(Kind.Http({ relativePath }));\n if (relativePath === \"crons.ts\")\n return Option.some(Kind.Crons({ relativePath }));\n if (relativePath === \"auth.ts\")\n return Option.some(Kind.Auth({ relativePath }));\n const tablePath = Schema.decodeOption(TableModulePath)(relativePath);\n if (Option.isSome(tablePath))\n return Option.some(Kind.Table({ relativePath: tablePath.value }));\n const specPath = Schema.decodeOption(SpecModulePath.SpecModulePath)(\n relativePath,\n );\n if (Option.isSome(specPath))\n return Option.some(Kind.Spec({ relativePath: specPath.value }));\n return Schema.decodeOption(ImplModulePath)(relativePath).pipe(\n Option.map((implPath) => Kind.Impl({ relativePath: implPath })),\n );\n};\n\nexport const discover = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const tryEntry = Effect.fnUntraced(function* (\n kind: Exclude<Kind, { readonly _tag: \"Config\" }>,\n ) {\n const absolutePath = path.join(confectDirectory, kind.relativePath);\n if (!(yield* fs.exists(absolutePath))) {\n return Option.none<EntryPoint>();\n }\n return Option.some<EntryPoint>({\n ...kind,\n absolutePath,\n inputPath: yield* fs\n .realPath(absolutePath)\n .pipe(Effect.orElseSucceed(() => absolutePath)),\n });\n });\n\n const declaration = yield* tryEntry(Kind.App({ relativePath: \"app.ts\" }));\n const fixedEntryOptions = yield* Effect.all([\n tryEntry(Kind.Env({ relativePath: \"env.ts\" })),\n Effect.succeed(declaration),\n (yield* ConvexDirectory.target).kind === \"component\"\n ? tryEntry(Kind.Callbacks({ relativePath: \"callbacks.ts\" }))\n : Effect.succeedNone,\n tryEntry(Kind.Http({ relativePath: \"http.ts\" })),\n tryEntry(Kind.Crons({ relativePath: \"crons.ts\" })),\n tryEntry(Kind.Auth({ relativePath: \"auth.ts\" })),\n ]);\n\n const moduleRelativePaths = yield* Effect.all([\n discoverLeafSpecFiles,\n discoverLeafImplFiles,\n discoverTableFiles,\n ]).pipe(Effect.map(Array.flatten));\n const moduleEntryOptions = yield* Effect.forEach(\n Array.getSomes(moduleRelativePaths.map(parse)),\n tryEntry,\n );\n\n // `convex/convex.config.ts` feeds the generated components registry, so\n // edits to it (or to a locally-defined component definition it imports—npm component definitions are externalized and not watched) must re-run\n // codegen.\n const convexDirectory = yield* ConvexDirectory.get;\n const convexConfigEntryOption = yield* Effect.gen(function* () {\n const absolutePath = path.join(convexDirectory, CONVEX_CONFIG_FILENAME);\n // A declared backend's `convex.config.ts` is codegen output, not input.\n if (Option.isSome(declaration) || !(yield* fs.exists(absolutePath))) {\n return Option.none<EntryPoint>();\n }\n return Option.some<EntryPoint>({\n ...Kind.Config(),\n absolutePath,\n inputPath: yield* fs\n .realPath(absolutePath)\n .pipe(Effect.orElseSucceed(() => absolutePath)),\n });\n });\n\n return Array.getSomes([\n ...fixedEntryOptions,\n convexConfigEntryOption,\n ...moduleEntryOptions,\n ]);\n}).pipe(\n Effect.retry({\n times: 3,\n while: (error) =>\n error._tag === \"PlatformError\" && error.reason._tag === \"NotFound\",\n }),\n);\n"],"mappings":"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"}
@@ -12,11 +12,13 @@ import * as Path from "effect/Path";
12
12
  import * as HashSet from "effect/HashSet";
13
13
  import * as Match from "effect/Match";
14
14
  import * as Option from "effect/Option";
15
+ import * as Context from "effect/Context";
15
16
  import * as Schema from "effect/Schema";
16
17
  import * as Console from "effect/Console";
17
18
  import * as Layer from "effect/Layer";
18
19
  import * as NodeWorker from "@effect/platform-node/NodeWorker";
19
20
  import { fork } from "node:child_process";
21
+ import * as Pool from "effect/Pool";
20
22
  import * as LogLevel from "effect/LogLevel";
21
23
  import * as References from "effect/References";
22
24
  import * as Rpc from "effect/rpc/Rpc";
@@ -35,7 +37,7 @@ const RequestContext = Schema.Struct({
35
37
  });
36
38
  var EvaluationError = class extends Schema.TaggedError()("EvaluationError", { diagnostic: Schema.String }) {};
37
39
  const Failure = Schema.Union([EvaluationError, ComponentNodeGroupError]);
38
- const requests = RpcGroup.make(Rpc.make("Previous", {
40
+ const requests = RpcGroup.make(Rpc.make("Ready", { success: Schema.Void }), Rpc.make("Previous", {
39
41
  payload: RequestContext,
40
42
  success: FunctionPaths,
41
43
  error: Failure
@@ -60,6 +62,29 @@ const requests = RpcGroup.make(Rpc.make("Previous", {
60
62
  success: GenerationSnapshot,
61
63
  error: Failure
62
64
  }));
65
+ const acquireWorker = Effect.gen(function* () {
66
+ const child = yield* Effect.acquireRelease(Effect.sync(() => fork(new URL("../dist/EvaluationWorker.mjs", import.meta.url), { serialization: "advanced" })), (evaluator) => Effect.callback((resume) => {
67
+ if (evaluator.exitCode !== null || evaluator.signalCode !== null) {
68
+ resume(Effect.void);
69
+ return;
70
+ }
71
+ evaluator.once("exit", () => resume(Effect.void));
72
+ evaluator.kill("SIGKILL");
73
+ }));
74
+ const protocol = yield* Layer.build(RpcClient.layerProtocolWorker({ size: 1 }).pipe(Layer.provide(NodeWorker.layer(() => child))));
75
+ const client = yield* RpcClient.make(requests).pipe(Effect.provideContext(protocol));
76
+ yield* client.Ready();
77
+ yield* Effect.logDebug("Evaluator ready").pipe(Effect.annotateLogs({ pid: child.pid }));
78
+ return {
79
+ child,
80
+ client
81
+ };
82
+ });
83
+ var Standby = class extends Context.Service()("@confect/cli/Evaluation/Standby") {};
84
+ const prewarmedLayer = Layer.effect(Standby, Pool.make({
85
+ acquire: acquireWorker,
86
+ size: 1
87
+ }));
63
88
  const withWorker = Effect.fn("Evaluation.withWorker")(function* (run) {
64
89
  const requestContext = {
65
90
  projectRoot: yield* ProjectRoot.get,
@@ -72,17 +97,18 @@ const withWorker = Effect.fn("Evaluation.withWorker")(function* (run) {
72
97
  minimumLogLevel: yield* References.MinimumLogLevel
73
98
  };
74
99
  return yield* Effect.scoped(Effect.gen(function* () {
75
- const child = yield* Effect.acquireRelease(Effect.sync(() => fork(new URL("../dist/EvaluationWorker.mjs", import.meta.url), { serialization: "advanced" })), (evaluator) => Effect.callback((resume) => {
76
- if (evaluator.exitCode !== null || evaluator.signalCode !== null) {
77
- resume(Effect.void);
78
- return;
79
- }
80
- evaluator.once("exit", () => resume(Effect.void));
81
- evaluator.kill("SIGKILL");
82
- }));
83
- return yield* Effect.gen(function* () {
84
- return yield* run(yield* RpcClient.make(requests), requestContext);
85
- }).pipe(Effect.provide(RpcClient.layerProtocolWorker({ size: 1 }).pipe(Layer.provide(NodeWorker.layer(() => child)))));
100
+ const standby = yield* Effect.serviceOption(Standby);
101
+ return yield* run((yield* Option.match(standby, {
102
+ onNone: () => acquireWorker,
103
+ onSome: (pool) => Effect.gen(function* () {
104
+ while (true) {
105
+ const candidate = yield* Pool.get(pool);
106
+ yield* Effect.addFinalizer(() => Pool.invalidate(pool, candidate));
107
+ if (candidate.child.connected && candidate.child.exitCode === null && candidate.child.signalCode === null) return candidate;
108
+ yield* Pool.invalidate(pool, candidate);
109
+ }
110
+ })
111
+ })).client, requestContext);
86
112
  })).pipe(Effect.catchTags({
87
113
  WorkerError: (error) => Effect.fail(new EvaluationError({ diagnostic: error.message })),
88
114
  RpcClientError: (error) => Effect.fail(new EvaluationError({ diagnostic: error.message }))
@@ -112,6 +138,6 @@ const catchAndLog = (effect) => effect.pipe(Effect.asSome, Effect.catchTags({
112
138
  ComponentNodeGroupError: (error) => logCodegenError(error).pipe(Effect.as(Option.none()))
113
139
  }));
114
140
  //#endregion
115
- export { EvaluationError, RequestContext, catchAndLog, generateSnapshot, loadPreviousFunctionPaths, requests, updateDeclarations, validate };
141
+ export { EvaluationError, RequestContext, catchAndLog, generateSnapshot, loadPreviousFunctionPaths, prewarmedLayer, requests, updateDeclarations, validate };
116
142
 
117
143
  //# sourceMappingURL=Evaluation.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Evaluation.mjs","names":["GenerationSnapshot.GenerationSnapshot","EntryPoint.Declaration","GenerationSnapshot.functionPaths"],"sources":["../src/Evaluation.ts"],"sourcesContent":["import * as NodeWorker from \"@effect/platform-node/NodeWorker\";\nimport { fork } from \"node:child_process\";\nimport * as Console from \"effect/Console\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Layer from \"effect/Layer\";\nimport * as LogLevel from \"effect/LogLevel\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Schema from \"effect/Schema\";\nimport * as References from \"effect/References\";\nimport * as Rpc from \"effect/rpc/Rpc\";\nimport * as RpcClient from \"effect/rpc/RpcClient\";\nimport type { RpcClientError } from \"effect/rpc/RpcClientError\";\nimport * as RpcGroup from \"effect/rpc/RpcGroup\";\nimport type * as Array from \"effect/Array\";\nimport * as Match from \"effect/Match\";\nimport { ComponentNodeGroupError, logCodegenError } from \"./CodegenError\";\nimport * as EntryPoint from \"./EntryPoint\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport { FunctionPaths } from \"./FunctionPaths\";\nimport { ImplModulePath } from \"./ImplModulePath\";\nimport { ProjectRoot } from \"./ProjectRoot\";\n\nexport const RequestContext = Schema.Struct({\n projectRoot: Schema.String,\n confectDirectory: Schema.String,\n convexDirectory: Schema.String,\n target: Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"app\") }),\n Schema.Struct({\n kind: Schema.Literal(\"component\"),\n definition: Schema.String,\n }),\n ]),\n minimumLogLevel: Schema.Literals(LogLevel.values),\n});\nexport type RequestContext = typeof RequestContext.Type;\n\nexport class EvaluationError extends Schema.TaggedError<EvaluationError>()(\n \"EvaluationError\",\n { diagnostic: Schema.String },\n) {}\n\n// A rejected Node group stays typed so the caller can restore component output.\nconst Failure = Schema.Union([EvaluationError, ComponentNodeGroupError]);\n\nexport const requests = RpcGroup.make(\n Rpc.make(\"Previous\", {\n payload: RequestContext,\n success: FunctionPaths,\n error: Failure,\n }),\n Rpc.make(\"Generate\", {\n payload: RequestContext,\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n Rpc.make(\"Validate\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n paths: Schema.Array(ImplModulePath),\n }),\n success: Schema.Void,\n error: Failure,\n }),\n Rpc.make(\"Update\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Schema.NonEmptyArray(EntryPoint.Declaration),\n paths: Schema.Array(ImplModulePath),\n }),\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n);\n\nconst withWorker = Effect.fn(\"Evaluation.withWorker\")(function* <A>(\n run: (\n client: RpcClient.RpcClient<RpcGroup.Rpcs<typeof requests>, RpcClientError>,\n requestContext: RequestContext,\n ) => Effect.Effect<\n A,\n EvaluationError | ComponentNodeGroupError | RpcClientError\n >,\n) {\n const requestContext = {\n projectRoot: yield* ProjectRoot.get,\n confectDirectory: yield* ConfectDirectory.get,\n convexDirectory: yield* ConvexDirectory.get,\n target: Match.value(yield* ConvexDirectory.target).pipe(\n Match.when({ kind: \"app\" }, () => ({ kind: \"app\" as const })),\n Match.when({ kind: \"component\" }, ({ scope }) => ({\n kind: \"component\" as const,\n definition: scope.slice(\"component:\".length),\n })),\n Match.exhaustive,\n ),\n minimumLogLevel: yield* References.MinimumLogLevel,\n };\n return yield* Effect.scoped(\n Effect.gen(function* () {\n const child = yield* Effect.acquireRelease(\n Effect.sync(() =>\n fork(new URL(\"../dist/EvaluationWorker.mjs\", import.meta.url), {\n serialization: \"advanced\",\n }),\n ),\n (evaluator) =>\n Effect.callback<void>((resume) => {\n if (evaluator.exitCode !== null || evaluator.signalCode !== null) {\n resume(Effect.void);\n return;\n }\n evaluator.once(\"exit\", () => resume(Effect.void));\n evaluator.kill(\"SIGKILL\");\n }),\n );\n return yield* Effect.gen(function* () {\n const client = yield* RpcClient.make(requests);\n return yield* run(client, requestContext);\n }).pipe(\n Effect.provide(\n RpcClient.layerProtocolWorker({ size: 1 }).pipe(\n Layer.provide(NodeWorker.layer(() => child)),\n ),\n ),\n );\n }),\n ).pipe(\n Effect.catchTags({\n WorkerError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n RpcClientError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n }),\n );\n});\n\nexport const loadPreviousFunctionPaths = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n if (\n !(yield* fs.exists(path.join(confectDirectory, \"_generated\", \"spec.ts\")))\n ) {\n return FunctionPaths.make(HashSet.empty());\n }\n return yield* withWorker((client, requestContext) =>\n client.Previous(requestContext),\n );\n});\n\nexport const generateSnapshot = withWorker((client, requestContext) =>\n client.Generate(requestContext),\n);\n\nexport const generate = generateSnapshot.pipe(\n Effect.map(GenerationSnapshot.functionPaths),\n);\n\nexport const updateDeclarations = (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Array.NonEmptyReadonlyArray<EntryPoint.Declaration>,\n paths: ReadonlyArray<ImplModulePath>,\n) =>\n withWorker((client, requestContext) =>\n client.Update({\n ...requestContext,\n snapshot,\n declarations,\n paths,\n }),\n );\n\nexport const validate = (paths: ReadonlyArray<ImplModulePath>) =>\n withWorker((client, requestContext) =>\n client.Validate({ ...requestContext, paths }),\n );\n\nexport const catchAndLog = <A, R>(\n effect: Effect.Effect<A, EvaluationError | ComponentNodeGroupError, R>,\n): Effect.Effect<Option.Option<A>, never, R> =>\n effect.pipe(\n Effect.asSome,\n Effect.catchTags({\n EvaluationError: ({ diagnostic }) =>\n Console.error(diagnostic).pipe(Effect.as(Option.none<A>())),\n ComponentNodeGroupError: (error) =>\n logCodegenError(error).pipe(Effect.as(Option.none<A>())),\n }),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"Evaluation.mjs","names":["GenerationSnapshot.GenerationSnapshot","EntryPoint.Declaration","GenerationSnapshot.functionPaths"],"sources":["../src/Evaluation.ts"],"sourcesContent":["import * as NodeWorker from \"@effect/platform-node/NodeWorker\";\nimport { fork } from \"node:child_process\";\nimport * as Console from \"effect/Console\";\nimport * as Context from \"effect/Context\";\nimport * as Pool from \"effect/Pool\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Layer from \"effect/Layer\";\nimport * as LogLevel from \"effect/LogLevel\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Schema from \"effect/Schema\";\nimport * as References from \"effect/References\";\nimport * as Rpc from \"effect/rpc/Rpc\";\nimport * as RpcClient from \"effect/rpc/RpcClient\";\nimport type { RpcClientError } from \"effect/rpc/RpcClientError\";\nimport * as RpcGroup from \"effect/rpc/RpcGroup\";\nimport type * as Array from \"effect/Array\";\nimport * as Match from \"effect/Match\";\nimport { ComponentNodeGroupError, logCodegenError } from \"./CodegenError.js\";\nimport * as EntryPoint from \"./EntryPoint.js\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot.js\";\nimport { ConfectDirectory } from \"./ConfectDirectory.js\";\nimport { ConvexDirectory } from \"./ConvexDirectory.js\";\nimport { FunctionPaths } from \"./FunctionPaths.js\";\nimport { ImplModulePath } from \"./ImplModulePath.js\";\nimport { ProjectRoot } from \"./ProjectRoot.js\";\n\nexport const RequestContext = Schema.Struct({\n projectRoot: Schema.String,\n confectDirectory: Schema.String,\n convexDirectory: Schema.String,\n target: Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"app\") }),\n Schema.Struct({\n kind: Schema.Literal(\"component\"),\n definition: Schema.String,\n }),\n ]),\n minimumLogLevel: Schema.Literals(LogLevel.values),\n});\nexport type RequestContext = typeof RequestContext.Type;\n\nexport class EvaluationError extends Schema.TaggedError<EvaluationError>()(\n \"EvaluationError\",\n { diagnostic: Schema.String },\n) {}\n\n// A rejected Node group stays typed so the caller can restore component output.\nconst Failure = Schema.Union([EvaluationError, ComponentNodeGroupError]);\n\nexport const requests = RpcGroup.make(\n Rpc.make(\"Ready\", { success: Schema.Void }),\n Rpc.make(\"Previous\", {\n payload: RequestContext,\n success: FunctionPaths,\n error: Failure,\n }),\n Rpc.make(\"Generate\", {\n payload: RequestContext,\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n Rpc.make(\"Validate\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n paths: Schema.Array(ImplModulePath),\n }),\n success: Schema.Void,\n error: Failure,\n }),\n Rpc.make(\"Update\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Schema.NonEmptyArray(EntryPoint.Declaration),\n paths: Schema.Array(ImplModulePath),\n }),\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n);\n\nconst acquireWorker = Effect.gen(function* () {\n const child = yield* Effect.acquireRelease(\n Effect.sync(() =>\n fork(new URL(\"../dist/EvaluationWorker.mjs\", import.meta.url), {\n serialization: \"advanced\",\n }),\n ),\n (evaluator) =>\n Effect.callback<void>((resume) => {\n if (evaluator.exitCode !== null || evaluator.signalCode !== null) {\n resume(Effect.void);\n return;\n }\n evaluator.once(\"exit\", () => resume(Effect.void));\n evaluator.kill(\"SIGKILL\");\n }),\n );\n const protocol = yield* Layer.build(\n RpcClient.layerProtocolWorker({ size: 1 }).pipe(\n Layer.provide(NodeWorker.layer(() => child)),\n ),\n );\n const client = yield* RpcClient.make(requests).pipe(\n Effect.provideContext(protocol),\n );\n yield* client.Ready();\n yield* Effect.logDebug(\"Evaluator ready\").pipe(\n Effect.annotateLogs({ pid: child.pid }),\n );\n return { child, client };\n});\n\nclass Standby extends Context.Service<\n Standby,\n Pool.Pool<\n Effect.Success<typeof acquireWorker>,\n Effect.Error<typeof acquireWorker>\n >\n>()(\"@confect/cli/Evaluation/Standby\") {}\n\n// Each evaluator handles one evaluation to isolate globals and module caches.\n// Discarding it bounds memory and recovers from crashes. Dev prepares the next\n// evaluator between saves.\nexport const prewarmedLayer = Layer.effect(\n Standby,\n Pool.make({ acquire: acquireWorker, size: 1 }),\n);\n\nconst withWorker = Effect.fn(\"Evaluation.withWorker\")(function* <A>(\n run: (\n client: RpcClient.RpcClient<RpcGroup.Rpcs<typeof requests>, RpcClientError>,\n requestContext: RequestContext,\n ) => Effect.Effect<\n A,\n EvaluationError | ComponentNodeGroupError | RpcClientError\n >,\n) {\n const requestContext = {\n projectRoot: yield* ProjectRoot.get,\n confectDirectory: yield* ConfectDirectory.get,\n convexDirectory: yield* ConvexDirectory.get,\n target: Match.value(yield* ConvexDirectory.target).pipe(\n Match.when({ kind: \"app\" }, () => ({ kind: \"app\" as const })),\n Match.when({ kind: \"component\" }, ({ scope }) => ({\n kind: \"component\" as const,\n definition: scope.slice(\"component:\".length),\n })),\n Match.exhaustive,\n ),\n minimumLogLevel: yield* References.MinimumLogLevel,\n };\n return yield* Effect.scoped(\n Effect.gen(function* () {\n const standby = yield* Effect.serviceOption(Standby);\n const worker = yield* Option.match(standby, {\n onNone: () => acquireWorker,\n onSome: (pool) =>\n Effect.gen(function* () {\n while (true) {\n const candidate = yield* Pool.get(pool);\n yield* Effect.addFinalizer(() =>\n Pool.invalidate(pool, candidate),\n );\n // An idle exit has no pending RPC to fail.\n if (\n candidate.child.connected &&\n candidate.child.exitCode === null &&\n candidate.child.signalCode === null\n )\n return candidate;\n yield* Pool.invalidate(pool, candidate);\n }\n }),\n });\n return yield* run(worker.client, requestContext);\n }),\n ).pipe(\n Effect.catchTags({\n WorkerError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n RpcClientError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n }),\n );\n});\n\nexport const loadPreviousFunctionPaths = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n if (\n !(yield* fs.exists(path.join(confectDirectory, \"_generated\", \"spec.ts\")))\n ) {\n return FunctionPaths.make(HashSet.empty());\n }\n return yield* withWorker((client, requestContext) =>\n client.Previous(requestContext),\n );\n});\n\nexport const generateSnapshot = withWorker((client, requestContext) =>\n client.Generate(requestContext),\n);\n\nexport const generate = generateSnapshot.pipe(\n Effect.map(GenerationSnapshot.functionPaths),\n);\n\nexport const updateDeclarations = (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Array.NonEmptyReadonlyArray<EntryPoint.Declaration>,\n paths: ReadonlyArray<ImplModulePath>,\n) =>\n withWorker((client, requestContext) =>\n client.Update({\n ...requestContext,\n snapshot,\n declarations,\n paths,\n }),\n );\n\nexport const validate = (paths: ReadonlyArray<ImplModulePath>) =>\n withWorker((client, requestContext) =>\n client.Validate({ ...requestContext, paths }),\n );\n\nexport const catchAndLog = <A, R>(\n effect: Effect.Effect<A, EvaluationError | ComponentNodeGroupError, R>,\n): Effect.Effect<Option.Option<A>, never, R> =>\n effect.pipe(\n Effect.asSome,\n Effect.catchTags({\n EvaluationError: ({ diagnostic }) =>\n Console.error(diagnostic).pipe(Effect.as(Option.none<A>())),\n ComponentNodeGroupError: (error) =>\n logCodegenError(error).pipe(Effect.as(Option.none<A>())),\n }),\n );\n"],"mappings":"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"}
@@ -15,6 +15,7 @@ import * as Schema from "effect/Schema";
15
15
  import * as esbuild from "esbuild";
16
16
  import * as Layer from "effect/Layer";
17
17
  import * as IdScope from "@confect/core/IdScope";
18
+ import * as Schedule from "effect/Schedule";
18
19
  import * as References from "effect/References";
19
20
  import * as NodeWorkerRunner from "@effect/platform-node/NodeWorkerRunner";
20
21
  import * as RpcServer from "effect/rpc/RpcServer";
@@ -34,12 +35,23 @@ const evaluate = (requestContext, effect) => effect.pipe(Effect.provideService(R
34
35
  return Effect.fail(new EvaluationError({ diagnostic: Option.isSome(failure) && isCodegenError(failure.value) ? renderCodegenError(failure.value) : Cause.pretty(cause) }));
35
36
  }));
36
37
  const handlers = requests.toLayer({
38
+ Ready: () => Effect.void,
37
39
  Previous: (requestContext) => evaluate(requestContext, loadPreviousFunctionPaths),
38
40
  Generate: (requestContext) => evaluate(requestContext, generateWithSnapshot.pipe(Effect.map(({ snapshot }) => snapshot))),
39
41
  Validate: (request) => evaluate(request, validateImplFiles(request.paths)),
40
42
  Update: (request) => evaluate(request, updateDeclarations(request.snapshot, request.declarations, request.paths))
41
43
  });
42
- RpcServer.layer(requests).pipe(Layer.provide(handlers), Layer.provide(NodeServices.layer), Layer.provide(RpcServer.layerProtocolWorkerRunner.pipe(Layer.provide(NodeWorkerRunner.layer))), Layer.launch, Effect.ensuring(Effect.promise(() => esbuild.stop())), NodeRuntime.runMain);
44
+ const parentPid = process.ppid;
45
+ process.once("disconnect", () => process.exit(0));
46
+ const watchParent = Effect.sync(() => {
47
+ if (!process.connected || process.ppid !== parentPid) process.exit(0);
48
+ try {
49
+ process.kill(parentPid, 0);
50
+ } catch {
51
+ process.exit(0);
52
+ }
53
+ }).pipe(Effect.repeat({ schedule: Schedule.spaced("1 second") }));
54
+ RpcServer.layer(requests).pipe(Layer.provide(handlers), Layer.provide(NodeServices.layer), Layer.provide(RpcServer.layerProtocolWorkerRunner.pipe(Layer.provide(NodeWorkerRunner.layer))), Layer.launch, Effect.raceFirst(watchParent), Effect.ensuring(Effect.promise(() => esbuild.stop())), NodeRuntime.runMain);
43
55
  //#endregion
44
56
  export {};
45
57
 
@@ -1 +1 @@
1
- {"version":3,"file":"EvaluationWorker.mjs","names":["CodegenError.ComponentNodeGroupError","CodegenError.isCodegenError","CodegenError.renderCodegenError"],"sources":["../src/EvaluationWorker.ts"],"sourcesContent":["import * as NodeRuntime from \"@effect/platform-node/NodeRuntime\";\nimport * as NodeServices from \"@effect/platform-node/NodeServices\";\nimport * as NodeWorkerRunner from \"@effect/platform-node/NodeWorkerRunner\";\nimport * as IdScope from \"@confect/core/IdScope\";\nimport * as Cause from \"effect/Cause\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as References from \"effect/References\";\nimport * as Schema from \"effect/Schema\";\nimport * as RpcServer from \"effect/rpc/RpcServer\";\nimport * as esbuild from \"esbuild\";\nimport * as CodegenError from \"./CodegenError\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport type { RequestContext } from \"./Evaluation\";\nimport { EvaluationError, requests } from \"./Evaluation\";\nimport { validateImplFiles } from \"./LeafModule\";\nimport { ProjectRoot } from \"./ProjectRoot\";\nimport {\n generateWithSnapshot,\n loadPreviousFunctionPaths,\n updateDeclarations,\n} from \"./confect/codegen\";\n\nconst evaluate = <A, E, R>(\n requestContext: RequestContext,\n effect: Effect.Effect<A, E, R>,\n) =>\n effect.pipe(\n Effect.provideService(\n References.MinimumLogLevel,\n requestContext.minimumLogLevel,\n ),\n Effect.provideService(ProjectRoot, {\n get: Effect.succeed(requestContext.projectRoot),\n }),\n Effect.provideService(ConfectDirectory, {\n get: Effect.succeed(requestContext.confectDirectory),\n }),\n Effect.provideService(ConvexDirectory, {\n get: Effect.succeed(requestContext.convexDirectory),\n target: Match.value(requestContext.target).pipe(\n Match.when({ kind: \"app\" }, () => ({\n kind: \"app\" as const,\n scope: IdScope.app,\n })),\n Match.when({ kind: \"component\" }, ({ definition }) => ({\n kind: \"component\" as const,\n scope: IdScope.component(definition),\n })),\n Match.exhaustive,\n ),\n }),\n Effect.catchCause(\n (\n cause,\n ): Effect.Effect<\n never,\n EvaluationError | CodegenError.ComponentNodeGroupError\n > => {\n const failure = Cause.findErrorOption(cause);\n if (\n Option.isSome(failure) &&\n Schema.is(CodegenError.ComponentNodeGroupError)(failure.value)\n )\n return Effect.fail(failure.value);\n return Effect.fail(\n new EvaluationError({\n diagnostic:\n Option.isSome(failure) &&\n CodegenError.isCodegenError(failure.value)\n ? CodegenError.renderCodegenError(failure.value)\n : Cause.pretty(cause),\n }),\n );\n },\n ),\n );\n\nconst handlers = requests.toLayer({\n Previous: (requestContext) =>\n evaluate(requestContext, loadPreviousFunctionPaths),\n Generate: (requestContext) =>\n evaluate(\n requestContext,\n generateWithSnapshot.pipe(Effect.map(({ snapshot }) => snapshot)),\n ),\n Validate: (request) => evaluate(request, validateImplFiles(request.paths)),\n Update: (request) =>\n evaluate(\n request,\n updateDeclarations(request.snapshot, request.declarations, request.paths),\n ),\n});\n\nRpcServer.layer(requests).pipe(\n Layer.provide(handlers),\n Layer.provide(NodeServices.layer),\n Layer.provide(\n RpcServer.layerProtocolWorkerRunner.pipe(\n Layer.provide(NodeWorkerRunner.layer),\n ),\n ),\n Layer.launch,\n Effect.ensuring(Effect.promise(() => esbuild.stop())),\n NodeRuntime.runMain,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,YACJ,gBACA,WAEA,OAAO,KACL,OAAO,eACL,WAAW,iBACX,eAAe,eACjB,GACA,OAAO,eAAe,aAAa,EACjC,KAAK,OAAO,QAAQ,eAAe,WAAW,EAChD,CAAC,GACD,OAAO,eAAe,kBAAkB,EACtC,KAAK,OAAO,QAAQ,eAAe,gBAAgB,EACrD,CAAC,GACD,OAAO,eAAe,iBAAiB;CACrC,KAAK,OAAO,QAAQ,eAAe,eAAe;CAClD,QAAQ,MAAM,MAAM,eAAe,MAAM,CAAC,CAAC,KACzC,MAAM,KAAK,EAAE,MAAM,MAAM,UAAU;EACjC,MAAM;EACN,OAAO,QAAQ;CACjB,EAAE,GACF,MAAM,KAAK,EAAE,MAAM,YAAY,IAAI,EAAE,kBAAkB;EACrD,MAAM;EACN,OAAO,QAAQ,UAAU,UAAU;CACrC,EAAE,GACF,MAAM,UACR;AACF,CAAC,GACD,OAAO,YAEH,UAIG;CACH,MAAM,UAAU,MAAM,gBAAgB,KAAK;CAC3C,IACE,OAAO,OAAO,OAAO,KACrB,OAAO,GAAGA,uBAAoC,CAAC,CAAC,QAAQ,KAAK,GAE7D,OAAO,OAAO,KAAK,QAAQ,KAAK;CAClC,OAAO,OAAO,KACZ,IAAI,gBAAgB,EAClB,YACE,OAAO,OAAO,OAAO,KACrBC,eAA4B,QAAQ,KAAK,IACrCC,mBAAgC,QAAQ,KAAK,IAC7C,MAAM,OAAO,KAAK,EAC1B,CAAC,CACH;AACF,CACF,CACF;AAEF,MAAM,WAAW,SAAS,QAAQ;CAChC,WAAW,mBACT,SAAS,gBAAgB,yBAAyB;CACpD,WAAW,mBACT,SACE,gBACA,qBAAqB,KAAK,OAAO,KAAK,EAAE,eAAe,QAAQ,CAAC,CAClE;CACF,WAAW,YAAY,SAAS,SAAS,kBAAkB,QAAQ,KAAK,CAAC;CACzE,SAAS,YACP,SACE,SACA,mBAAmB,QAAQ,UAAU,QAAQ,cAAc,QAAQ,KAAK,CAC1E;AACJ,CAAC;AAED,UAAU,MAAM,QAAQ,CAAC,CAAC,KACxB,MAAM,QAAQ,QAAQ,GACtB,MAAM,QAAQ,aAAa,KAAK,GAChC,MAAM,QACJ,UAAU,0BAA0B,KAClC,MAAM,QAAQ,iBAAiB,KAAK,CACtC,CACF,GACA,MAAM,QACN,OAAO,SAAS,OAAO,cAAc,QAAQ,KAAK,CAAC,CAAC,GACpD,YAAY,OACd"}
1
+ {"version":3,"file":"EvaluationWorker.mjs","names":["CodegenError.ComponentNodeGroupError","CodegenError.isCodegenError","CodegenError.renderCodegenError"],"sources":["../src/EvaluationWorker.ts"],"sourcesContent":["import * as NodeRuntime from \"@effect/platform-node/NodeRuntime\";\nimport * as NodeServices from \"@effect/platform-node/NodeServices\";\nimport * as NodeWorkerRunner from \"@effect/platform-node/NodeWorkerRunner\";\nimport * as IdScope from \"@confect/core/IdScope\";\nimport * as Cause from \"effect/Cause\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as References from \"effect/References\";\nimport * as Schema from \"effect/Schema\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as RpcServer from \"effect/rpc/RpcServer\";\nimport * as esbuild from \"esbuild\";\nimport * as CodegenError from \"./CodegenError.js\";\nimport { ConfectDirectory } from \"./ConfectDirectory.js\";\nimport { ConvexDirectory } from \"./ConvexDirectory.js\";\nimport type { RequestContext } from \"./Evaluation.js\";\nimport { EvaluationError, requests } from \"./Evaluation.js\";\nimport { validateImplFiles } from \"./LeafModule.js\";\nimport { ProjectRoot } from \"./ProjectRoot.js\";\nimport {\n generateWithSnapshot,\n loadPreviousFunctionPaths,\n updateDeclarations,\n} from \"./confect/codegen.js\";\n\nconst evaluate = <A, E, R>(\n requestContext: RequestContext,\n effect: Effect.Effect<A, E, R>,\n) =>\n effect.pipe(\n Effect.provideService(\n References.MinimumLogLevel,\n requestContext.minimumLogLevel,\n ),\n Effect.provideService(ProjectRoot, {\n get: Effect.succeed(requestContext.projectRoot),\n }),\n Effect.provideService(ConfectDirectory, {\n get: Effect.succeed(requestContext.confectDirectory),\n }),\n Effect.provideService(ConvexDirectory, {\n get: Effect.succeed(requestContext.convexDirectory),\n target: Match.value(requestContext.target).pipe(\n Match.when({ kind: \"app\" }, () => ({\n kind: \"app\" as const,\n scope: IdScope.app,\n })),\n Match.when({ kind: \"component\" }, ({ definition }) => ({\n kind: \"component\" as const,\n scope: IdScope.component(definition),\n })),\n Match.exhaustive,\n ),\n }),\n Effect.catchCause(\n (\n cause,\n ): Effect.Effect<\n never,\n EvaluationError | CodegenError.ComponentNodeGroupError\n > => {\n const failure = Cause.findErrorOption(cause);\n if (\n Option.isSome(failure) &&\n Schema.is(CodegenError.ComponentNodeGroupError)(failure.value)\n )\n return Effect.fail(failure.value);\n return Effect.fail(\n new EvaluationError({\n diagnostic:\n Option.isSome(failure) &&\n CodegenError.isCodegenError(failure.value)\n ? CodegenError.renderCodegenError(failure.value)\n : Cause.pretty(cause),\n }),\n );\n },\n ),\n );\n\nconst handlers = requests.toLayer({\n Ready: () => Effect.void,\n Previous: (requestContext) =>\n evaluate(requestContext, loadPreviousFunctionPaths),\n Generate: (requestContext) =>\n evaluate(\n requestContext,\n generateWithSnapshot.pipe(Effect.map(({ snapshot }) => snapshot)),\n ),\n Validate: (request) => evaluate(request, validateImplFiles(request.paths)),\n Update: (request) =>\n evaluate(\n request,\n updateDeclarations(request.snapshot, request.declarations, request.paths),\n ),\n});\n\n// Evaluators must not outlive the CLI, even when it is killed without cleanup.\nconst parentPid = process.ppid;\nprocess.once(\"disconnect\", () => process.exit(0));\nconst watchParent = Effect.sync(() => {\n if (!process.connected || process.ppid !== parentPid) process.exit(0);\n try {\n process.kill(parentPid, 0);\n } catch {\n process.exit(0);\n }\n}).pipe(Effect.repeat({ schedule: Schedule.spaced(\"1 second\") }));\n\nRpcServer.layer(requests).pipe(\n Layer.provide(handlers),\n Layer.provide(NodeServices.layer),\n Layer.provide(\n RpcServer.layerProtocolWorkerRunner.pipe(\n Layer.provide(NodeWorkerRunner.layer),\n ),\n ),\n Layer.launch,\n Effect.raceFirst(watchParent),\n Effect.ensuring(Effect.promise(() => esbuild.stop())),\n NodeRuntime.runMain,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAM,YACJ,gBACA,WAEA,OAAO,KACL,OAAO,eACL,WAAW,iBACX,eAAe,eACjB,GACA,OAAO,eAAe,aAAa,EACjC,KAAK,OAAO,QAAQ,eAAe,WAAW,EAChD,CAAC,GACD,OAAO,eAAe,kBAAkB,EACtC,KAAK,OAAO,QAAQ,eAAe,gBAAgB,EACrD,CAAC,GACD,OAAO,eAAe,iBAAiB;CACrC,KAAK,OAAO,QAAQ,eAAe,eAAe;CAClD,QAAQ,MAAM,MAAM,eAAe,MAAM,CAAC,CAAC,KACzC,MAAM,KAAK,EAAE,MAAM,MAAM,UAAU;EACjC,MAAM;EACN,OAAO,QAAQ;CACjB,EAAE,GACF,MAAM,KAAK,EAAE,MAAM,YAAY,IAAI,EAAE,kBAAkB;EACrD,MAAM;EACN,OAAO,QAAQ,UAAU,UAAU;CACrC,EAAE,GACF,MAAM,UACR;AACF,CAAC,GACD,OAAO,YAEH,UAIG;CACH,MAAM,UAAU,MAAM,gBAAgB,KAAK;CAC3C,IACE,OAAO,OAAO,OAAO,KACrB,OAAO,GAAGA,uBAAoC,CAAC,CAAC,QAAQ,KAAK,GAE7D,OAAO,OAAO,KAAK,QAAQ,KAAK;CAClC,OAAO,OAAO,KACZ,IAAI,gBAAgB,EAClB,YACE,OAAO,OAAO,OAAO,KACrBC,eAA4B,QAAQ,KAAK,IACrCC,mBAAgC,QAAQ,KAAK,IAC7C,MAAM,OAAO,KAAK,EAC1B,CAAC,CACH;AACF,CACF,CACF;AAEF,MAAM,WAAW,SAAS,QAAQ;CAChC,aAAa,OAAO;CACpB,WAAW,mBACT,SAAS,gBAAgB,yBAAyB;CACpD,WAAW,mBACT,SACE,gBACA,qBAAqB,KAAK,OAAO,KAAK,EAAE,eAAe,QAAQ,CAAC,CAClE;CACF,WAAW,YAAY,SAAS,SAAS,kBAAkB,QAAQ,KAAK,CAAC;CACzE,SAAS,YACP,SACE,SACA,mBAAmB,QAAQ,UAAU,QAAQ,cAAc,QAAQ,KAAK,CAC1E;AACJ,CAAC;AAGD,MAAM,YAAY,QAAQ;AAC1B,QAAQ,KAAK,oBAAoB,QAAQ,KAAK,CAAC,CAAC;AAChD,MAAM,cAAc,OAAO,WAAW;CACpC,IAAI,CAAC,QAAQ,aAAa,QAAQ,SAAS,WAAW,QAAQ,KAAK,CAAC;CACpE,IAAI;EACF,QAAQ,KAAK,WAAW,CAAC;CAC3B,QAAQ;EACN,QAAQ,KAAK,CAAC;CAChB;AACF,CAAC,CAAC,CAAC,KAAK,OAAO,OAAO,EAAE,UAAU,SAAS,OAAO,UAAU,EAAE,CAAC,CAAC;AAEhE,UAAU,MAAM,QAAQ,CAAC,CAAC,KACxB,MAAM,QAAQ,QAAQ,GACtB,MAAM,QAAQ,aAAa,KAAK,GAChC,MAAM,QACJ,UAAU,0BAA0B,KAClC,MAAM,QAAQ,iBAAiB,KAAK,CACtC,CACF,GACA,MAAM,QACN,OAAO,UAAU,WAAW,GAC5B,OAAO,SAAS,OAAO,cAAc,QAAQ,KAAK,CAAC,CAAC,GACpD,YAAY,OACd"}
@@ -1,9 +1,12 @@
1
1
  import { fromGroupModulePath, modulePath } from "./GroupPath.mjs";
2
+ import { ProjectRoot } from "./ProjectRoot.mjs";
2
3
  import { logFileAdded, logFileModified, logFileRemoved } from "./log.mjs";
4
+ import { UnownedConvexEntrypointError } from "./CodegenError.mjs";
3
5
  import { ConvexDirectory } from "./ConvexDirectory.mjs";
4
6
  import { ConfectDirectory } from "./ConfectDirectory.mjs";
5
7
  import { CodeBlockWriter } from "./CodeBlockWriter.mjs";
6
- import { removePathIfExists, toModuleImportPath } from "./utils.mjs";
8
+ import { crons, declaredHttp, http } from "./templates.mjs";
9
+ import { removePathIfExists, toModuleImportPath, toPosixPath } from "./utils.mjs";
7
10
  import { GroupPaths } from "./GroupPaths.mjs";
8
11
  import { functionPaths, plan } from "./GenerationSnapshot.mjs";
9
12
  import * as Effect from "effect/Effect";
@@ -14,6 +17,80 @@ import { pipe } from "effect/Function";
14
17
  import * as HashSet from "effect/HashSet";
15
18
  import * as Match from "effect/Match";
16
19
  //#region src/FunctionModule.ts
20
+ const RESERVED_CONVEX_TS_FILE_NAMES = /* @__PURE__ */ new Set([
21
+ "schema.ts",
22
+ "http.ts",
23
+ "crons.ts",
24
+ "auth.config.ts",
25
+ "convex.config.ts"
26
+ ]);
27
+ const getEntrypoints = Effect.gen(function* () {
28
+ const fs = yield* FileSystem.FileSystem;
29
+ const path = yield* Path.Path;
30
+ const convex = yield* ConvexDirectory.get;
31
+ const files = yield* fs.readDirectory(convex, { recursive: true });
32
+ const components = files.filter((file) => path.basename(file) === "convex.config.ts" && path.dirname(file) !== ".").map((file) => path.dirname(file) + path.sep);
33
+ return files.filter((file) => {
34
+ const base = path.basename(file);
35
+ return !file.startsWith("_generated" + path.sep) && !components.some((component) => file.startsWith(component)) && /\.(?:js|mjs|cjs|ts|tsx|mts|cts|jsx)$/.test(base) && !base.startsWith(".") && !base.startsWith("#") && (base.match(/\./g)?.length ?? 0) === 1 && base !== "schema.ts" && base !== "schema.js" && !file.includes(" ");
36
+ });
37
+ });
38
+ const tokenize = (source, modulePath, path) => {
39
+ const token = /\s+|\/\/[^\r\n]*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*'|[$A-Z_a-z][$\w]*|[{}()[\].,:;=]/y;
40
+ const tokens = [];
41
+ while (token.lastIndex < source.length) {
42
+ const match = token.exec(source);
43
+ if (match === null) return void 0;
44
+ const value = match[0];
45
+ if (/^\s|^\//.test(value)) continue;
46
+ if (value.startsWith("\"") || value.startsWith("'")) {
47
+ const literal = value.slice(1, -1);
48
+ tokens.push(JSON.stringify(literal.startsWith(".") ? path.resolve(path.dirname(modulePath), literal.replace(/\.js$/, "")) : literal));
49
+ } else tokens.push(value);
50
+ }
51
+ return tokens;
52
+ };
53
+ const matchesShape = (actual, expected) => {
54
+ let index = 0;
55
+ for (const token of expected) {
56
+ if (token === ";" && actual[index] !== ";") continue;
57
+ if (actual[index] === "," && (token === "}" || token === ")")) index++;
58
+ if (actual[index++] !== token) return false;
59
+ }
60
+ return index === actual.length;
61
+ };
62
+ const assertOwnedEntrypoints = Effect.gen(function* () {
63
+ const fs = yield* FileSystem.FileSystem;
64
+ const path = yield* Path.Path;
65
+ const convex = yield* ConvexDirectory.get;
66
+ const confect = yield* ConfectDirectory.get;
67
+ const projectRoot = yield* ProjectRoot.get;
68
+ const importFromConvex = (file) => toModuleImportPath(path.relative(convex, path.join(confect, file)));
69
+ const optional = /* @__PURE__ */ new Map([["http.ts", [yield* http({ httpImportPath: yield* importFromConvex("http.ts") }), yield* declaredHttp({
70
+ schemaImportPath: yield* importFromConvex("_generated/schema.ts"),
71
+ httpImportPath: yield* importFromConvex("http.ts")
72
+ })]], ["crons.ts", [yield* crons({ cronsImportPath: yield* importFromConvex("crons.ts") })]]]);
73
+ const refused = [];
74
+ for (const relative of yield* getEntrypoints) {
75
+ const absolute = path.join(convex, relative);
76
+ const tokens = tokenize(yield* fs.readFileString(absolute), absolute, path);
77
+ if (tokens !== void 0) {
78
+ if (optional.get(relative)?.some((template) => matchesShape(tokens, tokenize(template, absolute, path)))) continue;
79
+ if (path.extname(relative) === ".ts") {
80
+ const names = tokens.flatMap((token, index) => token === "export" && tokens[index + 1] === "const" ? [tokens[index + 2]] : []);
81
+ const group = yield* fromGroupModulePath(relative);
82
+ const template = yield* render({
83
+ functionNames: names,
84
+ registeredFunctionsImportPath: yield* registeredFunctionsImportPathForGroup(group, absolute),
85
+ useNode: tokens[0] === "\"use node\""
86
+ });
87
+ if (names.length > 0 && new Set(names).size === names.length && matchesShape(tokens, tokenize(template, absolute, path))) continue;
88
+ }
89
+ }
90
+ refused.push(toPosixPath(path, path.relative(projectRoot, absolute)));
91
+ }
92
+ if (refused.length > 0) return yield* new UnownedConvexEntrypointError({ filePaths: refused.sort() });
93
+ });
17
94
  const render = ({ functionNames, registeredFunctionsImportPath, useNode = false }) => renderEffect({
18
95
  functionNames,
19
96
  registeredFunctionsImportPath,
@@ -92,18 +169,9 @@ const applyFunctionPlan = Effect.fnUntraced(function* (plan) {
92
169
  yield* writeGroups(plan.changed);
93
170
  });
94
171
  const getGroupPathsFromFs = Effect.gen(function* () {
95
- const fs = yield* FileSystem.FileSystem;
96
172
  const path = yield* Path.Path;
97
- const convexDirectory = yield* ConvexDirectory.get;
98
- const RESERVED_CONVEX_TS_FILE_NAMES = /* @__PURE__ */ new Set([
99
- "schema.ts",
100
- "http.ts",
101
- "crons.ts",
102
- "auth.config.ts",
103
- "convex.config.ts"
104
- ]);
105
- const allConvexPaths = yield* fs.readDirectory(convexDirectory, { recursive: true });
106
- const groupPathArray = yield* pipe(allConvexPaths, Array.filter((convexPath) => path.extname(convexPath) === ".ts" && !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath)) && path.basename(path.dirname(convexPath)) !== "_generated"), Effect.forEach((groupModulePath) => fromGroupModulePath(groupModulePath)));
173
+ const allConvexPaths = yield* getEntrypoints;
174
+ const groupPathArray = yield* pipe(allConvexPaths, Array.filter((convexPath) => path.extname(convexPath) === ".ts" && !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath))), Effect.forEach((groupModulePath) => fromGroupModulePath(groupModulePath)));
107
175
  return GroupPaths.make(HashSet.fromIterable(groupPathArray));
108
176
  });
109
177
  const removeGroups = Effect.fnUntraced(function* (groupPaths) {
@@ -132,6 +200,6 @@ const writeGroups = (groups) => Effect.forEach(groups, Effect.fnUntraced(functio
132
200
  yield* Match.value(change).pipe(Match.when("Added", () => logFileAdded(modulePath$1)), Match.when("Modified", () => logFileModified(modulePath$1)), Match.when("Unchanged", () => Effect.void), Match.exhaustive);
133
201
  }));
134
202
  //#endregion
135
- export { applyFunctionPlan, generateFunctions, generateGroupModule, registeredFunctionsImportPathForGroup, removeGroups, render, writeGroups };
203
+ export { applyFunctionPlan, assertOwnedEntrypoints, generateFunctions, generateGroupModule, registeredFunctionsImportPathForGroup, removeGroups, render, writeGroups };
136
204
 
137
205
  //# sourceMappingURL=FunctionModule.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionModule.mjs","names":["GroupPath.modulePath","modulePath","GenerationSnapshot.plan","GenerationSnapshot.functionPaths","GroupPath.fromGroupModulePath"],"sources":["../src/FunctionModule.ts"],"sourcesContent":["import * as FileSystem from \"effect/FileSystem\";\nimport * as Path from \"effect/Path\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Match from \"effect/Match\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot\";\nimport * as GroupPath from \"./GroupPath\";\nimport * as GroupPaths from \"./GroupPaths\";\nimport { CodeBlockWriter } from \"./CodeBlockWriter\";\nimport { logFileAdded, logFileModified, logFileRemoved } from \"./log\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport { removePathIfExists, toModuleImportPath } from \"./utils\";\n\nexport const render = ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof renderEffect>[0]) =>\n renderEffect({ functionNames, registeredFunctionsImportPath, useNode });\n\nconst renderEffect = Effect.fnUntraced(function* ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\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, (name) =>\n cbw.writeLine(`export const ${name} = registeredFunctions.${name};`),\n );\n\n return yield* cbw.toString();\n});\n\nexport const generateGroupModule = ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof generateGroupModuleEffect>[0]) =>\n generateGroupModuleEffect({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\nconst generateGroupModuleEffect = Effect.fnUntraced(function* ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n groupPath: GroupPath.GroupPath;\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n const directoryPath = path.dirname(modulePath);\n if (!(yield* fs.exists(directoryPath))) {\n yield* fs.makeDirectory(directoryPath, { recursive: true });\n }\n\n const functionsContentsString = yield* render({\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\n if (!(yield* fs.exists(modulePath))) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Added\" as const;\n }\n const existing = yield* fs.readFileString(modulePath);\n if (existing !== functionsContentsString) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Modified\" as const;\n }\n return \"Unchanged\" as const;\n});\n\n/**\n * Compute the module import specifier (relative to `modulePath`) for a group's\n * registry file under `confect/_generated/registeredFunctions/`. The registry\n * path mirrors the group's path one-to-one (see\n * `registeredFunctionsRelativePath` in `LeafModule.ts`) for both Convex and\n * Node groups.\n */\nexport const registeredFunctionsImportPathForGroup = Effect.fnUntraced(\n function* (groupPath: GroupPath.GroupPath, modulePath: string) {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const registeredFunctionsPath =\n path.join(\n confectDirectory,\n \"_generated\",\n \"registeredFunctions\",\n ...groupPath.pathSegments,\n ) + \".ts\";\n\n return yield* toModuleImportPath(\n path.relative(path.dirname(modulePath), registeredFunctionsPath),\n );\n },\n);\n\nconst logGroupPaths = Effect.fnUntraced(function* <R>(\n groupPaths: GroupPaths.GroupPaths,\n logFn: (fullPath: string) => Effect.Effect<void, never, R>,\n): Effect.fn.Return<void, never, R | Path.Path | ConvexDirectory> {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.forEach(\n groupPaths,\n Effect.fnUntraced(function* (gp: GroupPath.GroupPath) {\n const relativeModulePath = yield* GroupPath.modulePath(gp);\n yield* logFn(path.join(convexDirectory, relativeModulePath));\n }),\n );\n});\n\nexport const generateFunctions = Effect.fnUntraced(function* (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n) {\n const groupPathsFromFs = yield* getGroupPathsFromFs;\n yield* applyFunctionPlan(GenerationSnapshot.plan(snapshot, groupPathsFromFs));\n return GenerationSnapshot.functionPaths(snapshot);\n});\n\nexport const applyFunctionPlan = Effect.fnUntraced(function* (\n plan: GenerationSnapshot.ModulePlan,\n) {\n const removed = GroupPaths.GroupPaths.make(\n HashSet.fromIterable(plan.removed),\n );\n yield* removeGroups(removed);\n yield* logGroupPaths(removed, logFileRemoved);\n yield* writeGroups(plan.changed);\n});\n\nconst getGroupPathsFromFs = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n const RESERVED_CONVEX_TS_FILE_NAMES = new Set([\n \"schema.ts\",\n \"http.ts\",\n \"crons.ts\",\n \"auth.config.ts\",\n \"convex.config.ts\",\n ]);\n\n const allConvexPaths = yield* fs.readDirectory(convexDirectory, {\n recursive: true,\n });\n const groupPathArray = yield* pipe(\n allConvexPaths,\n Array.filter(\n (convexPath) =>\n path.extname(convexPath) === \".ts\" &&\n !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath)) &&\n path.basename(path.dirname(convexPath)) !== \"_generated\",\n ),\n Effect.forEach((groupModulePath) =>\n GroupPath.fromGroupModulePath(groupModulePath),\n ),\n );\n return GroupPaths.GroupPaths.make(HashSet.fromIterable(groupPathArray));\n});\n\nexport const removeGroups = Effect.fnUntraced(function* (\n groupPaths: GroupPaths.GroupPaths,\n) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.all(\n HashSet.map(groupPaths, (groupPath) =>\n Effect.gen(function* () {\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n yield* Effect.logDebug(`Removing group '${relativeModulePath}'...`);\n\n yield* removePathIfExists(modulePath);\n yield* Effect.logDebug(`Group '${relativeModulePath}' removed`);\n }),\n ),\n { concurrency: \"unbounded\" },\n );\n});\n\nexport const writeGroups = (\n groups: ReadonlyArray<GenerationSnapshot.GroupSummary>,\n) =>\n Effect.forEach(\n groups,\n Effect.fnUntraced(function* (group: GenerationSnapshot.GroupSummary) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n const relativeModulePath = yield* GroupPath.modulePath(group.path);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n const registeredFunctionsImportPath =\n yield* registeredFunctionsImportPathForGroup(group.path, modulePath);\n const change = yield* generateGroupModule({\n groupPath: group.path,\n functionNames: group.functionNames,\n registeredFunctionsImportPath,\n useNode: group.runtime === \"Node\",\n });\n yield* Match.value(change).pipe(\n Match.when(\"Added\", () => logFileAdded(modulePath)),\n Match.when(\"Modified\", () => logFileModified(modulePath)),\n Match.when(\"Unchanged\", () => Effect.void),\n Match.exhaustive,\n );\n }),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"FunctionModule.mjs","names":["templates.http","templates.declaredHttp","templates.crons","GroupPath.fromGroupModulePath","GroupPath.modulePath","modulePath","GenerationSnapshot.plan","GenerationSnapshot.functionPaths"],"sources":["../src/FunctionModule.ts"],"sourcesContent":["import * as FileSystem from \"effect/FileSystem\";\nimport * as Path from \"effect/Path\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Match from \"effect/Match\";\nimport { UnownedConvexEntrypointError } from \"./CodegenError.js\";\nimport * as templates from \"./templates.js\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot.js\";\nimport * as GroupPath from \"./GroupPath.js\";\nimport * as GroupPaths from \"./GroupPaths.js\";\nimport { CodeBlockWriter } from \"./CodeBlockWriter.js\";\nimport { logFileAdded, logFileModified, logFileRemoved } from \"./log.js\";\nimport { ConfectDirectory } from \"./ConfectDirectory.js\";\nimport { ConvexDirectory } from \"./ConvexDirectory.js\";\nimport {\n removePathIfExists,\n toModuleImportPath,\n toPosixPath,\n} from \"./utils.js\";\nimport { ProjectRoot } from \"./ProjectRoot.js\";\n\nconst RESERVED_CONVEX_TS_FILE_NAMES = new Set([\n \"schema.ts\",\n \"http.ts\",\n \"crons.ts\",\n \"auth.config.ts\",\n \"convex.config.ts\",\n]);\n\n// Keep ownership and removal aligned with Convex's bundler entryPoints filter.\nconst getEntrypoints = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convex = yield* ConvexDirectory.get;\n const files = yield* fs.readDirectory(convex, { recursive: true });\n const components = files\n .filter(\n (file) =>\n path.basename(file) === \"convex.config.ts\" &&\n path.dirname(file) !== \".\",\n )\n .map((file) => path.dirname(file) + path.sep);\n return files.filter((file) => {\n const base = path.basename(file);\n return (\n !file.startsWith(\"_generated\" + path.sep) &&\n !components.some((component) => file.startsWith(component)) &&\n /\\.(?:js|mjs|cjs|ts|tsx|mts|cts|jsx)$/.test(base) &&\n !base.startsWith(\".\") &&\n !base.startsWith(\"#\") &&\n (base.match(/\\./g)?.length ?? 0) === 1 &&\n base !== \"schema.ts\" &&\n base !== \"schema.js\" &&\n !file.includes(\" \")\n );\n });\n});\n\nconst tokenize = (\n source: string,\n modulePath: string,\n path: Path.Path,\n): string[] | undefined => {\n const token =\n /\\s+|\\/\\/[^\\r\\n]*|\\/\\*[\\s\\S]*?\\*\\/|\"(?:\\\\.|[^\"\\\\\\r\\n])*\"|'(?:\\\\.|[^'\\\\\\r\\n])*'|[$A-Z_a-z][$\\w]*|[{}()[\\].,:;=]/y;\n const tokens: string[] = [];\n while (token.lastIndex < source.length) {\n const match = token.exec(source);\n if (match === null) return undefined;\n const value = match[0];\n if (/^\\s|^\\//.test(value)) continue;\n if (value.startsWith('\"') || value.startsWith(\"'\")) {\n const literal = value.slice(1, -1);\n tokens.push(\n JSON.stringify(\n literal.startsWith(\".\")\n ? path.resolve(\n path.dirname(modulePath),\n literal.replace(/\\.js$/, \"\"),\n )\n : literal,\n ),\n );\n } else tokens.push(value);\n }\n return tokens;\n};\n\nconst matchesShape = (\n actual: readonly string[],\n expected: readonly string[],\n) => {\n let index = 0;\n for (const token of expected) {\n if (token === \";\" && actual[index] !== \";\") continue;\n if (actual[index] === \",\" && (token === \"}\" || token === \")\")) index++;\n if (actual[index++] !== token) return false;\n }\n return index === actual.length;\n};\n\nexport const assertOwnedEntrypoints = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convex = yield* ConvexDirectory.get;\n const confect = yield* ConfectDirectory.get;\n const projectRoot = yield* ProjectRoot.get;\n const importFromConvex = (file: string) =>\n toModuleImportPath(path.relative(convex, path.join(confect, file)));\n const optional = new Map([\n [\n \"http.ts\",\n [\n yield* templates.http({\n httpImportPath: yield* importFromConvex(\"http.ts\"),\n }),\n yield* templates.declaredHttp({\n schemaImportPath: yield* importFromConvex(\"_generated/schema.ts\"),\n httpImportPath: yield* importFromConvex(\"http.ts\"),\n }),\n ],\n ],\n [\n \"crons.ts\",\n [\n yield* templates.crons({\n cronsImportPath: yield* importFromConvex(\"crons.ts\"),\n }),\n ],\n ],\n ]);\n const refused: string[] = [];\n for (const relative of yield* getEntrypoints) {\n const absolute = path.join(convex, relative);\n const tokens = tokenize(yield* fs.readFileString(absolute), absolute, path);\n if (tokens !== undefined) {\n if (\n optional\n .get(relative)\n ?.some((template) =>\n matchesShape(tokens, tokenize(template, absolute, path)!),\n )\n )\n continue;\n if (path.extname(relative) === \".ts\") {\n const names = tokens.flatMap((token, index) =>\n token === \"export\" && tokens[index + 1] === \"const\"\n ? [tokens[index + 2]!]\n : [],\n );\n const group = yield* GroupPath.fromGroupModulePath(relative);\n const template = yield* render({\n functionNames: names,\n registeredFunctionsImportPath:\n yield* registeredFunctionsImportPathForGroup(group, absolute),\n useNode: tokens[0] === '\"use node\"',\n });\n if (\n names.length > 0 &&\n new Set(names).size === names.length &&\n matchesShape(tokens, tokenize(template, absolute, path)!)\n )\n continue;\n }\n }\n refused.push(toPosixPath(path, path.relative(projectRoot, absolute)));\n }\n if (refused.length > 0)\n return yield* new UnownedConvexEntrypointError({\n filePaths: refused.sort(),\n });\n});\n\nexport const render = ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof renderEffect>[0]) =>\n renderEffect({ functionNames, registeredFunctionsImportPath, useNode });\n\nconst renderEffect = Effect.fnUntraced(function* ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\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, (name) =>\n cbw.writeLine(`export const ${name} = registeredFunctions.${name};`),\n );\n\n return yield* cbw.toString();\n});\n\nexport const generateGroupModule = ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof generateGroupModuleEffect>[0]) =>\n generateGroupModuleEffect({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\nconst generateGroupModuleEffect = Effect.fnUntraced(function* ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n groupPath: GroupPath.GroupPath;\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n const directoryPath = path.dirname(modulePath);\n if (!(yield* fs.exists(directoryPath))) {\n yield* fs.makeDirectory(directoryPath, { recursive: true });\n }\n\n const functionsContentsString = yield* render({\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\n if (!(yield* fs.exists(modulePath))) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Added\" as const;\n }\n const existing = yield* fs.readFileString(modulePath);\n if (existing !== functionsContentsString) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Modified\" as const;\n }\n return \"Unchanged\" as const;\n});\n\n/**\n * Compute the module import specifier (relative to `modulePath`) for a group's\n * registry file under `confect/_generated/registeredFunctions/`. The registry\n * path mirrors the group's path one-to-one (see\n * `registeredFunctionsRelativePath` in `LeafModule.ts`) for both Convex and\n * Node groups.\n */\nexport const registeredFunctionsImportPathForGroup = Effect.fnUntraced(\n function* (groupPath: GroupPath.GroupPath, modulePath: string) {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const registeredFunctionsPath =\n path.join(\n confectDirectory,\n \"_generated\",\n \"registeredFunctions\",\n ...groupPath.pathSegments,\n ) + \".ts\";\n\n return yield* toModuleImportPath(\n path.relative(path.dirname(modulePath), registeredFunctionsPath),\n );\n },\n);\n\nconst logGroupPaths = Effect.fnUntraced(function* <R>(\n groupPaths: GroupPaths.GroupPaths,\n logFn: (fullPath: string) => Effect.Effect<void, never, R>,\n): Effect.fn.Return<void, never, R | Path.Path | ConvexDirectory> {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.forEach(\n groupPaths,\n Effect.fnUntraced(function* (gp: GroupPath.GroupPath) {\n const relativeModulePath = yield* GroupPath.modulePath(gp);\n yield* logFn(path.join(convexDirectory, relativeModulePath));\n }),\n );\n});\n\nexport const generateFunctions = Effect.fnUntraced(function* (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n) {\n const groupPathsFromFs = yield* getGroupPathsFromFs;\n yield* applyFunctionPlan(GenerationSnapshot.plan(snapshot, groupPathsFromFs));\n return GenerationSnapshot.functionPaths(snapshot);\n});\n\nexport const applyFunctionPlan = Effect.fnUntraced(function* (\n plan: GenerationSnapshot.ModulePlan,\n) {\n const removed = GroupPaths.GroupPaths.make(\n HashSet.fromIterable(plan.removed),\n );\n yield* removeGroups(removed);\n yield* logGroupPaths(removed, logFileRemoved);\n yield* writeGroups(plan.changed);\n});\n\nconst getGroupPathsFromFs = Effect.gen(function* () {\n const path = yield* Path.Path;\n const allConvexPaths = yield* getEntrypoints;\n const groupPathArray = yield* pipe(\n allConvexPaths,\n Array.filter(\n (convexPath) =>\n path.extname(convexPath) === \".ts\" &&\n !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath)),\n ),\n Effect.forEach((groupModulePath) =>\n GroupPath.fromGroupModulePath(groupModulePath),\n ),\n );\n return GroupPaths.GroupPaths.make(HashSet.fromIterable(groupPathArray));\n});\n\nexport const removeGroups = Effect.fnUntraced(function* (\n groupPaths: GroupPaths.GroupPaths,\n) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.all(\n HashSet.map(groupPaths, (groupPath) =>\n Effect.gen(function* () {\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n yield* Effect.logDebug(`Removing group '${relativeModulePath}'...`);\n\n yield* removePathIfExists(modulePath);\n yield* Effect.logDebug(`Group '${relativeModulePath}' removed`);\n }),\n ),\n { concurrency: \"unbounded\" },\n );\n});\n\nexport const writeGroups = (\n groups: ReadonlyArray<GenerationSnapshot.GroupSummary>,\n) =>\n Effect.forEach(\n groups,\n Effect.fnUntraced(function* (group: GenerationSnapshot.GroupSummary) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n const relativeModulePath = yield* GroupPath.modulePath(group.path);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n const registeredFunctionsImportPath =\n yield* registeredFunctionsImportPathForGroup(group.path, modulePath);\n const change = yield* generateGroupModule({\n groupPath: group.path,\n functionNames: group.functionNames,\n registeredFunctionsImportPath,\n useNode: group.runtime === \"Node\",\n });\n yield* Match.value(change).pipe(\n Match.when(\"Added\", () => logFileAdded(modulePath)),\n Match.when(\"Modified\", () => logFileModified(modulePath)),\n Match.when(\"Unchanged\", () => Effect.void),\n Match.exhaustive,\n );\n }),\n );\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionPath.mjs","names":["GroupPath.GroupPath"],"sources":["../src/FunctionPath.ts"],"sourcesContent":["import * as Schema from \"effect/Schema\";\nimport * as GroupPath from \"./GroupPath\";\n\n/**\n * The path to a function in the Confect API.\n */\nexport class FunctionPath extends Schema.Class<FunctionPath>(\"FunctionPath\")({\n groupPath: GroupPath.GroupPath,\n name: Schema.NonEmptyString,\n}) {}\n\n/**\n * Get the group path from a function path.\n */\nexport const groupPath = (functionPath: FunctionPath): GroupPath.GroupPath =>\n functionPath.groupPath;\n\n/**\n * Get the function name from a function path.\n */\nexport const name = (functionPath: FunctionPath): string => functionPath.name;\n\n/**\n * Get the function path as a string.\n */\nexport const toString = (functionPath: FunctionPath): string =>\n `${GroupPath.toString(functionPath.groupPath)}.${functionPath.name}`;\n"],"mappings":";;;;;;AAMA,IAAa,eAAb,cAAkC,OAAO,MAAoB,cAAc,CAAC,CAAC;CAC3E,WAAWA;CACX,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;;;;AAKJ,MAAa,aAAa,iBACxB,aAAa"}
1
+ {"version":3,"file":"FunctionPath.mjs","names":["GroupPath.GroupPath"],"sources":["../src/FunctionPath.ts"],"sourcesContent":["import * as Schema from \"effect/Schema\";\nimport * as GroupPath from \"./GroupPath.js\";\n\n/**\n * The path to a function in the Confect API.\n */\nexport class FunctionPath extends Schema.Class<FunctionPath>(\"FunctionPath\")({\n groupPath: GroupPath.GroupPath,\n name: Schema.NonEmptyString,\n}) {}\n\n/**\n * Get the group path from a function path.\n */\nexport const groupPath = (functionPath: FunctionPath): GroupPath.GroupPath =>\n functionPath.groupPath;\n\n/**\n * Get the function name from a function path.\n */\nexport const name = (functionPath: FunctionPath): string => functionPath.name;\n\n/**\n * Get the function path as a string.\n */\nexport const toString = (functionPath: FunctionPath): string =>\n `${GroupPath.toString(functionPath.groupPath)}.${functionPath.name}`;\n"],"mappings":";;;;;;AAMA,IAAa,eAAb,cAAkC,OAAO,MAAoB,cAAc,CAAC,CAAC;CAC3E,WAAWA;CACX,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;;;;AAKJ,MAAa,aAAa,iBACxB,aAAa"}
@@ -1 +1 @@
1
- {"version":3,"file":"FunctionPaths.mjs","names":["FunctionPath.FunctionPath","GroupPath.make","GroupPath.append","FunctionPath.groupPath"],"sources":["../src/FunctionPaths.ts"],"sourcesContent":["import { type GroupSpec, Spec } from \"@confect/core\";\nimport { pipe } from \"effect/Function\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Option from \"effect/Option\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as FunctionPath from \"./FunctionPath\";\nimport * as GroupPath from \"./GroupPath\";\nimport * as GroupPaths from \"./GroupPaths\";\n\nexport const FunctionPaths = Schema.HashSet(FunctionPath.FunctionPath).pipe(\n Schema.brand(\"@confect/cli/FunctionPaths\"),\n);\nexport type FunctionPaths = typeof FunctionPaths.Type;\n\nexport const make = (spec: Spec.AnyWithProps): FunctionPaths =>\n makeHelper(\n Spec.groups(spec),\n Option.none(),\n FunctionPaths.make(HashSet.empty()),\n );\n\nconst makeHelper = (\n groups: {\n [key: string]: GroupSpec.AnyWithProps;\n },\n currentGroupPath: Option.Option<GroupPath.GroupPath>,\n apiPaths: FunctionPaths,\n): FunctionPaths =>\n Record.reduce(groups, apiPaths, (acc, group, groupName) => {\n const groupPath = Option.match(currentGroupPath, {\n onNone: () => GroupPath.make([groupName]),\n onSome: (path) => GroupPath.append(path, groupName),\n });\n\n const accWithFunctions = Record.reduce(\n group.functions,\n acc,\n (acc_, _fn, name) =>\n FunctionPaths.make(\n HashSet.add(\n acc_,\n FunctionPath.FunctionPath.make({\n groupPath,\n name,\n }),\n ),\n ),\n );\n\n return makeHelper(group.groups, Option.some(groupPath), accWithFunctions);\n });\n\nexport const groupPaths = (\n functionPaths: FunctionPaths,\n): GroupPaths.GroupPaths =>\n pipe(functionPaths, HashSet.map(FunctionPath.groupPath), (paths) =>\n GroupPaths.GroupPaths.make(paths),\n );\n\nexport const diff = (\n previousFunctions: FunctionPaths,\n currentFunctions: FunctionPaths,\n): {\n functionsAdded: FunctionPaths;\n functionsRemoved: FunctionPaths;\n groupsRemoved: GroupPaths.GroupPaths;\n groupsAdded: GroupPaths.GroupPaths;\n groupsChanged: GroupPaths.GroupPaths;\n} => {\n const currentGroups = groupPaths(currentFunctions);\n const previousGroups = groupPaths(previousFunctions);\n\n const groupsAdded = GroupPaths.GroupPaths.make(\n HashSet.difference(currentGroups, previousGroups),\n );\n const groupsRemoved = GroupPaths.GroupPaths.make(\n HashSet.difference(previousGroups, currentGroups),\n );\n\n const functionsAdded = FunctionPaths.make(\n HashSet.difference(currentFunctions, previousFunctions),\n );\n const existingGroupsToWhichFunctionsWereAdded = GroupPaths.GroupPaths.make(\n HashSet.intersection(currentGroups, groupPaths(functionsAdded)),\n );\n\n const functionsRemoved = FunctionPaths.make(\n HashSet.difference(previousFunctions, currentFunctions),\n );\n const existingGroupsToWhichFunctionsWereRemoved = GroupPaths.GroupPaths.make(\n HashSet.intersection(previousGroups, groupPaths(functionsRemoved)),\n );\n\n const groupsChanged = pipe(\n existingGroupsToWhichFunctionsWereAdded,\n HashSet.union(existingGroupsToWhichFunctionsWereRemoved),\n HashSet.difference(HashSet.union(groupsAdded, groupsRemoved)),\n (paths) => GroupPaths.GroupPaths.make(paths),\n );\n\n return {\n functionsAdded,\n functionsRemoved,\n groupsRemoved,\n groupsAdded,\n groupsChanged,\n };\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,gBAAgB,OAAO,QAAQA,YAAyB,CAAC,CAAC,KACrE,OAAO,MAAM,4BAA4B,CAC3C;AAGA,MAAa,QAAQ,SACnB,WACE,KAAK,OAAO,IAAI,GAChB,OAAO,KAAK,GACZ,cAAc,KAAK,QAAQ,MAAM,CAAC,CACpC;AAEF,MAAM,cACJ,QAGA,kBACA,aAEA,OAAO,OAAO,QAAQ,WAAW,KAAK,OAAO,cAAc;CACzD,MAAM,YAAY,OAAO,MAAM,kBAAkB;EAC/C,cAAcC,OAAe,CAAC,SAAS,CAAC;EACxC,SAAS,SAASC,OAAiB,MAAM,SAAS;CACpD,CAAC;CAED,MAAM,mBAAmB,OAAO,OAC9B,MAAM,WACN,MACC,MAAM,KAAK,SACV,cAAc,KACZ,QAAQ,IACN,MAAA,aAC0B,KAAK;EAC7B;EACA;CACF,CAAC,CACH,CACF,CACJ;CAEA,OAAO,WAAW,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG,gBAAgB;AAC1E,CAAC;AAEH,MAAa,cACX,kBAEA,KAAK,eAAe,QAAQ,IAAIC,SAAsB,IAAI,UAAA,WAClC,KAAK,KAAK,CAClC;AAEF,MAAa,QACX,mBACA,qBAOG;CACH,MAAM,gBAAgB,WAAW,gBAAgB;CACjD,MAAM,iBAAiB,WAAW,iBAAiB;CAEnD,MAAM,cAAA,WAAoC,KACxC,QAAQ,WAAW,eAAe,cAAc,CAClD;CACA,MAAM,gBAAA,WAAsC,KAC1C,QAAQ,WAAW,gBAAgB,aAAa,CAClD;CAEA,MAAM,iBAAiB,cAAc,KACnC,QAAQ,WAAW,kBAAkB,iBAAiB,CACxD;CACA,MAAM,0CAAA,WAAgE,KACpE,QAAQ,aAAa,eAAe,WAAW,cAAc,CAAC,CAChE;CAEA,MAAM,mBAAmB,cAAc,KACrC,QAAQ,WAAW,mBAAmB,gBAAgB,CACxD;CACA,MAAM,4CAAA,WAAkE,KACtE,QAAQ,aAAa,gBAAgB,WAAW,gBAAgB,CAAC,CACnE;CASA,OAAO;EACL;EACA;EACA;EACA;EACA,eAZoB,KACpB,yCACA,QAAQ,MAAM,yCAAyC,GACvD,QAAQ,WAAW,QAAQ,MAAM,aAAa,aAAa,CAAC,IAC3D,UAAA,WAAgC,KAAK,KAAK,CAQ/B;CACd;AACF"}
1
+ {"version":3,"file":"FunctionPaths.mjs","names":["FunctionPath.FunctionPath","GroupPath.make","GroupPath.append","FunctionPath.groupPath"],"sources":["../src/FunctionPaths.ts"],"sourcesContent":["import { type GroupSpec, Spec } from \"@confect/core\";\nimport { pipe } from \"effect/Function\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Option from \"effect/Option\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as FunctionPath from \"./FunctionPath.js\";\nimport * as GroupPath from \"./GroupPath.js\";\nimport * as GroupPaths from \"./GroupPaths.js\";\n\nexport const FunctionPaths = Schema.HashSet(FunctionPath.FunctionPath).pipe(\n Schema.brand(\"@confect/cli/FunctionPaths\"),\n);\nexport type FunctionPaths = typeof FunctionPaths.Type;\n\nexport const make = (spec: Spec.AnyWithProps): FunctionPaths =>\n makeHelper(\n Spec.groups(spec),\n Option.none(),\n FunctionPaths.make(HashSet.empty()),\n );\n\nconst makeHelper = (\n groups: {\n [key: string]: GroupSpec.AnyWithProps;\n },\n currentGroupPath: Option.Option<GroupPath.GroupPath>,\n apiPaths: FunctionPaths,\n): FunctionPaths =>\n Record.reduce(groups, apiPaths, (acc, group, groupName) => {\n const groupPath = Option.match(currentGroupPath, {\n onNone: () => GroupPath.make([groupName]),\n onSome: (path) => GroupPath.append(path, groupName),\n });\n\n const accWithFunctions = Record.reduce(\n group.functions,\n acc,\n (acc_, _fn, name) =>\n FunctionPaths.make(\n HashSet.add(\n acc_,\n FunctionPath.FunctionPath.make({\n groupPath,\n name,\n }),\n ),\n ),\n );\n\n return makeHelper(group.groups, Option.some(groupPath), accWithFunctions);\n });\n\nexport const groupPaths = (\n functionPaths: FunctionPaths,\n): GroupPaths.GroupPaths =>\n pipe(functionPaths, HashSet.map(FunctionPath.groupPath), (paths) =>\n GroupPaths.GroupPaths.make(paths),\n );\n\nexport const diff = (\n previousFunctions: FunctionPaths,\n currentFunctions: FunctionPaths,\n): {\n functionsAdded: FunctionPaths;\n functionsRemoved: FunctionPaths;\n groupsRemoved: GroupPaths.GroupPaths;\n groupsAdded: GroupPaths.GroupPaths;\n groupsChanged: GroupPaths.GroupPaths;\n} => {\n const currentGroups = groupPaths(currentFunctions);\n const previousGroups = groupPaths(previousFunctions);\n\n const groupsAdded = GroupPaths.GroupPaths.make(\n HashSet.difference(currentGroups, previousGroups),\n );\n const groupsRemoved = GroupPaths.GroupPaths.make(\n HashSet.difference(previousGroups, currentGroups),\n );\n\n const functionsAdded = FunctionPaths.make(\n HashSet.difference(currentFunctions, previousFunctions),\n );\n const existingGroupsToWhichFunctionsWereAdded = GroupPaths.GroupPaths.make(\n HashSet.intersection(currentGroups, groupPaths(functionsAdded)),\n );\n\n const functionsRemoved = FunctionPaths.make(\n HashSet.difference(previousFunctions, currentFunctions),\n );\n const existingGroupsToWhichFunctionsWereRemoved = GroupPaths.GroupPaths.make(\n HashSet.intersection(previousGroups, groupPaths(functionsRemoved)),\n );\n\n const groupsChanged = pipe(\n existingGroupsToWhichFunctionsWereAdded,\n HashSet.union(existingGroupsToWhichFunctionsWereRemoved),\n HashSet.difference(HashSet.union(groupsAdded, groupsRemoved)),\n (paths) => GroupPaths.GroupPaths.make(paths),\n );\n\n return {\n functionsAdded,\n functionsRemoved,\n groupsRemoved,\n groupsAdded,\n groupsChanged,\n };\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,gBAAgB,OAAO,QAAQA,YAAyB,CAAC,CAAC,KACrE,OAAO,MAAM,4BAA4B,CAC3C;AAGA,MAAa,QAAQ,SACnB,WACE,KAAK,OAAO,IAAI,GAChB,OAAO,KAAK,GACZ,cAAc,KAAK,QAAQ,MAAM,CAAC,CACpC;AAEF,MAAM,cACJ,QAGA,kBACA,aAEA,OAAO,OAAO,QAAQ,WAAW,KAAK,OAAO,cAAc;CACzD,MAAM,YAAY,OAAO,MAAM,kBAAkB;EAC/C,cAAcC,OAAe,CAAC,SAAS,CAAC;EACxC,SAAS,SAASC,OAAiB,MAAM,SAAS;CACpD,CAAC;CAED,MAAM,mBAAmB,OAAO,OAC9B,MAAM,WACN,MACC,MAAM,KAAK,SACV,cAAc,KACZ,QAAQ,IACN,MAAA,aAC0B,KAAK;EAC7B;EACA;CACF,CAAC,CACH,CACF,CACJ;CAEA,OAAO,WAAW,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG,gBAAgB;AAC1E,CAAC;AAEH,MAAa,cACX,kBAEA,KAAK,eAAe,QAAQ,IAAIC,SAAsB,IAAI,UAAA,WAClC,KAAK,KAAK,CAClC;AAEF,MAAa,QACX,mBACA,qBAOG;CACH,MAAM,gBAAgB,WAAW,gBAAgB;CACjD,MAAM,iBAAiB,WAAW,iBAAiB;CAEnD,MAAM,cAAA,WAAoC,KACxC,QAAQ,WAAW,eAAe,cAAc,CAClD;CACA,MAAM,gBAAA,WAAsC,KAC1C,QAAQ,WAAW,gBAAgB,aAAa,CAClD;CAEA,MAAM,iBAAiB,cAAc,KACnC,QAAQ,WAAW,kBAAkB,iBAAiB,CACxD;CACA,MAAM,0CAAA,WAAgE,KACpE,QAAQ,aAAa,eAAe,WAAW,cAAc,CAAC,CAChE;CAEA,MAAM,mBAAmB,cAAc,KACrC,QAAQ,WAAW,mBAAmB,gBAAgB,CACxD;CACA,MAAM,4CAAA,WAAkE,KACtE,QAAQ,aAAa,gBAAgB,WAAW,gBAAgB,CAAC,CACnE;CASA,OAAO;EACL;EACA;EACA;EACA;EACA,eAZoB,KACpB,yCACA,QAAQ,MAAM,yCAAyC,GACvD,QAAQ,WAAW,QAAQ,MAAM,aAAa,aAAa,CAAC,IAC3D,UAAA,WAAgC,KAAK,KAAK,CAQ/B;CACd;AACF"}