bonescript-compiler 0.5.4 → 0.5.6
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/dist/cli.js +94 -4
- package/dist/cli.js.map +1 -1
- package/dist/emit_audit.d.ts +7 -0
- package/dist/emit_audit.js +89 -0
- package/dist/emit_audit.js.map +1 -0
- package/dist/emit_full.js +19 -0
- package/dist/emit_full.js.map +1 -1
- package/dist/emit_nakama.d.ts +23 -0
- package/dist/emit_nakama.js +510 -0
- package/dist/emit_nakama.js.map +1 -0
- package/dist/emit_openapi.d.ts +7 -0
- package/dist/emit_openapi.js +333 -0
- package/dist/emit_openapi.js.map +1 -0
- package/dist/emit_postman.d.ts +6 -0
- package/dist/emit_postman.js +126 -0
- package/dist/emit_postman.js.map +1 -0
- package/dist/emit_sdk.d.ts +7 -0
- package/dist/emit_sdk.js +162 -0
- package/dist/emit_sdk.js.map +1 -0
- package/dist/emit_seed.d.ts +6 -0
- package/dist/emit_seed.js +88 -0
- package/dist/emit_seed.js.map +1 -0
- package/dist/emit_zod.d.ts +7 -0
- package/dist/emit_zod.js +115 -0
- package/dist/emit_zod.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/cli.ts +97 -4
- package/src/emit_audit.ts +112 -0
- package/src/emit_full.ts +25 -0
- package/src/emit_nakama.ts +576 -0
- package/src/emit_openapi.ts +344 -0
- package/src/emit_postman.ts +145 -0
- package/src/emit_sdk.ts +195 -0
- package/src/emit_seed.ts +91 -0
- package/src/emit_zod.ts +111 -0
- package/src/index.ts +10 -0
package/src/emit_seed.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoneScript Seed File Emitter
|
|
3
|
+
* Generates a TypeScript seed script from an IRSystem.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as IR from "./ir";
|
|
7
|
+
|
|
8
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
function toSnakeCase(s: string): string {
|
|
11
|
+
return s.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function seedValue(irType: string, fieldName: string, i: number): string {
|
|
15
|
+
if (irType === "string") return `"sample_${fieldName}_${i + 1}"`;
|
|
16
|
+
if (irType === "uint" || irType === "int") return String(i + 1);
|
|
17
|
+
if (irType === "float") return String((i + 1) * 1.5);
|
|
18
|
+
if (irType === "bool") return i % 2 === 0 ? "true" : "false";
|
|
19
|
+
if (irType === "uuid") return "uuid()";
|
|
20
|
+
if (irType === "timestamp") return "new Date().toISOString()";
|
|
21
|
+
if (irType === "bytes") return `"sample_${fieldName}_${i + 1}"`;
|
|
22
|
+
if (irType === "json") return "JSON.stringify({})";
|
|
23
|
+
const listMatch = irType.match(/^list<(.+)>$/);
|
|
24
|
+
if (listMatch) return "JSON.stringify([])";
|
|
25
|
+
const setMatch = irType.match(/^set<(.+)>$/);
|
|
26
|
+
if (setMatch) return "JSON.stringify([])";
|
|
27
|
+
const optMatch = irType.match(/^optional<(.+)>$/);
|
|
28
|
+
if (optMatch) return "null";
|
|
29
|
+
return `"sample_${fieldName}_${i + 1}"`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
export function emitSeedFile(system: IR.IRSystem): string {
|
|
35
|
+
const lines: string[] = [];
|
|
36
|
+
|
|
37
|
+
lines.push(`// Generated by BoneScript compiler.`);
|
|
38
|
+
lines.push(`// Seed script for: ${system.name} v${system.version}`);
|
|
39
|
+
lines.push(`// Run: npx ts-node src/seed.ts`);
|
|
40
|
+
lines.push("");
|
|
41
|
+
lines.push(`import { query, pool } from "./db";`);
|
|
42
|
+
lines.push(`import { v4 as uuid } from "uuid";`);
|
|
43
|
+
lines.push("");
|
|
44
|
+
|
|
45
|
+
const seedModels: { mod: IR.IRModule; model: IR.IRModel }[] = [];
|
|
46
|
+
for (const mod of system.modules) {
|
|
47
|
+
if (mod.kind === "api_service" || mod.kind === "data_store") {
|
|
48
|
+
for (const model of mod.models) {
|
|
49
|
+
seedModels.push({ mod, model });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
lines.push(`async function main(): Promise<void> {`);
|
|
55
|
+
lines.push(` console.log("Seeding ${system.name}...");`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
|
|
58
|
+
for (const { model } of seedModels) {
|
|
59
|
+
const tableName = toSnakeCase(model.name) + "s";
|
|
60
|
+
lines.push(` // Seed ${model.name}`);
|
|
61
|
+
lines.push(` console.log(" Seeding ${tableName}...");`);
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < 3; i++) {
|
|
64
|
+
const fieldNames = model.fields.map((f) => f.name);
|
|
65
|
+
const fieldValues = model.fields.map((f) =>
|
|
66
|
+
seedValue(f.type, f.name, i)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
lines.push(` await query(`);
|
|
70
|
+
lines.push(
|
|
71
|
+
` \`INSERT INTO ${tableName} (${fieldNames.join(", ")}) VALUES (${fieldNames.map((_, idx) => `$${idx + 1}`).join(", ")}) ON CONFLICT DO NOTHING\`,`
|
|
72
|
+
);
|
|
73
|
+
lines.push(` [${fieldValues.join(", ")}]`);
|
|
74
|
+
lines.push(` );`);
|
|
75
|
+
}
|
|
76
|
+
lines.push("");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
lines.push(` console.log("Seed complete.");`);
|
|
80
|
+
lines.push(`}`);
|
|
81
|
+
lines.push("");
|
|
82
|
+
lines.push(`main()`);
|
|
83
|
+
lines.push(` .catch((err) => {`);
|
|
84
|
+
lines.push(` console.error("Seed failed:", err);`);
|
|
85
|
+
lines.push(` process.exit(1);`);
|
|
86
|
+
lines.push(` })`);
|
|
87
|
+
lines.push(` .finally(() => pool.end());`);
|
|
88
|
+
lines.push("");
|
|
89
|
+
|
|
90
|
+
return lines.join("\n");
|
|
91
|
+
}
|
package/src/emit_zod.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BoneScript Zod Schema Emitter
|
|
3
|
+
* Generates Zod v3 validation schemas from an IRSystem.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as IR from "./ir";
|
|
7
|
+
|
|
8
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
function toPascalCase(s: string): string {
|
|
11
|
+
return s
|
|
12
|
+
.replace(/_([a-z])/g, (_: string, c: string) => c.toUpperCase())
|
|
13
|
+
.replace(/^([a-z])/, (_: string, c: string) => c.toUpperCase());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function irTypeToZod(irType: string): string {
|
|
17
|
+
if (irType === "string") return "z.string()";
|
|
18
|
+
if (irType === "uint") return "z.number().int().nonnegative()";
|
|
19
|
+
if (irType === "int") return "z.number().int()";
|
|
20
|
+
if (irType === "float") return "z.number()";
|
|
21
|
+
if (irType === "bool") return "z.boolean()";
|
|
22
|
+
if (irType === "timestamp") return "z.string().datetime()";
|
|
23
|
+
if (irType === "uuid") return "z.string().uuid()";
|
|
24
|
+
if (irType === "bytes") return "z.string()";
|
|
25
|
+
if (irType === "json") return "z.unknown()";
|
|
26
|
+
const listMatch = irType.match(/^list<(.+)>$/);
|
|
27
|
+
if (listMatch) return `z.array(${irTypeToZod(listMatch[1])})`;
|
|
28
|
+
const setMatch = irType.match(/^set<(.+)>$/);
|
|
29
|
+
if (setMatch) return `z.array(${irTypeToZod(setMatch[1])})`;
|
|
30
|
+
const optMatch = irType.match(/^optional<(.+)>$/);
|
|
31
|
+
if (optMatch) return `${irTypeToZod(optMatch[1])}.nullable()`;
|
|
32
|
+
return "z.unknown()";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function applyConstraints(
|
|
36
|
+
baseZod: string,
|
|
37
|
+
fieldName: string,
|
|
38
|
+
constraints: IR.IRModelConstraint[]
|
|
39
|
+
): string {
|
|
40
|
+
let result = baseZod;
|
|
41
|
+
for (const c of constraints) {
|
|
42
|
+
if (c.target !== fieldName) continue;
|
|
43
|
+
if (c.kind === "range") {
|
|
44
|
+
if (c.params.min !== undefined) result += `.min(${c.params.min})`;
|
|
45
|
+
if (c.params.max !== undefined) result += `.max(${c.params.max})`;
|
|
46
|
+
} else if (c.kind === "enum") {
|
|
47
|
+
const vals = c.params.values as string[];
|
|
48
|
+
if (vals && vals.length > 0) {
|
|
49
|
+
result = `z.enum([${vals.map((v) => JSON.stringify(v)).join(", ")}])`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export function emitZodSchemas(system: IR.IRSystem): string {
|
|
59
|
+
const lines: string[] = [];
|
|
60
|
+
|
|
61
|
+
lines.push(`// Generated by BoneScript compiler.`);
|
|
62
|
+
lines.push(`import { z } from "zod";`);
|
|
63
|
+
lines.push("");
|
|
64
|
+
|
|
65
|
+
// Model schemas
|
|
66
|
+
for (const mod of system.modules) {
|
|
67
|
+
for (const model of mod.models) {
|
|
68
|
+
const schemaName = toPascalCase(model.name) + "Schema";
|
|
69
|
+
const typeName = toPascalCase(model.name);
|
|
70
|
+
|
|
71
|
+
lines.push(`export const ${schemaName} = z.object({`);
|
|
72
|
+
for (const field of model.fields) {
|
|
73
|
+
let zodType = irTypeToZod(field.type);
|
|
74
|
+
zodType = applyConstraints(zodType, field.name, model.constraints);
|
|
75
|
+
if (field.nullable) {
|
|
76
|
+
zodType = zodType + ".nullable()";
|
|
77
|
+
}
|
|
78
|
+
lines.push(` ${field.name}: ${zodType},`);
|
|
79
|
+
}
|
|
80
|
+
lines.push(`});`);
|
|
81
|
+
lines.push(`export type ${typeName} = z.infer<typeof ${schemaName}>;`);
|
|
82
|
+
lines.push("");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Capability input schemas
|
|
87
|
+
for (const mod of system.modules) {
|
|
88
|
+
for (const iface of mod.interfaces) {
|
|
89
|
+
for (const method of iface.methods) {
|
|
90
|
+
if (method.input.length === 0) continue;
|
|
91
|
+
const modPascal = toPascalCase(mod.name);
|
|
92
|
+
const methodPascal = toPascalCase(method.name);
|
|
93
|
+
const schemaName = `${modPascal}${methodPascal}InputSchema`;
|
|
94
|
+
|
|
95
|
+
lines.push(`export const ${schemaName} = z.object({`);
|
|
96
|
+
for (const field of method.input) {
|
|
97
|
+
const zodType = irTypeToZod(field.type);
|
|
98
|
+
lines.push(` ${field.name}: ${zodType},`);
|
|
99
|
+
}
|
|
100
|
+
lines.push(`});`);
|
|
101
|
+
lines.push("");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return lines.join("\n");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function emitZodPackageAdditions(): string {
|
|
110
|
+
return JSON.stringify({ zod: "3.22.4" }, null, 2);
|
|
111
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,8 @@ export { Lowering } from "./lowering";
|
|
|
15
15
|
export { ConstraintSolver } from "./solver";
|
|
16
16
|
export type { SolverResult } from "./solver";
|
|
17
17
|
export { FullEmitter } from "./emit_full";
|
|
18
|
+
export { NakamaEmitter } from "./emit_nakama";
|
|
19
|
+
export type { NakamaEmittedFile } from "./emit_nakama";
|
|
18
20
|
export type { EmittedFile } from "./emitter";
|
|
19
21
|
export { Verifier } from "./verifier";
|
|
20
22
|
export type { VerifyResult, VerifyIssue } from "./verifier";
|
|
@@ -38,6 +40,14 @@ export { lookupAlgorithm, listAlgorithms, listByCategory } from "./algorithm_cat
|
|
|
38
40
|
// Extension system
|
|
39
41
|
export { mergeWithExisting, extractImplementations, validateExtensions } from "./extension_manager";
|
|
40
42
|
|
|
43
|
+
// New emitters
|
|
44
|
+
export { emitOpenApiSpec, emitOpenApiJson } from "./emit_openapi";
|
|
45
|
+
export { emitTypescriptSdk, emitSdkPackageJson } from "./emit_sdk";
|
|
46
|
+
export { emitZodSchemas } from "./emit_zod";
|
|
47
|
+
export { emitPostmanCollection } from "./emit_postman";
|
|
48
|
+
export { emitSeedFile } from "./emit_seed";
|
|
49
|
+
export { emitAuditSchema, emitAuditMiddleware } from "./emit_audit";
|
|
50
|
+
|
|
41
51
|
/**
|
|
42
52
|
* Convenience function: compile a .bone source string to files.
|
|
43
53
|
*/
|