@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/cli.js CHANGED
@@ -3,8 +3,9 @@ import {
3
3
  computeGeneratorOutputDirs,
4
4
  computeWatchTargets,
5
5
  filterTables,
6
- loadConfig
7
- } from "./chunk-HGD5CBM5.js";
6
+ loadConfig,
7
+ trpcOutDir
8
+ } from "./chunk-K4J4XIFO.js";
8
9
 
9
10
  // src/cli.ts
10
11
  import { SchemaAnalyzer } from "@drzl/analyzer";
@@ -16,6 +17,25 @@ import { Command } from "commander";
16
17
  import * as path4 from "path";
17
18
  import ora from "ora";
18
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
+
19
39
  // src/validation-options.ts
20
40
  function validationOptions(g, cfg, outDir, caps = {}) {
21
41
  return {
@@ -29,6 +49,8 @@ function validationOptions(g, cfg, outDir, caps = {}) {
29
49
  coerceDates: g.coerceDates,
30
50
  applyDefaults: g.applyDefaults,
31
51
  duplicateFinder: g.duplicateFinder,
52
+ nestedSchemas: g.nestedSchemas,
53
+ nestedDepth: g.nestedDepth,
32
54
  // Only where the generator can act on them, so an unsupported option is absent rather than
33
55
  // present and ignored.
34
56
  ...caps.schemaTypes ? {
@@ -319,12 +341,34 @@ program.command("generate").description("Run configured generators (drzl.config.
319
341
  templateOptions: g.templateOptions,
320
342
  importExtension: g.importExtension,
321
343
  validation: g.validation,
344
+ // Documented on this generator since it was added and never reachable from a config
345
+ // file, because the config schema had no such key and zod stripped it in silence.
346
+ databaseInjection: g.databaseInjection,
322
347
  servicesDir,
323
348
  onProgress: ({ index }) => progress.update(index)
324
349
  });
325
350
  progress.stop();
326
351
  ora().succeed(chalk2.green(`Generated (${g.kind}): ${files.length} files`));
327
352
  files.forEach((f) => console.log(" -", chalk2.cyan(f)));
353
+ } else if (g.kind === "trpc") {
354
+ try {
355
+ const { TRPCGenerator } = await loadGenerator(
356
+ "@drzl/generator-trpc",
357
+ () => import("./dist-XBGVORL3.js")
358
+ );
359
+ const gen = new TRPCGenerator(analysis);
360
+ const { files } = await gen.generate({
361
+ ...trpcOptions(g, cfg, servicesDir),
362
+ onProgress: ({ index }) => progress.update(index)
363
+ });
364
+ progress.stop();
365
+ ora().succeed(chalk2.green(`Generated (trpc): ${files.length} files`));
366
+ files.forEach((f) => console.log(" -", chalk2.cyan(f)));
367
+ } catch (e) {
368
+ progress.stop();
369
+ reportGeneratorFailure(g.kind, e);
370
+ process.exit(1);
371
+ }
328
372
  } else if (g.kind === "service") {
329
373
  try {
330
374
  const { ServiceGenerator } = await loadGenerator(
@@ -340,7 +384,12 @@ program.command("generate").description("Run configured generators (drzl.config.
340
384
  dataAccess: g.dataAccess,
341
385
  dbImportPath: g.dbImportPath,
342
386
  schemaImportPath: g.schemaImportPath,
343
- importExtension: g.importExtension
387
+ importExtension: g.importExtension,
388
+ // The other half of `databaseInjection`. A router generator in injection mode
389
+ // emits `Service.getById(ctx.db, id)`, and only a service generated in the same
390
+ // mode has a `db` parameter to receive it. This branch never passed the option, so
391
+ // the two halves of one generated project disagreed about the signature.
392
+ databaseInjection: g.databaseInjection
344
393
  });
345
394
  progress.stop();
346
395
  ora().succeed(chalk2.green(`Generated (service): ${files.length} files`));
@@ -505,7 +554,34 @@ program.command("generate:orpc").argument("<schema>", "path to drizzle schema (T
505
554
  process.exit(1);
506
555
  }
507
556
  });
508
- 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", "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) => {
557
+ program.command("generate:trpc").argument("<schema>", "path to drizzle schema (TS)").option("-o, --outDir <dir>", "output directory", "src/api").option("--template <name>", "standard | service", "standard").option("--includeRelations", "include relation endpoints").option("--servicesDir <dir>", "where the service generator writes", "src/services").action(async (schema, opts) => {
558
+ try {
559
+ const analyzer = new SchemaAnalyzer(schema);
560
+ const analysis = await analyzer.analyze({
561
+ includeRelations: !!opts.includeRelations,
562
+ validateConstraints: true
563
+ });
564
+ const { TRPCGenerator } = await loadGenerator(
565
+ "@drzl/generator-trpc",
566
+ () => import("./dist-XBGVORL3.js")
567
+ );
568
+ const gen = new TRPCGenerator(analysis);
569
+ const { files } = await gen.generate({
570
+ outputDir: opts.outDir,
571
+ template: opts.template,
572
+ includeRelations: !!opts.includeRelations,
573
+ // Only consulted by `--template service`, and passed unconditionally so this command
574
+ // cannot become the branch that forgets it.
575
+ servicesDir: opts.servicesDir
576
+ });
577
+ console.log(chalk2.green(`Generated:`), files.map((f) => chalk2.cyan(f)).join(", "));
578
+ maybeShowSponsorMessage({ reason: "generate:trpc" });
579
+ } catch (e) {
580
+ reportGeneratorFailure("trpc", e);
581
+ process.exit(1);
582
+ }
583
+ });
584
+ 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) => {
509
585
  let cfg = await loadConfig(opts.config);
510
586
  if (!cfg) {
511
587
  console.error(chalk2.red("No config found. Create drzl.config.ts or pass --config."));
@@ -605,8 +681,13 @@ program.command("watch").description("Watch schema and regenerate on changes").o
605
681
  return;
606
682
  }
607
683
  const newFiles = [];
684
+ const servicesDir = cfg.generators.find((x) => x.kind === "service")?.path ?? "src/services";
685
+ const PIPELINE_KINDS = {
686
+ "generate-orpc": "orpc",
687
+ "generate-trpc": "trpc"
688
+ };
608
689
  for (const g of cfg.generators) {
609
- if (opts.pipeline !== "all" && !(opts.pipeline === "generate-orpc" && g.kind === "orpc")) {
690
+ if (opts.pipeline !== "all" && PIPELINE_KINDS[opts.pipeline] !== g.kind) {
610
691
  continue;
611
692
  }
612
693
  if (g.kind === "orpc") {
@@ -620,13 +701,32 @@ program.command("watch").description("Watch schema and regenerate on changes").o
620
701
  format: g.format,
621
702
  templateOptions: g.templateOptions,
622
703
  importExtension: g.importExtension,
623
- validation: g.validation
704
+ validation: g.validation,
705
+ databaseInjection: g.databaseInjection,
706
+ servicesDir
624
707
  });
625
708
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
626
709
  chalk2.green(`Generated (${g.kind}):`),
627
710
  files.map((f) => chalk2.cyan(f)).join(", ")
628
711
  );
629
712
  newFiles.push(...files);
713
+ } else if (g.kind === "trpc") {
714
+ try {
715
+ const { TRPCGenerator } = await loadGenerator(
716
+ "@drzl/generator-trpc",
717
+ () => import("./dist-XBGVORL3.js")
718
+ );
719
+ const gen = new TRPCGenerator(analysis);
720
+ const { files } = await gen.generate(trpcOptions(g, cfg, servicesDir));
721
+ 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(", ")
724
+ );
725
+ newFiles.push(...files);
726
+ } catch (e) {
727
+ reportGeneratorFailure(g.kind, e);
728
+ return;
729
+ }
630
730
  } else if (g.kind === "service") {
631
731
  try {
632
732
  const { ServiceGenerator } = await loadGenerator(
@@ -642,7 +742,8 @@ program.command("watch").description("Watch schema and regenerate on changes").o
642
742
  dataAccess: g.dataAccess,
643
743
  dbImportPath: g.dbImportPath,
644
744
  schemaImportPath: g.schemaImportPath,
645
- importExtension: g.importExtension
745
+ importExtension: g.importExtension,
746
+ databaseInjection: g.databaseInjection
646
747
  });
647
748
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
648
749
  chalk2.green(`Generated (service): ${files.length} files`),
@@ -661,15 +762,9 @@ program.command("watch").description("Watch schema and regenerate on changes").o
661
762
  );
