@lunora/codegen 1.0.0-alpha.14 → 1.0.0-alpha.141
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 +6 -0
- package/dist/index.d.mts +3018 -1005
- package/dist/index.d.ts +3018 -1005
- package/dist/index.mjs +1 -31
- package/dist/packem_shared/AGENTS_FILENAME-D1qA0h5m.mjs +1 -0
- package/dist/packem_shared/CONTAINERS_FILENAME-oKaARMoA.mjs +1 -0
- package/dist/packem_shared/CodegenDiagnosticError-BUXlG3P-.mjs +1 -0
- package/dist/packem_shared/DEFAULT_TARGET-CrhWLUK7.mjs +1 -0
- package/dist/packem_shared/FLAGS_FILENAME-BasxlnVS.mjs +1 -0
- package/dist/packem_shared/GENERATED_HEADER-BgmuZY9e.mjs +1 -0
- package/dist/packem_shared/LUNORA_ERROR_CODES-BYg8Lpgb.mjs +1 -0
- package/dist/packem_shared/MUTATORS_FILENAME-DJvAhDlD.mjs +1 -0
- package/dist/packem_shared/NOTIFY_FILENAME-B-eIjru_.mjs +1 -0
- package/dist/packem_shared/OPENRPC_VERSION-B9ZC0SrC.mjs +3 -0
- package/dist/packem_shared/QUEUES_FILENAME-D229WtRm.mjs +1 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-iOZaWN69.mjs +9 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-DLXXalg2.mjs +2 -0
- package/dist/packem_shared/SDK_LANGUAGES-CFyux-74.mjs +371 -0
- package/dist/packem_shared/SHAPES_FILENAME-BTdasTq2.mjs +1 -0
- package/dist/packem_shared/SchemaSnapshotParseError-CvPTjDrT.mjs +16 -0
- package/dist/packem_shared/WORKFLOWS_FILENAME-DRaiCNa6.mjs +1 -0
- package/dist/packem_shared/ast-CjWtsS6S.mjs +1 -0
- package/dist/packem_shared/buildOpenApiDocument-DLEWgA5Y.mjs +3 -0
- package/dist/packem_shared/chain-CtC3-wwZ.mjs +1 -0
- package/dist/packem_shared/classify-procedure-call-AKeIK05y.mjs +1 -0
- package/dist/packem_shared/describeErrorLevelFindings-D23VSkFP.mjs +1 -0
- package/dist/packem_shared/discoverAuthApiCalls-C35kkayg.mjs +1 -0
- package/dist/packem_shared/discoverCrons-wXBfQcfn.mjs +1 -0
- package/dist/packem_shared/discoverFunctions-BBDziFXy.mjs +1 -0
- package/dist/packem_shared/discoverHttpRoutes-Dmow2gql.mjs +1 -0
- package/dist/packem_shared/discoverInserts-C5l2INmE.mjs +1 -0
- package/dist/packem_shared/discoverMaskProcedures-Df4JQp_2.mjs +1 -0
- package/dist/packem_shared/discoverMigrations-CWH7T6qz.mjs +1 -0
- package/dist/packem_shared/discoverNondeterministicCalls-JsO91i57.mjs +1 -0
- package/dist/packem_shared/discoverQueries-iypfwfdZ.mjs +1 -0
- package/dist/packem_shared/discoverR2sqlCalls-BbfOpwE4.mjs +1 -0
- package/dist/packem_shared/discoverRlsMetadata-DGUGYgWs.mjs +1 -0
- package/dist/packem_shared/discoverRlsProcedures-CRshfYZE.mjs +1 -0
- package/dist/packem_shared/discoverSandboxUsage-DdewAOuj.mjs +1 -0
- package/dist/packem_shared/discoverSchema-Bp8DcNq7.mjs +1 -0
- package/dist/packem_shared/discoverStorageRulesMetadata-gyO60A5S.mjs +1 -0
- package/dist/packem_shared/emit-s6mHBmXu.mjs +2268 -0
- package/dist/packem_shared/emitApp-D1qxNeh1.mjs +646 -0
- package/dist/packem_shared/exported-procedure-chains-MlZRKqSD.mjs +1 -0
- package/dist/packem_shared/formatAdvisories-CkEu1eye.mjs +2 -0
- package/dist/packem_shared/index-CCDlo9L7.mjs +1 -0
- package/dist/packem_shared/isTypedSchema-B_qlBbE-.mjs +2 -0
- package/dist/packem_shared/module-specifiers-WF8iAydP.mjs +1 -0
- package/dist/packem_shared/parse-validator-BFTp87yz.mjs +1 -0
- package/dist/packem_shared/paths-C-9fwEgQ.mjs +1 -0
- package/dist/packem_shared/queries-B_xEHIeL.mjs +1 -0
- package/dist/packem_shared/readPackageDependencies-C6h6FZuP.mjs +1 -0
- package/dist/packem_shared/redact-Cy14LEnc.mjs +1 -0
- package/dist/packem_shared/schemaFromIr-BWFnvCVg.mjs +1 -0
- package/dist/packem_shared/unwrap-handler-return-CmIWbykC.mjs +1 -0
- package/package.json +16 -7
- package/dist/packem_shared/CONTAINERS_FILENAME-DlP6YM_Q.mjs +0 -224
- package/dist/packem_shared/CodegenDiagnosticError-DeblMkzO.mjs +0 -23
- package/dist/packem_shared/GENERATED_HEADER-BEA7oWGC.mjs +0 -2841
- package/dist/packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs +0 -61
- package/dist/packem_shared/LUNORA_SOLUTION_RULES-BTejmZp-.mjs +0 -131
- package/dist/packem_shared/OPENRPC_VERSION-CQ3f8YQ-.mjs +0 -60
- package/dist/packem_shared/QUEUES_FILENAME-B5_eWCRe.mjs +0 -119
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-BXtduJFE.mjs +0 -954
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs +0 -245
- package/dist/packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs +0 -84
- package/dist/packem_shared/buildOpenApiDocument-699G4RP4.mjs +0 -183
- package/dist/packem_shared/discover-ast-CT6BgBr4.mjs +0 -13
- package/dist/packem_shared/discoverAuthApiCalls-CoirYbg6.mjs +0 -62
- package/dist/packem_shared/discoverCrons-Cev7RRAf.mjs +0 -257
- package/dist/packem_shared/discoverFunctions-BWMczzBx.mjs +0 -465
- package/dist/packem_shared/discoverHttpRoutes-CfP6cMzt.mjs +0 -131
- package/dist/packem_shared/discoverInserts-C7zxXkUf.mjs +0 -61
- package/dist/packem_shared/discoverMaskProcedures-Cm81kwrb.mjs +0 -217
- package/dist/packem_shared/discoverMigrations-Bi5nJ0mJ.mjs +0 -97
- package/dist/packem_shared/discoverNondeterministicCalls-C4M8AXmQ.mjs +0 -122
- package/dist/packem_shared/discoverQueries-B0wGT-xe.mjs +0 -62
- package/dist/packem_shared/discoverR2sqlCalls-BVNMd428.mjs +0 -80
- package/dist/packem_shared/discoverRlsMetadata-BS9GOGC5.mjs +0 -280
- package/dist/packem_shared/discoverSchema-BnWHHJ4T.mjs +0 -822
- package/dist/packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs +0 -97
- package/dist/packem_shared/emitApp-DiK0QSBn.mjs +0 -617
- package/dist/packem_shared/formatAdvisories-8NIv1k0I.mjs +0 -69
- package/dist/packem_shared/parse-validator-Cabb60UV.mjs +0 -133
- package/dist/packem_shared/paths-BRd6JHuF.mjs +0 -11
- package/dist/packem_shared/schemaFromIr-DTYsLBaA.mjs +0 -57
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { runAdvisor } from '@lunora/advisor';
|
|
2
|
-
|
|
3
|
-
const flattenIndexes = (table) => [
|
|
4
|
-
...table.indexes.map((index) => {
|
|
5
|
-
return { fields: index.fields, kind: "index", name: index.name, unique: index.unique };
|
|
6
|
-
}),
|
|
7
|
-
...table.searchIndexes.map((index) => {
|
|
8
|
-
return { fields: [index.field, ...index.filterFields ?? []], kind: "search", name: index.name };
|
|
9
|
-
}),
|
|
10
|
-
...table.rankIndexes.map((index) => {
|
|
11
|
-
return { fields: [...index.sortBy.map((key) => key.field), ...index.partitionBy ?? []], kind: "rank", name: index.name };
|
|
12
|
-
}),
|
|
13
|
-
...table.vectorIndexes.filter((index) => index.field !== void 0).map((index) => {
|
|
14
|
-
return { fields: [index.field], kind: "vector", name: index.name };
|
|
15
|
-
})
|
|
16
|
-
];
|
|
17
|
-
const toAdvisorSchema = (schema) => {
|
|
18
|
-
return {
|
|
19
|
-
tables: schema.tables.map((table) => {
|
|
20
|
-
return {
|
|
21
|
-
externallyManaged: table.externallyManaged ?? false,
|
|
22
|
-
fields: Object.keys(table.shape),
|
|
23
|
-
indexes: flattenIndexes(table),
|
|
24
|
-
name: table.name,
|
|
25
|
-
relations: table.relations.map((relation) => {
|
|
26
|
-
return {
|
|
27
|
-
field: relation.field,
|
|
28
|
-
kind: relation.kind,
|
|
29
|
-
name: relation.name,
|
|
30
|
-
onDelete: relation.onDelete,
|
|
31
|
-
references: relation.references,
|
|
32
|
-
table: relation.table
|
|
33
|
-
};
|
|
34
|
-
})
|
|
35
|
-
};
|
|
36
|
-
})
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures, containers, workflows, workflowCalls, maskProcedures, nondeterministicCalls, procedureProtections, argumentValidators, secretLiterals, sqlInterpolations, adminRoutes, r2sqlCalls) => runAdvisor(
|
|
40
|
-
{
|
|
41
|
-
adminRoutes,
|
|
42
|
-
argValidators: argumentValidators,
|
|
43
|
-
authApiCalls,
|
|
44
|
-
containers,
|
|
45
|
-
inserts,
|
|
46
|
-
maskProcedures,
|
|
47
|
-
nondeterministicCalls,
|
|
48
|
-
procedureProtections,
|
|
49
|
-
queries,
|
|
50
|
-
r2sqlCalls,
|
|
51
|
-
rlsProcedures,
|
|
52
|
-
schema: toAdvisorSchema(schema),
|
|
53
|
-
secretLiterals,
|
|
54
|
-
sqlInterpolations,
|
|
55
|
-
workflowCalls,
|
|
56
|
-
workflows
|
|
57
|
-
},
|
|
58
|
-
{ source: "static" }
|
|
59
|
-
);
|
|
60
|
-
const formatAdvisories = (findings) => {
|
|
61
|
-
if (findings.length === 0) {
|
|
62
|
-
return "";
|
|
63
|
-
}
|
|
64
|
-
const header = `@lunora/codegen: ${String(findings.length)} schema advisor finding${findings.length === 1 ? "" : "s"}`;
|
|
65
|
-
const lines = findings.map((finding) => ` [${finding.level}] ${finding.name}: ${finding.detail}`);
|
|
66
|
-
return [header, ...lines].join("\n");
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export { formatAdvisories, lintSchema };
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { Node } from 'ts-morph';
|
|
2
|
-
|
|
3
|
-
const FIELD_NAME_RE = /^[A-Za-z_$][\w$]*$/u;
|
|
4
|
-
const COLUMN_MODIFIERS = /* @__PURE__ */ new Set(["$defaultFn", "$onUpdateFn", "$type", "default", "defaultNow", "nullable", "unique"]);
|
|
5
|
-
const applyColumnModifier = (base, modifier) => {
|
|
6
|
-
const column = { notNull: true, ...base.column };
|
|
7
|
-
switch (modifier) {
|
|
8
|
-
case "$defaultFn":
|
|
9
|
-
case "default":
|
|
10
|
-
case "defaultNow": {
|
|
11
|
-
column.hasDefault = true;
|
|
12
|
-
break;
|
|
13
|
-
}
|
|
14
|
-
case "$onUpdateFn": {
|
|
15
|
-
column.hasOnUpdate = true;
|
|
16
|
-
break;
|
|
17
|
-
}
|
|
18
|
-
case "$type": {
|
|
19
|
-
break;
|
|
20
|
-
}
|
|
21
|
-
case "nullable": {
|
|
22
|
-
column.notNull = false;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
case "unique": {
|
|
26
|
-
column.unique = true;
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return { ...base, column };
|
|
31
|
-
};
|
|
32
|
-
const SCALAR_KINDS = /* @__PURE__ */ new Set(["any", "bigint", "boolean", "bytes", "date", "null", "number", "string", "timestamp"]);
|
|
33
|
-
const TRANSPARENT_MODIFIERS = /* @__PURE__ */ new Set(["check", "meta"]);
|
|
34
|
-
const parseValidator = (expression) => {
|
|
35
|
-
if (Node.isCallExpression(expression)) {
|
|
36
|
-
return parseValidatorCall(expression);
|
|
37
|
-
}
|
|
38
|
-
return { kind: "any", sourceText: expression.getText() };
|
|
39
|
-
};
|
|
40
|
-
const parseObjectShape = (object) => {
|
|
41
|
-
const out = {};
|
|
42
|
-
for (const property of object.getProperties()) {
|
|
43
|
-
if (!Node.isPropertyAssignment(property)) {
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const nameNode = property.getNameNode();
|
|
47
|
-
if (Node.isComputedPropertyName(nameNode)) {
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const initializer = property.getInitializer();
|
|
51
|
-
if (!initializer) {
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const fieldName = property.getName();
|
|
55
|
-
if (!FIELD_NAME_RE.test(fieldName)) {
|
|
56
|
-
throw new Error(`@lunora/codegen: field name is not a valid JS identifier: ${JSON.stringify(fieldName)}`);
|
|
57
|
-
}
|
|
58
|
-
out[fieldName] = parseValidator(initializer);
|
|
59
|
-
}
|
|
60
|
-
return out;
|
|
61
|
-
};
|
|
62
|
-
const parseArgument = (argument, fallback) => argument && Node.isExpression(argument) ? parseValidator(argument) : fallback;
|
|
63
|
-
const parseBuilderMember = (member, args) => {
|
|
64
|
-
if (SCALAR_KINDS.has(member)) {
|
|
65
|
-
return { kind: member };
|
|
66
|
-
}
|
|
67
|
-
const [first, second] = args;
|
|
68
|
-
switch (member) {
|
|
69
|
-
case "array": {
|
|
70
|
-
return { inner: parseArgument(first, { kind: "any" }), kind: "array" };
|
|
71
|
-
}
|
|
72
|
-
case "from": {
|
|
73
|
-
return { kind: "from" };
|
|
74
|
-
}
|
|
75
|
-
case "id": {
|
|
76
|
-
return { kind: "id", tableName: first && Node.isStringLiteral(first) ? first.getLiteralText() : "_unknown_" };
|
|
77
|
-
}
|
|
78
|
-
case "literal": {
|
|
79
|
-
return {
|
|
80
|
-
kind: "literal",
|
|
81
|
-
// Captures the source text — for string/number/boolean/null literals
|
|
82
|
-
// this matches the TS type representation directly.
|
|
83
|
-
literalValue: first ? first.getText() : "undefined"
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
case "object": {
|
|
87
|
-
return first && Node.isObjectLiteralExpression(first) ? { kind: "object", shape: parseObjectShape(first) } : { kind: "object", shape: {} };
|
|
88
|
-
}
|
|
89
|
-
case "optional": {
|
|
90
|
-
return { inner: parseArgument(first, { kind: "any" }), kind: "optional" };
|
|
91
|
-
}
|
|
92
|
-
case "record": {
|
|
93
|
-
return {
|
|
94
|
-
keyType: parseArgument(first, { kind: "string" }),
|
|
95
|
-
kind: "record",
|
|
96
|
-
valueType: parseArgument(second, { kind: "any" })
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
case "storage": {
|
|
100
|
-
return first && Node.isStringLiteral(first) ? { bucket: first.getLiteralText(), kind: "storage" } : { kind: "storage" };
|
|
101
|
-
}
|
|
102
|
-
case "union": {
|
|
103
|
-
return {
|
|
104
|
-
kind: "union",
|
|
105
|
-
members: args.filter((argument) => Node.isExpression(argument)).map((argument) => parseValidator(argument))
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
default: {
|
|
109
|
-
throw new Error(`Unsupported validator kind: ${member}`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
const parseValidatorCall = (call) => {
|
|
114
|
-
const callee = call.getExpression();
|
|
115
|
-
if (!Node.isPropertyAccessExpression(callee)) {
|
|
116
|
-
return { kind: "any", sourceText: call.getText() };
|
|
117
|
-
}
|
|
118
|
-
const member = callee.getName();
|
|
119
|
-
const args = call.getArguments();
|
|
120
|
-
if (COLUMN_MODIFIERS.has(member)) {
|
|
121
|
-
const receiver = callee.getExpression();
|
|
122
|
-
const base = Node.isExpression(receiver) ? parseValidator(receiver) : { kind: "any" };
|
|
123
|
-
return applyColumnModifier(base, member);
|
|
124
|
-
}
|
|
125
|
-
if (TRANSPARENT_MODIFIERS.has(member)) {
|
|
126
|
-
const receiver = callee.getExpression();
|
|
127
|
-
const base = Node.isExpression(receiver) ? parseValidator(receiver) : { kind: "any" };
|
|
128
|
-
return member === "check" ? { ...base, hasRefinement: true } : base;
|
|
129
|
-
}
|
|
130
|
-
return parseBuilderMember(member, args);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export { parseObjectShape as a, parseValidator as p };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const INDEX_SUFFIX = /\/index$/u;
|
|
2
|
-
const NON_IDENTIFIER = /[^\dA-Za-z]/gu;
|
|
3
|
-
const sanitizeNamespace = (filePath) => (
|
|
4
|
-
// `lunora/ratelimit/index.ts` surfaces as `api.ratelimit.*` (and dispatches as
|
|
5
|
-
// `ratelimit:fn`) rather than the noisy `api.ratelimit_index.*` — the registry
|
|
6
|
-
// convention. Only a trailing `/index` is dropped, so `lunora/index.ts` and
|
|
7
|
-
// `lunora/ratelimit/queries.ts` (→ `ratelimit_queries`) are unaffected.
|
|
8
|
-
filePath.replace(INDEX_SUFFIX, "").replaceAll(NON_IDENTIFIER, "_")
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
export { sanitizeNamespace as s };
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
const parseLiteral = (text) => {
|
|
2
|
-
try {
|
|
3
|
-
return JSON.parse(text);
|
|
4
|
-
} catch {
|
|
5
|
-
const trimmed = text.trim();
|
|
6
|
-
if (trimmed.length >= 2 && (trimmed.startsWith("'") || trimmed.startsWith('"')) && trimmed.at(-1) === trimmed[0]) {
|
|
7
|
-
return trimmed.slice(1, -1);
|
|
8
|
-
}
|
|
9
|
-
return trimmed;
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
const convertValidator = (ir) => {
|
|
13
|
-
const meta = {};
|
|
14
|
-
if (ir.column !== void 0) {
|
|
15
|
-
meta.column = {
|
|
16
|
-
// A non-undefined `defaultValue` is the sentinel `hasServerDefault`
|
|
17
|
-
// reads to skip the column (the server fills `.default()`/`.$defaultFn()`).
|
|
18
|
-
// eslint-disable-next-line unicorn/no-null -- null is a deliberate non-undefined sentinel here
|
|
19
|
-
defaultValue: ir.column.hasDefault === true ? null : void 0,
|
|
20
|
-
notNull: ir.column.notNull,
|
|
21
|
-
unique: ir.column.unique
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
if (ir.inner !== void 0) {
|
|
25
|
-
meta.inner = convertValidator(ir.inner);
|
|
26
|
-
}
|
|
27
|
-
if (ir.members !== void 0) {
|
|
28
|
-
meta.members = ir.members.map((member) => convertValidator(member));
|
|
29
|
-
}
|
|
30
|
-
if (ir.shape !== void 0) {
|
|
31
|
-
meta.shape = Object.fromEntries(Object.entries(ir.shape).map(([field, child]) => [field, convertValidator(child)]));
|
|
32
|
-
}
|
|
33
|
-
if (ir.tableName !== void 0) {
|
|
34
|
-
meta.tableName = ir.tableName;
|
|
35
|
-
}
|
|
36
|
-
if (ir.literalValue !== void 0) {
|
|
37
|
-
meta.value = parseLiteral(ir.literalValue);
|
|
38
|
-
}
|
|
39
|
-
if (ir.keyType !== void 0) {
|
|
40
|
-
meta.keyValidator = convertValidator(ir.keyType);
|
|
41
|
-
}
|
|
42
|
-
if (ir.valueType !== void 0) {
|
|
43
|
-
meta.valueValidator = convertValidator(ir.valueType);
|
|
44
|
-
}
|
|
45
|
-
return { _meta: meta, kind: ir.kind };
|
|
46
|
-
};
|
|
47
|
-
const schemaFromIr = (ir) => {
|
|
48
|
-
const tables = Object.fromEntries(
|
|
49
|
-
ir.tables.map((table) => [
|
|
50
|
-
table.name,
|
|
51
|
-
{ shape: Object.fromEntries(Object.entries(table.shape).map(([field, validator]) => [field, convertValidator(validator)])) }
|
|
52
|
-
])
|
|
53
|
-
);
|
|
54
|
-
return { tables };
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export { schemaFromIr };
|