@confect/cli 9.0.0-next.8 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +187 -1
  2. package/dist/Bundler.mjs +1 -4
  3. package/dist/Bundler.mjs.map +1 -1
  4. package/dist/CodegenError.mjs +3 -13
  5. package/dist/CodegenError.mjs.map +1 -1
  6. package/dist/LeafModule.mjs +9 -22
  7. package/dist/LeafModule.mjs.map +1 -1
  8. package/dist/SpecAssemblyNode.mjs +1 -8
  9. package/dist/SpecAssemblyNode.mjs.map +1 -1
  10. package/dist/confect/codegen.mjs +26 -69
  11. package/dist/confect/codegen.mjs.map +1 -1
  12. package/dist/confect/dev.mjs +0 -3
  13. package/dist/confect/dev.mjs.map +1 -1
  14. package/dist/log.mjs +2 -2
  15. package/dist/log.mjs.map +1 -1
  16. package/dist/package.mjs +1 -1
  17. package/dist/templates.mjs +5 -14
  18. package/dist/templates.mjs.map +1 -1
  19. package/dist/utils.mjs +32 -22
  20. package/dist/utils.mjs.map +1 -1
  21. package/package.json +4 -21
  22. package/dist/index.d.mts +0 -1
  23. package/src/BuildError.ts +0 -217
  24. package/src/Bundler.ts +0 -145
  25. package/src/CodeBlockWriter.ts +0 -65
  26. package/src/CodegenError.ts +0 -443
  27. package/src/ConfectDirectory.ts +0 -45
  28. package/src/ConvexDirectory.ts +0 -72
  29. package/src/FunctionPath.ts +0 -27
  30. package/src/FunctionPaths.ts +0 -107
  31. package/src/GroupPath.ts +0 -116
  32. package/src/GroupPaths.ts +0 -7
  33. package/src/LeafModule.ts +0 -323
  34. package/src/ProjectRoot.ts +0 -55
  35. package/src/SpecAssemblyNode.ts +0 -88
  36. package/src/TableModule.ts +0 -157
  37. package/src/cliApp.ts +0 -8
  38. package/src/confect/codegen.ts +0 -908
  39. package/src/confect/dev.ts +0 -790
  40. package/src/confect.ts +0 -19
  41. package/src/index.ts +0 -23
  42. package/src/log.ts +0 -110
  43. package/src/templates.ts +0 -633
  44. package/src/utils.ts +0 -428
