@confect/cli 9.0.0-next.1 → 9.0.0-next.10
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 +337 -1
- package/dist/BuildError.mjs +9 -2
- package/dist/BuildError.mjs.map +1 -1
- package/dist/Bundler.mjs +67 -57
- package/dist/Bundler.mjs.map +1 -1
- package/dist/CodeBlockWriter.mjs +1 -1
- package/dist/CodeBlockWriter.mjs.map +1 -1
- package/dist/CodegenError.mjs +29 -21
- package/dist/CodegenError.mjs.map +1 -1
- package/dist/ConfectDirectory.mjs +5 -2
- package/dist/ConfectDirectory.mjs.map +1 -1
- package/dist/ConvexDirectory.mjs +6 -2
- package/dist/ConvexDirectory.mjs.map +1 -1
- package/dist/FunctionPath.mjs +1 -1
- package/dist/FunctionPath.mjs.map +1 -1
- package/dist/FunctionPaths.mjs +5 -1
- package/dist/FunctionPaths.mjs.map +1 -1
- package/dist/GroupPath.mjs +9 -2
- package/dist/GroupPath.mjs.map +1 -1
- package/dist/GroupPaths.mjs +1 -1
- package/dist/GroupPaths.mjs.map +1 -1
- package/dist/LeafModule.mjs +19 -26
- package/dist/LeafModule.mjs.map +1 -1
- package/dist/ProjectRoot.mjs +8 -3
- package/dist/ProjectRoot.mjs.map +1 -1
- package/dist/SpecAssemblyNode.mjs +9 -11
- package/dist/SpecAssemblyNode.mjs.map +1 -1
- package/dist/TableModule.mjs +94 -0
- package/dist/TableModule.mjs.map +1 -0
- package/dist/cliApp.mjs +1 -1
- package/dist/cliApp.mjs.map +1 -1
- package/dist/confect/codegen.mjs +203 -142
- package/dist/confect/codegen.mjs.map +1 -1
- package/dist/confect/dev.mjs +36 -17
- package/dist/confect/dev.mjs.map +1 -1
- package/dist/confect.mjs +2 -2
- package/dist/confect.mjs.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/log.mjs +9 -4
- package/dist/log.mjs.map +1 -1
- package/dist/package.mjs +1 -1
- package/dist/templates.mjs +132 -45
- package/dist/templates.mjs.map +1 -1
- package/dist/utils.mjs +42 -22
- package/dist/utils.mjs.map +1 -1
- package/package.json +33 -50
- package/dist/index.d.mts +0 -1
- package/src/BuildError.ts +0 -210
- package/src/Bundler.ts +0 -144
- package/src/CodeBlockWriter.ts +0 -65
- package/src/CodegenError.ts +0 -376
- package/src/ConfectDirectory.ts +0 -42
- package/src/ConvexDirectory.ts +0 -68
- package/src/FunctionPath.ts +0 -27
- package/src/FunctionPaths.ts +0 -103
- package/src/GroupPath.ts +0 -118
- package/src/GroupPaths.ts +0 -7
- package/src/LeafModule.ts +0 -317
- package/src/ProjectRoot.ts +0 -50
- package/src/SpecAssemblyNode.ts +0 -82
- package/src/cliApp.ts +0 -8
- package/src/confect/codegen.ts +0 -710
- package/src/confect/dev.ts +0 -749
- package/src/confect.ts +0 -19
- package/src/index.ts +0 -22
- package/src/log.ts +0 -104
- package/src/templates.ts +0 -482
- package/src/utils.ts +0 -429
package/dist/confect/codegen.mjs
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
|
-
import { logFileAdded, logFileModified, logFileRemoved, logPending, logSuccess } from "../log.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { logFileAdded, logFileModified, logFileRemoved, logPending, logSuccess, logWarn } from "../log.mjs";
|
|
2
|
+
import { bundle } from "../Bundler.mjs";
|
|
3
|
+
import { LegacySchemaFileError, MissingImplFileError, MissingSpecFileError, ParentChildNameCollisionError, tapAndLog } from "../CodegenError.mjs";
|
|
4
4
|
import { ConvexDirectory } from "../ConvexDirectory.mjs";
|
|
5
5
|
import { ConfectDirectory } from "../ConfectDirectory.mjs";
|
|
6
6
|
import { FunctionPaths, make } from "../FunctionPaths.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import
|
|
7
|
+
import { assemblyNodesFromLeaves } from "../SpecAssemblyNode.mjs";
|
|
8
|
+
import { assembledSpec, convexSchema, id, refs, registeredFunctionsForGroup, runtimeSchema, schema, services, tableWrapper } from "../templates.mjs";
|
|
9
|
+
import { WriteTracker, generateAuthConfig, generateCrons, generateFunctions, generateHttp, removePathIfExists, toModuleImportPath, touchConvexSchema, writeFileStringAndLog } from "../utils.mjs";
|
|
10
|
+
import { discoverLeafImplFiles, discoverLeafSpecFiles, implPathForSpec, registeredFunctionsRelativePath, specPathForImpl, toLeafModule, validateImpl, validateSpec } from "../LeafModule.mjs";
|
|
11
|
+
import { TABLES_DIRNAME, discover, validate } from "../TableModule.mjs";
|
|
12
|
+
import * as Effect from "effect/Effect";
|
|
13
|
+
import * as Command from "@effect/cli/Command";
|
|
14
14
|
import { Spec } from "@confect/core";
|
|
15
|
-
import * as
|
|
16
|
-
import
|
|
15
|
+
import * as FileSystem from "@effect/platform/FileSystem";
|
|
16
|
+
import * as Path from "@effect/platform/Path";
|
|
17
|
+
import * as Array from "effect/Array";
|
|
18
|
+
import * as Either from "effect/Either";
|
|
19
|
+
import * as HashSet from "effect/HashSet";
|
|
20
|
+
import * as Match from "effect/Match";
|
|
21
|
+
import * as Option from "effect/Option";
|
|
22
|
+
import * as Ref from "effect/Ref";
|
|
17
23
|
|
|
18
24
|
//#region src/confect/codegen.ts
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
const GENERATED_DIRNAME = "_generated";
|
|
26
|
+
const GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "spec.ts"));
|
|
27
|
+
const GENERATED_SCHEMA_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "schema.ts"));
|
|
28
|
+
const GENERATED_CONVEX_SCHEMA_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "convexSchema.ts"));
|
|
29
|
+
const GENERATED_ID_PATH = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "id.ts"));
|
|
30
|
+
const GENERATED_TABLES_DIRNAME = Effect.andThen(Path.Path, (path) => path.join(GENERATED_DIRNAME, "tables"));
|
|
31
|
+
const LEGACY_PATHS = Effect.gen(function* () {
|
|
32
|
+
const path = yield* Path.Path;
|
|
33
|
+
return [
|
|
34
|
+
"spec.ts",
|
|
35
|
+
"nodeSpec.ts",
|
|
36
|
+
"impl.ts",
|
|
37
|
+
"nodeImpl.ts",
|
|
38
|
+
path.join(GENERATED_DIRNAME, "registeredFunctions.ts"),
|
|
39
|
+
path.join(GENERATED_DIRNAME, "nodeRegisteredFunctions.ts"),
|
|
40
|
+
path.join(GENERATED_DIRNAME, "impl.ts"),
|
|
41
|
+
path.join(GENERATED_DIRNAME, "nodeImpl.ts"),
|
|
42
|
+
path.join(GENERATED_DIRNAME, "nodeSpec.ts")
|
|
43
|
+
];
|
|
44
|
+
});
|
|
33
45
|
const codegen = Command.make("codegen", {}, () => Effect.gen(function* () {
|
|
34
46
|
yield* logPending("Performing initial sync…");
|
|
35
47
|
yield* codegenHandler.pipe(Effect.asVoid, Effect.tap(() => logSuccess("Generated files are up-to-date")), tapAndLog);
|
|
@@ -43,23 +55,31 @@ const codegenHandler = Effect.gen(function* () {
|
|
|
43
55
|
});
|
|
44
56
|
const runCodegen = Effect.gen(function* () {
|
|
45
57
|
yield* generateConfectGeneratedDirectory;
|
|
46
|
-
yield*
|
|
58
|
+
yield* rejectLegacySchemaFile;
|
|
59
|
+
const tableModules = yield* discover;
|
|
60
|
+
yield* warnIfNoTables(tableModules);
|
|
61
|
+
yield* generateIdConstructor(tableModules);
|
|
62
|
+
yield* validate(tableModules);
|
|
63
|
+
yield* generateTableWrappers(tableModules);
|
|
64
|
+
yield* removeObsoleteTableWrappers(tableModules);
|
|
65
|
+
yield* generateRuntimeSchema(tableModules);
|
|
47
66
|
const { leaves, groupSpecsByRelativePath } = yield* loadAndValidateLeafModules;
|
|
48
67
|
yield* removeLegacyFiles;
|
|
49
68
|
yield* validateNoParentChildNameCollisions(leaves, groupSpecsByRelativePath);
|
|
50
69
|
yield* generateAssembledSpecs(leaves);
|
|
51
|
-
yield* validateImplModules(leaves);
|
|
52
|
-
yield* generateGroupRegisteredFunctions(leaves);
|
|
53
|
-
yield* removeObsoleteRegisteredFunctions(leaves);
|
|
54
70
|
yield* Effect.all([
|
|
55
|
-
|
|
71
|
+
removeGeneratedApi,
|
|
56
72
|
generateRefs,
|
|
57
|
-
|
|
58
|
-
generateServices
|
|
73
|
+
removeGeneratedNodeApi,
|
|
74
|
+
generateServices,
|
|
75
|
+
generateConvexSchema(tableModules)
|
|
59
76
|
], { concurrency: "unbounded" });
|
|
77
|
+
yield* validateImplModules(leaves);
|
|
78
|
+
yield* generateGroupRegisteredFunctions(leaves);
|
|
79
|
+
yield* removeObsoleteRegisteredFunctions(leaves);
|
|
60
80
|
const [functionPaths] = yield* Effect.all([
|
|
61
81
|
generateFunctionModules,
|
|
62
|
-
|
|
82
|
+
generateConvexSchemaReexport,
|
|
63
83
|
logGenerated(generateHttp),
|
|
64
84
|
logGenerated(generateCrons),
|
|
65
85
|
logGenerated(generateAuthConfig)
|
|
@@ -82,8 +102,12 @@ const loadAndValidateLeafModules = Effect.gen(function* () {
|
|
|
82
102
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
83
103
|
const specFiles = yield* discoverLeafSpecFiles;
|
|
84
104
|
const results = yield* Effect.forEach(specFiles, (specRelativePath) => Effect.gen(function* () {
|
|
85
|
-
const
|
|
86
|
-
const groupSpec = yield* validateSpec(
|
|
105
|
+
const discovered = yield* toLeafModule(specRelativePath);
|
|
106
|
+
const groupSpec = yield* validateSpec(discovered);
|
|
107
|
+
const leaf = {
|
|
108
|
+
...discovered,
|
|
109
|
+
runtime: Option.some(groupSpec.runtime)
|
|
110
|
+
};
|
|
87
111
|
const implRelativePath = yield* implPathForSpec(specRelativePath);
|
|
88
112
|
const implAbsolutePath = path.join(confectDirectory, implRelativePath);
|
|
89
113
|
if (!(yield* fs.exists(implAbsolutePath))) return yield* new MissingImplFileError({
|
|
@@ -110,11 +134,8 @@ const loadAndValidateLeafModules = Effect.gen(function* () {
|
|
|
110
134
|
* `Refs.make` error rather than a codegen-time diagnostic.
|
|
111
135
|
*/
|
|
112
136
|
const validateNoParentChildNameCollisions = (leaves, groupSpecsByRelativePath) => Effect.gen(function* () {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
const nodeNodes = assemblyNodesFromLeaves(Array.map(node, toNodeRegistryLeaf));
|
|
116
|
-
yield* Effect.forEach(convexNodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
|
|
117
|
-
yield* Effect.forEach(nodeNodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
|
|
137
|
+
const nodes = assemblyNodesFromLeaves(leaves);
|
|
138
|
+
yield* Effect.forEach(nodes, (n) => checkAssemblyNodeForCollisions(n, groupSpecsByRelativePath));
|
|
118
139
|
});
|
|
119
140
|
const checkAssemblyNodeForCollisions = (node, groupSpecsByRelativePath) => Effect.gen(function* () {
|
|
120
141
|
yield* Option.match(node.importBinding, {
|
|
@@ -184,7 +205,8 @@ const removeLegacyFiles = Effect.gen(function* () {
|
|
|
184
205
|
const fs = yield* FileSystem.FileSystem;
|
|
185
206
|
const path = yield* Path.Path;
|
|
186
207
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
187
|
-
|
|
208
|
+
const legacyPaths = yield* LEGACY_PATHS;
|
|
209
|
+
yield* Effect.forEach(legacyPaths, (relativePath) => Effect.gen(function* () {
|
|
188
210
|
const absolutePath = path.join(confectDirectory, relativePath);
|
|
189
211
|
if (yield* fs.exists(absolutePath)) {
|
|
190
212
|
yield* removePathIfExists(absolutePath);
|
|
@@ -195,23 +217,10 @@ const removeLegacyFiles = Effect.gen(function* () {
|
|
|
195
217
|
const generateAssembledSpecs = (leaves) => Effect.gen(function* () {
|
|
196
218
|
const path = yield* Path.Path;
|
|
197
219
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
nodes,
|
|
203
|
-
runtime: "Convex"
|
|
204
|
-
});
|
|
205
|
-
yield* writeFileStringAndLog(path.join(confectDirectory, GENERATED_SPEC_PATH), specContents);
|
|
206
|
-
}
|
|
207
|
-
if (node.length > 0) {
|
|
208
|
-
const nodes = assemblyNodesFromLeaves(Array.map(node, toNodeRegistryLeaf));
|
|
209
|
-
const nodeSpecContents = yield* assembledSpec({
|
|
210
|
-
nodes,
|
|
211
|
-
runtime: "Node"
|
|
212
|
-
});
|
|
213
|
-
yield* writeFileStringAndLog(path.join(confectDirectory, GENERATED_NODE_SPEC_PATH), nodeSpecContents);
|
|
214
|
-
}
|
|
220
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
221
|
+
const nodes = assemblyNodesFromLeaves(leaves);
|
|
222
|
+
const specContents = yield* assembledSpec({ nodes });
|
|
223
|
+
yield* writeFileStringAndLog(path.join(confectDirectory, generatedSpecPath), specContents);
|
|
215
224
|
});
|
|
216
225
|
const validateImplModules = (leaves) => Effect.forEach(leaves, validateImpl);
|
|
217
226
|
const generateGroupRegisteredFunctions = (leaves) => Effect.gen(function* () {
|
|
@@ -224,15 +233,19 @@ const generateGroupRegisteredFunctions = (leaves) => Effect.gen(function* () {
|
|
|
224
233
|
const fs = yield* FileSystem.FileSystem;
|
|
225
234
|
if (!(yield* fs.exists(registryDir))) yield* fs.makeDirectory(registryDir, { recursive: true });
|
|
226
235
|
const implRelativePath = yield* implPathForSpec(leaf.relativePath);
|
|
227
|
-
const
|
|
228
|
-
const
|
|
236
|
+
const schemaImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, "_generated", "schema.ts")));
|
|
237
|
+
const specImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, leaf.relativePath)));
|
|
229
238
|
const implImportPath = yield* toModuleImportPath(path.relative(path.dirname(registryPath), path.join(confectDirectory, implRelativePath)));
|
|
239
|
+
const runtime = yield* Option.match(leaf.runtime, {
|
|
240
|
+
onNone: () => Effect.dieMessage(`Runtime for '${leaf.relativePath}' was not resolved before registry generation.`),
|
|
241
|
+
onSome: Effect.succeed
|
|
242
|
+
});
|
|
230
243
|
yield* writeFileStringAndLog(registryPath, yield* registeredFunctionsForGroup({
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
schemaImportPath,
|
|
245
|
+
specImportPath,
|
|
233
246
|
implImportPath,
|
|
234
247
|
layerExportName: leaf.exportName,
|
|
235
|
-
useNode:
|
|
248
|
+
useNode: runtime === "Node"
|
|
236
249
|
}));
|
|
237
250
|
}));
|
|
238
251
|
});
|
|
@@ -260,130 +273,178 @@ const removeObsoleteRegisteredFunctions = (leaves) => Effect.gen(function* () {
|
|
|
260
273
|
const getGeneratedSpecPath = Effect.gen(function* () {
|
|
261
274
|
const path = yield* Path.Path;
|
|
262
275
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
const getGeneratedNodeSpecPath = Effect.gen(function* () {
|
|
266
|
-
const path = yield* Path.Path;
|
|
267
|
-
const confectDirectory = yield* ConfectDirectory.get;
|
|
268
|
-
return path.join(confectDirectory, GENERATED_NODE_SPEC_PATH);
|
|
276
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
277
|
+
return path.join(confectDirectory, generatedSpecPath);
|
|
269
278
|
});
|
|
270
279
|
const loadGeneratedSpec = Effect.gen(function* () {
|
|
271
280
|
const specPath = yield* getGeneratedSpecPath;
|
|
272
281
|
const { module: specModule } = yield* bundle(specPath);
|
|
273
282
|
const spec = specModule.default;
|
|
274
|
-
if (!Spec.
|
|
283
|
+
if (!Spec.isSpec(spec)) return yield* Effect.dieMessage("_generated/spec.ts does not export a valid Spec");
|
|
275
284
|
return spec;
|
|
276
285
|
});
|
|
277
|
-
const loadGeneratedNodeSpec = Effect.gen(function* () {
|
|
278
|
-
const fs = yield* FileSystem.FileSystem;
|
|
279
|
-
const nodeSpecPath = yield* getGeneratedNodeSpecPath;
|
|
280
|
-
if (!(yield* fs.exists(nodeSpecPath))) return Option.none();
|
|
281
|
-
const { module: nodeSpecModule } = yield* bundle(nodeSpecPath);
|
|
282
|
-
const nodeSpec = nodeSpecModule.default;
|
|
283
|
-
if (!Spec.isNodeSpec(nodeSpec)) return yield* Effect.dieMessage("_generated/nodeSpec.ts does not export a valid Node Spec");
|
|
284
|
-
return Option.some(nodeSpec);
|
|
285
|
-
});
|
|
286
286
|
const emptyFunctionPaths = FunctionPaths.make(HashSet.empty());
|
|
287
287
|
const loadPreviousFunctionPaths = Effect.gen(function* () {
|
|
288
288
|
const fs = yield* FileSystem.FileSystem;
|
|
289
289
|
const specPath = yield* getGeneratedSpecPath;
|
|
290
290
|
if (!(yield* fs.exists(specPath))) return emptyFunctionPaths;
|
|
291
291
|
const specEither = yield* loadGeneratedSpec.pipe(Effect.either);
|
|
292
|
-
return
|
|
293
|
-
onLeft: () =>
|
|
294
|
-
onRight: (spec) =>
|
|
295
|
-
const nodeSpecOption = yield* loadGeneratedNodeSpec;
|
|
296
|
-
const mergedSpec = Option.match(nodeSpecOption, {
|
|
297
|
-
onNone: () => spec,
|
|
298
|
-
onSome: (nodeSpec) => Spec.merge(spec, nodeSpec)
|
|
299
|
-
});
|
|
300
|
-
return make(mergedSpec);
|
|
301
|
-
})
|
|
292
|
+
return Either.match(specEither, {
|
|
293
|
+
onLeft: () => emptyFunctionPaths,
|
|
294
|
+
onRight: (spec) => make(spec)
|
|
302
295
|
});
|
|
303
296
|
});
|
|
304
|
-
|
|
297
|
+
/**
|
|
298
|
+
* Remove a now-obsolete `_generated/<name>.ts` if present (and log it), for
|
|
299
|
+
* projects upgrading from a version that still emitted it.
|
|
300
|
+
*/
|
|
301
|
+
const removeObsoleteGeneratedFile = (fileName) => Effect.gen(function* () {
|
|
302
|
+
const fs = yield* FileSystem.FileSystem;
|
|
305
303
|
const path = yield* Path.Path;
|
|
306
304
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
305
|
+
const filePath = path.join(confectDirectory, "_generated", fileName);
|
|
306
|
+
if (yield* fs.exists(filePath)) {
|
|
307
|
+
yield* removePathIfExists(filePath);
|
|
308
|
+
yield* logFileRemoved(filePath);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
const removeGeneratedApi = removeObsoleteGeneratedFile("api.ts");
|
|
312
|
+
const removeGeneratedNodeApi = removeObsoleteGeneratedFile("nodeApi.ts");
|
|
313
|
+
const generateFunctionModules = Effect.gen(function* () {
|
|
314
|
+
return yield* generateFunctions(yield* loadGeneratedSpec);
|
|
315
315
|
});
|
|
316
|
-
|
|
316
|
+
/**
|
|
317
|
+
* The user-authored `confect/schema.ts` is no longer supported: codegen now
|
|
318
|
+
* owns both `_generated/schema.ts` (runtime) and `_generated/convexSchema.ts`
|
|
319
|
+
* (deploy), derived from a single scan of `confect/tables/*.ts`. Detect a
|
|
320
|
+
* stray file and fail with a clear migration message — leaving it in place
|
|
321
|
+
* would silently shadow the codegen-owned `_generated/schema.ts` /
|
|
322
|
+
* `_generated/convexSchema.ts`.
|
|
323
|
+
*/
|
|
324
|
+
const rejectLegacySchemaFile = Effect.gen(function* () {
|
|
317
325
|
const fs = yield* FileSystem.FileSystem;
|
|
318
326
|
const path = yield* Path.Path;
|
|
319
327
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
if (!(yield* fs.exists(nodeSpecPath))) {
|
|
323
|
-
if (yield* fs.exists(nodeApiPath)) {
|
|
324
|
-
yield* removePathIfExists(nodeApiPath);
|
|
325
|
-
yield* logFileRemoved(nodeApiPath);
|
|
326
|
-
}
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
const nodeApiDir = path.dirname(nodeApiPath);
|
|
330
|
-
const schemaImportPath = yield* toModuleImportPath(path.relative(nodeApiDir, path.join(confectDirectory, "schema.ts")));
|
|
331
|
-
const nodeSpecImportPath = yield* toModuleImportPath(path.relative(nodeApiDir, nodeSpecPath));
|
|
332
|
-
yield* writeFileStringAndLog(nodeApiPath, yield* nodeApi({
|
|
333
|
-
schemaImportPath,
|
|
334
|
-
nodeSpecImportPath
|
|
335
|
-
}));
|
|
328
|
+
const legacyPath = path.join(confectDirectory, "schema.ts");
|
|
329
|
+
if (yield* fs.exists(legacyPath)) return yield* new LegacySchemaFileError({ schemaPath: "schema.ts" });
|
|
336
330
|
});
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Surface a yellow `⚠` warning when codegen sees no tables — either the
|
|
333
|
+
* `confect/tables/` directory is missing or it contains no `.ts` files.
|
|
334
|
+
* Generation still succeeds (emitting an empty `DatabaseSchema` and
|
|
335
|
+
* `defineSchema({})`), since action-only / table-free Confect backends
|
|
336
|
+
* are legal — but the warning catches the much more common case of a
|
|
337
|
+
* typoed directory or files placed under the wrong root.
|
|
338
|
+
*/
|
|
339
|
+
const warnIfNoTables = (tableModules) => tableModules.length === 0 ? logWarn(`No tables discovered in \`confect/${TABLES_DIRNAME}/\`. Generating an empty schema; add a \`Table.make(...)\` module under that directory unless this backend is intentionally tables-free.`) : Effect.void;
|
|
340
|
+
const tableModuleBindings = (tableModules, generatedFilePath) => Effect.gen(function* () {
|
|
341
|
+
const path = yield* Path.Path;
|
|
342
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
343
|
+
const generatedDir = path.dirname(generatedFilePath);
|
|
344
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
345
|
+
return yield* Effect.forEach(tableModules, (tm) => Effect.gen(function* () {
|
|
346
|
+
const wrapperAbsolutePath = path.join(confectDirectory, generatedTablesDirname, `${tm.tableName}.ts`);
|
|
347
|
+
return {
|
|
348
|
+
importPath: yield* toModuleImportPath(path.relative(generatedDir, wrapperAbsolutePath)),
|
|
349
|
+
tableName: tm.tableName
|
|
350
|
+
};
|
|
343
351
|
}));
|
|
344
352
|
});
|
|
345
|
-
const
|
|
353
|
+
const generateIdConstructor = (tableModules) => Effect.gen(function* () {
|
|
354
|
+
const path = yield* Path.Path;
|
|
355
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
356
|
+
const generatedIdPath = yield* GENERATED_ID_PATH;
|
|
357
|
+
const idPath = path.join(confectDirectory, generatedIdPath);
|
|
358
|
+
const tableNames = tableModules.map((tm) => tm.tableName);
|
|
359
|
+
yield* writeFileStringAndLog(idPath, yield* id({ tableNames }));
|
|
360
|
+
});
|
|
361
|
+
const generateTableWrappers = (tableModules) => Effect.gen(function* () {
|
|
346
362
|
const fs = yield* FileSystem.FileSystem;
|
|
347
363
|
const path = yield* Path.Path;
|
|
348
364
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
yield*
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
365
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
366
|
+
const wrappersDir = path.join(confectDirectory, generatedTablesDirname);
|
|
367
|
+
if (!(yield* fs.exists(wrappersDir))) yield* fs.makeDirectory(wrappersDir, { recursive: true });
|
|
368
|
+
yield* Effect.forEach(tableModules, (tm) => Effect.gen(function* () {
|
|
369
|
+
const wrapperPath = path.join(confectDirectory, generatedTablesDirname, `${tm.tableName}.ts`);
|
|
370
|
+
const unnamedAbsolutePath = path.join(confectDirectory, tm.relativePath);
|
|
371
|
+
const unnamedImportPath = yield* toModuleImportPath(path.relative(path.dirname(wrapperPath), unnamedAbsolutePath));
|
|
372
|
+
yield* writeFileStringAndLog(wrapperPath, yield* tableWrapper({
|
|
373
|
+
tableName: tm.tableName,
|
|
374
|
+
unnamedImportPath
|
|
375
|
+
}));
|
|
376
|
+
}), { concurrency: "unbounded" });
|
|
377
|
+
});
|
|
378
|
+
/**
|
|
379
|
+
* Remove any stale `_generated/tables/*.ts` wrapper whose source table
|
|
380
|
+
* has been deleted or renamed. Mirrors `removeObsoleteRegisteredFunctions`
|
|
381
|
+
* for the wrapper directory.
|
|
382
|
+
*/
|
|
383
|
+
const removeObsoleteTableWrappers = (tableModules) => Effect.gen(function* () {
|
|
384
|
+
const fs = yield* FileSystem.FileSystem;
|
|
385
|
+
const path = yield* Path.Path;
|
|
386
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
387
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
388
|
+
const wrappersDir = path.join(confectDirectory, generatedTablesDirname);
|
|
389
|
+
if (!(yield* fs.exists(wrappersDir))) return;
|
|
390
|
+
const expected = new Set(tableModules.map((tm) => `${tm.tableName}.ts`));
|
|
391
|
+
const existing = yield* fs.readDirectory(wrappersDir, { recursive: true });
|
|
392
|
+
yield* Effect.forEach(existing, (entry) => {
|
|
393
|
+
if (path.extname(entry) !== ".ts") return Effect.void;
|
|
394
|
+
if (!expected.has(entry)) return Effect.gen(function* () {
|
|
395
|
+
const absolutePath = path.join(wrappersDir, entry);
|
|
396
|
+
if (yield* fs.exists(absolutePath)) {
|
|
397
|
+
yield* removePathIfExists(absolutePath);
|
|
398
|
+
yield* logFileRemoved(absolutePath);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
return Effect.void;
|
|
402
|
+
});
|
|
355
403
|
});
|
|
356
|
-
const
|
|
404
|
+
const generateRuntimeSchema = (tableModules) => Effect.gen(function* () {
|
|
405
|
+
const path = yield* Path.Path;
|
|
406
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
407
|
+
const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;
|
|
408
|
+
const schemaPath = path.join(confectDirectory, generatedSchemaPath);
|
|
409
|
+
const bindings = yield* tableModuleBindings(tableModules, schemaPath);
|
|
410
|
+
yield* writeFileStringAndLog(schemaPath, yield* runtimeSchema({ tableModules: bindings }));
|
|
411
|
+
});
|
|
412
|
+
const generateConvexSchema = (tableModules) => Effect.gen(function* () {
|
|
413
|
+
const path = yield* Path.Path;
|
|
414
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
415
|
+
const generatedConvexSchemaPath = yield* GENERATED_CONVEX_SCHEMA_PATH;
|
|
416
|
+
const convexSchemaPath = path.join(confectDirectory, generatedConvexSchemaPath);
|
|
417
|
+
const bindings = yield* tableModuleBindings(tableModules, convexSchemaPath);
|
|
418
|
+
yield* writeFileStringAndLog(convexSchemaPath, yield* convexSchema({ tableModules: bindings }));
|
|
419
|
+
});
|
|
420
|
+
const generateConvexSchemaReexport = Effect.gen(function* () {
|
|
357
421
|
const path = yield* Path.Path;
|
|
358
422
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
359
423
|
const convexDirectory = yield* ConvexDirectory.get;
|
|
360
|
-
const
|
|
424
|
+
const generatedConvexSchemaRelativePath = yield* GENERATED_CONVEX_SCHEMA_PATH;
|
|
361
425
|
const convexSchemaPath = path.join(convexDirectory, "schema.ts");
|
|
362
|
-
const
|
|
363
|
-
yield*
|
|
426
|
+
const generatedConvexSchemaPath = path.join(confectDirectory, generatedConvexSchemaRelativePath);
|
|
427
|
+
const convexSchemaImportPath = yield* toModuleImportPath(path.relative(path.dirname(convexSchemaPath), generatedConvexSchemaPath));
|
|
428
|
+
yield* writeFileStringAndLog(convexSchemaPath, yield* schema({ convexSchemaImportPath }));
|
|
364
429
|
});
|
|
365
430
|
const generateServices = Effect.gen(function* () {
|
|
366
431
|
const path = yield* Path.Path;
|
|
367
432
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
368
433
|
const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
|
|
369
434
|
const servicesPath = path.join(confectGeneratedDirectory, "services.ts");
|
|
370
|
-
const
|
|
435
|
+
const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;
|
|
436
|
+
const schemaImportPath = yield* toModuleImportPath(path.relative(path.dirname(servicesPath), path.join(confectDirectory, generatedSchemaPath)));
|
|
371
437
|
yield* writeFileStringAndLog(servicesPath, yield* services({ schemaImportPath }));
|
|
372
438
|
});
|
|
373
439
|
const generateRefs = Effect.gen(function* () {
|
|
374
|
-
const fs = yield* FileSystem.FileSystem;
|
|
375
440
|
const path = yield* Path.Path;
|
|
376
441
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
377
442
|
const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
|
|
378
443
|
const refsPath = path.join(confectGeneratedDirectory, "refs.ts");
|
|
379
444
|
const refsDir = path.dirname(refsPath);
|
|
380
|
-
const
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
yield* writeFileStringAndLog(refsPath, yield* refs({
|
|
384
|
-
specImportPath,
|
|
385
|
-
nodeSpecImportPath
|
|
386
|
-
}));
|
|
445
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
446
|
+
const specImportPath = yield* toModuleImportPath(path.relative(refsDir, path.join(confectDirectory, generatedSpecPath)));
|
|
447
|
+
yield* writeFileStringAndLog(refsPath, yield* refs({ specImportPath }));
|
|
387
448
|
});
|
|
388
449
|
const logGenerated = (effect) => effect.pipe(Effect.tap(Option.match({
|
|
389
450
|
onNone: () => Effect.void,
|