@confect/cli 9.0.0-next.8 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +187 -1
  2. package/dist/Bundler.mjs +1 -4
  3. package/dist/Bundler.mjs.map +1 -1
  4. package/dist/CodegenError.mjs +3 -13
  5. package/dist/CodegenError.mjs.map +1 -1
  6. package/dist/LeafModule.mjs +9 -22
  7. package/dist/LeafModule.mjs.map +1 -1
  8. package/dist/SpecAssemblyNode.mjs +1 -8
  9. package/dist/SpecAssemblyNode.mjs.map +1 -1
  10. package/dist/confect/codegen.mjs +26 -69
  11. package/dist/confect/codegen.mjs.map +1 -1
  12. package/dist/confect/dev.mjs +0 -3
  13. package/dist/confect/dev.mjs.map +1 -1
  14. package/dist/log.mjs +2 -2
  15. package/dist/log.mjs.map +1 -1
  16. package/dist/package.mjs +1 -1
  17. package/dist/templates.mjs +5 -14
  18. package/dist/templates.mjs.map +1 -1
  19. package/dist/utils.mjs +32 -22
  20. package/dist/utils.mjs.map +1 -1
  21. package/package.json +4 -21
  22. package/dist/index.d.mts +0 -1
  23. package/src/BuildError.ts +0 -217
  24. package/src/Bundler.ts +0 -145
  25. package/src/CodeBlockWriter.ts +0 -65
  26. package/src/CodegenError.ts +0 -443
  27. package/src/ConfectDirectory.ts +0 -45
  28. package/src/ConvexDirectory.ts +0 -72
  29. package/src/FunctionPath.ts +0 -27
  30. package/src/FunctionPaths.ts +0 -107
  31. package/src/GroupPath.ts +0 -116
  32. package/src/GroupPaths.ts +0 -7
  33. package/src/LeafModule.ts +0 -323
  34. package/src/ProjectRoot.ts +0 -55
  35. package/src/SpecAssemblyNode.ts +0 -88
  36. package/src/TableModule.ts +0 -157
  37. package/src/cliApp.ts +0 -8
  38. package/src/confect/codegen.ts +0 -908
  39. package/src/confect/dev.ts +0 -790
  40. package/src/confect.ts +0 -19
  41. package/src/index.ts +0 -23
  42. package/src/log.ts +0 -110
  43. package/src/templates.ts +0 -633
  44. package/src/utils.ts +0 -428