@@ -1 +1 @@
1
- {"version":3,"file":"LeafModule.mjs","names":["Bundler.bundle","Bundler.directlyImports"],"sources":["../src/LeafModule.ts"],"sourcesContent":["import { GroupSpec, Registry } from \"@confect/core\";\nimport * as GroupImpl from \"@confect/server/GroupImpl\";\nimport * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport type { Context } from \"effect\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as String from \"effect/String\";\nimport { fromBundlerError } from \"./BuildError\";\nimport * as Bundler from \"./Bundler\";\nimport {\n ImplMissingDefaultLayerError,\n ImplMissingFunctionsError,\n ImplMissingSpecImportError,\n ImplNotFinalizedError,\n SpecMissingDefaultGroupSpecError,\n SpecRuntimeMismatchError,\n} from \"./CodegenError\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { removePathExtension } from \"./utils\";\n\nexport interface LeafModule {\n readonly relativePath: string;\n readonly pathSegments: readonly [string, ...string[]];\n readonly groupPathDot: string;\n readonly registryGroupPathDot: string;\n readonly exportName: string;\n readonly runtime: \"Convex\" | \"Node\";\n readonly specImportPath: string;\n}\n\nexport const SPEC_SUFFIX = \".spec.ts\";\nexport const IMPL_SUFFIX = \".impl.ts\";\n\nconst swapModuleSuffix = (\n relativePath: string,\n fromSuffix: string,\n toSuffix: string,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { dir, name, ext } = path.parse(relativePath);\n if (ext !== \".ts\" || !name.endsWith(fromSuffix.slice(0, -\".ts\".length))) {\n return relativePath;\n }\n\n const stem = name.slice(0, -fromSuffix.slice(0, -\".ts\".length).length);\n const nextName = `${stem}${toSuffix.slice(0, -\".ts\".length)}`;\n return dir.length > 0\n ? path.join(dir, `${nextName}${ext}`)\n : `${nextName}${ext}`;\n });\n\nexport const isLeafSpecPath = (relativePath: string) =>\n relativePath.endsWith(SPEC_SUFFIX);\n\nexport const isLeafImplPath = (relativePath: string) =>\n relativePath.endsWith(IMPL_SUFFIX);\n\nexport const exportNameFromModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { name, ext } = path.parse(relativePath);\n if (ext !== \".ts\") {\n return name;\n }\n return name.endsWith(\".spec\") ? name.slice(0, -\".spec\".length) : name;\n });\n\nexport const groupPathFromRelativeModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { dir, name, ext } = path.parse(relativePath);\n const stem =\n ext === \".ts\" && name.endsWith(\".spec\")\n ? name.slice(0, -\".spec\".length)\n : name;\n const dirSegments = Array.filter(\n String.split(dir, path.sep),\n String.isNonEmpty,\n );\n const pathSegments = Array.append(dirSegments, stem) as [\n string,\n ...string[],\n ];\n return {\n pathSegments,\n groupPathDot: Array.join(pathSegments, \".\"),\n };\n });\n\nexport const specImportPathFromGenerated = (specRelativePath: string) =>\n Effect.gen(function* () {\n const withoutExt = yield* removePathExtension(specRelativePath);\n return `../${withoutExt}`;\n });\n\nexport const specPathForImpl = (implRelativePath: string) =>\n swapModuleSuffix(implRelativePath, IMPL_SUFFIX, SPEC_SUFFIX);\n\nexport const implPathForSpec = (specRelativePath: string) =>\n swapModuleSuffix(specRelativePath, SPEC_SUFFIX, IMPL_SUFFIX);\n\nexport const isNodeLeafModule = (relativePath: string) =>\n relativePath.startsWith(\"node/\") || relativePath.startsWith(\"node\\\\\");\n\nexport const toNodeRegistryLeaf = (leaf: LeafModule): LeafModule => ({\n ...leaf,\n pathSegments: [leaf.exportName],\n groupPathDot: leaf.exportName,\n});\n\nexport const registeredFunctionsRelativePath = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n return (\n path.join(\n \"registeredFunctions\",\n ...leaf.pathSegments.slice(leaf.runtime === \"Node\" ? 1 : 0),\n ) + \".ts\"\n );\n });\n\nexport const discoverLeafSpecFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const excludedDirs = new Set([\"_generated\", \"tables\"]);\n const excludedFiles = new Set([\"nodeSpec.ts\", \"spec.ts\"]);\n\n const allPaths = yield* fs.readDirectory(confectDirectory, {\n recursive: true,\n });\n\n return Array.filter(allPaths, (relativePath) => {\n if (!isLeafSpecPath(relativePath)) {\n return false;\n }\n\n if (excludedFiles.has(relativePath)) {\n return false;\n }\n\n const segments = String.split(relativePath, path.sep);\n return !Array.some(segments, (segment) => excludedDirs.has(segment));\n });\n});\n\nexport const discoverLeafImplFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const excludedDirs = new Set([\"_generated\", \"tables\"]);\n\n const allPaths = yield* fs.readDirectory(confectDirectory, {\n recursive: true,\n });\n\n return Array.filter(allPaths, (relativePath) => {\n if (!isLeafImplPath(relativePath)) {\n return false;\n }\n\n const segments = String.split(relativePath, path.sep);\n return !Array.some(segments, (segment) => excludedDirs.has(segment));\n });\n});\n\nexport const toLeafModule = (specRelativePath: string) =>\n Effect.gen(function* () {\n const exportName = yield* exportNameFromModulePath(specRelativePath);\n const { pathSegments, groupPathDot } =\n yield* groupPathFromRelativeModulePath(specRelativePath);\n const specImportPath = yield* specImportPathFromGenerated(specRelativePath);\n const runtime = isNodeLeafModule(specRelativePath) ? \"Node\" : \"Convex\";\n\n return {\n relativePath: specRelativePath,\n pathSegments,\n groupPathDot,\n exportName,\n runtime,\n registryGroupPathDot: runtime === \"Node\" ? exportName : groupPathDot,\n specImportPath,\n } satisfies LeafModule;\n });\n\nconst absoluteModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const confectDirectory = yield* ConfectDirectory.get;\n const path = yield* Path.Path;\n return path.resolve(confectDirectory, relativePath);\n });\n\n/**\n * Validate that the leaf's spec file default-exports a `GroupSpec` whose\n * runtime matches the leaf's location (`Convex` for files outside\n * `confect/node/`, `Node` for files inside it). Returns the validated\n * `GroupSpec` so callers can avoid re-bundling for later inspection (e.g.\n * parent/child name-collision checks at codegen time).\n */\nexport const validateSpec = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const absolutePath = yield* absoluteModulePath(leaf.relativePath);\n const { module } = yield* Bundler.bundle(absolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(leaf.relativePath, error)),\n );\n\n const groupSpec = module.default;\n\n if (!GroupSpec.isGroupSpec(groupSpec)) {\n return yield* new SpecMissingDefaultGroupSpecError({\n specPath: leaf.relativePath,\n });\n }\n\n if (groupSpec.runtime !== leaf.runtime) {\n return yield* new SpecRuntimeMismatchError({\n specPath: leaf.relativePath,\n expectedRuntime: leaf.runtime,\n actualRuntime: groupSpec.runtime,\n });\n }\n\n return groupSpec;\n });\n\n/**\n * Walk the built `Context` for a `Finalized` `GroupImpl` service value. The\n * lookup is value-shaped (via `GroupImpl.isFinalizedGroupImpl`) so we don't\n * need to know the group's path up front to construct a typed tag for it.\n */\nconst findFinalizedGroupImpl = <S>(\n context: Context.Context<S>,\n): Option.Option<GroupImpl.AnyFinalized> =>\n Array.findFirst(context.unsafeMap.values(), GroupImpl.isFinalizedGroupImpl);\n\n/**\n * Build the impl layer with a fresh `Registry` so each validation is\n * isolated from prior validations' `FunctionImpl.make` writes. The CLI no\n * longer reads the registry directly — `GroupImpl.finalize` snapshots the\n * registered function names onto the produced `Finalized` `GroupImpl`\n * service value — but a fresh `Ref` is still required because the default\n * `Context.Reference` is cached globally and would otherwise accumulate\n * items across impls.\n */\nconst buildImplLayer = (implLayer: Layer.Layer<unknown>) =>\n Effect.gen(function* () {\n const registry = Ref.unsafeMake<Registry.RegistryItems>({});\n return yield* Layer.build(\n implLayer as Layer.Layer<unknown, never, never>,\n ).pipe(Effect.provideService(Registry.Registry, registry));\n }).pipe(Effect.scoped);\n\n/**\n * Validate that the leaf's sibling impl file imports the spec, default-exports\n * a finalized `GroupImpl` layer, and provides a `FunctionImpl` for every\n * function declared by the spec.\n */\nexport const validateImpl = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const implRelativePath = yield* implPathForSpec(leaf.relativePath);\n const implAbsolutePath = yield* absoluteModulePath(implRelativePath);\n const specAbsolutePath = yield* absoluteModulePath(leaf.relativePath);\n\n const bundled = yield* Bundler.bundle(implAbsolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(implRelativePath, error)),\n );\n\n if (\n !(yield* Bundler.directlyImports(\n bundled,\n implAbsolutePath,\n specAbsolutePath,\n ))\n ) {\n return yield* new ImplMissingSpecImportError({\n implPath: implRelativePath,\n expectedSpecPath: leaf.relativePath,\n });\n }\n\n if (!Layer.isLayer(bundled.module.default)) {\n return yield* new ImplMissingDefaultLayerError({\n implPath: implRelativePath,\n });\n }\n\n const { module: specModule } = yield* Bundler.bundle(specAbsolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(leaf.relativePath, error)),\n );\n const groupSpec = specModule.default as GroupSpec.AnyWithProps;\n const expectedFunctionNames = Object.keys(groupSpec.functions);\n\n const context = yield* buildImplLayer(\n bundled.module.default as Layer.Layer<unknown>,\n );\n const finalizedGroupImpl = yield* Option.match(\n findFinalizedGroupImpl(context),\n {\n onNone: () => new ImplNotFinalizedError({ implPath: implRelativePath }),\n onSome: Effect.succeed,\n },\n );\n\n const registeredSet = new Set(finalizedGroupImpl.registeredFunctionNames);\n const missing = expectedFunctionNames.filter(\n (name) => !registeredSet.has(name),\n );\n\n if (missing.length > 0) {\n return yield* new ImplMissingFunctionsError({\n implPath: implRelativePath,\n groupPath: leaf.groupPathDot,\n missingFunctionNames: missing,\n });\n }\n });\n"],"mappings":";;;;;;;;;;;;;;;;;AAkCA,MAAa,cAAc;AAC3B,MAAa,cAAc;AAE3B,MAAM,oBACJ,cACA,YACA,aAEA,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,EAAE,KAAK,MAAM,QAAQ,KAAK,MAAM,aAAa;AACnD,KAAI,QAAQ,SAAS,CAAC,KAAK,SAAS,WAAW,MAAM,GAAG,GAAc,CAAC,CACrE,QAAO;CAIT,MAAM,WAAW,GADJ,KAAK,MAAM,GAAG,CAAC,WAAW,MAAM,GAAG,GAAc,CAAC,OAAO,GAC3C,SAAS,MAAM,GAAG,GAAc;AAC3D,QAAO,IAAI,SAAS,IAChB,KAAK,KAAK,KAAK,GAAG,WAAW,MAAM,GACnC,GAAG,WAAW;EAClB;AAEJ,MAAa,kBAAkB,iBAC7B,aAAa,SAAS,YAAY;AAEpC,MAAa,kBAAkB,iBAC7B,aAAa,SAAS,YAAY;AAEpC,MAAa,4BAA4B,iBACvC,OAAO,IAAI,aAAa;CAEtB,MAAM,EAAE,MAAM,SADD,OAAO,KAAK,MACE,MAAM,aAAa;AAC9C,KAAI,QAAQ,MACV,QAAO;AAET,QAAO,KAAK,SAAS,QAAQ,GAAG,KAAK,MAAM,GAAG,GAAgB,GAAG;EACjE;AAEJ,MAAa,mCAAmC,iBAC9C,OAAO,IAAI,aAAa;CACtB,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,EAAE,KAAK,MAAM,QAAQ,KAAK,MAAM,aAAa;CACnD,MAAM,OACJ,QAAQ,SAAS,KAAK,SAAS,QAAQ,GACnC,KAAK,MAAM,GAAG,GAAgB,GAC9B;CACN,MAAM,cAAc,MAAM,OACxB,OAAO,MAAM,KAAK,KAAK,IAAI,EAC3B,OAAO,WACR;CACD,MAAM,eAAe,MAAM,OAAO,aAAa,KAAK;AAIpD,QAAO;EACL;EACA,cAAc,MAAM,KAAK,cAAc,IAAI;EAC5C;EACD;AAEJ,MAAa,+BAA+B,qBAC1C,OAAO,IAAI,aAAa;AAEtB,QAAO,MADY,OAAO,oBAAoB,iBAAiB;EAE/D;AAEJ,MAAa,mBAAmB,qBAC9B,iBAAiB,kBAAkB,aAAa,YAAY;AAE9D,MAAa,mBAAmB,qBAC9B,iBAAiB,kBAAkB,aAAa,YAAY;AAE9D,MAAa,oBAAoB,iBAC/B,aAAa,WAAW,QAAQ,IAAI,aAAa,WAAW,SAAS;AAEvE,MAAa,sBAAsB,UAAkC;CACnE,GAAG;CACH,cAAc,CAAC,KAAK,WAAW;CAC/B,cAAc,KAAK;CACpB;AAED,MAAa,mCAAmC,SAC9C,OAAO,IAAI,aAAa;AAEtB,SADa,OAAO,KAAK,MAElB,KACH,uBACA,GAAG,KAAK,aAAa,MAAM,KAAK,YAAY,SAAS,IAAI,EAAE,CAC5D,GAAG;EAEN;AAEJ,MAAa,wBAAwB,OAAO,IAAI,aAAa;CAC3D,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,mBAAmB,OAAO,iBAAiB;CAEjD,MAAM,eAAe,IAAI,IAAI,CAAC,cAAc,SAAS,CAAC;CACtD,MAAM,gBAAgB,IAAI,IAAI,CAAC,eAAe,UAAU,CAAC;CAEzD,MAAM,WAAW,OAAO,GAAG,cAAc,kBAAkB,EACzD,WAAW,MACZ,CAAC;AAEF,QAAO,MAAM,OAAO,WAAW,iBAAiB;AAC9C,MAAI,CAAC,eAAe,aAAa,CAC/B,QAAO;AAGT,MAAI,cAAc,IAAI,aAAa,CACjC,QAAO;EAGT,MAAM,WAAW,OAAO,MAAM,cAAc,KAAK,IAAI;AACrD,SAAO,CAAC,MAAM,KAAK,WAAW,YAAY,aAAa,IAAI,QAAQ,CAAC;GACpE;EACF;AAEF,MAAa,wBAAwB,OAAO,IAAI,aAAa;CAC3D,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,mBAAmB,OAAO,iBAAiB;CAEjD,MAAM,eAAe,IAAI,IAAI,CAAC,cAAc,SAAS,CAAC;CAEtD,MAAM,WAAW,OAAO,GAAG,cAAc,kBAAkB,EACzD,WAAW,MACZ,CAAC;AAEF,QAAO,MAAM,OAAO,WAAW,iBAAiB;AAC9C,MAAI,CAAC,eAAe,aAAa,CAC/B,QAAO;EAGT,MAAM,WAAW,OAAO,MAAM,cAAc,KAAK,IAAI;AACrD,SAAO,CAAC,MAAM,KAAK,WAAW,YAAY,aAAa,IAAI,QAAQ,CAAC;GACpE;EACF;AAEF,MAAa,gBAAgB,qBAC3B,OAAO,IAAI,aAAa;CACtB,MAAM,aAAa,OAAO,yBAAyB,iBAAiB;CACpE,MAAM,EAAE,cAAc,iBACpB,OAAO,gCAAgC,iBAAiB;CAC1D,MAAM,iBAAiB,OAAO,4BAA4B,iBAAiB;CAC3E,MAAM,UAAU,iBAAiB,iBAAiB,GAAG,SAAS;AAE9D,QAAO;EACL,cAAc;EACd;EACA;EACA;EACA;EACA,sBAAsB,YAAY,SAAS,aAAa;EACxD;EACD;EACD;AAEJ,MAAM,sBAAsB,iBAC1B,OAAO,IAAI,aAAa;CACtB,MAAM,mBAAmB,OAAO,iBAAiB;AAEjD,SADa,OAAO,KAAK,MACb,QAAQ,kBAAkB,aAAa;EACnD;;;;;;;;AASJ,MAAa,gBAAgB,SAC3B,OAAO,IAAI,aAAa;CACtB,MAAM,eAAe,OAAO,mBAAmB,KAAK,aAAa;CACjE,MAAM,EAAE,WAAW,OAAOA,OAAe,aAAa,CAAC,KACrD,OAAO,UAAU,UAAU,iBAAiB,KAAK,cAAc,MAAM,CAAC,CACvE;CAED,MAAM,YAAY,OAAO;AAEzB,KAAI,CAAC,UAAU,YAAY,UAAU,CACnC,QAAO,OAAO,IAAI,iCAAiC,EACjD,UAAU,KAAK,cAChB,CAAC;AAGJ,KAAI,UAAU,YAAY,KAAK,QAC7B,QAAO,OAAO,IAAI,yBAAyB;EACzC,UAAU,KAAK;EACf,iBAAiB,KAAK;EACtB,eAAe,UAAU;EAC1B,CAAC;AAGJ,QAAO;EACP;;;;;;AAOJ,MAAM,0BACJ,YAEA,MAAM,UAAU,QAAQ,UAAU,QAAQ,EAAE,UAAU,qBAAqB;;;;;;;;;;AAW7E,MAAM,kBAAkB,cACtB,OAAO,IAAI,aAAa;CACtB,MAAM,WAAW,IAAI,WAAmC,EAAE,CAAC;AAC3D,QAAO,OAAO,MAAM,MAClB,UACD,CAAC,KAAK,OAAO,eAAe,SAAS,UAAU,SAAS,CAAC;EAC1D,CAAC,KAAK,OAAO,OAAO;;;;;;AAOxB,MAAa,gBAAgB,SAC3B,OAAO,IAAI,aAAa;CACtB,MAAM,mBAAmB,OAAO,gBAAgB,KAAK,aAAa;CAClE,MAAM,mBAAmB,OAAO,mBAAmB,iBAAiB;CACpE,MAAM,mBAAmB,OAAO,mBAAmB,KAAK,aAAa;CAErE,MAAM,UAAU,OAAOA,OAAe,iBAAiB,CAAC,KACtD,OAAO,UAAU,UAAU,iBAAiB,kBAAkB,MAAM,CAAC,CACtE;AAED,KACE,EAAE,OAAOC,gBACP,SACA,kBACA,iBACD,EAED,QAAO,OAAO,IAAI,2BAA2B;EAC3C,UAAU;EACV,kBAAkB,KAAK;EACxB,CAAC;AAGJ,KAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,QAAQ,CACxC,QAAO,OAAO,IAAI,6BAA6B,EAC7C,UAAU,kBACX,CAAC;CAGJ,MAAM,EAAE,QAAQ,eAAe,OAAOD,OAAe,iBAAiB,CAAC,KACrE,OAAO,UAAU,UAAU,iBAAiB,KAAK,cAAc,MAAM,CAAC,CACvE;CACD,MAAM,YAAY,WAAW;CAC7B,MAAM,wBAAwB,OAAO,KAAK,UAAU,UAAU;CAE9D,MAAM,UAAU,OAAO,eACrB,QAAQ,OAAO,QAChB;CACD,MAAM,qBAAqB,OAAO,OAAO,MACvC,uBAAuB,QAAQ,EAC/B;EACE,cAAc,IAAI,sBAAsB,EAAE,UAAU,kBAAkB,CAAC;EACvE,QAAQ,OAAO;EAChB,CACF;CAED,MAAM,gBAAgB,IAAI,IAAI,mBAAmB,wBAAwB;CACzE,MAAM,UAAU,sBAAsB,QACnC,SAAS,CAAC,cAAc,IAAI,KAAK,CACnC;AAED,KAAI,QAAQ,SAAS,EACnB,QAAO,OAAO,IAAI,0BAA0B;EAC1C,UAAU;EACV,WAAW,KAAK;EAChB,sBAAsB;EACvB,CAAC;EAEJ"}
1
+ {"version":3,"file":"LeafModule.mjs","names":["Bundler.bundle","Bundler.directlyImports"],"sources":["../src/LeafModule.ts"],"sourcesContent":["import { GroupSpec, Registry } from \"@confect/core\";\nimport * as GroupImpl from \"@confect/server/GroupImpl\";\nimport * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport type { Context } from \"effect\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as String from \"effect/String\";\nimport { fromBundlerError } from \"./BuildError\";\nimport * as Bundler from \"./Bundler\";\nimport {\n ImplMissingDefaultLayerError,\n ImplMissingFunctionsError,\n ImplMissingSpecImportError,\n ImplNotFinalizedError,\n SpecMissingDefaultGroupSpecError,\n} from \"./CodegenError\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { removePathExtension } from \"./utils\";\n\nexport interface LeafModule {\n readonly relativePath: string;\n readonly pathSegments: readonly [string, ...string[]];\n readonly groupPathDot: string;\n readonly exportName: string;\n /**\n * The runtime declared by the group's spec — `\"Node\"` for\n * `GroupSpec.makeNode()`, `\"Convex\"` for `GroupSpec.make()`. `None` while the\n * runtime is unknown: discovery (`toLeafModule`) works from the file path alone,\n * which does not determine the runtime, so this is filled in once the spec has\n * been bundled and validated (see `validateSpec`).\n */\n readonly runtime: Option.Option<\"Convex\" | \"Node\">;\n readonly specImportPath: string;\n}\n\nexport const SPEC_SUFFIX = \".spec.ts\";\nexport const IMPL_SUFFIX = \".impl.ts\";\n\nconst swapModuleSuffix = (\n relativePath: string,\n fromSuffix: string,\n toSuffix: string,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { dir, name, ext } = path.parse(relativePath);\n if (ext !== \".ts\" || !name.endsWith(fromSuffix.slice(0, -\".ts\".length))) {\n return relativePath;\n }\n\n const stem = name.slice(0, -fromSuffix.slice(0, -\".ts\".length).length);\n const nextName = `${stem}${toSuffix.slice(0, -\".ts\".length)}`;\n return dir.length > 0\n ? path.join(dir, `${nextName}${ext}`)\n : `${nextName}${ext}`;\n });\n\nexport const isLeafSpecPath = (relativePath: string) =>\n relativePath.endsWith(SPEC_SUFFIX);\n\nexport const isLeafImplPath = (relativePath: string) =>\n relativePath.endsWith(IMPL_SUFFIX);\n\nexport const exportNameFromModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { name, ext } = path.parse(relativePath);\n if (ext !== \".ts\") {\n return name;\n }\n return name.endsWith(\".spec\") ? name.slice(0, -\".spec\".length) : name;\n });\n\nexport const groupPathFromRelativeModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const { dir, name, ext } = path.parse(relativePath);\n const stem =\n ext === \".ts\" && name.endsWith(\".spec\")\n ? name.slice(0, -\".spec\".length)\n : name;\n const dirSegments = Array.filter(\n String.split(dir, path.sep),\n String.isNonEmpty,\n );\n const pathSegments = Array.append(dirSegments, stem) as [\n string,\n ...string[],\n ];\n return {\n pathSegments,\n groupPathDot: Array.join(pathSegments, \".\"),\n };\n });\n\nexport const specImportPathFromGenerated = (specRelativePath: string) =>\n Effect.gen(function* () {\n const withoutExt = yield* removePathExtension(specRelativePath);\n return `../${withoutExt}`;\n });\n\nexport const specPathForImpl = (implRelativePath: string) =>\n swapModuleSuffix(implRelativePath, IMPL_SUFFIX, SPEC_SUFFIX);\n\nexport const implPathForSpec = (specRelativePath: string) =>\n swapModuleSuffix(specRelativePath, SPEC_SUFFIX, IMPL_SUFFIX);\n\nexport const registeredFunctionsRelativePath = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n return path.join(\"registeredFunctions\", ...leaf.pathSegments) + \".ts\";\n });\n\nexport const discoverLeafSpecFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const excludedDirs = new Set([\"_generated\", \"tables\"]);\n const excludedFiles = new Set([\"nodeSpec.ts\", \"spec.ts\"]);\n\n const allPaths = yield* fs.readDirectory(confectDirectory, {\n recursive: true,\n });\n\n return Array.filter(allPaths, (relativePath) => {\n if (!isLeafSpecPath(relativePath)) {\n return false;\n }\n\n if (excludedFiles.has(relativePath)) {\n return false;\n }\n\n const segments = String.split(relativePath, path.sep);\n return !Array.some(segments, (segment) => excludedDirs.has(segment));\n });\n});\n\nexport const discoverLeafImplFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const excludedDirs = new Set([\"_generated\", \"tables\"]);\n\n const allPaths = yield* fs.readDirectory(confectDirectory, {\n recursive: true,\n });\n\n return Array.filter(allPaths, (relativePath) => {\n if (!isLeafImplPath(relativePath)) {\n return false;\n }\n\n const segments = String.split(relativePath, path.sep);\n return !Array.some(segments, (segment) => excludedDirs.has(segment));\n });\n});\n\nexport const toLeafModule = (specRelativePath: string) =>\n Effect.gen(function* () {\n const exportName = yield* exportNameFromModulePath(specRelativePath);\n const { pathSegments, groupPathDot } =\n yield* groupPathFromRelativeModulePath(specRelativePath);\n const specImportPath = yield* specImportPathFromGenerated(specRelativePath);\n\n return {\n relativePath: specRelativePath,\n pathSegments,\n groupPathDot,\n exportName,\n // Unknown until the spec is bundled; see `LeafModule.runtime`.\n runtime: Option.none(),\n specImportPath,\n } satisfies LeafModule;\n });\n\nconst absoluteModulePath = (relativePath: string) =>\n Effect.gen(function* () {\n const confectDirectory = yield* ConfectDirectory.get;\n const path = yield* Path.Path;\n return path.resolve(confectDirectory, relativePath);\n });\n\n/**\n * Validate that the leaf's spec file default-exports a `GroupSpec`. Returns the\n * validated `GroupSpec` so callers can read its runtime and avoid re-bundling for\n * later inspection (e.g. stamping `leaf.runtime` and parent/child name-collision\n * checks at codegen time). The group's runtime (`Convex` vs `Node`) is whatever\n * the spec declares — it is not constrained by the file's location.\n */\nexport const validateSpec = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const absolutePath = yield* absoluteModulePath(leaf.relativePath);\n const { module } = yield* Bundler.bundle(absolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(leaf.relativePath, error)),\n );\n\n const groupSpec = module.default;\n\n if (!GroupSpec.isGroupSpec(groupSpec)) {\n return yield* new SpecMissingDefaultGroupSpecError({\n specPath: leaf.relativePath,\n });\n }\n\n return groupSpec;\n });\n\n/**\n * Walk the built `Context` for a `Finalized` `GroupImpl` service value. The\n * lookup is value-shaped (via `GroupImpl.isFinalizedGroupImpl`) so we don't\n * need to know the group's path up front to construct a typed tag for it.\n */\nconst findFinalizedGroupImpl = <S>(\n context: Context.Context<S>,\n): Option.Option<GroupImpl.AnyFinalized> =>\n Array.findFirst(context.unsafeMap.values(), GroupImpl.isFinalizedGroupImpl);\n\n/**\n * Build the impl layer with a fresh `Registry` so each validation is\n * isolated from prior validations' `FunctionImpl.make` writes. The CLI no\n * longer reads the registry directly — `GroupImpl.finalize` snapshots the\n * registered function names onto the produced `Finalized` `GroupImpl`\n * service value — but a fresh `Ref` is still required because the default\n * `Context.Reference` is cached globally and would otherwise accumulate\n * items across impls.\n */\nconst buildImplLayer = (implLayer: Layer.Layer<unknown>) =>\n Effect.gen(function* () {\n const registry = Ref.unsafeMake<Registry.RegistryItems>({});\n return yield* Layer.build(\n implLayer as Layer.Layer<unknown, never, never>,\n ).pipe(Effect.provideService(Registry.Registry, registry));\n }).pipe(Effect.scoped);\n\n/**\n * Validate that the leaf's sibling impl file imports the spec, default-exports\n * a finalized `GroupImpl` layer, and provides a `FunctionImpl` for every\n * function declared by the spec.\n */\nexport const validateImpl = (leaf: LeafModule) =>\n Effect.gen(function* () {\n const implRelativePath = yield* implPathForSpec(leaf.relativePath);\n const implAbsolutePath = yield* absoluteModulePath(implRelativePath);\n const specAbsolutePath = yield* absoluteModulePath(leaf.relativePath);\n\n const bundled = yield* Bundler.bundle(implAbsolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(implRelativePath, error)),\n );\n\n if (\n !(yield* Bundler.directlyImports(\n bundled,\n implAbsolutePath,\n specAbsolutePath,\n ))\n ) {\n return yield* new ImplMissingSpecImportError({\n implPath: implRelativePath,\n expectedSpecPath: leaf.relativePath,\n });\n }\n\n if (!Layer.isLayer(bundled.module.default)) {\n return yield* new ImplMissingDefaultLayerError({\n implPath: implRelativePath,\n });\n }\n\n const { module: specModule } = yield* Bundler.bundle(specAbsolutePath).pipe(\n Effect.mapError((error) => fromBundlerError(leaf.relativePath, error)),\n );\n const groupSpec = specModule.default as GroupSpec.AnyWithProps;\n const expectedFunctionNames = Object.keys(groupSpec.functions);\n\n const context = yield* buildImplLayer(\n bundled.module.default as Layer.Layer<unknown>,\n );\n const finalizedGroupImpl = yield* Option.match(\n findFinalizedGroupImpl(context),\n {\n onNone: () => new ImplNotFinalizedError({ implPath: implRelativePath }),\n onSome: Effect.succeed,\n },\n );\n\n const registeredSet = new Set(finalizedGroupImpl.registeredFunctionNames);\n const missing = expectedFunctionNames.filter(\n (name) => !registeredSet.has(name),\n );\n\n if (missing.length > 0) {\n return yield* new ImplMissingFunctionsError({\n implPath: implRelativePath,\n groupPath: leaf.groupPathDot,\n missingFunctionNames: missing,\n });\n }\n });\n"],"mappings":"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"}
@@ -20,13 +20,6 @@ const assemblyNodesAtDepth = (leaves, depth) => pipe(Array.groupBy(leaves, (leaf
20
20
  };
21
21
  }));
