@drzl/cli 0.1.0 → 0.3.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.cjs CHANGED
@@ -24,14 +24,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/cli.ts
27
- var import_commander = require("commander");
27
+ var import_analyzer = require("@drzl/analyzer");
28
+ var import_generator_orpc = require("@drzl/generator-orpc");
28
29
  var import_chalk = __toESM(require("chalk"), 1);
29
- var import_ora = __toESM(require("ora"), 1);
30
+ var import_chokidar = __toESM(require("chokidar"), 1);
30
31
  var import_cli_progress = __toESM(require("cli-progress"), 1);
32
+ var import_commander = require("commander");
33
+ var path2 = __toESM(require("path"), 1);
34
+ var import_ora = __toESM(require("ora"), 1);
31
35
 
32
36
  // src/config.ts
37
+ var fs = __toESM(require("fs"), 1);
38
+ var import_node_module = require("module");
39
+ var path = __toESM(require("path"), 1);
33
40
  var import_zod = require("zod");
34
- var import_meta = {};
35
41
  var NamingSchema = import_zod.z.object({
36
42
  routerSuffix: import_zod.z.string().default("Router"),
37
43
  procedureCase: import_zod.z.enum(["camel", "kebab", "snake"]).default("camel")
@@ -55,7 +61,7 @@ var GeneratorSchema = import_zod.z.object({
55
61
  dataAccess: import_zod.z.enum(["stub", "drizzle"]).default("stub").optional(),
56
62
  dbImportPath: import_zod.z.string().optional(),
57
63
  schemaImportPath: import_zod.z.string().optional(),
58
- // zod generator specific options
64
+ // zod/valibot/arktype generator specific options
59
65
  schemaSuffix: import_zod.z.string().optional(),
60
66
  fileSuffix: import_zod.z.string().optional(),
61
67
  // orpc validation sharing
@@ -68,14 +74,15 @@ var GeneratorSchema = import_zod.z.object({
68
74
  // template options
69
75
  templateOptions: import_zod.z.record(import_zod.z.string(), import_zod.z.any()).optional()
70
76
  });
77
+ var AnalyzerSchema = import_zod.z.object({
78
+ includeRelations: import_zod.z.boolean().default(true),
79
+ validateConstraints: import_zod.z.boolean().default(true),
80
+ includeHeuristicRelations: import_zod.z.boolean().default(false)
81
+ });
71
82
  var ConfigSchema = import_zod.z.object({
72
83
  schema: import_zod.z.string(),
73
84
  outDir: import_zod.z.string().default("src/api"),
74
- analyzer: import_zod.z.object({
75
- includeRelations: import_zod.z.boolean().default(true),
76
- validateConstraints: import_zod.z.boolean().default(true),
77
- includeHeuristicRelations: import_zod.z.boolean().default(false)
78
- }).default({
85
+ analyzer: AnalyzerSchema.default({
79
86
  includeRelations: true,
80
87
  validateConstraints: true,
81
88
  includeHeuristicRelations: false
@@ -83,55 +90,99 @@ var ConfigSchema = import_zod.z.object({
83
90
  generators: import_zod.z.array(GeneratorSchema).min(1).default([{ kind: "orpc" }])
84
91
  });
85
92
  async function loadConfig(customPath) {
86
- const path = await import("path");
87
- const fs = await import("fs/promises");
88
- const candidates = customPath ? [customPath] : ["drzl.config.ts", "drzl.config.mjs", "drzl.config.js"];
93
+ const fsp = await import("fs/promises");
94
+ const candidates = customPath ? [customPath] : [
95
+ "drzl.config.ts",
96
+ "drzl.config.mjs",
97
+ "drzl.config.js",
98
+ "drzl.config.cjs",
99
+ "drzl.config.json"
100
+ ];
89
101
  for (const c of candidates) {
90
102
  const p = path.resolve(process.cwd(), c);
91
103
  try {
92
- await fs.access(p);
104
+ await fsp.access(p);
93
105
  } catch {
94
106
  continue;
95
107
  }
96
- if (/\.json$/i.test(p)) {
97
- try {
98
- const content = await fs.readFile(p, "utf8");
99
- const raw = JSON.parse(content);
100
- const parsed = ConfigSchema.parse(raw);
101
- return parsed;
102
- } catch (e2) {
103
- throw new Error(`Failed to load config from ${p}: ${String(e2)}`);
104
- }
108
+ const ext = path.extname(p).toLowerCase();
109
+ if (ext === ".json") {
110
+ const raw2 = JSON.parse(await fsp.readFile(p, "utf8"));
111
+ return ConfigSchema.parse(raw2);
105
112
  }
113
+ const { createJiti } = await import("jiti");
114
+ const stat = await fsp.stat(p);
115
+ const base = typeof __filename !== "undefined" ? __filename : path.join(process.cwd(), "index.js");
116
+ const jiti = createJiti(base, {
117
+ moduleCache: false,
118
+ // re-evaluate each time
119
+ fsCache: true,
120
+ // keep transform cache
121
+ cacheVersion: String(stat.mtimeMs),
122
+ // bump on edit
123
+ interopDefault: true,
124
+ tryNative: false
125
+ // <— prevent native import of .ts
126
+ // debug: true,
127
+ });
128
+ const mod = await jiti.import(p);
129
+ const raw = mod?.default ?? mod;
130
+ return ConfigSchema.parse(raw);
131
+ }
132
+ return null;
133
+ }
134
+ function computeGeneratorOutputDirs(cfg, cwd = process.cwd()) {
135
+ const abs = (p) => path.resolve(cwd, p);
136
+ const dirs = /* @__PURE__ */ new Set();
137
+ dirs.add(abs(cfg.outDir));
138
+ for (const g of cfg.generators) {
139
+ if (g.kind === "service") dirs.add(abs(g.path ?? "src/services"));
140
+ if (g.kind === "zod") dirs.add(abs(g.path ?? "src/validators/zod"));
141
+ if (g.kind === "valibot") dirs.add(abs(g.path ?? "src/validators/valibot"));
142
+ if (g.kind === "arktype") dirs.add(abs(g.path ?? "src/validators/arktype"));
143
+ }
144
+ return [...dirs];
145
+ }
146
+ function resolveTemplateDirsSync(cfg, cwd = process.cwd()) {
147
+ const results = [];
148
+ const req = (0, import_node_module.createRequire)(
149
+ typeof __filename !== "undefined" ? __filename : path.join(process.cwd(), "index.js")
150
+ );
151
+ for (const g of cfg.generators) {
152
+ const t = g.template;
153
+ if (!t || t === "standard" || t === "minimal") continue;
154
+ let pkgDir = null;
106
155
  try {
107
- const { createJiti } = await import("jiti");
108
- const jit = createJiti(import_meta.url);
109
- const mod = await jit.import(p);
110
- const raw = mod && typeof mod === "object" && "default" in mod ? mod.default : mod;
111
- const parsed = ConfigSchema.safeParse(raw);
112
- if (!parsed.success) {
113
- throw new Error(parsed.error.message);
114
- }
115
- return parsed.data;
116
- } catch (e) {
117
- console.error(`jiti failed to load ${p}:`, e);
118
- try {
119
- const content = await fs.readFile(p, "utf8");
120
- const raw = JSON.parse(content);
121
- const parsed = ConfigSchema.parse(raw);
122
- return parsed;
123
- } catch (e2) {
124
- throw new Error(`Failed to load config from ${p}: ${String(e2)}`);
125
- }
156
+ const pkg = req.resolve(`${t}/package.json`, { paths: [cwd] });
157
+ pkgDir = path.dirname(pkg);
158
+ } catch {
159
+ }
160
+ if (pkgDir) {
161
+ results.push(pkgDir);
162
+ continue;
163
+ }
164
+ if (/[./\\]/.test(t)) {
165
+ const abs = path.resolve(cwd, t);
166
+ if (fs.existsSync(abs)) results.push(abs);
126
167
  }
127
168
  }
128
- return null;
169
+ return Array.from(new Set(results));
170
+ }
171
+ function computeWatchTargets(cfg, cwd = process.cwd()) {
172
+ const abs = (p) => path.resolve(cwd, p);
173
+ const schemaAbs = abs(cfg.schema);
174
+ const targets = /* @__PURE__ */ new Set([
175
+ path.join(path.dirname(schemaAbs), "**/*.{ts,tsx,js}"),
176
+ abs("drzl.config.ts"),
177
+ abs("drzl.config.js"),
178
+ abs("drzl.config.mjs"),
179
+ abs("drzl.config.cjs")
180
+ ]);
181
+ for (const t of resolveTemplateDirsSync(cfg, cwd)) targets.add(t);
182
+ return [...targets];
129
183
  }
130
184
 
131
185
  // src/cli.ts
132
- var import_analyzer = require("@drzl/analyzer");
133
- var import_generator_orpc = require("@drzl/generator-orpc");
134
- var import_chokidar = __toESM(require("chokidar"), 1);
135
186
  var program = new import_commander.Command();
136
187
  program.name("drzl").description("DRZL - Drizzle Developer Toolkit").version("0.0.1");
137
188
  program.command("analyze").argument("<schema>", "path to drizzle schema (TS)").option("--relations", "include relations", true).option("--validate", "validate constraints", true).option("--out <file>", "write analysis JSON to file").option("--json", "print JSON to stdout (overrides --out)", false).action(async (schema, opts) => {
@@ -148,8 +199,8 @@ program.command("analyze").argument("<schema>", "path to drizzle schema (TS)").o
148
199
  if (opts.json) {
149
200
  console.log(json);
150
201
  } else if (opts.out) {
151
- const fs = await import("fs/promises");
152
- await fs.writeFile(opts.out, json, "utf8");
202
+ const fs2 = await import("fs/promises");
203
+ await fs2.writeFile(opts.out, json, "utf8");
153
204
  spinner?.succeed(import_chalk.default.green(`Analysis written to ${opts.out} in ${ms}ms`));
154
205
  } else {
155
206
  spinner?.succeed(import_chalk.default.green(`Analyzed in ${ms}ms`));
@@ -338,21 +389,84 @@ program.command("generate:orpc").argument("<schema>", "path to drizzle schema (T
338
389
  process.exit(1);
339
390
  }
340
391
  });
341
- 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).action(async (opts) => {
342
- const cfg = await loadConfig(opts.config);
392
+ 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) => {
393
+ let cfg = await loadConfig(opts.config);
343
394
  if (!cfg) {
344
395
  console.error(import_chalk.default.red("No config found. Create drzl.config.ts or pass --config."));
345
396
  process.exit(2);
346
397
  return;
347
398
  }
399
+ const abs = (p) => path2.resolve(process.cwd(), p);
400
+ const isInside = (child, parent) => {
401
+ const rel = path2.relative(parent, child);
402
+ return !!rel && !rel.startsWith("..") && !path2.isAbsolute(rel);
403
+ };
404
+ const ignoredOutDirs = new Set(computeGeneratorOutputDirs(cfg).map(abs));
405
+ const currentTargets = new Set(computeWatchTargets(cfg).map(abs));
406
+ const syncWatcherTargets = (watcher2, next) => {
407
+ const add = [];
408
+ const del = [];
409
+ for (const p of next) if (!currentTargets.has(p)) add.push(p);
410
+ for (const p of currentTargets) if (!next.has(p)) del.push(p);
411
+ if (add.length) watcher2.add(add);
412
+ if (del.length) watcher2.unwatch(del);
413
+ currentTargets.clear();
414
+ next.forEach((p) => currentTargets.add(p));
415
+ };
416
+ const rebuildIgnoreDirsFrom = (cfgNow) => {
417
+ ignoredOutDirs.clear();
418
+ for (const d of computeGeneratorOutputDirs(cfgNow)) ignoredOutDirs.add(abs(d));
419
+ };
420
+ const ignoredFn = (p) => {
421
+ const full = abs(p);
422
+ for (const dir of ignoredOutDirs) {
423
+ if (full === dir || isInside(full, dir)) return true;
424
+ }
425
+ return false;
426
+ };
427
+ const watcher = import_chokidar.default.watch(Array.from(currentTargets), {
428
+ ignoreInitial: true,
429
+ awaitWriteFinish: { stabilityThreshold: 400, pollInterval: 50 },
430
+ usePolling: !!opts.poll,
431
+ ignored: ignoredFn
432
+ });
433
+ const logTrigger = (type, file) => {
434
+ if (opts.json) console.log(JSON.stringify({ event: "trigger", type, file }));
435
+ };
436
+ watcher.on("add", (p) => {
437
+ logTrigger("add", p);
438
+ trigger(p);
439
+ }).on("change", (p) => {
440
+ logTrigger("change", p);
441
+ trigger(p);
442
+ }).on("unlink", (p) => {
443
+ logTrigger("unlink", p);
444
+ trigger(p);
445
+ });
348
446
  let lastFiles = [];
349
447
  const run = async () => {
350
448
  try {
449
+ const reloaded = await loadConfig(opts.config);
450
+ if (!reloaded) throw new Error("Config disappeared during watch.");
451
+ cfg = reloaded;
452
+ rebuildIgnoreDirsFrom(cfg);
453
+ const nextTargets = new Set(computeWatchTargets(cfg).map(abs));
454
+ syncWatcherTargets(watcher, nextTargets);
351
455
  if (!opts.json) console.clear();
456
+ if (opts.json) {
457
+ console.log(
458
+ JSON.stringify({
459
+ event: "watch_config_applied",
460
+ targets: Array.from(currentTargets),
461
+ ignored: Array.from(ignoredOutDirs)
462
+ })
463
+ );
464
+ }
352
465
  const analyzer = new import_analyzer.SchemaAnalyzer(cfg.schema);
353
466
  const analysis = await analyzer.analyze({
354
467
  includeRelations: cfg.analyzer.includeRelations,
355
- validateConstraints: cfg.analyzer.validateConstraints
468
+ validateConstraints: cfg.analyzer.validateConstraints,
469
+ includeHeuristicRelations: cfg.analyzer.includeHeuristicRelations
356
470
  });
357
471
  if (opts.pipeline === "analyze") {
358
472
  if (opts.json) {
@@ -370,62 +484,174 @@ program.command("watch").description("Watch schema and regenerate on changes").o
370
484
  }
371
485
  const newFiles = [];
372
486
  for (const g of cfg.generators) {
373
- if (g.kind === "orpc" && (opts.pipeline === "all" || opts.pipeline === "generate-orpc")) {
487
+ if (opts.pipeline !== "all" && !(opts.pipeline === "generate-orpc" && g.kind === "orpc")) {
488
+ continue;
489
+ }
490
+ if (g.kind === "orpc") {
374
491
  const gen = new import_generator_orpc.ORPCGenerator(analysis);
375
492
  const { files } = await gen.generate({
376
493
  outputDir: cfg.outDir,
377
494
  template: g.template,
378
495
  includeRelations: g.includeRelations,
379
- naming: g.naming
496
+ naming: g.naming,
497
+ outputHeader: g.outputHeader,
498
+ format: g.format,
499
+ templateOptions: g.templateOptions,
500
+ validation: g.validation
380
501
  });
381
- if (opts.json) {
382
- console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files }));
383
- } else {
384
- console.log(
385
- import_chalk.default.green(`Generated (${g.kind}):`),
502
+ opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
503
+ import_chalk.default.green(`Generated (${g.kind}):`),
504
+ files.map((f) => import_chalk.default.cyan(f)).join(", ")
505
+ );
506
+ newFiles.push(...files);
507
+ } else if (g.kind === "service") {
508
+ try {
509
+ const { ServiceGenerator } = await import("@drzl/generator-service");
510
+ const gen = new ServiceGenerator(analysis);
511
+ const target = g.path ?? "src/services";
512
+ const files = await gen.generate({
513
+ outDir: target,
514
+ outputHeader: g.outputHeader,
515
+ format: g.format,
516
+ dataAccess: g.dataAccess,
517
+ dbImportPath: g.dbImportPath,
518
+ schemaImportPath: g.schemaImportPath
519
+ });
520
+ opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
521
+ import_chalk.default.green(`Generated (service): ${files.length} files`),
386
522
  files.map((f) => import_chalk.default.cyan(f)).join(", ")
387
523
  );
524
+ newFiles.push(...files);
525
+ } catch (e) {
526
+ console.error(
527
+ import_chalk.default.red("Service generator missing."),
528
+ import_chalk.default.yellow("\nInstall with: npm install @drzl/generator-service")
529
+ );
530
+ console.error(import_chalk.default.gray("Error details:"), e?.message ?? e);
531
+ return;
532
+ }
533
+ } else if (g.kind === "zod") {
534
+ try {
535
+ const { ZodGenerator } = await import("@drzl/generator-zod");
536
+ const gen = new ZodGenerator(analysis);
537
+ const target = g.path ?? "src/validators/zod";
538
+ const files = await gen.generate({
539
+ outDir: target,
540
+ outputHeader: g.outputHeader,
541
+ format: g.format,
542
+ schemaSuffix: g.schemaSuffix,
543
+ fileSuffix: g.fileSuffix
544
+ });
545
+ opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
546
+ import_chalk.default.green(`Generated (zod): ${files.length} files`),
547
+ files.map((f) => import_chalk.default.cyan(f)).join(", ")
548
+ );
549
+ newFiles.push(...files);
550
+ } catch (e) {
551
+ console.error(
552
+ import_chalk.default.red("Zod generator missing."),
553
+ import_chalk.default.yellow("\nInstall with: npm install @drzl/generator-zod")
554
+ );
555
+ console.error(import_chalk.default.gray("Error details:"), e?.message ?? e);
556
+ return;
557
+ }
558
+ } else if (g.kind === "valibot") {
559
+ try {
560
+ const { ValibotGenerator } = await import("@drzl/generator-valibot");
561
+ const gen = new ValibotGenerator(analysis);
562
+ const target = g.path ?? "src/validators/valibot";
563
+ const files = await gen.generate({
564
+ outDir: target,
565
+ outputHeader: g.outputHeader,
566
+ format: g.format,
567
+ schemaSuffix: g.schemaSuffix,
568
+ fileSuffix: g.fileSuffix
569
+ });
570
+ opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
571
+ import_chalk.default.green(`Generated (valibot): ${files.length} files`),
572
+ files.map((f) => import_chalk.default.cyan(f)).join(", ")
573
+ );
574
+ newFiles.push(...files);
575
+ } catch (e) {
576
+ console.error(
577
+ import_chalk.default.red("Valibot generator missing."),
578
+ import_chalk.default.yellow("\nInstall with: npm install @drzl/generator-valibot")
579
+ );
580
+ console.error(import_chalk.default.gray("Error details:"), e?.message ?? e);
581
+ return;
582
+ }
583
+ } else if (g.kind === "arktype") {
584
+ try {
585
+ const { ArkTypeGenerator } = await import("@drzl/generator-arktype");
586
+ const gen = new ArkTypeGenerator(analysis);
587
+ const target = g.path ?? "src/validators/arktype";
588
+ const files = await gen.generate({
589
+ outDir: target,
590
+ outputHeader: g.outputHeader,
591
+ format: g.format,
592
+ schemaSuffix: g.schemaSuffix,
593
+ fileSuffix: g.fileSuffix
594
+ });
595
+ opts.json ? console.log(JSON.stringify({ event: "generate_complete", kind: g.kind, files })) : console.log(
596
+ import_chalk.default.green(`Generated (arktype): ${files.length} files`),
597
+ files.map((f) => import_chalk.default.cyan(f)).join(", ")
598
+ );
599
+ newFiles.push(...files);
600
+ } catch (e) {
601
+ console.error(
602
+ import_chalk.default.red("ArkType generator missing."),
603
+ import_chalk.default.yellow("\nInstall with: npm install @drzl/generator-arktype")
604
+ );
605
+ console.error(import_chalk.default.gray("Error details:"), e?.message ?? e);
606
+ return;
388
607
  }
389
- newFiles.push(...files);
390
608
  }
391
609
  }
392
610
  const added = newFiles.filter((f) => !lastFiles.includes(f));
393
611
  const removed = lastFiles.filter((f) => !newFiles.includes(f));
394
- if (opts.json) {
395
- console.log(JSON.stringify({ event: "diff", added, removed }));
396
- } else {
612
+ opts.json ? console.log(JSON.stringify({ event: "diff", added, removed })) : (() => {
397
613
  if (added.length) console.log(import_chalk.default.blue(`Added: ${added.join(", ")}`));
398
614
  if (removed.length) console.log(import_chalk.default.yellow(`Removed: ${removed.join(", ")}`));
399
- }
615
+ })();
400
616
  lastFiles = newFiles;
401
617
  } catch (e) {
402
- if (opts.json)
403
- console.log(JSON.stringify({ event: "error", message: String(e?.message ?? e) }));
404
- else console.error(import_chalk.default.red("Watch pipeline failed:"), e?.message ?? e);
618
+ opts.json ? console.log(JSON.stringify({ event: "error", message: String(e?.message ?? e) })) : console.error(import_chalk.default.red("Watch pipeline failed:"), e?.message ?? e);
405
619
  }
406
620
  };
407
621
  const debounced = Number(opts.debounce) || 200;
408
622
  let timer = null;
409
623
  const trigger = (file) => {
410
- if (file && file.startsWith(cfg.outDir)) return;
411
- clearTimeout(timer);
624
+ if (file) {
625
+ const full = abs(file);
626
+ for (const dir of ignoredOutDirs) {
627
+ if (full === dir || isInside(full, dir)) return;
628
+ }
629
+ }
630
+ if (timer) clearTimeout(timer);
412
631
  timer = setTimeout(run, debounced);
413
632
  };
414
- console.log(import_chalk.default.gray("Watching for changes..."));
415
- const watchSet = /* @__PURE__ */ new Set([cfg.schema]);
416
- for (const g of cfg.generators) {
417
- if (g.template && g.template !== "standard" && g.template !== "minimal") {
418
- watchSet.add(g.template);
419
- }
633
+ if (opts.json) {
634
+ console.log(
635
+ JSON.stringify({
636
+ event: "watching",
637
+ targets: Array.from(currentTargets),
638
+ ignored: Array.from(ignoredOutDirs)
639
+ })
640
+ );
641
+ } else {
642
+ console.log(
643
+ import_chalk.default.gray(
644
+ "Watching:\n " + Array.from(currentTargets).map((p) => path2.relative(process.cwd(), p)).join("\n ")
645
+ )
646
+ );
420
647
  }
421
- watchSet.add(cfg.outDir);
422
- import_chokidar.default.watch(Array.from(watchSet), { ignoreInitial: true }).on("add", (p) => trigger(p)).on("change", (p) => trigger(p)).on("unlink", (p) => trigger(p));
648
+ watcher.on("add", (p) => trigger(p)).on("change", (p) => trigger(p)).on("unlink", (p) => trigger(p)).on("error", (err) => console.error(import_chalk.default.red("Watcher error:"), err));
423
649
  await run();
424
650
  });
425
651
  program.command("init").description("Scaffold a drzl.config.ts").option("-y, --yes", "accept defaults").action(async (_opts) => {
426
- const fs = await import("fs/promises");
427
- const path = await import("path");
428
- const target = path.resolve(process.cwd(), "drzl.config.ts");
652
+ const fs2 = await import("fs/promises");
653
+ const path3 = await import("path");
654
+ const target = path3.resolve(process.cwd(), "drzl.config.ts");
429
655
  const template = `export default {
430
656
  schema: 'src/db/schema.ts',
431
657
  outDir: 'src/api',
@@ -436,7 +662,7 @@ program.command("init").description("Scaffold a drzl.config.ts").option("-y, --y
436
662
  } as const
437
663
  `;
438
664
  try {
439
- await fs.writeFile(target, template, { flag: "wx" });
665
+ await fs2.writeFile(target, template, { flag: "wx" });
440
666
  console.log(import_chalk.default.green(`Created ${target}`));
441
667
  } catch (e) {
442
668
  console.error(import_chalk.default.red("Init failed:"), e?.message ?? e);