@confect/cli 1.0.0-next.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 (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +7 -0
  3. package/dist/FunctionPath.mjs +19 -0
  4. package/dist/FunctionPath.mjs.map +1 -0
  5. package/dist/FunctionPaths.mjs +41 -0
  6. package/dist/FunctionPaths.mjs.map +1 -0
  7. package/dist/GroupPath.mjs +52 -0
  8. package/dist/GroupPath.mjs.map +1 -0
  9. package/dist/GroupPaths.mjs +9 -0
  10. package/dist/GroupPaths.mjs.map +1 -0
  11. package/dist/_virtual/rolldown_runtime.mjs +28 -0
  12. package/dist/cliApp.mjs +13 -0
  13. package/dist/cliApp.mjs.map +1 -0
  14. package/dist/confect/codegen.mjs +111 -0
  15. package/dist/confect/codegen.mjs.map +1 -0
  16. package/dist/confect/dev.mjs +253 -0
  17. package/dist/confect/dev.mjs.map +1 -0
  18. package/dist/confect.mjs +14 -0
  19. package/dist/confect.mjs.map +1 -0
  20. package/dist/index.d.mts +1 -0
  21. package/dist/index.mjs +19 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/log.mjs +25 -0
  24. package/dist/log.mjs.map +1 -0
  25. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeCommandExecutor.mjs +12 -0
  26. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeCommandExecutor.mjs.map +1 -0
  27. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeFileSystem.mjs +15 -0
  28. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeFileSystem.mjs.map +1 -0
  29. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodePath.mjs +25 -0
  30. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodePath.mjs.map +1 -0
  31. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeRuntime.mjs +12 -0
  32. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeRuntime.mjs.map +1 -0
  33. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeTerminal.mjs +17 -0
  34. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/NodeTerminal.mjs.map +1 -0
  35. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/commandExecutor.mjs +129 -0
  36. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/commandExecutor.mjs.map +1 -0
  37. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/error.mjs +43 -0
  38. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/error.mjs.map +1 -0
  39. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/fileSystem.mjs +329 -0
  40. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/fileSystem.mjs.map +1 -0
  41. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/path.mjs +51 -0
  42. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/path.mjs.map +1 -0
  43. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/runtime.mjs +31 -0
  44. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/runtime.mjs.map +1 -0
  45. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/sink.mjs +24 -0
  46. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/sink.mjs.map +1 -0
  47. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/stream.mjs +91 -0
  48. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/stream.mjs.map +1 -0
  49. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/terminal.mjs +75 -0
  50. package/dist/node_modules/.pnpm/@effect_platform-node-shared@0.53.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effe_e0eeb3aae5ffec3060feb87d17ffb17c/node_modules/@effect/platform-node-shared/dist/esm/internal/terminal.mjs.map +1 -0
  51. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeContext.mjs +21 -0
  52. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeContext.mjs.map +1 -0
  53. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeFileSystem.mjs +15 -0
  54. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeFileSystem.mjs.map +1 -0
  55. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeRuntime.mjs +15 -0
  56. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeRuntime.mjs.map +1 -0
  57. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeWorker.mjs +27 -0
  58. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/NodeWorker.mjs.map +1 -0
  59. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/internal/worker.mjs +71 -0
  60. package/dist/node_modules/.pnpm/@effect_platform-node@0.100.0_@effect_cluster@0.52.9_@effect_platform@0.93.2_effect@3.1_a15ca1802d939cd85cc564105ef862ac/node_modules/@effect/platform-node/dist/esm/internal/worker.mjs.map +1 -0
  61. package/dist/packages/cli/package.mjs +6 -0
  62. package/dist/packages/cli/package.mjs.map +1 -0
  63. package/dist/packages/core/dist/Spec.mjs +23 -0
  64. package/dist/packages/core/dist/Spec.mjs.map +1 -0
  65. package/dist/packages/core/dist/_virtual/rolldown_runtime.mjs +14 -0
  66. package/dist/packages/core/dist/_virtual/rolldown_runtime.mjs.map +1 -0
  67. package/dist/services/ConfectDirectory.mjs +31 -0
  68. package/dist/services/ConfectDirectory.mjs.map +1 -0
  69. package/dist/services/ConvexDirectory.mjs +41 -0
  70. package/dist/services/ConvexDirectory.mjs.map +1 -0
  71. package/dist/services/ProjectRoot.mjs +35 -0
  72. package/dist/services/ProjectRoot.mjs.map +1 -0
  73. package/dist/templates.mjs +204 -0
  74. package/dist/templates.mjs.map +1 -0
  75. package/dist/utils.mjs +162 -0
  76. package/dist/utils.mjs.map +1 -0
  77. package/package.json +86 -0
  78. package/src/FunctionPath.ts +28 -0
  79. package/src/FunctionPaths.ts +103 -0
  80. package/src/GroupPath.ts +117 -0
  81. package/src/GroupPaths.ts +7 -0
  82. package/src/cliApp.ts +8 -0
  83. package/src/confect/codegen.ts +228 -0
  84. package/src/confect/dev.ts +611 -0
  85. package/src/confect.ts +19 -0
  86. package/src/index.ts +22 -0
  87. package/src/log.ts +106 -0
  88. package/src/services/ConfectDirectory.ts +41 -0
  89. package/src/services/ConvexDirectory.ts +67 -0
  90. package/src/services/ProjectRoot.ts +49 -0
  91. package/src/templates.ts +380 -0
  92. package/src/utils.ts +332 -0
package/src/log.ts ADDED
@@ -0,0 +1,106 @@
1
+ import { Path } from "@effect/platform";
2
+ import { Ansi, AnsiDoc } from "@effect/printer-ansi";
3
+ import { Console, Effect, pipe, String } from "effect";
4
+ import type * as FunctionPath from "./FunctionPath";
5
+ import * as GroupPath from "./GroupPath";
6
+ import { ProjectRoot } from "./services/ProjectRoot";
7
+
8
+ // --- File operation logs ---
9
+
10
+ const logFile = (char: string, color: Ansi.Ansi) => (fullPath: string) =>
11
+ Effect.gen(function* () {
12
+ const projectRoot = yield* ProjectRoot.get;
13
+ const path = yield* Path.Path;
14
+
15
+ const prefix = projectRoot + path.sep;
16
+ const suffix = pipe(fullPath, String.startsWith(prefix))
17
+ ? pipe(fullPath, String.slice(prefix.length))
18
+ : fullPath;
19
+
20
+ yield* Console.log(
21
+ pipe(
22
+ AnsiDoc.char(char),
23
+ AnsiDoc.annotate(color),
24
+ AnsiDoc.catWithSpace(
25
+ AnsiDoc.hcat([
26
+ pipe(AnsiDoc.text(prefix), AnsiDoc.annotate(Ansi.blackBright)),
27
+ pipe(AnsiDoc.text(suffix), AnsiDoc.annotate(color)),
28
+ ]),
29
+ ),
30
+ AnsiDoc.render({ style: "pretty" }),
31
+ ),
32
+ );
33
+ });
34
+
35
+ export const logFileAdded = logFile("+", Ansi.green);
36
+
37
+ export const logFileRemoved = logFile("-", Ansi.red);
38
+
39
+ export const logFileModified = logFile("~", Ansi.yellow);
40
+
41
+ // --- Function subline logs ---
42
+
43
+ const logFunction =
44
+ (char: string, color: Ansi.Ansi) =>
45
+ (functionPath: FunctionPath.FunctionPath) =>
46
+ Console.log(
47
+ pipe(
48
+ AnsiDoc.text(" "),
49
+ AnsiDoc.cat(pipe(AnsiDoc.char(char), AnsiDoc.annotate(color))),
50
+ AnsiDoc.catWithSpace(
51
+ AnsiDoc.hcat([
52
+ pipe(
53
+ AnsiDoc.text(GroupPath.toString(functionPath.groupPath) + "."),
54
+ AnsiDoc.annotate(Ansi.blackBright),
55
+ ),
56
+ pipe(AnsiDoc.text(functionPath.name), AnsiDoc.annotate(color)),
57
+ ]),
58
+ ),
59
+ AnsiDoc.render({ style: "pretty" }),
60
+ ),
61
+ );
62
+
63
+ export const logFunctionAdded = logFunction("+", Ansi.green);
64
+
65
+ export const logFunctionRemoved = logFunction("-", Ansi.red);
66
+
67
+ // --- Process status logs ---
68
+
69
+ const logStatus =
70
+ (
71
+ char: string,
72
+ charColor: Ansi.Ansi,
73
+ messageText: string,
74
+ messageColor: Ansi.Ansi,
75
+ ) =>
76
+ (message: string) =>
77
+ Console.log(
78
+ pipe(
79
+ AnsiDoc.char(char),
80
+ AnsiDoc.annotate(charColor),
81
+ AnsiDoc.catWithSpace(
82
+ pipe(
83
+ AnsiDoc.char(" "),
84
+ AnsiDoc.cat(AnsiDoc.text(messageText)),
85
+ AnsiDoc.cat(AnsiDoc.char(" ")),
86
+ AnsiDoc.annotate(messageColor),
87
+ ),
88
+ ),
89
+ AnsiDoc.catWithSpace(AnsiDoc.text(message)),
90
+ AnsiDoc.render({ style: "pretty" }),
91
+ ),
92
+ );
93
+
94
+ export const logCompleted = logStatus(
95
+ "✔︎",
96
+ Ansi.green,
97
+ "SUCCESS",
98
+ Ansi.combine(Ansi.green, Ansi.bgGreenBright),
99
+ );
100
+
101
+ export const logFailed = logStatus(
102
+ "✘",
103
+ Ansi.red,
104
+ "FAILURE",
105
+ Ansi.combine(Ansi.red, Ansi.bgRedBright),
106
+ );
@@ -0,0 +1,41 @@
1
+ import { FileSystem, Path } from "@effect/platform";
2
+ import { Effect, Ref, Schema } from "effect";
3
+ import { ConvexDirectory } from "./ConvexDirectory";
4
+
5
+ export class ConfectDirectory extends Effect.Service<ConfectDirectory>()(
6
+ "@confect/cli/services/ConfectDirectory",
7
+ {
8
+ effect: Effect.gen(function* () {
9
+ const convexDirectory = yield* findConfectDirectory;
10
+
11
+ const ref = yield* Ref.make<string>(convexDirectory);
12
+
13
+ return { get: Ref.get(ref) } as const;
14
+ }),
15
+ dependencies: [ConvexDirectory.Default],
16
+ accessors: true,
17
+ },
18
+ ) {}
19
+
20
+ export class ConfectDirectoryNotFoundError extends Schema.TaggedError<ConfectDirectoryNotFoundError>(
21
+ "ConfectDirectoryNotFoundError",
22
+ )("ConfectDirectoryNotFoundError", {}) {
23
+ override get message(): string {
24
+ return "Could not find Confect directory";
25
+ }
26
+ }
27
+
28
+ export const findConfectDirectory = Effect.gen(function* () {
29
+ const fs = yield* FileSystem.FileSystem;
30
+ const path = yield* Path.Path;
31
+
32
+ const convexDirectory = yield* ConvexDirectory.get;
33
+
34
+ const confectDirectory = path.join(path.dirname(convexDirectory), "confect");
35
+
36
+ if (yield* fs.exists(confectDirectory)) {
37
+ return confectDirectory;
38
+ } else {
39
+ return yield* Effect.fail(new ConfectDirectoryNotFoundError());
40
+ }
41
+ });
@@ -0,0 +1,67 @@
1
+ import { FileSystem, Path } from "@effect/platform";
2
+ import { Effect, Option, Ref, Schema } from "effect";
3
+ import { ProjectRoot } from "./ProjectRoot";
4
+
5
+ export class ConvexDirectory extends Effect.Service<ConvexDirectory>()(
6
+ "@confect/cli/services/ConvexDirectory",
7
+ {
8
+ effect: Effect.gen(function* () {
9
+ const convexDirectory = yield* findConvexDirectory;
10
+
11
+ const ref = yield* Ref.make<string>(convexDirectory);
12
+
13
+ return { get: Ref.get(ref) } as const;
14
+ }),
15
+ dependencies: [ProjectRoot.Default],
16
+ accessors: true,
17
+ },
18
+ ) {}
19
+
20
+ export class ConvexDirectoryNotFoundError extends Schema.TaggedError<ConvexDirectoryNotFoundError>(
21
+ "ConvexDirectoryNotFoundError",
22
+ )("ConvexDirectoryNotFoundError", {}) {
23
+ override get message(): string {
24
+ return "Could not find Convex directory";
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Schema for `convex.json` configuration file.
30
+ * @see https://docs.convex.dev/production/project-configuration
31
+ */
32
+ const ConvexJsonConfig = Schema.parseJson(
33
+ Schema.Struct({
34
+ functions: Schema.optional(Schema.String),
35
+ }),
36
+ );
37
+
38
+ const findConvexDirectory = Effect.gen(function* () {
39
+ const fs = yield* FileSystem.FileSystem;
40
+ const path = yield* Path.Path;
41
+
42
+ const projectRoot = yield* ProjectRoot.get;
43
+
44
+ const defaultPath = path.join(projectRoot, "convex");
45
+
46
+ const convexJsonPath = path.join(projectRoot, "convex.json");
47
+
48
+ const convexDirectory = yield* Effect.if(fs.exists(convexJsonPath), {
49
+ onTrue: () =>
50
+ fs.readFileString(convexJsonPath).pipe(
51
+ Effect.andThen(Schema.decodeOption(ConvexJsonConfig)),
52
+ Effect.map((config) =>
53
+ Option.fromNullable(config.functions).pipe(
54
+ Option.map((functionsDir) => path.join(projectRoot, functionsDir)),
55
+ ),
56
+ ),
57
+ Effect.andThen(Option.getOrElse(() => defaultPath)),
58
+ ),
59
+ onFalse: () => Effect.succeed(defaultPath),
60
+ });
61
+
62
+ if (yield* fs.exists(convexDirectory)) {
63
+ return convexDirectory;
64
+ } else {
65
+ return yield* Effect.fail(new ConvexDirectoryNotFoundError());
66
+ }
67
+ });
@@ -0,0 +1,49 @@
1
+ import { FileSystem, Path } from "@effect/platform";
2
+ import { NodeFileSystem } from "@effect/platform-node";
3
+ import { Array, Effect, Option, Ref, Schema } from "effect";
4
+
5
+ export class ProjectRoot extends Effect.Service<ProjectRoot>()(
6
+ "@confect/cli/services/ProjectRoot",
7
+ {
8
+ effect: Effect.gen(function* () {
9
+ const projectRoot = yield* findProjectRoot;
10
+
11
+ const ref = yield* Ref.make<string>(projectRoot);
12
+
13
+ return { get: Ref.get(ref) } as const;
14
+ }),
15
+ dependencies: [NodeFileSystem.layer],
16
+ accessors: true,
17
+ },
18
+ ) {}
19
+
20
+ export const findProjectRoot = Effect.gen(function* () {
21
+ const fs = yield* FileSystem.FileSystem;
22
+ const path = yield* Path.Path;
23
+
24
+ const startDir = path.resolve(".");
25
+ const root = path.parse(startDir).root;
26
+
27
+ const directories = Array.unfold(startDir, (dir) =>
28
+ dir === root
29
+ ? Option.none()
30
+ : Option.some([dir, path.dirname(dir)] as const),
31
+ );
32
+
33
+ const projectRoot = yield* Effect.findFirst(directories, (dir) =>
34
+ fs.exists(path.join(dir, "package.json")),
35
+ );
36
+
37
+ return yield* Option.match(projectRoot, {
38
+ onNone: () => Effect.fail(new ProjectRootNotFoundError()),
39
+ onSome: Effect.succeed,
40
+ });
41
+ });
42
+
43
+ export class ProjectRootNotFoundError extends Schema.TaggedError<ProjectRootNotFoundError>(
44
+ "ProjectRootNotFoundError",
45
+ )("ProjectRootNotFoundError", {}) {
46
+ override get message(): string {
47
+ return "Could not find project root (no 'package.json' found)";
48
+ }
49
+ }
@@ -0,0 +1,380 @@
1
+ import type { Options as CodeBlockWriterOptions } from "code-block-writer";
2
+ import CodeBlockWriter_ from "code-block-writer";
3
+ import { Array, Effect } from "effect";
4
+ import type * as GroupPath from "./GroupPath";
5
+
6
+ export const functions = ({
7
+ groupPath,
8
+ functionNames,
9
+ registeredFunctionsImportPath,
10
+ }: {
11
+ groupPath: GroupPath.GroupPath;
12
+ functionNames: string[];
13
+ registeredFunctionsImportPath: string;
14
+ }) =>
15
+ Effect.gen(function* () {
16
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
17
+
18
+ yield* cbw.writeLine(
19
+ `import registeredFunctions from "${registeredFunctionsImportPath}";`,
20
+ );
21
+ yield* cbw.newLine();
22
+ for (const functionName of functionNames) {
23
+ yield* cbw.writeLine(
24
+ `export const ${functionName} = registeredFunctions.${Array.join([...groupPath.pathSegments, functionName], ".")};`,
25
+ );
26
+ }
27
+
28
+ return yield* cbw.toString();
29
+ });
30
+
31
+ export const schema = ({ schemaImportPath }: { schemaImportPath: string }) =>
32
+ Effect.gen(function* () {
33
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
34
+
35
+ yield* cbw.writeLine(`import schemaDefinition from "${schemaImportPath}";`);
36
+ yield* cbw.newLine();
37
+ yield* cbw.writeLine(
38
+ `export default schemaDefinition.convexSchemaDefinition;`,
39
+ );
40
+
41
+ return yield* cbw.toString();
42
+ });
43
+
44
+ export const http = ({ httpImportPath }: { httpImportPath: string }) =>
45
+ Effect.gen(function* () {
46
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
47
+
48
+ yield* cbw.writeLine(`import http from "${httpImportPath}";`);
49
+ yield* cbw.newLine();
50
+ yield* cbw.writeLine(`export default http;`);
51
+
52
+ return yield* cbw.toString();
53
+ });
54
+
55
+ export const convexConfig = ({ appImportPath }: { appImportPath: string }) =>
56
+ Effect.gen(function* () {
57
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
58
+
59
+ yield* cbw.writeLine(`import app from "${appImportPath}";`);
60
+ yield* cbw.newLine();
61
+ yield* cbw.writeLine(`export default app;`);
62
+
63
+ return yield* cbw.toString();
64
+ });
65
+
66
+ export const crons = ({ cronsImportPath }: { cronsImportPath: string }) =>
67
+ Effect.gen(function* () {
68
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
69
+
70
+ yield* cbw.writeLine(`import crons from "${cronsImportPath}";`);
71
+ yield* cbw.newLine();
72
+ yield* cbw.writeLine(`export default crons;`);
73
+
74
+ return yield* cbw.toString();
75
+ });
76
+
77
+ export const authConfig = ({ authImportPath }: { authImportPath: string }) =>
78
+ Effect.gen(function* () {
79
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
80
+
81
+ yield* cbw.writeLine(`import auth from "${authImportPath}";`);
82
+ yield* cbw.newLine();
83
+ yield* cbw.writeLine(`export default auth;`);
84
+
85
+ return yield* cbw.toString();
86
+ });
87
+
88
+ export const refs = ({ specImportPath }: { specImportPath: string }) =>
89
+ Effect.gen(function* () {
90
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
91
+
92
+ yield* cbw.writeLine(`import { Refs } from "@confect/core";`);
93
+ yield* cbw.writeLine(`import spec from "${specImportPath}";`);
94
+ yield* cbw.blankLine();
95
+ yield* cbw.writeLine(
96
+ `export const { public: api, internal } = Refs.make(spec);`,
97
+ );
98
+
99
+ return yield* cbw.toString();
100
+ });
101
+
102
+ export const api = ({
103
+ schemaImportPath,
104
+ specImportPath,
105
+ }: {
106
+ schemaImportPath: string;
107
+ specImportPath: string;
108
+ }) =>
109
+ Effect.gen(function* () {
110
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
111
+
112
+ yield* cbw.writeLine(`import { Api } from "@confect/server";`);
113
+ yield* cbw.writeLine(`import schema from "${schemaImportPath}";`);
114
+ yield* cbw.writeLine(`import spec from "${specImportPath}";`);
115
+ yield* cbw.blankLine();
116
+ yield* cbw.writeLine(`export default Api.make(schema, spec);`);
117
+
118
+ return yield* cbw.toString();
119
+ });
120
+
121
+ export const registeredFunctions = ({
122
+ implImportPath,
123
+ }: {
124
+ implImportPath: string;
125
+ }) =>
126
+ Effect.gen(function* () {
127
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
128
+
129
+ yield* cbw.writeLine(
130
+ `import { RegisteredFunctions } from "@confect/server";`,
131
+ );
132
+ yield* cbw.writeLine(`import impl from "${implImportPath}";`);
133
+ yield* cbw.blankLine();
134
+ yield* cbw.writeLine(`export default RegisteredFunctions.make(impl);`);
135
+
136
+ return yield* cbw.toString();
137
+ });
138
+
139
+ export const services = ({ schemaImportPath }: { schemaImportPath: string }) =>
140
+ Effect.gen(function* () {
141
+ const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
142
+
143
+ // Imports
144
+ yield* cbw.writeLine("import {");
145
+ yield* cbw.indent(
146
+ Effect.gen(function* () {
147
+ yield* cbw.writeLine("ActionCtx as ActionCtx_,");
148
+ yield* cbw.writeLine("ActionRunner as ActionRunner_,");
149
+ yield* cbw.writeLine("Auth as Auth_,");
150
+ yield* cbw.writeLine("type DataModel,");
151
+ yield* cbw.writeLine("DatabaseReader as DatabaseReader_,");
152
+ yield* cbw.writeLine("DatabaseWriter as DatabaseWriter_,");
153
+ yield* cbw.writeLine("MutationCtx as MutationCtx_,");
154
+ yield* cbw.writeLine("MutationRunner as MutationRunner_,");
155
+ yield* cbw.writeLine("QueryCtx as QueryCtx_,");
156
+ yield* cbw.writeLine("QueryRunner as QueryRunner_,");
157
+ yield* cbw.writeLine("Scheduler as Scheduler_,");
158
+ yield* cbw.writeLine("Storage,");
159
+ yield* cbw.writeLine("VectorSearch as VectorSearch_,");
160
+ }),
161
+ );
162
+ yield* cbw.writeLine(`} from "@confect/server";`);
163
+ yield* cbw.writeLine(
164
+ `import type schemaDefinition from "${schemaImportPath}";`,
165
+ );
166
+ yield* cbw.blankLine();
167
+
168
+ // Auth
169
+ yield* cbw.writeLine("export const Auth = Auth_.Auth;");
170
+ yield* cbw.writeLine("export type Auth = typeof Auth.Identifier;");
171
+ yield* cbw.blankLine();
172
+
173
+ // Scheduler
174
+ yield* cbw.writeLine("export const Scheduler = Scheduler_.Scheduler;");
175
+ yield* cbw.writeLine(
176
+ "export type Scheduler = typeof Scheduler.Identifier;",
177
+ );
178
+ yield* cbw.blankLine();
179
+
180
+ // StorageReader
181
+ yield* cbw.writeLine("export const StorageReader = Storage.StorageReader;");
182
+ yield* cbw.writeLine(
183
+ "export type StorageReader = typeof StorageReader.Identifier;",
184
+ );
185
+ yield* cbw.blankLine();
186
+
187
+ // StorageWriter
188
+ yield* cbw.writeLine("export const StorageWriter = Storage.StorageWriter;");
189
+ yield* cbw.writeLine(
190
+ "export type StorageWriter = typeof StorageWriter.Identifier;",
191
+ );
192
+ yield* cbw.blankLine();
193
+
194
+ // StorageActionWriter
195
+ yield* cbw.writeLine(
196
+ "export const StorageActionWriter = Storage.StorageActionWriter;",
197
+ );
198
+ yield* cbw.writeLine(
199
+ "export type StorageActionWriter = typeof StorageActionWriter.Identifier;",
200
+ );
201
+ yield* cbw.blankLine();
202
+
203
+ // VectorSearch
204
+ yield* cbw.writeLine("export const VectorSearch =");
205
+ yield* cbw.indent(
206
+ cbw.writeLine(
207
+ "VectorSearch_.VectorSearch<DataModel.FromSchema<typeof schemaDefinition>>();",
208
+ ),
209
+ );
210
+ yield* cbw.writeLine(
211
+ "export type VectorSearch = typeof VectorSearch.Identifier;",
212
+ );
213
+ yield* cbw.blankLine();
214
+
215
+ // DatabaseReader
216
+ yield* cbw.writeLine("export const DatabaseReader =");
217
+ yield* cbw.indent(
218
+ cbw.writeLine(
219
+ "DatabaseReader_.DatabaseReader<typeof schemaDefinition>();",
220
+ ),
221
+ );
222
+ yield* cbw.writeLine(
223
+ "export type DatabaseReader = typeof DatabaseReader.Identifier;",
224
+ );
225
+ yield* cbw.blankLine();
226
+
227
+ // DatabaseWriter
228
+ yield* cbw.writeLine("export const DatabaseWriter =");
229
+ yield* cbw.indent(
230
+ cbw.writeLine(
231
+ "DatabaseWriter_.DatabaseWriter<typeof schemaDefinition>();",
232
+ ),
233
+ );
234
+ yield* cbw.writeLine(
235
+ "export type DatabaseWriter = typeof DatabaseWriter.Identifier;",
236
+ );
237
+ yield* cbw.blankLine();
238
+
239
+ // QueryRunner
240
+ yield* cbw.writeLine(
241
+ "export const QueryRunner = QueryRunner_.QueryRunner;",
242
+ );
243
+ yield* cbw.writeLine(
244
+ "export type QueryRunner = typeof QueryRunner.Identifier;",
245
+ );
246
+ yield* cbw.blankLine();
247
+
248
+ // MutationRunner
249
+ yield* cbw.writeLine(
250
+ "export const MutationRunner = MutationRunner_.MutationRunner;",
251
+ );
252
+ yield* cbw.writeLine(
253
+ "export type MutationRunner = typeof MutationRunner.Identifier;",
254
+ );
255
+ yield* cbw.blankLine();
256
+
257
+ // ActionRunner
258
+ yield* cbw.writeLine(
259
+ "export const ActionRunner = ActionRunner_.ActionRunner;",
260
+ );
261
+ yield* cbw.writeLine(
262
+ "export type ActionRunner = typeof ActionRunner.Identifier;",
263
+ );
264
+ yield* cbw.blankLine();
265
+
266
+ // QueryCtx
267
+ yield* cbw.writeLine("export const QueryCtx =");
268
+ yield* cbw.indent(
269
+ Effect.gen(function* () {
270
+ yield* cbw.writeLine("QueryCtx_.QueryCtx<");
271
+ yield* cbw.indent(
272
+ cbw.writeLine(
273
+ "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
274
+ ),
275
+ );
276
+ yield* cbw.writeLine(">();");
277
+ }),
278
+ );
279
+ yield* cbw.writeLine("export type QueryCtx = typeof QueryCtx.Identifier;");
280
+ yield* cbw.blankLine();
281
+
282
+ // MutationCtx
283
+ yield* cbw.writeLine("export const MutationCtx =");
284
+ yield* cbw.indent(
285
+ Effect.gen(function* () {
286
+ yield* cbw.writeLine("MutationCtx_.MutationCtx<");
287
+ yield* cbw.indent(
288
+ cbw.writeLine(
289
+ "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
290
+ ),
291
+ );
292
+ yield* cbw.writeLine(">();");
293
+ }),
294
+ );
295
+ yield* cbw.writeLine(
296
+ "export type MutationCtx = typeof MutationCtx.Identifier;",
297
+ );
298
+ yield* cbw.blankLine();
299
+
300
+ // ActionCtx
301
+ yield* cbw.writeLine("export const ActionCtx =");
302
+ yield* cbw.indent(
303
+ Effect.gen(function* () {
304
+ yield* cbw.writeLine("ActionCtx_.ActionCtx<");
305
+ yield* cbw.indent(
306
+ cbw.writeLine(
307
+ "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
308
+ ),
309
+ );
310
+ yield* cbw.writeLine(">();");
311
+ }),
312
+ );
313
+ yield* cbw.writeLine(
314
+ "export type ActionCtx = typeof ActionCtx.Identifier;",
315
+ );
316
+
317
+ return yield* cbw.toString();
318
+ });
319
+
320
+ class CodeBlockWriter {
321
+ private readonly writer: CodeBlockWriter_;
322
+
323
+ constructor(opts?: Partial<CodeBlockWriterOptions>) {
324
+ this.writer = new CodeBlockWriter_(opts);
325
+ }
326
+
327
+ indent<E = never, R = never>(
328
+ eff: Effect.Effect<void, E, R>,
329
+ ): Effect.Effect<void, E, R> {
330
+ return Effect.gen(this, function* () {
331
+ const indentationLevel = this.writer.getIndentationLevel();
332
+ this.writer.setIndentationLevel(indentationLevel + 1);
333
+ yield* eff;
334
+ this.writer.setIndentationLevel(indentationLevel);
335
+ });
336
+ }
337
+
338
+ writeLine<E = never, R = never>(line: string): Effect.Effect<void, E, R> {
339
+ return Effect.sync(() => {
340
+ this.writer.writeLine(line);
341
+ });
342
+ }
343
+
344
+ write<E = never, R = never>(text: string): Effect.Effect<void, E, R> {
345
+ return Effect.sync(() => {
346
+ this.writer.write(text);
347
+ });
348
+ }
349
+
350
+ quote<E = never, R = never>(text: string): Effect.Effect<void, E, R> {
351
+ return Effect.sync(() => {
352
+ this.writer.quote(text);
353
+ });
354
+ }
355
+
356
+ conditionalWriteLine<E = never, R = never>(
357
+ condition: boolean,
358
+ text: string,
359
+ ): Effect.Effect<void, E, R> {
360
+ return Effect.sync(() => {
361
+ this.writer.conditionalWriteLine(condition, text);
362
+ });
363
+ }
364
+
365
+ newLine<E = never, R = never>(): Effect.Effect<void, E, R> {
366
+ return Effect.sync(() => {
367
+ this.writer.newLine();
368
+ });
369
+ }
370
+
371
+ blankLine<E = never, R = never>(): Effect.Effect<void, E, R> {
372
+ return Effect.sync(() => {
373
+ this.writer.blankLine();
374
+ });
375
+ }
376
+
377
+ toString<E = never, R = never>(): Effect.Effect<string, E, R> {
378
+ return Effect.sync(() => this.writer.toString());
379
+ }
380
+ }