22
22
  const assemblyNodesFromLeaves = (leaves) => assemblyNodesAtDepth(leaves, 0);
23
- const partitionByRuntime = (leaves) => {
24
- const [node, convex] = Array.partition(leaves, (leaf) => leaf.runtime === "Convex");
25
- return {
26
- convex,
27
- node
28
- };
29
- };
30
23
  const importBindingsForNode = (node) => pipe(node.children, Array.flatMap(importBindingsForNode), (childBindings) => Option.match(node.importBinding, {
31
24
  onNone: () => childBindings,
32
25
  onSome: (binding) => Array.prepend(childBindings, binding)
@@ -34,5 +27,5 @@ const importBindingsForNode = (node) => pipe(node.children, Array.flatMap(import
34
27
  const collectImportBindings = (nodes) => pipe(Array.flatMap(nodes, importBindingsForNode), (bindings) => Record.fromIterableBy(bindings, (binding) => binding.importPath), Record.toEntries, Array.map(([, binding]) => binding), Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)));
35
28
 
36
29
  //#endregion
37
- export { assemblyNodesFromLeaves, collectImportBindings, partitionByRuntime };
30
+ export { assemblyNodesFromLeaves, collectImportBindings };
38
31
  //# sourceMappingURL=SpecAssemblyNode.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"SpecAssemblyNode.mjs","names":[],"sources":["../src/SpecAssemblyNode.ts"],"sourcesContent":["import type { LeafModule } from \"./LeafModule\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport * as Record from \"effect/Record\";\n\nexport interface SpecImportBinding {\n readonly importPath: string;\n readonly exportName: string;\n readonly localName: string;\n}\n\nexport interface SpecAssemblyNode {\n readonly segment: string;\n readonly importBinding: Option.Option<SpecImportBinding>;\n readonly children: ReadonlyArray<SpecAssemblyNode>;\n}\n\nconst importBindingFromLeaf = (leaf: LeafModule): SpecImportBinding => ({\n importPath: leaf.specImportPath,\n exportName: leaf.exportName,\n localName: leaf.pathSegments.join(\"_\"),\n});\n\nconst assemblyNodesAtDepth = (\n leaves: ReadonlyArray<LeafModule>,\n depth: number,\n): ReadonlyArray<SpecAssemblyNode> =>\n pipe(\n Array.groupBy(leaves, (leaf) => leaf.pathSegments[depth]!),\n Record.toEntries,\n Array.sortBy(Order.mapInput(Order.string, ([segment]) => segment)),\n Array.map(([segment, groupLeaves]) => {\n const terminal = Array.findFirst(\n groupLeaves,\n (leaf) => leaf.pathSegments.length === depth + 1,\n );\n const descendants = Array.filter(\n groupLeaves,\n (leaf) => leaf.pathSegments.length > depth + 1,\n );\n return {\n segment,\n importBinding: Option.map(terminal, importBindingFromLeaf),\n children: assemblyNodesAtDepth(descendants, depth + 1),\n };\n }),\n );\n\nexport const assemblyNodesFromLeaves = (\n leaves: ReadonlyArray<LeafModule>,\n): ReadonlyArray<SpecAssemblyNode> => assemblyNodesAtDepth(leaves, 0);\n\nexport const partitionByRuntime = (\n leaves: ReadonlyArray<LeafModule>,\n): {\n readonly convex: ReadonlyArray<LeafModule>;\n readonly node: ReadonlyArray<LeafModule>;\n} => {\n const [node, convex] = Array.partition(\n leaves,\n (leaf) => leaf.runtime === \"Convex\",\n );\n return { convex, node };\n};\n\nconst importBindingsForNode = (\n node: SpecAssemblyNode,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(node.children, Array.flatMap(importBindingsForNode), (childBindings) =>\n Option.match(node.importBinding, {\n onNone: () => childBindings,\n onSome: (binding) => Array.prepend(childBindings, binding),\n }),\n );\n\nexport const collectImportBindings = (\n nodes: ReadonlyArray<SpecAssemblyNode>,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(\n Array.flatMap(nodes, importBindingsForNode),\n (bindings) =>\n Record.fromIterableBy(bindings, (binding) => binding.importPath),\n Record.toEntries,\n Array.map(([, binding]) => binding),\n Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)),\n );\n"],"mappings":";;;;;;;AAmBA,MAAM,yBAAyB,UAAyC;CACtE,YAAY,KAAK;CACjB,YAAY,KAAK;CACjB,WAAW,KAAK,aAAa,KAAK,IAAI;CACvC;AAED,MAAM,wBACJ,QACA,UAEA,KACE,MAAM,QAAQ,SAAS,SAAS,KAAK,aAAa,OAAQ,EAC1D,OAAO,WACP,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,CAAC,aAAa,QAAQ,CAAC,EAClE,MAAM,KAAK,CAAC,SAAS,iBAAiB;CACpC,MAAM,WAAW,MAAM,UACrB,cACC,SAAS,KAAK,aAAa,WAAW,QAAQ,EAChD;CACD,MAAM,cAAc,MAAM,OACxB,cACC,SAAS,KAAK,aAAa,SAAS,QAAQ,EAC9C;AACD,QAAO;EACL;EACA,eAAe,OAAO,IAAI,UAAU,sBAAsB;EAC1D,UAAU,qBAAqB,aAAa,QAAQ,EAAE;EACvD;EACD,CACH;AAEH,MAAa,2BACX,WACoC,qBAAqB,QAAQ,EAAE;AAErE,MAAa,sBACX,WAIG;CACH,MAAM,CAAC,MAAM,UAAU,MAAM,UAC3B,SACC,SAAS,KAAK,YAAY,SAC5B;AACD,QAAO;EAAE;EAAQ;EAAM;;AAGzB,MAAM,yBACJ,SAEA,KAAK,KAAK,UAAU,MAAM,QAAQ,sBAAsB,GAAG,kBACzD,OAAO,MAAM,KAAK,eAAe;CAC/B,cAAc;CACd,SAAS,YAAY,MAAM,QAAQ,eAAe,QAAQ;CAC3D,CAAC,CACH;AAEH,MAAa,yBACX,UAEA,KACE,MAAM,QAAQ,OAAO,sBAAsB,GAC1C,aACC,OAAO,eAAe,WAAW,YAAY,QAAQ,WAAW,EAClE,OAAO,WACP,MAAM,KAAK,GAAG,aAAa,QAAQ,EACnC,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,UAAU,CAAC,CAC3E"}
1
+ {"version":3,"file":"SpecAssemblyNode.mjs","names":[],"sources":["../src/SpecAssemblyNode.ts"],"sourcesContent":["import type { LeafModule } from \"./LeafModule\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport * as Record from \"effect/Record\";\n\nexport interface SpecImportBinding {\n readonly importPath: string;\n readonly exportName: string;\n readonly localName: string;\n}\n\nexport interface SpecAssemblyNode {\n readonly segment: string;\n readonly importBinding: Option.Option<SpecImportBinding>;\n readonly children: ReadonlyArray<SpecAssemblyNode>;\n}\n\nconst importBindingFromLeaf = (leaf: LeafModule): SpecImportBinding => ({\n importPath: leaf.specImportPath,\n exportName: leaf.exportName,\n localName: leaf.pathSegments.join(\"_\"),\n});\n\nconst assemblyNodesAtDepth = (\n leaves: ReadonlyArray<LeafModule>,\n depth: number,\n): ReadonlyArray<SpecAssemblyNode> =>\n pipe(\n Array.groupBy(leaves, (leaf) => leaf.pathSegments[depth]!),\n Record.toEntries,\n Array.sortBy(Order.mapInput(Order.string, ([segment]) => segment)),\n Array.map(([segment, groupLeaves]) => {\n const terminal = Array.findFirst(\n groupLeaves,\n (leaf) => leaf.pathSegments.length === depth + 1,\n );\n const descendants = Array.filter(\n groupLeaves,\n (leaf) => leaf.pathSegments.length > depth + 1,\n );\n return {\n segment,\n importBinding: Option.map(terminal, importBindingFromLeaf),\n children: assemblyNodesAtDepth(descendants, depth + 1),\n };\n }),\n );\n\nexport const assemblyNodesFromLeaves = (\n leaves: ReadonlyArray<LeafModule>,\n): ReadonlyArray<SpecAssemblyNode> => assemblyNodesAtDepth(leaves, 0);\n\nconst importBindingsForNode = (\n node: SpecAssemblyNode,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(node.children, Array.flatMap(importBindingsForNode), (childBindings) =>\n Option.match(node.importBinding, {\n onNone: () => childBindings,\n onSome: (binding) => Array.prepend(childBindings, binding),\n }),\n );\n\nexport const collectImportBindings = (\n nodes: ReadonlyArray<SpecAssemblyNode>,\n): ReadonlyArray<SpecImportBinding> =>\n pipe(\n Array.flatMap(nodes, importBindingsForNode),\n (bindings) =>\n Record.fromIterableBy(bindings, (binding) => binding.importPath),\n Record.toEntries,\n Array.map(([, binding]) => binding),\n Array.sortBy(Order.mapInput(Order.string, (binding) => binding.localName)),\n );\n"],"mappings":";;;;;;;AAmBA,MAAM,yBAAyB,UAAyC;CACtE,YAAY,KAAK;CACjB,YAAY,KAAK;CACjB,WAAW,KAAK,aAAa,KAAK,IAAI;CACvC;AAED,MAAM,wBACJ,QACA,UAEA,KACE,MAAM,QAAQ,SAAS,SAAS,KAAK,aAAa,OAAQ,EAC1D,OAAO,WACP,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,CAAC,aAAa,QAAQ,CAAC,EAClE,MAAM,KAAK,CAAC,SAAS,iBAAiB;CACpC,MAAM,WAAW,MAAM,UACrB,cACC,SAAS,KAAK,aAAa,WAAW,QAAQ,EAChD;CACD,MAAM,cAAc,MAAM,OACxB,cACC,SAAS,KAAK,aAAa,SAAS,QAAQ,EAC9C;AACD,QAAO;EACL;EACA,eAAe,OAAO,IAAI,UAAU,sBAAsB;EAC1D,UAAU,qBAAqB,aAAa,QAAQ,EAAE;EACvD;EACD,CACH;AAEH,MAAa,2BACX,WACoC,qBAAqB,QAAQ,EAAE;AAErE,MAAM,yBACJ,SAEA,KAAK,KAAK,UAAU,MAAM,QAAQ,sBAAsB,GAAG,kBACzD,OAAO,MAAM,KAAK,eAAe;CAC/B,cAAc;CACd,SAAS,YAAY,MAAM,QAAQ,eAAe,QAAQ;CAC3D,CAAC,CACH;AAEH,MAAa,yBACX,UAEA,KACE,MAAM,QAAQ,OAAO,sBAAsB,GAC1C,aACC,OAAO,eAAe,WAAW,YAAY,QAAQ,WAAW,EAClE,OAAO,WACP,MAAM,KAAK,GAAG,aAAa,QAAQ,EACnC,MAAM,OAAO,MAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,UAAU,CAAC,CAC3E"}
@@ -4,10 +4,10 @@ import { LegacySchemaFileError, MissingImplFileError, MissingSpecFileError, Pare
4
4
  import { ConvexDirectory } from "../ConvexDirectory.mjs";
5
5
  import { ConfectDirectory } from "../ConfectDirectory.mjs";
6
6
  import { FunctionPaths, make } from "../FunctionPaths.mjs";
7
- import { assemblyNodesFromLeaves, partitionByRuntime } from "../SpecAssemblyNode.mjs";
7
+ import { assemblyNodesFromLeaves } from "../SpecAssemblyNode.mjs";
8
8
  import { assembledSpec, convexSchema, id, refs, registeredFunctionsForGroup, runtimeSchema, schema, services, tableWrapper } from "../templates.mjs";
9
9
  import { WriteTracker, generateAuthConfig, generateCrons, generateFunctions, generateHttp, removePathIfExists, toModuleImportPath, touchConvexSchema, writeFileStringAndLog } from "../utils.mjs";
10
- import { discoverLeafImplFiles, discoverLeafSpecFiles, implPathForSpec, registeredFunctionsRelativePath, specPathForImpl, toLeafModule, toNodeRegistryLeaf, validateImpl, validateSpec } from "../LeafModule.mjs";
10
+ import { discoverLeafImplFiles, discoverLeafSpecFiles, implPathForSpec, registeredFunctionsRelativePath, specPathForImpl, toLeafModule, validateImpl, validateSpec } from "../LeafModule.mjs";
11
11
  import { TABLES_DIRNAME, discover, validate } from "../TableModule.mjs";
12
12
  import * as Effect from "effect/Effect";
13
13
  import * as Command from "@effect/cli/Command";
@@ -24,7 +24,6 @@ import * as Ref from "effect/Ref";
24
24
  //#region src/confect/codegen.ts
25
25
  const GENERATED_DIRNAME = "_generated";
26
26
  const GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "spec.ts"));
27
- const GENERATED_NODE_SPEC_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "nodeSpec.ts"));
28
27
  const GENERATED_SCHEMA_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "schema.ts"));
