@gaganref/confect-cli 0.0.0-stage → 10.3.1-fork.2

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 (99) hide show
  1. package/CHANGELOG.md +1824 -0
  2. package/LICENSE +7 -0
  3. package/README.md +16 -2
  4. package/bin/confect.mjs +26 -0
  5. package/dist/Ansi.mjs +18 -0
  6. package/dist/Ansi.mjs.map +1 -0
  7. package/dist/BuildError.mjs +30 -0
  8. package/dist/BuildError.mjs.map +1 -0
  9. package/dist/Bundler.mjs +426 -0
  10. package/dist/Bundler.mjs.map +1 -0
  11. package/dist/CodeBlockWriter.mjs +55 -0
  12. package/dist/CodeBlockWriter.mjs.map +1 -0
  13. package/dist/CodegenError.mjs +194 -0
  14. package/dist/CodegenError.mjs.map +1 -0
  15. package/dist/ConfectDirectory.mjs +35 -0
  16. package/dist/ConfectDirectory.mjs.map +1 -0
  17. package/dist/ConvexConfig.mjs +198 -0
  18. package/dist/ConvexConfig.mjs.map +1 -0
  19. package/dist/ConvexDirectory.mjs +54 -0
  20. package/dist/ConvexDirectory.mjs.map +1 -0
  21. package/dist/Declaration.mjs +258 -0
  22. package/dist/Declaration.mjs.map +1 -0
  23. package/dist/DirectoryOptions.mjs +42 -0
  24. package/dist/DirectoryOptions.mjs.map +1 -0
  25. package/dist/DocName.mjs +25 -0
  26. package/dist/DocName.mjs.map +1 -0
  27. package/dist/EntryPoint.mjs +111 -0
  28. package/dist/EntryPoint.mjs.map +1 -0
  29. package/dist/Evaluation.mjs +117 -0
  30. package/dist/Evaluation.mjs.map +1 -0
  31. package/dist/EvaluationWorker.mjs +46 -0
  32. package/dist/EvaluationWorker.mjs.map +1 -0
  33. package/dist/FunctionModule.mjs +137 -0
  34. package/dist/FunctionModule.mjs.map +1 -0
  35. package/dist/FunctionPath.mjs +18 -0
  36. package/dist/FunctionPath.mjs.map +1 -0
  37. package/dist/FunctionPaths.mjs +45 -0
  38. package/dist/FunctionPaths.mjs.map +1 -0
  39. package/dist/GenerationSnapshot.mjs +183 -0
  40. package/dist/GenerationSnapshot.mjs.map +1 -0
  41. package/dist/GroupPath.mjs +51 -0
  42. package/dist/GroupPath.mjs.map +1 -0
  43. package/dist/GroupPaths.mjs +8 -0
  44. package/dist/GroupPaths.mjs.map +1 -0
  45. package/dist/ImplModulePath.mjs +8 -0
  46. package/dist/ImplModulePath.mjs.map +1 -0
  47. package/dist/LeafModule.mjs +285 -0
  48. package/dist/LeafModule.mjs.map +1 -0
  49. package/dist/ProjectRoot.mjs +38 -0
  50. package/dist/ProjectRoot.mjs.map +1 -0
  51. package/dist/RelativeModulePath.mjs +13 -0
  52. package/dist/RelativeModulePath.mjs.map +1 -0
  53. package/dist/Remove.mjs +24 -0
  54. package/dist/Remove.mjs.map +1 -0
  55. package/dist/RestoreWatcher.mjs +31 -0
  56. package/dist/RestoreWatcher.mjs.map +1 -0
  57. package/dist/Rollback.mjs +50 -0
  58. package/dist/Rollback.mjs.map +1 -0
  59. package/dist/SnapshotError.mjs +21 -0
  60. package/dist/SnapshotError.mjs.map +1 -0
  61. package/dist/SpecAssemblyNode.mjs +91 -0
  62. package/dist/SpecAssemblyNode.mjs.map +1 -0
  63. package/dist/SpecModulePath.mjs +10 -0
  64. package/dist/SpecModulePath.mjs.map +1 -0
  65. package/dist/SyncState.mjs +122 -0
  66. package/dist/SyncState.mjs.map +1 -0
  67. package/dist/TableModule.mjs +97 -0
  68. package/dist/TableModule.mjs.map +1 -0
  69. package/dist/TableModulePath.mjs +8 -0
  70. package/dist/TableModulePath.mjs.map +1 -0
  71. package/dist/WatchBuild.mjs +190 -0
  72. package/dist/WatchBuild.mjs.map +1 -0
  73. package/dist/WatchGraph.mjs +35 -0
  74. package/dist/WatchGraph.mjs.map +1 -0
  75. package/dist/WatchTopology.mjs +55 -0
  76. package/dist/WatchTopology.mjs.map +1 -0
  77. package/dist/Watcher.mjs +378 -0
  78. package/dist/Watcher.mjs.map +1 -0
  79. package/dist/cliApp.mjs +9 -0
  80. package/dist/cliApp.mjs.map +1 -0
  81. package/dist/confect/codegen.mjs +548 -0
  82. package/dist/confect/codegen.mjs.map +1 -0
  83. package/dist/confect/declaration.mjs +218 -0
  84. package/dist/confect/declaration.mjs.map +1 -0
  85. package/dist/confect/dev.mjs +182 -0
  86. package/dist/confect/dev.mjs.map +1 -0
  87. package/dist/confect.mjs +9 -0
  88. package/dist/confect.mjs.map +1 -0
  89. package/dist/index.mjs +19 -0
  90. package/dist/index.mjs.map +1 -0
  91. package/dist/log.mjs +107 -0
  92. package/dist/log.mjs.map +1 -0
  93. package/dist/package.mjs +6 -0
  94. package/dist/package.mjs.map +1 -0
  95. package/dist/templates.mjs +448 -0
  96. package/dist/templates.mjs.map +1 -0
  97. package/dist/utils.mjs +105 -0
  98. package/dist/utils.mjs.map +1 -0
  99. package/package.json +51 -3
