@confect/cli 9.0.0-next.0 → 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.
Files changed (69) hide show
  1. package/CHANGELOG.md +351 -1
  2. package/dist/BuildError.mjs +9 -2
  3. package/dist/BuildError.mjs.map +1 -1
  4. package/dist/Bundler.mjs +67 -57
  5. package/dist/Bundler.mjs.map +1 -1
  6. package/dist/CodeBlockWriter.mjs +1 -1
  7. package/dist/CodeBlockWriter.mjs.map +1 -1
  8. package/dist/CodegenError.mjs +36 -21
  9. package/dist/CodegenError.mjs.map +1 -1
  10. package/dist/ConfectDirectory.mjs +5 -2
  11. package/dist/ConfectDirectory.mjs.map +1 -1
  12. package/dist/ConvexDirectory.mjs +6 -2
  13. package/dist/ConvexDirectory.mjs.map +1 -1
  14. package/dist/FunctionPath.mjs +1 -1
  15. package/dist/FunctionPath.mjs.map +1 -1
  16. package/dist/FunctionPaths.mjs +5 -1
  17. package/dist/FunctionPaths.mjs.map +1 -1
  18. package/dist/GroupPath.mjs +9 -2
  19. package/dist/GroupPath.mjs.map +1 -1
  20. package/dist/GroupPaths.mjs +1 -1
  21. package/dist/GroupPaths.mjs.map +1 -1
  22. package/dist/LeafModule.mjs +20 -24
  23. package/dist/LeafModule.mjs.map +1 -1
  24. package/dist/ProjectRoot.mjs +8 -3
  25. package/dist/ProjectRoot.mjs.map +1 -1
  26. package/dist/SpecAssemblyNode.mjs +9 -11
  27. package/dist/SpecAssemblyNode.mjs.map +1 -1
  28. package/dist/TableModule.mjs +94 -0
  29. package/dist/TableModule.mjs.map +1 -0
  30. package/dist/cliApp.mjs +1 -1
  31. package/dist/cliApp.mjs.map +1 -1
  32. package/dist/confect/codegen.mjs +272 -141
  33. package/dist/confect/codegen.mjs.map +1 -1
  34. package/dist/confect/dev.mjs +36 -17
  35. package/dist/confect/dev.mjs.map +1 -1
  36. package/dist/confect.mjs +2 -2
  37. package/dist/confect.mjs.map +1 -1
  38. package/dist/index.mjs +3 -2
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/log.mjs +9 -4
  41. package/dist/log.mjs.map +1 -1
  42. package/dist/package.mjs +1 -1
  43. package/dist/templates.mjs +139 -48
  44. package/dist/templates.mjs.map +1 -1
  45. package/dist/utils.mjs +42 -22
  46. package/dist/utils.mjs.map +1 -1
  47. package/package.json +33 -50
  48. package/dist/index.d.mts +0 -1
  49. package/src/BuildError.ts +0 -210
  50. package/src/Bundler.ts +0 -144
  51. package/src/CodeBlockWriter.ts +0 -65
  52. package/src/CodegenError.ts +0 -344
  53. package/src/ConfectDirectory.ts +0 -42
  54. package/src/ConvexDirectory.ts +0 -68
  55. package/src/FunctionPath.ts +0 -27
  56. package/src/FunctionPaths.ts +0 -103
  57. package/src/GroupPath.ts +0 -118
  58. package/src/GroupPaths.ts +0 -7
  59. package/src/LeafModule.ts +0 -313
  60. package/src/ProjectRoot.ts +0 -50
  61. package/src/SpecAssemblyNode.ts +0 -82
  62. package/src/cliApp.ts +0 -8
  63. package/src/confect/codegen.ts +0 -589
  64. package/src/confect/dev.ts +0 -749
  65. package/src/confect.ts +0 -19
  66. package/src/index.ts +0 -22
  67. package/src/log.ts +0 -104
  68. package/src/templates.ts +0 -477
  69. package/src/utils.ts +0 -429
