@forinda/kickjs-cli 1.2.0 → 1.2.2

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
@@ -22,7 +22,13 @@ import { fileURLToPath } from "url";
22
22
  // src/utils/fs.ts
23
23
  import { writeFile, mkdir, access, readFile } from "fs/promises";
24
24
  import { dirname } from "path";
25
+ var _dryRun = false;
26
+ function setDryRun(enabled) {
27
+ _dryRun = enabled;
28
+ }
29
+ __name(setDryRun, "setDryRun");
25
30
  async function writeFileSafe(filePath, content) {
31
+ if (_dryRun) return;
26
32
  await mkdir(dirname(filePath), {
27
33
  recursive: true
28
34
  });
@@ -1926,7 +1932,7 @@ function promptUser(question) {
1926
1932
  }
1927
1933
  __name(promptUser, "promptUser");
1928
1934
  async function generateModule(options) {
1929
- const { name, modulesDir, noEntity, noTests, repo = "inmemory", force } = options;
1935
+ const { name, modulesDir, noEntity, noTests, repo = "inmemory", force, dryRun } = options;
1930
1936
  let pattern = options.pattern ?? "ddd";
1931
1937
  if (options.minimal) pattern = "minimal";
1932
1938
  const kebab = toKebabCase(name);
@@ -1938,6 +1944,10 @@ async function generateModule(options) {
1938
1944
  let overwriteAll = force ?? false;
1939
1945
  const write = /* @__PURE__ */ __name(async (relativePath, content) => {
1940
1946
  const fullPath = join2(moduleDir, relativePath);
1947
+ if (dryRun) {
1948
+ files.push(fullPath);
1949
+ return;
1950
+ }
1941
1951
  if (!overwriteAll && await fileExists(fullPath)) {
1942
1952
  const answer = await promptUser(` File already exists: ${relativePath}
1943
1953
  Overwrite? (y/n/a = yes/no/all) `);
@@ -1979,7 +1989,9 @@ async function generateModule(options) {
1979
1989
  await generateDddFiles(ctx);
1980
1990
  break;
1981
1991
  }
1982
- await autoRegisterModule(modulesDir, pascal, plural);
1992
+ if (!dryRun) {
1993
+ await autoRegisterModule(modulesDir, pascal, plural);
1994
+ }
1983
1995
  return files;
1984
1996
  }
1985
1997
  __name(generateModule, "generateModule");
@@ -3299,13 +3311,19 @@ async function loadKickConfig(cwd) {
3299
3311
  __name(loadKickConfig, "loadKickConfig");
3300
3312
 
3301
3313
  // src/commands/generate.ts
3302
- function printGenerated(files) {
3314
+ function isDryRun(cmd) {
3315
+ return cmd.parent?.opts()?.dryRun ?? false;
3316
+ }
3317
+ __name(isDryRun, "isDryRun");
3318
+ function printGenerated(files, dryRun = false) {
3303
3319
  const cwd = process.cwd();
3320
+ const label = dryRun ? "Would generate" : "Generated";
3304
3321
  console.log(`
3305
- Generated ${files.length} file${files.length === 1 ? "" : "s"}:`);
3322
+ ${label} ${files.length} file${files.length === 1 ? "" : "s"}:`);
3306
3323
  for (const f of files) {
3307
3324
  console.log(` ${f.replace(cwd + "/", "")}`);
3308
3325
  }
3326
+ if (dryRun) console.log("\n (dry run \u2014 no files were written)");
3309
3327
  console.log();
3310
3328
  }
3311
3329
  __name(printGenerated, "printGenerated");
@@ -3369,14 +3387,16 @@ function printGeneratorList() {
3369
3387
  }
3370
3388
  __name(printGeneratorList, "printGeneratorList");
3371
3389
  function registerGenerateCommand(program) {
3372
- const gen = program.command("generate").alias("g").description("Generate code scaffolds").option("--list", "List all available generators").action((opts) => {
3390
+ const gen = program.command("generate").alias("g").description("Generate code scaffolds").option("--list", "List all available generators").option("--dry-run", "Preview files that would be generated without writing them").action((opts) => {
3373
3391
  if (opts.list) {
3374
3392
  printGeneratorList();
3375
3393
  } else {
3376
3394
  gen.help();
3377
3395
  }
3378
3396
  });
3379
- gen.command("module <name>").description("Generate a module (structure depends on project pattern)").option("--no-entity", "Skip entity and value object generation").option("--no-tests", "Skip test file generation").option("--repo <type>", "Repository implementation: inmemory | drizzle | prisma").option("--pattern <pattern>", "Override project pattern: rest | ddd | cqrs | minimal").option("--minimal", "Shorthand for --pattern minimal").option("--modules-dir <dir>", "Modules directory").option("-f, --force", "Overwrite existing files without prompting").action(async (name, opts) => {
3397
+ gen.command("module <name>").description("Generate a module (structure depends on project pattern)").option("--no-entity", "Skip entity and value object generation").option("--no-tests", "Skip test file generation").option("--repo <type>", "Repository implementation: inmemory | drizzle | prisma").option("--pattern <pattern>", "Override project pattern: rest | ddd | cqrs | minimal").option("--minimal", "Shorthand for --pattern minimal").option("--modules-dir <dir>", "Modules directory").option("-f, --force", "Overwrite existing files without prompting").action(async (name, opts, cmd) => {
3398
+ const dryRun = isDryRun(cmd);
3399
+ setDryRun(dryRun);
3380
3400
  const config = await loadKickConfig(process.cwd());
3381
3401
  const modulesDir = opts.modulesDir ?? config?.modulesDir ?? "src/modules";
3382
3402
  const repo = opts.repo ?? config?.defaultRepo ?? "inmemory";
@@ -3389,18 +3409,23 @@ function registerGenerateCommand(program) {
3389
3409
  repo,
3390
3410
  minimal: opts.minimal,
3391
3411
  force: opts.force,
3392
- pattern
3412
+ pattern,
3413
+ dryRun
3393
3414
  });
3394
- printGenerated(files);
3415
+ printGenerated(files, dryRun);
3395
3416
  });
3396
- gen.command("adapter <name>").description("Generate an AppAdapter with lifecycle hooks and middleware support").option("-o, --out <dir>", "Output directory", "src/adapters").action(async (name, opts) => {
3417
+ gen.command("adapter <name>").description("Generate an AppAdapter with lifecycle hooks and middleware support").option("-o, --out <dir>", "Output directory", "src/adapters").action(async (name, opts, cmd) => {
3418
+ const dryRun = isDryRun(cmd);
3419
+ setDryRun(dryRun);
3397
3420
  const files = await generateAdapter({
3398
3421
  name,
3399
3422
  outDir: resolve4(opts.out)
3400
3423
  });
3401
- printGenerated(files);
3424
+ printGenerated(files, dryRun);
3402
3425
  });
3403
- gen.command("middleware <name>").description("Generate an Express middleware function\n Use -m to scope it to a module: kick g middleware auth -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts) => {
3426
+ gen.command("middleware <name>").description("Generate an Express middleware function\n Use -m to scope it to a module: kick g middleware auth -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts, cmd) => {
3427
+ const dryRun = isDryRun(cmd);
3428
+ setDryRun(dryRun);
3404
3429
  const config = await loadKickConfig(process.cwd());
3405
3430
  const modulesDir = config?.modulesDir ?? "src/modules";
3406
3431
  const files = await generateMiddleware({
@@ -3410,9 +3435,11 @@ function registerGenerateCommand(program) {
3410
3435
  modulesDir,
3411
3436
  pattern: config?.pattern
3412
3437
  });
3413
- printGenerated(files);
3438
+ printGenerated(files, dryRun);
3414
3439
  });
3415
- gen.command("guard <name>").description("Generate a route guard (auth, roles, etc.)\n Use -m to scope it to a module: kick g guard admin -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts) => {
3440
+ gen.command("guard <name>").description("Generate a route guard (auth, roles, etc.)\n Use -m to scope it to a module: kick g guard admin -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts, cmd) => {
3441
+ const dryRun = isDryRun(cmd);
3442
+ setDryRun(dryRun);
3416
3443
  const config = await loadKickConfig(process.cwd());
3417
3444
  const modulesDir = config?.modulesDir ?? "src/modules";
3418
3445
  const files = await generateGuard({
@@ -3422,9 +3449,11 @@ function registerGenerateCommand(program) {
3422
3449
  modulesDir,
3423
3450
  pattern: config?.pattern
3424
3451
  });
3425
- printGenerated(files);
3452
+ printGenerated(files, dryRun);
3426
3453
  });
3427
- gen.command("service <name>").description("Generate a @Service() class\n Use -m to scope it to a module: kick g service payment -m orders").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts) => {
3454
+ gen.command("service <name>").description("Generate a @Service() class\n Use -m to scope it to a module: kick g service payment -m orders").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts, cmd) => {
3455
+ const dryRun = isDryRun(cmd);
3456
+ setDryRun(dryRun);
3428
3457
  const config = await loadKickConfig(process.cwd());
3429
3458
  const modulesDir = config?.modulesDir ?? "src/modules";
3430
3459
  const files = await generateService({
@@ -3434,9 +3463,11 @@ function registerGenerateCommand(program) {
3434
3463
  modulesDir,
3435
3464
  pattern: config?.pattern
3436
3465
  });
3437
- printGenerated(files);
3466
+ printGenerated(files, dryRun);
3438
3467
  });
3439
- gen.command("controller <name>").description("Generate a @Controller() class with basic routes\n Use -m to scope it to a module: kick g controller auth -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts) => {
3468
+ gen.command("controller <name>").description("Generate a @Controller() class with basic routes\n Use -m to scope it to a module: kick g controller auth -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts, cmd) => {
3469
+ const dryRun = isDryRun(cmd);
3470
+ setDryRun(dryRun);
3440
3471
  const config = await loadKickConfig(process.cwd());
3441
3472
  const modulesDir = config?.modulesDir ?? "src/modules";
3442
3473
  const files = await generateController2({
@@ -3446,9 +3477,11 @@ function registerGenerateCommand(program) {
3446
3477
  modulesDir,
3447
3478
  pattern: config?.pattern
3448
3479
  });
3449
- printGenerated(files);
3480
+ printGenerated(files, dryRun);
3450
3481
  });
3451
- gen.command("dto <name>").description("Generate a Zod DTO schema\n Use -m to scope it to a module: kick g dto create-user -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts) => {
3482
+ gen.command("dto <name>").description("Generate a Zod DTO schema\n Use -m to scope it to a module: kick g dto create-user -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module folder").action(async (name, opts, cmd) => {
3483
+ const dryRun = isDryRun(cmd);
3484
+ setDryRun(dryRun);
3452
3485
  const config = await loadKickConfig(process.cwd());
3453
3486
  const modulesDir = config?.modulesDir ?? "src/modules";
3454
3487
  const files = await generateDto({
@@ -3458,9 +3491,11 @@ function registerGenerateCommand(program) {
3458
3491
  modulesDir,
3459
3492
  pattern: config?.pattern
3460
3493
  });
3461
- printGenerated(files);
3494
+ printGenerated(files, dryRun);
3462
3495
  });
3463
- gen.command("test <name>").description("Generate a Vitest test scaffold\n Use -m to scope it to a module: kick g test user-service -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module's __tests__/ folder").action(async (name, opts) => {
3496
+ gen.command("test <name>").description("Generate a Vitest test scaffold\n Use -m to scope it to a module: kick g test user-service -m users").option("-o, --out <dir>", "Output directory (overrides --module)").option("-m, --module <module>", "Place inside a module's __tests__/ folder").action(async (name, opts, cmd) => {
3497
+ const dryRun = isDryRun(cmd);
3498
+ setDryRun(dryRun);
3464
3499
  const config = await loadKickConfig(process.cwd());
3465
3500
  const modulesDir = config?.modulesDir ?? "src/modules";
3466
3501
  const files = await generateTest({
@@ -3469,24 +3504,30 @@ function registerGenerateCommand(program) {
3469
3504
  moduleName: opts.module,
3470
3505
  modulesDir
3471
3506
  });
3472
- printGenerated(files);
3507
+ printGenerated(files, dryRun);
3473
3508
  });
3474
- gen.command("resolver <name>").description("Generate a GraphQL @Resolver class with @Query and @Mutation methods").option("-o, --out <dir>", "Output directory", "src/resolvers").action(async (name, opts) => {
3509
+ gen.command("resolver <name>").description("Generate a GraphQL @Resolver class with @Query and @Mutation methods").option("-o, --out <dir>", "Output directory", "src/resolvers").action(async (name, opts, cmd) => {
3510
+ const dryRun = isDryRun(cmd);
3511
+ setDryRun(dryRun);
3475
3512
  const files = await generateResolver({
3476
3513
  name,
3477
3514
  outDir: resolve4(opts.out)
3478
3515
  });
3479
- printGenerated(files);
3516
+ printGenerated(files, dryRun);
3480
3517
  });
3481
- gen.command("job <name>").description("Generate a @Job queue processor with @Process handlers").option("-o, --out <dir>", "Output directory", "src/jobs").option("-q, --queue <name>", "Queue name (default: <name>-queue)").action(async (name, opts) => {
3518
+ gen.command("job <name>").description("Generate a @Job queue processor with @Process handlers").option("-o, --out <dir>", "Output directory", "src/jobs").option("-q, --queue <name>", "Queue name (default: <name>-queue)").action(async (name, opts, cmd) => {
3519
+ const dryRun = isDryRun(cmd);
3520
+ setDryRun(dryRun);
3482
3521
  const files = await generateJob({
3483
3522
  name,
3484
3523
  outDir: resolve4(opts.out),
3485
3524
  queue: opts.queue
3486
3525
  });
3487
- printGenerated(files);
3526
+ printGenerated(files, dryRun);
3488
3527
  });
3489
- gen.command("scaffold <name> [fields...]").description("Generate a full CRUD module from field definitions\n Example: kick g scaffold Post title:string body:text published:boolean?\n Types: string, text, number, int, float, boolean, date, email, url, uuid, json, enum:a,b,c\n Append ? for optional fields: description:text?").option("--no-entity", "Skip entity and value object generation").option("--no-tests", "Skip test file generation").option("--modules-dir <dir>", "Modules directory").action(async (name, rawFields, opts) => {
3528
+ gen.command("scaffold <name> [fields...]").description("Generate a full CRUD module from field definitions\n Example: kick g scaffold Post title:string body:text published:boolean?\n Types: string, text, number, int, float, boolean, date, email, url, uuid, json, enum:a,b,c\n Append ? for optional fields: description:text?").option("--no-entity", "Skip entity and value object generation").option("--no-tests", "Skip test file generation").option("--modules-dir <dir>", "Modules directory").action(async (name, rawFields, opts, cmd) => {
3529
+ const dryRun = isDryRun(cmd);
3530
+ setDryRun(dryRun);
3490
3531
  if (rawFields.length === 0) {
3491
3532
  console.error("\n Error: At least one field is required.\n Usage: kick g scaffold <name> <field:type> [field:type...]\n Example: kick g scaffold Post title:string body:text published:boolean\n");
3492
3533
  process.exit(1);
@@ -3506,16 +3547,18 @@ function registerGenerateCommand(program) {
3506
3547
  for (const f of fields) {
3507
3548
  console.log(` ${f.name}: ${f.type}${f.optional ? " (optional)" : ""}`);
3508
3549
  }
3509
- printGenerated(files);
3550
+ printGenerated(files, dryRun);
3510
3551
  });
3511
- gen.command("config").description("Generate a kick.config.ts at the project root").option("--modules-dir <dir>", "Modules directory path", "src/modules").option("--repo <type>", "Default repository type: inmemory | drizzle | prisma", "inmemory").option("-f, --force", "Overwrite existing kick.config.ts without prompting").action(async (opts) => {
3552
+ gen.command("config").description("Generate a kick.config.ts at the project root").option("--modules-dir <dir>", "Modules directory path", "src/modules").option("--repo <type>", "Default repository type: inmemory | drizzle | prisma", "inmemory").option("-f, --force", "Overwrite existing kick.config.ts without prompting").action(async (opts, cmd) => {
3553
+ const dryRun = isDryRun(cmd);
3554
+ setDryRun(dryRun);
3512
3555
  const files = await generateConfig({
3513
3556
  outDir: resolve4("."),
3514
3557
  modulesDir: opts.modulesDir,
3515
3558
  defaultRepo: opts.repo,
3516
3559
  force: opts.force
3517
3560
  });
3518
- printGenerated(files);
3561
+ printGenerated(files, dryRun);
3519
3562
  });
3520
3563
  }
3521
3564
  __name(registerGenerateCommand, "registerGenerateCommand");