@@ -0,0 +1,117 @@
1
+ import { ProjectRoot } from "./ProjectRoot.mjs";
2
+ import { ComponentNodeGroupError, logCodegenError } from "./CodegenError.mjs";
3
+ import { ConvexDirectory } from "./ConvexDirectory.mjs";
4
+ import { ConfectDirectory } from "./ConfectDirectory.mjs";
5
+ import { FunctionPaths } from "./FunctionPaths.mjs";
6
+ import { ImplModulePath } from "./ImplModulePath.mjs";
7
+ import { GenerationSnapshot, functionPaths } from "./GenerationSnapshot.mjs";
8
+ import { Declaration } from "./EntryPoint.mjs";
9
+ import * as Effect from "effect/Effect";
10
+ import * as FileSystem from "effect/FileSystem";
11
+ import * as Path from "effect/Path";
12
+ import * as HashSet from "effect/HashSet";
13
+ import * as Match from "effect/Match";
14
+ import * as Option from "effect/Option";
15
+ import * as Schema from "effect/Schema";
16
+ import * as Console from "effect/Console";
17
+ import * as Layer from "effect/Layer";
18
+ import * as NodeWorker from "@effect/platform-node/NodeWorker";
19
+ import { fork } from "node:child_process";
20
+ import * as LogLevel from "effect/LogLevel";
21
+ import * as References from "effect/References";
22
+ import * as Rpc from "effect/rpc/Rpc";
23
+ import * as RpcClient from "effect/rpc/RpcClient";
24
+ import * as RpcGroup from "effect/rpc/RpcGroup";
25
+ //#region src/Evaluation.ts
26
+ const RequestContext = Schema.Struct({
27
+ projectRoot: Schema.String,
28
+ confectDirectory: Schema.String,
29
+ convexDirectory: Schema.String,
30
+ target: Schema.Union([Schema.Struct({ kind: Schema.Literal("app") }), Schema.Struct({
31
+ kind: Schema.Literal("component"),
32
+ definition: Schema.String
33
+ })]),
34
+ minimumLogLevel: Schema.Literals(LogLevel.values)
35
+ });
36
+ var EvaluationError = class extends Schema.TaggedError()("EvaluationError", { diagnostic: Schema.String }) {};
37
+ const Failure = Schema.Union([EvaluationError, ComponentNodeGroupError]);
38
+ const requests = RpcGroup.make(Rpc.make("Previous", {
39
+ payload: RequestContext,
40
+ success: FunctionPaths,
41
+ error: Failure
42
+ }), Rpc.make("Generate", {
43
+ payload: RequestContext,
44
+ success: GenerationSnapshot,
45
+ error: Failure
46
+ }), Rpc.make("Validate", {
47
+ payload: Schema.Struct({
48
+ ...RequestContext.fields,
49
+ paths: Schema.Array(ImplModulePath)
50
+ }),
51
+ success: Schema.Void,
52
+ error: Failure
53
+ }), Rpc.make("Update", {
54
+ payload: Schema.Struct({
55
+ ...RequestContext.fields,
56
+ snapshot: GenerationSnapshot,
57
+ declarations: Schema.NonEmptyArray(Declaration),
58
+ paths: Schema.Array(ImplModulePath)
59
+ }),
60
+ success: GenerationSnapshot,
61
+ error: Failure
62
+ }));
63
+ const withWorker = Effect.fn("Evaluation.withWorker")(function* (run) {
64
+ const requestContext = {
65
+ projectRoot: yield* ProjectRoot.get,
66
+ confectDirectory: yield* ConfectDirectory.get,
67
+ convexDirectory: yield* ConvexDirectory.get,
68
+ target: Match.value(yield* ConvexDirectory.target).pipe(Match.when({ kind: "app" }, () => ({ kind: "app" })), Match.when({ kind: "component" }, ({ scope }) => ({
69
+ kind: "component",
70
+ definition: scope.slice(10)
71
+ })), Match.exhaustive),
72
+ minimumLogLevel: yield* References.MinimumLogLevel
73
+ };
74
+ return yield* Effect.scoped(Effect.gen(function* () {
75
+ const child = yield* Effect.acquireRelease(Effect.sync(() => fork(new URL("../dist/EvaluationWorker.mjs", import.meta.url), { serialization: "advanced" })), (evaluator) => Effect.callback((resume) => {
76
+ if (evaluator.exitCode !== null || evaluator.signalCode !== null) {
77
+ resume(Effect.void);
78
+ return;
79
+ }
80
+ evaluator.once("exit", () => resume(Effect.void));
81
+ evaluator.kill("SIGKILL");
82
+ }));
83
+ return yield* Effect.gen(function* () {
84
+ return yield* run(yield* RpcClient.make(requests), requestContext);
85
+ }).pipe(Effect.provide(RpcClient.layerProtocolWorker({ size: 1 }).pipe(Layer.provide(NodeWorker.layer(() => child)))));
86
+ })).pipe(Effect.catchTags({
87
+ WorkerError: (error) => Effect.fail(new EvaluationError({ diagnostic: error.message })),
88
+ RpcClientError: (error) => Effect.fail(new EvaluationError({ diagnostic: error.message }))
89
+ }));
90
+ });
91
+ const loadPreviousFunctionPaths = Effect.gen(function* () {
92
+ const fs = yield* FileSystem.FileSystem;
93
+ const path = yield* Path.Path;
94
+ const confectDirectory = yield* ConfectDirectory.get;
95
+ if (!(yield* fs.exists(path.join(confectDirectory, "_generated", "spec.ts")))) return FunctionPaths.make(HashSet.empty());
96
+ return yield* withWorker((client, requestContext) => client.Previous(requestContext));
97
+ });
98
+ const generateSnapshot = withWorker((client, requestContext) => client.Generate(requestContext));
99
+ generateSnapshot.pipe(Effect.map(functionPaths));
100
+ const updateDeclarations = (snapshot, declarations, paths) => withWorker((client, requestContext) => client.Update({
101
+ ...requestContext,
102
+ snapshot,
103
+ declarations,
104
+ paths
105
+ }));
106
+ const validate = (paths) => withWorker((client, requestContext) => client.Validate({
107
+ ...requestContext,
108
+ paths
109
+ }));
110
+ const catchAndLog = (effect) => effect.pipe(Effect.asSome, Effect.catchTags({
111
+ EvaluationError: ({ diagnostic }) => Console.error(diagnostic).pipe(Effect.as(Option.none())),
112
+ ComponentNodeGroupError: (error) => logCodegenError(error).pipe(Effect.as(Option.none()))
113
+ }));
114
+ //#endregion
115
+ export { EvaluationError, RequestContext, catchAndLog, generateSnapshot, loadPreviousFunctionPaths, requests, updateDeclarations, validate };
116
+
117
+ //# sourceMappingURL=Evaluation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Evaluation.mjs","names":["GenerationSnapshot.GenerationSnapshot","EntryPoint.Declaration","GenerationSnapshot.functionPaths"],"sources":["../src/Evaluation.ts"],"sourcesContent":["import * as NodeWorker from \"@effect/platform-node/NodeWorker\";\nimport { fork } from \"node:child_process\";\nimport * as Console from \"effect/Console\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Layer from \"effect/Layer\";\nimport * as LogLevel from \"effect/LogLevel\";\nimport * as Option from \"effect/Option\";\nimport * as Path from \"effect/Path\";\nimport * as Schema from \"effect/Schema\";\nimport * as References from \"effect/References\";\nimport * as Rpc from \"effect/rpc/Rpc\";\nimport * as RpcClient from \"effect/rpc/RpcClient\";\nimport type { RpcClientError } from \"effect/rpc/RpcClientError\";\nimport * as RpcGroup from \"effect/rpc/RpcGroup\";\nimport type * as Array from \"effect/Array\";\nimport * as Match from \"effect/Match\";\nimport { ComponentNodeGroupError, logCodegenError } from \"./CodegenError\";\nimport * as EntryPoint from \"./EntryPoint\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport { FunctionPaths } from \"./FunctionPaths\";\nimport { ImplModulePath } from \"./ImplModulePath\";\nimport { ProjectRoot } from \"./ProjectRoot\";\n\nexport const RequestContext = Schema.Struct({\n projectRoot: Schema.String,\n confectDirectory: Schema.String,\n convexDirectory: Schema.String,\n target: Schema.Union([\n Schema.Struct({ kind: Schema.Literal(\"app\") }),\n Schema.Struct({\n kind: Schema.Literal(\"component\"),\n definition: Schema.String,\n }),\n ]),\n minimumLogLevel: Schema.Literals(LogLevel.values),\n});\nexport type RequestContext = typeof RequestContext.Type;\n\nexport class EvaluationError extends Schema.TaggedError<EvaluationError>()(\n \"EvaluationError\",\n { diagnostic: Schema.String },\n) {}\n\n// A rejected Node group stays typed so the caller can restore component output.\nconst Failure = Schema.Union([EvaluationError, ComponentNodeGroupError]);\n\nexport const requests = RpcGroup.make(\n Rpc.make(\"Previous\", {\n payload: RequestContext,\n success: FunctionPaths,\n error: Failure,\n }),\n Rpc.make(\"Generate\", {\n payload: RequestContext,\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n Rpc.make(\"Validate\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n paths: Schema.Array(ImplModulePath),\n }),\n success: Schema.Void,\n error: Failure,\n }),\n Rpc.make(\"Update\", {\n payload: Schema.Struct({\n ...RequestContext.fields,\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Schema.NonEmptyArray(EntryPoint.Declaration),\n paths: Schema.Array(ImplModulePath),\n }),\n success: GenerationSnapshot.GenerationSnapshot,\n error: Failure,\n }),\n);\n\nconst withWorker = Effect.fn(\"Evaluation.withWorker\")(function* <A>(\n run: (\n client: RpcClient.RpcClient<RpcGroup.Rpcs<typeof requests>, RpcClientError>,\n requestContext: RequestContext,\n ) => Effect.Effect<\n A,\n EvaluationError | ComponentNodeGroupError | RpcClientError\n >,\n) {\n const requestContext = {\n projectRoot: yield* ProjectRoot.get,\n confectDirectory: yield* ConfectDirectory.get,\n convexDirectory: yield* ConvexDirectory.get,\n target: Match.value(yield* ConvexDirectory.target).pipe(\n Match.when({ kind: \"app\" }, () => ({ kind: \"app\" as const })),\n Match.when({ kind: \"component\" }, ({ scope }) => ({\n kind: \"component\" as const,\n definition: scope.slice(\"component:\".length),\n })),\n Match.exhaustive,\n ),\n minimumLogLevel: yield* References.MinimumLogLevel,\n };\n return yield* Effect.scoped(\n Effect.gen(function* () {\n const child = yield* Effect.acquireRelease(\n Effect.sync(() =>\n fork(new URL(\"../dist/EvaluationWorker.mjs\", import.meta.url), {\n serialization: \"advanced\",\n }),\n ),\n (evaluator) =>\n Effect.callback<void>((resume) => {\n if (evaluator.exitCode !== null || evaluator.signalCode !== null) {\n resume(Effect.void);\n return;\n }\n evaluator.once(\"exit\", () => resume(Effect.void));\n evaluator.kill(\"SIGKILL\");\n }),\n );\n return yield* Effect.gen(function* () {\n const client = yield* RpcClient.make(requests);\n return yield* run(client, requestContext);\n }).pipe(\n Effect.provide(\n RpcClient.layerProtocolWorker({ size: 1 }).pipe(\n Layer.provide(NodeWorker.layer(() => child)),\n ),\n ),\n );\n }),\n ).pipe(\n Effect.catchTags({\n WorkerError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n RpcClientError: (error) =>\n Effect.fail(new EvaluationError({ diagnostic: error.message })),\n }),\n );\n});\n\nexport const loadPreviousFunctionPaths = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n if (\n !(yield* fs.exists(path.join(confectDirectory, \"_generated\", \"spec.ts\")))\n ) {\n return FunctionPaths.make(HashSet.empty());\n }\n return yield* withWorker((client, requestContext) =>\n client.Previous(requestContext),\n );\n});\n\nexport const generateSnapshot = withWorker((client, requestContext) =>\n client.Generate(requestContext),\n);\n\nexport const generate = generateSnapshot.pipe(\n Effect.map(GenerationSnapshot.functionPaths),\n);\n\nexport const updateDeclarations = (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n declarations: Array.NonEmptyReadonlyArray<EntryPoint.Declaration>,\n paths: ReadonlyArray<ImplModulePath>,\n) =>\n withWorker((client, requestContext) =>\n client.Update({\n ...requestContext,\n snapshot,\n declarations,\n paths,\n }),\n );\n\nexport const validate = (paths: ReadonlyArray<ImplModulePath>) =>\n withWorker((client, requestContext) =>\n client.Validate({ ...requestContext, paths }),\n );\n\nexport const catchAndLog = <A, R>(\n effect: Effect.Effect<A, EvaluationError | ComponentNodeGroupError, R>,\n): Effect.Effect<Option.Option<A>, never, R> =>\n effect.pipe(\n Effect.asSome,\n Effect.catchTags({\n EvaluationError: ({ diagnostic }) =>\n Console.error(diagnostic).pipe(Effect.as(Option.none<A>())),\n ComponentNodeGroupError: (error) =>\n logCodegenError(error).pipe(Effect.as(Option.none<A>())),\n }),\n );\n"],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { ProjectRoot } from "./ProjectRoot.mjs";
2
+ import { ComponentNodeGroupError, isCodegenError, renderCodegenError } from "./CodegenError.mjs";
3
+ import { ConvexDirectory } from "./ConvexDirectory.mjs";
4
+ import { ConfectDirectory } from "./ConfectDirectory.mjs";
5
+ import { validateImplFiles } from "./LeafModule.mjs";
6
+ import { generateWithSnapshot, loadPreviousFunctionPaths, updateDeclarations } from "./confect/codegen.mjs";
7
+ import { EvaluationError, requests } from "./Evaluation.mjs";
8
+ import * as NodeServices from "@effect/platform-node/NodeServices";
9
+ import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
10
+ import * as Effect from "effect/Effect";
11
+ import * as Match from "effect/Match";
12
+ import * as Option from "effect/Option";
13
+ import * as Cause from "effect/Cause";
14
+ import * as Schema from "effect/Schema";
15
+ import * as esbuild from "esbuild";
16
+ import * as Layer from "effect/Layer";
17
+ import * as IdScope from "@confect/core/IdScope";
18
+ import * as References from "effect/References";
19
+ import * as NodeWorkerRunner from "@effect/platform-node/NodeWorkerRunner";
20
+ import * as RpcServer from "effect/rpc/RpcServer";
21
+ //#region src/EvaluationWorker.ts
22
+ const evaluate = (requestContext, effect) => effect.pipe(Effect.provideService(References.MinimumLogLevel, requestContext.minimumLogLevel), Effect.provideService(ProjectRoot, { get: Effect.succeed(requestContext.projectRoot) }), Effect.provideService(ConfectDirectory, { get: Effect.succeed(requestContext.confectDirectory) }), Effect.provideService(ConvexDirectory, {
23
+ get: Effect.succeed(requestContext.convexDirectory),
24
+ target: Match.value(requestContext.target).pipe(Match.when({ kind: "app" }, () => ({
25
+ kind: "app",
26
+ scope: IdScope.app
27
+ })), Match.when({ kind: "component" }, ({ definition }) => ({
28
+ kind: "component",
29
+ scope: IdScope.component(definition)
30
+ })), Match.exhaustive)
31
+ }), Effect.catchCause((cause) => {
32
+ const failure = Cause.findErrorOption(cause);
33
+ if (Option.isSome(failure) && Schema.is(ComponentNodeGroupError)(failure.value)) return Effect.fail(failure.value);
34
+ return Effect.fail(new EvaluationError({ diagnostic: Option.isSome(failure) && isCodegenError(failure.value) ? renderCodegenError(failure.value) : Cause.pretty(cause) }));
35
+ }));
36
+ const handlers = requests.toLayer({
37
+ Previous: (requestContext) => evaluate(requestContext, loadPreviousFunctionPaths),
38
+ Generate: (requestContext) => evaluate(requestContext, generateWithSnapshot.pipe(Effect.map(({ snapshot }) => snapshot))),
39
+ Validate: (request) => evaluate(request, validateImplFiles(request.paths)),
40
+ Update: (request) => evaluate(request, updateDeclarations(request.snapshot, request.declarations, request.paths))
41
+ });
42
+ RpcServer.layer(requests).pipe(Layer.provide(handlers), Layer.provide(NodeServices.layer), Layer.provide(RpcServer.layerProtocolWorkerRunner.pipe(Layer.provide(NodeWorkerRunner.layer))), Layer.launch, Effect.ensuring(Effect.promise(() => esbuild.stop())), NodeRuntime.runMain);
43
+ //#endregion
44
+ export {};
45
+
46
+ //# sourceMappingURL=EvaluationWorker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvaluationWorker.mjs","names":["CodegenError.ComponentNodeGroupError","CodegenError.isCodegenError","CodegenError.renderCodegenError"],"sources":["../src/EvaluationWorker.ts"],"sourcesContent":["import * as NodeRuntime from \"@effect/platform-node/NodeRuntime\";\nimport * as NodeServices from \"@effect/platform-node/NodeServices\";\nimport * as NodeWorkerRunner from \"@effect/platform-node/NodeWorkerRunner\";\nimport * as IdScope from \"@confect/core/IdScope\";\nimport * as Cause from \"effect/Cause\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as References from \"effect/References\";\nimport * as Schema from \"effect/Schema\";\nimport * as RpcServer from \"effect/rpc/RpcServer\";\nimport * as esbuild from \"esbuild\";\nimport * as CodegenError from \"./CodegenError\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport type { RequestContext } from \"./Evaluation\";\nimport { EvaluationError, requests } from \"./Evaluation\";\nimport { validateImplFiles } from \"./LeafModule\";\nimport { ProjectRoot } from \"./ProjectRoot\";\nimport {\n generateWithSnapshot,\n loadPreviousFunctionPaths,\n updateDeclarations,\n} from \"./confect/codegen\";\n\nconst evaluate = <A, E, R>(\n requestContext: RequestContext,\n effect: Effect.Effect<A, E, R>,\n) =>\n effect.pipe(\n Effect.provideService(\n References.MinimumLogLevel,\n requestContext.minimumLogLevel,\n ),\n Effect.provideService(ProjectRoot, {\n get: Effect.succeed(requestContext.projectRoot),\n }),\n Effect.provideService(ConfectDirectory, {\n get: Effect.succeed(requestContext.confectDirectory),\n }),\n Effect.provideService(ConvexDirectory, {\n get: Effect.succeed(requestContext.convexDirectory),\n target: Match.value(requestContext.target).pipe(\n Match.when({ kind: \"app\" }, () => ({\n kind: \"app\" as const,\n scope: IdScope.app,\n })),\n Match.when({ kind: \"component\" }, ({ definition }) => ({\n kind: \"component\" as const,\n scope: IdScope.component(definition),\n })),\n Match.exhaustive,\n ),\n }),\n Effect.catchCause(\n (\n cause,\n ): Effect.Effect<\n never,\n EvaluationError | CodegenError.ComponentNodeGroupError\n > => {\n const failure = Cause.findErrorOption(cause);\n if (\n Option.isSome(failure) &&\n Schema.is(CodegenError.ComponentNodeGroupError)(failure.value)\n )\n return Effect.fail(failure.value);\n return Effect.fail(\n new EvaluationError({\n diagnostic:\n Option.isSome(failure) &&\n CodegenError.isCodegenError(failure.value)\n ? CodegenError.renderCodegenError(failure.value)\n : Cause.pretty(cause),\n }),\n );\n },\n ),\n );\n\nconst handlers = requests.toLayer({\n Previous: (requestContext) =>\n evaluate(requestContext, loadPreviousFunctionPaths),\n Generate: (requestContext) =>\n evaluate(\n requestContext,\n generateWithSnapshot.pipe(Effect.map(({ snapshot }) => snapshot)),\n ),\n Validate: (request) => evaluate(request, validateImplFiles(request.paths)),\n Update: (request) =>\n evaluate(\n request,\n updateDeclarations(request.snapshot, request.declarations, request.paths),\n ),\n});\n\nRpcServer.layer(requests).pipe(\n Layer.provide(handlers),\n Layer.provide(NodeServices.layer),\n Layer.provide(\n RpcServer.layerProtocolWorkerRunner.pipe(\n Layer.provide(NodeWorkerRunner.layer),\n ),\n ),\n Layer.launch,\n Effect.ensuring(Effect.promise(() => esbuild.stop())),\n NodeRuntime.runMain,\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,YACJ,gBACA,WAEA,OAAO,KACL,OAAO,eACL,WAAW,iBACX,eAAe,eACjB,GACA,OAAO,eAAe,aAAa,EACjC,KAAK,OAAO,QAAQ,eAAe,WAAW,EAChD,CAAC,GACD,OAAO,eAAe,kBAAkB,EACtC,KAAK,OAAO,QAAQ,eAAe,gBAAgB,EACrD,CAAC,GACD,OAAO,eAAe,iBAAiB;CACrC,KAAK,OAAO,QAAQ,eAAe,eAAe;CAClD,QAAQ,MAAM,MAAM,eAAe,MAAM,CAAC,CAAC,KACzC,MAAM,KAAK,EAAE,MAAM,MAAM,UAAU;EACjC,MAAM;EACN,OAAO,QAAQ;CACjB,EAAE,GACF,MAAM,KAAK,EAAE,MAAM,YAAY,IAAI,EAAE,kBAAkB;EACrD,MAAM;EACN,OAAO,QAAQ,UAAU,UAAU;CACrC,EAAE,GACF,MAAM,UACR;AACF,CAAC,GACD,OAAO,YAEH,UAIG;CACH,MAAM,UAAU,MAAM,gBAAgB,KAAK;CAC3C,IACE,OAAO,OAAO,OAAO,KACrB,OAAO,GAAGA,uBAAoC,CAAC,CAAC,QAAQ,KAAK,GAE7D,OAAO,OAAO,KAAK,QAAQ,KAAK;CAClC,OAAO,OAAO,KACZ,IAAI,gBAAgB,EAClB,YACE,OAAO,OAAO,OAAO,KACrBC,eAA4B,QAAQ,KAAK,IACrCC,mBAAgC,QAAQ,KAAK,IAC7C,MAAM,OAAO,KAAK,EAC1B,CAAC,CACH;AACF,CACF,CACF;AAEF,MAAM,WAAW,SAAS,QAAQ;CAChC,WAAW,mBACT,SAAS,gBAAgB,yBAAyB;CACpD,WAAW,mBACT,SACE,gBACA,qBAAqB,KAAK,OAAO,KAAK,EAAE,eAAe,QAAQ,CAAC,CAClE;CACF,WAAW,YAAY,SAAS,SAAS,kBAAkB,QAAQ,KAAK,CAAC;CACzE,SAAS,YACP,SACE,SACA,mBAAmB,QAAQ,UAAU,QAAQ,cAAc,QAAQ,KAAK,CAC1E;AACJ,CAAC;AAED,UAAU,MAAM,QAAQ,CAAC,CAAC,KACxB,MAAM,QAAQ,QAAQ,GACtB,MAAM,QAAQ,aAAa,KAAK,GAChC,MAAM,QACJ,UAAU,0BAA0B,KAClC,MAAM,QAAQ,iBAAiB,KAAK,CACtC,CACF,GACA,MAAM,QACN,OAAO,SAAS,OAAO,cAAc,QAAQ,KAAK,CAAC,CAAC,GACpD,YAAY,OACd"}
@@ -0,0 +1,137 @@
1
+ import { fromGroupModulePath, modulePath } from "./GroupPath.mjs";
2
+ import { logFileAdded, logFileModified, logFileRemoved } from "./log.mjs";
3
+ import { ConvexDirectory } from "./ConvexDirectory.mjs";
4
+ import { ConfectDirectory } from "./ConfectDirectory.mjs";
5
+ import { CodeBlockWriter } from "./CodeBlockWriter.mjs";
6
+ import { removePathIfExists, toModuleImportPath } from "./utils.mjs";
7
+ import { GroupPaths } from "./GroupPaths.mjs";
8
+ import { functionPaths, plan } from "./GenerationSnapshot.mjs";
9
+ import * as Effect from "effect/Effect";
10
+ import * as FileSystem from "effect/FileSystem";
11
+ import * as Path from "effect/Path";
12
+ import * as Array from "effect/Array";
13
+ import { pipe } from "effect/Function";
14
+ import * as HashSet from "effect/HashSet";
15
+ import * as Match from "effect/Match";
16
+ //#region src/FunctionModule.ts
17
+ const render = ({ functionNames, registeredFunctionsImportPath, useNode = false }) => renderEffect({
18
+ functionNames,
19
+ registeredFunctionsImportPath,
20
+ useNode
21
+ });
22
+ const renderEffect = Effect.fnUntraced(function* ({ functionNames, registeredFunctionsImportPath, useNode = false }) {
23
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
24
+ if (useNode) {
25
+ yield* cbw.writeLine(`"use node";`);
26
+ yield* cbw.blankLine();
27
+ }
28
+ yield* cbw.writeLine(`import registeredFunctions from "${registeredFunctionsImportPath}";`);
29
+ yield* cbw.newLine();
30
+ yield* Effect.forEach(functionNames, (name) => cbw.writeLine(`export const ${name} = registeredFunctions.${name};`));
31
+ return yield* cbw.toString();
32
+ });
33
+ const generateGroupModule = ({ groupPath, functionNames, registeredFunctionsImportPath, useNode = false }) => generateGroupModuleEffect({
34
+ groupPath,
35
+ functionNames,
36
+ registeredFunctionsImportPath,
37
+ useNode
38
+ });
39
+ const generateGroupModuleEffect = Effect.fnUntraced(function* ({ groupPath, functionNames, registeredFunctionsImportPath, useNode = false }) {
40
+ const fs = yield* FileSystem.FileSystem;
41
+ const path = yield* Path.Path;
42
+ const convexDirectory = yield* ConvexDirectory.get;
43
+ const relativeModulePath = yield* modulePath(groupPath);
44
+ const modulePath$3 = path.join(convexDirectory, relativeModulePath);
45
+ const directoryPath = path.dirname(modulePath$3);
46
+ if (!(yield* fs.exists(directoryPath))) yield* fs.makeDirectory(directoryPath, { recursive: true });
47
+ const functionsContentsString = yield* render({
48
+ functionNames,
49
+ registeredFunctionsImportPath,
50
+ useNode
51
+ });
52
+ if (!(yield* fs.exists(modulePath$3))) {
53
+ yield* fs.writeFileString(modulePath$3, functionsContentsString);
54
+ return "Added";
55
+ }
56
+ if ((yield* fs.readFileString(modulePath$3)) !== functionsContentsString) {
57
+ yield* fs.writeFileString(modulePath$3, functionsContentsString);
58
+ return "Modified";
59
+ }
60
+ return "Unchanged";
61
+ });
62
+ /**
63
+ * Compute the module import specifier (relative to `modulePath`) for a group's
64
+ * registry file under `confect/_generated/registeredFunctions/`. The registry
65
+ * path mirrors the group's path one-to-one (see
66
+ * `registeredFunctionsRelativePath` in `LeafModule.ts`) for both Convex and
67
+ * Node groups.
68
+ */
69
+ const registeredFunctionsImportPathForGroup = Effect.fnUntraced(function* (groupPath, modulePath) {
70
+ const path = yield* Path.Path;
71
+ const confectDirectory = yield* ConfectDirectory.get;
72
+ const registeredFunctionsPath = path.join(confectDirectory, "_generated", "registeredFunctions", ...groupPath.pathSegments) + ".ts";
73
+ return yield* toModuleImportPath(path.relative(path.dirname(modulePath), registeredFunctionsPath));
74
+ });
75
+ const logGroupPaths = Effect.fnUntraced(function* (groupPaths, logFn) {
76
+ const path = yield* Path.Path;
77
+ const convexDirectory = yield* ConvexDirectory.get;
78
+ yield* Effect.forEach(groupPaths, Effect.fnUntraced(function* (gp) {
79
+ const relativeModulePath = yield* modulePath(gp);
80
+ yield* logFn(path.join(convexDirectory, relativeModulePath));
81
+ }));
82
+ });
83
+ const generateFunctions = Effect.fnUntraced(function* (snapshot) {
84
+ const groupPathsFromFs = yield* getGroupPathsFromFs;
85
+ yield* applyFunctionPlan(plan(snapshot, groupPathsFromFs));
86
+ return functionPaths(snapshot);
87
+ });
88
+ const applyFunctionPlan = Effect.fnUntraced(function* (plan) {
89
+ const removed = GroupPaths.make(HashSet.fromIterable(plan.removed));
90
+ yield* removeGroups(removed);
91
+ yield* logGroupPaths(removed, logFileRemoved);
92
+ yield* writeGroups(plan.changed);
93
+ });
94
+ const getGroupPathsFromFs = Effect.gen(function* () {
95
+ const fs = yield* FileSystem.FileSystem;
96
+ const path = yield* Path.Path;
97
+ const convexDirectory = yield* ConvexDirectory.get;
98
+ const RESERVED_CONVEX_TS_FILE_NAMES = /* @__PURE__ */ new Set([
99
+ "schema.ts",
100
+ "http.ts",
101
+ "crons.ts",
102
+ "auth.config.ts",
103
+ "convex.config.ts"
104
+ ]);
105
+ const allConvexPaths = yield* fs.readDirectory(convexDirectory, { recursive: true });
106
+ const groupPathArray = yield* pipe(allConvexPaths, Array.filter((convexPath) => path.extname(convexPath) === ".ts" && !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath)) && path.basename(path.dirname(convexPath)) !== "_generated"), Effect.forEach((groupModulePath) => fromGroupModulePath(groupModulePath)));
107
+ return GroupPaths.make(HashSet.fromIterable(groupPathArray));
108
+ });
109
+ const removeGroups = Effect.fnUntraced(function* (groupPaths) {
110
+ const path = yield* Path.Path;
111
+ const convexDirectory = yield* ConvexDirectory.get;
112
+ yield* Effect.all(HashSet.map(groupPaths, (groupPath) => Effect.gen(function* () {
113
+ const relativeModulePath = yield* modulePath(groupPath);
114
+ const modulePath$2 = path.join(convexDirectory, relativeModulePath);
115
+ yield* Effect.logDebug(`Removing group '${relativeModulePath}'...`);
116
+ yield* removePathIfExists(modulePath$2);
117
+ yield* Effect.logDebug(`Group '${relativeModulePath}' removed`);
118
+ })), { concurrency: "unbounded" });
119
+ });
120
+ const writeGroups = (groups) => Effect.forEach(groups, Effect.fnUntraced(function* (group) {
121
+ const path = yield* Path.Path;
122
+ const convexDirectory = yield* ConvexDirectory.get;
123
+ const relativeModulePath = yield* modulePath(group.path);
124
+ const modulePath$1 = path.join(convexDirectory, relativeModulePath);
125
+ const registeredFunctionsImportPath = yield* registeredFunctionsImportPathForGroup(group.path, modulePath$1);
126
+ const change = yield* generateGroupModule({
127
+ groupPath: group.path,
128
+ functionNames: group.functionNames,
129
+ registeredFunctionsImportPath,
130
+ useNode: group.runtime === "Node"
131
+ });
132
+ yield* Match.value(change).pipe(Match.when("Added", () => logFileAdded(modulePath$1)), Match.when("Modified", () => logFileModified(modulePath$1)), Match.when("Unchanged", () => Effect.void), Match.exhaustive);
133
+ }));
134
+ //#endregion
135
+ export { applyFunctionPlan, generateFunctions, generateGroupModule, registeredFunctionsImportPathForGroup, removeGroups, render, writeGroups };
136
+
137
+ //# sourceMappingURL=FunctionModule.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FunctionModule.mjs","names":["GroupPath.modulePath","modulePath","GenerationSnapshot.plan","GenerationSnapshot.functionPaths","GroupPath.fromGroupModulePath"],"sources":["../src/FunctionModule.ts"],"sourcesContent":["import * as FileSystem from \"effect/FileSystem\";\nimport * as Path from \"effect/Path\";\nimport { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Match from \"effect/Match\";\nimport * as GenerationSnapshot from \"./GenerationSnapshot\";\nimport * as GroupPath from \"./GroupPath\";\nimport * as GroupPaths from \"./GroupPaths\";\nimport { CodeBlockWriter } from \"./CodeBlockWriter\";\nimport { logFileAdded, logFileModified, logFileRemoved } from \"./log\";\nimport { ConfectDirectory } from \"./ConfectDirectory\";\nimport { ConvexDirectory } from \"./ConvexDirectory\";\nimport { removePathIfExists, toModuleImportPath } from \"./utils\";\n\nexport const render = ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof renderEffect>[0]) =>\n renderEffect({ functionNames, registeredFunctionsImportPath, useNode });\n\nconst renderEffect = Effect.fnUntraced(function* ({\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\n const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });\n\n if (useNode) {\n yield* cbw.writeLine(`\"use node\";`);\n yield* cbw.blankLine();\n }\n\n yield* cbw.writeLine(\n `import registeredFunctions from \"${registeredFunctionsImportPath}\";`,\n );\n yield* cbw.newLine();\n yield* Effect.forEach(functionNames, (name) =>\n cbw.writeLine(`export const ${name} = registeredFunctions.${name};`),\n );\n\n return yield* cbw.toString();\n});\n\nexport const generateGroupModule = ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: Parameters<typeof generateGroupModuleEffect>[0]) =>\n generateGroupModuleEffect({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\nconst generateGroupModuleEffect = Effect.fnUntraced(function* ({\n groupPath,\n functionNames,\n registeredFunctionsImportPath,\n useNode = false,\n}: {\n groupPath: GroupPath.GroupPath;\n functionNames: ReadonlyArray<string>;\n registeredFunctionsImportPath: string;\n useNode?: boolean;\n}) {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n const directoryPath = path.dirname(modulePath);\n if (!(yield* fs.exists(directoryPath))) {\n yield* fs.makeDirectory(directoryPath, { recursive: true });\n }\n\n const functionsContentsString = yield* render({\n functionNames,\n registeredFunctionsImportPath,\n useNode,\n });\n\n if (!(yield* fs.exists(modulePath))) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Added\" as const;\n }\n const existing = yield* fs.readFileString(modulePath);\n if (existing !== functionsContentsString) {\n yield* fs.writeFileString(modulePath, functionsContentsString);\n return \"Modified\" as const;\n }\n return \"Unchanged\" as const;\n});\n\n/**\n * Compute the module import specifier (relative to `modulePath`) for a group's\n * registry file under `confect/_generated/registeredFunctions/`. The registry\n * path mirrors the group's path one-to-one (see\n * `registeredFunctionsRelativePath` in `LeafModule.ts`) for both Convex and\n * Node groups.\n */\nexport const registeredFunctionsImportPathForGroup = Effect.fnUntraced(\n function* (groupPath: GroupPath.GroupPath, modulePath: string) {\n const path = yield* Path.Path;\n const confectDirectory = yield* ConfectDirectory.get;\n\n const registeredFunctionsPath =\n path.join(\n confectDirectory,\n \"_generated\",\n \"registeredFunctions\",\n ...groupPath.pathSegments,\n ) + \".ts\";\n\n return yield* toModuleImportPath(\n path.relative(path.dirname(modulePath), registeredFunctionsPath),\n );\n },\n);\n\nconst logGroupPaths = Effect.fnUntraced(function* <R>(\n groupPaths: GroupPaths.GroupPaths,\n logFn: (fullPath: string) => Effect.Effect<void, never, R>,\n): Effect.fn.Return<void, never, R | Path.Path | ConvexDirectory> {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.forEach(\n groupPaths,\n Effect.fnUntraced(function* (gp: GroupPath.GroupPath) {\n const relativeModulePath = yield* GroupPath.modulePath(gp);\n yield* logFn(path.join(convexDirectory, relativeModulePath));\n }),\n );\n});\n\nexport const generateFunctions = Effect.fnUntraced(function* (\n snapshot: GenerationSnapshot.GenerationSnapshot,\n) {\n const groupPathsFromFs = yield* getGroupPathsFromFs;\n yield* applyFunctionPlan(GenerationSnapshot.plan(snapshot, groupPathsFromFs));\n return GenerationSnapshot.functionPaths(snapshot);\n});\n\nexport const applyFunctionPlan = Effect.fnUntraced(function* (\n plan: GenerationSnapshot.ModulePlan,\n) {\n const removed = GroupPaths.GroupPaths.make(\n HashSet.fromIterable(plan.removed),\n );\n yield* removeGroups(removed);\n yield* logGroupPaths(removed, logFileRemoved);\n yield* writeGroups(plan.changed);\n});\n\nconst getGroupPathsFromFs = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n const RESERVED_CONVEX_TS_FILE_NAMES = new Set([\n \"schema.ts\",\n \"http.ts\",\n \"crons.ts\",\n \"auth.config.ts\",\n \"convex.config.ts\",\n ]);\n\n const allConvexPaths = yield* fs.readDirectory(convexDirectory, {\n recursive: true,\n });\n const groupPathArray = yield* pipe(\n allConvexPaths,\n Array.filter(\n (convexPath) =>\n path.extname(convexPath) === \".ts\" &&\n !RESERVED_CONVEX_TS_FILE_NAMES.has(path.basename(convexPath)) &&\n path.basename(path.dirname(convexPath)) !== \"_generated\",\n ),\n Effect.forEach((groupModulePath) =>\n GroupPath.fromGroupModulePath(groupModulePath),\n ),\n );\n return GroupPaths.GroupPaths.make(HashSet.fromIterable(groupPathArray));\n});\n\nexport const removeGroups = Effect.fnUntraced(function* (\n groupPaths: GroupPaths.GroupPaths,\n) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n\n yield* Effect.all(\n HashSet.map(groupPaths, (groupPath) =>\n Effect.gen(function* () {\n const relativeModulePath = yield* GroupPath.modulePath(groupPath);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n\n yield* Effect.logDebug(`Removing group '${relativeModulePath}'...`);\n\n yield* removePathIfExists(modulePath);\n yield* Effect.logDebug(`Group '${relativeModulePath}' removed`);\n }),\n ),\n { concurrency: \"unbounded\" },\n );\n});\n\nexport const writeGroups = (\n groups: ReadonlyArray<GenerationSnapshot.GroupSummary>,\n) =>\n Effect.forEach(\n groups,\n Effect.fnUntraced(function* (group: GenerationSnapshot.GroupSummary) {\n const path = yield* Path.Path;\n const convexDirectory = yield* ConvexDirectory.get;\n const relativeModulePath = yield* GroupPath.modulePath(group.path);\n const modulePath = path.join(convexDirectory, relativeModulePath);\n const registeredFunctionsImportPath =\n yield* registeredFunctionsImportPathForGroup(group.path, modulePath);\n const change = yield* generateGroupModule({\n groupPath: group.path,\n functionNames: group.functionNames,\n registeredFunctionsImportPath,\n useNode: group.runtime === \"Node\",\n });\n yield* Match.value(change).pipe(\n Match.when(\"Added\", () => logFileAdded(modulePath)),\n Match.when(\"Modified\", () => logFileModified(modulePath)),\n Match.when(\"Unchanged\", () => Effect.void),\n Match.exhaustive,\n );\n }),\n );\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { GroupPath } from "./GroupPath.mjs";
2
+ import * as Schema from "effect/Schema";
3
+ //#region src/FunctionPath.ts
4
+ /**
5
+ * The path to a function in the Confect API.
6
+ */
7
+ var FunctionPath = class extends Schema.Class("FunctionPath")({
8
+ groupPath: GroupPath,
9
+ name: Schema.NonEmptyString
10
+ }) {};
11
+ /**
12
+ * Get the group path from a function path.
13
+ */
14
+ const groupPath = (functionPath) => functionPath.groupPath;
15
+ //#endregion
16
+ export { FunctionPath, groupPath };
17
+
18
+ //# sourceMappingURL=FunctionPath.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FunctionPath.mjs","names":["GroupPath.GroupPath"],"sources":["../src/FunctionPath.ts"],"sourcesContent":["import * as Schema from \"effect/Schema\";\nimport * as GroupPath from \"./GroupPath\";\n\n/**\n * The path to a function in the Confect API.\n */\nexport class FunctionPath extends Schema.Class<FunctionPath>(\"FunctionPath\")({\n groupPath: GroupPath.GroupPath,\n name: Schema.NonEmptyString,\n}) {}\n\n/**\n * Get the group path from a function path.\n */\nexport const groupPath = (functionPath: FunctionPath): GroupPath.GroupPath =>\n functionPath.groupPath;\n\n/**\n * Get the function name from a function path.\n */\nexport const name = (functionPath: FunctionPath): string => functionPath.name;\n\n/**\n * Get the function path as a string.\n */\nexport const toString = (functionPath: FunctionPath): string =>\n `${GroupPath.toString(functionPath.groupPath)}.${functionPath.name}`;\n"],"mappings":";;;;;;AAMA,IAAa,eAAb,cAAkC,OAAO,MAAoB,cAAc,CAAC,CAAC;CAC3E,WAAWA;CACX,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;;;;AAKJ,MAAa,aAAa,iBACxB,aAAa"}
@@ -0,0 +1,45 @@
1
+ import { append, make as make$1 } from "./GroupPath.mjs";
2
+ import { FunctionPath, groupPath } from "./FunctionPath.mjs";
3
+ import { GroupPaths } from "./GroupPaths.mjs";
4
+ import { Spec } from "@confect/core";
5
+ import { pipe } from "effect/Function";
6
+ import * as HashSet from "effect/HashSet";
7
+ import * as Option from "effect/Option";
8
+ import * as Record from "effect/Record";
9
+ import * as Schema from "effect/Schema";
10
+ //#region src/FunctionPaths.ts
11
+ const FunctionPaths = Schema.HashSet(FunctionPath).pipe(Schema.brand("@confect/cli/FunctionPaths"));
12
+ const make = (spec) => makeHelper(Spec.groups(spec), Option.none(), FunctionPaths.make(HashSet.empty()));
13
+ const makeHelper = (groups, currentGroupPath, apiPaths) => Record.reduce(groups, apiPaths, (acc, group, groupName) => {
14
+ const groupPath = Option.match(currentGroupPath, {
15
+ onNone: () => make$1([groupName]),
16
+ onSome: (path) => append(path, groupName)
17
+ });
18
+ const accWithFunctions = Record.reduce(group.functions, acc, (acc_, _fn, name) => FunctionPaths.make(HashSet.add(acc_, FunctionPath.make({
19
+ groupPath,
20
+ name
21
+ }))));
22
+ return makeHelper(group.groups, Option.some(groupPath), accWithFunctions);
23
+ });
24
+ const groupPaths = (functionPaths) => pipe(functionPaths, HashSet.map(groupPath), (paths) => GroupPaths.make(paths));
25
+ const diff = (previousFunctions, currentFunctions) => {
26
+ const currentGroups = groupPaths(currentFunctions);
27
+ const previousGroups = groupPaths(previousFunctions);
28
+ const groupsAdded = GroupPaths.make(HashSet.difference(currentGroups, previousGroups));
29
+ const groupsRemoved = GroupPaths.make(HashSet.difference(previousGroups, currentGroups));
30
+ const functionsAdded = FunctionPaths.make(HashSet.difference(currentFunctions, previousFunctions));
31
+ const existingGroupsToWhichFunctionsWereAdded = GroupPaths.make(HashSet.intersection(currentGroups, groupPaths(functionsAdded)));
32
+ const functionsRemoved = FunctionPaths.make(HashSet.difference(previousFunctions, currentFunctions));
33
+ const existingGroupsToWhichFunctionsWereRemoved = GroupPaths.make(HashSet.intersection(previousGroups, groupPaths(functionsRemoved)));
34
+ return {
35
+ functionsAdded,
36
+ functionsRemoved,
37
+ groupsRemoved,
38
+ groupsAdded,
39
+ groupsChanged: pipe(existingGroupsToWhichFunctionsWereAdded, HashSet.union(existingGroupsToWhichFunctionsWereRemoved), HashSet.difference(HashSet.union(groupsAdded, groupsRemoved)), (paths) => GroupPaths.make(paths))
40
+ };
41
+ };
42
+ //#endregion
43
+ export { FunctionPaths, diff, groupPaths, make };
44
+
45
+ //# sourceMappingURL=FunctionPaths.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FunctionPaths.mjs","names":["FunctionPath.FunctionPath","GroupPath.make","GroupPath.append","FunctionPath.groupPath"],"sources":["../src/FunctionPaths.ts"],"sourcesContent":["import { type GroupSpec, Spec } from \"@confect/core\";\nimport { pipe } from \"effect/Function\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Option from \"effect/Option\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as FunctionPath from \"./FunctionPath\";\nimport * as GroupPath from \"./GroupPath\";\nimport * as GroupPaths from \"./GroupPaths\";\n\nexport const FunctionPaths = Schema.HashSet(FunctionPath.FunctionPath).pipe(\n Schema.brand(\"@confect/cli/FunctionPaths\"),\n);\nexport type FunctionPaths = typeof FunctionPaths.Type;\n\nexport const make = (spec: Spec.AnyWithProps): FunctionPaths =>\n makeHelper(\n Spec.groups(spec),\n Option.none(),\n FunctionPaths.make(HashSet.empty()),\n );\n\nconst makeHelper = (\n groups: {\n [key: string]: GroupSpec.AnyWithProps;\n },\n currentGroupPath: Option.Option<GroupPath.GroupPath>,\n apiPaths: FunctionPaths,\n): FunctionPaths =>\n Record.reduce(groups, apiPaths, (acc, group, groupName) => {\n const groupPath = Option.match(currentGroupPath, {\n onNone: () => GroupPath.make([groupName]),\n onSome: (path) => GroupPath.append(path, groupName),\n });\n\n const accWithFunctions = Record.reduce(\n group.functions,\n acc,\n (acc_, _fn, name) =>\n FunctionPaths.make(\n HashSet.add(\n acc_,\n FunctionPath.FunctionPath.make({\n groupPath,\n name,\n }),\n ),\n ),\n );\n\n return makeHelper(group.groups, Option.some(groupPath), accWithFunctions);\n });\n\nexport const groupPaths = (\n functionPaths: FunctionPaths,\n): GroupPaths.GroupPaths =>\n pipe(functionPaths, HashSet.map(FunctionPath.groupPath), (paths) =>\n GroupPaths.GroupPaths.make(paths),\n );\n\nexport const diff = (\n previousFunctions: FunctionPaths,\n currentFunctions: FunctionPaths,\n): {\n functionsAdded: FunctionPaths;\n functionsRemoved: FunctionPaths;\n groupsRemoved: GroupPaths.GroupPaths;\n groupsAdded: GroupPaths.GroupPaths;\n groupsChanged: GroupPaths.GroupPaths;\n} => {\n const currentGroups = groupPaths(currentFunctions);\n const previousGroups = groupPaths(previousFunctions);\n\n const groupsAdded = GroupPaths.GroupPaths.make(\n HashSet.difference(currentGroups, previousGroups),\n );\n const groupsRemoved = GroupPaths.GroupPaths.make(\n HashSet.difference(previousGroups, currentGroups),\n );\n\n const functionsAdded = FunctionPaths.make(\n HashSet.difference(currentFunctions, previousFunctions),\n );\n const existingGroupsToWhichFunctionsWereAdded = GroupPaths.GroupPaths.make(\n HashSet.intersection(currentGroups, groupPaths(functionsAdded)),\n );\n\n const functionsRemoved = FunctionPaths.make(\n HashSet.difference(previousFunctions, currentFunctions),\n );\n const existingGroupsToWhichFunctionsWereRemoved = GroupPaths.GroupPaths.make(\n HashSet.intersection(previousGroups, groupPaths(functionsRemoved)),\n );\n\n const groupsChanged = pipe(\n existingGroupsToWhichFunctionsWereAdded,\n HashSet.union(existingGroupsToWhichFunctionsWereRemoved),\n HashSet.difference(HashSet.union(groupsAdded, groupsRemoved)),\n (paths) => GroupPaths.GroupPaths.make(paths),\n );\n\n return {\n functionsAdded,\n functionsRemoved,\n groupsRemoved,\n groupsAdded,\n groupsChanged,\n };\n};\n"],"mappings":";;;;;;;;;;AAUA,MAAa,gBAAgB,OAAO,QAAQA,YAAyB,CAAC,CAAC,KACrE,OAAO,MAAM,4BAA4B,CAC3C;AAGA,MAAa,QAAQ,SACnB,WACE,KAAK,OAAO,IAAI,GAChB,OAAO,KAAK,GACZ,cAAc,KAAK,QAAQ,MAAM,CAAC,CACpC;AAEF,MAAM,cACJ,QAGA,kBACA,aAEA,OAAO,OAAO,QAAQ,WAAW,KAAK,OAAO,cAAc;CACzD,MAAM,YAAY,OAAO,MAAM,kBAAkB;EAC/C,cAAcC,OAAe,CAAC,SAAS,CAAC;EACxC,SAAS,SAASC,OAAiB,MAAM,SAAS;CACpD,CAAC;CAED,MAAM,mBAAmB,OAAO,OAC9B,MAAM,WACN,MACC,MAAM,KAAK,SACV,cAAc,KACZ,QAAQ,IACN,MAAA,aAC0B,KAAK;EAC7B;EACA;CACF,CAAC,CACH,CACF,CACJ;CAEA,OAAO,WAAW,MAAM,QAAQ,OAAO,KAAK,SAAS,GAAG,gBAAgB;AAC1E,CAAC;AAEH,MAAa,cACX,kBAEA,KAAK,eAAe,QAAQ,IAAIC,SAAsB,IAAI,UAAA,WAClC,KAAK,KAAK,CAClC;AAEF,MAAa,QACX,mBACA,qBAOG;CACH,MAAM,gBAAgB,WAAW,gBAAgB;CACjD,MAAM,iBAAiB,WAAW,iBAAiB;CAEnD,MAAM,cAAA,WAAoC,KACxC,QAAQ,WAAW,eAAe,cAAc,CAClD;CACA,MAAM,gBAAA,WAAsC,KAC1C,QAAQ,WAAW,gBAAgB,aAAa,CAClD;CAEA,MAAM,iBAAiB,cAAc,KACnC,QAAQ,WAAW,kBAAkB,iBAAiB,CACxD;CACA,MAAM,0CAAA,WAAgE,KACpE,QAAQ,aAAa,eAAe,WAAW,cAAc,CAAC,CAChE;CAEA,MAAM,mBAAmB,cAAc,KACrC,QAAQ,WAAW,mBAAmB,gBAAgB,CACxD;CACA,MAAM,4CAAA,WAAkE,KACtE,QAAQ,aAAa,gBAAgB,WAAW,gBAAgB,CAAC,CACnE;CASA,OAAO;EACL;EACA;EACA;EACA;EACA,eAZoB,KACpB,yCACA,QAAQ,MAAM,yCAAyC,GACvD,QAAQ,WAAW,QAAQ,MAAM,aAAa,aAAa,CAAC,IAC3D,UAAA,WAAgC,KAAK,KAAK,CAQ/B;CACd;AACF"}
@@ -0,0 +1,183 @@
1
+ import { GroupPath, append, make } from "./GroupPath.mjs";
2
+ import { SnapshotError } from "./SnapshotError.mjs";
3
+ import { ParentChildNameCollisionError } from "./CodegenError.mjs";
4
+ import { FunctionPath } from "./FunctionPath.mjs";
5
+ import { FunctionPaths } from "./FunctionPaths.mjs";
6
+ import { SpecModulePath } from "./SpecModulePath.mjs";
7
+ import * as Effect from "effect/Effect";
8
+ import { Identifier } from "@confect/core";
9
+ import * as Array from "effect/Array";
10
+ import * as Result from "effect/Result";
11
+ import * as HashSet from "effect/HashSet";
12
+ import * as Match from "effect/Match";
13
+ import * as Option from "effect/Option";
14
+ import * as Record from "effect/Record";
15
+ import * as HashMap from "effect/HashMap";
16
+ import * as Schema from "effect/Schema";
17
+ import * as String from "effect/String";
18
+ import * as SchemaGetter from "effect/SchemaGetter";
19
+ import * as SchemaIssue from "effect/SchemaIssue";
20
+ //#region src/GenerationSnapshot.ts
21
+ const GroupSummary = Schema.Struct({
22
+ path: GroupPath,
23
+ runtime: Schema.Literals(["Convex", "Node"]),
24
+ functionNames: Schema.Array(Schema.NonEmptyString)
25
+ });
26
+ const GroupTree = Schema.Struct({
27
+ runtime: GroupSummary.fields.runtime,
28
+ functionNames: GroupSummary.fields.functionNames,
29
+ groups: Schema.Record(Schema.String, Schema.suspend(() => GroupTree))
30
+ });
31
+ var Snapshot = class Snapshot {
32
+ #leaves;
33
+ constructor(leaves) {
34
+ this.#leaves = leaves;
35
+ }
36
+ static parseLeaves(leaves) {
37
+ return Result.map(parseNoParentChildNameCollisions(leaves), (parsed) => new Snapshot(parsed));
38
+ }
39
+ get leaves() {
40
+ return this.#leaves;
41
+ }
42
+ };
43
+ const Entries = Schema.Array(Schema.Tuple([Schema.String, GroupTree]));
44
+ const CanonicalSpecPath = SpecModulePath.check(Schema.makeFilter((path) => !path.includes("\\")));
45
+ const rootPath = (path) => make(String.split(path.slice(0, -8), "/"));
46
+ const parseTree = (relativePath, path, tree) => Result.gen(function* () {
47
+ yield* Result.try({
48
+ try: () => {
49
+ for (const name of tree.functionNames) Identifier.validateConfectFunctionIdentifier(name);
50
+ },
51
+ catch: () => new SnapshotError({
52
+ reason: "NoncanonicalFunctionNames",
53
+ relativePath,
54
+ pathSegments: path.pathSegments
55
+ })
56
+ });
57
+ if (HashSet.size(HashSet.fromIterable(tree.functionNames)) !== tree.functionNames.length) return yield* Result.fail(new SnapshotError({
58
+ reason: "NoncanonicalFunctionNames",
59
+ relativePath,
60
+ pathSegments: path.pathSegments
61
+ }));
62
+ for (const [name, child] of Object.entries(tree.groups)) {
63
+ yield* Result.try({
64
+ try: () => Identifier.validateConfectFunctionIdentifier(name),
65
+ catch: () => new SnapshotError({
66
+ reason: "NoncanonicalPath",
67
+ relativePath,
68
+ pathSegments: [...path.pathSegments, name]
69
+ })
70
+ });
71
+ yield* parseTree(relativePath, append(path, name), child);
72
+ }
73
+ return tree;
74
+ });
75
+ const fromEntries = (entries) => Result.gen(function* () {
76
+ let leaves = HashMap.empty();
77
+ for (const [key, tree] of entries) {
78
+ const relativePath = yield* Schema.decodeResult(CanonicalSpecPath)(key).pipe(Result.mapError((cause) => new SnapshotError({
79
+ reason: "NoncanonicalPath",
80
+ relativePath: key,
81
+ pathSegments: [],
82
+ cause
83
+ })));
84
+ const path = rootPath(relativePath);
85
+ yield* Result.try({
86
+ try: () => {
87
+ for (const segment of path.pathSegments) Identifier.validateConfectFunctionIdentifier(segment);
88
+ },
89
+ catch: () => new SnapshotError({
90
+ reason: "NoncanonicalPath",
91
+ relativePath,
92
+ pathSegments: path.pathSegments
93
+ })
94
+ });
95
+ if (HashMap.has(leaves, relativePath)) return yield* Result.fail(new SnapshotError({
96
+ reason: "DuplicateLeaf",
97
+ relativePath,
98
+ pathSegments: path.pathSegments
99
+ }));
100
+ const parsed = yield* parseTree(relativePath, path, tree);
101
+ leaves = HashMap.set(leaves, relativePath, parsed);
102
+ }
103
+ return yield* Snapshot.parseLeaves(leaves);
104
+ });
105
+ const parse = (input) => Schema.decodeUnknownResult(Entries)(input).pipe(Result.mapError((cause) => new SnapshotError({
106
+ reason: "InvalidShape",
107
+ relativePath: "",
108
+ pathSegments: [],
109
+ cause
110
+ })), Result.flatMap(fromEntries));
111
+ const GenerationSnapshot = Entries.pipe(Schema.decodeTo(Schema.declare((input) => input instanceof Snapshot), {
112
+ decode: SchemaGetter.transformEffect((entries, options) => Effect.fromResult(fromEntries(entries)).pipe(Effect.mapError((error) => new SchemaIssue.InvalidValue({ message: Match.value(error).pipe(Match.tagsExhaustive({
113
+ SnapshotError: (failure) => failure.message,
114
+ ParentChildNameCollisionError: (failure) => `${failure.parentSpecPath} declares a ${failure.collisionKind} named ${failure.collisionName} that collides with ${failure.childSpecPath}`
115
+ })) }, entries, options)))),
116
+ encode: SchemaGetter.transform((snapshot) => HashMap.toEntries(snapshot.leaves))
117
+ }));
118
+ const summarize = (group) => ({
119
+ runtime: group.runtime,
120
+ functionNames: Record.keys(group.functions),
121
+ groups: Record.map(group.groups, summarize)
122
+ });
123
+ const update = (snapshot, leaves) => Result.gen(function* () {
124
+ if (leaves.length === 0) return snapshot;
125
+ const replacement = yield* fromLoadedLeaves(leaves);
126
+ return yield* Snapshot.parseLeaves(HashMap.union(snapshot.leaves, replacement.leaves));
127
+ });
128
+ const fromLoadedLeaves = (leaves) => parse(leaves.map((leaf) => [leaf.relativePath.replaceAll("\\", "/"), summarize(leaf.spec)]));
129
+ const groups = (snapshot) => {
130
+ const visit = (path, tree) => [{
131
+ path,
132
+ runtime: tree.runtime,
133
+ functionNames: Array.sort(tree.functionNames, String.Order)
134
+ }, ...Array.flatMap(Array.sort(Object.keys(tree.groups), String.Order), (name) => visit(append(path, name), tree.groups[name]))];
135
+ return Array.flatMap(Array.fromIterable(snapshot.leaves), ([path, tree]) => visit(rootPath(path), tree));
136
+ };
137
+ const functionPaths = (snapshot) => FunctionPaths.make(HashSet.fromIterable(Array.flatMap(groups(snapshot), (group) => group.functionNames.map((name) => FunctionPath.make({
138
+ groupPath: group.path,
139
+ name
140
+ })))));
141
+ const generatedGroups = (snapshot) => HashMap.fromIterable(Array.filterMap(groups(snapshot), (group) => group.functionNames.length === 0 ? Result.fail(void 0) : Result.succeed([group.path, group])));
142
+ const plan = (snapshot, existing) => {
143
+ const current = generatedGroups(snapshot);
144
+ return {
145
+ removed: Array.fromIterable(existing).filter((path) => !HashMap.has(current, path)),
146
+ changed: Array.fromIterable(HashMap.values(current))
147
+ };
148
+ };
149
+ const equivalentGroup = Schema.toEquivalence(GroupSummary);
150
+ const diff = (before, after) => {
151
+ const previous = generatedGroups(before);
152
+ const current = generatedGroups(after);
153
+ return {
154
+ removed: Array.filter(HashMap.keys(previous), (path) => !HashMap.has(current, path)),
155
+ changed: Array.filter(HashMap.values(current), (group) => {
156
+ const old = HashMap.get(previous, group.path);
157
+ return Option.isNone(old) || !equivalentGroup(old.value, group);
158
+ })
159
+ };
160
+ };
161
+ const parseNoParentChildNameCollisions = (leaves) => {
162
+ for (const childPath of HashMap.keys(leaves)) {
163
+ const segments = rootPath(childPath).pathSegments;
164
+ for (let depth = 1; depth < segments.length; depth++) {
165
+ const parentPath = SpecModulePath.make(`${segments.slice(0, depth).join("/")}.spec.ts`);
166
+ const parent = HashMap.get(leaves, parentPath);
167
+ if (Option.isNone(parent)) continue;
168
+ const collisionName = segments[depth];
169
+ const collisionKind = parent.value.functionNames.includes(collisionName) ? "function" : Object.hasOwn(parent.value.groups, collisionName) ? "group" : void 0;
170
+ if (collisionKind !== void 0) return Result.fail(new ParentChildNameCollisionError({
171
+ parentSpecPath: parentPath,
172
+ childSpecPath: childPath,
173
+ collisionName,
174
+ collisionKind
175
+ }));
176
+ }
177
+ }
178
+ return Result.succeed(leaves);
179
+ };
180
+ //#endregion
181
+ export { GenerationSnapshot, GroupSummary, GroupTree, diff, fromLoadedLeaves, functionPaths, parse, plan, update };
182
+
183
+ //# sourceMappingURL=GenerationSnapshot.mjs.map