@drzl/cli 4.14.4 → 4.16.0
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/{chunk-HGD5CBM5.js → chunk-K4J4XIFO.js} +60 -7
- package/dist/chunk-K4J4XIFO.js.map +1 -0
- package/dist/cli.cjs +778 -86
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +161 -33
- package/dist/cli.js.map +1 -1
- package/dist/config.cjs +62 -8
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +41 -3
- package/dist/config.d.ts +41 -3
- package/dist/config.js +5 -3
- package/dist/dist-XBGVORL3.js +512 -0
- package/dist/dist-XBGVORL3.js.map +1 -0
- package/package.json +10 -9
- package/dist/chunk-HGD5CBM5.js.map +0 -1
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
// ../generator-trpc/dist/index.js
|
|
2
|
+
import {
|
|
3
|
+
formatCode,
|
|
4
|
+
importSpecifier,
|
|
5
|
+
resolveAffix,
|
|
6
|
+
resolveConfiguredImport,
|
|
7
|
+
schemaName
|
|
8
|
+
} from "@drzl/validation-core";
|
|
9
|
+
var TRPC_MAJOR = 11;
|
|
10
|
+
var q = (v) => JSON.stringify(v);
|
|
11
|
+
var LIB_IMPORTS = {
|
|
12
|
+
zod: "import { z } from 'zod';",
|
|
13
|
+
valibot: "import * as v from 'valibot';",
|
|
14
|
+
arktype: "import { type } from 'arktype';"
|
|
15
|
+
};
|
|
16
|
+
var LIB_USAGE = {
|
|
17
|
+
zod: /\bz\./,
|
|
18
|
+
valibot: /\bv\./,
|
|
19
|
+
arktype: /\btype\(/
|
|
20
|
+
};
|
|
21
|
+
var LIBS = {
|
|
22
|
+
zod: {
|
|
23
|
+
number: "z.number()",
|
|
24
|
+
string: "z.string()",
|
|
25
|
+
boolean: "z.boolean()",
|
|
26
|
+
date: "z.date()",
|
|
27
|
+
unknown: "z.unknown()",
|
|
28
|
+
tuple: (n) => `z.tuple([${Array.from({ length: n }, () => "z.number()").join(", ")}])`,
|
|
29
|
+
numberObject: (fields) => `z.object({ ${fields.map((f) => `${f}: z.number()`).join(", ")} })`,
|
|
30
|
+
enum: (vals) => `z.enum([${vals.map(q).join(", ")}] as const)`,
|
|
31
|
+
nullable: (b) => `${b}.nullable()`,
|
|
32
|
+
optional: (b) => `${b}.optional()`,
|
|
33
|
+
object: (body) => `z.object({
|
|
34
|
+
${body}
|
|
35
|
+
})`,
|
|
36
|
+
objectInline: (body) => `z.object({ ${body} })`,
|
|
37
|
+
partialUpdate: (s) => `${s}.partial()`,
|
|
38
|
+
arrayOf: (s) => `z.array(${s})`,
|
|
39
|
+
nullableOf: (s) => `${s}.nullable()`,
|
|
40
|
+
booleanSchema: "z.boolean()"
|
|
41
|
+
},
|
|
42
|
+
valibot: {
|
|
43
|
+
number: "v.number()",
|
|
44
|
+
string: "v.string()",
|
|
45
|
+
boolean: "v.boolean()",
|
|
46
|
+
date: "v.date()",
|
|
47
|
+
unknown: "v.unknown()",
|
|
48
|
+
tuple: (n) => `v.tuple([${Array.from({ length: n }, () => "v.number()").join(", ")}])`,
|
|
49
|
+
numberObject: (fields) => `v.object({ ${fields.map((f) => `${f}: v.number()`).join(", ")} })`,
|
|
50
|
+
enum: (vals) => `v.picklist([${vals.map(q).join(", ")}] as const)`,
|
|
51
|
+
nullable: (b) => `v.nullable(${b})`,
|
|
52
|
+
optional: (b) => `v.optional(${b})`,
|
|
53
|
+
object: (body) => `v.object({
|
|
54
|
+
${body}
|
|
55
|
+
})`,
|
|
56
|
+
objectInline: (body) => `v.object({ ${body} })`,
|
|
57
|
+
arrayOf: (s) => `v.array(${s})`,
|
|
58
|
+
nullableOf: (s) => `v.nullable(${s})`,
|
|
59
|
+
booleanSchema: "v.boolean()"
|
|
60
|
+
},
|
|
61
|
+
arktype: {
|
|
62
|
+
number: "number",
|
|
63
|
+
string: "string",
|
|
64
|
+
boolean: "boolean",
|
|
65
|
+
date: "Date",
|
|
66
|
+
unknown: "unknown",
|
|
67
|
+
// The surrounding encode adds the quotes, so the union is built with the inner quoting
|
|
68
|
+
// ArkType expects. Emitting `'${...}'` here produces `''admin' | 'user''`, which does not parse.
|
|
69
|
+
enum: (vals) => vals.map((x) => `'${x.replace(/'/g, "\\'")}'`).join(" | "),
|
|
70
|
+
nullable: (b) => `(${b} | null)`,
|
|
71
|
+
optional: (b) => `${b}?`,
|
|
72
|
+
object: (body) => `type({
|
|
73
|
+
${body}
|
|
74
|
+
})`,
|
|
75
|
+
objectInline: (body) => `type({ ${body} })`,
|
|
76
|
+
fieldIsString: true,
|
|
77
|
+
arrayOf: (s) => `${s}.array()`,
|
|
78
|
+
nullableOf: (s) => `${s}.or('null')`,
|
|
79
|
+
booleanSchema: `type('boolean')`
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function isWide(column) {
|
|
83
|
+
if (column.enumValues && column.enumValues.length) return false;
|
|
84
|
+
if (column.shape?.kind === "tuple" || column.shape?.kind === "numberObject") return false;
|
|
85
|
+
return !["number", "string", "boolean", "Date"].includes(column.tsType);
|
|
86
|
+
}
|
|
87
|
+
function mapExpr(column, lib, mode) {
|
|
88
|
+
const d = LIBS[lib];
|
|
89
|
+
let base = (() => {
|
|
90
|
+
if (column.enumValues && column.enumValues.length) return d.enum(column.enumValues);
|
|
91
|
+
if (column.shape?.kind === "tuple" && d.tuple) return d.tuple(column.shape.length);
|
|
92
|
+
if (column.shape?.kind === "numberObject" && d.numberObject) {
|
|
93
|
+
return d.numberObject(column.shape.fields);
|
|
94
|
+
}
|
|
95
|
+
switch (column.tsType) {
|
|
96
|
+
case "number":
|
|
97
|
+
return d.number;
|
|
98
|
+
case "string":
|
|
99
|
+
return d.string;
|
|
100
|
+
case "boolean":
|
|
101
|
+
return d.boolean;
|
|
102
|
+
case "Date":
|
|
103
|
+
return d.date;
|
|
104
|
+
default:
|
|
105
|
+
return d.unknown;
|
|
106
|
+
}
|
|
107
|
+
})();
|
|
108
|
+
if (column.nullable) base = d.nullable(base);
|
|
109
|
+
if (mode !== "select") {
|
|
110
|
+
const optional = mode === "update" || column.nullable || column.hasDefault;
|
|
111
|
+
if (optional) base = d.optional(base);
|
|
112
|
+
}
|
|
113
|
+
return base;
|
|
114
|
+
}
|
|
115
|
+
function field(column, lib, mode) {
|
|
116
|
+
const d = LIBS[lib];
|
|
117
|
+
const expr = mapExpr(column, lib, mode);
|
|
118
|
+
return `${objectKey(column.name)}: ${d.fieldIsString ? JSON.stringify(expr) : expr}`;
|
|
119
|
+
}
|
|
120
|
+
function objectKey(name) {
|
|
121
|
+
return isIdent(name) ? name : JSON.stringify(name);
|
|
122
|
+
}
|
|
123
|
+
function renderSchema(table, lib, mode) {
|
|
124
|
+
const d = LIBS[lib];
|
|
125
|
+
const cols = table.columns.filter((c) => mode === "select" ? true : !c.isGenerated);
|
|
126
|
+
const body = cols.map((c) => ` ${field(c, lib, mode)},`).join("\n");
|
|
127
|
+
const schema = d.object(body);
|
|
128
|
+
return mode === "update" && d.partialUpdate ? d.partialUpdate(schema) : schema;
|
|
129
|
+
}
|
|
130
|
+
function toCase(s, c) {
|
|
131
|
+
if (!c) return s;
|
|
132
|
+
const parts = s.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").split(/\s+/);
|
|
133
|
+
if (c === "camel") {
|
|
134
|
+
return parts.map(
|
|
135
|
+
(p, i) => i === 0 ? p.toLowerCase() : p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()
|
|
136
|
+
).join("");
|
|
137
|
+
}
|
|
138
|
+
if (c === "kebab") return parts.map((p) => p.toLowerCase()).join("-");
|
|
139
|
+
if (c === "snake") return parts.map((p) => p.toLowerCase()).join("_");
|
|
140
|
+
return s;
|
|
141
|
+
}
|
|
142
|
+
var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
143
|
+
var singularize = (s) => s.endsWith("ies") ? s.slice(0, -3) + "y" : s.endsWith("s") ? s.slice(0, -1) : s;
|
|
144
|
+
var isIdent = (s) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s);
|
|
145
|
+
var BASE_MODULE = "trpc";
|
|
146
|
+
function keyColumns(table) {
|
|
147
|
+
const names = table.primaryKey?.columns ?? [];
|
|
148
|
+
if (!names.length) return null;
|
|
149
|
+
const cols = names.map((n) => table.columns.find((c) => c.name === n));
|
|
150
|
+
if (cols.some((c) => !c)) return null;
|
|
151
|
+
return cols;
|
|
152
|
+
}
|
|
153
|
+
var TRPCGenerator = class {
|
|
154
|
+
constructor(analysis) {
|
|
155
|
+
this.analysis = analysis;
|
|
156
|
+
}
|
|
157
|
+
async generate(opts) {
|
|
158
|
+
const fs = await import("fs/promises");
|
|
159
|
+
const path = await import("path");
|
|
160
|
+
const out = path.resolve(process.cwd(), opts.outputDir);
|
|
161
|
+
const ctx = {
|
|
162
|
+
out,
|
|
163
|
+
services: path.resolve(process.cwd(), opts.servicesDir ?? "src/services")
|
|
164
|
+
};
|
|
165
|
+
await fs.mkdir(out, { recursive: true });
|
|
166
|
+
const files = [];
|
|
167
|
+
const write = async (filePath, content) => {
|
|
168
|
+
const formatted = await formatCode(
|
|
169
|
+
buildHeader(opts.outputHeader) + content,
|
|
170
|
+
filePath,
|
|
171
|
+
opts.format
|
|
172
|
+
);
|
|
173
|
+
await fs.writeFile(filePath, formatted, "utf8");
|
|
174
|
+
files.push(filePath);
|
|
175
|
+
};
|
|
176
|
+
const basePath = path.join(out, `${BASE_MODULE}.ts`);
|
|
177
|
+
await write(basePath, renderBase(opts));
|
|
178
|
+
const routers = [];
|
|
179
|
+
const total = this.analysis.tables.length;
|
|
180
|
+
let index = 0;
|
|
181
|
+
for (const table of this.analysis.tables) {
|
|
182
|
+
const base = `${table.tsName}${opts.naming?.routerSuffix ?? ""}`;
|
|
183
|
+
const filePath = path.join(out, `${toCase(base, opts.naming?.procedureCase)}.ts`);
|
|
184
|
+
if (filePath === basePath) {
|
|
185
|
+
throw new Error(
|
|
186
|
+
`@drzl/generator-trpc: the router for table "${table.name}" would be written to ${filePath}, which is the shared tRPC base module this generator also writes. Set naming.routerSuffix to move it out of the way.`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
await write(filePath, renderRouter(table, opts, ctx));
|
|
190
|
+
routers.push({ table, filePath, exportName: routerExportName(table, opts.naming) });
|
|
191
|
+
index++;
|
|
192
|
+
opts.onProgress?.({ index, total, table: table.name, filePath });
|
|
193
|
+
}
|
|
194
|
+
await write(path.join(out, "index.ts"), renderBarrel(routers, ctx, path, opts));
|
|
195
|
+
return { files };
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var index_default = TRPCGenerator;
|
|
199
|
+
function renderBase(opts) {
|
|
200
|
+
const injection = opts.databaseInjection?.enabled === true;
|
|
201
|
+
const dbType = opts.databaseInjection?.databaseType ?? "unknown";
|
|
202
|
+
const typeImport = opts.databaseInjection?.databaseTypeImport ? `import type { ${opts.databaseInjection.databaseTypeImport.name} } from '${opts.databaseInjection.databaseTypeImport.from}';
|
|
203
|
+
` : "";
|
|
204
|
+
const trpcImport = injection ? `import { initTRPC, TRPCError } from '@trpc/server';` : `import { initTRPC } from '@trpc/server';`;
|
|
205
|
+
const context = injection ? `/**
|
|
206
|
+
* What your \`createContext\` hands every procedure.
|
|
207
|
+
*
|
|
208
|
+
* \`db\` is optional here and required by \`dbProcedure\` below. That split is what lets an adapter
|
|
209
|
+
* build a context without a handle, for a health check or a public route, while every generated
|
|
210
|
+
* procedure still sees one that is present.
|
|
211
|
+
*/
|
|
212
|
+
export interface Context {
|
|
213
|
+
db?: ${dbType};
|
|
214
|
+
}` : `/**
|
|
215
|
+
* What your \`createContext\` hands every procedure. Nothing generated reads it, so it is left
|
|
216
|
+
* open; narrow it to the shape your own context really has.
|
|
217
|
+
*/
|
|
218
|
+
export type Context = Record<string, unknown>;`;
|
|
219
|
+
const middleware = injection ? `
|
|
220
|
+
/**
|
|
221
|
+
* The builder every generated procedure is built from: it refuses to run without a database
|
|
222
|
+
* handle, and narrows \`ctx.db\` from optional to present for everything downstream.
|
|
223
|
+
*/
|
|
224
|
+
export const dbProcedure = t.procedure.use(async ({ ctx, next }) => {
|
|
225
|
+
if (!ctx.db) {
|
|
226
|
+
throw new TRPCError({
|
|
227
|
+
code: 'INTERNAL_SERVER_ERROR',
|
|
228
|
+
message: 'No database handle on the tRPC context. Provide one from createContext.',
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return next({ ctx: { db: ctx.db } });
|
|
232
|
+
});
|
|
233
|
+
` : "";
|
|
234
|
+
return `// Generated by @drzl/generator-trpc
|
|
235
|
+
// The shared tRPC base. Every generated router imports from here.
|
|
236
|
+
${trpcImport}
|
|
237
|
+
${typeImport}
|
|
238
|
+
${context}
|
|
239
|
+
|
|
240
|
+
const t = initTRPC.context<Context>().create();
|
|
241
|
+
|
|
242
|
+
export const router = t.router;
|
|
243
|
+
export const mergeRouters = t.mergeRouters;
|
|
244
|
+
export const middleware = t.middleware;
|
|
245
|
+
/** Needed to call this router in-process, from a test or from SSR. */
|
|
246
|
+
export const createCallerFactory = t.createCallerFactory;
|
|
247
|
+
export const publicProcedure = t.procedure;
|
|
248
|
+
${middleware}`;
|
|
249
|
+
}
|
|
250
|
+
function renderRouter(table, opts, ctx) {
|
|
251
|
+
const lib = opts.validation?.library ?? "zod";
|
|
252
|
+
const d = LIBS[lib];
|
|
253
|
+
const service = opts.template === "service";
|
|
254
|
+
const injection = opts.databaseInjection?.enabled === true;
|
|
255
|
+
const builder = injection ? "dbProcedure" : "publicProcedure";
|
|
256
|
+
const insertName = `Insert${table.tsName}Schema`;
|
|
257
|
+
const updateName = `Update${table.tsName}Schema`;
|
|
258
|
+
const selectName = `Select${table.tsName}Schema`;
|
|
259
|
+
const writable = !table.readOnly;
|
|
260
|
+
const key = keyColumns(table);
|
|
261
|
+
const Service = `${cap(singularize(table.tsName))}Service`;
|
|
262
|
+
const serviceKeyable = !!key && key.length === 1 && key[0].tsType === "number";
|
|
263
|
+
const keyArg = key && key.length === 1 ? `input.${key[0].name}` : "";
|
|
264
|
+
const dbArg = injection ? "ctx.db, " : "";
|
|
265
|
+
const wiredParams = injection ? "{ ctx, input }" : "{ input }";
|
|
266
|
+
const procedures = [];
|
|
267
|
+
const notImplemented = (what) => `throw new Error('Not implemented: ${what} ${table.tsName}.');`;
|
|
268
|
+
procedures.push({
|
|
269
|
+
name: "list",
|
|
270
|
+
kind: "query",
|
|
271
|
+
output: d.arrayOf(selectName),
|
|
272
|
+
params: service && injection ? "{ ctx }" : "",
|
|
273
|
+
body: service ? [`return await ${Service}.getAll(${injection ? "ctx.db" : ""});`] : ["return [];"]
|
|
274
|
+
});
|
|
275
|
+
const keyInput = key ? d.objectInline(key.map((c) => field(c, lib, "select")).join(", ")) : void 0;
|
|
276
|
+
if (key && keyInput) {
|
|
277
|
+
const wired = service && serviceKeyable;
|
|
278
|
+
procedures.push({
|
|
279
|
+
name: "byId",
|
|
280
|
+
kind: "query",
|
|
281
|
+
input: keyInput,
|
|
282
|
+
output: d.nullableOf(selectName),
|
|
283
|
+
params: wired ? wiredParams : "{ input: _input }",
|
|
284
|
+
body: wired ? [`return await ${Service}.getById(${dbArg}${keyArg});`] : service ? [serviceKeyNote(table), notImplemented("byId")] : ["return null;"]
|
|
285
|
+
});
|
|
286
|
+
if (writable) {
|
|
287
|
+
const updateInput = d.objectInline(
|
|
288
|
+
[...key.map((c) => field(c, lib, "select")), `data: ${updateName}`].join(", ")
|
|
289
|
+
);
|
|
290
|
+
procedures.push({
|
|
291
|
+
name: "update",
|
|
292
|
+
kind: "mutation",
|
|
293
|
+
input: updateInput,
|
|
294
|
+
output: selectName,
|
|
295
|
+
params: wired ? wiredParams : "{ input: _input }",
|
|
296
|
+
body: wired ? [`return await ${Service}.update(${dbArg}${keyArg}, input.data);`] : service ? [serviceKeyNote(table), notImplemented("update")] : [notImplemented("update")]
|
|
297
|
+
});
|
|
298
|
+
procedures.push({
|
|
299
|
+
name: "delete",
|
|
300
|
+
kind: "mutation",
|
|
301
|
+
input: keyInput,
|
|
302
|
+
output: d.booleanSchema,
|
|
303
|
+
params: wired ? wiredParams : "{ input: _input }",
|
|
304
|
+
body: wired ? [`return await ${Service}.delete(${dbArg}${keyArg});`] : service ? [serviceKeyNote(table), notImplemented("delete")] : ["return true;"]
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (writable) {
|
|
309
|
+
procedures.push({
|
|
310
|
+
name: "create",
|
|
311
|
+
kind: "mutation",
|
|
312
|
+
input: insertName,
|
|
313
|
+
output: selectName,
|
|
314
|
+
params: service ? wiredParams : "{ input: _input }",
|
|
315
|
+
body: service ? [`return await ${Service}.create(${dbArg}input);`] : [notImplemented("create")]
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
if (opts.includeRelations) {
|
|
319
|
+
const taken = new Set(procedures.map((p) => p.name));
|
|
320
|
+
procedures.push(...relationProcedures(table, lib, selectName, taken, service));
|
|
321
|
+
}
|
|
322
|
+
const order = ["list", "byId", "create", "update", "delete"];
|
|
323
|
+
const rank = (n) => order.indexOf(n) === -1 ? order.length : order.indexOf(n);
|
|
324
|
+
procedures.sort((a, b) => rank(a.name) - rank(b.name));
|
|
325
|
+
const routerName = routerExportName(table, opts.naming);
|
|
326
|
+
const entries = procedures.map((p) => {
|
|
327
|
+
const rawKey = toCase(p.name, opts.naming?.procedureCase);
|
|
328
|
+
const propKey = isIdent(rawKey) ? rawKey : JSON.stringify(rawKey);
|
|
329
|
+
return [
|
|
330
|
+
` ${propKey}: ${builder}`,
|
|
331
|
+
...p.input ? [` .input(${p.input})`] : [],
|
|
332
|
+
` .output(${p.output})`,
|
|
333
|
+
` .${p.kind}(async (${p.params}) => {`,
|
|
334
|
+
...p.body.map((line) => ` ${line}`),
|
|
335
|
+
` }),`
|
|
336
|
+
].join("\n");
|
|
337
|
+
}).join("\n");
|
|
338
|
+
const body = `export const ${routerName} = router({
|
|
339
|
+
${entries}
|
|
340
|
+
});
|
|
341
|
+
`;
|
|
342
|
+
const useShared = !!opts.validation?.useShared && !!opts.validation?.importPath;
|
|
343
|
+
const declared = [];
|
|
344
|
+
if (!useShared) {
|
|
345
|
+
if (writable) {
|
|
346
|
+
declared.push(`export const ${insertName} = ${renderSchema(table, lib, "insert")};`);
|
|
347
|
+
declared.push(`export const ${updateName} = ${renderSchema(table, lib, "update")};`);
|
|
348
|
+
}
|
|
349
|
+
declared.push(`export const ${selectName} = ${renderSchema(table, lib, "select")};`);
|
|
350
|
+
}
|
|
351
|
+
const decided = [...declared, body].join("\n\n");
|
|
352
|
+
const imports = [];
|
|
353
|
+
if (useShared) {
|
|
354
|
+
const sharedAffix = resolveAffix({
|
|
355
|
+
affix: opts.validation?.affix,
|
|
356
|
+
schemaSuffix: opts.validation?.schemaSuffix
|
|
357
|
+
});
|
|
358
|
+
const wanted = [
|
|
359
|
+
["insert", insertName],
|
|
360
|
+
["update", updateName],
|
|
361
|
+
["select", selectName]
|
|
362
|
+
].filter(([, local]) => decided.includes(local));
|
|
363
|
+
if (wanted.length) {
|
|
364
|
+
const spec = resolveConfiguredImport(
|
|
365
|
+
opts.validation.importPath,
|
|
366
|
+
ctx.out,
|
|
367
|
+
process.cwd(),
|
|
368
|
+
opts.importExtension
|
|
369
|
+
);
|
|
370
|
+
const names = wanted.map(([mode, local]) => {
|
|
371
|
+
const exported = schemaName(mode, table.tsName, sharedAffix);
|
|
372
|
+
return exported === local ? local : `${exported} as ${local}`;
|
|
373
|
+
}).join(", ");
|
|
374
|
+
imports.push(`import { ${names} } from '${spec}';`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
imports.push(
|
|
378
|
+
`import { ${[builder, "router"].sort().join(", ")} } from '${importSpecifier(
|
|
379
|
+
`./${BASE_MODULE}.ts`,
|
|
380
|
+
opts.importExtension
|
|
381
|
+
)}';`
|
|
382
|
+
);
|
|
383
|
+
if (service) {
|
|
384
|
+
imports.push(`import { ${Service} } from '${serviceImportSpecifier(table, ctx, opts)}';`);
|
|
385
|
+
}
|
|
386
|
+
if (LIB_USAGE[lib].test(decided)) imports.unshift(LIB_IMPORTS[lib]);
|
|
387
|
+
const wide = table.columns.filter(isWide).map((c) => c.name);
|
|
388
|
+
const wideNote = wide.length ? `// No validated type for ${wide.length === 1 ? "this column" : "these columns"}: ${wide.join(", ")}.
|
|
389
|
+
// DRZL could not derive one from the schema, so the router accepts any value there.
|
|
390
|
+
` : "";
|
|
391
|
+
return `// Generated by @drzl/generator-trpc
|
|
392
|
+
// Router for table: ${table.name}
|
|
393
|
+
${wideNote}${imports.join("\n")}
|
|
394
|
+
|
|
395
|
+
${decided}`;
|
|
396
|
+
}
|
|
397
|
+
function relationProcedures(table, lib, selectSchemaName, taken, service) {
|
|
398
|
+
const d = LIBS[lib];
|
|
399
|
+
const out = [];
|
|
400
|
+
for (const fk of table.foreignKeys ?? []) {
|
|
401
|
+
if (fk.columns.length !== 1) continue;
|
|
402
|
+
const colName = fk.columns[0];
|
|
403
|
+
const column = table.columns.find((c) => c.name === colName);
|
|
404
|
+
if (!column) continue;
|
|
405
|
+
const name = `listBy${cap(colName)}`;
|
|
406
|
+
if (taken.has(name)) continue;
|
|
407
|
+
taken.add(name);
|
|
408
|
+
out.push({
|
|
409
|
+
name,
|
|
410
|
+
kind: "query",
|
|
411
|
+
input: d.objectInline(field(column, lib, "select")),
|
|
412
|
+
output: d.arrayOf(selectSchemaName),
|
|
413
|
+
params: "{ input: _input }",
|
|
414
|
+
body: [
|
|
415
|
+
`// Rows of ${table.name} whose ${JSON.stringify(colName)} matches _input.${colName}.`,
|
|
416
|
+
// In `service` mode every other procedure really does reach the database, so a lookup
|
|
417
|
+
// quietly answering with an empty array would read as "no matching rows". There is no
|
|
418
|
+
// generated service method for it, so it says so instead. In `standard` mode everything
|
|
419
|
+
// is a stub and `[]` is consistent with `list`.
|
|
420
|
+
service ? `throw new Error('Not implemented: ${name} ${table.tsName}.');` : "return [];"
|
|
421
|
+
]
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return out;
|
|
425
|
+
}
|
|
426
|
+
function renderBarrel(routers, ctx, path, opts) {
|
|
427
|
+
const baseSpec = importSpecifier(`./${BASE_MODULE}.ts`, opts.importExtension);
|
|
428
|
+
const reExports = `export { createCallerFactory, publicProcedure, router } from '${baseSpec}';
|
|
429
|
+
` + (opts.databaseInjection?.enabled === true ? `export { dbProcedure } from '${baseSpec}';
|
|
430
|
+
` : "") + `export type { Context } from '${baseSpec}';
|
|
431
|
+
`;
|
|
432
|
+
if (!routers.length) {
|
|
433
|
+
return `// Generated by @drzl/generator-trpc
|
|
434
|
+
// No tables detected in analysis. Add tables to your schema and regenerate.
|
|
435
|
+
import { router } from '${baseSpec}';
|
|
436
|
+
|
|
437
|
+
export const appRouter = router({});
|
|
438
|
+
|
|
439
|
+
/** The type a tRPC client is parameterised by: \`createTRPCClient<AppRouter>()\`. */
|
|
440
|
+
export type AppRouter = typeof appRouter;
|
|
441
|
+
|
|
442
|
+
${reExports}`;
|
|
443
|
+
}
|
|
444
|
+
const entries = routers.map(({ filePath, exportName, table }) => ({
|
|
445
|
+
rel: importSpecifier(
|
|
446
|
+
"./" + path.relative(ctx.out, filePath).replace(/\\/g, "/"),
|
|
447
|
+
opts.importExtension
|
|
448
|
+
),
|
|
449
|
+
exportName,
|
|
450
|
+
// The namespace a client reaches this table's procedures through: `trpc.userProfiles.list`.
|
|
451
|
+
// `tsName` verbatim, because it is already a valid identifier and it is the name the user
|
|
452
|
+
// wrote in their schema. The oRPC barrel lowercases this key, turning `userProfiles` into
|
|
453
|
+
// `userprofiles`: harmless in an object literal nobody reads, and not harmless when the key
|
|
454
|
+
// is the public API of a typed client.
|
|
455
|
+
key: table.tsName
|
|
456
|
+
}));
|
|
457
|
+
const importLines = entries.map(({ rel, exportName }) => `import { ${exportName} } from '${rel}';`).join("\n");
|
|
458
|
+
const bodyLines = entries.map(({ key, exportName }) => ` ${isIdent(key) ? key : JSON.stringify(key)}: ${exportName},`).join("\n");
|
|
459
|
+
return `// Generated by @drzl/generator-trpc
|
|
460
|
+
import { router } from '${baseSpec}';
|
|
461
|
+
${importLines}
|
|
462
|
+
|
|
463
|
+
export const appRouter = router({
|
|
464
|
+
${bodyLines}
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
/** The type a tRPC client is parameterised by: \`createTRPCClient<AppRouter>()\`. */
|
|
468
|
+
export type AppRouter = typeof appRouter;
|
|
469
|
+
|
|
470
|
+
${reExports}`;
|
|
471
|
+
}
|
|
472
|
+
function serviceKeyNote(table) {
|
|
473
|
+
const cols = table.primaryKey?.columns ?? [];
|
|
474
|
+
const shape = cols.length > 1 ? `has a composite primary key (${cols.join(", ")})` : `has a non-numeric primary key (${cols[0]})`;
|
|
475
|
+
return `// ${table.name} ${shape}, and @drzl/generator-service types its key parameter as one number.
|
|
476
|
+
// Wire this to your own lookup.`;
|
|
477
|
+
}
|
|
478
|
+
function routerExportName(table, naming) {
|
|
479
|
+
const base = `${table.tsName}${naming?.routerSuffix ?? "Router"}`;
|
|
480
|
+
const c = naming?.procedureCase;
|
|
481
|
+
return toCase(base, c === "kebab" ? "camel" : c);
|
|
482
|
+
}
|
|
483
|
+
function serviceImportSpecifier(table, ctx, opts) {
|
|
484
|
+
const rel = relativePosix(ctx.out, ctx.services);
|
|
485
|
+
const dir = !rel ? "." : rel.startsWith(".") ? rel : `./${rel}`;
|
|
486
|
+
return importSpecifier(`${dir}/${singularize(table.tsName)}Service.ts`, opts.importExtension);
|
|
487
|
+
}
|
|
488
|
+
function relativePosix(from, to) {
|
|
489
|
+
const norm = (p) => p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
490
|
+
const a = norm(from).split("/");
|
|
491
|
+
const b = norm(to).split("/");
|
|
492
|
+
let i = 0;
|
|
493
|
+
while (i < a.length && i < b.length && a[i] === b[i]) i++;
|
|
494
|
+
return [...Array.from({ length: a.length - i }, () => ".."), ...b.slice(i)].join("/");
|
|
495
|
+
}
|
|
496
|
+
function buildHeader(h) {
|
|
497
|
+
if (h && h.enabled === false) return "";
|
|
498
|
+
const text = h?.text?.trim();
|
|
499
|
+
const lines = text ? text.split(/\r?\n/).map((l) => `// ${l}`) : [
|
|
500
|
+
"// Generated by DRZL (@drzl/*)",
|
|
501
|
+
"// Generated output is granted to you under your project's license.",
|
|
502
|
+
"// You may use, copy, modify, and distribute without attribution."
|
|
503
|
+
];
|
|
504
|
+
return lines.join("\n") + "\n\n";
|
|
505
|
+
}
|
|
506
|
+
export {
|
|
507
|
+
BASE_MODULE,
|
|
508
|
+
TRPCGenerator,
|
|
509
|
+
TRPC_MAJOR,
|
|
510
|
+
index_default as default
|
|
511
|
+
};
|
|
512
|
+
//# sourceMappingURL=dist-XBGVORL3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../generator-trpc/dist/index.js"],"sourcesContent":["// src/index.ts\nimport {\n formatCode,\n importSpecifier,\n resolveAffix,\n resolveConfiguredImport,\n schemaName\n} from \"@drzl/validation-core\";\nvar TRPC_MAJOR = 11;\nvar q = (v) => JSON.stringify(v);\nvar LIB_IMPORTS = {\n zod: \"import { z } from 'zod';\",\n valibot: \"import * as v from 'valibot';\",\n arktype: \"import { type } from 'arktype';\"\n};\nvar LIB_USAGE = {\n zod: /\\bz\\./,\n valibot: /\\bv\\./,\n arktype: /\\btype\\(/\n};\nvar LIBS = {\n zod: {\n number: \"z.number()\",\n string: \"z.string()\",\n boolean: \"z.boolean()\",\n date: \"z.date()\",\n unknown: \"z.unknown()\",\n tuple: (n) => `z.tuple([${Array.from({ length: n }, () => \"z.number()\").join(\", \")}])`,\n numberObject: (fields) => `z.object({ ${fields.map((f) => `${f}: z.number()`).join(\", \")} })`,\n enum: (vals) => `z.enum([${vals.map(q).join(\", \")}] as const)`,\n nullable: (b) => `${b}.nullable()`,\n optional: (b) => `${b}.optional()`,\n object: (body) => `z.object({\n${body}\n})`,\n objectInline: (body) => `z.object({ ${body} })`,\n partialUpdate: (s) => `${s}.partial()`,\n arrayOf: (s) => `z.array(${s})`,\n nullableOf: (s) => `${s}.nullable()`,\n booleanSchema: \"z.boolean()\"\n },\n valibot: {\n number: \"v.number()\",\n string: \"v.string()\",\n boolean: \"v.boolean()\",\n date: \"v.date()\",\n unknown: \"v.unknown()\",\n tuple: (n) => `v.tuple([${Array.from({ length: n }, () => \"v.number()\").join(\", \")}])`,\n numberObject: (fields) => `v.object({ ${fields.map((f) => `${f}: v.number()`).join(\", \")} })`,\n enum: (vals) => `v.picklist([${vals.map(q).join(\", \")}] as const)`,\n nullable: (b) => `v.nullable(${b})`,\n optional: (b) => `v.optional(${b})`,\n object: (body) => `v.object({\n${body}\n})`,\n objectInline: (body) => `v.object({ ${body} })`,\n arrayOf: (s) => `v.array(${s})`,\n nullableOf: (s) => `v.nullable(${s})`,\n booleanSchema: \"v.boolean()\"\n },\n arktype: {\n number: \"number\",\n string: \"string\",\n boolean: \"boolean\",\n date: \"Date\",\n unknown: \"unknown\",\n // The surrounding encode adds the quotes, so the union is built with the inner quoting\n // ArkType expects. Emitting `'${...}'` here produces `''admin' | 'user''`, which does not parse.\n enum: (vals) => vals.map((x) => `'${x.replace(/'/g, \"\\\\'\")}'`).join(\" | \"),\n nullable: (b) => `(${b} | null)`,\n optional: (b) => `${b}?`,\n object: (body) => `type({\n${body}\n})`,\n objectInline: (body) => `type({ ${body} })`,\n fieldIsString: true,\n arrayOf: (s) => `${s}.array()`,\n nullableOf: (s) => `${s}.or('null')`,\n booleanSchema: `type('boolean')`\n }\n};\nfunction isWide(column) {\n if (column.enumValues && column.enumValues.length) return false;\n if (column.shape?.kind === \"tuple\" || column.shape?.kind === \"numberObject\") return false;\n return ![\"number\", \"string\", \"boolean\", \"Date\"].includes(column.tsType);\n}\nfunction mapExpr(column, lib, mode) {\n const d = LIBS[lib];\n let base = (() => {\n if (column.enumValues && column.enumValues.length) return d.enum(column.enumValues);\n if (column.shape?.kind === \"tuple\" && d.tuple) return d.tuple(column.shape.length);\n if (column.shape?.kind === \"numberObject\" && d.numberObject) {\n return d.numberObject(column.shape.fields);\n }\n switch (column.tsType) {\n case \"number\":\n return d.number;\n case \"string\":\n return d.string;\n case \"boolean\":\n return d.boolean;\n case \"Date\":\n return d.date;\n default:\n return d.unknown;\n }\n })();\n if (column.nullable) base = d.nullable(base);\n if (mode !== \"select\") {\n const optional = mode === \"update\" || column.nullable || column.hasDefault;\n if (optional) base = d.optional(base);\n }\n return base;\n}\nfunction field(column, lib, mode) {\n const d = LIBS[lib];\n const expr = mapExpr(column, lib, mode);\n return `${objectKey(column.name)}: ${d.fieldIsString ? JSON.stringify(expr) : expr}`;\n}\nfunction objectKey(name) {\n return isIdent(name) ? name : JSON.stringify(name);\n}\nfunction renderSchema(table, lib, mode) {\n const d = LIBS[lib];\n const cols = table.columns.filter((c) => mode === \"select\" ? true : !c.isGenerated);\n const body = cols.map((c) => ` ${field(c, lib, mode)},`).join(\"\\n\");\n const schema = d.object(body);\n return mode === \"update\" && d.partialUpdate ? d.partialUpdate(schema) : schema;\n}\nfunction toCase(s, c) {\n if (!c) return s;\n const parts = s.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").replace(/[_-]/g, \" \").split(/\\s+/);\n if (c === \"camel\") {\n return parts.map(\n (p, i) => i === 0 ? p.toLowerCase() : p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()\n ).join(\"\");\n }\n if (c === \"kebab\") return parts.map((p) => p.toLowerCase()).join(\"-\");\n if (c === \"snake\") return parts.map((p) => p.toLowerCase()).join(\"_\");\n return s;\n}\nvar cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);\nvar singularize = (s) => s.endsWith(\"ies\") ? s.slice(0, -3) + \"y\" : s.endsWith(\"s\") ? s.slice(0, -1) : s;\nvar isIdent = (s) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(s);\nvar BASE_MODULE = \"trpc\";\nfunction keyColumns(table) {\n const names = table.primaryKey?.columns ?? [];\n if (!names.length) return null;\n const cols = names.map((n) => table.columns.find((c) => c.name === n));\n if (cols.some((c) => !c)) return null;\n return cols;\n}\nvar TRPCGenerator = class {\n constructor(analysis) {\n this.analysis = analysis;\n }\n async generate(opts) {\n const fs = await import(\"fs/promises\");\n const path = await import(\"path\");\n const out = path.resolve(process.cwd(), opts.outputDir);\n const ctx = {\n out,\n services: path.resolve(process.cwd(), opts.servicesDir ?? \"src/services\")\n };\n await fs.mkdir(out, { recursive: true });\n const files = [];\n const write = async (filePath, content) => {\n const formatted = await formatCode(\n buildHeader(opts.outputHeader) + content,\n filePath,\n opts.format\n );\n await fs.writeFile(filePath, formatted, \"utf8\");\n files.push(filePath);\n };\n const basePath = path.join(out, `${BASE_MODULE}.ts`);\n await write(basePath, renderBase(opts));\n const routers = [];\n const total = this.analysis.tables.length;\n let index = 0;\n for (const table of this.analysis.tables) {\n const base = `${table.tsName}${opts.naming?.routerSuffix ?? \"\"}`;\n const filePath = path.join(out, `${toCase(base, opts.naming?.procedureCase)}.ts`);\n if (filePath === basePath) {\n throw new Error(\n `@drzl/generator-trpc: the router for table \"${table.name}\" would be written to ${filePath}, which is the shared tRPC base module this generator also writes. Set naming.routerSuffix to move it out of the way.`\n );\n }\n await write(filePath, renderRouter(table, opts, ctx));\n routers.push({ table, filePath, exportName: routerExportName(table, opts.naming) });\n index++;\n opts.onProgress?.({ index, total, table: table.name, filePath });\n }\n await write(path.join(out, \"index.ts\"), renderBarrel(routers, ctx, path, opts));\n return { files };\n }\n};\nvar index_default = TRPCGenerator;\nfunction renderBase(opts) {\n const injection = opts.databaseInjection?.enabled === true;\n const dbType = opts.databaseInjection?.databaseType ?? \"unknown\";\n const typeImport = opts.databaseInjection?.databaseTypeImport ? `import type { ${opts.databaseInjection.databaseTypeImport.name} } from '${opts.databaseInjection.databaseTypeImport.from}';\n` : \"\";\n const trpcImport = injection ? `import { initTRPC, TRPCError } from '@trpc/server';` : `import { initTRPC } from '@trpc/server';`;\n const context = injection ? `/**\n * What your \\`createContext\\` hands every procedure.\n *\n * \\`db\\` is optional here and required by \\`dbProcedure\\` below. That split is what lets an adapter\n * build a context without a handle, for a health check or a public route, while every generated\n * procedure still sees one that is present.\n */\nexport interface Context {\n db?: ${dbType};\n}` : `/**\n * What your \\`createContext\\` hands every procedure. Nothing generated reads it, so it is left\n * open; narrow it to the shape your own context really has.\n */\nexport type Context = Record<string, unknown>;`;\n const middleware = injection ? `\n/**\n * The builder every generated procedure is built from: it refuses to run without a database\n * handle, and narrows \\`ctx.db\\` from optional to present for everything downstream.\n */\nexport const dbProcedure = t.procedure.use(async ({ ctx, next }) => {\n if (!ctx.db) {\n throw new TRPCError({\n code: 'INTERNAL_SERVER_ERROR',\n message: 'No database handle on the tRPC context. Provide one from createContext.',\n });\n }\n return next({ ctx: { db: ctx.db } });\n});\n` : \"\";\n return `// Generated by @drzl/generator-trpc\n// The shared tRPC base. Every generated router imports from here.\n${trpcImport}\n${typeImport}\n${context}\n\nconst t = initTRPC.context<Context>().create();\n\nexport const router = t.router;\nexport const mergeRouters = t.mergeRouters;\nexport const middleware = t.middleware;\n/** Needed to call this router in-process, from a test or from SSR. */\nexport const createCallerFactory = t.createCallerFactory;\nexport const publicProcedure = t.procedure;\n${middleware}`;\n}\nfunction renderRouter(table, opts, ctx) {\n const lib = opts.validation?.library ?? \"zod\";\n const d = LIBS[lib];\n const service = opts.template === \"service\";\n const injection = opts.databaseInjection?.enabled === true;\n const builder = injection ? \"dbProcedure\" : \"publicProcedure\";\n const insertName = `Insert${table.tsName}Schema`;\n const updateName = `Update${table.tsName}Schema`;\n const selectName = `Select${table.tsName}Schema`;\n const writable = !table.readOnly;\n const key = keyColumns(table);\n const Service = `${cap(singularize(table.tsName))}Service`;\n const serviceKeyable = !!key && key.length === 1 && key[0].tsType === \"number\";\n const keyArg = key && key.length === 1 ? `input.${key[0].name}` : \"\";\n const dbArg = injection ? \"ctx.db, \" : \"\";\n const wiredParams = injection ? \"{ ctx, input }\" : \"{ input }\";\n const procedures = [];\n const notImplemented = (what) => `throw new Error('Not implemented: ${what} ${table.tsName}.');`;\n procedures.push({\n name: \"list\",\n kind: \"query\",\n output: d.arrayOf(selectName),\n params: service && injection ? \"{ ctx }\" : \"\",\n body: service ? [`return await ${Service}.getAll(${injection ? \"ctx.db\" : \"\"});`] : [\"return [];\"]\n });\n const keyInput = key ? d.objectInline(key.map((c) => field(c, lib, \"select\")).join(\", \")) : void 0;\n if (key && keyInput) {\n const wired = service && serviceKeyable;\n procedures.push({\n name: \"byId\",\n kind: \"query\",\n input: keyInput,\n output: d.nullableOf(selectName),\n params: wired ? wiredParams : \"{ input: _input }\",\n body: wired ? [`return await ${Service}.getById(${dbArg}${keyArg});`] : service ? [serviceKeyNote(table), notImplemented(\"byId\")] : [\"return null;\"]\n });\n if (writable) {\n const updateInput = d.objectInline(\n [...key.map((c) => field(c, lib, \"select\")), `data: ${updateName}`].join(\", \")\n );\n procedures.push({\n name: \"update\",\n kind: \"mutation\",\n input: updateInput,\n output: selectName,\n params: wired ? wiredParams : \"{ input: _input }\",\n body: wired ? [`return await ${Service}.update(${dbArg}${keyArg}, input.data);`] : service ? [serviceKeyNote(table), notImplemented(\"update\")] : [notImplemented(\"update\")]\n });\n procedures.push({\n name: \"delete\",\n kind: \"mutation\",\n input: keyInput,\n output: d.booleanSchema,\n params: wired ? wiredParams : \"{ input: _input }\",\n body: wired ? [`return await ${Service}.delete(${dbArg}${keyArg});`] : service ? [serviceKeyNote(table), notImplemented(\"delete\")] : [\"return true;\"]\n });\n }\n }\n if (writable) {\n procedures.push({\n name: \"create\",\n kind: \"mutation\",\n input: insertName,\n output: selectName,\n params: service ? wiredParams : \"{ input: _input }\",\n body: service ? [`return await ${Service}.create(${dbArg}input);`] : [notImplemented(\"create\")]\n });\n }\n if (opts.includeRelations) {\n const taken = new Set(procedures.map((p) => p.name));\n procedures.push(...relationProcedures(table, lib, selectName, taken, service));\n }\n const order = [\"list\", \"byId\", \"create\", \"update\", \"delete\"];\n const rank = (n) => order.indexOf(n) === -1 ? order.length : order.indexOf(n);\n procedures.sort((a, b) => rank(a.name) - rank(b.name));\n const routerName = routerExportName(table, opts.naming);\n const entries = procedures.map((p) => {\n const rawKey = toCase(p.name, opts.naming?.procedureCase);\n const propKey = isIdent(rawKey) ? rawKey : JSON.stringify(rawKey);\n return [\n ` ${propKey}: ${builder}`,\n ...p.input ? [` .input(${p.input})`] : [],\n ` .output(${p.output})`,\n ` .${p.kind}(async (${p.params}) => {`,\n ...p.body.map((line) => ` ${line}`),\n ` }),`\n ].join(\"\\n\");\n }).join(\"\\n\");\n const body = `export const ${routerName} = router({\n${entries}\n});\n`;\n const useShared = !!opts.validation?.useShared && !!opts.validation?.importPath;\n const declared = [];\n if (!useShared) {\n if (writable) {\n declared.push(`export const ${insertName} = ${renderSchema(table, lib, \"insert\")};`);\n declared.push(`export const ${updateName} = ${renderSchema(table, lib, \"update\")};`);\n }\n declared.push(`export const ${selectName} = ${renderSchema(table, lib, \"select\")};`);\n }\n const decided = [...declared, body].join(\"\\n\\n\");\n const imports = [];\n if (useShared) {\n const sharedAffix = resolveAffix({\n affix: opts.validation?.affix,\n schemaSuffix: opts.validation?.schemaSuffix\n });\n const wanted = [\n [\"insert\", insertName],\n [\"update\", updateName],\n [\"select\", selectName]\n ].filter(([, local]) => decided.includes(local));\n if (wanted.length) {\n const spec = resolveConfiguredImport(\n opts.validation.importPath,\n ctx.out,\n process.cwd(),\n opts.importExtension\n );\n const names = wanted.map(([mode, local]) => {\n const exported = schemaName(mode, table.tsName, sharedAffix);\n return exported === local ? local : `${exported} as ${local}`;\n }).join(\", \");\n imports.push(`import { ${names} } from '${spec}';`);\n }\n }\n imports.push(\n `import { ${[builder, \"router\"].sort().join(\", \")} } from '${importSpecifier(\n `./${BASE_MODULE}.ts`,\n opts.importExtension\n )}';`\n );\n if (service) {\n imports.push(`import { ${Service} } from '${serviceImportSpecifier(table, ctx, opts)}';`);\n }\n if (LIB_USAGE[lib].test(decided)) imports.unshift(LIB_IMPORTS[lib]);\n const wide = table.columns.filter(isWide).map((c) => c.name);\n const wideNote = wide.length ? `// No validated type for ${wide.length === 1 ? \"this column\" : \"these columns\"}: ${wide.join(\", \")}.\n// DRZL could not derive one from the schema, so the router accepts any value there.\n` : \"\";\n return `// Generated by @drzl/generator-trpc\n// Router for table: ${table.name}\n${wideNote}${imports.join(\"\\n\")}\n\n${decided}`;\n}\nfunction relationProcedures(table, lib, selectSchemaName, taken, service) {\n const d = LIBS[lib];\n const out = [];\n for (const fk of table.foreignKeys ?? []) {\n if (fk.columns.length !== 1) continue;\n const colName = fk.columns[0];\n const column = table.columns.find((c) => c.name === colName);\n if (!column) continue;\n const name = `listBy${cap(colName)}`;\n if (taken.has(name)) continue;\n taken.add(name);\n out.push({\n name,\n kind: \"query\",\n input: d.objectInline(field(column, lib, \"select\")),\n output: d.arrayOf(selectSchemaName),\n params: \"{ input: _input }\",\n body: [\n `// Rows of ${table.name} whose ${JSON.stringify(colName)} matches _input.${colName}.`,\n // In `service` mode every other procedure really does reach the database, so a lookup\n // quietly answering with an empty array would read as \"no matching rows\". There is no\n // generated service method for it, so it says so instead. In `standard` mode everything\n // is a stub and `[]` is consistent with `list`.\n service ? `throw new Error('Not implemented: ${name} ${table.tsName}.');` : \"return [];\"\n ]\n });\n }\n return out;\n}\nfunction renderBarrel(routers, ctx, path, opts) {\n const baseSpec = importSpecifier(`./${BASE_MODULE}.ts`, opts.importExtension);\n const reExports = `export { createCallerFactory, publicProcedure, router } from '${baseSpec}';\n` + (opts.databaseInjection?.enabled === true ? `export { dbProcedure } from '${baseSpec}';\n` : \"\") + `export type { Context } from '${baseSpec}';\n`;\n if (!routers.length) {\n return `// Generated by @drzl/generator-trpc\n// No tables detected in analysis. Add tables to your schema and regenerate.\nimport { router } from '${baseSpec}';\n\nexport const appRouter = router({});\n\n/** The type a tRPC client is parameterised by: \\`createTRPCClient<AppRouter>()\\`. */\nexport type AppRouter = typeof appRouter;\n\n${reExports}`;\n }\n const entries = routers.map(({ filePath, exportName, table }) => ({\n rel: importSpecifier(\n \"./\" + path.relative(ctx.out, filePath).replace(/\\\\/g, \"/\"),\n opts.importExtension\n ),\n exportName,\n // The namespace a client reaches this table's procedures through: `trpc.userProfiles.list`.\n // `tsName` verbatim, because it is already a valid identifier and it is the name the user\n // wrote in their schema. The oRPC barrel lowercases this key, turning `userProfiles` into\n // `userprofiles`: harmless in an object literal nobody reads, and not harmless when the key\n // is the public API of a typed client.\n key: table.tsName\n }));\n const importLines = entries.map(({ rel, exportName }) => `import { ${exportName} } from '${rel}';`).join(\"\\n\");\n const bodyLines = entries.map(({ key, exportName }) => ` ${isIdent(key) ? key : JSON.stringify(key)}: ${exportName},`).join(\"\\n\");\n return `// Generated by @drzl/generator-trpc\nimport { router } from '${baseSpec}';\n${importLines}\n\nexport const appRouter = router({\n${bodyLines}\n});\n\n/** The type a tRPC client is parameterised by: \\`createTRPCClient<AppRouter>()\\`. */\nexport type AppRouter = typeof appRouter;\n\n${reExports}`;\n}\nfunction serviceKeyNote(table) {\n const cols = table.primaryKey?.columns ?? [];\n const shape = cols.length > 1 ? `has a composite primary key (${cols.join(\", \")})` : `has a non-numeric primary key (${cols[0]})`;\n return `// ${table.name} ${shape}, and @drzl/generator-service types its key parameter as one number.\n// Wire this to your own lookup.`;\n}\nfunction routerExportName(table, naming) {\n const base = `${table.tsName}${naming?.routerSuffix ?? \"Router\"}`;\n const c = naming?.procedureCase;\n return toCase(base, c === \"kebab\" ? \"camel\" : c);\n}\nfunction serviceImportSpecifier(table, ctx, opts) {\n const rel = relativePosix(ctx.out, ctx.services);\n const dir = !rel ? \".\" : rel.startsWith(\".\") ? rel : `./${rel}`;\n return importSpecifier(`${dir}/${singularize(table.tsName)}Service.ts`, opts.importExtension);\n}\nfunction relativePosix(from, to) {\n const norm = (p) => p.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const a = norm(from).split(\"/\");\n const b = norm(to).split(\"/\");\n let i = 0;\n while (i < a.length && i < b.length && a[i] === b[i]) i++;\n return [...Array.from({ length: a.length - i }, () => \"..\"), ...b.slice(i)].join(\"/\");\n}\nfunction buildHeader(h) {\n if (h && h.enabled === false) return \"\";\n const text = h?.text?.trim();\n const lines = text ? text.split(/\\r?\\n/).map((l) => `// ${l}`) : [\n \"// Generated by DRZL (@drzl/*)\",\n \"// Generated output is granted to you under your project's license.\",\n \"// You may use, copy, modify, and distribute without attribution.\"\n ];\n return lines.join(\"\\n\") + \"\\n\\n\";\n}\nexport {\n BASE_MODULE,\n TRPCGenerator,\n TRPC_MAJOR,\n index_default as default\n};\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drzl/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.16.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"jiti": "^2.7.0",
|
|
30
30
|
"ora": "^9.4.1",
|
|
31
31
|
"zod": "^4.4.3",
|
|
32
|
-
"@drzl/
|
|
33
|
-
"@drzl/generator-orpc": "^2.8.0",
|
|
34
|
-
"@drzl/generator-arktype": "^3.13.0",
|
|
32
|
+
"@drzl/generator-arktype": "^3.14.0",
|
|
35
33
|
"@drzl/generator-service": "^2.4.0",
|
|
36
|
-
"@drzl/generator-
|
|
37
|
-
"@drzl/generator-
|
|
38
|
-
"@drzl/
|
|
39
|
-
"@drzl/
|
|
34
|
+
"@drzl/generator-typebox": "^0.11.0",
|
|
35
|
+
"@drzl/generator-orpc": "^2.8.0",
|
|
36
|
+
"@drzl/analyzer": "^1.17.7",
|
|
37
|
+
"@drzl/generator-valibot": "^3.17.0",
|
|
38
|
+
"@drzl/generator-zod": "^3.18.0",
|
|
39
|
+
"@drzl/validation-core": "^3.17.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"drizzle-orm": "^0.45.2",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
"url": "https://github.com/sponsors/omar-dulaimi"
|
|
63
63
|
},
|
|
64
64
|
"optionalDependencies": {
|
|
65
|
-
"@drzl/generator-json-schema": "^0.5.0"
|
|
65
|
+
"@drzl/generator-json-schema": "^0.5.0",
|
|
66
|
+
"@drzl/generator-trpc": "^0.2.0"
|
|
66
67
|
},
|
|
67
68
|
"scripts": {
|
|
68
69
|
"build": "tsup src/cli.ts src/config.ts --format esm,cjs --sourcemap --dts --clean",
|