@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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +7 -0
- package/dist/FunctionPath.mjs +19 -0
- package/dist/FunctionPath.mjs.map +1 -0
- package/dist/FunctionPaths.mjs +41 -0
- package/dist/FunctionPaths.mjs.map +1 -0
- package/dist/GroupPath.mjs +52 -0
- package/dist/GroupPath.mjs.map +1 -0
- package/dist/GroupPaths.mjs +9 -0
- package/dist/GroupPaths.mjs.map +1 -0
- package/dist/_virtual/rolldown_runtime.mjs +28 -0
- package/dist/cliApp.mjs +13 -0
- package/dist/cliApp.mjs.map +1 -0
- package/dist/confect/codegen.mjs +111 -0
- package/dist/confect/codegen.mjs.map +1 -0
- package/dist/confect/dev.mjs +253 -0
- package/dist/confect/dev.mjs.map +1 -0
- package/dist/confect.mjs +14 -0
- package/dist/confect.mjs.map +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -0
- package/dist/log.mjs +25 -0
- package/dist/log.mjs.map +1 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/dist/packages/cli/package.mjs +6 -0
- package/dist/packages/cli/package.mjs.map +1 -0
- package/dist/packages/core/dist/Spec.mjs +23 -0
- package/dist/packages/core/dist/Spec.mjs.map +1 -0
- package/dist/packages/core/dist/_virtual/rolldown_runtime.mjs +14 -0
- package/dist/packages/core/dist/_virtual/rolldown_runtime.mjs.map +1 -0
- package/dist/services/ConfectDirectory.mjs +31 -0
- package/dist/services/ConfectDirectory.mjs.map +1 -0
- package/dist/services/ConvexDirectory.mjs +41 -0
- package/dist/services/ConvexDirectory.mjs.map +1 -0
- package/dist/services/ProjectRoot.mjs +35 -0
- package/dist/services/ProjectRoot.mjs.map +1 -0
- package/dist/templates.mjs +204 -0
- package/dist/templates.mjs.map +1 -0
- package/dist/utils.mjs +162 -0
- package/dist/utils.mjs.map +1 -0
- package/package.json +86 -0
- package/src/FunctionPath.ts +28 -0
- package/src/FunctionPaths.ts +103 -0
- package/src/GroupPath.ts +117 -0
- package/src/GroupPaths.ts +7 -0
- package/src/cliApp.ts +8 -0
- package/src/confect/codegen.ts +228 -0
- package/src/confect/dev.ts +611 -0
- package/src/confect.ts +19 -0
- package/src/index.ts +22 -0
- package/src/log.ts +106 -0
- package/src/services/ConfectDirectory.ts +41 -0
- package/src/services/ConvexDirectory.ts +67 -0
- package/src/services/ProjectRoot.ts +49 -0
- package/src/templates.ts +380 -0
- 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
|
+
}
|
package/src/templates.ts
ADDED
|
@@ -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
|
+
}
|