662
763
  const gen = new ZodGenerator(analysis);
663
764
  const target = g.path ?? "src/validators/zod";
664
- const files = await gen.generate({
665
- outDir: target,
666
- outputHeader: g.outputHeader,
667
- format: g.format,
668
- schemaSuffix: g.schemaSuffix,
669
- fileSuffix: g.fileSuffix,
670
- importExtension: g.importExtension,
671
- affix: g.affix
672
- });
765
+ const files = await gen.generate(
766
+ validationOptions(g, cfg, target, { schemaTypes: true })
767
+ );
673
768
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
674
769
  chalk2.green(`Generated (zod): ${files.length} files`),
675
770
  files.map((f) => chalk2.cyan(f)).join(", ")
@@ -687,15 +782,9 @@ program.command("watch").description("Watch schema and regenerate on changes").o
687
782
  );
688
783
  const gen = new ValibotGenerator(analysis);
689
784
  const target = g.path ?? "src/validators/valibot";
690
- const files = await gen.generate({
691
- outDir: target,
692
- outputHeader: g.outputHeader,
693
- format: g.format,
694
- schemaSuffix: g.schemaSuffix,
695
- fileSuffix: g.fileSuffix,
696
- importExtension: g.importExtension,
697
- affix: g.affix
698
- });
785
+ const files = await gen.generate(
786
+ validationOptions(g, cfg, target, { schemaTypes: true })
787
+ );
699
788
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
700
789
  chalk2.green(`Generated (valibot): ${files.length} files`),
