@drzl/cli 4.16.0 → 4.18.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/cli.js CHANGED
@@ -5,37 +5,18 @@ import {
5
5
  filterTables,
6
6
  loadConfig,
7
7
  trpcOutDir
8
- } from "./chunk-K4J4XIFO.js";
8
+ } from "./chunk-I4KMDCQR.js";
9
9
 
10
10
  // src/cli.ts
11
11
  import { SchemaAnalyzer } from "@drzl/analyzer";
12
12
  import { ORPCGenerator } from "@drzl/generator-orpc";
13
- import chalk2 from "chalk";
13
+ import chalk3 from "chalk";
14
14
  import chokidar from "chokidar";
15
15
  import cliProgress from "cli-progress";
16
16
  import { Command } from "commander";
17
17
  import * as path4 from "path";
18
18
  import ora from "ora";
19
19
 
20
- // src/trpc-options.ts
21
- function trpcOptions(g, cfg, servicesDir) {
22
- return {
23
- outputDir: trpcOutDir(g, cfg),
24
- template: g.template,
25
- includeRelations: g.includeRelations,
26
- naming: g.naming,
27
- outputHeader: g.outputHeader,
28
- format: g.format,
29
- importExtension: g.importExtension,
30
- validation: g.validation,
31
- databaseInjection: g.databaseInjection,
32
- // Where the service generator is actually writing, so `template: 'service'` emits an import
33
- // of a module that exists. The generator defaults this to `src/services`, which is right only
34
- // by coincidence for a config that puts them elsewhere.
35
- servicesDir
36
- };
37
- }
38
-
39
20
  // src/validation-options.ts