@@ -1,589 +0,0 @@
1
- import { Spec } from "@confect/core";
2
- import * as DatabaseSchema from "@confect/server/DatabaseSchema";
3
- import { Command } from "@effect/cli";
4
- import { FileSystem, Path } from "@effect/platform";
5
- import { Array, Effect, Either, HashSet, Match, Option, Ref } from "effect";
6
- import { fromBundlerError } from "../BuildError";
7
- import * as CodegenError from "../CodegenError";
8
- import {
9
- MissingImplFileError,
10
- MissingSchemaFileError,
11
- MissingSpecFileError,
12
- SchemaInvalidDefaultExportError,
13
- } from "../CodegenError";
14
- import { ConfectDirectory } from "../ConfectDirectory";
15
- import { ConvexDirectory } from "../ConvexDirectory";
16
- import * as FunctionPaths from "../FunctionPaths";
17
- import {
18
- logFileAdded,
19
- logFileModified,
20
- logFileRemoved,
21
- logPending,
22
- logSuccess,
23
- } from "../log";
24
- import {
25
- discoverLeafImplFiles,
26
- discoverLeafSpecFiles,
27
- implPathForSpec,
28
- registeredFunctionsRelativePath,
29
- specPathForImpl,
30
- toLeafModule,
31
- toNodeRegistryLeaf,
32
- validateImpl,
33
- validateSpec,
34
- type LeafModule,
35
- } from "../LeafModule";
36
- import {
37
- assemblyNodesFromLeaves,
38
- partitionByRuntime,
39
- } from "../SpecAssemblyNode";
40
- import * as templates from "../templates";
41
- import * as Bundler from "../Bundler";
42
- import {
43
- generateAuthConfig,
44
- generateCrons,
45
- generateFunctions,
46
- generateHttp,
47
- removePathExtension,
48
- removePathIfExists,
49
- toModuleImportPath,
50
- touchConvexSchema,
51
- writeFileStringAndLog,
52
- WriteTracker,
53
- } from "../utils";
54
-
55
- const GENERATED_SPEC_PATH = "_generated/spec.ts";
56
- const GENERATED_NODE_SPEC_PATH = "_generated/nodeSpec.ts";
57
-
58
- const LEGACY_PATHS = [
59
- "spec.ts",
60
- "nodeSpec.ts",
61
- "impl.ts",
62
- "nodeImpl.ts",
63
- "notesAndRandom.impl.ts",
64
- "groups.impl.ts",
65
- "_generated/registeredFunctions.ts",
66
- "_generated/nodeRegisteredFunctions.ts",
67
- "_generated/impl.ts",
68
- "_generated/nodeImpl.ts",
69
- ];
70
-
71
- export const codegen = Command.make("codegen", {}, () =>
72
- Effect.gen(function* () {
73
- yield* logPending("Performing initial sync…");
74
- yield* codegenHandler.pipe(
75
- Effect.asVoid,
76
- Effect.tap(() => logSuccess("Generated files are up-to-date")),
77
- CodegenError.tapAndLog,
78
- );
79
- }),
80
- ).pipe(
81
- Command.withDescription(
82
- "Generate `confect/_generated` files and the contents of the `convex` directory (except `convex.config.ts` and `tsconfig.json`)",
83
- ),
84
- );
85
-
86
- export const codegenHandler = Effect.gen(function* () {
87
- const tracker = yield* Ref.make(false);
88
-
89
- const functionPaths = yield* runCodegen.pipe(
90
- Effect.provideService(WriteTracker, tracker),
91
- );
92
-
93
- const anyWritesHappened = yield* Ref.get(tracker);
94
- return { functionPaths, anyWritesHappened };
95
- });
96
-
97
- const runCodegen = Effect.gen(function* () {
98
- yield* generateConfectGeneratedDirectory;
99
- // Validate schema first so its missing-file / invalid-default-export
100
- // diagnostics surface ahead of impl bundling, which transitively depends
101
- // on schema via `_generated/api.ts` and would otherwise blow up with a
102
- // less actionable bundler error.
103
- yield* validateSchema;
104
- const leaves = yield* loadAndValidateLeafModules;
105
- yield* removeLegacyFiles;
106
- yield* generateAssembledSpecs(leaves);
107
- yield* validateImplModules(leaves);
108
- yield* generateGroupRegisteredFunctions(leaves);
109
- yield* removeObsoleteRegisteredFunctions(leaves);
110
- yield* Effect.all(
111
- [generateApi, generateRefs, generateNodeApi, generateServices],
112
- { concurrency: "unbounded" },
113
- );
114
- const [functionPaths] = yield* Effect.all(
115
- [
116
- generateFunctionModules,
117
- generateSchema,
118
- logGenerated(generateHttp),
119
- logGenerated(generateCrons),
120
- logGenerated(generateAuthConfig),
121
- ],
122
- { concurrency: "unbounded" },
123
- );
124
- yield* touchConvexSchema;
125
- return functionPaths;
126
- });
127
-
128
- const generateConfectGeneratedDirectory = Effect.gen(function* () {
129
- const fs = yield* FileSystem.FileSystem;
130
- const path = yield* Path.Path;
131
- const confectDirectory = yield* ConfectDirectory.get;
132
-
133
- if (!(yield* fs.exists(path.join(confectDirectory, "_generated")))) {
134
- yield* fs.makeDirectory(path.join(confectDirectory, "_generated"), {
135
- recursive: true,
136
- });
137
- yield* logFileAdded(path.join(confectDirectory, "_generated") + "/");
138
- }
139
- });
140
-
141
- const loadAndValidateLeafModules = Effect.gen(function* () {
142
- const fs = yield* FileSystem.FileSystem;
143
- const path = yield* Path.Path;
144
- const confectDirectory = yield* ConfectDirectory.get;
145
- const specFiles = yield* discoverLeafSpecFiles;
146
-
147
- const leaves = yield* Effect.forEach(specFiles, (specRelativePath) =>
148
- Effect.gen(function* () {
149
- const leaf = yield* toLeafModule(specRelativePath);
150
- yield* validateSpec(leaf);
151
-
152
- const implRelativePath = yield* implPathForSpec(specRelativePath);
153
- const implAbsolutePath = path.join(confectDirectory, implRelativePath);
154
- if (!(yield* fs.exists(implAbsolutePath))) {
155
- return yield* new MissingImplFileError({
156
- specPath: specRelativePath,
157
- expectedImplPath: implRelativePath,
158
- });
159
- }
160
-
161
- return leaf;
162
- }),
163
- );
164
-
165
- yield* validateOrphanImpls(specFiles);
166
-
167
- return leaves;
168
- });
169
-
170
- const validateOrphanImpls = (specFiles: ReadonlyArray<string>) =>
171
- Effect.gen(function* () {
172
- const fs = yield* FileSystem.FileSystem;
173
- const path = yield* Path.Path;
174
- const confectDirectory = yield* ConfectDirectory.get;
175
- const implFiles = yield* discoverLeafImplFiles;
176
- const specPaths = new Set(specFiles);
177
-
178
- yield* Effect.forEach(implFiles, (implRelativePath) =>
179
- Effect.gen(function* () {
180
- const specRelativePath = yield* specPathForImpl(implRelativePath);
181
- if (specPaths.has(specRelativePath)) {
182
- return;
183
- }
184
-
185
- const specAbsolutePath = path.join(confectDirectory, specRelativePath);
186
- if (!(yield* fs.exists(specAbsolutePath))) {
187
- return yield* new MissingSpecFileError({
188
- implPath: implRelativePath,
189
- expectedSpecPath: specRelativePath,
190
- });
191
- }
192
- }),
193
- );
194
- });
195
-
196
- const removeLegacyFiles = Effect.gen(function* () {
197
- const fs = yield* FileSystem.FileSystem;
198
- const path = yield* Path.Path;
199
- const confectDirectory = yield* ConfectDirectory.get;
200
-
201
- yield* Effect.forEach(LEGACY_PATHS, (relativePath) =>
202
- Effect.gen(function* () {
203
- const absolutePath = path.join(confectDirectory, relativePath);
204
- if (yield* fs.exists(absolutePath)) {
205
- yield* removePathIfExists(absolutePath);
206
- yield* logFileRemoved(absolutePath);
207
- }
208
- }),
209
- );
210
- });
211
-
212
- const generateAssembledSpecs = (leaves: ReadonlyArray<LeafModule>) =>
213
- Effect.gen(function* () {
214
- const path = yield* Path.Path;
215
- const confectDirectory = yield* ConfectDirectory.get;
216
- const { convex, node } = partitionByRuntime(leaves);
217
-
218
- if (convex.length > 0) {
219
- const nodes = assemblyNodesFromLeaves(convex);
220
- const specContents = yield* templates.assembledSpec({
221
- nodes,
222
- runtime: "Convex",
223
- });
224
- yield* writeFileStringAndLog(
225
- path.join(confectDirectory, GENERATED_SPEC_PATH),
226
- specContents,
227
- );
228
- }
229
-
230
- if (node.length > 0) {
231
- const nodes = assemblyNodesFromLeaves(
232
- Array.map(node, toNodeRegistryLeaf),
233
- );
234
- const nodeSpecContents = yield* templates.assembledSpec({
235
- nodes,
236
- runtime: "Node",
237
- });
238
- yield* writeFileStringAndLog(
239
- path.join(confectDirectory, GENERATED_NODE_SPEC_PATH),
240
- nodeSpecContents,
241
- );
242
- }
243
- });
244
-
245
- const validateImplModules = (leaves: ReadonlyArray<LeafModule>) =>
246
- Effect.forEach(leaves, validateImpl);
247
-
248
- const generateGroupRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>
249
- Effect.gen(function* () {
250
- const path = yield* Path.Path;
251
- const confectDirectory = yield* ConfectDirectory.get;
252
-
253
- yield* Effect.forEach(leaves, (leaf) =>
254
- Effect.gen(function* () {
255
- const registryRelativePath =
256
- yield* registeredFunctionsRelativePath(leaf);
257
- const registryPath = path.join(
258
- confectDirectory,
259
- "_generated",
260
- registryRelativePath,
261
- );
262
- const registryDir = path.dirname(registryPath);
263
- const fs = yield* FileSystem.FileSystem;
264
- if (!(yield* fs.exists(registryDir))) {
265
- yield* fs.makeDirectory(registryDir, { recursive: true });
266
- }
267
-
268
- const implRelativePath = yield* implPathForSpec(leaf.relativePath);
269
- const apiFileName = leaf.runtime === "Node" ? "nodeApi.ts" : "api.ts";
270
- const apiImportPath = yield* toModuleImportPath(
271
- path.relative(
272
- path.dirname(registryPath),
273
- path.join(confectDirectory, "_generated", apiFileName),
274
- ),
275
- );
276
- const implImportPath = yield* toModuleImportPath(
277
- path.relative(
278
- path.dirname(registryPath),
279
- path.join(confectDirectory, implRelativePath),
280
- ),
281
- );
282
-
283
- const contents = yield* templates.registeredFunctionsForGroup({
284
- apiImportPath,
285
- groupPathDot: leaf.registryGroupPathDot,
286
- implImportPath,
287
- layerExportName: leaf.exportName,
288
- useNode: leaf.runtime === "Node",
289
- });
290
-
291
- yield* writeFileStringAndLog(registryPath, contents);
292
- }),
293
- );
294
- });
295
-
296
- const removeObsoleteRegisteredFunctions = (leaves: ReadonlyArray<LeafModule>) =>
297
- Effect.gen(function* () {
298
- const fs = yield* FileSystem.FileSystem;
299
- const path = yield* Path.Path;
300
- const confectDirectory = yield* ConfectDirectory.get;
301
- const registryRoot = path.join(
302
- confectDirectory,
303
- "_generated",
304
- "registeredFunctions",
305
- );
306
-
307
- if (!(yield* fs.exists(registryRoot))) {
308
- return;
309
- }
310
-
311
- const expected = new Set(
312
- yield* Effect.forEach(leaves, (leaf) =>
313
- registeredFunctionsRelativePath(leaf),
314
- ),
315
- );
316
-
317
- const existing = yield* fs.readDirectory(registryRoot, { recursive: true });
318
- yield* Effect.forEach(existing, (relativePath) => {
319
- if (path.extname(relativePath) !== ".ts") {
320
- return Effect.void;
321
- }
322
- const normalized = path.join("registeredFunctions", relativePath);
323
- if (!expected.has(normalized)) {
324
- return Effect.gen(function* () {
325
- const absolutePath = path.join(registryRoot, relativePath);
326
- if (yield* fs.exists(absolutePath)) {
327
- yield* removePathIfExists(absolutePath);
328
- yield* logFileRemoved(absolutePath);
329
- }
330
- });
331
- }
332
- return Effect.void;
333
- });
334
- });
335
-
336
- const getGeneratedSpecPath = Effect.gen(function* () {
337
- const path = yield* Path.Path;
338
- const confectDirectory = yield* ConfectDirectory.get;
339
- return path.join(confectDirectory, GENERATED_SPEC_PATH);
340
- });
341
-
342
- const getGeneratedNodeSpecPath = Effect.gen(function* () {
343
- const path = yield* Path.Path;
344
- const confectDirectory = yield* ConfectDirectory.get;
345
- return path.join(confectDirectory, GENERATED_NODE_SPEC_PATH);
346
- });
347
-
348
- const loadGeneratedSpec = Effect.gen(function* () {
349
- const specPath = yield* getGeneratedSpecPath;
350
- const { module: specModule } = yield* Bundler.bundle(specPath);
351
- const spec = specModule.default;
352
-
353
- if (!Spec.isConvexSpec(spec)) {
354
- return yield* Effect.dieMessage(
355
- "_generated/spec.ts does not export a valid Convex Spec",
356
- );
357
- }
358
-
359
- return spec;
360
- });
361
-
362
- const loadGeneratedNodeSpec = Effect.gen(function* () {
363
- const fs = yield* FileSystem.FileSystem;
364
- const nodeSpecPath = yield* getGeneratedNodeSpecPath;
365
-
366
- if (!(yield* fs.exists(nodeSpecPath))) {
367
- return Option.none<Spec.AnyWithPropsWithRuntime<"Node">>();
368
- }
369
-
370
- const { module: nodeSpecModule } = yield* Bundler.bundle(nodeSpecPath);
371
- const nodeSpec = nodeSpecModule.default;
372
-
373
- if (!Spec.isNodeSpec(nodeSpec)) {
374
- return yield* Effect.dieMessage(
375
- "_generated/nodeSpec.ts does not export a valid Node Spec",
376
- );
377
- }
378
-
379
- return Option.some(nodeSpec);
380
- });
381
-
382
- const emptyFunctionPaths = FunctionPaths.FunctionPaths.make(HashSet.empty());
383
-
384
- export const loadPreviousFunctionPaths = Effect.gen(function* () {
385
- const fs = yield* FileSystem.FileSystem;
386
- const specPath = yield* getGeneratedSpecPath;
387
-
388
- if (!(yield* fs.exists(specPath))) {
389
- return emptyFunctionPaths;
390
- }
391
-
392
- const specEither = yield* loadGeneratedSpec.pipe(Effect.either);
393
-
394
- return yield* Either.match(specEither, {
395
- onLeft: () => Effect.succeed(emptyFunctionPaths),
396
- onRight: (spec) =>
397
- Effect.gen(function* () {
398
- const nodeSpecOption = yield* loadGeneratedNodeSpec;
399
- const mergedSpec = Option.match(nodeSpecOption, {
400
- onNone: () => spec,
401
- onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),
402
- });
403
- return FunctionPaths.make(mergedSpec);
404
- }),
405
- });
406
- });
407
-
408
- const generateApi = Effect.gen(function* () {
409
- const path = yield* Path.Path;
410
- const confectDirectory = yield* ConfectDirectory.get;
411
-
412
- const apiPath = path.join(confectDirectory, "_generated", "api.ts");
413
- const apiDir = path.dirname(apiPath);
414
-
415
- const schemaImportPath = yield* toModuleImportPath(
416
- path.relative(apiDir, path.join(confectDirectory, "schema.ts")),
417
- );
418
-
419
- const specImportPath = yield* toModuleImportPath(
420
- path.relative(apiDir, path.join(confectDirectory, GENERATED_SPEC_PATH)),
421
- );
422
-
423
- const apiContents = yield* templates.api({
424
- schemaImportPath,
425
- specImportPath,
426
- });
427
-
428
- yield* writeFileStringAndLog(apiPath, apiContents);
429
- });
430
-
431
- export const generateNodeApi = Effect.gen(function* () {
432
- const fs = yield* FileSystem.FileSystem;
433
- const path = yield* Path.Path;
434
- const confectDirectory = yield* ConfectDirectory.get;
435
-
436
- const nodeSpecPath = yield* getGeneratedNodeSpecPath;
437
- const nodeApiPath = path.join(confectDirectory, "_generated", "nodeApi.ts");
438
-
439
- if (!(yield* fs.exists(nodeSpecPath))) {
440
- if (yield* fs.exists(nodeApiPath)) {
441
- yield* removePathIfExists(nodeApiPath);
442
- yield* logFileRemoved(nodeApiPath);
443
- }
444
- return;
445
- }
446
-
447
- const nodeApiDir = path.dirname(nodeApiPath);
448
-
449
- const schemaImportPath = yield* toModuleImportPath(
450
- path.relative(nodeApiDir, path.join(confectDirectory, "schema.ts")),
451
- );
452
-
453
- const nodeSpecImportPath = yield* toModuleImportPath(
454
- path.relative(nodeApiDir, nodeSpecPath),
455
- );
456
-
457
- const nodeApiContents = yield* templates.nodeApi({
458
- schemaImportPath,
459
- nodeSpecImportPath,
460
- });
461
-
462
- yield* writeFileStringAndLog(nodeApiPath, nodeApiContents);
463
- });
464
-
465
- const generateFunctionModules = Effect.gen(function* () {
466
- const spec = yield* loadGeneratedSpec;
467
- const nodeSpecOption = yield* loadGeneratedNodeSpec;
468
-
469
- const mergedSpec = Option.match(nodeSpecOption, {
470
- onNone: () => spec,
471
- onSome: (nodeSpec) => Spec.merge(spec, nodeSpec),
472
- });
473
-
474
- return yield* generateFunctions(mergedSpec);
475
- });
476
-
477
- export const validateSchema = Effect.gen(function* () {
478
- const fs = yield* FileSystem.FileSystem;
479
- const path = yield* Path.Path;
480
- const confectDirectory = yield* ConfectDirectory.get;
481
- const confectSchemaPath = path.join(confectDirectory, "schema.ts");
482
-
483
- if (!(yield* fs.exists(confectSchemaPath))) {
484
- return yield* new MissingSchemaFileError({ schemaPath: "schema.ts" });
485
- }
486
-
487
- yield* Bundler.bundle(confectSchemaPath).pipe(
488
- Effect.mapError((error) => fromBundlerError("schema.ts", error)),
489
- Effect.andThen(({ module: schemaModule }) => {
490
- const defaultExport = schemaModule.default;
491
-
492
- return DatabaseSchema.isDatabaseSchema(defaultExport)
493
- ? Effect.succeed(defaultExport)
494
- : Effect.fail(
495
- new SchemaInvalidDefaultExportError({
496
- schemaPath: "schema.ts",
497
- }),
498
- );
499
- }),
500
- );
501
- });
502
-
503
- const generateSchema = Effect.gen(function* () {
504
- const path = yield* Path.Path;
505
- const confectDirectory = yield* ConfectDirectory.get;
506
- const convexDirectory = yield* ConvexDirectory.get;
507
-
508
- const confectSchemaPath = path.join(confectDirectory, "schema.ts");
509
-
510
- // `validateSchema` runs once at the top of `runCodegen`; no need to
511
- // bundle the schema again here.
512
-
513
- const convexSchemaPath = path.join(convexDirectory, "schema.ts");
514
-
515
- const relativeImportPath = path.relative(
516
- path.dirname(convexSchemaPath),
517
- confectSchemaPath,
518
- );
519
- const importPathWithoutExt = yield* removePathExtension(relativeImportPath);
520
- const schemaContents = yield* templates.schema({
521
- schemaImportPath: importPathWithoutExt,
522
- });
523
-
524
- yield* writeFileStringAndLog(convexSchemaPath, schemaContents);
525
- });
526
-
527
- const generateServices = Effect.gen(function* () {
528
- const path = yield* Path.Path;
529
- const confectDirectory = yield* ConfectDirectory.get;
530
-
531
- const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
532
-
533
- const servicesPath = path.join(confectGeneratedDirectory, "services.ts");
534
- const schemaImportPath = path.relative(
535
- path.dirname(servicesPath),
536
- path.join(confectDirectory, "schema"),
537
- );
538
-
539
- const servicesContentsString = yield* templates.services({
540
- schemaImportPath,
541
- });
542
-
543
- yield* writeFileStringAndLog(servicesPath, servicesContentsString);
544
- });
545
-
546
- const generateRefs = Effect.gen(function* () {
547
- const fs = yield* FileSystem.FileSystem;
548
- const path = yield* Path.Path;
549
- const confectDirectory = yield* ConfectDirectory.get;
550
-
551
- const confectGeneratedDirectory = path.join(confectDirectory, "_generated");
552
- const refsPath = path.join(confectGeneratedDirectory, "refs.ts");
553
- const refsDir = path.dirname(refsPath);
554
-
555
- const specImportPath = yield* toModuleImportPath(
556
- path.relative(refsDir, path.join(confectDirectory, GENERATED_SPEC_PATH)),
557
- );
558
-
559
- const nodeSpecPath = yield* getGeneratedNodeSpecPath;
560
- const nodeSpecExists = yield* fs.exists(nodeSpecPath);
561
- const nodeSpecImportPath = nodeSpecExists
562
- ? Option.some(
563
- yield* toModuleImportPath(path.relative(refsDir, nodeSpecPath)),
564
- )
565
- : Option.none<string>();
566
-
567
- const refsContents = yield* templates.refs({
568
- specImportPath,
569
- nodeSpecImportPath,
570
- });
571
-
572
- yield* writeFileStringAndLog(refsPath, refsContents);
573
- });
574
-
575
- const logGenerated = (effect: typeof generateHttp) =>
576
- effect.pipe(
577
- Effect.tap(
578
- Option.match({
579
- onNone: () => Effect.void,
580
- onSome: ({ change, convexFilePath }) =>
581
- Match.value(change).pipe(
582
- Match.when("Added", () => logFileAdded(convexFilePath)),
583
- Match.when("Modified", () => logFileModified(convexFilePath)),
584
- Match.when("Unchanged", () => Effect.void),
585
- Match.exhaustive,
586
- ),
587
- }),
588
- ),
589
- );