package/src/templates.ts DELETED
@@ -1,633 +0,0 @@
1
- import * as Array from "effect/Array";
2
- import * as Effect from "effect/Effect";
3
- import * as Option from "effect/Option";
4
- import { CodeBlockWriter } from "./CodeBlockWriter";
5
- import {
6
- collectImportBindings,
7
- type SpecAssemblyNode,
8
- } from "./SpecAssemblyNode";
9
-
10
- export const functions = ({
11
- functionNames,
12
- registeredFunctionsImportPath,
13
- useNode = false,
14
- }: {
15
- functionNames: string[];
16
- registeredFunctionsImportPath: string;
17
- useNode?: boolean;
18
- }) =>
19
- Effect.gen(function* () {
20
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
21
-
22
- if (useNode) {
23
- yield* cbw.writeLine(`"use node";`);
24
- yield* cbw.blankLine();
25
- }
26
-
27
- yield* cbw.writeLine(
28
- `import registeredFunctions from "${registeredFunctionsImportPath}";`,
29
- );
30
- yield* cbw.newLine();
31
- yield* Effect.forEach(functionNames, (functionName) =>
32
- cbw.writeLine(
33
- `export const ${functionName} = registeredFunctions.${functionName};`,
34
- ),
35
- );
36
-
37
- return yield* cbw.toString();
38
- });
39
-
40
- /**
41
- * Emit `convex/schema.ts` as a one-line re-export of the codegen-emitted
42
- * deploy schema in `confect/_generated/convexSchema.ts`. Deploy-time
43
- * consumers (the Convex CLI, `convex-test`) keep reading
44
- * `convex/schema.ts`; the runtime `DatabaseSchema` in
45
- * `confect/_generated/schema.ts` is untouched by this file.
46
- */
47
- export const schema = ({
48
- convexSchemaImportPath,
49
- }: {
50
- convexSchemaImportPath: string;
51
- }) =>
52
- Effect.gen(function* () {
53
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
54
-
55
- yield* cbw.writeLine(
56
- `export { default } from "${convexSchemaImportPath}";`,
57
- );
58
-
59
- return yield* cbw.toString();
60
- });
61
-
62
- interface TableModuleBinding {
63
- readonly importPath: string;
64
- readonly tableName: string;
65
- }
66
-
67
- /**
68
- * Emit `confect/_generated/schema.ts` — the runtime `DatabaseSchema` used
69
- * by impls and the per-group registries (and downstream by per-function
70
- * bundles for codec lookup). Every table wrapper at
71
- * `confect/_generated/tables/<name>.ts` is imported statically and
72
- * registered as a value entry on the `DatabaseSchema.make({...})` call.
73
- * Per-table laziness lives inside each `Table`: its `Fields`, `Doc`, and
74
- * `tableDefinition` are lazy memoised getters that only evaluate the
75
- * user-supplied field-schema callback on first access, so unused tables in
76
- * a function bundle never pay schema-construction cost despite the
77
- * static import.
78
- *
79
- * The `DatabaseSchema` import is aliased to `$DatabaseSchema` because each
80
- * table is imported under its own (filename-derived) name; a table named
81
- * `DatabaseSchema` would otherwise collide with the library import and emit
82
- * a duplicate-binding file. The leading `$` makes the alias collision-proof:
83
- * `validateConfectTableIdentifier` requires names to match
84
- * `/^[a-zA-Z][a-zA-Z0-9_]*$/`, which forbids `$`, so no valid table import
85
- * can ever shadow it.
86
- */
87
- export const runtimeSchema = ({
88
- tableModules,
89
- }: {
90
- tableModules: ReadonlyArray<TableModuleBinding>;
91
- }) =>
92
- Effect.gen(function* () {
93
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
94
-
95
- yield* cbw.writeLine(
96
- `import { DatabaseSchema as $DatabaseSchema } from "@confect/server";`,
97
- );
98
-
99
- if (tableModules.length > 0) {
100
- yield* cbw.blankLine();
101
- yield* Effect.forEach(tableModules, ({ tableName, importPath }) =>
102
- cbw.writeLine(`import ${tableName} from "${importPath}";`),
103
- );
104
- }
105
-
106
- yield* cbw.blankLine();
107
-
108
- if (tableModules.length === 0) {
109
- yield* cbw.writeLine(`export default $DatabaseSchema.make({});`);
110
- } else {
111
- yield* cbw.writeLine(`export default $DatabaseSchema.make({`);
112
- yield* cbw.indent(
113
- Effect.gen(function* () {
114
- for (const { tableName } of tableModules) {
115
- yield* cbw.writeLine(`${tableName},`);
116
- }
117
- }),
118
- );
119
- yield* cbw.writeLine(`});`);
120
- }
121
-
122
- return yield* cbw.toString();
123
- });
124
-
125
- /**
126
- * Emit `confect/_generated/convexSchema.ts` — the Convex deploy-time
127
- * `SchemaDefinition`. Imports every table from its generated wrapper at
128
- * `_generated/tables/<name>` and calls `defineSchema({...})` exactly once.
129
- * The file deliberately avoids any `@confect/server` import so that the
130
- * deploy artifact's import graph stays decoupled from the runtime
131
- * `DatabaseSchema` machinery.
132
- *
133
- * The `defineSchema` import is aliased to `$defineSchema` because each table
134
- * is imported under its own (filename-derived) name; a table named
135
- * `defineSchema` would otherwise collide with the library import and emit a
136
- * duplicate-binding file. The leading `$` makes the alias collision-proof:
137
- * `validateConfectTableIdentifier` requires names to match
138
- * `/^[a-zA-Z][a-zA-Z0-9_]*$/`, which forbids `$`, so no valid table import
139
- * can ever shadow it.
140
- */
141
- export const convexSchema = ({
142
- tableModules,
143
- }: {
144
- tableModules: ReadonlyArray<TableModuleBinding>;
145
- }) =>
146
- Effect.gen(function* () {
147
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
148
-
149
- yield* cbw.writeLine(
150
- `import { defineSchema as $defineSchema } from "convex/server";`,
151
- );
152
-
153
- if (tableModules.length > 0) {
154
- yield* cbw.blankLine();
155
- yield* Effect.forEach(tableModules, ({ tableName, importPath }) =>
156
- cbw.writeLine(`import ${tableName} from "${importPath}";`),
157
- );
158
- }
159
-
160
- yield* cbw.blankLine();
161
-
162
- if (tableModules.length === 0) {
163
- yield* cbw.writeLine(`export default $defineSchema({});`);
164
- } else {
165
- yield* cbw.writeLine(`export default $defineSchema({`);
166
- yield* cbw.indent(
167
- Effect.gen(function* () {
168
- for (const { tableName } of tableModules) {
169
- yield* cbw.writeLine(`${tableName}: ${tableName}.tableDefinition,`);
170
- }
171
- }),
172
- );
173
- yield* cbw.writeLine(`});`);
174
- }
175
-
176
- return yield* cbw.toString();
177
- });
178
-
179
- /**
180
- * Emit `confect/_generated/id.ts` — a type-constrained `Id` constructor and
181
- * a `TableNames` union derived from the user's `confect/tables/*.ts`
182
- * filenames. User-authored table modules import `Id` from this file to
183
- * declare cross-table id references without typing the destination name as
184
- * a free string (and without ever importing each other transitively).
185
- *
186
- * When the table directory is empty the `TableNames` union resolves to
187
- * `never`, which still lets the file typecheck against an empty workspace.
188
- */
189
- export const id = ({ tableNames }: { tableNames: ReadonlyArray<string> }) =>
190
- Effect.gen(function* () {
191
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
192
-
193
- yield* cbw.writeLine(`import { GenericId } from "@confect/core";`);
194
- yield* cbw.blankLine();
195
-
196
- const union =
197
- tableNames.length === 0
198
- ? "never"
199
- : tableNames.map((n) => `"${n}"`).join(" | ");
200
- yield* cbw.writeLine(`export type TableNames = ${union};`);
201
- yield* cbw.blankLine();
202
-
203
- yield* cbw.writeLine(
204
- `export const Id = <const TableName extends TableNames>(`,
205
- );
206
- yield* cbw.indent(cbw.writeLine(`tableName: TableName,`));
207
- yield* cbw.writeLine(`) => GenericId.GenericId(tableName);`);
208
-
209
- return yield* cbw.toString();
210
- });
211
-
212
- /**
213
- * Emit `confect/_generated/tables/<tableName>.ts` — a two-line wrapper that
214
- * imports the user-authored `UnnamedTable` and binds the file basename to
215
- * it, producing the fully-named `Table` value that downstream consumers
216
- * (schema, specs, impls) read.
217
- */
218
- export const tableWrapper = ({
219
- tableName,
220
- unnamedImportPath,
221
- }: {
222
- tableName: string;
223
- unnamedImportPath: string;
224
- }) =>
225
- Effect.gen(function* () {
226
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
227
-
228
- yield* cbw.writeLine(`import unnamed from "${unnamedImportPath}";`);
229
- yield* cbw.blankLine();
230
- yield* cbw.writeLine(`export default unnamed("${tableName}");`);
231
-
232
- return yield* cbw.toString();
233
- });
234
-
235
- export const http = ({ httpImportPath }: { httpImportPath: string }) =>
236
- Effect.gen(function* () {
237
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
238
-
239
- yield* cbw.writeLine(`import http from "${httpImportPath}";`);
240
- yield* cbw.newLine();
241
- yield* cbw.writeLine(`export default http;`);
242
-
243
- return yield* cbw.toString();
244
- });
245
-
246
- export const crons = ({ cronsImportPath }: { cronsImportPath: string }) =>
247
- Effect.gen(function* () {
248
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
249
-
250
- yield* cbw.writeLine(`import crons from "${cronsImportPath}";`);
251
- yield* cbw.newLine();
252
- yield* cbw.writeLine(`export default crons.convexCronJobs;`);
253
-
254
- return yield* cbw.toString();
255
- });
256
-
257
- export const authConfig = ({ authImportPath }: { authImportPath: string }) =>
258
- Effect.gen(function* () {
259
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
260
-
261
- yield* cbw.writeLine(`import auth from "${authImportPath}";`);
262
- yield* cbw.newLine();
263
- yield* cbw.writeLine(`export default auth;`);
264
-
265
- return yield* cbw.toString();
266
- });
267
-
268
- export const refs = ({
269
- specImportPath,
270
- nodeSpecImportPath,
271
- }: {
272
- specImportPath: string;
273
- nodeSpecImportPath: Option.Option<string>;
274
- }) =>
275
- Effect.gen(function* () {
276
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
277
-
278
- yield* cbw.writeLine(`import { Refs } from "@confect/core";`);
279
- yield* cbw.writeLine(`import spec from "${specImportPath}";`);
280
- yield* Option.match(nodeSpecImportPath, {
281
- onNone: () => Effect.void,
282
- onSome: (nodeSpecImportPath_) =>
283
- cbw.writeLine(`import nodeSpec from "${nodeSpecImportPath_}";`),
284
- });
285
- yield* cbw.blankLine();
286
- yield* cbw.writeLine(
287
- Option.match(nodeSpecImportPath, {
288
- onSome: () => `export default Refs.make(spec, nodeSpec);`,
289
- onNone: () => `export default Refs.make(spec);`,
290
- }),
291
- );
292
-
293
- return yield* cbw.toString();
294
- });
295
-
296
- export const registeredFunctionsForGroup = ({
297
- schemaImportPath,
298
- specImportPath,
299
- implImportPath,
300
- layerExportName,
301
- useNode = false,
302
- }: {
303
- schemaImportPath: string;
304
- specImportPath: string;
305
- implImportPath: string;
306
- layerExportName: string;
307
- useNode?: boolean;
308
- }) =>
309
- Effect.gen(function* () {
310
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
311
-
312
- if (useNode) {
313
- yield* cbw.writeLine(
314
- `import { RegisteredFunctions } from "@confect/server";`,
315
- );
316
- yield* cbw.writeLine(
317
- `import { RegisteredNodeFunction } from "@confect/server/node";`,
318
- );
319
- } else {
320
- yield* cbw.writeLine(
321
- `import { RegisteredConvexFunction, RegisteredFunctions } from "@confect/server";`,
322
- );
323
- }
324
-
325
- yield* cbw.writeLine(`import databaseSchema from "${schemaImportPath}";`);
326
- yield* cbw.writeLine(`import ${layerExportName} from "${implImportPath}";`);
327
- yield* cbw.blankLine();
328
- // The group's own leaf spec is referenced type-only (`typeof import(...)`),
329
- // so the spec module is erased at transpile time and never enters the
330
- // per-function bundle; only `databaseSchema` and the impl are runtime
331
- // imports. Typing from the leaf spec (not the project-wide assembled spec)
332
- // keeps the registry's type dependent solely on its own group.
333
- const specType = `typeof import("${specImportPath}")["default"]`;
334
- const makeFn = useNode
335
- ? "RegisteredNodeFunction.make"
336
- : "RegisteredConvexFunction.make";
337
- yield* cbw.writeLine(
338
- `export default RegisteredFunctions.buildForGroup<${specType}>(databaseSchema, ${layerExportName}, ${makeFn});`,
339
- );
340
-
341
- return yield* cbw.toString();
342
- });
343
-
344
- export const services = ({ schemaImportPath }: { schemaImportPath: string }) =>
345
- Effect.gen(function* () {
346
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
347
-
348
- // Imports
349
- yield* cbw.writeLine("import {");
350
- yield* cbw.indent(
351
- Effect.gen(function* () {
352
- yield* cbw.writeLine("ActionCtx as ActionCtx_,");
353
- yield* cbw.writeLine("ActionRunner as ActionRunner_,");
354
- yield* cbw.writeLine("Auth as Auth_,");
355
- yield* cbw.writeLine("type DataModel,");
356
- yield* cbw.writeLine("DatabaseReader as DatabaseReader_,");
357
- yield* cbw.writeLine("DatabaseWriter as DatabaseWriter_,");
358
- yield* cbw.writeLine("MutationCtx as MutationCtx_,");
359
- yield* cbw.writeLine("MutationRunner as MutationRunner_,");
360
- yield* cbw.writeLine("QueryCtx as QueryCtx_,");
361
- yield* cbw.writeLine("QueryRunner as QueryRunner_,");
362
- yield* cbw.writeLine("Scheduler as Scheduler_,");
363
- yield* cbw.writeLine("StorageActionWriter as StorageActionWriter_,");
364
- yield* cbw.writeLine("StorageReader as StorageReader_,");
365
- yield* cbw.writeLine("StorageWriter as StorageWriter_,");
366
- yield* cbw.writeLine("VectorSearch as VectorSearch_,");
367
- }),
368
- );
369
- yield* cbw.writeLine(`} from "@confect/server";`);
370
- yield* cbw.writeLine(
371
- `import type schemaDefinition from "${schemaImportPath}";`,
372
- );
373
- yield* cbw.blankLine();
374
-
375
- // Auth
376
- yield* cbw.writeLine("export const Auth = Auth_.Auth;");
377
- yield* cbw.writeLine("export type Auth = typeof Auth.Identifier;");
378
- yield* cbw.blankLine();
379
-
380
- // Scheduler
381
- yield* cbw.writeLine("export const Scheduler = Scheduler_.Scheduler;");
382
- yield* cbw.writeLine(
383
- "export type Scheduler = typeof Scheduler.Identifier;",
384
- );
385
- yield* cbw.blankLine();
386
-
387
- // StorageReader
388
- yield* cbw.writeLine(
389
- "export const StorageReader = StorageReader_.StorageReader;",
390
- );
391
- yield* cbw.writeLine(
392
- "export type StorageReader = typeof StorageReader.Identifier;",
393
- );
394
- yield* cbw.blankLine();
395
-
396
- // StorageWriter
397
- yield* cbw.writeLine(
398
- "export const StorageWriter = StorageWriter_.StorageWriter;",
399
- );
400
- yield* cbw.writeLine(
401
- "export type StorageWriter = typeof StorageWriter.Identifier;",
402
- );
403
- yield* cbw.blankLine();
404
-
405
- // StorageActionWriter
406
- yield* cbw.writeLine(
407
- "export const StorageActionWriter = StorageActionWriter_.StorageActionWriter;",
408
- );
409
- yield* cbw.writeLine(
410
- "export type StorageActionWriter = typeof StorageActionWriter.Identifier;",
411
- );
412
- yield* cbw.blankLine();
413
-
414
- // VectorSearch
415
- yield* cbw.writeLine("export const VectorSearch =");
416
- yield* cbw.indent(
417
- cbw.writeLine(
418
- "VectorSearch_.VectorSearch<DataModel.FromSchema<typeof schemaDefinition>>();",
419
- ),
420
- );
421
- yield* cbw.writeLine(
422
- "export type VectorSearch = typeof VectorSearch.Identifier;",
423
- );
424
- yield* cbw.blankLine();
425
-
426
- // DatabaseReader
427
- yield* cbw.writeLine("export const DatabaseReader =");
428
- yield* cbw.indent(
429
- cbw.writeLine(
430
- "DatabaseReader_.DatabaseReader<typeof schemaDefinition>();",
431
- ),
432
- );
433
- yield* cbw.writeLine(
434
- "export type DatabaseReader = typeof DatabaseReader.Identifier;",
435
- );
436
- yield* cbw.blankLine();
437
-
438
- // DatabaseWriter
439
- yield* cbw.writeLine("export const DatabaseWriter =");
440
- yield* cbw.indent(
441
- cbw.writeLine(
442
- "DatabaseWriter_.DatabaseWriter<typeof schemaDefinition>();",
443
- ),
444
- );
445
- yield* cbw.writeLine(
446
- "export type DatabaseWriter = typeof DatabaseWriter.Identifier;",
447
- );
448
- yield* cbw.blankLine();
449
-
450
- // QueryRunner
451
- yield* cbw.writeLine(
452
- "export const QueryRunner = QueryRunner_.QueryRunner;",
453
- );
454
- yield* cbw.writeLine(
455
- "export type QueryRunner = typeof QueryRunner.Identifier;",
456
- );
457
- yield* cbw.blankLine();
458
-
459
- // MutationRunner
460
- yield* cbw.writeLine(
461
- "export const MutationRunner = MutationRunner_.MutationRunner;",
462
- );
463
- yield* cbw.writeLine(
464
- "export type MutationRunner = typeof MutationRunner.Identifier;",
465
- );
466
- yield* cbw.blankLine();
467
-
468
- // ActionRunner
469
- yield* cbw.writeLine(
470
- "export const ActionRunner = ActionRunner_.ActionRunner;",
471
- );
472
- yield* cbw.writeLine(
473
- "export type ActionRunner = typeof ActionRunner.Identifier;",
474
- );
475
- yield* cbw.blankLine();
476
-
477
- // QueryCtx
478
- yield* cbw.writeLine("export const QueryCtx =");
479
- yield* cbw.indent(
480
- Effect.gen(function* () {
481
- yield* cbw.writeLine("QueryCtx_.QueryCtx<");
482
- yield* cbw.indent(
483
- cbw.writeLine(
484
- "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
485
- ),
486
- );
487
- yield* cbw.writeLine(">();");
488
- }),
489
- );
490
- yield* cbw.writeLine("export type QueryCtx = typeof QueryCtx.Identifier;");
491
- yield* cbw.blankLine();
492
-
493
- // MutationCtx
494
- yield* cbw.writeLine("export const MutationCtx =");
495
- yield* cbw.indent(
496
- Effect.gen(function* () {
497
- yield* cbw.writeLine("MutationCtx_.MutationCtx<");
498
- yield* cbw.indent(
499
- cbw.writeLine(
500
- "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
501
- ),
502
- );
503
- yield* cbw.writeLine(">();");
504
- }),
505
- );
506
- yield* cbw.writeLine(
507
- "export type MutationCtx = typeof MutationCtx.Identifier;",
508
- );
509
- yield* cbw.blankLine();
510
-
511
- // ActionCtx
512
- yield* cbw.writeLine("export const ActionCtx =");
513
- yield* cbw.indent(
514
- Effect.gen(function* () {
515
- yield* cbw.writeLine("ActionCtx_.ActionCtx<");
516
- yield* cbw.indent(
517
- cbw.writeLine(
518
- "DataModel.ToConvex<DataModel.FromSchema<typeof schemaDefinition>>",
519
- ),
520
- );
521
- yield* cbw.writeLine(">();");
522
- }),
523
- );
524
- yield* cbw.writeLine(
525
- "export type ActionCtx = typeof ActionCtx.Identifier;",
526
- );
527
-
528
- return yield* cbw.toString();
529
- });
530
-
531
- const writeChildAddGroupAt = (
532
- cbw: CodeBlockWriter,
533
- child: SpecAssemblyNode,
534
- groupFactory: string,
535
- ): Effect.Effect<void> =>
536
- Effect.gen(function* () {
537
- yield* cbw.write(".addGroupAt(");
538
- yield* cbw.quote(child.segment);
539
- yield* cbw.write(", ");
540
- yield* writeGroupAssembly(cbw, child, groupFactory);
541
- yield* cbw.write(")");
542
- });
543
-
544
- const writeGroupFactoryCall = (
545
- cbw: CodeBlockWriter,
546
- node: SpecAssemblyNode,
547
- groupFactory: string,
548
- ): Effect.Effect<void> =>
549
- Effect.gen(function* () {
550
- yield* cbw.write(groupFactory);
551
- yield* cbw.write("(");
552
- yield* cbw.quote(node.segment);
553
- yield* cbw.write(")");
554
-
555
- yield* Effect.forEach(node.children, (child) =>
556
- writeChildAddGroupAt(cbw, child, groupFactory),
557
- );
558
- });
559
-
560
- const writeGroupAssembly: (
561
- cbw: CodeBlockWriter,
562
- node: SpecAssemblyNode,
563
- groupFactory: string,
564
- ) => Effect.Effect<void> = (cbw, node, groupFactory) =>
565
- Option.match(node.importBinding, {
566
- onNone: () => writeGroupFactoryCall(cbw, node, groupFactory),
567
- onSome: (binding) =>
568
- Effect.gen(function* () {
569
- yield* cbw.write(binding.localName);
570
- yield* Effect.forEach(node.children, (child) =>
571
- writeChildAddGroupAt(cbw, child, groupFactory),
572
- );
573
- }),
574
- });
575
-
576
- const writeRootAddAt = (
577
- cbw: CodeBlockWriter,
578
- node: SpecAssemblyNode,
579
- groupFactory: string,
580
- ): Effect.Effect<void> =>
581
- Effect.gen(function* () {
582
- yield* cbw.write(".addAt(");
583
- yield* cbw.quote(node.segment);
584
- yield* cbw.write(", ");
585
-
586
- yield* writeGroupAssembly(cbw, node, groupFactory);
587
-
588
- yield* cbw.write(")");
589
- });
590
-
591
- export const assembledSpec = ({
592
- nodes,
593
- runtime,
594
- }: {
595
- nodes: ReadonlyArray<SpecAssemblyNode>;
596
- runtime: "Convex" | "Node";
597
- }) =>
598
- Effect.gen(function* () {
599
- const cbw = new CodeBlockWriter({ indentNumberOfSpaces: 2 });
600
-
601
- const nodeRequiresGroupFactory = (node: SpecAssemblyNode): boolean =>
602
- Option.isNone(node.importBinding) ||
603
- Array.some(node.children, nodeRequiresGroupFactory);
604
-
605
- const needsGroupSpec = Array.some(nodes, nodeRequiresGroupFactory);
606
- yield* cbw.writeLine(
607
- needsGroupSpec
608
- ? `import { GroupSpec, Spec } from "@confect/core";`
609
- : `import { Spec } from "@confect/core";`,
610
- );
611
-
612
- yield* Effect.forEach(collectImportBindings(nodes), (binding) =>
613
- cbw.writeLine(
614
- `import ${binding.localName} from "${binding.importPath}";`,
615
- ),
616
- );
617
-
618
- yield* cbw.blankLine();
619
-
620
- const specFactory =
621
- runtime === "Convex" ? "Spec.make()" : "Spec.makeNode()";
622
- const groupFactory =
623
- runtime === "Convex" ? "GroupSpec.makeAt" : "GroupSpec.makeNodeAt";
624
-
625
- yield* cbw.write(`export default ${specFactory}`);
626
- yield* Effect.forEach(nodes, (node) =>
627
- writeRootAddAt(cbw, node, groupFactory),
628
- );
629
- yield* cbw.write(";");
630
- yield* cbw.newLine();
631
-
632
- return yield* cbw.toString();
633
- });