@confect/cli 9.0.0-next.4 → 9.0.0-next.6
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 +178 -0
- package/dist/Bundler.mjs +63 -72
- package/dist/Bundler.mjs.map +1 -1
- package/dist/CodegenError.mjs +22 -9
- package/dist/CodegenError.mjs.map +1 -1
- package/dist/LeafModule.mjs +2 -2
- package/dist/LeafModule.mjs.map +1 -1
- package/dist/SpecAssemblyNode.mjs +1 -19
- package/dist/SpecAssemblyNode.mjs.map +1 -1
- package/dist/TableModule.mjs +90 -0
- package/dist/TableModule.mjs.map +1 -0
- package/dist/confect/codegen.mjs +175 -78
- package/dist/confect/codegen.mjs.map +1 -1
- package/dist/confect/dev.mjs +15 -12
- package/dist/confect/dev.mjs.map +1 -1
- package/dist/log.mjs +4 -3
- package/dist/log.mjs.map +1 -1
- package/dist/package.mjs +1 -1
- package/dist/templates.mjs +123 -34
- package/dist/templates.mjs.map +1 -1
- package/package.json +42 -42
- package/src/Bundler.ts +67 -90
- package/src/CodegenError.ts +90 -28
- package/src/LeafModule.ts +1 -1
- package/src/SpecAssemblyNode.ts +0 -36
- package/src/TableModule.ts +153 -0
- package/src/confect/codegen.ts +323 -132
- package/src/confect/dev.ts +52 -10
- package/src/log.ts +4 -2
- package/src/templates.ts +200 -59
package/src/confect/codegen.ts
CHANGED
|
@@ -1,27 +1,18 @@
|
|
|
1
|
-
import { type GroupSpec
|
|
2
|
-
import * as DatabaseSchema from "@confect/server/DatabaseSchema";
|
|
1
|
+
import { Spec, type GroupSpec } from "@confect/core";
|
|
3
2
|
import { Command } from "@effect/cli";
|
|
4
3
|
import { FileSystem, Path } from "@effect/platform";
|
|
5
4
|
import { Array, Effect, Either, HashSet, Match, Option, Ref } from "effect";
|
|
6
|
-
import
|
|
5
|
+
import * as Bundler from "../Bundler";
|
|
7
6
|
import * as CodegenError from "../CodegenError";
|
|
8
7
|
import {
|
|
8
|
+
LegacySchemaFileError,
|
|
9
9
|
MissingImplFileError,
|
|
10
|
-
MissingSchemaFileError,
|
|
11
10
|
MissingSpecFileError,
|
|
12
11
|
ParentChildNameCollisionError,
|
|
13
|
-
SchemaInvalidDefaultExportError,
|
|
14
12
|
} from "../CodegenError";
|
|
15
13
|
import { ConfectDirectory } from "../ConfectDirectory";
|
|
16
14
|
import { ConvexDirectory } from "../ConvexDirectory";
|
|
17
15
|
import * as FunctionPaths from "../FunctionPaths";
|
|
18
|
-
import {
|
|
19
|
-
logFileAdded,
|
|
20
|
-
logFileModified,
|
|
21
|
-
logFileRemoved,
|
|
22
|
-
logPending,
|
|
23
|
-
logSuccess,
|
|
24
|
-
} from "../log";
|
|
25
16
|
import {
|
|
26
17
|
discoverLeafImplFiles,
|
|
27
18
|
discoverLeafSpecFiles,
|
|
@@ -34,19 +25,26 @@ import {
|
|
|
34
25
|
validateSpec,
|
|
35
26
|
type LeafModule,
|
|
36
27
|
} from "../LeafModule";
|
|
28
|
+
import {
|
|
29
|
+
logFileAdded,
|
|
30
|
+
logFileModified,
|
|
31
|
+
logFileRemoved,
|
|
32
|
+
logPending,
|
|
33
|
+
logSuccess,
|
|
34
|
+
logWarn,
|
|
35
|
+
} from "../log";
|
|
37
36
|
import {
|
|
38
37
|
assemblyNodesFromLeaves,
|
|
39
38
|
partitionByRuntime,
|
|
40
39
|
type SpecAssemblyNode,
|
|
41
40
|
} from "../SpecAssemblyNode";
|
|
41
|
+
import * as TableModule from "../TableModule";
|
|
42
42
|
import * as templates from "../templates";
|
|
43
|
-
import * as Bundler from "../Bundler";
|
|
44
43
|
import {
|
|
45
44
|
generateAuthConfig,
|
|
46
45
|
generateCrons,
|
|
47
46
|
generateFunctions,
|
|
48
47
|
generateHttp,
|
|
49
|
-
removePathExtension,
|
|
50
48
|
removePathIfExists,
|
|
51
49
|
toModuleImportPath,
|
|
52
50
|
touchConvexSchema,
|
|
@@ -54,21 +52,41 @@ import {
|
|
|
54
52
|
WriteTracker,
|
|
55
53
|
} from "../utils";
|
|
56
54
|
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
const GENERATED_DIRNAME = "_generated";
|
|
56
|
+
|
|
57
|
+
const GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) =>
|
|
58
|
+
path.join(GENERATED_DIRNAME, "spec.ts"),
|
|
59
|
+
);
|
|
60
|
+
const GENERATED_NODE_SPEC_PATH = Effect.andThen(Path.Path, (path) =>
|
|
61
|
+
path.join(GENERATED_DIRNAME, "nodeSpec.ts"),
|
|
62
|
+
);
|
|
63
|
+
const GENERATED_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>
|
|
64
|
+
path.join(GENERATED_DIRNAME, "schema.ts"),
|
|
65
|
+
);
|
|
66
|
+
const GENERATED_CONVEX_SCHEMA_PATH = Effect.andThen(Path.Path, (path) =>
|
|
67
|
+
path.join(GENERATED_DIRNAME, "convexSchema.ts"),
|
|
68
|
+
);
|
|
69
|
+
const GENERATED_ID_PATH = Effect.andThen(Path.Path, (path) =>
|
|
70
|
+
path.join(GENERATED_DIRNAME, "id.ts"),
|
|
71
|
+
);
|
|
72
|
+
const GENERATED_TABLES_DIRNAME = Effect.andThen(Path.Path, (path) =>
|
|
73
|
+
path.join(GENERATED_DIRNAME, "tables"),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const LEGACY_PATHS = Effect.gen(function* () {
|
|
77
|
+
const path = yield* Path.Path;
|
|
78
|
+
|
|
79
|
+
return [
|
|
80
|
+
"spec.ts",
|
|
81
|
+
"nodeSpec.ts",
|
|
82
|
+
"impl.ts",
|
|
83
|
+
"nodeImpl.ts",
|
|
84
|
+
path.join(GENERATED_DIRNAME, "registeredFunctions.ts"),
|
|
85
|
+
path.join(GENERATED_DIRNAME, "nodeRegisteredFunctions.ts"),
|
|
86
|
+
path.join(GENERATED_DIRNAME, "impl.ts"),
|
|
87
|
+
path.join(GENERATED_DIRNAME, "nodeImpl.ts"),
|
|
88
|
+
];
|
|
89
|
+
});
|
|
72
90
|
|
|
73
91
|
export const codegen = Command.make("codegen", {}, () =>
|
|
74
92
|
Effect.gen(function* () {
|
|
@@ -98,27 +116,50 @@ export const codegenHandler = Effect.gen(function* () {
|
|
|
98
116
|
|
|
99
117
|
const runCodegen = Effect.gen(function* () {
|
|
100
118
|
yield* generateConfectGeneratedDirectory;
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
119
|
+
// Reject a legacy `confect/schema.ts` up front so the user-facing
|
|
120
|
+
// migration message surfaces before any bundler error from impl
|
|
121
|
+
// validation (each impl imports `_generated/schema.ts`).
|
|
122
|
+
yield* rejectLegacySchemaFile;
|
|
123
|
+
// List `confect/tables/*.ts` (filename-only — no bundling yet) so the
|
|
124
|
+
// `_generated/id.ts` constructor can be emitted *before* we bundle any
|
|
125
|
+
// user-authored table module. Tables import from `_generated/id.ts` for
|
|
126
|
+
// cross-table id refs, so it must exist on disk first.
|
|
127
|
+
const tableModules = yield* TableModule.discover;
|
|
128
|
+
yield* warnIfNoTables(tableModules);
|
|
129
|
+
yield* generateIdConstructor(tableModules);
|
|
130
|
+
// Now that `_generated/id.ts` is on disk, bundle each table module and
|
|
131
|
+
// check its default export is an `UnnamedTable`. Surface diagnostics
|
|
132
|
+
// here (rather than later) so they appear before impl-validation noise.
|
|
133
|
+
yield* TableModule.validate(tableModules);
|
|
134
|
+
yield* generateTableWrappers(tableModules);
|
|
135
|
+
yield* removeObsoleteTableWrappers(tableModules);
|
|
136
|
+
yield* generateRuntimeSchema(tableModules);
|
|
106
137
|
const { leaves, groupSpecsByRelativePath } =
|
|
107
138
|
yield* loadAndValidateLeafModules;
|
|
108
139
|
yield* removeLegacyFiles;
|
|
109
140
|
yield* validateNoParentChildNameCollisions(leaves, groupSpecsByRelativePath);
|
|
110
141
|
yield* generateAssembledSpecs(leaves);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
142
|
+
// `_generated/api.ts` / `nodeApi.ts` are no longer imported by generated or
|
|
143
|
+
// impl code (impls take the database schema from `_generated/schema`
|
|
144
|
+
// directly), so remove any copies left over from earlier versions before
|
|
145
|
+
// impl validation runs.
|
|
114
146
|
yield* Effect.all(
|
|
115
|
-
[
|
|
147
|
+
[
|
|
148
|
+
removeGeneratedApi,
|
|
149
|
+
generateRefs,
|
|
150
|
+
removeGeneratedNodeApi,
|
|
151
|
+
generateServices,
|
|
152
|
+
generateConvexSchema(tableModules),
|
|
153
|
+
],
|
|
116
154
|
{ concurrency: "unbounded" },
|
|
117
155
|
);
|
|
156
|
+
yield* validateImplModules(leaves);
|
|
157
|
+
yield* generateGroupRegisteredFunctions(leaves);
|
|
158
|
+
yield* removeObsoleteRegisteredFunctions(leaves);
|
|
118
159
|
const [functionPaths] = yield* Effect.all(
|
|
119
160
|
[
|
|
120
161
|
generateFunctionModules,
|
|
121
|
-
|
|
162
|
+
generateConvexSchemaReexport,
|
|
122
163
|
logGenerated(generateHttp),
|
|
123
164
|
logGenerated(generateCrons),
|
|
124
165
|
logGenerated(generateAuthConfig),
|
|
@@ -318,8 +359,9 @@ const removeLegacyFiles = Effect.gen(function* () {
|
|
|
318
359
|
const fs = yield* FileSystem.FileSystem;
|
|
319
360
|
const path = yield* Path.Path;
|
|
320
361
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
362
|
+
const legacyPaths = yield* LEGACY_PATHS;
|
|
321
363
|
|
|
322
|
-
yield* Effect.forEach(
|
|
364
|
+
yield* Effect.forEach(legacyPaths, (relativePath) =>
|
|
323
365
|
Effect.gen(function* () {
|
|
324
366
|
const absolutePath = path.join(confectDirectory, relativePath);
|
|
325
367
|
if (yield* fs.exists(absolutePath)) {
|
|
@@ -334,6 +376,8 @@ const generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
334
376
|
Effect.gen(function* () {
|
|
335
377
|
const path = yield* Path.Path;
|
|
336
378
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
379
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
380
|
+
const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
|
|
337
381
|
const { convex, node } = partitionByRuntime(leaves);
|
|
338
382
|
|
|
339
383
|
if (convex.length > 0) {
|
|
@@ -343,7 +387,7 @@ const generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
343
387
|
runtime: "Convex",
|
|
344
388
|
});
|
|
345
389
|
yield* writeFileStringAndLog(
|
|
346
|
-
path.join(confectDirectory,
|
|
390
|
+
path.join(confectDirectory, generatedSpecPath),
|
|
347
391
|
specContents,
|
|
348
392
|
);
|
|
349
393
|
}
|
|
@@ -357,7 +401,7 @@ const generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
357
401
|
runtime: "Node",
|
|
358
402
|
});
|
|
359
403
|
yield* writeFileStringAndLog(
|
|
360
|
-
path.join(confectDirectory,
|
|
404
|
+
path.join(confectDirectory, generatedNodeSpecPath),
|
|
361
405
|
nodeSpecContents,
|
|
362
406
|
);
|
|
363
407
|
}
|
|
@@ -387,11 +431,18 @@ const generateGroupRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
387
431
|
}
|
|
388
432
|
|
|
389
433
|
const implRelativePath = yield* implPathForSpec(leaf.relativePath);
|
|
390
|
-
const
|
|
391
|
-
|
|
434
|
+
const schemaImportPath = yield* toModuleImportPath(
|
|
435
|
+
path.relative(
|
|
436
|
+
path.dirname(registryPath),
|
|
437
|
+
path.join(confectDirectory, "_generated", "schema.ts"),
|
|
438
|
+
),
|
|
439
|
+
);
|
|
440
|
+
// The group's own leaf spec (sibling of its impl), referenced
|
|
441
|
+
// type-only by the registry to shape its returned record.
|
|
442
|
+
const specImportPath = yield* toModuleImportPath(
|
|
392
443
|
path.relative(
|
|
393
444
|
path.dirname(registryPath),
|
|
394
|
-
path.join(confectDirectory,
|
|
445
|
+
path.join(confectDirectory, leaf.relativePath),
|
|
395
446
|
),
|
|
396
447
|
);
|
|
397
448
|
const implImportPath = yield* toModuleImportPath(
|
|
@@ -402,8 +453,8 @@ const generateGroupRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
402
453
|
);
|
|
403
454
|
|
|
404
455
|
const contents = yield* templates.registeredFunctionsForGroup({
|
|
405
|
-
|
|
406
|
-
|
|
456
|
+
schemaImportPath,
|
|
457
|
+
specImportPath,
|
|
407
458
|
implImportPath,
|
|
408
459
|
layerExportName: leaf.exportName,
|
|
409
460
|
useNode: leaf.runtime === "Node",
|
|
@@ -457,13 +508,15 @@ const removeObsoleteRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>
|
|
|
457
508
|
const getGeneratedSpecPath = Effect.gen(function* () {
|
|
458
509
|
const path = yield* Path.Path;
|
|
459
510
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
460
|
-
|
|
511
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
512
|
+
return path.join(confectDirectory, generatedSpecPath);
|
|
461
513
|
});
|
|
462
514
|
|
|
463
515
|
const getGeneratedNodeSpecPath = Effect.gen(function* () {
|
|
464
516
|
const path = yield* Path.Path;
|
|
465
517
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
466
|
-
|
|
518
|
+
const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
|
|
519
|
+
return path.join(confectDirectory, generatedNodeSpecPath);
|
|
467
520
|
});
|
|
468
521
|
|
|
469
522
|
const loadGeneratedSpec = Effect.gen(function* () {
|
|
@@ -526,120 +579,254 @@ export const loadPreviousFunctionPaths = Effect.gen(function* () {
|
|
|
526
579
|
});
|
|
527
580
|
});
|
|
528
581
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Remove a now-obsolete `_generated/<name>.ts` if present (and log it), for
|
|
584
|
+
* projects upgrading from a version that still emitted it.
|
|
585
|
+
*/
|
|
586
|
+
const removeObsoleteGeneratedFile = (fileName: string) =>
|
|
587
|
+
Effect.gen(function* () {
|
|
588
|
+
const fs = yield* FileSystem.FileSystem;
|
|
589
|
+
const path = yield* Path.Path;
|
|
590
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
591
|
+
const filePath = path.join(confectDirectory, "_generated", fileName);
|
|
532
592
|
|
|
533
|
-
|
|
534
|
-
|
|
593
|
+
if (yield* fs.exists(filePath)) {
|
|
594
|
+
yield* removePathIfExists(filePath);
|
|
595
|
+
yield* logFileRemoved(filePath);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
535
598
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
599
|
+
// `_generated/api.ts` is no longer imported by generated or impl code: impls
|
|
600
|
+
// take the database schema (`_generated/schema`) directly, and per-group
|
|
601
|
+
// registries reference the spec type-only. Remove any stale copy.
|
|
602
|
+
const removeGeneratedApi = removeObsoleteGeneratedFile("api.ts");
|
|
539
603
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
);
|
|
604
|
+
// `_generated/nodeApi.ts` is obsolete for the same reason.
|
|
605
|
+
const removeGeneratedNodeApi = removeObsoleteGeneratedFile("nodeApi.ts");
|
|
543
606
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
607
|
+
const generateFunctionModules = Effect.gen(function* () {
|
|
608
|
+
const spec = yield* loadGeneratedSpec;
|
|
609
|
+
const nodeSpecOption = yield* loadGeneratedNodeSpec;
|
|
610
|
+
|
|
611
|
+
const mergedSpec = Option.match(nodeSpecOption, {
|
|
612
|
+
onNone: () => spec,
|
|
613
|
+
onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),
|
|
547
614
|
});
|
|
548
615
|
|
|
549
|
-
yield*
|
|
616
|
+
return yield* generateFunctions(mergedSpec);
|
|
550
617
|
});
|
|
551
618
|
|
|
552
|
-
|
|
619
|
+
/**
|
|
620
|
+
* The user-authored `confect/schema.ts` is no longer supported: codegen now
|
|
621
|
+
* owns both `_generated/schema.ts` (runtime) and `_generated/convexSchema.ts`
|
|
622
|
+
* (deploy), derived from a single scan of `confect/tables/*.ts`. Detect a
|
|
623
|
+
* stray file and fail with a clear migration message — leaving it in place
|
|
624
|
+
* would silently shadow the codegen-owned `_generated/schema.ts` /
|
|
625
|
+
* `_generated/convexSchema.ts`.
|
|
626
|
+
*/
|
|
627
|
+
const rejectLegacySchemaFile = Effect.gen(function* () {
|
|
553
628
|
const fs = yield* FileSystem.FileSystem;
|
|
554
629
|
const path = yield* Path.Path;
|
|
555
630
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
631
|
+
const legacyPath = path.join(confectDirectory, "schema.ts");
|
|
556
632
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (!(yield* fs.exists(nodeSpecPath))) {
|
|
561
|
-
if (yield* fs.exists(nodeApiPath)) {
|
|
562
|
-
yield* removePathIfExists(nodeApiPath);
|
|
563
|
-
yield* logFileRemoved(nodeApiPath);
|
|
564
|
-
}
|
|
565
|
-
return;
|
|
633
|
+
if (yield* fs.exists(legacyPath)) {
|
|
634
|
+
return yield* new LegacySchemaFileError({ schemaPath: "schema.ts" });
|
|
566
635
|
}
|
|
636
|
+
});
|
|
567
637
|
|
|
568
|
-
|
|
638
|
+
/**
|
|
639
|
+
* Surface a yellow `⚠` warning when codegen sees no tables — either the
|
|
640
|
+
* `confect/tables/` directory is missing or it contains no `.ts` files.
|
|
641
|
+
* Generation still succeeds (emitting an empty `DatabaseSchema` and
|
|
642
|
+
* `defineSchema({})`), since action-only / table-free Confect backends
|
|
643
|
+
* are legal — but the warning catches the much more common case of a
|
|
644
|
+
* typoed directory or files placed under the wrong root.
|
|
645
|
+
*/
|
|
646
|
+
const warnIfNoTables = (
|
|
647
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
648
|
+
) =>
|
|
649
|
+
tableModules.length === 0
|
|
650
|
+
? logWarn(
|
|
651
|
+
`No tables discovered in \`confect/${TableModule.TABLES_DIRNAME}/\`. ` +
|
|
652
|
+
`Generating an empty schema; add a \`Table.make(...)\` module under that ` +
|
|
653
|
+
`directory unless this backend is intentionally tables-free.`,
|
|
654
|
+
)
|
|
655
|
+
: Effect.void;
|
|
569
656
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
657
|
+
const tableModuleBindings = (
|
|
658
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
659
|
+
generatedFilePath: string,
|
|
660
|
+
) =>
|
|
661
|
+
Effect.gen(function* () {
|
|
662
|
+
const path = yield* Path.Path;
|
|
663
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
664
|
+
const generatedDir = path.dirname(generatedFilePath);
|
|
573
665
|
|
|
574
|
-
|
|
575
|
-
path.relative(nodeApiDir, nodeSpecPath),
|
|
576
|
-
);
|
|
666
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
577
667
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
668
|
+
return yield* Effect.forEach(tableModules, (tm) =>
|
|
669
|
+
Effect.gen(function* () {
|
|
670
|
+
const wrapperAbsolutePath = path.join(
|
|
671
|
+
confectDirectory,
|
|
672
|
+
generatedTablesDirname,
|
|
673
|
+
`${tm.tableName}.ts`,
|
|
674
|
+
);
|
|
675
|
+
const importPath = yield* toModuleImportPath(
|
|
676
|
+
path.relative(generatedDir, wrapperAbsolutePath),
|
|
677
|
+
);
|
|
678
|
+
return {
|
|
679
|
+
importPath,
|
|
680
|
+
tableName: tm.tableName,
|
|
681
|
+
};
|
|
682
|
+
}),
|
|
683
|
+
);
|
|
581
684
|
});
|
|
582
685
|
|
|
583
|
-
|
|
584
|
-
|
|
686
|
+
const generateIdConstructor = (
|
|
687
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
688
|
+
) =>
|
|
689
|
+
Effect.gen(function* () {
|
|
690
|
+
const path = yield* Path.Path;
|
|
691
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
692
|
+
const generatedIdPath = yield* GENERATED_ID_PATH;
|
|
693
|
+
const idPath = path.join(confectDirectory, generatedIdPath);
|
|
585
694
|
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
const nodeSpecOption = yield* loadGeneratedNodeSpec;
|
|
695
|
+
const tableNames = tableModules.map((tm) => tm.tableName);
|
|
696
|
+
const contents = yield* templates.id({ tableNames });
|
|
589
697
|
|
|
590
|
-
|
|
591
|
-
onNone: () => spec,
|
|
592
|
-
onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),
|
|
698
|
+
yield* writeFileStringAndLog(idPath, contents);
|
|
593
699
|
});
|
|
594
700
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
701
|
+
const generateTableWrappers = (
|
|
702
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
703
|
+
) =>
|
|
704
|
+
Effect.gen(function* () {
|
|
705
|
+
const fs = yield* FileSystem.FileSystem;
|
|
706
|
+
const path = yield* Path.Path;
|
|
707
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
708
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
709
|
+
const wrappersDir = path.join(confectDirectory, generatedTablesDirname);
|
|
603
710
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
711
|
+
if (!(yield* fs.exists(wrappersDir))) {
|
|
712
|
+
yield* fs.makeDirectory(wrappersDir, { recursive: true });
|
|
713
|
+
}
|
|
607
714
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
new SchemaInvalidDefaultExportError({
|
|
617
|
-
schemaPath: "schema.ts",
|
|
618
|
-
}),
|
|
715
|
+
yield* Effect.forEach(
|
|
716
|
+
tableModules,
|
|
717
|
+
(tm) =>
|
|
718
|
+
Effect.gen(function* () {
|
|
719
|
+
const wrapperPath = path.join(
|
|
720
|
+
confectDirectory,
|
|
721
|
+
generatedTablesDirname,
|
|
722
|
+
`${tm.tableName}.ts`,
|
|
619
723
|
);
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
724
|
+
const unnamedAbsolutePath = path.join(
|
|
725
|
+
confectDirectory,
|
|
726
|
+
tm.relativePath,
|
|
727
|
+
);
|
|
728
|
+
const unnamedImportPath = yield* toModuleImportPath(
|
|
729
|
+
path.relative(path.dirname(wrapperPath), unnamedAbsolutePath),
|
|
730
|
+
);
|
|
731
|
+
const contents = yield* templates.tableWrapper({
|
|
732
|
+
tableName: tm.tableName,
|
|
733
|
+
unnamedImportPath,
|
|
734
|
+
});
|
|
735
|
+
yield* writeFileStringAndLog(wrapperPath, contents);
|
|
736
|
+
}),
|
|
737
|
+
{ concurrency: "unbounded" },
|
|
738
|
+
);
|
|
739
|
+
});
|
|
623
740
|
|
|
624
|
-
|
|
741
|
+
/**
|
|
742
|
+
* Remove any stale `_generated/tables/*.ts` wrapper whose source table
|
|
743
|
+
* has been deleted or renamed. Mirrors `removeObsoleteRegisteredFunctions`
|
|
744
|
+
* for the wrapper directory.
|
|
745
|
+
*/
|
|
746
|
+
const removeObsoleteTableWrappers = (
|
|
747
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
748
|
+
) =>
|
|
749
|
+
Effect.gen(function* () {
|
|
750
|
+
const fs = yield* FileSystem.FileSystem;
|
|
751
|
+
const path = yield* Path.Path;
|
|
752
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
753
|
+
const generatedTablesDirname = yield* GENERATED_TABLES_DIRNAME;
|
|
754
|
+
const wrappersDir = path.join(confectDirectory, generatedTablesDirname);
|
|
755
|
+
|
|
756
|
+
if (!(yield* fs.exists(wrappersDir))) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const expected = new Set(tableModules.map((tm) => `${tm.tableName}.ts`));
|
|
761
|
+
const existing = yield* fs.readDirectory(wrappersDir, { recursive: true });
|
|
762
|
+
yield* Effect.forEach(existing, (entry) => {
|
|
763
|
+
if (path.extname(entry) !== ".ts") {
|
|
764
|
+
return Effect.void;
|
|
765
|
+
}
|
|
766
|
+
if (!expected.has(entry)) {
|
|
767
|
+
return Effect.gen(function* () {
|
|
768
|
+
const absolutePath = path.join(wrappersDir, entry);
|
|
769
|
+
if (yield* fs.exists(absolutePath)) {
|
|
770
|
+
yield* removePathIfExists(absolutePath);
|
|
771
|
+
yield* logFileRemoved(absolutePath);
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
return Effect.void;
|
|
776
|
+
});
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
const generateRuntimeSchema = (
|
|
780
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
781
|
+
) =>
|
|
782
|
+
Effect.gen(function* () {
|
|
783
|
+
const path = yield* Path.Path;
|
|
784
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
785
|
+
const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;
|
|
786
|
+
const schemaPath = path.join(confectDirectory, generatedSchemaPath);
|
|
787
|
+
|
|
788
|
+
const bindings = yield* tableModuleBindings(tableModules, schemaPath);
|
|
789
|
+
const contents = yield* templates.runtimeSchema({ tableModules: bindings });
|
|
790
|
+
|
|
791
|
+
yield* writeFileStringAndLog(schemaPath, contents);
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
const generateConvexSchema = (
|
|
795
|
+
tableModules: ReadonlyArray<TableModule.TableModule>,
|
|
796
|
+
) =>
|
|
797
|
+
Effect.gen(function* () {
|
|
798
|
+
const path = yield* Path.Path;
|
|
799
|
+
const confectDirectory = yield* ConfectDirectory.get;
|
|
800
|
+
const generatedConvexSchemaPath = yield* GENERATED_CONVEX_SCHEMA_PATH;
|
|
801
|
+
const convexSchemaPath = path.join(
|
|
802
|
+
confectDirectory,
|
|
803
|
+
generatedConvexSchemaPath,
|
|
804
|
+
);
|
|
805
|
+
|
|
806
|
+
const bindings = yield* tableModuleBindings(tableModules, convexSchemaPath);
|
|
807
|
+
const contents = yield* templates.convexSchema({ tableModules: bindings });
|
|
808
|
+
|
|
809
|
+
yield* writeFileStringAndLog(convexSchemaPath, contents);
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
const generateConvexSchemaReexport = Effect.gen(function* () {
|
|
625
813
|
const path = yield* Path.Path;
|
|
626
814
|
const confectDirectory = yield* ConfectDirectory.get;
|
|
627
815
|
const convexDirectory = yield* ConvexDirectory.get;
|
|
628
|
-
|
|
629
|
-
const confectSchemaPath = path.join(confectDirectory, "schema.ts");
|
|
630
|
-
|
|
631
|
-
// `validateSchema` runs once at the top of `runCodegen`; no need to
|
|
632
|
-
// bundle the schema again here.
|
|
816
|
+
const generatedConvexSchemaRelativePath = yield* GENERATED_CONVEX_SCHEMA_PATH;
|
|
633
817
|
|
|
634
818
|
const convexSchemaPath = path.join(convexDirectory, "schema.ts");
|
|
819
|
+
const generatedConvexSchemaPath = path.join(
|
|
820
|
+
confectDirectory,
|
|
821
|
+
generatedConvexSchemaRelativePath,
|
|
822
|
+
);
|
|
635
823
|
|
|
636
|
-
const
|
|
637
|
-
path.dirname(convexSchemaPath),
|
|
638
|
-
confectSchemaPath,
|
|
824
|
+
const convexSchemaImportPath = yield* toModuleImportPath(
|
|
825
|
+
path.relative(path.dirname(convexSchemaPath), generatedConvexSchemaPath),
|
|
639
826
|
);
|
|
640
|
-
|
|
827
|
+
|
|
641
828
|
const schemaContents = yield* templates.schema({
|
|
642
|
-
|
|
829
|
+
convexSchemaImportPath,
|
|
643
830
|
});
|
|
644
831
|
|
|
645
832
|
yield* writeFileStringAndLog(convexSchemaPath, schemaContents);
|
|
@@ -652,9 +839,12 @@ const generateServices = Effect.gen(function* () {
|
|
|
652
839
|
const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
|
|
653
840
|
|
|
654
841
|
const servicesPath = path.join(confectGeneratedDirectory, "services.ts");
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
path.
|
|
842
|
+
const generatedSchemaPath = yield* GENERATED_SCHEMA_PATH;
|
|
843
|
+
const schemaImportPath = yield* toModuleImportPath(
|
|
844
|
+
path.relative(
|
|
845
|
+
path.dirname(servicesPath),
|
|
846
|
+
path.join(confectDirectory, generatedSchemaPath),
|
|
847
|
+
),
|
|
658
848
|
);
|
|
659
849
|
|
|
660
850
|
const servicesContentsString = yield* templates.services({
|
|
@@ -672,9 +862,10 @@ const generateRefs = Effect.gen(function* () {
|
|
|
672
862
|
const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
|
|
673
863
|
const refsPath = path.join(confectGeneratedDirectory, "refs.ts");
|
|
674
864
|
const refsDir = path.dirname(refsPath);
|
|
865
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
675
866
|
|
|
676
867
|
const specImportPath = yield* toModuleImportPath(
|
|
677
|
-
path.relative(refsDir, path.join(confectDirectory,
|
|
868
|
+
path.relative(refsDir, path.join(confectDirectory, generatedSpecPath)),
|
|
678
869
|
);
|
|
679
870
|
|
|
680
871
|
const nodeSpecPath = yield* getGeneratedNodeSpecPath;
|