@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/dev.ts
CHANGED
|
@@ -22,9 +22,13 @@ import {
|
|
|
22
22
|
Stream,
|
|
23
23
|
String,
|
|
24
24
|
} from "effect";
|
|
25
|
+
import {
|
|
26
|
+
externalPlugin,
|
|
27
|
+
loadTsConfig,
|
|
28
|
+
tsconfigPathsToRegExp,
|
|
29
|
+
} from "bundle-require";
|
|
25
30
|
import * as esbuild from "esbuild";
|
|
26
31
|
import { logCoalescedBuildErrors } from "../BuildError";
|
|
27
|
-
import { absoluteExternalsPlugin } from "../Bundler";
|
|
28
32
|
import * as CodegenError from "../CodegenError";
|
|
29
33
|
import { ConfectDirectory } from "../ConfectDirectory";
|
|
30
34
|
import { ConvexDirectory } from "../ConvexDirectory";
|
|
@@ -45,8 +49,14 @@ import { ProjectRoot } from "../ProjectRoot";
|
|
|
45
49
|
import { generateAuthConfig, generateCrons, generateHttp } from "../utils";
|
|
46
50
|
import { codegenHandler, loadPreviousFunctionPaths } from "./codegen";
|
|
47
51
|
|
|
48
|
-
const
|
|
49
|
-
|
|
52
|
+
const GENERATED_DIRNAME = "_generated";
|
|
53
|
+
|
|
54
|
+
const GENERATED_SPEC_PATH = Effect.andThen(Path.Path, (path) =>
|
|
55
|
+
path.join(GENERATED_DIRNAME, "spec.ts"),
|
|
56
|
+
);
|
|
57
|
+
const GENERATED_NODE_SPEC_PATH = Effect.andThen(Path.Path, (path) =>
|
|
58
|
+
path.join(GENERATED_DIRNAME, "nodeSpec.ts"),
|
|
59
|
+
);
|
|
50
60
|
|
|
51
61
|
// Quiescence window: the sync loop waits this long for further signals
|
|
52
62
|
// after each batch. One user edit fires `onEnd` on every esbuild
|
|
@@ -95,7 +105,7 @@ const changeChar = (change: "Added" | "Removed" | "Modified") =>
|
|
|
95
105
|
Match.value(change).pipe(
|
|
96
106
|
Match.when("Added", () => ({ char: "+", color: Ansi.green })),
|
|
97
107
|
Match.when("Removed", () => ({ char: "-", color: Ansi.red })),
|
|
98
|
-
Match.when("Modified", () => ({ char: "~", color: Ansi.
|
|
108
|
+
Match.when("Modified", () => ({ char: "~", color: Ansi.magenta })),
|
|
99
109
|
Match.exhaustive,
|
|
100
110
|
);
|
|
101
111
|
|
|
@@ -410,10 +420,18 @@ const discoverEntryPoints = Effect.gen(function* () {
|
|
|
410
420
|
});
|
|
411
421
|
});
|
|
412
422
|
|
|
423
|
+
const generatedSpecPath = yield* GENERATED_SPEC_PATH;
|
|
424
|
+
const generatedNodeSpecPath = yield* GENERATED_NODE_SPEC_PATH;
|
|
425
|
+
|
|
413
426
|
const fixedEntryOptions = yield* Effect.all([
|
|
414
|
-
tryEntry(
|
|
415
|
-
tryEntry(
|
|
416
|
-
|
|
427
|
+
tryEntry(generatedSpecPath, "specDirty"),
|
|
428
|
+
tryEntry(generatedNodeSpecPath, "specDirty"),
|
|
429
|
+
// `confect/schema.ts` is no longer user-authored; the runtime
|
|
430
|
+
// `DatabaseSchema` lives at `_generated/schema.ts` (codegen-written,
|
|
431
|
+
// so not an entry point — wiring it through esbuild would form a
|
|
432
|
+
// codegen→write→onEnd→codegen loop). Updates to `confect/tables/*.ts`
|
|
433
|
+
// still reach this dev loop via the impl entry points' import graphs;
|
|
434
|
+
// brand-new tables are caught by the Create-event safety net below.
|
|
417
435
|
tryEntry("http.ts", "httpDirty"),
|
|
418
436
|
tryEntry("crons.ts", "cronsDirty"),
|
|
419
437
|
tryEntry("auth.ts", "authDirty"),
|
|
@@ -430,6 +448,7 @@ const discoverEntryPoints = Effect.gen(function* () {
|
|
|
430
448
|
|
|
431
449
|
const esbuildOptions = (
|
|
432
450
|
entry: EntryPoint,
|
|
451
|
+
notExternal: ReadonlyArray<RegExp>,
|
|
433
452
|
signal: Queue.Queue<void>,
|
|
434
453
|
pendingRef: Ref.Ref<Pending>,
|
|
435
454
|
watcherErrorsRef: Ref.Ref<WatcherErrors>,
|
|
@@ -451,7 +470,7 @@ const esbuildOptions = (
|
|
|
451
470
|
format: "esm" as const,
|
|
452
471
|
logLevel: "silent" as const,
|
|
453
472
|
plugins: [
|
|
454
|
-
|
|
473
|
+
externalPlugin({ notExternal: [...notExternal] }),
|
|
455
474
|
{
|
|
456
475
|
name: "notify-rebuild",
|
|
457
476
|
setup(build: esbuild.PluginBuild) {
|
|
@@ -489,6 +508,7 @@ const esbuildOptions = (
|
|
|
489
508
|
|
|
490
509
|
const createEntryPointWatcher = (
|
|
491
510
|
entry: EntryPoint,
|
|
511
|
+
notExternal: ReadonlyArray<RegExp>,
|
|
492
512
|
signal: Queue.Queue<void>,
|
|
493
513
|
pendingRef: Ref.Ref<Pending>,
|
|
494
514
|
watcherErrorsRef: Ref.Ref<WatcherErrors>,
|
|
@@ -496,7 +516,13 @@ const createEntryPointWatcher = (
|
|
|
496
516
|
Effect.acquireRelease(
|
|
497
517
|
Effect.promise(async () => {
|
|
498
518
|
const ctx = await esbuild.context(
|
|
499
|
-
esbuildOptions(
|
|
519
|
+
esbuildOptions(
|
|
520
|
+
entry,
|
|
521
|
+
notExternal,
|
|
522
|
+
signal,
|
|
523
|
+
pendingRef,
|
|
524
|
+
watcherErrorsRef,
|
|
525
|
+
),
|
|
500
526
|
);
|
|
501
527
|
await ctx.watch();
|
|
502
528
|
return ctx;
|
|
@@ -534,6 +560,17 @@ const entryPointsWatcher = (
|
|
|
534
560
|
Effect.gen(function* () {
|
|
535
561
|
const parentScope = yield* Effect.scope;
|
|
536
562
|
const scopesRef = yield* Ref.make(new Map<string, Scope.CloseableScope>());
|
|
563
|
+
const projectRoot = yield* ProjectRoot.get;
|
|
564
|
+
// Discover the user's `tsconfig.json#paths` once at watcher startup so
|
|
565
|
+
// `~/...`-style aliases pointing into the user's source tree get bundled
|
|
566
|
+
// by esbuild instead of externalized via `bundle-require`'s `node_modules`
|
|
567
|
+
// heuristic. `loadTsConfig` walks up from `projectRoot` to find a
|
|
568
|
+
// `tsconfig.json`; if none exists, `paths` is empty and `notExternal` is
|
|
569
|
+
// `[]`, leaving the externalization rule unchanged.
|
|
570
|
+
const tsconfig = loadTsConfig(projectRoot);
|
|
571
|
+
const notExternal = tsconfigPathsToRegExp(
|
|
572
|
+
tsconfig?.data.compilerOptions?.paths ?? {},
|
|
573
|
+
);
|
|
537
574
|
|
|
538
575
|
const sync = Effect.gen(function* () {
|
|
539
576
|
const desired = yield* discoverEntryPoints;
|
|
@@ -569,6 +606,7 @@ const entryPointsWatcher = (
|
|
|
569
606
|
);
|
|
570
607
|
yield* createEntryPointWatcher(
|
|
571
608
|
entry,
|
|
609
|
+
notExternal,
|
|
572
610
|
signal,
|
|
573
611
|
pendingRef,
|
|
574
612
|
watcherErrorsRef,
|
|
@@ -679,6 +717,10 @@ const handleConfectChange = ({
|
|
|
679
717
|
);
|
|
680
718
|
}
|
|
681
719
|
|
|
720
|
+
// A stray `confect/schema.ts` (now codegen-owned at
|
|
721
|
+
// `_generated/schema.ts`) shouldn't exist; flagging it here ensures the
|
|
722
|
+
// next codegen pass surfaces the migration error
|
|
723
|
+
// (`LegacySchemaFileError`) instead of silently ignoring the file.
|
|
682
724
|
if (relativePath === "schema.ts") {
|
|
683
725
|
return flipDirtyAndSignal(
|
|
684
726
|
pendingRef,
|
|
@@ -699,7 +741,7 @@ const handleConfectChange = ({
|
|
|
699
741
|
);
|
|
700
742
|
}
|
|
701
743
|
|
|
702
|
-
// Any other `.ts` under `confect/` (helpers like `tables/
|
|
744
|
+
// Any other `.ts` under `confect/` (helpers like `tables/notes.ts`).
|
|
703
745
|
// Updates to such files are handled by the esbuild watcher for whichever
|
|
704
746
|
// entry point imports them — its onEnd flips the right dirty flag.
|
|
705
747
|
// Creates are our safety net: when a previously-missing import is added,
|
package/src/log.ts
CHANGED
|
@@ -57,7 +57,7 @@ export const logFileAdded = logFile("+", Ansi.green);
|
|
|
57
57
|
|
|
58
58
|
export const logFileRemoved = logFile("-", Ansi.red);
|
|
59
59
|
|
|
60
|
-
export const logFileModified = logFile("~", Ansi.
|
|
60
|
+
export const logFileModified = logFile("~", Ansi.magenta);
|
|
61
61
|
|
|
62
62
|
// --- Function subline logs ---
|
|
63
63
|
|
|
@@ -101,4 +101,6 @@ export const logSuccess = logStatus("✔︎", Ansi.green);
|
|
|
101
101
|
|
|
102
102
|
export const logFailure = logStatus("✘", Ansi.red);
|
|
103
103
|
|
|
104
|
-
export const logPending = logStatus("⭘", Ansi.
|
|
104
|
+
export const logPending = logStatus("⭘", Ansi.cyan);
|
|
105
|
+
|
|
106
|
+
export const logWarn = logStatus("⚠", Ansi.yellow);
|
package/src/templates.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { Array, Effect, Option } from "effect";
|
|
|
2
2
|
import { CodeBlockWriter } from "./CodeBlockWriter";
|
|
3
3
|
import {
|
|
4
4
|
collectImportBindings,
|
|
5
|
-
collectLeafPaths,
|
|
6
5
|
type SpecAssemblyNode,
|
|
7
6
|
} from "./SpecAssemblyNode";
|
|
8
7
|
|
|
@@ -36,15 +35,197 @@ export const functions = ({
|
|
|
36
35
|
return yield* cbw.toString();
|
|
37
36
|
});
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Emit `convex/schema.ts` as a one-line re-export of the codegen-emitted
|
|
40
|
+
* deploy schema in `confect/_generated/convexSchema.ts`. Deploy-time
|
|
41
|
+
* consumers (the Convex CLI, `convex-test`) keep reading
|
|
42
|
+
* `convex/schema.ts`; the runtime `DatabaseSchema` in
|
|
43
|
+
* `confect/_generated/schema.ts` is untouched by this file.
|
|
44
|
+
*/
|
|
45
|
+
export const schema = ({
|
|
46
|
+
convexSchemaImportPath,
|
|
47
|
+
}: {
|
|
48
|
+
convexSchemaImportPath: string;
|
|
49
|
+
}) =>
|
|
40
50
|
Effect.gen(function* () {
|
|
41
51
|
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
42
52
|
|
|
43
|
-
yield* cbw.writeLine(`import schemaDefinition from "${schemaImportPath}";`);
|
|
44
|
-
yield* cbw.newLine();
|
|
45
53
|
yield* cbw.writeLine(
|
|
46
|
-
`export default
|
|
54
|
+
`export { default } from "${convexSchemaImportPath}";`,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return yield* cbw.toString();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
interface TableModuleBinding {
|
|
61
|
+
readonly importPath: string;
|
|
62
|
+
readonly tableName: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Emit `confect/_generated/schema.ts` — the runtime `DatabaseSchema` used
|
|
67
|
+
* by impls and the per-group registries (and downstream by per-function
|
|
68
|
+
* bundles for codec lookup). Every table wrapper at
|
|
69
|
+
* `confect/_generated/tables/<name>.ts` is imported statically and
|
|
70
|
+
* registered as a value entry on the `DatabaseSchema.make({...})` call.
|
|
71
|
+
* Per-table laziness lives inside each `Table`: its `Fields`, `Doc`, and
|
|
72
|
+
* `tableDefinition` are lazy memoised getters that only evaluate the
|
|
73
|
+
* user-supplied field-schema callback on first access, so unused tables in
|
|
74
|
+
* a function bundle never pay schema-construction cost despite the
|
|
75
|
+
* static import.
|
|
76
|
+
*
|
|
77
|
+
* The `DatabaseSchema` import is aliased to `$DatabaseSchema` because each
|
|
78
|
+
* table is imported under its own (filename-derived) name; a table named
|
|
79
|
+
* `DatabaseSchema` would otherwise collide with the library import and emit
|
|
80
|
+
* a duplicate-binding file. The leading `$` makes the alias collision-proof:
|
|
81
|
+
* `validateConfectTableIdentifier` requires names to match
|
|
82
|
+
* `/^[a-zA-Z][a-zA-Z0-9_]*$/`, which forbids `$`, so no valid table import
|
|
83
|
+
* can ever shadow it.
|
|
84
|
+
*/
|
|
85
|
+
export const runtimeSchema = ({
|
|
86
|
+
tableModules,
|
|
87
|
+
}: {
|
|
88
|
+
tableModules: ReadonlyArray<TableModuleBinding>;
|
|
89
|
+
}) =>
|
|
90
|
+
Effect.gen(function* () {
|
|
91
|
+
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
92
|
+
|
|
93
|
+
yield* cbw.writeLine(
|
|
94
|
+
`import { DatabaseSchema as $DatabaseSchema } from "@confect/server";`,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (tableModules.length > 0) {
|
|
98
|
+
yield* cbw.blankLine();
|
|
99
|
+
yield* Effect.forEach(tableModules, ({ tableName, importPath }) =>
|
|
100
|
+
cbw.writeLine(`import ${tableName} from "${importPath}";`),
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
yield* cbw.blankLine();
|
|
105
|
+
|
|
106
|
+
if (tableModules.length === 0) {
|
|
107
|
+
yield* cbw.writeLine(`export default $DatabaseSchema.make({});`);
|
|
108
|
+
} else {
|
|
109
|
+
yield* cbw.writeLine(`export default $DatabaseSchema.make({`);
|
|
110
|
+
yield* cbw.indent(
|
|
111
|
+
Effect.gen(function* () {
|
|
112
|
+
for (const { tableName } of tableModules) {
|
|
113
|
+
yield* cbw.writeLine(`${tableName},`);
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
yield* cbw.writeLine(`});`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return yield* cbw.toString();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Emit `confect/_generated/convexSchema.ts` — the Convex deploy-time
|
|
125
|
+
* `SchemaDefinition`. Imports every table from its generated wrapper at
|
|
126
|
+
* `_generated/tables/<name>` and calls `defineSchema({...})` exactly once.
|
|
127
|
+
* The file deliberately avoids any `@confect/server` import so that the
|
|
128
|
+
* deploy artifact's import graph stays decoupled from the runtime
|
|
129
|
+
* `DatabaseSchema` machinery.
|
|
130
|
+
*
|
|
131
|
+
* The `defineSchema` import is aliased to `$defineSchema` because each table
|
|
132
|
+
* is imported under its own (filename-derived) name; a table named
|
|
133
|
+
* `defineSchema` would otherwise collide with the library import and emit a
|
|
134
|
+
* duplicate-binding file. The leading `$` makes the alias collision-proof:
|
|
135
|
+
* `validateConfectTableIdentifier` requires names to match
|
|
136
|
+
* `/^[a-zA-Z][a-zA-Z0-9_]*$/`, which forbids `$`, so no valid table import
|
|
137
|
+
* can ever shadow it.
|
|
138
|
+
*/
|
|
139
|
+
export const convexSchema = ({
|
|
140
|
+
tableModules,
|
|
141
|
+
}: {
|
|
142
|
+
tableModules: ReadonlyArray<TableModuleBinding>;
|
|
143
|
+
}) =>
|
|
144
|
+
Effect.gen(function* () {
|
|
145
|
+
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
146
|
+
|
|
147
|
+
yield* cbw.writeLine(
|
|
148
|
+
`import { defineSchema as $defineSchema } from "convex/server";`,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (tableModules.length > 0) {
|
|
152
|
+
yield* cbw.blankLine();
|
|
153
|
+
yield* Effect.forEach(tableModules, ({ tableName, importPath }) =>
|
|
154
|
+
cbw.writeLine(`import ${tableName} from "${importPath}";`),
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
yield* cbw.blankLine();
|
|
159
|
+
|
|
160
|
+
if (tableModules.length === 0) {
|
|
161
|
+
yield* cbw.writeLine(`export default $defineSchema({});`);
|
|
162
|
+
} else {
|
|
163
|
+
yield* cbw.writeLine(`export default $defineSchema({`);
|
|
164
|
+
yield* cbw.indent(
|
|
165
|
+
Effect.gen(function* () {
|
|
166
|
+
for (const { tableName } of tableModules) {
|
|
167
|
+
yield* cbw.writeLine(`${tableName}: ${tableName}.tableDefinition,`);
|
|
168
|
+
}
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
yield* cbw.writeLine(`});`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return yield* cbw.toString();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Emit `confect/_generated/id.ts` — a type-constrained `Id` constructor and
|
|
179
|
+
* a `TableNames` union derived from the user's `confect/tables/*.ts`
|
|
180
|
+
* filenames. User-authored table modules import `Id` from this file to
|
|
181
|
+
* declare cross-table id references without typing the destination name as
|
|
182
|
+
* a free string (and without ever importing each other transitively).
|
|
183
|
+
*
|
|
184
|
+
* When the table directory is empty the `TableNames` union resolves to
|
|
185
|
+
* `never`, which still lets the file typecheck against an empty workspace.
|
|
186
|
+
*/
|
|
187
|
+
export const id = ({ tableNames }: { tableNames: ReadonlyArray<string> }) =>
|
|
188
|
+
Effect.gen(function* () {
|
|
189
|
+
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
190
|
+
|
|
191
|
+
yield* cbw.writeLine(`import { GenericId } from "@confect/core";`);
|
|
192
|
+
yield* cbw.blankLine();
|
|
193
|
+
|
|
194
|
+
const union =
|
|
195
|
+
tableNames.length === 0
|
|
196
|
+
? "never"
|
|
197
|
+
: tableNames.map((n) => `"${n}"`).join(" | ");
|
|
198
|
+
yield* cbw.writeLine(`export type TableNames = ${union};`);
|
|
199
|
+
yield* cbw.blankLine();
|
|
200
|
+
|
|
201
|
+
yield* cbw.writeLine(
|
|
202
|
+
`export const Id = <const TableName extends TableNames>(`,
|
|
47
203
|
);
|
|
204
|
+
yield* cbw.indent(cbw.writeLine(`tableName: TableName,`));
|
|
205
|
+
yield* cbw.writeLine(`) => GenericId.GenericId(tableName);`);
|
|
206
|
+
|
|
207
|
+
return yield* cbw.toString();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Emit `confect/_generated/tables/<tableName>.ts` — a two-line wrapper that
|
|
212
|
+
* imports the user-authored `UnnamedTable` and binds the file basename to
|
|
213
|
+
* it, producing the fully-named `Table` value that downstream consumers
|
|
214
|
+
* (schema, specs, impls) read.
|
|
215
|
+
*/
|
|
216
|
+
export const tableWrapper = ({
|
|
217
|
+
tableName,
|
|
218
|
+
unnamedImportPath,
|
|
219
|
+
}: {
|
|
220
|
+
tableName: string;
|
|
221
|
+
unnamedImportPath: string;
|
|
222
|
+
}) =>
|
|
223
|
+
Effect.gen(function* () {
|
|
224
|
+
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
225
|
+
|
|
226
|
+
yield* cbw.writeLine(`import unnamed from "${unnamedImportPath}";`);
|
|
227
|
+
yield* cbw.blankLine();
|
|
228
|
+
yield* cbw.writeLine(`export default unnamed("${tableName}");`);
|
|
48
229
|
|
|
49
230
|
return yield* cbw.toString();
|
|
50
231
|
});
|
|
@@ -110,54 +291,15 @@ export const refs = ({
|
|
|
110
291
|
return yield* cbw.toString();
|
|
111
292
|
});
|
|
112
293
|
|
|
113
|
-
export const
|
|
294
|
+
export const registeredFunctionsForGroup = ({
|
|
114
295
|
schemaImportPath,
|
|
115
296
|
specImportPath,
|
|
116
|
-
}: {
|
|
117
|
-
schemaImportPath: string;
|
|
118
|
-
specImportPath: string;
|
|
119
|
-
}) =>
|
|
120
|
-
Effect.gen(function* () {
|
|
121
|
-
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
122
|
-
|
|
123
|
-
yield* cbw.writeLine(`import { Api } from "@confect/server";`);
|
|
124
|
-
yield* cbw.writeLine(`import schema from "${schemaImportPath}";`);
|
|
125
|
-
yield* cbw.writeLine(`import spec from "${specImportPath}";`);
|
|
126
|
-
yield* cbw.blankLine();
|
|
127
|
-
yield* cbw.writeLine(`export default Api.make(schema, spec);`);
|
|
128
|
-
|
|
129
|
-
return yield* cbw.toString();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
export const nodeApi = ({
|
|
133
|
-
schemaImportPath,
|
|
134
|
-
nodeSpecImportPath,
|
|
135
|
-
}: {
|
|
136
|
-
schemaImportPath: string;
|
|
137
|
-
nodeSpecImportPath: string;
|
|
138
|
-
}) =>
|
|
139
|
-
Effect.gen(function* () {
|
|
140
|
-
const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
|
|
141
|
-
|
|
142
|
-
yield* cbw.writeLine(`import { Api } from "@confect/server";`);
|
|
143
|
-
yield* cbw.blankLine();
|
|
144
|
-
yield* cbw.writeLine(`import schema from "${schemaImportPath}";`);
|
|
145
|
-
yield* cbw.writeLine(`import nodeSpec from "${nodeSpecImportPath}";`);
|
|
146
|
-
yield* cbw.blankLine();
|
|
147
|
-
yield* cbw.writeLine(`export default Api.make(schema, nodeSpec);`);
|
|
148
|
-
|
|
149
|
-
return yield* cbw.toString();
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
export const registeredFunctionsForGroup = ({
|
|
153
|
-
apiImportPath,
|
|
154
|
-
groupPathDot,
|
|
155
297
|
implImportPath,
|
|
156
298
|
layerExportName,
|
|
157
299
|
useNode = false,
|
|
158
300
|
}: {
|
|
159
|
-
|
|
160
|
-
|
|
301
|
+
schemaImportPath: string;
|
|
302
|
+
specImportPath: string;
|
|
161
303
|
implImportPath: string;
|
|
162
304
|
layerExportName: string;
|
|
163
305
|
useNode?: boolean;
|
|
@@ -178,14 +320,20 @@ export const registeredFunctionsForGroup = ({
|
|
|
178
320
|
);
|
|
179
321
|
}
|
|
180
322
|
|
|
181
|
-
yield* cbw.writeLine(`import
|
|
323
|
+
yield* cbw.writeLine(`import databaseSchema from "${schemaImportPath}";`);
|
|
182
324
|
yield* cbw.writeLine(`import ${layerExportName} from "${implImportPath}";`);
|
|
183
325
|
yield* cbw.blankLine();
|
|
184
|
-
|
|
326
|
+
// The group's own leaf spec is referenced type-only (`typeof import(...)`),
|
|
327
|
+
// so the spec module is erased at transpile time and never enters the
|
|
328
|
+
// per-function bundle; only `databaseSchema` and the impl are runtime
|
|
329
|
+
// imports. Typing from the leaf spec (not the project-wide assembled spec)
|
|
330
|
+
// keeps the registry's type dependent solely on its own group.
|
|
331
|
+
const specType = `typeof import("${specImportPath}")["default"]`;
|
|
332
|
+
const makeFn = useNode
|
|
333
|
+
? "RegisteredNodeFunction.make"
|
|
334
|
+
: "RegisteredConvexFunction.make";
|
|
185
335
|
yield* cbw.writeLine(
|
|
186
|
-
|
|
187
|
-
? `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredNodeFunction.make);`
|
|
188
|
-
: `export default RegisteredFunctions.buildForGroup(api, ${quotedGroupPath}, ${layerExportName}, RegisteredConvexFunction.make);`,
|
|
336
|
+
`export default RegisteredFunctions.buildForGroup<${specType}>(databaseSchema, ${layerExportName}, ${makeFn});`,
|
|
189
337
|
);
|
|
190
338
|
|
|
191
339
|
return yield* cbw.toString();
|
|
@@ -473,13 +621,6 @@ export const assembledSpec = ({
|
|
|
473
621
|
runtime === "Convex" ? "GroupSpec.makeAt" : "GroupSpec.makeNodeAt";
|
|
474
622
|
|
|
475
623
|
yield* cbw.write(`export default ${specFactory}`);
|
|
476
|
-
yield* Effect.forEach(collectLeafPaths(nodes), (leaf) =>
|
|
477
|
-
Effect.gen(function* () {
|
|
478
|
-
yield* cbw.write(`.addPath(${leaf.binding.localName}, `);
|
|
479
|
-
yield* cbw.quote(leaf.dotPath);
|
|
480
|
-
yield* cbw.write(")");
|
|
481
|
-
}),
|
|
482
|
-
);
|
|
483
624
|
yield* Effect.forEach(nodes, (node) =>
|
|
484
625
|
writeRootAddAt(cbw, node, groupFactory),
|
|
485
626
|
);
|