701
790
  files.map((f) => chalk2.cyan(f)).join(", ")
@@ -713,17 +802,54 @@ program.command("watch").description("Watch schema and regenerate on changes").o
713
802
  );
714
803
  const gen = new ArkTypeGenerator(analysis);
715
804
  const target = g.path ?? "src/validators/arktype";
805
+ const files = await gen.generate(
806
+ validationOptions(g, cfg, target, { schemaTypes: false })
807
+ );
808
+ 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(", ")
811
+ );
812
+ newFiles.push(...files);
813
+ } catch (e) {
814
+ reportGeneratorFailure(g.kind, e);
815
+ return;
816
+ }
817
+ } else if (g.kind === "typebox") {
818
+ try {
819
+ const { TypeBoxGenerator } = await loadGenerator(
820
+ "@drzl/generator-typebox",
821
+ () => import("@drzl/generator-typebox")
822
+ );
823
+ const gen = new TypeBoxGenerator(analysis);
824
+ const target = g.path ?? "src/validators/typebox";
825
+ const files = await gen.generate(
826
+ validationOptions(g, cfg, target, { schemaTypes: true })
827
+ );
828
+ 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(", ")
831
+ );
832
+ newFiles.push(...files);
833
+ } catch (e) {
834
+ reportGeneratorFailure(g.kind, e);
835
+ return;
836
+ }
837
+ } else if (g.kind === "json-schema") {
838
+ try {
839
+ const { JsonSchemaGenerator } = await loadGenerator(
840
+ "@drzl/generator-json-schema",
841
+ () => import("./dist-UE55LTXV.js")
842
+ );
843
+ const gen = new JsonSchemaGenerator(analysis);
844
+ const target = g.path ?? "src/validators/json-schema";
716
845
  const files = await gen.generate({
717
- outDir: target,
718
- outputHeader: g.outputHeader,
719
- format: g.format,
720
- schemaSuffix: g.schemaSuffix,
721
- fileSuffix: g.fileSuffix,
722
- importExtension: g.importExtension,
723
- affix: g.affix
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
724
850
  });
725
851
  opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
726
- chalk2.green(`Generated (arktype): ${files.length} files`),
852
+ chalk2.green(`Generated (json-schema): ${files.length} files`),
727
853
  files.map((f) => chalk2.cyan(f)).join(", ")
728
854
  );
729
855
  newFiles.push(...files);
@@ -787,6 +913,8 @@ program.command("init").description("Scaffold a drzl.config.ts").option("-y, --y
787
913
  outDir: 'src/api',
788
914
  analyzer: { includeRelations: true, validateConstraints: true },
789
915
  generators: [
916
+ // For tRPC instead: { kind: 'trpc', template: 'standard', includeRelations: true }
917
+ // To run both, give one of them its own \`path\`; they share \`outDir\` otherwise.
790
918
  { kind: 'orpc', template: 'standard', includeRelations: true }
791
919
  ]
792
920
  } as const