29
28
  const GENERATED_CONVEX_SCHEMA_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "convexSchema.ts"));
30
29
  const GENERATED_ID_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "id.ts"));
@@ -39,7 +38,8 @@ const LEGACY_PATHS = Effect.gen(function* () {
39
38
  path.join(GENERATED_DIRNAME, "registeredFunctions.ts"),
40
39
  path.join(GENERATED_DIRNAME, "nodeRegisteredFunctions.ts"),
41
40
  path.join(GENERATED_DIRNAME, "impl.ts"),
42
- path.join(GENERATED_DIRNAME, "nodeImpl.ts")
41
+ path.join(GENERATED_DIRNAME, "nodeImpl.ts"),
42
+ path.join(GENERATED_DIRNAME, "nodeSpec.ts")
43
43
  ];
44
44
  });
45
45
  const codegen = Command.make("codegen", {}, () => Effect.gen(function* () {
@@ -102,8 +102,12 @@ const loadAndValidateLeafModules = Effect.gen(function* () {
102
102
  const confectDirectory = yield* ConfectDirectory.get;
103
103
  const specFiles = yield* discoverLeafSpecFiles;
104
104
  const results = yield* Effect.forEach(specFiles, (specRelativePath) => Effect.gen(function* () {
105
- const leaf = yield* toLeafModule(specRelativePath);
106
- const groupSpec = yield* validateSpec(leaf);
105
+ const discovered = yield* toLeafModule(specRelativePath);
106
+ const groupSpec = yield* validateSpec(discovered);
107
+ const leaf = {
108
+ ...discovered,
109
+ runtime: Option.some(groupSpec.runtime)
110
+ };
107
111
  const implRelativePath = yield* implPathForSpec(specRelativePath);
108
112
  const implAbsolutePath = path.join(confectDirectory, implRelativePath);
109
113
  if (!(yield* fs.exists(implAbsolutePath))) return yield* new MissingImplFileError({
@@ -130,11 +134,8 @@ const loadAndValidateLeafModules = Effect.gen(function* () {
130
134
  * `Refs.make` error rather than a codegen-time diagnostic.
131
135
  */
132
136
  const validateNoParentChildNameCollisions = (leaves, groupSpecsByRelativePath) => Effect.gen(function* () {
133
- const { convex, node } = partitionByRuntime(leaves);
134
- const convexNodes = assemblyNodesFromLeaves(convex);
135
- const nodeNodes = assemblyNodesFromLeaves(Array.map(node, toNodeRegistryLeaf));
136
- yield* Effect.forEach(convexNodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
137
- yield* Effect.forEach(nodeNodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
137
+ const nodes = assemblyNodesFromLeaves(leaves);
138
+ yield* Effect.forEach(nodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
138
139
  });
139
140
  const checkAssemblyNodeForCollisions = (node, groupSpecsByRelativePath) => Effect.gen(function* () {
140
141
  yield* Option.match(node.importBinding, {
@@ -217,24 +218,9 @@ const generateAssembledSpecs = (leaves) => Effect.gen(function* () {
217
218
  const path = yield* Path.Path;
218
219
  const confectDirectory = yield* ConfectDirectory.get;
219
220
  const generatedSpecPath = yield* GENERATED_SPEC_PATH;
220
- const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
221
- const { convex, node } = partitionByRuntime(leaves);
222
- if (convex.length > 0) {
223
- const nodes = assemblyNodesFromLeaves(convex);
224
- const specContents = yield* assembledSpec({
225
- nodes,
226
- runtime: "Convex"
227
- });
228
- yield* writeFileStringAndLog(path.join(confectDirectory, generatedSpecPath), specContents);
229
- }
230
- if (node.length > 0) {
231
- const nodes = assemblyNodesFromLeaves(Array.map(node, toNodeRegistryLeaf));
232
- const nodeSpecContents = yield* assembledSpec({
233
- nodes,
234
- runtime: "Node"
235
- });
236
- yield* writeFileStringAndLog(path.join(confectDirectory, generatedNodeSpecPath), nodeSpecContents);
237
- }
221
+ const nodes = assemblyNodesFromLeaves(leaves);
222
+ const specContents = yield* assembledSpec({ nodes });
223
+ yield* writeFileStringAndLog(path.join(confectDirectory, generatedSpecPath), specContents);
238
224
  });
239
225
  const validateImplModules = (leaves) => Effect.forEach(leaves, validateImpl);
240
226
  const generateGroupRegisteredFunctions = (leaves) => Effect.gen(function* () {
@@ -250,12 +236,16 @@ const generateGroupRegisteredFunctions = (leaves) => Effect.gen(function* () {
250
236
  const schemaImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, "_generated", "schema.ts")));
251
237
  const specImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, leaf.relativePath)));
252
238
  const implImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, implRelativePath)));
239
+ const runtime = yield* Option.match(leaf.runtime, {
240
+ onNone: () => Effect.dieMessage(`Runtime for '${leaf.relativePath}' was not resolved before registry generation.`),
241
+ onSome: Effect.succeed
242
+ });
253
243
  yield* writeFileStringAndLog(registryPath, yield* registeredFunctionsForGroup({
254
244
  schemaImportPath,
255
245
  specImportPath,
256
246
  implImportPath,
257
247
  layerExportName: leaf.exportName,
258
- useNode: leaf.runtime === "Node"
248
+ useNode: runtime === "Node"
259
249
  }));
260
250
  }));
261
251
  });
@@ -286,44 +276,22 @@ const getGeneratedSpecPath = Effect.gen(function* () {
286
276
  const generatedSpecPath = yield* GENERATED_SPEC_PATH;
287
277
  return path.join(confectDirectory, generatedSpecPath);
288
278
  });
289
- const getGeneratedNodeSpecPath = Effect.gen(function* () {
290
- const path = yield* Path.Path;
291
- const confectDirectory = yield* ConfectDirectory.get;
292
- const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
293
- return path.join(confectDirectory, generatedNodeSpecPath);
294
- });
295
279
  const loadGeneratedSpec = Effect.gen(function* () {
296
280
  const specPath = yield* getGeneratedSpecPath;
297
281
  const { module: specModule } = yield* bundle(specPath);
298
282
  const spec = specModule.default;
299
- if (!Spec.isConvexSpec(spec)) return yield* Effect.dieMessage("_generated/spec.ts does not export a valid Convex Spec");
283
+ if (!Spec.isSpec(spec)) return yield* Effect.dieMessage("_generated/spec.ts does not export a valid Spec");
300
284
  return spec;
301
285
  });
302
- const loadGeneratedNodeSpec = Effect.gen(function* () {
303
- const fs = yield* FileSystem.FileSystem;
304
- const nodeSpecPath = yield* getGeneratedNodeSpecPath;
305
- if (!(yield* fs.exists(nodeSpecPath))) return Option.none();
306
- const { module: nodeSpecModule } = yield* bundle(nodeSpecPath);
307
- const nodeSpec = nodeSpecModule.default;
308
- if (!Spec.isNodeSpec(nodeSpec)) return yield* Effect.dieMessage("_generated/nodeSpec.ts does not export a valid Node Spec");
309
- return Option.some(nodeSpec);
310
- });
311
286
  const emptyFunctionPaths = FunctionPaths.make(HashSet.empty());
312
287
  const loadPreviousFunctionPaths = Effect.gen(function* () {
313
288
  const fs = yield* FileSystem.FileSystem;
314
289
  const specPath = yield* getGeneratedSpecPath;
315
290
  if (!(yield* fs.exists(specPath))) return emptyFunctionPaths;
316
291
  const specEither = yield* loadGeneratedSpec.pipe(Effect.either);
317
- return yield* Either.match(specEither, {
318
- onLeft: () => Effect.succeed(emptyFunctionPaths),
319
- onRight: (spec) => Effect.gen(function* () {
320
- const nodeSpecOption = yield* loadGeneratedNodeSpec;
321
- const mergedSpec = Option.match(nodeSpecOption, {
322
- onNone: () => spec,
323
- onSome: (nodeSpec) => Spec.merge(spec, nodeSpec)
324
- });
325
- return make(mergedSpec);
326
- })
292
+ return Either.match(specEither, {
293
+ onLeft: () => emptyFunctionPaths,
294
+ onRight: (spec) => make(spec)
327
295
  });
328
296
  });
329
297
  /**
@@ -343,12 +311,7 @@ const removeObsoleteGeneratedFile = (fileName) => Effect.gen(function* () {
343
311
  const removeGeneratedApi = removeObsoleteGeneratedFile("api.ts");
344
312
  const removeGeneratedNodeApi = removeObsoleteGeneratedFile("nodeApi.ts");
345
313
  const generateFunctionModules = Effect.gen(function* () {
346
- const spec = yield* loadGeneratedSpec;
347
- const nodeSpecOption = yield* loadGeneratedNodeSpec;
348
- return yield* generateFunctions(Option.match(nodeSpecOption, {
349
- onNone: () => spec,
350
- onSome: (nodeSpec) => Spec.merge(spec, nodeSpec)
351
- }));
314
+ return yield* generateFunctions(yield* loadGeneratedSpec);
352
315
  });
353
316
  /**
354
317
  * The user-authored `confect/schema.ts` is no longer supported: codegen now
@@ -474,7 +437,6 @@ const generateServices = Effect.gen(function* () {
474
437
  yield* writeFileStringAndLog(servicesPath, yield* services({ schemaImportPath }));
475
438
  });
476
439
  const generateRefs = Effect.gen(function* () {
477
- const fs = yield* FileSystem.FileSystem;
478
440
  const path = yield* Path.Path;
479
441
  const confectDirectory = yield* ConfectDirectory.get;
480
442
  const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
@@ -482,12 +444,7 @@ const generateRefs = Effect.gen(function* () {
482
444
  const refsDir = path.dirname(refsPath);
483
445
  const generatedSpecPath = yield* GENERATED_SPEC_PATH;
484
446
  const specImportPath = yield* toModuleImportPath(path.relative(refsDir, path.join(confectDirectory, generatedSpecPath)));
485
- const nodeSpecPath = yield* getGeneratedNodeSpecPath;
486
- const nodeSpecImportPath = (yield* fs.exists(nodeSpecPath)) ? Option.some(yield* toModuleImportPath(path.relative(refsDir, nodeSpecPath))) : Option.none();
487
- yield* writeFileStringAndLog(refsPath, yield* refs({
488
- specImportPath,
489
- nodeSpecImportPath
490
- }));
447
+ yield* writeFileStringAndLog(refsPath, yield* refs({ specImportPath }));
491
448
  });
492
449
  const logGenerated = (effect) => effect.pipe(Effect.tap(Option.match({
493
450
  onNone: () => Effect.void,
@@ -1 +1 @@
1
- {"version":3,"file":"codegen.mjs","names":["CodegenError.tapAndLog","TableModule.discover","TableModule.validate","templates.assembledSpec","templates.registeredFunctionsForGroup","Bundler.bundle","FunctionPaths.make","TableModule.TABLES_DIRNAME","templates.id","templates.tableWrapper","templates.runtimeSchema","templates.convexSchema","templates.schema","templates.services","templates.refs"],"sources":["../../src/confect/codegen.ts"],"sourcesContent":["import { Spec, type GroupSpec } from \"@confect/core\";\nimport * as Command from \"@effect/cli/Command\";\nimport * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Either from \"effect/Either\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as Bundler from \"../Bundler\";\nimport * as CodegenError from \"../CodegenError\";\nimport {\n LegacySchemaFileError,\n MissingImplFileError,\n MissingSpecFileError,\n ParentChildNameCollisionError,\n} from \"../CodegenError\";\nimport { ConfectDirectory } from \"../ConfectDirectory\";\nimport { ConvexDirectory } from \"../ConvexDirectory\";\nimport * as FunctionPaths from \"../FunctionPaths\";\nimport {\n discoverLeafImplFiles,\n discoverLeafSpecFiles,\n implPathForSpec,\n registeredFunctionsRelativePath,\n specPathForImpl,\n toLeafModule,\n toNodeRegistryLeaf,\n validateImpl,\n validateSpec,\n type LeafModule,\n} from \"../LeafModule\";\nimport {\n logFileAdded,\n logFileModified,\n logFileRemoved,\n logPending,\n logSuccess,\n logWarn,\n} from \"../log\";\nimport {\n assemblyNodesFromLeaves,\n partitionByRuntime,\n type SpecAssemblyNode,\n} from \"../SpecAssemblyNode\";\nimport * as TableModule from \"../TableModule\";\nimport * as templates from \"../templates\";\nimport {\n generateAuthConfig,\n generateCrons,\n generateFunctions,\n generateHttp,\n removePathIfExists,\n toModuleImportPath,\n touchConvexSchema,\n writeFileStringAndLog,\n WriteTracker,\n} from \"../utils\";\n\nconst GENERATED_DIRNAME = \"_generated\";\n\nconst GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"spec.ts\"),\n);\nconst GENERATED_NODE_SPEC_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"nodeSpec.ts\"),\n);\nconst GENERATED_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"schema.ts\"),\n);\nconst GENERATED_CONVEX_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"convexSchema.ts\"),\n);\nconst GENERATED_ID_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"id.ts\"),\n);\nconst GENERATED_TABLES_DIRNAME = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"tables\"),\n);\n\nconst LEGACY_PATHS = Effect.gen(function* () {\n const path = yield* Path.Path;\n\n return [\n \"spec.ts\",\n \"nodeSpec.ts\",\n \"impl.ts\",\n \"nodeImpl.ts\",\n path.join(GENERATED_DIRNAME, \"registeredFunctions.ts\"),\n path.join(GENERATED_DIRNAME, \"nodeRegisteredFunctions.ts\"),\n path.join(GENERATED_DIRNAME, \"impl.ts\"),\n path.join(GENERATED_DIRNAME, \"nodeImpl.ts\"),\n ];\n});\n\nexport const codegen = Command.make(\"codegen\", {}, () =>\n Effect.gen(function* () {\n yield* logPending(\"Performing initial sync…\");\n yield* codegenHandler.pipe(\n Effect.asVoid,\n Effect.tap(() => logSuccess(\"Generated files are up-to-date\")),\n CodegenError.tapAndLog,\n );\n }),\n).pipe(\n Command.withDescription(\n \"Generate `confect/_generated` files and the contents of the `convex` directory (except `convex.config.ts` and `tsconfig.json`)\",\n ),\n);\n\nexport const codegenHandler = Effect.gen(function* () {\n const tracker = yield* Ref.make(false);\n\n const functionPaths = yield* runCodegen.pipe(\n Effect.provideService(WriteTracker, tracker),\n );\n\n const anyWritesHappened = yield* Ref.get(tracker);\n return { functionPaths, anyWritesHappened };\n});\n\nconst runCodegen = Effect.gen(function* () {\n yield* generateConfectGeneratedDirectory;\n // Reject a legacy `confect/schema.ts` up front so the user-facing\n // migration message surfaces before any bundler error from impl\n // validation (each impl imports `_generated/schema.ts`).\n yield* rejectLegacySchemaFile;\n // List `confect/tables/*.ts` (filename-only — no bundling yet) so the\n // `_generated/id.ts` constructor can be emitted *before* we bundle any\n // user-authored table module. Tables import from `_generated/id.ts` for\n // cross-table id refs, so it must exist on disk first.\n const tableModules = yield* TableModule.discover;\n yield* warnIfNoTables(tableModules);\n yield* generateIdConstructor(tableModules);\n // Now that `_generated/id.ts` is on disk, bundle each table module and\n // check its default export is an `UnnamedTable`. Surface diagnostics\n // here (rather than later) so they appear before impl-validation noise.\n yield* TableModule.validate(tableModules);\n yield* generateTableWrappers(tableModules);\n yield* removeObsoleteTableWrappers(tableModules);\n yield* generateRuntimeSchema(tableModules);\n const { leaves, groupSpecsByRelativePath } =\n yield* loadAndValidateLeafModules;\n yield* removeLegacyFiles;\n yield* validateNoParentChildNameCollisions(leaves, groupSpecsByRelativePath);\n yield* generateAssembledSpecs(leaves);\n // `_generated/api.ts` / `nodeApi.ts` are no longer imported by generated or\n // impl code (impls take the database schema from `_generated/schema`\n // directly), so remove any copies left over from earlier versions before\n // impl validation runs.\n yield* Effect.all(\n [\n removeGeneratedApi,\n generateRefs,\n removeGeneratedNodeApi,\n generateServices,\n generateConvexSchema(tableModules),\n ],\n { concurrency: \"unbounded\" },\n );\n yield* validateImplModules(leaves);\n yield* generateGroupRegisteredFunctions(leaves);\n yield* removeObsoleteRegisteredFunctions(leaves);\n const [functionPaths] = yield* Effect.all(\n [\n generateFunctionModules,\n generateConvexSchemaReexport,\n logGenerated(generateHttp),\n logGenerated(generateCrons),\n logGenerated(generateAuthConfig),\n ],\n { concurrency: \"unbounded\" },\n );\n yield* touchConvexSchema;\n return functionPaths;\n});\n\nconst generateConfectGeneratedDirectory = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n if (!(yield* fs.exists(path.join(confectDirectory, \"_generated\")))) {\n yield* fs.makeDirectory(path.join(confectDirectory, \"_generated\"), {\n recursive: true,\n });\n yield* logFileAdded(path.join(confectDirectory, \"_generated\") + \"/\");\n }\n});\n\nconst loadAndValidateLeafModules = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const specFiles = yield* discoverLeafSpecFiles;\n\n const results = yield* Effect.forEach(specFiles, (specRelativePath) =>\n Effect.gen(function* () {\n const leaf = yield* toLeafModule(specRelativePath);\n const groupSpec = yield* validateSpec(leaf);\n\n const implRelativePath = yield* implPathForSpec(specRelativePath);\n const implAbsolutePath = path.join(confectDirectory, implRelativePath);\n if (!(yield* fs.exists(implAbsolutePath))) {\n return yield* new MissingImplFileError({\n specPath: specRelativePath,\n expectedImplPath: implRelativePath,\n });\n }\n\n return { leaf, groupSpec };\n }),\n );\n\n yield* validateOrphanImpls(specFiles);\n\n const leaves = Array.map(results, ({ leaf }) => leaf);\n const groupSpecsByRelativePath = new Map(\n Array.map(results, ({ leaf, groupSpec }) => [leaf.relativePath, groupSpec]),\n );\n\n return { leaves, groupSpecsByRelativePath };\n});\n\n/**\n * Walk the assembly tree and fail with a {@link ParentChildNameCollisionError}\n * when a parent leaf declares a function or subgroup whose name matches a\n * sibling subdirectory spec's segment. Without this check the colliding\n * descendant would overwrite the parent's entry in the assembled\n * `GroupSpec.groups` map at runtime, surfacing as a confusing\n * `Refs.make` error rather than a codegen-time diagnostic.\n */\nexport const validateNoParentChildNameCollisions = (\n leaves: ReadonlyArray<LeafModule>,\n groupSpecsByRelativePath: ReadonlyMap<string, GroupSpec.AnyWithProps>,\n) =>\n Effect.gen(function* () {\n const { convex, node } = partitionByRuntime(leaves);\n const convexNodes = assemblyNodesFromLeaves(convex);\n const nodeNodes = assemblyNodesFromLeaves(\n Array.map(node, toNodeRegistryLeaf),\n );\n yield* Effect.forEach(convexNodes, (n) =>\n checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath),\n );\n yield* Effect.forEach(nodeNodes, (n) =>\n checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath),\n );\n });\n\nconst checkAssemblyNodeForCollisions = (\n node: SpecAssemblyNode,\n groupSpecsByRelativePath: ReadonlyMap<string, GroupSpec.AnyWithProps>,\n): Effect.Effect<void, ParentChildNameCollisionError> =>\n Effect.gen(function* () {\n yield* Option.match(node.importBinding, {\n onNone: () => Effect.void,\n onSome: (binding) =>\n Effect.gen(function* () {\n if (node.children.length === 0) return;\n const parentRelativePath = bindingToRelativeSpecPath(\n binding.importPath,\n );\n const parentGroupSpec =\n groupSpecsByRelativePath.get(parentRelativePath);\n if (parentGroupSpec === undefined) return;\n yield* Effect.forEach(node.children, (child) => {\n if (\n Object.prototype.hasOwnProperty.call(\n parentGroupSpec.functions,\n child.segment,\n )\n ) {\n return Effect.fail(\n new ParentChildNameCollisionError({\n parentSpecPath: parentRelativePath,\n childSpecPath: childRepresentativeSpecPath(child),\n collisionName: child.segment,\n collisionKind: \"function\",\n }),\n );\n }\n if (\n Object.prototype.hasOwnProperty.call(\n parentGroupSpec.groups,\n child.segment,\n )\n ) {\n return Effect.fail(\n new ParentChildNameCollisionError({\n parentSpecPath: parentRelativePath,\n childSpecPath: childRepresentativeSpecPath(child),\n collisionName: child.segment,\n collisionKind: \"group\",\n }),\n );\n }\n return Effect.void;\n });\n }),\n });\n yield* Effect.forEach(node.children, (child) =>\n checkAssemblyNodeForCollisions(child, groupSpecsByRelativePath),\n );\n });\n\n/**\n * `LeafModule.specImportPath` is the import path used from inside the\n * generated `_generated/spec.ts` (e.g. `\"../notes.spec\"`). Strip the\n * `../` prefix and re-add the `.ts` extension to recover the leaf's\n * confect-relative spec path used as the key in\n * `groupSpecsByRelativePath`.\n */\nconst bindingToRelativeSpecPath = (importPath: string): string => {\n const withoutDotDot = importPath.startsWith(\"../\")\n ? importPath.slice(3)\n : importPath;\n return `${withoutDotDot}.ts`;\n};\n\n/**\n * A child assembly node may itself be a parent without a leaf (when the\n * actual leaves live only in deeper subdirectories). In that case we\n * surface the first descendant leaf as a representative path so the\n * error message points at something the user actually wrote.\n */\nconst childRepresentativeSpecPath = (node: SpecAssemblyNode): string => {\n if (Option.isSome(node.importBinding)) {\n return bindingToRelativeSpecPath(node.importBinding.value.importPath);\n }\n for (const child of node.children) {\n return childRepresentativeSpecPath(child);\n }\n return node.segment;\n};\n\nconst validateOrphanImpls = (specFiles: ReadonlyArray<string>) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const implFiles = yield* discoverLeafImplFiles;\n const specPaths = new Set(specFiles);\n\n yield* Effect.forEach(implFiles, (implRelativePath) =>\n Effect.gen(function* () {\n const specRelativePath = yield* specPathForImpl(implRelativePath);\n if (specPaths.has(specRelativePath)) {\n return;\n }\n\n const specAbsolutePath = path.join(confectDirectory, specRelativePath);\n if (!(yield* fs.exists(specAbsolutePath))) {\n return yield* new MissingSpecFileError({\n implPath: implRelativePath,\n expectedSpecPath: specRelativePath,\n });\n }\n }),\n );\n });\n\nconst removeLegacyFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const legacyPaths = yield* LEGACY_PATHS;\n\n yield* Effect.forEach(legacyPaths, (relativePath) =>\n Effect.gen(function* () {\n const absolutePath = path.join(confectDirectory, relativePath);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n }),\n );\n});\n\nconst generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;\n const { convex, node } = partitionByRuntime(leaves);\n\n if (convex.length > 0) {\n const nodes = assemblyNodesFromLeaves(convex);\n const specContents = yield* templates.assembledSpec({\n nodes,\n runtime: \"Convex\",\n });\n yield* writeFileStringAndLog(\n path.join(confectDirectory, generatedSpecPath),\n specContents,\n );\n }\n\n if (node.length > 0) {\n const nodes = assemblyNodesFromLeaves(\n Array.map(node, toNodeRegistryLeaf),\n );\n const nodeSpecContents = yield* templates.assembledSpec({\n nodes,\n runtime: \"Node\",\n });\n yield* writeFileStringAndLog(\n path.join(confectDirectory, generatedNodeSpecPath),\n nodeSpecContents,\n );\n }\n });\n\nconst validateImplModules = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.forEach(leaves, validateImpl);\n\nconst generateGroupRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n yield* Effect.forEach(leaves, (leaf) =>\n Effect.gen(function* () {\n const registryRelativePath =\n yield* registeredFunctionsRelativePath(leaf);\n const registryPath = path.join(\n confectDirectory,\n \"_generated\",\n registryRelativePath,\n );\n const registryDir = path.dirname(registryPath);\n const fs = yield* FileSystem.FileSystem;\n if (!(yield* fs.exists(registryDir))) {\n yield* fs.makeDirectory(registryDir, { recursive: true });\n }\n\n const implRelativePath = yield* implPathForSpec(leaf.relativePath);\n const schemaImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, \"_generated\", \"schema.ts\"),\n ),\n );\n // The group's own leaf spec (sibling of its impl), referenced\n // type-only by the registry to shape its returned record.\n const specImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, leaf.relativePath),\n ),\n );\n const implImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, implRelativePath),\n ),\n );\n\n const contents = yield* templates.registeredFunctionsForGroup({\n schemaImportPath,\n specImportPath,\n implImportPath,\n layerExportName: leaf.exportName,\n useNode: leaf.runtime === \"Node\",\n });\n\n yield* writeFileStringAndLog(registryPath, contents);\n }),\n );\n });\n\nconst removeObsoleteRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const registryRoot = path.join(\n confectDirectory,\n \"_generated\",\n \"registeredFunctions\",\n );\n\n if (!(yield* fs.exists(registryRoot))) {\n return;\n }\n\n const expected = new Set(\n yield* Effect.forEach(leaves, (leaf) =>\n registeredFunctionsRelativePath(leaf),\n ),\n );\n\n const existing = yield* fs.readDirectory(registryRoot, { recursive: true });\n yield* Effect.forEach(existing, (relativePath) => {\n if (path.extname(relativePath) !== \".ts\") {\n return Effect.void;\n }\n const normalized = path.join(\"registeredFunctions\", relativePath);\n if (!expected.has(normalized)) {\n return Effect.gen(function* () {\n const absolutePath = path.join(registryRoot, relativePath);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n });\n }\n return Effect.void;\n });\n });\n\nconst getGeneratedSpecPath = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n return path.join(confectDirectory, generatedSpecPath);\n});\n\nconst getGeneratedNodeSpecPath = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;\n return path.join(confectDirectory, generatedNodeSpecPath);\n});\n\nconst loadGeneratedSpec = Effect.gen(function* () {\n const specPath = yield* getGeneratedSpecPath;\n const { module: specModule } = yield* Bundler.bundle(specPath);\n const spec = specModule.default;\n\n if (!Spec.isConvexSpec(spec)) {\n return yield* Effect.dieMessage(\n \"_generated/spec.ts does not export a valid Convex Spec\",\n );\n }\n\n return spec;\n});\n\nconst loadGeneratedNodeSpec = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const nodeSpecPath = yield* getGeneratedNodeSpecPath;\n\n if (!(yield* fs.exists(nodeSpecPath))) {\n return Option.none<Spec.AnyWithPropsWithRuntime<\"Node\">>();\n }\n\n const { module: nodeSpecModule } = yield* Bundler.bundle(nodeSpecPath);\n const nodeSpec = nodeSpecModule.default;\n\n if (!Spec.isNodeSpec(nodeSpec)) {\n return yield* Effect.dieMessage(\n \"_generated/nodeSpec.ts does not export a valid Node Spec\",\n );\n }\n\n return Option.some(nodeSpec);\n});\n\nconst emptyFunctionPaths = FunctionPaths.FunctionPaths.make(HashSet.empty());\n\nexport const loadPreviousFunctionPaths = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const specPath = yield* getGeneratedSpecPath;\n\n if (!(yield* fs.exists(specPath))) {\n return emptyFunctionPaths;\n }\n\n const specEither = yield* loadGeneratedSpec.pipe(Effect.either);\n\n return yield* Either.match(specEither, {\n onLeft: () => Effect.succeed(emptyFunctionPaths),\n onRight: (spec) =>\n Effect.gen(function* () {\n const nodeSpecOption = yield* loadGeneratedNodeSpec;\n const mergedSpec = Option.match(nodeSpecOption, {\n onNone: () => spec,\n onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),\n });\n return FunctionPaths.make(mergedSpec);\n }),\n });\n});\n\n/**\n * Remove a now-obsolete `_generated/<name>.ts` if present (and log it), for\n * projects upgrading from a version that still emitted it.\n */\nconst removeObsoleteGeneratedFile = (fileName: string) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const filePath = path.join(confectDirectory, \"_generated\", fileName);\n\n if (yield* fs.exists(filePath)) {\n yield* removePathIfExists(filePath);\n yield* logFileRemoved(filePath);\n }\n });\n\n// `_generated/api.ts` is no longer imported by generated or impl code: impls\n// take the database schema (`_generated/schema`) directly, and per-group\n// registries reference the spec type-only. Remove any stale copy.\nconst removeGeneratedApi = removeObsoleteGeneratedFile(\"api.ts\");\n\n// `_generated/nodeApi.ts` is obsolete for the same reason.\nconst removeGeneratedNodeApi = removeObsoleteGeneratedFile(\"nodeApi.ts\");\n\nconst generateFunctionModules = Effect.gen(function* () {\n const spec = yield* loadGeneratedSpec;\n const nodeSpecOption = yield* loadGeneratedNodeSpec;\n\n const mergedSpec = Option.match(nodeSpecOption, {\n onNone: () => spec,\n onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),\n });\n\n return yield* generateFunctions(mergedSpec);\n});\n\n/**\n * The user-authored `confect/schema.ts` is no longer supported: codegen now\n * owns both `_generated/schema.ts` (runtime) and `_generated/convexSchema.ts`\n * (deploy), derived from a single scan of `confect/tables/*.ts`. Detect a\n * stray file and fail with a clear migration message — leaving it in place\n * would silently shadow the codegen-owned `_generated/schema.ts` /\n * `_generated/convexSchema.ts`.\n */\nconst rejectLegacySchemaFile = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const legacyPath = path.join(confectDirectory, \"schema.ts\");\n\n if (yield* fs.exists(legacyPath)) {\n return yield* new LegacySchemaFileError({ schemaPath: \"schema.ts\" });\n }\n});\n\n/**\n * Surface a yellow `⚠` warning when codegen sees no tables — either the\n * `confect/tables/` directory is missing or it contains no `.ts` files.\n * Generation still succeeds (emitting an empty `DatabaseSchema` and\n * `defineSchema({})`), since action-only / table-free Confect backends\n * are legal — but the warning catches the much more common case of a\n * typoed directory or files placed under the wrong root.\n */\nconst warnIfNoTables = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n tableModules.length === 0\n ? logWarn(\n `No tables discovered in \\`confect/${TableModule.TABLES_DIRNAME}/\\`. ` +\n `Generating an empty schema; add a \\`Table.make(...)\\` module under that ` +\n `directory unless this backend is intentionally tables-free.`,\n )\n : Effect.void;\n\nconst tableModuleBindings = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n generatedFilePath: string,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedDir = path.dirname(generatedFilePath);\n\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n\n return yield* Effect.forEach(tableModules, (tm) =>\n Effect.gen(function* () {\n const wrapperAbsolutePath = path.join(\n confectDirectory,\n generatedTablesDirname,\n `${tm.tableName}.ts`,\n );\n const importPath = yield* toModuleImportPath(\n path.relative(generatedDir, wrapperAbsolutePath),\n );\n return {\n importPath,\n tableName: tm.tableName,\n };\n }),\n );\n });\n\nconst generateIdConstructor = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedIdPath = yield* GENERATED_ID_PATH;\n const idPath = path.join(confectDirectory, generatedIdPath);\n\n const tableNames = tableModules.map((tm) => tm.tableName);\n const contents = yield* templates.id({ tableNames });\n\n yield* writeFileStringAndLog(idPath, contents);\n });\n\nconst generateTableWrappers = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n const wrappersDir = path.join(confectDirectory, generatedTablesDirname);\n\n if (!(yield* fs.exists(wrappersDir))) {\n yield* fs.makeDirectory(wrappersDir, { recursive: true });\n }\n\n yield* Effect.forEach(\n tableModules,\n (tm) =>\n Effect.gen(function* () {\n const wrapperPath = path.join(\n confectDirectory,\n generatedTablesDirname,\n `${tm.tableName}.ts`,\n );\n const unnamedAbsolutePath = path.join(\n confectDirectory,\n tm.relativePath,\n );\n const unnamedImportPath = yield* toModuleImportPath(\n path.relative(path.dirname(wrapperPath), unnamedAbsolutePath),\n );\n const contents = yield* templates.tableWrapper({\n tableName: tm.tableName,\n unnamedImportPath,\n });\n yield* writeFileStringAndLog(wrapperPath, contents);\n }),\n { concurrency: \"unbounded\" },\n );\n });\n\n/**\n * Remove any stale `_generated/tables/*.ts` wrapper whose source table\n * has been deleted or renamed. Mirrors `removeObsoleteRegisteredFunctions`\n * for the wrapper directory.\n */\nconst removeObsoleteTableWrappers = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n const wrappersDir = path.join(confectDirectory, generatedTablesDirname);\n\n if (!(yield* fs.exists(wrappersDir))) {\n return;\n }\n\n const expected = new Set(tableModules.map((tm) => `${tm.tableName}.ts`));\n const existing = yield* fs.readDirectory(wrappersDir, { recursive: true });\n yield* Effect.forEach(existing, (entry) => {\n if (path.extname(entry) !== \".ts\") {\n return Effect.void;\n }\n if (!expected.has(entry)) {\n return Effect.gen(function* () {\n const absolutePath = path.join(wrappersDir, entry);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n });\n }\n return Effect.void;\n });\n });\n\nconst generateRuntimeSchema = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;\n const schemaPath = path.join(confectDirectory, generatedSchemaPath);\n\n const bindings = yield* tableModuleBindings(tableModules, schemaPath);\n const contents = yield* templates.runtimeSchema({ tableModules: bindings });\n\n yield* writeFileStringAndLog(schemaPath, contents);\n });\n\nconst generateConvexSchema = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedConvexSchemaPath = yield* GENERATED_CONVEX_SCHEMA_PATH;\n const convexSchemaPath = path.join(\n confectDirectory,\n generatedConvexSchemaPath,\n );\n\n const bindings = yield* tableModuleBindings(tableModules, convexSchemaPath);\n const contents = yield* templates.convexSchema({ tableModules: bindings });\n\n yield* writeFileStringAndLog(convexSchemaPath, contents);\n });\n\nconst generateConvexSchemaReexport = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const convexDirectory = yield* ConvexDirectory.get;\n const generatedConvexSchemaRelativePath = yield* GENERATED_CONVEX_SCHEMA_PATH;\n\n const convexSchemaPath = path.join(convexDirectory, \"schema.ts\");\n const generatedConvexSchemaPath = path.join(\n confectDirectory,\n generatedConvexSchemaRelativePath,\n );\n\n const convexSchemaImportPath = yield* toModuleImportPath(\n path.relative(path.dirname(convexSchemaPath), generatedConvexSchemaPath),\n );\n\n const schemaContents = yield* templates.schema({\n convexSchemaImportPath,\n });\n\n yield* writeFileStringAndLog(convexSchemaPath, schemaContents);\n});\n\nconst generateServices = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const confectGeneratedDirectory = path.join(confectDirectory, \"_generated\");\n\n const servicesPath = path.join(confectGeneratedDirectory, \"services.ts\");\n const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;\n const schemaImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(servicesPath),\n path.join(confectDirectory, generatedSchemaPath),\n ),\n );\n\n const servicesContentsString = yield* templates.services({\n schemaImportPath,\n });\n\n yield* writeFileStringAndLog(servicesPath, servicesContentsString);\n});\n\nconst generateRefs = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const confectGeneratedDirectory = path.join(confectDirectory, \"_generated\");\n const refsPath = path.join(confectGeneratedDirectory, \"refs.ts\");\n const refsDir = path.dirname(refsPath);\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n\n const specImportPath = yield* toModuleImportPath(\n path.relative(refsDir, path.join(confectDirectory, generatedSpecPath)),\n );\n\n const nodeSpecPath = yield* getGeneratedNodeSpecPath;\n const nodeSpecExists = yield* fs.exists(nodeSpecPath);\n const nodeSpecImportPath = nodeSpecExists\n ? Option.some(\n yield* toModuleImportPath(path.relative(refsDir, nodeSpecPath)),\n )\n : Option.none<string>();\n\n const refsContents = yield* templates.refs({\n specImportPath,\n nodeSpecImportPath,\n });\n\n yield* writeFileStringAndLog(refsPath, refsContents);\n});\n\nconst logGenerated = (effect: typeof generateHttp) =>\n effect.pipe(\n Effect.tap(\n Option.match({\n onNone: () => Effect.void,\n onSome: ({ change, convexFilePath }) =>\n Match.value(change).pipe(\n Match.when(\"Added\", () => logFileAdded(convexFilePath)),\n Match.when(\"Modified\", () => logFileModified(convexFilePath)),\n Match.when(\"Unchanged\", () => Effect.void),\n Match.exhaustive,\n ),\n }),\n ),\n );\n"],"mappings":"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"}
1
+ {"version":3,"file":"codegen.mjs","names":["CodegenError.tapAndLog","TableModule.discover","TableModule.validate","templates.assembledSpec","templates.registeredFunctionsForGroup","Bundler.bundle","FunctionPaths.make","TableModule.TABLES_DIRNAME","templates.id","templates.tableWrapper","templates.runtimeSchema","templates.convexSchema","templates.schema","templates.services","templates.refs"],"sources":["../../src/confect/codegen.ts"],"sourcesContent":["import { Spec, type GroupSpec } from \"@confect/core\";\nimport * as Command from \"@effect/cli/Command\";\nimport * as FileSystem from \"@effect/platform/FileSystem\";\nimport * as Path from \"@effect/platform/Path\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Either from \"effect/Either\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as Bundler from \"../Bundler\";\nimport * as CodegenError from \"../CodegenError\";\nimport {\n LegacySchemaFileError,\n MissingImplFileError,\n MissingSpecFileError,\n ParentChildNameCollisionError,\n} from \"../CodegenError\";\nimport { ConfectDirectory } from \"../ConfectDirectory\";\nimport { ConvexDirectory } from \"../ConvexDirectory\";\nimport * as FunctionPaths from \"../FunctionPaths\";\nimport {\n discoverLeafImplFiles,\n discoverLeafSpecFiles,\n implPathForSpec,\n registeredFunctionsRelativePath,\n specPathForImpl,\n toLeafModule,\n validateImpl,\n validateSpec,\n type LeafModule,\n} from \"../LeafModule\";\nimport {\n logFileAdded,\n logFileModified,\n logFileRemoved,\n logPending,\n logSuccess,\n logWarn,\n} from \"../log\";\nimport {\n assemblyNodesFromLeaves,\n type SpecAssemblyNode,\n} from \"../SpecAssemblyNode\";\nimport * as TableModule from \"../TableModule\";\nimport * as templates from \"../templates\";\nimport {\n generateAuthConfig,\n generateCrons,\n generateFunctions,\n generateHttp,\n removePathIfExists,\n toModuleImportPath,\n touchConvexSchema,\n writeFileStringAndLog,\n WriteTracker,\n} from \"../utils\";\n\nconst GENERATED_DIRNAME = \"_generated\";\n\nconst GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"spec.ts\"),\n);\nconst GENERATED_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"schema.ts\"),\n);\nconst GENERATED_CONVEX_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"convexSchema.ts\"),\n);\nconst GENERATED_ID_PATH = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"id.ts\"),\n);\nconst GENERATED_TABLES_DIRNAME = Effect.andThen(Path.Path, (path) =>\n path.join(GENERATED_DIRNAME, \"tables\"),\n);\n\nconst LEGACY_PATHS = Effect.gen(function* () {\n const path = yield* Path.Path;\n\n return [\n \"spec.ts\",\n \"nodeSpec.ts\",\n \"impl.ts\",\n \"nodeImpl.ts\",\n path.join(GENERATED_DIRNAME, \"registeredFunctions.ts\"),\n path.join(GENERATED_DIRNAME, \"nodeRegisteredFunctions.ts\"),\n path.join(GENERATED_DIRNAME, \"impl.ts\"),\n path.join(GENERATED_DIRNAME, \"nodeImpl.ts\"),\n // `_generated/nodeSpec.ts` is not part of the generated output (all groups\n // live in `_generated/spec.ts`); delete any copy left by an older version.\n path.join(GENERATED_DIRNAME, \"nodeSpec.ts\"),\n ];\n});\n\nexport const codegen = Command.make(\"codegen\", {}, () =>\n Effect.gen(function* () {\n yield* logPending(\"Performing initial sync…\");\n yield* codegenHandler.pipe(\n Effect.asVoid,\n Effect.tap(() => logSuccess(\"Generated files are up-to-date\")),\n CodegenError.tapAndLog,\n );\n }),\n).pipe(\n Command.withDescription(\n \"Generate `confect/_generated` files and the contents of the `convex` directory (except `convex.config.ts` and `tsconfig.json`)\",\n ),\n);\n\nexport const codegenHandler = Effect.gen(function* () {\n const tracker = yield* Ref.make(false);\n\n const functionPaths = yield* runCodegen.pipe(\n Effect.provideService(WriteTracker, tracker),\n );\n\n const anyWritesHappened = yield* Ref.get(tracker);\n return { functionPaths, anyWritesHappened };\n});\n\nconst runCodegen = Effect.gen(function* () {\n yield* generateConfectGeneratedDirectory;\n // Reject a legacy `confect/schema.ts` up front so the user-facing\n // migration message surfaces before any bundler error from impl\n // validation (each impl imports `_generated/schema.ts`).\n yield* rejectLegacySchemaFile;\n // List `confect/tables/*.ts` (filename-only — no bundling yet) so the\n // `_generated/id.ts` constructor can be emitted *before* we bundle any\n // user-authored table module. Tables import from `_generated/id.ts` for\n // cross-table id refs, so it must exist on disk first.\n const tableModules = yield* TableModule.discover;\n yield* warnIfNoTables(tableModules);\n yield* generateIdConstructor(tableModules);\n // Now that `_generated/id.ts` is on disk, bundle each table module and\n // check its default export is an `UnnamedTable`. Surface diagnostics\n // here (rather than later) so they appear before impl-validation noise.\n yield* TableModule.validate(tableModules);\n yield* generateTableWrappers(tableModules);\n yield* removeObsoleteTableWrappers(tableModules);\n yield* generateRuntimeSchema(tableModules);\n const { leaves, groupSpecsByRelativePath } =\n yield* loadAndValidateLeafModules;\n yield* removeLegacyFiles;\n yield* validateNoParentChildNameCollisions(leaves, groupSpecsByRelativePath);\n yield* generateAssembledSpecs(leaves);\n // `_generated/api.ts` / `nodeApi.ts` are no longer imported by generated or\n // impl code (impls take the database schema from `_generated/schema`\n // directly), so remove any copies left over from earlier versions before\n // impl validation runs.\n yield* Effect.all(\n [\n removeGeneratedApi,\n generateRefs,\n removeGeneratedNodeApi,\n generateServices,\n generateConvexSchema(tableModules),\n ],\n { concurrency: \"unbounded\" },\n );\n yield* validateImplModules(leaves);\n yield* generateGroupRegisteredFunctions(leaves);\n yield* removeObsoleteRegisteredFunctions(leaves);\n const [functionPaths] = yield* Effect.all(\n [\n generateFunctionModules,\n generateConvexSchemaReexport,\n logGenerated(generateHttp),\n logGenerated(generateCrons),\n logGenerated(generateAuthConfig),\n ],\n { concurrency: \"unbounded\" },\n );\n yield* touchConvexSchema;\n return functionPaths;\n});\n\nconst generateConfectGeneratedDirectory = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n if (!(yield* fs.exists(path.join(confectDirectory, \"_generated\")))) {\n yield* fs.makeDirectory(path.join(confectDirectory, \"_generated\"), {\n recursive: true,\n });\n yield* logFileAdded(path.join(confectDirectory, \"_generated\") + \"/\");\n }\n});\n\nconst loadAndValidateLeafModules = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const specFiles = yield* discoverLeafSpecFiles;\n\n const results = yield* Effect.forEach(specFiles, (specRelativePath) =>\n Effect.gen(function* () {\n const discovered = yield* toLeafModule(specRelativePath);\n const groupSpec = yield* validateSpec(discovered);\n // Fill in the runtime now that the spec is bundled; discovery left it `None`.\n const leaf = {\n ...discovered,\n runtime: Option.some(groupSpec.runtime),\n };\n\n const implRelativePath = yield* implPathForSpec(specRelativePath);\n const implAbsolutePath = path.join(confectDirectory, implRelativePath);\n if (!(yield* fs.exists(implAbsolutePath))) {\n return yield* new MissingImplFileError({\n specPath: specRelativePath,\n expectedImplPath: implRelativePath,\n });\n }\n\n return { leaf, groupSpec };\n }),\n );\n\n yield* validateOrphanImpls(specFiles);\n\n const leaves = Array.map(results, ({ leaf }) => leaf);\n const groupSpecsByRelativePath = new Map(\n Array.map(results, ({ leaf, groupSpec }) => [leaf.relativePath, groupSpec]),\n );\n\n return { leaves, groupSpecsByRelativePath };\n});\n\n/**\n * Walk the assembly tree and fail with a {@link ParentChildNameCollisionError}\n * when a parent leaf declares a function or subgroup whose name matches a\n * sibling subdirectory spec's segment. Without this check the colliding\n * descendant would overwrite the parent's entry in the assembled\n * `GroupSpec.groups` map at runtime, surfacing as a confusing\n * `Refs.make` error rather than a codegen-time diagnostic.\n */\nexport const validateNoParentChildNameCollisions = (\n leaves: ReadonlyArray<LeafModule>,\n groupSpecsByRelativePath: ReadonlyMap<string, GroupSpec.AnyWithProps>,\n) =>\n Effect.gen(function* () {\n // Convex and Node groups share one namespace, so they assemble into a\n // single tree. A Node group nested under a Convex parent (or vice versa) is\n // caught here by the parent/child collision check.\n const nodes = assemblyNodesFromLeaves(leaves);\n yield* Effect.forEach(nodes, (n) =>\n checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath),\n );\n });\n\nconst checkAssemblyNodeForCollisions = (\n node: SpecAssemblyNode,\n groupSpecsByRelativePath: ReadonlyMap<string, GroupSpec.AnyWithProps>,\n): Effect.Effect<void, ParentChildNameCollisionError> =>\n Effect.gen(function* () {\n yield* Option.match(node.importBinding, {\n onNone: () => Effect.void,\n onSome: (binding) =>\n Effect.gen(function* () {\n if (node.children.length === 0) return;\n const parentRelativePath = bindingToRelativeSpecPath(\n binding.importPath,\n );\n const parentGroupSpec =\n groupSpecsByRelativePath.get(parentRelativePath);\n if (parentGroupSpec === undefined) return;\n yield* Effect.forEach(node.children, (child) => {\n if (\n Object.prototype.hasOwnProperty.call(\n parentGroupSpec.functions,\n child.segment,\n )\n ) {\n return Effect.fail(\n new ParentChildNameCollisionError({\n parentSpecPath: parentRelativePath,\n childSpecPath: childRepresentativeSpecPath(child),\n collisionName: child.segment,\n collisionKind: \"function\",\n }),\n );\n }\n if (\n Object.prototype.hasOwnProperty.call(\n parentGroupSpec.groups,\n child.segment,\n )\n ) {\n return Effect.fail(\n new ParentChildNameCollisionError({\n parentSpecPath: parentRelativePath,\n childSpecPath: childRepresentativeSpecPath(child),\n collisionName: child.segment,\n collisionKind: \"group\",\n }),\n );\n }\n return Effect.void;\n });\n }),\n });\n yield* Effect.forEach(node.children, (child) =>\n checkAssemblyNodeForCollisions(child, groupSpecsByRelativePath),\n );\n });\n\n/**\n * `LeafModule.specImportPath` is the import path used from inside the\n * generated `_generated/spec.ts` (e.g. `\"../notes.spec\"`). Strip the\n * `../` prefix and re-add the `.ts` extension to recover the leaf's\n * confect-relative spec path used as the key in\n * `groupSpecsByRelativePath`.\n */\nconst bindingToRelativeSpecPath = (importPath: string): string => {\n const withoutDotDot = importPath.startsWith(\"../\")\n ? importPath.slice(3)\n : importPath;\n return `${withoutDotDot}.ts`;\n};\n\n/**\n * A child assembly node may itself be a parent without a leaf (when the\n * actual leaves live only in deeper subdirectories). In that case we\n * surface the first descendant leaf as a representative path so the\n * error message points at something the user actually wrote.\n */\nconst childRepresentativeSpecPath = (node: SpecAssemblyNode): string => {\n if (Option.isSome(node.importBinding)) {\n return bindingToRelativeSpecPath(node.importBinding.value.importPath);\n }\n for (const child of node.children) {\n return childRepresentativeSpecPath(child);\n }\n return node.segment;\n};\n\nconst validateOrphanImpls = (specFiles: ReadonlyArray<string>) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const implFiles = yield* discoverLeafImplFiles;\n const specPaths = new Set(specFiles);\n\n yield* Effect.forEach(implFiles, (implRelativePath) =>\n Effect.gen(function* () {\n const specRelativePath = yield* specPathForImpl(implRelativePath);\n if (specPaths.has(specRelativePath)) {\n return;\n }\n\n const specAbsolutePath = path.join(confectDirectory, specRelativePath);\n if (!(yield* fs.exists(specAbsolutePath))) {\n return yield* new MissingSpecFileError({\n implPath: implRelativePath,\n expectedSpecPath: specRelativePath,\n });\n }\n }),\n );\n });\n\nconst removeLegacyFiles = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const legacyPaths = yield* LEGACY_PATHS;\n\n yield* Effect.forEach(legacyPaths, (relativePath) =>\n Effect.gen(function* () {\n const absolutePath = path.join(confectDirectory, relativePath);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n }),\n );\n});\n\nconst generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n\n // A single assembled spec holds every group regardless of runtime — a Node\n // group's `makeNode()` lives in its imported leaf spec, so the assembled\n // file is runtime-agnostic. Always emit it (even empty) so downstream\n // readers (`loadGeneratedSpec`, `generateRefs`) always find a spec module.\n const nodes = assemblyNodesFromLeaves(leaves);\n const specContents = yield* templates.assembledSpec({ nodes });\n yield* writeFileStringAndLog(\n path.join(confectDirectory, generatedSpecPath),\n specContents,\n );\n });\n\nconst validateImplModules = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.forEach(leaves, validateImpl);\n\nconst generateGroupRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n yield* Effect.forEach(leaves, (leaf) =>\n Effect.gen(function* () {\n const registryRelativePath =\n yield* registeredFunctionsRelativePath(leaf);\n const registryPath = path.join(\n confectDirectory,\n \"_generated\",\n registryRelativePath,\n );\n const registryDir = path.dirname(registryPath);\n const fs = yield* FileSystem.FileSystem;\n if (!(yield* fs.exists(registryDir))) {\n yield* fs.makeDirectory(registryDir, { recursive: true });\n }\n\n const implRelativePath = yield* implPathForSpec(leaf.relativePath);\n const schemaImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, \"_generated\", \"schema.ts\"),\n ),\n );\n // The group's own leaf spec (sibling of its impl), referenced\n // type-only by the registry to shape its returned record.\n const specImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, leaf.relativePath),\n ),\n );\n const implImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(registryPath),\n path.join(confectDirectory, implRelativePath),\n ),\n );\n\n // Every leaf reaching this point came through\n // `loadAndValidateLeafModules`, which stamps the runtime from the\n // validated spec — so `None` here means that invariant was broken.\n const runtime = yield* Option.match(leaf.runtime, {\n onNone: () =>\n Effect.dieMessage(\n `Runtime for '${leaf.relativePath}' was not resolved before registry generation.`,\n ),\n onSome: Effect.succeed,\n });\n\n const contents = yield* templates.registeredFunctionsForGroup({\n schemaImportPath,\n specImportPath,\n implImportPath,\n layerExportName: leaf.exportName,\n useNode: runtime === \"Node\",\n });\n\n yield* writeFileStringAndLog(registryPath, contents);\n }),\n );\n });\n\nconst removeObsoleteRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const registryRoot = path.join(\n confectDirectory,\n \"_generated\",\n \"registeredFunctions\",\n );\n\n if (!(yield* fs.exists(registryRoot))) {\n return;\n }\n\n const expected = new Set(\n yield* Effect.forEach(leaves, (leaf) =>\n registeredFunctionsRelativePath(leaf),\n ),\n );\n\n const existing = yield* fs.readDirectory(registryRoot, { recursive: true });\n yield* Effect.forEach(existing, (relativePath) => {\n if (path.extname(relativePath) !== \".ts\") {\n return Effect.void;\n }\n const normalized = path.join(\"registeredFunctions\", relativePath);\n if (!expected.has(normalized)) {\n return Effect.gen(function* () {\n const absolutePath = path.join(registryRoot, relativePath);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n });\n }\n return Effect.void;\n });\n });\n\nconst getGeneratedSpecPath = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n return path.join(confectDirectory, generatedSpecPath);\n});\n\nconst loadGeneratedSpec = Effect.gen(function* () {\n const specPath = yield* getGeneratedSpecPath;\n const { module: specModule } = yield* Bundler.bundle(specPath);\n const spec = specModule.default;\n\n if (!Spec.isSpec(spec)) {\n return yield* Effect.dieMessage(\n \"_generated/spec.ts does not export a valid Spec\",\n );\n }\n\n return spec;\n});\n\nconst emptyFunctionPaths = FunctionPaths.FunctionPaths.make(HashSet.empty());\n\nexport const loadPreviousFunctionPaths = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const specPath = yield* getGeneratedSpecPath;\n\n if (!(yield* fs.exists(specPath))) {\n return emptyFunctionPaths;\n }\n\n const specEither = yield* loadGeneratedSpec.pipe(Effect.either);\n\n return Either.match(specEither, {\n onLeft: () => emptyFunctionPaths,\n onRight: (spec) => FunctionPaths.make(spec),\n });\n});\n\n/**\n * Remove a now-obsolete `_generated/<name>.ts` if present (and log it), for\n * projects upgrading from a version that still emitted it.\n */\nconst removeObsoleteGeneratedFile = (fileName: string) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const filePath = path.join(confectDirectory, \"_generated\", fileName);\n\n if (yield* fs.exists(filePath)) {\n yield* removePathIfExists(filePath);\n yield* logFileRemoved(filePath);\n }\n });\n\n// `_generated/api.ts` is no longer imported by generated or impl code: impls\n// take the database schema (`_generated/schema`) directly, and per-group\n// registries reference the spec type-only. Remove any stale copy.\nconst removeGeneratedApi = removeObsoleteGeneratedFile(\"api.ts\");\n\n// `_generated/nodeApi.ts` is obsolete for the same reason.\nconst removeGeneratedNodeApi = removeObsoleteGeneratedFile(\"nodeApi.ts\");\n\nconst generateFunctionModules = Effect.gen(function* () {\n const spec = yield* loadGeneratedSpec;\n return yield* generateFunctions(spec);\n});\n\n/**\n * The user-authored `confect/schema.ts` is no longer supported: codegen now\n * owns both `_generated/schema.ts` (runtime) and `_generated/convexSchema.ts`\n * (deploy), derived from a single scan of `confect/tables/*.ts`. Detect a\n * stray file and fail with a clear migration message — leaving it in place\n * would silently shadow the codegen-owned `_generated/schema.ts` /\n * `_generated/convexSchema.ts`.\n */\nconst rejectLegacySchemaFile = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const legacyPath = path.join(confectDirectory, \"schema.ts\");\n\n if (yield* fs.exists(legacyPath)) {\n return yield* new LegacySchemaFileError({ schemaPath: \"schema.ts\" });\n }\n});\n\n/**\n * Surface a yellow `⚠` warning when codegen sees no tables — either the\n * `confect/tables/` directory is missing or it contains no `.ts` files.\n * Generation still succeeds (emitting an empty `DatabaseSchema` and\n * `defineSchema({})`), since action-only / table-free Confect backends\n * are legal — but the warning catches the much more common case of a\n * typoed directory or files placed under the wrong root.\n */\nconst warnIfNoTables = (tableModules: ReadonlyArray<TableModule.TableModule>) =>\n tableModules.length === 0\n ? logWarn(\n `No tables discovered in \\`confect/${TableModule.TABLES_DIRNAME}/\\`. ` +\n `Generating an empty schema; add a \\`Table.make(...)\\` module under that ` +\n `directory unless this backend is intentionally tables-free.`,\n )\n : Effect.void;\n\nconst tableModuleBindings = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n generatedFilePath: string,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedDir = path.dirname(generatedFilePath);\n\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n\n return yield* Effect.forEach(tableModules, (tm) =>\n Effect.gen(function* () {\n const wrapperAbsolutePath = path.join(\n confectDirectory,\n generatedTablesDirname,\n `${tm.tableName}.ts`,\n );\n const importPath = yield* toModuleImportPath(\n path.relative(generatedDir, wrapperAbsolutePath),\n );\n return {\n importPath,\n tableName: tm.tableName,\n };\n }),\n );\n });\n\nconst generateIdConstructor = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedIdPath = yield* GENERATED_ID_PATH;\n const idPath = path.join(confectDirectory, generatedIdPath);\n\n const tableNames = tableModules.map((tm) => tm.tableName);\n const contents = yield* templates.id({ tableNames });\n\n yield* writeFileStringAndLog(idPath, contents);\n });\n\nconst generateTableWrappers = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n const wrappersDir = path.join(confectDirectory, generatedTablesDirname);\n\n if (!(yield* fs.exists(wrappersDir))) {\n yield* fs.makeDirectory(wrappersDir, { recursive: true });\n }\n\n yield* Effect.forEach(\n tableModules,\n (tm) =>\n Effect.gen(function* () {\n const wrapperPath = path.join(\n confectDirectory,\n generatedTablesDirname,\n `${tm.tableName}.ts`,\n );\n const unnamedAbsolutePath = path.join(\n confectDirectory,\n tm.relativePath,\n );\n const unnamedImportPath = yield* toModuleImportPath(\n path.relative(path.dirname(wrapperPath), unnamedAbsolutePath),\n );\n const contents = yield* templates.tableWrapper({\n tableName: tm.tableName,\n unnamedImportPath,\n });\n yield* writeFileStringAndLog(wrapperPath, contents);\n }),\n { concurrency: \"unbounded\" },\n );\n });\n\n/**\n * Remove any stale `_generated/tables/*.ts` wrapper whose source table\n * has been deleted or renamed. Mirrors `removeObsoleteRegisteredFunctions`\n * for the wrapper directory.\n */\nconst removeObsoleteTableWrappers = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;\n const wrappersDir = path.join(confectDirectory, generatedTablesDirname);\n\n if (!(yield* fs.exists(wrappersDir))) {\n return;\n }\n\n const expected = new Set(tableModules.map((tm) => `${tm.tableName}.ts`));\n const existing = yield* fs.readDirectory(wrappersDir, { recursive: true });\n yield* Effect.forEach(existing, (entry) => {\n if (path.extname(entry) !== \".ts\") {\n return Effect.void;\n }\n if (!expected.has(entry)) {\n return Effect.gen(function* () {\n const absolutePath = path.join(wrappersDir, entry);\n if (yield* fs.exists(absolutePath)) {\n yield* removePathIfExists(absolutePath);\n yield* logFileRemoved(absolutePath);\n }\n });\n }\n return Effect.void;\n });\n });\n\nconst generateRuntimeSchema = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;\n const schemaPath = path.join(confectDirectory, generatedSchemaPath);\n\n const bindings = yield* tableModuleBindings(tableModules, schemaPath);\n const contents = yield* templates.runtimeSchema({ tableModules: bindings });\n\n yield* writeFileStringAndLog(schemaPath, contents);\n });\n\nconst generateConvexSchema = (\n tableModules: ReadonlyArray<TableModule.TableModule>,\n) =>\n Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const generatedConvexSchemaPath = yield* GENERATED_CONVEX_SCHEMA_PATH;\n const convexSchemaPath = path.join(\n confectDirectory,\n generatedConvexSchemaPath,\n );\n\n const bindings = yield* tableModuleBindings(tableModules, convexSchemaPath);\n const contents = yield* templates.convexSchema({ tableModules: bindings });\n\n yield* writeFileStringAndLog(convexSchemaPath, contents);\n });\n\nconst generateConvexSchemaReexport = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n const convexDirectory = yield* ConvexDirectory.get;\n const generatedConvexSchemaRelativePath = yield* GENERATED_CONVEX_SCHEMA_PATH;\n\n const convexSchemaPath = path.join(convexDirectory, \"schema.ts\");\n const generatedConvexSchemaPath = path.join(\n confectDirectory,\n generatedConvexSchemaRelativePath,\n );\n\n const convexSchemaImportPath = yield* toModuleImportPath(\n path.relative(path.dirname(convexSchemaPath), generatedConvexSchemaPath),\n );\n\n const schemaContents = yield* templates.schema({\n convexSchemaImportPath,\n });\n\n yield* writeFileStringAndLog(convexSchemaPath, schemaContents);\n});\n\nconst generateServices = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const confectGeneratedDirectory = path.join(confectDirectory, \"_generated\");\n\n const servicesPath = path.join(confectGeneratedDirectory, \"services.ts\");\n const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;\n const schemaImportPath = yield* toModuleImportPath(\n path.relative(\n path.dirname(servicesPath),\n path.join(confectDirectory, generatedSchemaPath),\n ),\n );\n\n const servicesContentsString = yield* templates.services({\n schemaImportPath,\n });\n\n yield* writeFileStringAndLog(servicesPath, servicesContentsString);\n});\n\nconst generateRefs = Effect.gen(function* () {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const confectGeneratedDirectory = path.join(confectDirectory, \"_generated\");\n const refsPath = path.join(confectGeneratedDirectory, \"refs.ts\");\n const refsDir = path.dirname(refsPath);\n const generatedSpecPath = yield* GENERATED_SPEC_PATH;\n\n const specImportPath = yield* toModuleImportPath(\n path.relative(refsDir, path.join(confectDirectory, generatedSpecPath)),\n );\n\n const refsContents = yield* templates.refs({ specImportPath });\n\n yield* writeFileStringAndLog(refsPath, refsContents);\n});\n\nconst logGenerated = (effect: typeof generateHttp) =>\n effect.pipe(\n Effect.tap(\n Option.match({\n onNone: () => Effect.void,\n onSome: ({ change, convexFilePath }) =>\n Match.value(change).pipe(\n Match.when(\"Added\", () => logFileAdded(convexFilePath)),\n Match.when(\"Modified\", () => logFileModified(convexFilePath)),\n Match.when(\"Unchanged\", () => Effect.void),\n Match.exhaustive,\n ),\n }),\n ),\n );\n"],"mappings":"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"}
@@ -38,7 +38,6 @@ import * as Stream from "effect/Stream";
38
38
  //#region src/confect/dev.ts
39
39
  const GENERATED_DIRNAME = "_generated";
40
40
  const GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "spec.ts"));
41
- const GENERATED_NODE_SPEC_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "nodeSpec.ts"));
42
41
  const COALESCE_QUIESCENCE = Duration.millis(300);
43
42
  const COALESCE_MAX_WAIT = Duration.seconds(5);
44
43
  const ECHO_COOLDOWN = Duration.millis(500);
@@ -184,10 +183,8 @@ const discoverEntryPoints = Effect.gen(function* () {
184
183
  });
185
184
  });
186
185
  const generatedSpecPath = yield* GENERATED_SPEC_PATH;
187
- const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
188
186
  const fixedEntryOptions = yield* Effect.all([
189
187
  tryEntry(generatedSpecPath, "specDirty"),
190
- tryEntry(generatedNodeSpecPath, "specDirty"),
191
188
  tryEntry("http.ts", "httpDirty"),
192
189
  tryEntry("crons.ts", "cronsDirty"),
193
190
  tryEntry("auth.ts", "authDirty")