@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/README.md +4 -4
- package/dist/chunk-MEPFGJIF.js +164 -0
- package/dist/chunk-MEPFGJIF.js.map +1 -0
- package/dist/cli.cjs +305 -79
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +213 -35
- package/dist/cli.js.map +1 -1
- package/dist/config.cjs +100 -42
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +140 -0
- package/dist/config.d.ts +140 -0
- package/dist/config.js +11 -3
- package/package.json +16 -10
- package/dist/chunk-XVTVU3EC.js +0 -109
- package/dist/chunk-XVTVU3EC.js.map +0 -1
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
|
|
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
|
|
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:
|
|
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
|
|
87
|
-
const
|
|
88
|
-
|
|
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
|
|
104
|
+
await fsp.access(p);
|
|
93
105
|
} catch {
|
|
94
106
|
continue;
|
|
95
107
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
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
|
|
152
|
-
await
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
411
|
-
|
|
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
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
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
|
|
427
|
-
const
|
|
428
|
-
const target =
|
|
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
|
|
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);
|