40
21
  function validationOptions(g, cfg, outDir, caps = {}) {
41
22
  return {
@@ -62,6 +43,297 @@ function validationOptions(g, cfg, outDir, caps = {}) {
62
43
  };
63
44
  }
64
45
 
46
+ // src/json-schema-options.ts
47
+ function jsonSchemaOptions(g, cfg, outDir) {
48
+ return {
49
+ // JSON Schema is data, so nothing it emits references a type from the schema module.
50
+ ...validationOptions(g, cfg, outDir, { schemaTypes: false }),
51
+ target: g.target,
52
+ components: g.components,
53
+ document: g.document,
54
+ // Read only while emitting a document, where it adds `/users/{id}/posts`. The per-table
55
+ // schemas are flat whatever it says.
56
+ includeRelations: g.includeRelations
57
+ };
58
+ }
59
+
60
+ // src/trpc-options.ts
61
+ function trpcOptions(g, cfg, servicesDir) {
62
+ return {
63
+ outputDir: trpcOutDir(g, cfg),
64
+ template: g.template,
65
+ includeRelations: g.includeRelations,
66
+ naming: g.naming,
67
+ outputHeader: g.outputHeader,
68
+ format: g.format,
69
+ importExtension: g.importExtension,
70
+ validation: g.validation,
71
+ databaseInjection: g.databaseInjection,
72
+ // Where the service generator is actually writing, so `template: 'service'` emits an import
73
+ // of a module that exists. The generator defaults this to `src/services`, which is right only
74
+ // by coincidence for a config that puts them elsewhere.
75
+ servicesDir
76
+ };
77
+ }
78
+
79
+ // src/doctor.ts
80
+ import { parseCheck } from "@drzl/validation-core";
81
+ import chalk from "chalk";
82
+ var HANDLED_CODES = /* @__PURE__ */ new Set(["DRZL_ANL_UNKNOWN_COLUMN"]);
83
+ function splitPath(path5) {
84
+ if (!path5) return {};
85
+ const dot = path5.lastIndexOf(".");
86
+ if (dot <= 0) return { table: path5 };
87
+ return { table: path5.slice(0, dot), column: path5.slice(dot + 1) };
88
+ }
89
+ function namedColumns(parsed) {
90
+ const out = [];
91
+ for (const c of parsed.checks) out.push({ column: c.column, scalar: true });
92
+ for (const s of parsed.sets ?? []) out.push({ column: s.column, scalar: true });
93
+ for (const l of parsed.lengths ?? []) out.push({ column: l.column, scalar: false });
94
+ for (const c of parsed.cardinalities ?? []) out.push({ column: c.column, scalar: false });
95
+ for (const r of parsed.rows ?? []) {
96
+ out.push({ column: r.left, scalar: false });
97
+ out.push({ column: r.right, scalar: false });
98
+ }
99
+ return out;
100
+ }
101
+ function describeShape(c) {
102
+ if (c.arrayDimensions) return "an array";
103
+ switch (c.shape?.kind) {
104
+ case "json":
105
+ return "a JSON";
106
+ case "buffer":
107
+ return "a binary";
108
+ case "tuple":
109
+ case "numberObject":
110
+ return "a structured";
111
+ case "numberVector":
112
+ return "a vector";
113
+ case "bitstring":
114
+ return "a bit-string";
115
+ case "byteString":
116
+ return "a byte-string";
117
+ case "custom":
118
+ return "a customType";
119
+ default:
120
+ return "a structured";
121
+ }
122
+ }
123
+ function checkFindings(table) {
124
+ const out = [];
125
+ const byName = new Map(table.columns.map((c) => [c.name, c]));
126
+ for (const k of table.checks ?? []) {
127
+ const label = k.name ? `"${k.name}"` : "an unnamed constraint";
128
+ const raw = k.expression ?? "";
129
+ const expr = raw.trim() ? raw : "(empty)";
130
+ const parsed = parseCheck(raw, k.name);
131
+ if (!parsed.ok) {
132
+ out.push({
133
+ kind: "check-declined",
134
+ level: "warn",
135
+ table: table.tsName,
136
+ constraint: k.name,
137
+ message: `CHECK ${label} on "${table.tsName}" is not translated: ${parsed.reason}. Expression: ${expr}`,
138
+ hint: "Only constraints whose meaning is unambiguous are translated, because a validator enforcing a guess rejects rows the database accepts. Your database still enforces this one; nothing DRZL emits does."
139
+ });
140
+ continue;
141
+ }
142
+ const seen = /* @__PURE__ */ new Set();
143
+ for (const { column, scalar } of namedColumns(parsed)) {
144
+ if (seen.has(column)) continue;
145
+ seen.add(column);
146
+ const col = byName.get(column);
147
+ if (!col) {
148
+ out.push({
149
+ kind: "check-unknown-column",
150
+ level: "warn",
151
+ table: table.tsName,
152
+ column,
153
+ constraint: k.name,
154
+ message: `CHECK ${label} on "${table.tsName}" names "${column}", which is not a column of that table, so nothing enforces it. Expression: ${expr}`,
155
+ hint: "A constraint is attached to the field it names. Check the spelling, or move a constraint spanning two tables out of the schema."
156
+ });
157
+ continue;
158
+ }
159
+ if (scalar && (col.arrayDimensions || col.shape)) {
160
+ out.push({
161
+ kind: "check-not-scalar",
162
+ level: "warn",
163
+ table: table.tsName,
164
+ column,
165
+ constraint: k.name,
166
+ message: `CHECK ${label} on "${table.tsName}" compares ${describeShape(col)} column "${column}" against a scalar literal, which does not describe it, so it is not translated. Expression: ${expr}`,
167
+ hint: "On an array column only cardinality(col) is read, since it is the one comparison that is about the array rather than about an element."
168
+ });
169
+ }
170
+ }
171
+ }
172
+ return out;
173
+ }
174
+ function primaryKeyFindings(table) {
175
+ if (table.readOnly) return [];
176
+ const pk = table.primaryKey?.columns ?? [];
177
+ if (!pk.length) {
178
+ const hasId = table.columns.some((c) => c.name === "id");
179
+ return [
180
+ {
181
+ kind: "no-primary-key",
182
+ level: "warn",
183
+ table: table.tsName,
184
+ message: hasId ? `Table "${table.tsName}" declares no primary key. The service and router generators fall back to a column named "id", which this table happens to have, so they work by coincidence.` : `Table "${table.tsName}" declares no primary key. The service and router generators fall back to a column named "id", which this table does not have, so the generated service will not compile.`,
185
+ hint: "Declare a primary key, or leave this table out with the config table filter."
186
+ }
187
+ ];
188
+ }
189
+ if (pk.length > 1) {
190
+ return [
191
+ {
192
+ kind: "partial-primary-key",
193
+ level: "warn",
194
+ table: table.tsName,
195
+ message: `Table "${table.tsName}" has a composite primary key (${pk.join(", ")}). The service and router generators key getById, update and delete on "${pk[0]}" alone, so those operations match on part of the key.`,
196
+ hint: "Treat the generated service as a starting point for this table and widen the key by hand."
197
+ }
198
+ ];
199
+ }
200
+ return [];
201
+ }
202
+ function buildDoctorReport(analysis, schemaPath) {
203
+ const findings = [];
204
+ const errors = analysis.issues.filter((i) => i.level === "error");
205
+ for (const i of errors) {
206
+ findings.push({
207
+ kind: "analyzer",
208
+ level: "error",
209
+ ...splitPath(i.path),
210
+ message: i.message,
211
+ hint: i.hint
212
+ });
213
+ }
214
+ for (const i of analysis.issues) {
215
+ if (i.code !== "DRZL_ANL_UNKNOWN_COLUMN") continue;
216
+ findings.push({
217
+ kind: "unknown-column",
218
+ level: "warn",
219
+ ...splitPath(i.path),
220
+ message: i.message,
221
+ hint: i.hint
222
+ });
223
+ }
224
+ for (const t of analysis.tables) findings.push(...checkFindings(t));
225
+ for (const t of analysis.tables) findings.push(...primaryKeyFindings(t));
226
+ for (const i of analysis.issues) {
227
+ if (i.level === "error" || HANDLED_CODES.has(i.code)) continue;
228
+ findings.push({
229
+ kind: "analyzer",
230
+ level: "warn",
231
+ ...splitPath(i.path),
232
+ message: i.message,
233
+ hint: i.hint
234
+ });
235
+ }
236
+ const columns = analysis.tables.reduce((n, t) => n + t.columns.length, 0);
237
+ const checks = analysis.tables.reduce((n, t) => n + (t.checks?.length ?? 0), 0);
238
+ return {
239
+ schema: schemaPath,
240
+ dialect: analysis.dialect,
241
+ ok: findings.length === 0,
242
+ counts: { tables: analysis.tables.length, columns, checks, findings: findings.length },
243
+ findings
244
+ };
245
+ }
246
+ var SECTIONS = [
247
+ {
248
+ kinds: ["unknown-column"],
249
+ title: "Columns DRZL cannot type",
250
+ why: "These get a validator that accepts any value."
251
+ },
252
+ {
253
+ kinds: ["check-declined", "check-unknown-column", "check-not-scalar"],
254
+ title: "CHECK constraints DRZL does not enforce",
255
+ why: "Your database still enforces these. Nothing DRZL generates does."
256
+ },
257
+ {
258
+ kinds: ["no-primary-key", "partial-primary-key"],
259
+ title: "Primary keys the generators cannot use",
260
+ why: "The generated getById, update and delete are keyed on one column."
261
+ },
262
+ {
263
+ kinds: ["analyzer"],
264
+ title: "Other findings",
265
+ why: "Reported by the analyzer while reading the schema."
266
+ }
267
+ ];
268
+ function wrap(text, indent, first = indent, width = 96) {
269
+ const lines = [];
270
+ let line = "";
271
+ for (const word of text.split(/\s+/)) {
272
+ if (line && `${line} ${word}`.length + indent.length > width) {
273
+ lines.push(line);
274
+ line = word;
275
+ } else {
276
+ line = line ? `${line} ${word}` : word;
277
+ }
278
+ }
279
+ if (line) lines.push(line);
280
+ return lines.map((l, i) => (i === 0 ? first : indent) + l).join("\n");
281
+ }
282
+ function renderDoctorReport(report) {
283
+ const out = [];
284
+ const plural = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
285
+ out.push(chalk.bold(`DRZL doctor ${report.schema}`));
286
+ out.push(
287
+ chalk.dim(
288
+ `${report.dialect}, ${plural(report.counts.tables, "table")}, ${plural(report.counts.columns, "column")}, ${plural(report.counts.checks, "CHECK constraint")}`
289
+ )
290
+ );
291
+ out.push("");
292
+ if (report.ok) {
293
+ out.push(chalk.green("Nothing to report."));
294
+ out.push(chalk.dim(" Every column has a type DRZL can describe."));
295
+ out.push(chalk.dim(" Every CHECK constraint is translated into the generated validators."));
296
+ out.push(chalk.dim(" Every table has a primary key the generators can use."));
297
+ return out.join("\n");
298
+ }
299
+ const fatal = report.findings.filter((f) => f.level === "error");
300
+ if (fatal.length) {
301
+ out.push(chalk.red("DRZL could not read this schema"));
302
+ out.push(chalk.dim(" Nothing else could be checked."));
303
+ out.push("");
304
+ for (const f of fatal) {
305
+ out.push(wrap(f.message, " ", ` ${chalk.dim("-")} `));
306
+ if (f.hint) out.push(chalk.dim(wrap(f.hint, " ")));
307
+ }
308
+ out.push("");
309
+ }
310
+ for (const section of SECTIONS) {
311
+ const mine = report.findings.filter(
312
+ (f) => f.level !== "error" && section.kinds.includes(f.kind)
313
+ );
314
+ if (!mine.length) continue;
315
+ out.push(chalk.yellow(`${section.title} (${mine.length})`));
316
+ out.push(chalk.dim(` ${section.why}`));
317
+ out.push("");
318
+ const groups = /* @__PURE__ */ new Map();
319
+ for (const f of mine) {
320
+ const key = f.hint ?? "";
321
+ groups.set(key, [...groups.get(key) ?? [], f]);
322
+ }
323
+ for (const [hint, items] of groups) {
324
+ for (const f of items) out.push(wrap(f.message, " ", ` ${chalk.dim("-")} `));
325
+ if (hint) out.push(chalk.dim(wrap(hint, " ")));
326
+ out.push("");
327
+ }
328
+ }
329
+ out.push(
330
+ chalk.bold(`${plural(report.counts.findings, "finding")} in ${report.schema}.`) + chalk.dim(
331
+ fatal.length ? " Fix the error above and run this again." : " None of these stop DRZL generating; they are what it will not check for you."
332
+ )
333
+ );
334
+ return out.join("\n");
335
+ }
336
+
65
337
  // src/drift.ts
66
338
  import { promises as fs } from "fs";
67
339
  import path from "path";
@@ -138,7 +410,7 @@ async function loadGenerator(specifier, load) {
138
410
  }
139
411
 
140
412
  // src/sponsor.ts
141
- import chalk from "chalk";
413
+ import chalk2 from "chalk";
142
414
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
143
415
  import path2 from "path";
144
416
  var CACHE_DIR = path2.join(process.cwd(), "node_modules", ".cache", "@drzl");
@@ -152,9 +424,9 @@ var tips = [
152
424
  "Need JSON Schema or OpenAPI? The json-schema generator emits both, with no runtime dependency.",
153
425
  "Use output headers to track generated files and trim noisy diffs."
154
426
  ];
155
- var green = (msg) => chalk.hex("#6ee7b7")(msg);
156
- var cyan = (msg) => chalk.cyan(msg);
157
- var gray = (msg) => chalk.gray(msg);
427
+ var green = (msg) => chalk2.hex("#6ee7b7")(msg);
428
+ var cyan = (msg) => chalk2.cyan(msg);
429
+ var gray = (msg) => chalk2.gray(msg);
158
430
  function maybeShowSponsorMessage({
159
431
  reason = "generate",
160
432
  minIntervalMs = DEFAULT_INTERVAL_MS,
@@ -243,13 +515,13 @@ var CLI_VERSION = readCliVersion();
243
515
  function reportGeneratorFailure(kind, e) {
244
516
  if (e instanceof GeneratorNotInstalledError) {
245
517
  console.error(
246
- chalk2.red(`The ${kind} generator is not installed.`),
247
- chalk2.yellow(`
518
+ chalk3.red(`The ${kind} generator is not installed.`),
519
+ chalk3.yellow(`
248
520
  Install with: npm install ${e.specifier}`)
249
521
  );
250
522
  return;
251
523
  }
252
- console.error(chalk2.red(`The ${kind} generator failed:`), e?.message ?? e);
524
+ console.error(chalk3.red(`The ${kind} generator failed:`), e?.message ?? e);
253
525
  }
254
526
  var program = new Command();
255
527
  program.name("drzl").description("DRZL - Drizzle Developer Toolkit").version(CLI_VERSION);
@@ -276,9 +548,9 @@ program.command("analyze").argument("<schema>", "path to drizzle schema (TS)").o
276
548
  } else if (opts.out) {
277
549
  const fs2 = await import("fs/promises");
278
550
  await fs2.writeFile(opts.out, json, "utf8");
279
- spinner?.succeed(chalk2.green(`Analysis written to ${opts.out} in ${ms}ms`));
551
+ spinner?.succeed(chalk3.green(`Analysis written to ${opts.out} in ${ms}ms`));
280
552
  } else {
281
- spinner?.succeed(chalk2.green(`Analyzed in ${ms}ms`));
553
+ spinner?.succeed(chalk3.green(`Analyzed in ${ms}ms`));
282
554
  console.log(json);
283
555
  }
284
556
  process.exit(res.issues.some((i) => i.level === "error") ? 2 : 0);
@@ -288,7 +560,48 @@ program.command("analyze").argument("<schema>", "path to drizzle schema (TS)").o
288
560
  console.log(JSON.stringify({ event: "error", code: "DRZL_CLI_ANALYZE", message: msg }));
289
561
  else
290
562
  console.error(
291
- chalk2.red("Analyze failed (DRZL_CLI_ANALYZE):"),
563
+ chalk3.red("Analyze failed (DRZL_CLI_ANALYZE):"),
564
+ msg,
565
+ "\nTip: run with --json for structured output."
566
+ );
567
+ process.exit(1);
568
+ }
569
+ });
570
+ program.command("doctor").description("Report what DRZL cannot type or enforce in your schema, and why").argument("[schema]", "path to drizzle schema (TS); defaults to the schema in drzl.config").option("-c, --config <path>", "path to drzl.config, read when no schema argument is given").option("--json", "print the report as JSON instead of prose", false).option("--strict", "exit 2 when anything is reported", false).action(async (schema, opts) => {
571
+ try {
572
+ let target = schema;
573
+ if (!target) {
574
+ const cfg = await loadConfig(opts.config);
575
+ target = cfg?.schema;
576
+ }
577
+ if (!target) {
578
+ const msg = "No schema given. Pass a path, or run from a directory with a drzl.config.";
579
+ if (opts.json)
580
+ console.log(JSON.stringify({ event: "error", code: "DRZL_CLI_DOCTOR", message: msg }));
581
+ else console.error(chalk3.red("Doctor failed (DRZL_CLI_DOCTOR):"), msg);
582
+ process.exit(1);
583
+ return;
584
+ }
585
+ const analyzer = new SchemaAnalyzer(target);
586
+ const analysis = await analyzer.analyze({
587
+ includeRelations: true,
588
+ validateConstraints: true
589
+ });
590
+ const report = buildDoctorReport(analysis, target);
591
+ if (opts.json) console.log(JSON.stringify(report, null, 2));
592
+ else console.log(renderDoctorReport(report));
593
+ if (report.findings.some((f) => f.level === "error")) {
594
+ process.exit(1);
595
+ return;
596
+ }
597
+ process.exit(opts.strict && report.findings.length ? 2 : 0);
598
+ } catch (e) {
599
+ const msg = e?.message ?? String(e);
600
+ if (opts.json)
601
+ console.log(JSON.stringify({ event: "error", code: "DRZL_CLI_DOCTOR", message: msg }));
602
+ else
603
+ console.error(
604
+ chalk3.red("Doctor failed (DRZL_CLI_DOCTOR):"),
292
605
  msg,
293
606
  "\nTip: run with --json for structured output."
294
607
  );
@@ -303,7 +616,7 @@ program.command("generate").description("Run configured generators (drzl.config.
303
616
  const cfg = await loadConfig(opts.config);
304
617
  if (!cfg) {
305
618
  console.error(
306
- chalk2.red("No config found (DRZL_CFG_001). Create drzl.config.ts or pass --config.")
619
+ chalk3.red("No config found (DRZL_CFG_001). Create drzl.config.ts or pass --config.")
307
620
  );
308
621
  process.exit(2);
309
622
  return;
@@ -348,8 +661,8 @@ program.command("generate").description("Run configured generators (drzl.config.
348
661
  onProgress: ({ index }) => progress.update(index)
349
662
  });
350
663
  progress.stop();
351
- ora().succeed(chalk2.green(`Generated (${g.kind}): ${files.length} files`));
352
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
664
+ ora().succeed(chalk3.green(`Generated (${g.kind}): ${files.length} files`));
665
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
353
666
  } else if (g.kind === "trpc") {
354
667
  try {
355
668
  const { TRPCGenerator } = await loadGenerator(
@@ -362,8 +675,8 @@ program.command("generate").description("Run configured generators (drzl.config.
362
675
  onProgress: ({ index }) => progress.update(index)
363
676
  });
364
677
  progress.stop();
365
- ora().succeed(chalk2.green(`Generated (trpc): ${files.length} files`));
366
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
678
+ ora().succeed(chalk3.green(`Generated (trpc): ${files.length} files`));
679
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
367
680
  } catch (e) {
368
681
  progress.stop();
369
682
  reportGeneratorFailure(g.kind, e);
@@ -392,8 +705,8 @@ program.command("generate").description("Run configured generators (drzl.config.
392
705
  databaseInjection: g.databaseInjection
393
706
  });
394
707
  progress.stop();
395
- ora().succeed(chalk2.green(`Generated (service): ${files.length} files`));
396
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
708
+ ora().succeed(chalk3.green(`Generated (service): ${files.length} files`));
709
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
397
710
  } catch (e) {
398
711
  progress.stop();
399
712
  reportGeneratorFailure(g.kind, e);
@@ -411,8 +724,8 @@ program.command("generate").description("Run configured generators (drzl.config.
411
724
  validationOptions(g, cfg, target, { schemaTypes: true })
412
725
  );
413
726
  progress.stop();
414
- ora().succeed(chalk2.green(`Generated (zod): ${files.length} files`));
415
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
727
+ ora().succeed(chalk3.green(`Generated (zod): ${files.length} files`));
728
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
416
729
  } catch (e) {
417
730
  progress.stop();
418
731
  reportGeneratorFailure(g.kind, e);
@@ -430,8 +743,8 @@ program.command("generate").description("Run configured generators (drzl.config.
430
743
  validationOptions(g, cfg, target, { schemaTypes: true })
431
744
  );
432
745
  progress.stop();
433
- ora().succeed(chalk2.green(`Generated (valibot): ${files.length} files`));
434
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
746
+ ora().succeed(chalk3.green(`Generated (valibot): ${files.length} files`));
747
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
435
748
  } catch (e) {
436
749
  progress.stop();
437
750
  reportGeneratorFailure(g.kind, e);
@@ -449,8 +762,8 @@ program.command("generate").description("Run configured generators (drzl.config.
449
762
  validationOptions(g, cfg, target, { schemaTypes: false })
450
763
  );
451
764
  progress.stop();
452
- ora().succeed(chalk2.green(`Generated (arktype): ${files.length} files`));
453
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
765
+ ora().succeed(chalk3.green(`Generated (arktype): ${files.length} files`));
766
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
454
767
  } catch (e) {
455
768
  progress.stop();
456
769
  reportGeneratorFailure(g.kind, e);
@@ -460,19 +773,14 @@ program.command("generate").description("Run configured generators (drzl.config.
460
773
  try {
461
774
  const { JsonSchemaGenerator } = await loadGenerator(
462
775
  "@drzl/generator-json-schema",
463
- () => import("./dist-UE55LTXV.js")
776
+ () => import("./dist-TRJLPIWT.js")
464
777
  );
465
778
  const gen = new JsonSchemaGenerator(analysis);
466
779
  const target = g.path ?? "src/validators/json-schema";
467
- const files = await gen.generate({
468
- // JSON Schema is data, so nothing here references a type from the schema module.
469
- ...validationOptions(g, cfg, target, { schemaTypes: false }),
470
- target: g.target,
471
- components: g.components
472
- });
780
+ const files = await gen.generate(jsonSchemaOptions(g, cfg, target));
473
781
  progress.stop();
474
- ora().succeed(chalk2.green(`Generated (json-schema): ${files.length} files`));
475
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
782
+ ora().succeed(chalk3.green(`Generated (json-schema): ${files.length} files`));
783
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
476
784
  } catch (e) {
477
785
  progress.stop();
478
786
  reportGeneratorFailure(g.kind, e);
@@ -490,8 +798,8 @@ program.command("generate").description("Run configured generators (drzl.config.
490
798
  validationOptions(g, cfg, target, { schemaTypes: true })
491
799
  );
492
800
  progress.stop();
493
- ora().succeed(chalk2.green(`Generated (typebox): ${files.length} files`));
494
- files.forEach((f) => console.log(" -", chalk2.cyan(f)));
801
+ ora().succeed(chalk3.green(`Generated (typebox): ${files.length} files`));
802
+ files.forEach((f) => console.log(" -", chalk3.cyan(f)));
495
803
  } catch (e) {
496
804
  progress.stop();
497
805
  reportGeneratorFailure(g.kind, e);
@@ -504,22 +812,22 @@ program.command("generate").description("Run configured generators (drzl.config.
504
812
  const drift = diffSnapshots(driftBefore, after);
505
813
  await restoreSnapshot(driftBefore, after);
506
814
  if (drift.length) {
507
- console.error(chalk2.red(`
815
+ console.error(chalk3.red(`
508
816
  Generated output is out of date (${drift.length} file(s)):`));
509
817
  for (const d of drift) {
510
818
  const mark = d.status === "added" ? "+" : d.status === "removed" ? "-" : "~";
511
819
  console.error(
512
- ` ${mark} ${chalk2.yellow(d.status.padEnd(8))} ${path4.relative(process.cwd(), d.file)}`
820
+ ` ${mark} ${chalk3.yellow(d.status.padEnd(8))} ${path4.relative(process.cwd(), d.file)}`
513
821
  );
514
822
  }
515
823
  console.error(
516
- chalk2.dim(
824
+ chalk3.dim(
517
825
  "\nRun `drzl generate` and commit the result. Nothing was written by this check."
518
826
  )
519
827
  );
520
828
  process.exit(1);
521
829
  }
522
- console.log(chalk2.green("Generated output is up to date."));
830
+ console.log(chalk3.green("Generated output is up to date."));
523
831
  return;
524
832
  }
525
833
  if (cfg.generators.length) {
@@ -527,7 +835,7 @@ Generated output is out of date (${drift.length} file(s)):`));
527
835
  }
528
836
  } catch (e) {
529
837
  console.error(
530
- chalk2.red("Generate failed (DRZL_GEN_001):"),
838
+ chalk3.red("Generate failed (DRZL_GEN_001):"),
531
839
  e?.message ?? e,
532
840
  "\nTip: check your drzl.config.ts and template path."
533
841
  );
@@ -547,10 +855,10 @@ program.command("generate:orpc").argument("<schema>", "path to drizzle schema (T
547
855
  template: opts.template,
548
856
  includeRelations: !!opts.includeRelations
549
857
  });
550
- console.log(chalk2.green(`Generated:`), files.map((f) => chalk2.cyan(f)).join(", "));
858
+ console.log(chalk3.green(`Generated:`), files.map((f) => chalk3.cyan(f)).join(", "));
551
859
  maybeShowSponsorMessage({ reason: "generate:orpc" });
552
860
  } catch (e) {
553
- console.error(chalk2.red("Generate orpc failed:"), e?.message ?? e);
861
+ console.error(chalk3.red("Generate orpc failed:"), e?.message ?? e);
554
862
  process.exit(1);
555
863
  }
556
864
  });
@@ -574,7 +882,7 @@ program.command("generate:trpc").argument("<schema>", "path to drizzle schema (T
574
882
  // cannot become the branch that forgets it.
575
883
  servicesDir: opts.servicesDir
576
884
  });
577
- console.log(chalk2.green(`Generated:`), files.map((f) => chalk2.cyan(f)).join(", "));
885
+ console.log(chalk3.green(`Generated:`), files.map((f) => chalk3.cyan(f)).join(", "));
578
886
  maybeShowSponsorMessage({ reason: "generate:trpc" });
579
887
  } catch (e) {
580
888
  reportGeneratorFailure("trpc", e);
@@ -584,7 +892,7 @@ program.command("generate:trpc").argument("<schema>", "path to drizzle schema (T
584
892
  program.command("watch").description("Watch schema and regenerate on changes").option("-c, --config <path>", "path to drzl.config").option("--pipeline <name>", "all | analyze | generate-orpc | generate-trpc", "all").option("--debounce <ms>", "debounce ms", "200").option("--json", "emit JSON logs", false).option("--poll", "force polling (helps WSL/Docker/remote FS)", false).action(async (opts) => {
585
893
  let cfg = await loadConfig(opts.config);
586
894
  if (!cfg) {
587
- console.error(chalk2.red("No config found. Create drzl.config.ts or pass --config."));
895
+ console.error(chalk3.red("No config found. Create drzl.config.ts or pass --config."));
588
896
  process.exit(2);
589
897
  return;
590
898
  }
@@ -676,7 +984,7 @@ program.command("watch").description("Watch schema and regenerate on changes").o
676
984
  })
677
985
  );
678
986
  } else {
679
- console.log(chalk2.green("Analyze complete."));
987
+ console.log(chalk3.green("Analyze complete."));
680
988
  }
681
989
  return;
682
990
  }
@@ -706,8 +1014,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
706
1014
  servicesDir
707
1015
  });
708
1016
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
709
- chalk2.green(`Generated (${g.kind}):`),
710
- files.map((f) => chalk2.cyan(f)).join(", ")
1017
+ chalk3.green(`Generated (${g.kind}):`),
1018
+ files.map((f) => chalk3.cyan(f)).join(", ")
711
1019
  );
712
1020
  newFiles.push(...files);
713
1021
  } else if (g.kind === "trpc") {
@@ -719,8 +1027,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
719
1027
  const gen = new TRPCGenerator(analysis);
720
1028
  const { files } = await gen.generate(trpcOptions(g, cfg, servicesDir));
721
1029
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
722
- chalk2.green(`Generated (trpc): ${files.length} files`),
723
- files.map((f) => chalk2.cyan(f)).join(", ")
1030
+ chalk3.green(`Generated (trpc): ${files.length} files`),
1031
+ files.map((f) => chalk3.cyan(f)).join(", ")
724
1032
  );
725
1033
  newFiles.push(...files);
726
1034
  } catch (e) {
@@ -746,8 +1054,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
746
1054
  databaseInjection: g.databaseInjection
747
1055
  });
748
1056
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
749
- chalk2.green(`Generated (service): ${files.length} files`),
750
- files.map((f) => chalk2.cyan(f)).join(", ")
1057
+ chalk3.green(`Generated (service): ${files.length} files`),
1058
+ files.map((f) => chalk3.cyan(f)).join(", ")
751
1059
  );
752
1060
  newFiles.push(...files);
753
1061
  } catch (e) {
@@ -766,8 +1074,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
766
1074
  validationOptions(g, cfg, target, { schemaTypes: true })
767
1075
  );
768
1076
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
769
- chalk2.green(`Generated (zod): ${files.length} files`),
770
- files.map((f) => chalk2.cyan(f)).join(", ")
1077
+ chalk3.green(`Generated (zod): ${files.length} files`),
1078
+ files.map((f) => chalk3.cyan(f)).join(", ")
771
1079
  );
772
1080
  newFiles.push(...files);
773
1081
  } catch (e) {
@@ -786,8 +1094,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
786
1094
  validationOptions(g, cfg, target, { schemaTypes: true })
787
1095
  );
788
1096
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
789
- chalk2.green(`Generated (valibot): ${files.length} files`),
790
- files.map((f) => chalk2.cyan(f)).join(", ")
1097
+ chalk3.green(`Generated (valibot): ${files.length} files`),
1098
+ files.map((f) => chalk3.cyan(f)).join(", ")
791
1099
  );
792
1100
  newFiles.push(...files);
793
1101
  } catch (e) {
@@ -806,8 +1114,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
806
1114
  validationOptions(g, cfg, target, { schemaTypes: false })
807
1115
  );
808
1116
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
809
- chalk2.green(`Generated (arktype): ${files.length} files`),
810
- files.map((f) => chalk2.cyan(f)).join(", ")
1117
+ chalk3.green(`Generated (arktype): ${files.length} files`),
1118
+ files.map((f) => chalk3.cyan(f)).join(", ")
811
1119
  );
812
1120
  newFiles.push(...files);
813
1121
  } catch (e) {
@@ -826,8 +1134,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
826
1134
  validationOptions(g, cfg, target, { schemaTypes: true })
827
1135
  );
828
1136
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
829
- chalk2.green(`Generated (typebox): ${files.length} files`),
830
- files.map((f) => chalk2.cyan(f)).join(", ")
1137
+ chalk3.green(`Generated (typebox): ${files.length} files`),
1138
+ files.map((f) => chalk3.cyan(f)).join(", ")
831
1139
  );
832
1140
  newFiles.push(...files);
833
1141
  } catch (e) {
@@ -838,19 +1146,14 @@ program.command("watch").description("Watch schema and regenerate on changes").o
838
1146
  try {
839
1147
  const { JsonSchemaGenerator } = await loadGenerator(
840
1148
  "@drzl/generator-json-schema",
841
- () => import("./dist-UE55LTXV.js")
1149
+ () => import("./dist-TRJLPIWT.js")
842
1150
  );
843
1151
  const gen = new JsonSchemaGenerator(analysis);
844
1152
  const target = g.path ?? "src/validators/json-schema";
845
- const files = await gen.generate({
846
- // JSON Schema is data, so nothing here references a type from the schema module.
847
- ...validationOptions(g, cfg, target, { schemaTypes: false }),
848
- target: g.target,
849
- components: g.components
850
- });
1153
+ const files = await gen.generate(jsonSchemaOptions(g, cfg, target));
851
1154
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
852
- chalk2.green(`Generated (json-schema): ${files.length} files`),
853
- files.map((f) => chalk2.cyan(f)).join(", ")
1155
+ chalk3.green(`Generated (json-schema): ${files.length} files`),
1156
+ files.map((f) => chalk3.cyan(f)).join(", ")
854
1157
  );
855
1158
  newFiles.push(...files);
856
1159
  } catch (e) {
@@ -862,8 +1165,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
862
1165
  const added = newFiles.filter((f) => !lastFiles.includes(f));
863
1166
  const removed = lastFiles.filter((f) => !newFiles.includes(f));
864
1167
  opts.json ? console.log(JSON.stringify({ event: "diff", added, removed })) : (() => {
865
- if (added.length) console.log(chalk2.blue(`Added: ${added.join(", ")}`));
866
- if (removed.length) console.log(chalk2.yellow(`Removed: ${removed.join(", ")}`));
1168
+ if (added.length) console.log(chalk3.blue(`Added: ${added.join(", ")}`));
1169
+ if (removed.length) console.log(chalk3.yellow(`Removed: ${removed.join(", ")}`));
867
1170
  })();
868
1171
  if (newFiles.length && !opts.json) {
869
1172
  const reason = opts.pipeline && opts.pipeline !== "all" ? `watch:${opts.pipeline}` : "watch";
@@ -871,7 +1174,7 @@ program.command("watch").description("Watch schema and regenerate on changes").o
871
1174
  }
872
1175
  lastFiles = newFiles;
873
1176
  } catch (e) {
874
- opts.json ? console.log(JSON.stringify({ event: "error", message: String(e?.message ?? e) })) : console.error(chalk2.red("Watch pipeline failed:"), e?.message ?? e);
1177
+ opts.json ? console.log(JSON.stringify({ event: "error", message: String(e?.message ?? e) })) : console.error(chalk3.red("Watch pipeline failed:"), e?.message ?? e);
875
1178
  }
876
1179
  };
877
1180
  const debounced = Number(opts.debounce) || 200;
@@ -896,12 +1199,12 @@ program.command("watch").description("Watch schema and regenerate on changes").o
896
1199
  );
897
1200
  } else {
898
1201
  console.log(
899
- chalk2.gray(
1202
+ chalk3.gray(
900
1203
  "Watching:\n " + Array.from(currentTargets).map((p) => path4.relative(process.cwd(), p)).join("\n ")
901
1204
  )
902
1205
  );
903
1206
  }
904
- watcher.on("add", (p) => trigger(p)).on("change", (p) => trigger(p)).on("unlink", (p) => trigger(p)).on("error", (err) => console.error(chalk2.red("Watcher error:"), err));
1207
+ watcher.on("add", (p) => trigger(p)).on("change", (p) => trigger(p)).on("unlink", (p) => trigger(p)).on("error", (err) => console.error(chalk3.red("Watcher error:"), err));
905
1208
  await run();
906
1209
  });
907
1210
  program.command("init").description("Scaffold a drzl.config.ts").option("-y, --yes", "accept defaults").action(async (_opts) => {
@@ -921,9 +1224,9 @@ program.command("init").description("Scaffold a drzl.config.ts").option("-y, --y
921
1224
  `;
922
1225
  try {
923
1226
  await fs2.writeFile(target, template, { flag: "wx" });
924
- console.log(chalk2.green(`Created ${target}`));
1227
+ console.log(chalk3.green(`Created ${target}`));
925
1228
  } catch (e) {
926
- console.error(chalk2.red("Init failed:"), e?.message ?? e);
1229
+ console.error(chalk3.red("Init failed:"), e?.message ?? e);
927
1230
  process.exit(1);
928
1231
  }
929
1232
  });
@@ -931,13 +1234,14 @@ function reportWideColumns(issues) {
931
1234
  const wide = issues.filter((i) => i.code === "DRZL_ANL_UNKNOWN_COLUMN");
932
1235
  if (!wide.length) return;
933
1236
  console.warn(
934
- chalk2.yellow(`
1237
+ chalk3.yellow(`
935
1238
  ${wide.length} column${wide.length === 1 ? "" : "s"} could not be typed:`)
936
1239
  );
937
- for (const i of wide.slice(0, 10)) console.warn(chalk2.gray(` - ${i.message}`));
938
- if (wide.length > 10) console.warn(chalk2.gray(` ... and ${wide.length - 10} more`));
1240
+ for (const i of wide.slice(0, 10)) console.warn(chalk3.gray(` - ${i.message}`));
1241
+ if (wide.length > 10) console.warn(chalk3.gray(` ... and ${wide.length - 10} more`));
939
1242
  const hints = [...new Set(wide.map((i) => i.hint).filter(Boolean))];
940
- for (const h of hints) console.warn(chalk2.gray(` ${h}`));
1243
+ for (const h of hints) console.warn(chalk3.gray(` ${h}`));
1244
+ console.warn(chalk3.gray(" Run `drzl doctor` for the full report."));
941
1245
  }
942
1246
  program.parseAsync(process.argv);
943
1247
  //# sourceMappingURL=cli.js.map