@lunora/codegen 0.0.0 → 1.0.0-alpha.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.
- package/LICENSE.md +105 -0
- package/README.md +117 -9
- package/__assets__/package-og.svg +14 -0
- package/dist/index.d.mts +1562 -0
- package/dist/index.d.ts +1562 -0
- package/dist/index.mjs +29 -0
- package/dist/packem_shared/CONTAINERS_FILENAME-DlP6YM_Q.mjs +224 -0
- package/dist/packem_shared/CodegenDiagnosticError-DeblMkzO.mjs +23 -0
- package/dist/packem_shared/GENERATED_HEADER-BiFXNUvo.mjs +2692 -0
- package/dist/packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs +61 -0
- package/dist/packem_shared/OPENRPC_VERSION-B4i9Qp3v.mjs +60 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-Bvv7qa_u.mjs +939 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs +245 -0
- package/dist/packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs +84 -0
- package/dist/packem_shared/buildOpenApiDocument-Cu3mZl-8.mjs +183 -0
- package/dist/packem_shared/discover-ast-CT6BgBr4.mjs +13 -0
- package/dist/packem_shared/discoverAuthApiCalls-CoirYbg6.mjs +62 -0
- package/dist/packem_shared/discoverCrons-Cev7RRAf.mjs +257 -0
- package/dist/packem_shared/discoverFunctions-BWMczzBx.mjs +465 -0
- package/dist/packem_shared/discoverHttpRoutes-CfP6cMzt.mjs +131 -0
- package/dist/packem_shared/discoverInserts-C7zxXkUf.mjs +61 -0
- package/dist/packem_shared/discoverMaskProcedures-Cm81kwrb.mjs +217 -0
- package/dist/packem_shared/discoverMigrations-Bi5nJ0mJ.mjs +97 -0
- package/dist/packem_shared/discoverNondeterministicCalls-C4M8AXmQ.mjs +122 -0
- package/dist/packem_shared/discoverQueries-B0wGT-xe.mjs +62 -0
- package/dist/packem_shared/discoverR2sqlCalls-BVNMd428.mjs +80 -0
- package/dist/packem_shared/discoverRlsMetadata-BS9GOGC5.mjs +280 -0
- package/dist/packem_shared/discoverSchema-BnWHHJ4T.mjs +822 -0
- package/dist/packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs +97 -0
- package/dist/packem_shared/emitApp-KfMaKXWe.mjs +603 -0
- package/dist/packem_shared/formatAdvisories-8NIv1k0I.mjs +69 -0
- package/dist/packem_shared/parse-validator-Cabb60UV.mjs +133 -0
- package/dist/packem_shared/paths-BRd6JHuF.mjs +11 -0
- package/dist/packem_shared/schemaFromIr-DTYsLBaA.mjs +57 -0
- package/package.json +45 -17
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { formatAdvisories, lintSchema } from './packem_shared/formatAdvisories-8NIv1k0I.mjs';
|
|
2
|
+
export { CodegenDiagnosticError, diagnosticAt } from './packem_shared/CodegenDiagnosticError-DeblMkzO.mjs';
|
|
3
|
+
export { default as discoverAuthApiCalls } from './packem_shared/discoverAuthApiCalls-CoirYbg6.mjs';
|
|
4
|
+
export { CONTAINERS_FILENAME, discoverContainers } from './packem_shared/CONTAINERS_FILENAME-DlP6YM_Q.mjs';
|
|
5
|
+
export { default as discoverCrons } from './packem_shared/discoverCrons-Cev7RRAf.mjs';
|
|
6
|
+
export { discoverFunctions } from './packem_shared/discoverFunctions-BWMczzBx.mjs';
|
|
7
|
+
export { default as discoverHttpRoutes } from './packem_shared/discoverHttpRoutes-CfP6cMzt.mjs';
|
|
8
|
+
export { default as discoverInserts } from './packem_shared/discoverInserts-C7zxXkUf.mjs';
|
|
9
|
+
export { default as discoverMaskProcedures } from './packem_shared/discoverMaskProcedures-Cm81kwrb.mjs';
|
|
10
|
+
export { default as discoverMigrations } from './packem_shared/discoverMigrations-Bi5nJ0mJ.mjs';
|
|
11
|
+
export { default as discoverNondeterministicCalls } from './packem_shared/discoverNondeterministicCalls-C4M8AXmQ.mjs';
|
|
12
|
+
export { default as discoverQueries } from './packem_shared/discoverQueries-B0wGT-xe.mjs';
|
|
13
|
+
export { default as discoverR2sqlCalls } from './packem_shared/discoverR2sqlCalls-BVNMd428.mjs';
|
|
14
|
+
export { discoverRlsMetadata, default as discoverRlsProcedures } from './packem_shared/discoverRlsMetadata-BS9GOGC5.mjs';
|
|
15
|
+
export { default as discoverSchema } from './packem_shared/discoverSchema-BnWHHJ4T.mjs';
|
|
16
|
+
export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
17
|
+
export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
18
|
+
export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-BiFXNUvo.mjs';
|
|
19
|
+
export { emitApp } from './packem_shared/emitApp-KfMaKXWe.mjs';
|
|
20
|
+
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-Cu3mZl-8.mjs';
|
|
21
|
+
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-B4i9Qp3v.mjs';
|
|
22
|
+
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-Bvv7qa_u.mjs';
|
|
23
|
+
export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
24
|
+
export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
|
|
25
|
+
export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
26
|
+
|
|
27
|
+
const VERSION = "0.0.0";
|
|
28
|
+
|
|
29
|
+
export { VERSION };
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { containerClassName, containerBindingName, normalizeContainerImage } from '@lunora/container';
|
|
4
|
+
import { SyntaxKind, Node } from 'ts-morph';
|
|
5
|
+
import { diagnosticAt } from './CodegenDiagnosticError-DeblMkzO.mjs';
|
|
6
|
+
|
|
7
|
+
const CONTAINERS_FILENAME = "containers.ts";
|
|
8
|
+
const isDefineContainer = (identifier) => {
|
|
9
|
+
const symbol = identifier.getSymbol();
|
|
10
|
+
if (!symbol) {
|
|
11
|
+
return identifier.getText() === "defineContainer";
|
|
12
|
+
}
|
|
13
|
+
for (const declaration of symbol.getDeclarations()) {
|
|
14
|
+
if (!Node.isImportSpecifier(declaration)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (declaration.getImportDeclaration().getModuleSpecifierValue() !== "@lunora/container") {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return declaration.getNameNode().getText() === "defineContainer";
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
const stringProperty = (expression, exportName, property) => {
|
|
25
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
26
|
+
return expression.getLiteralValue();
|
|
27
|
+
}
|
|
28
|
+
throw diagnosticAt(
|
|
29
|
+
expression,
|
|
30
|
+
`container "${exportName}": \`${property}\` must be a static string literal — it is deploy configuration codegen writes into wrangler.jsonc`
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
const numberProperty = (expression, exportName, property) => {
|
|
34
|
+
if (Node.isNumericLiteral(expression)) {
|
|
35
|
+
return expression.getLiteralValue();
|
|
36
|
+
}
|
|
37
|
+
throw diagnosticAt(
|
|
38
|
+
expression,
|
|
39
|
+
`container "${exportName}": \`${property}\` must be a static number literal — it is deploy configuration codegen writes into wrangler.jsonc`
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
const imageFromExpression = (expression, exportName) => {
|
|
43
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
44
|
+
return normalizeContainerImage(expression.getLiteralValue());
|
|
45
|
+
}
|
|
46
|
+
if (Node.isObjectLiteralExpression(expression)) {
|
|
47
|
+
const registry = expression.getProperty("registry");
|
|
48
|
+
if (registry && Node.isPropertyAssignment(registry)) {
|
|
49
|
+
const initializer = registry.getInitializerOrThrow();
|
|
50
|
+
return normalizeContainerImage({ registry: stringProperty(initializer, exportName, "image.registry") });
|
|
51
|
+
}
|
|
52
|
+
const build = expression.getProperty("build");
|
|
53
|
+
if (build && Node.isPropertyAssignment(build)) {
|
|
54
|
+
const initializer = build.getInitializerOrThrow();
|
|
55
|
+
return normalizeContainerImage({ build: stringProperty(initializer, exportName, "image.build") });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
throw diagnosticAt(expression, `container "${exportName}": \`image\` must be a static string path, { registry: "…" }, or { build: "…" } literal`);
|
|
59
|
+
};
|
|
60
|
+
const stringRecordLiteral = (expression) => {
|
|
61
|
+
if (!Node.isObjectLiteralExpression(expression)) {
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
const record = {};
|
|
65
|
+
for (const property of expression.getProperties()) {
|
|
66
|
+
if (!Node.isPropertyAssignment(property)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const value = property.getInitializerOrThrow();
|
|
70
|
+
if (Node.isStringLiteral(value) || Node.isNoSubstitutionTemplateLiteral(value)) {
|
|
71
|
+
record[property.getName()] = value.getLiteralValue();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return Object.keys(record).length > 0 ? record : void 0;
|
|
75
|
+
};
|
|
76
|
+
const rolloutLiteral = (expression) => {
|
|
77
|
+
if (!Node.isObjectLiteralExpression(expression)) {
|
|
78
|
+
return void 0;
|
|
79
|
+
}
|
|
80
|
+
const rollout = {};
|
|
81
|
+
for (const property of expression.getProperties()) {
|
|
82
|
+
if (!Node.isPropertyAssignment(property)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const key = property.getName();
|
|
86
|
+
const value = property.getInitializerOrThrow();
|
|
87
|
+
if (Node.isNumericLiteral(value) && (key === "gracePeriodSeconds" || key === "stepPercentage")) {
|
|
88
|
+
rollout[key] = value.getLiteralValue();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return rollout.gracePeriodSeconds === void 0 && rollout.stepPercentage === void 0 ? void 0 : rollout;
|
|
92
|
+
};
|
|
93
|
+
const booleanLiteral = (expression) => {
|
|
94
|
+
if (Node.isTrueLiteral(expression)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (Node.isFalseLiteral(expression)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return void 0;
|
|
101
|
+
};
|
|
102
|
+
const stringOrNumberLiteral = (expression) => {
|
|
103
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
104
|
+
return expression.getLiteralValue();
|
|
105
|
+
}
|
|
106
|
+
if (Node.isNumericLiteral(expression)) {
|
|
107
|
+
return expression.getLiteralValue();
|
|
108
|
+
}
|
|
109
|
+
return void 0;
|
|
110
|
+
};
|
|
111
|
+
const instanceTypeFromExpression = (expression, exportName) => {
|
|
112
|
+
if (Node.isStringLiteral(expression)) {
|
|
113
|
+
return expression.getLiteralValue();
|
|
114
|
+
}
|
|
115
|
+
if (Node.isObjectLiteralExpression(expression)) {
|
|
116
|
+
const custom = {};
|
|
117
|
+
for (const property of expression.getProperties()) {
|
|
118
|
+
if (!Node.isPropertyAssignment(property)) {
|
|
119
|
+
throw diagnosticAt(property, `container "${exportName}": \`instanceType\` must be an object of static number literals`);
|
|
120
|
+
}
|
|
121
|
+
const key = property.getName();
|
|
122
|
+
if (key !== "diskMb" && key !== "memoryMib" && key !== "vcpu") {
|
|
123
|
+
throw diagnosticAt(property, `container "${exportName}": unknown \`instanceType\` field "${key}" — expected vcpu, memoryMib, or diskMb`);
|
|
124
|
+
}
|
|
125
|
+
custom[key] = numberProperty(property.getInitializerOrThrow(), exportName, `instanceType.${key}`);
|
|
126
|
+
}
|
|
127
|
+
return custom;
|
|
128
|
+
}
|
|
129
|
+
throw diagnosticAt(expression, `container "${exportName}": \`instanceType\` must be a static string or { vcpu, memoryMib, diskMb } literal`);
|
|
130
|
+
};
|
|
131
|
+
const containerFromCall = (call, exportName) => {
|
|
132
|
+
const argument = call.getArguments()[0];
|
|
133
|
+
if (!argument || !Node.isObjectLiteralExpression(argument)) {
|
|
134
|
+
throw diagnosticAt(call, `container "${exportName}": defineContainer must be passed an inline object literal`);
|
|
135
|
+
}
|
|
136
|
+
const ir = {
|
|
137
|
+
bindingName: containerBindingName(exportName),
|
|
138
|
+
className: containerClassName(exportName),
|
|
139
|
+
exportName,
|
|
140
|
+
image: { buildContext: ".", dockerfilePath: "./Dockerfile", kind: "dockerfile" }
|
|
141
|
+
};
|
|
142
|
+
let sawImage = false;
|
|
143
|
+
for (const property of argument.getProperties()) {
|
|
144
|
+
if (!Node.isPropertyAssignment(property)) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const key = property.getName();
|
|
148
|
+
const initializer = property.getInitializerOrThrow();
|
|
149
|
+
switch (key) {
|
|
150
|
+
case "buildArgs": {
|
|
151
|
+
ir.buildArgs = stringRecordLiteral(initializer);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "enableInternet": {
|
|
155
|
+
ir.enableInternet = booleanLiteral(initializer);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case "image": {
|
|
159
|
+
ir.image = imageFromExpression(initializer, exportName);
|
|
160
|
+
sawImage = true;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case "instanceType": {
|
|
164
|
+
ir.instanceType = instanceTypeFromExpression(initializer, exportName);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case "maxInstances": {
|
|
168
|
+
ir.maxInstances = numberProperty(initializer, exportName, "maxInstances");
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
case "name": {
|
|
172
|
+
ir.name = stringProperty(initializer, exportName, "name");
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case "rollout": {
|
|
176
|
+
ir.rollout = rolloutLiteral(initializer);
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case "sleepAfter": {
|
|
180
|
+
ir.sleepAfter = stringOrNumberLiteral(initializer);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (!sawImage) {
|
|
186
|
+
throw diagnosticAt(argument, `container "${exportName}": defineContainer requires a static \`image\` property`);
|
|
187
|
+
}
|
|
188
|
+
return ir;
|
|
189
|
+
};
|
|
190
|
+
const containersFromSource = (source) => {
|
|
191
|
+
const containers = [];
|
|
192
|
+
for (const declaration of source.getVariableDeclarations()) {
|
|
193
|
+
if (!declaration.isExported()) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const initializer = declaration.getInitializer();
|
|
197
|
+
if (initializer?.getKind() !== SyntaxKind.CallExpression) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const call = initializer;
|
|
201
|
+
const callee = call.getExpression();
|
|
202
|
+
if (!Node.isIdentifier(callee) || !isDefineContainer(callee)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const nameNode = declaration.getNameNode();
|
|
206
|
+
if (!Node.isIdentifier(nameNode)) {
|
|
207
|
+
throw diagnosticAt(nameNode, "defineContainer exports must be plain named exports (no destructuring)");
|
|
208
|
+
}
|
|
209
|
+
containers.push(containerFromCall(call, nameNode.getText()));
|
|
210
|
+
}
|
|
211
|
+
return containers;
|
|
212
|
+
};
|
|
213
|
+
const discoverContainers = (project, lunoraDirectory) => {
|
|
214
|
+
const containersPath = join(lunoraDirectory, CONTAINERS_FILENAME);
|
|
215
|
+
if (!existsSync(containersPath)) {
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
const source = project.getSourceFile(containersPath) ?? project.addSourceFileAtPath(containersPath);
|
|
219
|
+
const containers = containersFromSource(source);
|
|
220
|
+
containers.sort((a, b) => a.exportName.localeCompare(b.exportName));
|
|
221
|
+
return containers;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export { CONTAINERS_FILENAME, discoverContainers };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class CodegenDiagnosticError extends Error {
|
|
2
|
+
column;
|
|
3
|
+
file;
|
|
4
|
+
line;
|
|
5
|
+
constructor(message, file, line, column) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "CodegenDiagnosticError";
|
|
8
|
+
this.file = file;
|
|
9
|
+
this.line = line;
|
|
10
|
+
this.column = column;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const diagnosticAt = (node, detail, meta) => {
|
|
14
|
+
const sourceFile = node.getSourceFile();
|
|
15
|
+
const file = sourceFile.getFilePath();
|
|
16
|
+
const line = node.getStartLineNumber();
|
|
17
|
+
const { column } = sourceFile.getLineAndColumnAtPos(node.getStart());
|
|
18
|
+
const message = `@lunora/codegen: ${detail} (${file}:${line.toString()}:${column.toString()})`;
|
|
19
|
+
const error = new CodegenDiagnosticError(message, file, line, column);
|
|
20
|
+
return meta ? Object.assign(error, meta) : error;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { CodegenDiagnosticError, diagnosticAt };
|