@gaganref/confect-cli 0.0.0-stage → 10.3.1-fork.1
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 +1824 -0
- package/LICENSE +7 -0
- package/README.md +16 -2
- package/bin/confect.mjs +26 -0
- package/dist/Ansi.mjs +18 -0
- package/dist/Ansi.mjs.map +1 -0
- package/dist/BuildError.mjs +30 -0
- package/dist/BuildError.mjs.map +1 -0
- package/dist/Bundler.mjs +426 -0
- package/dist/Bundler.mjs.map +1 -0
- package/dist/CodeBlockWriter.mjs +55 -0
- package/dist/CodeBlockWriter.mjs.map +1 -0
- package/dist/CodegenError.mjs +194 -0
- package/dist/CodegenError.mjs.map +1 -0
- package/dist/ConfectDirectory.mjs +35 -0
- package/dist/ConfectDirectory.mjs.map +1 -0
- package/dist/ConvexConfig.mjs +198 -0
- package/dist/ConvexConfig.mjs.map +1 -0
- package/dist/ConvexDirectory.mjs +54 -0
- package/dist/ConvexDirectory.mjs.map +1 -0
- package/dist/Declaration.mjs +258 -0
- package/dist/Declaration.mjs.map +1 -0
- package/dist/DirectoryOptions.mjs +42 -0
- package/dist/DirectoryOptions.mjs.map +1 -0
- package/dist/DocName.mjs +25 -0
- package/dist/DocName.mjs.map +1 -0
- package/dist/EntryPoint.mjs +111 -0
- package/dist/EntryPoint.mjs.map +1 -0
- package/dist/Evaluation.mjs +117 -0
- package/dist/Evaluation.mjs.map +1 -0
- package/dist/EvaluationWorker.mjs +46 -0
- package/dist/EvaluationWorker.mjs.map +1 -0
- package/dist/FunctionModule.mjs +137 -0
- package/dist/FunctionModule.mjs.map +1 -0
- package/dist/FunctionPath.mjs +18 -0
- package/dist/FunctionPath.mjs.map +1 -0
- package/dist/FunctionPaths.mjs +45 -0
- package/dist/FunctionPaths.mjs.map +1 -0
- package/dist/GenerationSnapshot.mjs +183 -0
- package/dist/GenerationSnapshot.mjs.map +1 -0
- package/dist/GroupPath.mjs +51 -0
- package/dist/GroupPath.mjs.map +1 -0
- package/dist/GroupPaths.mjs +8 -0
- package/dist/GroupPaths.mjs.map +1 -0
- package/dist/ImplModulePath.mjs +8 -0
- package/dist/ImplModulePath.mjs.map +1 -0
- package/dist/LeafModule.mjs +285 -0
- package/dist/LeafModule.mjs.map +1 -0
- package/dist/ProjectRoot.mjs +38 -0
- package/dist/ProjectRoot.mjs.map +1 -0
- package/dist/RelativeModulePath.mjs +13 -0
- package/dist/RelativeModulePath.mjs.map +1 -0
- package/dist/Remove.mjs +24 -0
- package/dist/Remove.mjs.map +1 -0
- package/dist/RestoreWatcher.mjs +31 -0
- package/dist/RestoreWatcher.mjs.map +1 -0
- package/dist/Rollback.mjs +50 -0
- package/dist/Rollback.mjs.map +1 -0
- package/dist/SnapshotError.mjs +21 -0
- package/dist/SnapshotError.mjs.map +1 -0
- package/dist/SpecAssemblyNode.mjs +91 -0
- package/dist/SpecAssemblyNode.mjs.map +1 -0
- package/dist/SpecModulePath.mjs +10 -0
- package/dist/SpecModulePath.mjs.map +1 -0
- package/dist/SyncState.mjs +122 -0
- package/dist/SyncState.mjs.map +1 -0
- package/dist/TableModule.mjs +97 -0
- package/dist/TableModule.mjs.map +1 -0
- package/dist/TableModulePath.mjs +8 -0
- package/dist/TableModulePath.mjs.map +1 -0
- package/dist/WatchBuild.mjs +190 -0
- package/dist/WatchBuild.mjs.map +1 -0
- package/dist/WatchGraph.mjs +35 -0
- package/dist/WatchGraph.mjs.map +1 -0
- package/dist/WatchTopology.mjs +55 -0
- package/dist/WatchTopology.mjs.map +1 -0
- package/dist/Watcher.mjs +378 -0
- package/dist/Watcher.mjs.map +1 -0
- package/dist/cliApp.mjs +9 -0
- package/dist/cliApp.mjs.map +1 -0
- package/dist/confect/codegen.mjs +548 -0
- package/dist/confect/codegen.mjs.map +1 -0
- package/dist/confect/declaration.mjs +218 -0
- package/dist/confect/declaration.mjs.map +1 -0
- package/dist/confect/dev.mjs +182 -0
- package/dist/confect/dev.mjs.map +1 -0
- package/dist/confect.mjs +9 -0
- package/dist/confect.mjs.map +1 -0
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -0
- package/dist/log.mjs +107 -0
- package/dist/log.mjs.map +1 -0
- package/dist/package.mjs +6 -0
- package/dist/package.mjs.map +1 -0
- package/dist/templates.mjs +448 -0
- package/dist/templates.mjs.map +1 -0
- package/dist/utils.mjs +105 -0
- package/dist/utils.mjs.map +1 -0
- package/package.json +51 -3
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import CodeBlockWriter_ from "code-block-writer";
|
|
3
|
+
//#region src/CodeBlockWriter.ts
|
|
4
|
+
const indentWriter = Effect.fnUntraced(function* (writer, effect) {
|
|
5
|
+
const indentationLevel = writer.getIndentationLevel();
|
|
6
|
+
writer.setIndentationLevel(indentationLevel + 1);
|
|
7
|
+
yield* effect;
|
|
8
|
+
writer.setIndentationLevel(indentationLevel);
|
|
9
|
+
});
|
|
10
|
+
var CodeBlockWriter = class {
|
|
11
|
+
writer;
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.writer = new CodeBlockWriter_(opts);
|
|
14
|
+
}
|
|
15
|
+
indent(effect) {
|
|
16
|
+
return indentWriter(this.writer, effect);
|
|
17
|
+
}
|
|
18
|
+
writeLine(line) {
|
|
19
|
+
return Effect.sync(() => {
|
|
20
|
+
this.writer.writeLine(line);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
write(text) {
|
|
24
|
+
return Effect.sync(() => {
|
|
25
|
+
this.writer.write(text);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
quote(text) {
|
|
29
|
+
return Effect.sync(() => {
|
|
30
|
+
this.writer.quote(text);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
conditionalWriteLine(condition, text) {
|
|
34
|
+
return Effect.sync(() => {
|
|
35
|
+
this.writer.conditionalWriteLine(condition, text);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
newLine() {
|
|
39
|
+
return Effect.sync(() => {
|
|
40
|
+
this.writer.newLine();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
blankLine() {
|
|
44
|
+
return Effect.sync(() => {
|
|
45
|
+
this.writer.blankLine();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
toString() {
|
|
49
|
+
return Effect.sync(() => this.writer.toString());
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { CodeBlockWriter };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=CodeBlockWriter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeBlockWriter.mjs","names":[],"sources":["../src/CodeBlockWriter.ts"],"sourcesContent":["import type { Options as CodeBlockWriterOptions } from \"code-block-writer\";\nimport CodeBlockWriter_ from \"code-block-writer\";\nimport * as Effect from \"effect/Effect\";\n\nconst indentWriter = Effect.fnUntraced(function* <E, R>(\n writer: CodeBlockWriter_,\n effect: Effect.Effect<void, E, R>,\n): Effect.fn.Return<void, E, R> {\n const indentationLevel = writer.getIndentationLevel();\n writer.setIndentationLevel(indentationLevel + 1);\n yield* effect;\n writer.setIndentationLevel(indentationLevel);\n});\n\nexport class CodeBlockWriter {\n private readonly writer: CodeBlockWriter_;\n\n constructor(opts?: Partial<CodeBlockWriterOptions>) {\n this.writer = new CodeBlockWriter_(opts);\n }\n\n indent<E = never, R = never>(\n effect: Effect.Effect<void, E, R>,\n ): Effect.Effect<void, E, R> {\n return indentWriter(this.writer, effect);\n }\n\n writeLine<E = never, R = never>(line: string): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.writeLine(line);\n });\n }\n\n write<E = never, R = never>(text: string): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.write(text);\n });\n }\n\n quote<E = never, R = never>(text: string): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.quote(text);\n });\n }\n\n conditionalWriteLine<E = never, R = never>(\n condition: boolean,\n text: string,\n ): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.conditionalWriteLine(condition, text);\n });\n }\n\n newLine<E = never, R = never>(): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.newLine();\n });\n }\n\n blankLine<E = never, R = never>(): Effect.Effect<void, E, R> {\n return Effect.sync(() => {\n this.writer.blankLine();\n });\n }\n\n toString<E = never, R = never>(): Effect.Effect<string, E, R> {\n return Effect.sync(() => this.writer.toString());\n }\n}\n"],"mappings":";;;AAIA,MAAM,eAAe,OAAO,WAAW,WACrC,QACA,QAC8B;CAC9B,MAAM,mBAAmB,OAAO,oBAAoB;CACpD,OAAO,oBAAoB,mBAAmB,CAAC;CAC/C,OAAO;CACP,OAAO,oBAAoB,gBAAgB;AAC7C,CAAC;AAED,IAAa,kBAAb,MAA6B;CAC3B;CAEA,YAAY,MAAwC;EAClD,KAAK,SAAS,IAAI,iBAAiB,IAAI;CACzC;CAEA,OACE,QAC2B;EAC3B,OAAO,aAAa,KAAK,QAAQ,MAAM;CACzC;CAEA,UAAgC,MAAyC;EACvE,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,UAAU,IAAI;EAC5B,CAAC;CACH;CAEA,MAA4B,MAAyC;EACnE,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,MAAM,IAAI;EACxB,CAAC;CACH;CAEA,MAA4B,MAAyC;EACnE,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,MAAM,IAAI;EACxB,CAAC;CACH;CAEA,qBACE,WACA,MAC2B;EAC3B,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,qBAAqB,WAAW,IAAI;EAClD,CAAC;CACH;CAEA,UAA2D;EACzD,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,QAAQ;EACtB,CAAC;CACH;CAEA,YAA6D;EAC3D,OAAO,OAAO,WAAW;GACvB,KAAK,OAAO,UAAU;EACxB,CAAC;CACH;CAEA,WAA8D;EAC5D,OAAO,OAAO,WAAW,KAAK,OAAO,SAAS,CAAC;CACjD;AACF"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { BuildError, isBuildError } from "./BuildError.mjs";
|
|
2
|
+
import { red } from "./Ansi.mjs";
|
|
3
|
+
import { formatPath, renderBuildError } from "./log.mjs";
|
|
4
|
+
import { SnapshotError } from "./SnapshotError.mjs";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Array from "effect/Array";
|
|
7
|
+
import { pipe } from "effect/Function";
|
|
8
|
+
import * as Match from "effect/Match";
|
|
9
|
+
import "effect/Option";
|
|
10
|
+
import * as Schema from "effect/Schema";
|
|
11
|
+
import * as Console from "effect/Console";
|
|
12
|
+
//#region src/CodegenError.ts
|
|
13
|
+
var MissingImplFileError = class extends Schema.TaggedError()("MissingImplFileError", {
|
|
14
|
+
specPath: Schema.String,
|
|
15
|
+
expectedImplPath: Schema.String
|
|
16
|
+
}) {};
|
|
17
|
+
var MissingSpecFileError = class extends Schema.TaggedError()("MissingSpecFileError", {
|
|
18
|
+
implPath: Schema.String,
|
|
19
|
+
expectedSpecPath: Schema.String
|
|
20
|
+
}) {};
|
|
21
|
+
var SpecMissingDefaultGroupSpecError = class extends Schema.TaggedError()("SpecMissingDefaultGroupSpecError", { specPath: Schema.String }) {};
|
|
22
|
+
var RemoveBusyError = class extends Schema.TaggedError()("RemoveBusyError", {
|
|
23
|
+
path: Schema.String,
|
|
24
|
+
attempts: Schema.Finite,
|
|
25
|
+
cause: Schema.Unknown
|
|
26
|
+
}) {};
|
|
27
|
+
var ComponentNodeGroupError = class extends Schema.TaggedError()("ComponentNodeGroupError", {
|
|
28
|
+
specPath: Schema.String,
|
|
29
|
+
groupPath: Schema.String
|
|
30
|
+
}) {};
|
|
31
|
+
var SpecImportsServerError = class extends Schema.TaggedError()("SpecImportsServerError", {
|
|
32
|
+
specPath: Schema.String,
|
|
33
|
+
importerPaths: Schema.Array(Schema.String)
|
|
34
|
+
}) {};
|
|
35
|
+
var InvalidMiddlewareAttachmentError = class extends Schema.TaggedError()("InvalidMiddlewareAttachmentError", {
|
|
36
|
+
specPath: Schema.String,
|
|
37
|
+
message: Schema.String
|
|
38
|
+
}) {};
|
|
39
|
+
var ImplMissingSpecImportError = class extends Schema.TaggedError()("ImplMissingSpecImportError", {
|
|
40
|
+
implPath: Schema.String,
|
|
41
|
+
expectedSpecPath: Schema.String
|
|
42
|
+
}) {};
|
|
43
|
+
var ImplMissingDefaultLayerError = class extends Schema.TaggedError()("ImplMissingDefaultLayerError", { implPath: Schema.String }) {};
|
|
44
|
+
var ImplNotFinalizedError = class extends Schema.TaggedError()("ImplNotFinalizedError", { implPath: Schema.String }) {};
|
|
45
|
+
var ImplMissingFunctionsError = class extends Schema.TaggedError()("ImplMissingFunctionsError", {
|
|
46
|
+
implPath: Schema.String,
|
|
47
|
+
groupPath: Schema.String,
|
|
48
|
+
missingFunctionNames: Schema.Array(Schema.String)
|
|
49
|
+
}) {};
|
|
50
|
+
var ImplMissingMiddlewareError = class extends Schema.TaggedError()("ImplMissingMiddlewareError", {
|
|
51
|
+
implPath: Schema.String,
|
|
52
|
+
groupPath: Schema.String,
|
|
53
|
+
missingMiddlewareKeys: Schema.Array(Schema.String)
|
|
54
|
+
}) {};
|
|
55
|
+
var ParentChildNameCollisionError = class extends Schema.TaggedError()("ParentChildNameCollisionError", {
|
|
56
|
+
parentSpecPath: Schema.String,
|
|
57
|
+
childSpecPath: Schema.String,
|
|
58
|
+
collisionName: Schema.String,
|
|
59
|
+
collisionKind: Schema.Literals(["function", "group"])
|
|
60
|
+
}) {};
|
|
61
|
+
var InvalidTableDefaultExportError = class extends Schema.TaggedError()("InvalidTableDefaultExportError", { tablePath: Schema.String }) {};
|
|
62
|
+
var InvalidTableFilenameError = class extends Schema.TaggedError()("InvalidTableFilenameError", {
|
|
63
|
+
tablePath: Schema.String,
|
|
64
|
+
reason: Schema.String
|
|
65
|
+
}) {};
|
|
66
|
+
var DuplicateTableNameError = class extends Schema.TaggedError()("DuplicateTableNameError", { collisions: Schema.Array(Schema.Struct({
|
|
67
|
+
tableName: Schema.String,
|
|
68
|
+
tablePaths: Schema.Array(Schema.String)
|
|
69
|
+
})) }) {};
|
|
70
|
+
var LegacySchemaFileError = class extends Schema.TaggedError()("LegacySchemaFileError", { schemaPath: Schema.String }) {};
|
|
71
|
+
var ConflictingDocNameError = class extends Schema.TaggedError()("ConflictingDocNameError", { collisions: Schema.Array(Schema.Struct({
|
|
72
|
+
docName: Schema.String,
|
|
73
|
+
tableNames: Schema.Array(Schema.String)
|
|
74
|
+
})) }) {};
|
|
75
|
+
var InvalidConvexConfigError = class extends Schema.TaggedError()("InvalidConvexConfigError", {
|
|
76
|
+
configPath: Schema.String,
|
|
77
|
+
reason: Schema.String
|
|
78
|
+
}) {};
|
|
79
|
+
var InvalidDeclarationError = class extends Schema.TaggedError()("InvalidDeclarationError", {
|
|
80
|
+
declarationPath: Schema.String,
|
|
81
|
+
reason: Schema.String
|
|
82
|
+
}) {};
|
|
83
|
+
var HandWrittenConvexFileError = class extends Schema.TaggedError()("HandWrittenConvexFileError", {
|
|
84
|
+
convexPath: Schema.String,
|
|
85
|
+
declarationPath: Schema.String
|
|
86
|
+
}) {};
|
|
87
|
+
var DeclarationKindMismatchError = class extends Schema.TaggedError()("DeclarationKindMismatchError", {
|
|
88
|
+
declarationPath: Schema.String,
|
|
89
|
+
declaredKind: Schema.Literals(["app", "component"]),
|
|
90
|
+
targetKind: Schema.Literals(["app", "component"])
|
|
91
|
+
}) {};
|
|
92
|
+
var CallbackPrefixError = class extends Schema.TaggedError()("CallbackPrefixError", {
|
|
93
|
+
declarationPath: Schema.String,
|
|
94
|
+
contractId: Schema.String,
|
|
95
|
+
componentName: Schema.String
|
|
96
|
+
}) {};
|
|
97
|
+
const CodegenError = Schema.Union([
|
|
98
|
+
SnapshotError,
|
|
99
|
+
BuildError,
|
|
100
|
+
MissingImplFileError,
|
|
101
|
+
MissingSpecFileError,
|
|
102
|
+
SpecMissingDefaultGroupSpecError,
|
|
103
|
+
ComponentNodeGroupError,
|
|
104
|
+
RemoveBusyError,
|
|
105
|
+
SpecImportsServerError,
|
|
106
|
+
InvalidMiddlewareAttachmentError,
|
|
107
|
+
ImplMissingSpecImportError,
|
|
108
|
+
ImplMissingDefaultLayerError,
|
|
109
|
+
ImplNotFinalizedError,
|
|
110
|
+
ImplMissingFunctionsError,
|
|
111
|
+
ImplMissingMiddlewareError,
|
|
112
|
+
ParentChildNameCollisionError,
|
|
113
|
+
InvalidTableDefaultExportError,
|
|
114
|
+
InvalidTableFilenameError,
|
|
115
|
+
DuplicateTableNameError,
|
|
116
|
+
LegacySchemaFileError,
|
|
117
|
+
ConflictingDocNameError,
|
|
118
|
+
InvalidConvexConfigError,
|
|
119
|
+
InvalidDeclarationError,
|
|
120
|
+
HandWrittenConvexFileError,
|
|
121
|
+
DeclarationKindMismatchError,
|
|
122
|
+
CallbackPrefixError
|
|
123
|
+
]);
|
|
124
|
+
const isCodegenError = (error) => {
|
|
125
|
+
if (isBuildError(error)) return true;
|
|
126
|
+
return Schema.is(CodegenError)(error);
|
|
127
|
+
};
|
|
128
|
+
const cross = red("✘");
|
|
129
|
+
const stemFromSpecPath = (specPath) => {
|
|
130
|
+
const lastSep = Math.max(specPath.lastIndexOf("/"), specPath.lastIndexOf("\\"));
|
|
131
|
+
const basename = lastSep < 0 ? specPath : specPath.slice(lastSep + 1);
|
|
132
|
+
return basename.endsWith(".spec.ts") ? basename.slice(0, -8) : basename;
|
|
133
|
+
};
|
|
134
|
+
const singleLine = (...parts) => `${cross} ${parts.join("")}`;
|
|
135
|
+
const renderMissingImplFileError = (error) => singleLine("Spec ", formatPath(error.specPath), " has no sibling impl; create ", formatPath(error.expectedImplPath), " and default-export a GroupImpl layer from it.");
|
|
136
|
+
const renderMissingSpecFileError = (error) => singleLine("Impl ", formatPath(error.implPath), " has no sibling spec; create ", formatPath(error.expectedSpecPath), " and default-export a GroupSpec from it, or remove the impl.");
|
|
137
|
+
const renderSpecMissingDefaultGroupSpecError = (error) => singleLine("Spec ", formatPath(error.specPath), " must default-export a GroupSpec; build it with GroupSpec.make() or GroupSpec.makeNode().");
|
|
138
|
+
const renderSpecImportsServerError = (error) => {
|
|
139
|
+
const importers = error.importerPaths.join(", ");
|
|
140
|
+
return singleLine("Spec ", formatPath(error.specPath), ` reaches a module that imports \`@confect/server\`: ${importers}. Spec modules are bundled into your client, so anything they import ships to the browser—move the server logic into a \`*.impl.ts\` module, or use \`import type\` if you only need the types.`);
|
|
141
|
+
};
|
|
142
|
+
const renderImplMissingSpecImportError = (error) => {
|
|
143
|
+
const stem = stemFromSpecPath(error.expectedSpecPath);
|
|
144
|
+
return singleLine("Impl ", formatPath(error.implPath), ` does not import its sibling spec; add \`import ${stem} from "./${stem}.spec"\` and pass it to FunctionImpl.make/GroupImpl.make.`);
|
|
145
|
+
};
|
|
146
|
+
const renderImplMissingDefaultLayerError = (error) => singleLine("Impl ", formatPath(error.implPath), " must default-export a GroupImpl layer; wrap your handlers with `GroupImpl.make(databaseSchema, groupSpec).pipe(Layer.provide(...))` and `export default` it.");
|
|
147
|
+
const renderImplNotFinalizedError = (error) => singleLine("Impl ", formatPath(error.implPath), " is not finalized; append `GroupImpl.finalize` to the end of the pipeline (e.g. `GroupImpl.make(databaseSchema, group).pipe(Layer.provide(...), GroupImpl.finalize)`).");
|
|
148
|
+
const renderImplMissingFunctionsError = (error) => {
|
|
149
|
+
const names = error.missingFunctionNames.join(", ");
|
|
150
|
+
return singleLine("Impl ", formatPath(error.implPath), ` does not implement every function declared by group \`${error.groupPath}\`; missing: ${names}. Add a \`FunctionImpl.make\` for each missing function and provide it to the group layer.`);
|
|
151
|
+
};
|
|
152
|
+
const renderImplMissingMiddlewareError = (error) => {
|
|
153
|
+
const keys = error.missingMiddlewareKeys.join(", ");
|
|
154
|
+
return singleLine("Impl ", formatPath(error.implPath), ` does not implement every middleware attached to group \`${error.groupPath}\`; missing: ${keys}. Provide a \`MiddlewareImpl.make\` (or \`makeByFunctionType\`/\`provides\`) layer for each missing middleware to the group layer.`);
|
|
155
|
+
};
|
|
156
|
+
const renderInvalidTableDefaultExportError = (error) => singleLine("Table ", formatPath(error.tablePath), " must default-export a Table (e.g. `export default Table.make({ ... })`); convert any named export to a default export.");
|
|
157
|
+
const renderInvalidTableFilenameError = (error) => singleLine("Table ", formatPath(error.tablePath), ` has an invalid filename: ${error.reason} Convex table names must start with a letter and contain only letters, numbers, and underscores; leading underscores are reserved for system tables.`);
|
|
158
|
+
const renderDuplicateTableNameError = (error) => {
|
|
159
|
+
const conflicts = error.collisions.map(({ tableName, tablePaths }) => `\`${tableName}\` (${tablePaths.join(", ")})`).join("; ");
|
|
160
|
+
return singleLine(`Multiple files under \`confect/tables/\` resolve to the same table name. Table names are derived from filenames, so each must be unique across the directory (including subdirectories); rename or remove all but one. Conflicts: ${conflicts}.`);
|
|
161
|
+
};
|
|
162
|
+
const renderConflictingDocNameError = (error) => {
|
|
163
|
+
const conflicts = pipe(error.collisions, Array.map(({ docName, tableNames }) => `\`${docName}\` (${Array.join(tableNames, ", ")})`), Array.join("; "));
|
|
164
|
+
return singleLine(`Multiple tables fold to the same generated document type name. Table names are converted to PascalCase (so \`user_profiles\` and \`userProfiles\` both become \`UserProfilesDoc\`); rename all but one of each colliding group. Conflicts: ${conflicts}.`);
|
|
165
|
+
};
|
|
166
|
+
const renderInvalidConvexConfigError = (error) => singleLine("Convex config ", formatPath(error.configPath), ` could not be evaluated: ${error.reason}`);
|
|
167
|
+
const renderLegacySchemaFileError = (error) => singleLine("Found a legacy ", formatPath(error.schemaPath), ". Delete it: tables in `confect/tables/*.ts` are now the single source of truth, and the runtime schema is generated as `confect/_generated/schema.ts`.");
|
|
168
|
+
const renderParentChildNameCollisionError = (error) => singleLine("Spec ", formatPath(error.parentSpecPath), ` declares a ${error.collisionKind} \`${error.collisionName}\` whose name collides with the sibling subdirectory spec `, formatPath(error.childSpecPath), `. Rename one of them so the assembled spec has a unique key at this path.`);
|
|
169
|
+
/**
|
|
170
|
+
* Render any {@link CodegenError} into a styled, ready-to-print string.
|
|
171
|
+
* Single-error variants render to a one-line `✘`-prefixed message;
|
|
172
|
+
* `BundleFailedError` (the only multi-error variant) renders to a header plus
|
|
173
|
+
* an esbuild diagnostic block.
|
|
174
|
+
*/
|
|
175
|
+
const renderCodegenError = (error) => {
|
|
176
|
+
if (isBuildError(error)) return renderBuildError(error);
|
|
177
|
+
if (error._tag === "ComponentNodeGroupError") return singleLine(`Group "${error.groupPath}" in ${error.specPath} uses the Node runtime. Convex components do not support Node.js functions.`);
|
|
178
|
+
if (error._tag === "RemoveBusyError") return singleLine("Could not remove ", formatPath(error.path), ` after ${error.attempts} attempts because it is busy. Close other tools using it and try again.`);
|
|
179
|
+
if (error._tag === "InvalidDeclarationError") return singleLine("Declaration ", formatPath(error.declarationPath), ` is invalid: ${error.reason}`);
|
|
180
|
+
if (error._tag === "DeclarationKindMismatchError") return singleLine("Declaration ", formatPath(error.declarationPath), ` declares kind "${error.declaredKind}", but the target directory is kind "${error.targetKind}".`);
|
|
181
|
+
if (error._tag === "CallbackPrefixError") return singleLine("Callback contract ", `"${error.contractId}" in `, formatPath(error.declarationPath), ` must start with "${error.componentName}/" for component "${error.componentName}".`);
|
|
182
|
+
if (error._tag === "HandWrittenConvexFileError") return singleLine("Found a hand-written ", formatPath(error.convexPath), ". `confect codegen` writes it from ", formatPath(error.declarationPath), " now; move its contents there and delete the file.");
|
|
183
|
+
return Match.value(error).pipe(Match.tag("SnapshotError", ({ reason, relativePath, pathSegments }) => singleLine(`Invalid generation metadata (${reason})`, relativePath === "" ? "" : ` for ${relativePath}`, pathSegments.length === 0 ? "." : ` at ${pathSegments.join("/")}.`)), Match.tag("MissingImplFileError", renderMissingImplFileError), Match.tag("MissingSpecFileError", renderMissingSpecFileError), Match.tag("SpecMissingDefaultGroupSpecError", renderSpecMissingDefaultGroupSpecError), Match.tag("SpecImportsServerError", renderSpecImportsServerError), Match.tag("InvalidMiddlewareAttachmentError", (attachmentError) => singleLine("Spec ", formatPath(attachmentError.specPath), `: ${attachmentError.message}`)), Match.tag("ImplMissingSpecImportError", renderImplMissingSpecImportError), Match.tag("ImplMissingDefaultLayerError", renderImplMissingDefaultLayerError), Match.tag("ImplNotFinalizedError", renderImplNotFinalizedError), Match.tag("ImplMissingFunctionsError", renderImplMissingFunctionsError), Match.tag("ImplMissingMiddlewareError", renderImplMissingMiddlewareError), Match.tag("ParentChildNameCollisionError", renderParentChildNameCollisionError), Match.tag("InvalidTableDefaultExportError", renderInvalidTableDefaultExportError), Match.tag("InvalidTableFilenameError", renderInvalidTableFilenameError), Match.tag("DuplicateTableNameError", renderDuplicateTableNameError), Match.tag("LegacySchemaFileError", renderLegacySchemaFileError), Match.tag("ConflictingDocNameError", renderConflictingDocNameError), Match.tag("InvalidConvexConfigError", renderInvalidConvexConfigError), Match.exhaustive);
|
|
184
|
+
};
|
|
185
|
+
const logCodegenError = (error) => Console.error(renderCodegenError(error));
|
|
186
|
+
/**
|
|
187
|
+
* Log any {@link CodegenError} thrown by `effect` and propagate the failure
|
|
188
|
+
* unchanged so the caller's error channel is preserved.
|
|
189
|
+
*/
|
|
190
|
+
const tapAndLog = (effect) => effect.pipe(Effect.tapError((error) => isCodegenError(error) ? logCodegenError(error) : Effect.void));
|
|
191
|
+
//#endregion
|
|
192
|
+
export { CallbackPrefixError, CodegenError, ComponentNodeGroupError, ConflictingDocNameError, DeclarationKindMismatchError, DuplicateTableNameError, HandWrittenConvexFileError, ImplMissingDefaultLayerError, ImplMissingFunctionsError, ImplMissingMiddlewareError, ImplMissingSpecImportError, ImplNotFinalizedError, InvalidConvexConfigError, InvalidDeclarationError, InvalidMiddlewareAttachmentError, InvalidTableDefaultExportError, InvalidTableFilenameError, LegacySchemaFileError, MissingImplFileError, MissingSpecFileError, ParentChildNameCollisionError, RemoveBusyError, SpecImportsServerError, SpecMissingDefaultGroupSpecError, isCodegenError, logCodegenError, renderCodegenError, tapAndLog };
|
|
193
|
+
|
|
194
|
+
//# sourceMappingURL=CodegenError.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodegenError.mjs","names":["Ansi.red"],"sources":["../src/CodegenError.ts"],"sourcesContent":["import * as Array from \"effect/Array\";\nimport * as Console from \"effect/Console\";\nimport { pipe } from \"effect/Function\";\nimport * as Effect from \"effect/Effect\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Schema from \"effect/Schema\";\nimport { BuildError, isBuildError } from \"./BuildError\";\nimport { SnapshotError } from \"./SnapshotError\";\nimport * as Ansi from \"./Ansi\";\nimport { formatPath, renderBuildError } from \"./log\";\n\n// --- Variants ---\n\nexport class MissingImplFileError extends Schema.TaggedError<MissingImplFileError>()(\n \"MissingImplFileError\",\n {\n specPath: Schema.String,\n expectedImplPath: Schema.String,\n },\n) {}\n\nexport class MissingSpecFileError extends Schema.TaggedError<MissingSpecFileError>()(\n \"MissingSpecFileError\",\n {\n implPath: Schema.String,\n expectedSpecPath: Schema.String,\n },\n) {}\n\nexport class SpecMissingDefaultGroupSpecError extends Schema.TaggedError<SpecMissingDefaultGroupSpecError>()(\n \"SpecMissingDefaultGroupSpecError\",\n {\n specPath: Schema.String,\n },\n) {}\n\nexport class RemoveBusyError extends Schema.TaggedError<RemoveBusyError>()(\n \"RemoveBusyError\",\n { path: Schema.String, attempts: Schema.Finite, cause: Schema.Unknown },\n) {}\n\nexport class ComponentNodeGroupError extends Schema.TaggedError<ComponentNodeGroupError>()(\n \"ComponentNodeGroupError\",\n {\n specPath: Schema.String,\n groupPath: Schema.String,\n },\n) {}\n\nexport class SpecImportsServerError extends Schema.TaggedError<SpecImportsServerError>()(\n \"SpecImportsServerError\",\n {\n specPath: Schema.String,\n importerPaths: Schema.Array(Schema.String),\n },\n) {}\n\nexport class InvalidMiddlewareAttachmentError extends Schema.TaggedError<InvalidMiddlewareAttachmentError>()(\n \"InvalidMiddlewareAttachmentError\",\n { specPath: Schema.String, message: Schema.String },\n) {}\n\nexport class ImplMissingSpecImportError extends Schema.TaggedError<ImplMissingSpecImportError>()(\n \"ImplMissingSpecImportError\",\n {\n implPath: Schema.String,\n expectedSpecPath: Schema.String,\n },\n) {}\n\nexport class ImplMissingDefaultLayerError extends Schema.TaggedError<ImplMissingDefaultLayerError>()(\n \"ImplMissingDefaultLayerError\",\n {\n implPath: Schema.String,\n },\n) {}\n\nexport class ImplNotFinalizedError extends Schema.TaggedError<ImplNotFinalizedError>()(\n \"ImplNotFinalizedError\",\n {\n implPath: Schema.String,\n },\n) {}\n\nexport class ImplMissingFunctionsError extends Schema.TaggedError<ImplMissingFunctionsError>()(\n \"ImplMissingFunctionsError\",\n {\n implPath: Schema.String,\n groupPath: Schema.String,\n missingFunctionNames: Schema.Array(Schema.String),\n },\n) {}\n\nexport class ImplMissingMiddlewareError extends Schema.TaggedError<ImplMissingMiddlewareError>()(\n \"ImplMissingMiddlewareError\",\n {\n implPath: Schema.String,\n groupPath: Schema.String,\n missingMiddlewareKeys: Schema.Array(Schema.String),\n },\n) {}\n\nexport class ParentChildNameCollisionError extends Schema.TaggedError<ParentChildNameCollisionError>()(\n \"ParentChildNameCollisionError\",\n {\n parentSpecPath: Schema.String,\n childSpecPath: Schema.String,\n collisionName: Schema.String,\n collisionKind: Schema.Literals([\"function\", \"group\"]),\n },\n) {}\n\nexport class InvalidTableDefaultExportError extends Schema.TaggedError<InvalidTableDefaultExportError>()(\n \"InvalidTableDefaultExportError\",\n {\n tablePath: Schema.String,\n },\n) {}\n\nexport class InvalidTableFilenameError extends Schema.TaggedError<InvalidTableFilenameError>()(\n \"InvalidTableFilenameError\",\n {\n tablePath: Schema.String,\n reason: Schema.String,\n },\n) {}\n\nexport class DuplicateTableNameError extends Schema.TaggedError<DuplicateTableNameError>()(\n \"DuplicateTableNameError\",\n {\n // Every table name that more than one file resolves to, each paired with\n // the colliding file paths. All collisions are captured in a single pass\n // so the user can fix them together rather than re-running codegen once\n // per conflict.\n collisions: Schema.Array(\n Schema.Struct({\n tableName: Schema.String,\n tablePaths: Schema.Array(Schema.String),\n }),\n ),\n },\n) {}\n\nexport class LegacySchemaFileError extends Schema.TaggedError<LegacySchemaFileError>()(\n \"LegacySchemaFileError\",\n {\n schemaPath: Schema.String,\n },\n) {}\n\nexport class ConflictingDocNameError extends Schema.TaggedError<ConflictingDocNameError>()(\n \"ConflictingDocNameError\",\n {\n collisions: Schema.Array(\n Schema.Struct({\n docName: Schema.String,\n tableNames: Schema.Array(Schema.String),\n }),\n ),\n },\n) {}\n\nexport class InvalidConvexConfigError extends Schema.TaggedError<InvalidConvexConfigError>()(\n \"InvalidConvexConfigError\",\n {\n configPath: Schema.String,\n reason: Schema.String,\n },\n) {}\n\nexport class InvalidDeclarationError extends Schema.TaggedError<InvalidDeclarationError>()(\n \"InvalidDeclarationError\",\n {\n declarationPath: Schema.String,\n reason: Schema.String,\n },\n) {}\n\nexport class HandWrittenConvexFileError extends Schema.TaggedError<HandWrittenConvexFileError>()(\n \"HandWrittenConvexFileError\",\n {\n convexPath: Schema.String,\n declarationPath: Schema.String,\n },\n) {}\n\nexport class DeclarationKindMismatchError extends Schema.TaggedError<DeclarationKindMismatchError>()(\n \"DeclarationKindMismatchError\",\n {\n declarationPath: Schema.String,\n declaredKind: Schema.Literals([\"app\", \"component\"]),\n targetKind: Schema.Literals([\"app\", \"component\"]),\n },\n) {}\n\nexport class CallbackPrefixError extends Schema.TaggedError<CallbackPrefixError>()(\n \"CallbackPrefixError\",\n {\n declarationPath: Schema.String,\n contractId: Schema.String,\n componentName: Schema.String,\n },\n) {}\n\nexport const CodegenError = Schema.Union([\n SnapshotError,\n BuildError,\n MissingImplFileError,\n MissingSpecFileError,\n SpecMissingDefaultGroupSpecError,\n ComponentNodeGroupError,\n RemoveBusyError,\n SpecImportsServerError,\n InvalidMiddlewareAttachmentError,\n ImplMissingSpecImportError,\n ImplMissingDefaultLayerError,\n ImplNotFinalizedError,\n ImplMissingFunctionsError,\n ImplMissingMiddlewareError,\n ParentChildNameCollisionError,\n InvalidTableDefaultExportError,\n InvalidTableFilenameError,\n DuplicateTableNameError,\n LegacySchemaFileError,\n ConflictingDocNameError,\n InvalidConvexConfigError,\n InvalidDeclarationError,\n HandWrittenConvexFileError,\n DeclarationKindMismatchError,\n CallbackPrefixError,\n]);\nexport type CodegenError = typeof CodegenError.Type;\n\nexport const isCodegenError = (error: unknown): error is CodegenError => {\n if (isBuildError(error)) return true;\n return Schema.is(CodegenError)(error);\n};\n\n// --- Per-variant rendering ---\n\nconst cross = Ansi.red(\"✘\");\n\nconst stemFromSpecPath = (specPath: string): string => {\n const lastSep = Math.max(\n specPath.lastIndexOf(\"/\"),\n specPath.lastIndexOf(\"\\\\\"),\n );\n const basename = lastSep < 0 ? specPath : specPath.slice(lastSep + 1);\n return basename.endsWith(\".spec.ts\")\n ? basename.slice(0, -\".spec.ts\".length)\n : basename;\n};\n\nconst singleLine = (...parts: ReadonlyArray<string>): string =>\n `${cross} ${parts.join(\"\")}`;\n\nconst renderMissingImplFileError = (error: MissingImplFileError): string =>\n singleLine(\n \"Spec \",\n formatPath(error.specPath),\n \" has no sibling impl; create \",\n formatPath(error.expectedImplPath),\n \" and default-export a GroupImpl layer from it.\",\n );\n\nconst renderMissingSpecFileError = (error: MissingSpecFileError): string =>\n singleLine(\n \"Impl \",\n formatPath(error.implPath),\n \" has no sibling spec; create \",\n formatPath(error.expectedSpecPath),\n \" and default-export a GroupSpec from it, or remove the impl.\",\n );\n\nconst renderSpecMissingDefaultGroupSpecError = (\n error: SpecMissingDefaultGroupSpecError,\n): string =>\n singleLine(\n \"Spec \",\n formatPath(error.specPath),\n \" must default-export a GroupSpec; build it with GroupSpec.make() or GroupSpec.makeNode().\",\n );\n\nconst renderSpecImportsServerError = (\n error: SpecImportsServerError,\n): string => {\n const importers = error.importerPaths.join(\", \");\n return singleLine(\n \"Spec \",\n formatPath(error.specPath),\n ` reaches a module that imports \\`@confect/server\\`: ${importers}. Spec modules are bundled into your client, so anything they import ships to the browser—move the server logic into a \\`*.impl.ts\\` module, or use \\`import type\\` if you only need the types.`,\n );\n};\n\nconst renderImplMissingSpecImportError = (\n error: ImplMissingSpecImportError,\n): string => {\n const stem = stemFromSpecPath(error.expectedSpecPath);\n return singleLine(\n \"Impl \",\n formatPath(error.implPath),\n ` does not import its sibling spec; add \\`import ${stem} from \"./${stem}.spec\"\\` and pass it to FunctionImpl.make/GroupImpl.make.`,\n );\n};\n\nconst renderImplMissingDefaultLayerError = (\n error: ImplMissingDefaultLayerError,\n): string =>\n singleLine(\n \"Impl \",\n formatPath(error.implPath),\n \" must default-export a GroupImpl layer; wrap your handlers with `GroupImpl.make(databaseSchema, groupSpec).pipe(Layer.provide(...))` and `export default` it.\",\n );\n\nconst renderImplNotFinalizedError = (error: ImplNotFinalizedError): string =>\n singleLine(\n \"Impl \",\n formatPath(error.implPath),\n \" is not finalized; append `GroupImpl.finalize` to the end of the pipeline (e.g. `GroupImpl.make(databaseSchema, group).pipe(Layer.provide(...), GroupImpl.finalize)`).\",\n );\n\nconst renderImplMissingFunctionsError = (\n error: ImplMissingFunctionsError,\n): string => {\n const names = error.missingFunctionNames.join(\", \");\n return singleLine(\n \"Impl \",\n formatPath(error.implPath),\n ` does not implement every function declared by group \\`${error.groupPath}\\`; missing: ${names}. Add a \\`FunctionImpl.make\\` for each missing function and provide it to the group layer.`,\n );\n};\n\nconst renderImplMissingMiddlewareError = (\n error: ImplMissingMiddlewareError,\n): string => {\n const keys = error.missingMiddlewareKeys.join(\", \");\n return singleLine(\n \"Impl \",\n formatPath(error.implPath),\n ` does not implement every middleware attached to group \\`${error.groupPath}\\`; missing: ${keys}. Provide a \\`MiddlewareImpl.make\\` (or \\`makeByFunctionType\\`/\\`provides\\`) layer for each missing middleware to the group layer.`,\n );\n};\n\nconst renderInvalidTableDefaultExportError = (\n error: InvalidTableDefaultExportError,\n): string =>\n singleLine(\n \"Table \",\n formatPath(error.tablePath),\n \" must default-export a Table (e.g. `export default Table.make({ ... })`); convert any named export to a default export.\",\n );\n\nconst renderInvalidTableFilenameError = (\n error: InvalidTableFilenameError,\n): string =>\n singleLine(\n \"Table \",\n formatPath(error.tablePath),\n ` has an invalid filename: ${error.reason} Convex table names must start with a letter and contain only letters, numbers, and underscores; leading underscores are reserved for system tables.`,\n );\n\nconst renderDuplicateTableNameError = (\n error: DuplicateTableNameError,\n): string => {\n const conflicts = error.collisions\n .map(\n ({ tableName, tablePaths }) =>\n `\\`${tableName}\\` (${tablePaths.join(\", \")})`,\n )\n .join(\"; \");\n return singleLine(\n `Multiple files under \\`confect/tables/\\` resolve to the same table name. Table names are derived from filenames, so each must be unique across the directory (including subdirectories); rename or remove all but one. Conflicts: ${conflicts}.`,\n );\n};\n\nconst renderConflictingDocNameError = (\n error: ConflictingDocNameError,\n): string => {\n const conflicts = pipe(\n error.collisions,\n Array.map(\n ({ docName, tableNames }) =>\n `\\`${docName}\\` (${Array.join(tableNames, \", \")})`,\n ),\n Array.join(\"; \"),\n );\n return singleLine(\n `Multiple tables fold to the same generated document type name. Table names are converted to PascalCase (so \\`user_profiles\\` and \\`userProfiles\\` both become \\`UserProfilesDoc\\`); rename all but one of each colliding group. Conflicts: ${conflicts}.`,\n );\n};\n\nconst renderInvalidConvexConfigError = (\n error: InvalidConvexConfigError,\n): string =>\n singleLine(\n \"Convex config \",\n formatPath(error.configPath),\n ` could not be evaluated: ${error.reason}`,\n );\n\nconst renderLegacySchemaFileError = (error: LegacySchemaFileError): string =>\n singleLine(\n \"Found a legacy \",\n formatPath(error.schemaPath),\n \". Delete it: tables in `confect/tables/*.ts` are now the single source of truth, and the runtime schema is generated as `confect/_generated/schema.ts`.\",\n );\n\nconst renderParentChildNameCollisionError = (\n error: ParentChildNameCollisionError,\n): string =>\n singleLine(\n \"Spec \",\n formatPath(error.parentSpecPath),\n ` declares a ${error.collisionKind} \\`${error.collisionName}\\` whose name collides with the sibling subdirectory spec `,\n formatPath(error.childSpecPath),\n `. Rename one of them so the assembled spec has a unique key at this path.`,\n );\n\n/**\n * Render any {@link CodegenError} into a styled, ready-to-print string.\n * Single-error variants render to a one-line `✘`-prefixed message;\n * `BundleFailedError` (the only multi-error variant) renders to a header plus\n * an esbuild diagnostic block.\n */\nexport const renderCodegenError = (error: CodegenError): string => {\n if (isBuildError(error)) return renderBuildError(error);\n // The renderer pipeline below is at Effect's pipe arity limit, so the\n // fork's errors render here.\n if (error._tag === \"ComponentNodeGroupError\") {\n return singleLine(\n `Group \"${error.groupPath}\" in ${error.specPath} uses the Node runtime. Convex components do not support Node.js functions.`,\n );\n }\n if (error._tag === \"RemoveBusyError\") {\n return singleLine(\n \"Could not remove \",\n formatPath(error.path),\n ` after ${error.attempts} attempts because it is busy. Close other tools using it and try again.`,\n );\n }\n if (error._tag === \"InvalidDeclarationError\") {\n return singleLine(\n \"Declaration \",\n formatPath(error.declarationPath),\n ` is invalid: ${error.reason}`,\n );\n }\n if (error._tag === \"DeclarationKindMismatchError\") {\n return singleLine(\n \"Declaration \",\n formatPath(error.declarationPath),\n ` declares kind \"${error.declaredKind}\", but the target directory is kind \"${error.targetKind}\".`,\n );\n }\n if (error._tag === \"CallbackPrefixError\") {\n return singleLine(\n \"Callback contract \",\n `\"${error.contractId}\" in `,\n formatPath(error.declarationPath),\n ` must start with \"${error.componentName}/\" for component \"${error.componentName}\".`,\n );\n }\n if (error._tag === \"HandWrittenConvexFileError\") {\n return singleLine(\n \"Found a hand-written \",\n formatPath(error.convexPath),\n \". `confect codegen` writes it from \",\n formatPath(error.declarationPath),\n \" now; move its contents there and delete the file.\",\n );\n }\n return Match.value(error).pipe(\n Match.tag(\"SnapshotError\", ({ reason, relativePath, pathSegments }) =>\n singleLine(\n `Invalid generation metadata (${reason})`,\n relativePath === \"\" ? \"\" : ` for ${relativePath}`,\n pathSegments.length === 0 ? \".\" : ` at ${pathSegments.join(\"/\")}.`,\n ),\n ),\n Match.tag(\"MissingImplFileError\", renderMissingImplFileError),\n Match.tag(\"MissingSpecFileError\", renderMissingSpecFileError),\n Match.tag(\n \"SpecMissingDefaultGroupSpecError\",\n renderSpecMissingDefaultGroupSpecError,\n ),\n Match.tag(\"SpecImportsServerError\", renderSpecImportsServerError),\n Match.tag(\"InvalidMiddlewareAttachmentError\", (attachmentError) =>\n singleLine(\n \"Spec \",\n formatPath(attachmentError.specPath),\n `: ${attachmentError.message}`,\n ),\n ),\n Match.tag(\"ImplMissingSpecImportError\", renderImplMissingSpecImportError),\n Match.tag(\n \"ImplMissingDefaultLayerError\",\n renderImplMissingDefaultLayerError,\n ),\n Match.tag(\"ImplNotFinalizedError\", renderImplNotFinalizedError),\n Match.tag(\"ImplMissingFunctionsError\", renderImplMissingFunctionsError),\n Match.tag(\"ImplMissingMiddlewareError\", renderImplMissingMiddlewareError),\n Match.tag(\n \"ParentChildNameCollisionError\",\n renderParentChildNameCollisionError,\n ),\n Match.tag(\n \"InvalidTableDefaultExportError\",\n renderInvalidTableDefaultExportError,\n ),\n Match.tag(\"InvalidTableFilenameError\", renderInvalidTableFilenameError),\n Match.tag(\"DuplicateTableNameError\", renderDuplicateTableNameError),\n Match.tag(\"LegacySchemaFileError\", renderLegacySchemaFileError),\n Match.tag(\"ConflictingDocNameError\", renderConflictingDocNameError),\n Match.tag(\"InvalidConvexConfigError\", renderInvalidConvexConfigError),\n Match.exhaustive,\n );\n};\n\nexport const logCodegenError = (error: CodegenError) =>\n Console.error(renderCodegenError(error));\n\n// --- Effect combinators ---\n\n/**\n * Log any {@link CodegenError} thrown by `effect` and propagate the failure\n * unchanged so the caller's error channel is preserved.\n */\nexport const tapAndLog = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.tapError((error) =>\n isCodegenError(error) ? logCodegenError(error) : Effect.void,\n ),\n );\n\n/**\n * Catch any {@link CodegenError} thrown by `effect`, log it, and resolve to\n * `Option.none()`. Success resolves to `Option.some(value)`.\n */\n// oxlint-disable effecttsgo/unsafe-effect-type-assertion -- catchIf removes the error variant selected by this refinement.\nexport const catchAndLog = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<Option.Option<A>, Exclude<E, CodegenError>, R> =>\n Effect.catchIf(Effect.map(effect, Option.some<A>), isCodegenError, (error) =>\n logCodegenError(error).pipe(Effect.as(Option.none<A>())),\n ) as Effect.Effect<Option.Option<A>, Exclude<E, CodegenError>, R>;\n// oxlint-enable effecttsgo/unsafe-effect-type-assertion\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ConvexDirectory, layer as layer$1 } from "./ConvexDirectory.mjs";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as FileSystem from "effect/FileSystem";
|
|
4
|
+
import * as Path from "effect/Path";
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import * as Ref from "effect/Ref";
|
|
7
|
+
import * as Schema from "effect/Schema";
|
|
8
|
+
import * as Layer from "effect/Layer";
|
|
9
|
+
//#region src/ConfectDirectory.ts
|
|
10
|
+
var ConfectDirectory = class ConfectDirectory extends Context.Service()("@confect/cli/ConfectDirectory") {
|
|
11
|
+
static get = ConfectDirectory.use((service) => service.get);
|
|
12
|
+
};
|
|
13
|
+
var ConfectDirectoryNotFoundError = class extends Schema.TaggedError()("ConfectDirectoryNotFoundError", {}) {
|
|
14
|
+
get message() {
|
|
15
|
+
return "Could not find Confect directory";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const findConfectDirectory = Effect.gen(function* () {
|
|
19
|
+
const fs = yield* FileSystem.FileSystem;
|
|
20
|
+
const path = yield* Path.Path;
|
|
21
|
+
const convexDirectory = yield* ConvexDirectory.get;
|
|
22
|
+
const confectDirectory = path.join(path.dirname(convexDirectory), "confect");
|
|
23
|
+
if (yield* fs.exists(confectDirectory)) return confectDirectory;
|
|
24
|
+
else return yield* new ConfectDirectoryNotFoundError();
|
|
25
|
+
});
|
|
26
|
+
const layerFromConvexDirectory = Layer.effect(ConfectDirectory, Effect.gen(function* () {
|
|
27
|
+
const confectDirectory = yield* findConfectDirectory;
|
|
28
|
+
const ref = yield* Ref.make(confectDirectory);
|
|
29
|
+
return { get: Ref.get(ref) };
|
|
30
|
+
}));
|
|
31
|
+
layerFromConvexDirectory.pipe(Layer.provide(layer$1));
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ConfectDirectory, ConfectDirectoryNotFoundError, findConfectDirectory, layerFromConvexDirectory };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=ConfectDirectory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfectDirectory.mjs","names":["ConvexDirectory.layer"],"sources":["../src/ConfectDirectory.ts"],"sourcesContent":["import * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as Layer from \"effect/Layer\";\nimport * as Path from \"effect/Path\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schema from \"effect/Schema\";\nimport * as ConvexDirectory from \"./ConvexDirectory\";\n\nexport class ConfectDirectory extends Context.Service<\n ConfectDirectory,\n { readonly get: Effect.Effect<string> }\n>()(\"@confect/cli/ConfectDirectory\") {\n static readonly get = ConfectDirectory.use((service) => service.get);\n}\n\nexport class ConfectDirectoryNotFoundError extends Schema.TaggedError<ConfectDirectoryNotFoundError>()(\n \"ConfectDirectoryNotFoundError\",\n {},\n) {\n override get message(): string {\n return \"Could not find Confect directory\";\n }\n}\n\nexport const findConfectDirectory = Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n\n const convexDirectory = yield* ConvexDirectory.ConvexDirectory.get;\n\n const confectDirectory = path.join(path.dirname(convexDirectory), \"confect\");\n\n if (yield* fs.exists(confectDirectory)) {\n return confectDirectory;\n } else {\n return yield* new ConfectDirectoryNotFoundError();\n }\n});\n\nexport const layerFromConvexDirectory = Layer.effect(\n ConfectDirectory,\n Effect.gen(function* () {\n const confectDirectory = yield* findConfectDirectory;\n\n const ref = yield* Ref.make<string>(confectDirectory);\n\n return { get: Ref.get(ref) } as const;\n }),\n);\n\nexport const layer = layerFromConvexDirectory.pipe(\n Layer.provide(ConvexDirectory.layer),\n);\n"],"mappings":";;;;;;;;;AASA,IAAa,mBAAb,MAAa,yBAAyB,QAAQ,QAG5C,CAAC,CAAC,+BAA+B,CAAC,CAAC;CACnC,OAAgB,MAAM,iBAAiB,KAAK,YAAY,QAAQ,GAAG;AACrE;AAEA,IAAa,gCAAb,cAAmD,OAAO,YAA2C,CAAC,CACpG,iCACA,CAAC,CACH,CAAC,CAAC;CACA,IAAa,UAAkB;EAC7B,OAAO;CACT;AACF;AAEA,MAAa,uBAAuB,OAAO,IAAI,aAAa;CAC1D,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,OAAO,OAAO,KAAK;CAEzB,MAAM,kBAAkB,OAAA,gBAAuC;CAE/D,MAAM,mBAAmB,KAAK,KAAK,KAAK,QAAQ,eAAe,GAAG,SAAS;CAE3E,IAAI,OAAO,GAAG,OAAO,gBAAgB,GACnC,OAAO;MAEP,OAAO,OAAO,IAAI,8BAA8B;AAEpD,CAAC;AAED,MAAa,2BAA2B,MAAM,OAC5C,kBACA,OAAO,IAAI,aAAa;CACtB,MAAM,mBAAmB,OAAO;CAEhC,MAAM,MAAM,OAAO,IAAI,KAAa,gBAAgB;CAEpD,OAAO,EAAE,KAAK,IAAI,IAAI,GAAG,EAAE;AAC7B,CAAC,CACH;AAEqB,yBAAyB,KAC5C,MAAM,QAAQA,OAAqB,CACrC"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { fromBundlerError } from "./BuildError.mjs";
|
|
2
|
+
import { bundle, resolveModule } from "./Bundler.mjs";
|
|
3
|
+
import { InvalidConvexConfigError } from "./CodegenError.mjs";
|
|
4
|
+
import { toPosixPath } from "./utils.mjs";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Path from "effect/Path";
|
|
7
|
+
import * as Array from "effect/Array";
|
|
8
|
+
import { pipe } from "effect/Function";
|
|
9
|
+
import * as Match from "effect/Match";
|
|
10
|
+
import * as Option from "effect/Option";
|
|
11
|
+
import * as Record from "effect/Record";
|
|
12
|
+
import * as Schema from "effect/Schema";
|
|
13
|
+
import * as String from "effect/String";
|
|
14
|
+
import * as Predicate from "effect/Predicate";
|
|
15
|
+
import * as Order from "effect/Order";
|
|
16
|
+
//#region src/ConvexConfig.ts
|
|
17
|
+
const CONVEX_CONFIG_FILENAME = "convex.config.ts";
|
|
18
|
+
const COMPONENT_CONFIG_NAMESPACE = "confect-component-config";
|
|
19
|
+
/**
|
|
20
|
+
* Where the plugin records how a definition was imported: the specifier as
|
|
21
|
+
* written and the file it resolved to. Codegen reads it to write the import of
|
|
22
|
+
* each mounted component into the generated `convex.config.ts`.
|
|
23
|
+
*/
|
|
24
|
+
const COMPONENT_IMPORT_KEY = "~confect/componentImport";
|
|
25
|
+
const componentImportOf = (definition) => {
|
|
26
|
+
if (!Predicate.hasProperty(definition, "~confect/componentImport")) return Option.none();
|
|
27
|
+
const recorded = definition[COMPONENT_IMPORT_KEY];
|
|
28
|
+
return Predicate.hasProperty(recorded, "specifier") && Predicate.isString(recorded.specifier) && Predicate.hasProperty(recorded, "path") && Predicate.isString(recorded.path) ? Option.some({
|
|
29
|
+
specifier: recorded.specifier,
|
|
30
|
+
path: recorded.path
|
|
31
|
+
}) : Option.none();
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Matches the trailing `convex.config` segment of a component-definition import
|
|
35
|
+
* (with or without an extension), e.g. `@convex-dev/workpool/convex.config` or
|
|
36
|
+
* `./waitlist/convex.config.ts`.
|
|
37
|
+
*/
|
|
38
|
+
const CONVEX_CONFIG_SUFFIX = /[/\\]convex\.config(\.[cm]?[jt]s)?$/;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the same config spellings that Convex accepts, for configs and test
|
|
41
|
+
* kits.
|
|
42
|
+
*/
|
|
43
|
+
const resolveDefinition = (specifier, importer, path) => {
|
|
44
|
+
const extension = path.extname(specifier);
|
|
45
|
+
const candidates = [
|
|
46
|
+
specifier,
|
|
47
|
+
...extension === ".js" ? [specifier.slice(0, -3) + ".ts"] : [],
|
|
48
|
+
...extension !== ".js" && extension !== ".ts" ? [specifier + ".js", specifier + ".ts"] : []
|
|
49
|
+
];
|
|
50
|
+
return Option.firstSomeOf(candidates.map((candidate) => resolveModule(candidate, importer)));
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* `convex/server`'s `app.use(definition)` rejects any definition object that
|
|
54
|
+
* lacks a string `componentDefinitionPath` ("This code only works in Convex
|
|
55
|
+
* runtime"): that property is normally stamped on by the Convex backend's
|
|
56
|
+
* module system when it evaluates a definition bundle. To evaluate
|
|
57
|
+
* `convex.config.ts` in plain Node, this plugin intercepts every non-entry
|
|
58
|
+
* import of a `convex.config` module (mirroring the Convex CLI's own
|
|
59
|
+
* `componentPlugin`) and swaps in a virtual wrapper that re-exports the real
|
|
60
|
+
* definition with `componentDefinitionPath` and `defaultName` filled in—the
|
|
61
|
+
* exact shape of Convex's `ImportedComponentDefinition`.
|
|
62
|
+
*/
|
|
63
|
+
const componentConfigPlugin = (path) => ({
|
|
64
|
+
name: "confect:component-config",
|
|
65
|
+
setup(build) {
|
|
66
|
+
build.onResolve({ filter: /convex\.config/ }, (args) => {
|
|
67
|
+
if (args.kind === "entry-point") return void 0;
|
|
68
|
+
if (args.namespace === COMPONENT_CONFIG_NAMESPACE) return { path: args.path };
|
|
69
|
+
if (args.namespace !== "file" && args.namespace !== "") return void 0;
|
|
70
|
+
const importer = args.importer !== "" ? args.importer : path.join(args.resolveDir, "_");
|
|
71
|
+
return pipe(resolveDefinition(args.path, importer, path), Option.match({
|
|
72
|
+
onNone: () => void 0,
|
|
73
|
+
onSome: (resolved) => ({
|
|
74
|
+
path: resolved,
|
|
75
|
+
namespace: COMPONENT_CONFIG_NAMESPACE,
|
|
76
|
+
pluginData: { specifier: args.path }
|
|
77
|
+
})
|
|
78
|
+
}));
|
|
79
|
+
});
|
|
80
|
+
build.onLoad({
|
|
81
|
+
filter: /.*/,
|
|
82
|
+
namespace: COMPONENT_CONFIG_NAMESPACE
|
|
83
|
+
}, (args) => {
|
|
84
|
+
const specifier = args.pluginData.specifier;
|
|
85
|
+
const componentDefinitionPath = !String.startsWith(".")(specifier) && !path.isAbsolute(specifier) ? String.replace(CONVEX_CONFIG_SUFFIX, "")(specifier) : path.dirname(args.path);
|
|
86
|
+
return {
|
|
87
|
+
loader: "js",
|
|
88
|
+
resolveDir: path.dirname(args.path),
|
|
89
|
+
contents: Array.join([`import real from ${JSON.stringify(args.path)};`, `export default { ...real, componentDefinitionPath: ${JSON.stringify(componentDefinitionPath)}, defaultName: real._name, [${JSON.stringify(COMPONENT_IMPORT_KEY)}]: ${JSON.stringify({
|
|
90
|
+
specifier,
|
|
91
|
+
path: args.path
|
|
92
|
+
})} };`], "\n")
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
/**
|
|
98
|
+
* The subset of `app.export()` (Convex's `AppDefinitionAnalysis`) that the
|
|
99
|
+
* registry needs: each installed component's mount name and the
|
|
100
|
+
* `componentDefinitionPath` injected by {@link componentConfigPlugin}.
|
|
101
|
+
*/
|
|
102
|
+
const AppDefinitionAnalysis = Schema.Struct({
|
|
103
|
+
httpMounts: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
|
|
104
|
+
childComponents: Schema.Array(Schema.Struct({
|
|
105
|
+
name: Schema.String,
|
|
106
|
+
path: Schema.String
|
|
107
|
+
}))
|
|
108
|
+
});
|
|
109
|
+
const byName = Order.mapInput(Order.String, (component) => component.name);
|
|
110
|
+
/**
|
|
111
|
+
* Convex component names must be alphanumeric plus underscores (see
|
|
112
|
+
* `defineComponent`'s docs). Beyond rejecting genuinely invalid names, this is
|
|
113
|
+
* a drift tripwire: if a future convex version stopped resolving names the way
|
|
114
|
+
* we rely on (e.g. `defaultName` disappearing), the fallback name would be a
|
|
115
|
+
* path segment like `convex.config`—caught here as a clear error instead of
|
|
116
|
+
* silently emitting a broken registry.
|
|
117
|
+
*/
|
|
118
|
+
const VALID_COMPONENT_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
119
|
+
/**
|
|
120
|
+
* Bundle and evaluate `convex/convex.config.ts` and list the components
|
|
121
|
+
* installed on the app, in mount-name order. `displayPath` is used in error
|
|
122
|
+
* messages (mirroring how impl/spec bundling reports relative paths).
|
|
123
|
+
*/
|
|
124
|
+
const discoverInstalledComponents = Effect.fn("ConvexConfig.discoverInstalledComponents")(function* (convexConfigPath, displayPath, kind = "app") {
|
|
125
|
+
const path = yield* Path.Path;
|
|
126
|
+
const { module } = yield* bundle(convexConfigPath, { plugins: [componentConfigPlugin(path)] }).pipe(Effect.mapError((error) => fromBundlerError(displayPath, error)));
|
|
127
|
+
const app = module.default;
|
|
128
|
+
const definition = Match.value(kind).pipe(Match.when("app", () => ({
|
|
129
|
+
isRoot: true,
|
|
130
|
+
constructor: "defineApp"
|
|
131
|
+
})), Match.when("component", () => ({
|
|
132
|
+
isRoot: false,
|
|
133
|
+
constructor: "defineComponent"
|
|
134
|
+
})), Match.exhaustive);
|
|
135
|
+
if (app === null || typeof app !== "object" || app._isRoot !== definition.isRoot || typeof app.export !== "function") return yield* new InvalidConvexConfigError({
|
|
136
|
+
configPath: displayPath,
|
|
137
|
+
reason: `it must default-export the ${kind} definition created by \`${definition.constructor}()\`.`
|
|
138
|
+
});
|
|
139
|
+
const analysis = yield* Effect.try({
|
|
140
|
+
try: () => app.export(),
|
|
141
|
+
catch: (cause) => new InvalidConvexConfigError({
|
|
142
|
+
configPath: displayPath,
|
|
143
|
+
reason: `exporting the app definition threw: ${globalThis.String(cause)}.`
|
|
144
|
+
})
|
|
145
|
+
});
|
|
146
|
+
const decoded = yield* Schema.decodeUnknownEffect(AppDefinitionAnalysis)(analysis).pipe(Effect.mapError((cause) => new InvalidConvexConfigError({
|
|
147
|
+
configPath: displayPath,
|
|
148
|
+
reason: `the app definition's installed components could not be read: ${cause.message}.`
|
|
149
|
+
})));
|
|
150
|
+
const components = pipe(decoded.childComponents, Array.map(({ name, path: componentDefinitionPath }) => {
|
|
151
|
+
const httpPrefix = Object.entries(decoded.httpMounts ?? {}).find(([, reference]) => reference === `_reference/childComponent/${name}`)?.[0];
|
|
152
|
+
return {
|
|
153
|
+
name,
|
|
154
|
+
componentDefinitionPath,
|
|
155
|
+
...httpPrefix === void 0 ? {} : { httpPrefix: httpPrefix.replace(/\/$/, "") }
|
|
156
|
+
};
|
|
157
|
+
}), Array.sort(byName));
|
|
158
|
+
const invalidNames = pipe(components, Array.map(({ name }) => name), Array.filter((name) => Option.isNone(String.match(VALID_COMPONENT_NAME)(name))));
|
|
159
|
+
if (Array.isArrayNonEmpty(invalidNames)) return yield* new InvalidConvexConfigError({
|
|
160
|
+
configPath: displayPath,
|
|
161
|
+
reason: `component names must be alphanumeric plus underscores, but got: ${pipe(invalidNames, Array.map((name) => `"${name}"`), Array.join(", "))}. Pass a valid \`name\` to \`app.use\`.`
|
|
162
|
+
});
|
|
163
|
+
const duplicateNames = pipe(components, Array.groupBy(({ name }) => name), Record.toEntries, Array.filter(([, group]) => group.length > 1), Array.map(([name]) => name));
|
|
164
|
+
if (Array.isArrayNonEmpty(duplicateNames)) return yield* new InvalidConvexConfigError({
|
|
165
|
+
configPath: displayPath,
|
|
166
|
+
reason: `multiple components are installed under the same name (${Array.join(duplicateNames, ", ")}); pass a unique \`name\` to \`app.use\` for each.`
|
|
167
|
+
});
|
|
168
|
+
return components;
|
|
169
|
+
});
|
|
170
|
+
/**
|
|
171
|
+
* The name passed to `defineComponent`, independent of the package's ID scope.
|
|
172
|
+
*/
|
|
173
|
+
const componentName = Effect.fnUntraced(function* (configPath) {
|
|
174
|
+
const path = yield* Path.Path;
|
|
175
|
+
const { module } = yield* bundle(configPath, { plugins: [componentConfigPlugin(path)] }).pipe(Effect.mapError((error) => fromBundlerError("convex/convex.config.ts", error)));
|
|
176
|
+
const definition = module.default;
|
|
177
|
+
if (!Predicate.hasProperty(definition, "_name") || !Predicate.isString(definition._name)) return yield* new InvalidConvexConfigError({
|
|
178
|
+
configPath: "convex/convex.config.ts",
|
|
179
|
+
reason: "the component definition must have a string name."
|
|
180
|
+
});
|
|
181
|
+
return definition._name;
|
|
182
|
+
});
|
|
183
|
+
/**
|
|
184
|
+
* The module specifier the generated registry's `ComponentApi` type import
|
|
185
|
+
* should use for a component, following Convex's own codegen convention:
|
|
186
|
+
* `<definition directory>/_generated/component.js`. Bare (npm) definition
|
|
187
|
+
* directories are used verbatim; locally-defined components (recorded as
|
|
188
|
+
* absolute directories) become a relative path from `confect/_generated`.
|
|
189
|
+
*/
|
|
190
|
+
const typeImportPath = (path, componentDefinitionPath, confectGeneratedDirectory) => {
|
|
191
|
+
if (!path.isAbsolute(componentDefinitionPath)) return componentDefinitionPath;
|
|
192
|
+
const relative = toPosixPath(path, path.relative(confectGeneratedDirectory, componentDefinitionPath));
|
|
193
|
+
return String.startsWith(".")(relative) ? relative : `./${relative}`;
|
|
194
|
+
};
|
|
195
|
+
//#endregion
|
|
196
|
+
export { COMPONENT_IMPORT_KEY, CONVEX_CONFIG_FILENAME, componentConfigPlugin, componentImportOf, componentName, discoverInstalledComponents, resolveDefinition, typeImportPath };
|
|
197
|
+
|
|
198
|
+
//# sourceMappingURL=ConvexConfig.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConvexConfig.mjs","names":["Bundler.resolveModule","Bundler.bundle"],"sources":["../src/ConvexConfig.ts"],"sourcesContent":["import { pipe } from \"effect/Function\";\nimport * as Array from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Match from \"effect/Match\";\nimport type * as FileSystem from \"effect/FileSystem\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport * as Path from \"effect/Path\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Record from \"effect/Record\";\nimport * as Schema from \"effect/Schema\";\nimport * as String from \"effect/String\";\nimport type * as esbuild from \"esbuild\";\nimport { fromBundlerError, type BuildError } from \"./BuildError\";\nimport * as Bundler from \"./Bundler\";\nimport { InvalidConvexConfigError } from \"./CodegenError\";\nimport { toPosixPath } from \"./utils\";\n\nexport const CONVEX_CONFIG_FILENAME = \"convex.config.ts\";\n\n/**\n * A component installed on the app via `app.use(...)` in\n * `convex/convex.config.ts`.\n */\nexport interface InstalledComponent {\n /**\n * The mount name (`app.use`'s `name` option, falling back to the name the\n * component was defined with).\n */\n readonly name: string;\n readonly httpPrefix?: string;\n /**\n * The directory the component's definition lives in, mirroring the Convex\n * runtime's convention (a `componentDefinitionPath` identifies the\n * definition's directory): the import specifier minus its trailing\n * `convex.config` segment when it was bare (e.g. `@convex-dev/workpool`), or\n * the resolved absolute directory when it was relative (a locally-defined\n * component).\n */\n readonly componentDefinitionPath: string;\n}\n\nconst COMPONENT_CONFIG_NAMESPACE = \"confect-component-config\";\n\n/**\n * Where the plugin records how a definition was imported: the specifier as\n * written and the file it resolved to. Codegen reads it to write the import of\n * each mounted component into the generated `convex.config.ts`.\n */\nexport const COMPONENT_IMPORT_KEY = \"~confect/componentImport\";\n\nexport interface ComponentImport {\n readonly specifier: string;\n readonly path: string;\n}\n\nexport const componentImportOf = (\n definition: unknown,\n): Option.Option<ComponentImport> => {\n if (!Predicate.hasProperty(definition, COMPONENT_IMPORT_KEY)) {\n return Option.none();\n }\n const recorded = definition[COMPONENT_IMPORT_KEY];\n return Predicate.hasProperty(recorded, \"specifier\") &&\n Predicate.isString(recorded.specifier) &&\n Predicate.hasProperty(recorded, \"path\") &&\n Predicate.isString(recorded.path)\n ? Option.some({ specifier: recorded.specifier, path: recorded.path })\n : Option.none();\n};\n\n/**\n * Matches the trailing `convex.config` segment of a component-definition import\n * (with or without an extension), e.g. `@convex-dev/workpool/convex.config` or\n * `./waitlist/convex.config.ts`.\n */\nconst CONVEX_CONFIG_SUFFIX = /[/\\\\]convex\\.config(\\.[cm]?[jt]s)?$/;\n\n/**\n * Resolve the same config spellings that Convex accepts, for configs and test\n * kits.\n */\nexport const resolveDefinition = (\n specifier: string,\n importer: string,\n path: Path.Path,\n): Option.Option<string> => {\n const extension = path.extname(specifier);\n const candidates = [\n specifier,\n ...(extension === \".js\" ? [specifier.slice(0, -3) + \".ts\"] : []),\n ...(extension !== \".js\" && extension !== \".ts\"\n ? [specifier + \".js\", specifier + \".ts\"]\n : []),\n ];\n return Option.firstSomeOf(\n candidates.map((candidate) => Bundler.resolveModule(candidate, importer)),\n );\n};\n\n/**\n * `convex/server`'s `app.use(definition)` rejects any definition object that\n * lacks a string `componentDefinitionPath` (\"This code only works in Convex\n * runtime\"): that property is normally stamped on by the Convex backend's\n * module system when it evaluates a definition bundle. To evaluate\n * `convex.config.ts` in plain Node, this plugin intercepts every non-entry\n * import of a `convex.config` module (mirroring the Convex CLI's own\n * `componentPlugin`) and swaps in a virtual wrapper that re-exports the real\n * definition with `componentDefinitionPath` and `defaultName` filled in—the\n * exact shape of Convex's `ImportedComponentDefinition`.\n */\nexport const componentConfigPlugin = (path: Path.Path): esbuild.Plugin => ({\n name: \"confect:component-config\",\n setup(build) {\n build.onResolve({ filter: /convex\\.config/ }, (args) => {\n // The app's own `convex.config.ts` is the entry point; only imports of\n // *component* definitions get wrapped.\n if (args.kind === \"entry-point\") return undefined;\n\n // Claim a wrapper's import of the real definition into the file\n // namespace: bundled, the definition's own nested `convex.config`\n // imports re-enter this plugin and get stamped; externalized, an npm\n // definition would be evaluated natively by Node, where its top-level\n // `component.use(...)` of unstamped nested definitions throws.\n if (args.namespace === COMPONENT_CONFIG_NAMESPACE) {\n return { path: args.path };\n }\n if (args.namespace !== \"file\" && args.namespace !== \"\") return undefined;\n\n const importer =\n args.importer !== \"\" ? args.importer : path.join(args.resolveDir, \"_\");\n\n // Component definitions are conventionally imported extensionless\n // (`.../convex.config`), which npm `exports` maps resolve but plain\n // file resolution may not—probe the same candidates Convex does.\n return pipe(\n resolveDefinition(args.path, importer, path),\n Option.match({\n onNone: () => undefined,\n onSome: (resolved) => ({\n path: resolved,\n namespace: COMPONENT_CONFIG_NAMESPACE,\n pluginData: { specifier: args.path },\n }),\n }),\n );\n });\n\n build.onLoad(\n { filter: /.*/, namespace: COMPONENT_CONFIG_NAMESPACE },\n (args) => {\n const specifier = (args.pluginData as { specifier: string }).specifier;\n // The injected path is the definition's *directory*, matching the\n // Convex runtime's convention—so even if a future convex version\n // stops reading `defaultName`, `app.use`'s last-resort fallback\n // (`componentDefinitionPath.split(\"/\").pop()`) still yields the\n // conventional component name rather than `convex.config`. Convex's\n // codegen doesn't trust relative specifiers as identifiers (the\n // importer's location is lost after bundling), so those are recorded\n // as the resolved absolute directory; bare specifiers keep their\n // package prefix so the generated type import stays a package\n // specifier.\n const isBareSpecifier =\n !String.startsWith(\".\")(specifier) && !path.isAbsolute(specifier);\n const componentDefinitionPath = isBareSpecifier\n ? String.replace(CONVEX_CONFIG_SUFFIX, \"\")(specifier)\n : path.dirname(args.path);\n\n // The real module is imported (not inlined) so any nested\n // `convex.config` imports resolve from the definition's own file\n // rather than from this virtual wrapper. `defaultName` comes from\n // `defineComponent(name)`'s `_name`, keeping `app.use`'s name\n // resolution identical to the Convex runtime's.\n return {\n loader: \"js\",\n resolveDir: path.dirname(args.path),\n contents: Array.join(\n [\n `import real from ${JSON.stringify(args.path)};`,\n `export default { ...real, componentDefinitionPath: ${JSON.stringify(componentDefinitionPath)}, defaultName: real._name, [${JSON.stringify(COMPONENT_IMPORT_KEY)}]: ${JSON.stringify({ specifier, path: args.path })} };`,\n ],\n \"\\n\",\n ),\n };\n },\n );\n },\n});\n\n/**\n * The subset of `app.export()` (Convex's `AppDefinitionAnalysis`) that the\n * registry needs: each installed component's mount name and the\n * `componentDefinitionPath` injected by {@link componentConfigPlugin}.\n */\nconst AppDefinitionAnalysis = Schema.Struct({\n httpMounts: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),\n childComponents: Schema.Array(\n Schema.Struct({\n name: Schema.String,\n path: Schema.String,\n }),\n ),\n});\n\nconst byName = Order.mapInput(\n Order.String,\n (component: InstalledComponent) => component.name,\n);\n\n/**\n * Convex component names must be alphanumeric plus underscores (see\n * `defineComponent`'s docs). Beyond rejecting genuinely invalid names, this is\n * a drift tripwire: if a future convex version stopped resolving names the way\n * we rely on (e.g. `defaultName` disappearing), the fallback name would be a\n * path segment like `convex.config`—caught here as a clear error instead of\n * silently emitting a broken registry.\n */\nconst VALID_COMPONENT_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/**\n * Bundle and evaluate `convex/convex.config.ts` and list the components\n * installed on the app, in mount-name order. `displayPath` is used in error\n * messages (mirroring how impl/spec bundling reports relative paths).\n */\nexport const discoverInstalledComponents = Effect.fn(\n \"ConvexConfig.discoverInstalledComponents\",\n)(function* (\n convexConfigPath: string,\n displayPath: string,\n kind: \"app\" | \"component\" = \"app\",\n): Effect.fn.Return<\n ReadonlyArray<InstalledComponent>,\n BuildError | InvalidConvexConfigError,\n Path.Path | FileSystem.FileSystem\n> {\n const path = yield* Path.Path;\n\n const { module } = yield* Bundler.bundle(convexConfigPath, {\n plugins: [componentConfigPlugin(path)],\n }).pipe(Effect.mapError((error) => fromBundlerError(displayPath, error)));\n\n const app = module.default as\n | { _isRoot?: unknown; export?: unknown }\n | null\n | undefined;\n\n const definition = Match.value(kind).pipe(\n Match.when(\"app\", () => ({ isRoot: true, constructor: \"defineApp\" })),\n Match.when(\"component\", () => ({\n isRoot: false,\n constructor: \"defineComponent\",\n })),\n Match.exhaustive,\n );\n\n if (\n app === null ||\n typeof app !== \"object\" ||\n app._isRoot !== definition.isRoot ||\n typeof app.export !== \"function\"\n ) {\n return yield* new InvalidConvexConfigError({\n configPath: displayPath,\n reason: `it must default-export the ${kind} definition created by \\`${definition.constructor}()\\`.`,\n });\n }\n\n const analysis = yield* Effect.try({\n try: () => (app.export as () => unknown)(),\n catch: (cause) =>\n new InvalidConvexConfigError({\n configPath: displayPath,\n reason: `exporting the app definition threw: ${globalThis.String(cause)}.`,\n }),\n });\n\n const decoded = yield* Schema.decodeUnknownEffect(AppDefinitionAnalysis)(\n analysis,\n ).pipe(\n Effect.mapError(\n (cause) =>\n new InvalidConvexConfigError({\n configPath: displayPath,\n reason: `the app definition's installed components could not be read: ${cause.message}.`,\n }),\n ),\n );\n\n const components = pipe(\n decoded.childComponents,\n Array.map(({ name, path: componentDefinitionPath }): InstalledComponent => {\n const httpPrefix = Object.entries(decoded.httpMounts ?? {}).find(\n ([, reference]) => reference === `_reference/childComponent/${name}`,\n )?.[0];\n return {\n name,\n componentDefinitionPath,\n ...(httpPrefix === undefined\n ? {}\n : { httpPrefix: httpPrefix.replace(/\\/$/, \"\") }),\n };\n }),\n Array.sort(byName),\n );\n\n const invalidNames = pipe(\n components,\n Array.map(({ name }) => name),\n Array.filter((name) =>\n Option.isNone(String.match(VALID_COMPONENT_NAME)(name)),\n ),\n );\n if (Array.isArrayNonEmpty(invalidNames)) {\n return yield* new InvalidConvexConfigError({\n configPath: displayPath,\n reason: `component names must be alphanumeric plus underscores, but got: ${pipe(\n invalidNames,\n Array.map((name) => `\"${name}\"`),\n Array.join(\", \"),\n )}. Pass a valid \\`name\\` to \\`app.use\\`.`,\n });\n }\n\n const duplicateNames = pipe(\n components,\n Array.groupBy(({ name }) => name),\n Record.toEntries,\n Array.filter(([, group]) => group.length > 1),\n Array.map(([name]) => name),\n );\n if (Array.isArrayNonEmpty(duplicateNames)) {\n return yield* new InvalidConvexConfigError({\n configPath: displayPath,\n reason: `multiple components are installed under the same name (${Array.join(duplicateNames, \", \")}); pass a unique \\`name\\` to \\`app.use\\` for each.`,\n });\n }\n\n return components;\n});\n\n/**\n * The name passed to `defineComponent`, independent of the package's ID scope.\n */\nexport const componentName = Effect.fnUntraced(function* (configPath: string) {\n const path = yield* Path.Path;\n const { module } = yield* Bundler.bundle(configPath, {\n plugins: [componentConfigPlugin(path)],\n }).pipe(\n Effect.mapError((error) =>\n fromBundlerError(\"convex/convex.config.ts\", error),\n ),\n );\n const definition: unknown = module.default;\n if (\n !Predicate.hasProperty(definition, \"_name\") ||\n !Predicate.isString(definition._name)\n ) {\n return yield* new InvalidConvexConfigError({\n configPath: \"convex/convex.config.ts\",\n reason: \"the component definition must have a string name.\",\n });\n }\n return definition._name;\n});\n\n/**\n * The module specifier the generated registry's `ComponentApi` type import\n * should use for a component, following Convex's own codegen convention:\n * `<definition directory>/_generated/component.js`. Bare (npm) definition\n * directories are used verbatim; locally-defined components (recorded as\n * absolute directories) become a relative path from `confect/_generated`.\n */\nexport const typeImportPath = (\n path: Path.Path,\n componentDefinitionPath: string,\n confectGeneratedDirectory: string,\n): string => {\n if (!path.isAbsolute(componentDefinitionPath)) {\n return componentDefinitionPath;\n }\n const relative = toPosixPath(\n path,\n path.relative(confectGeneratedDirectory, componentDefinitionPath),\n );\n return String.startsWith(\".\")(relative) ? relative : `./${relative}`;\n};\n"],"mappings":"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"}
|