create-meridian-app 0.1.24 → 0.1.26

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.
@@ -17,7 +17,7 @@ function renderPackageJson(vars) {
17
17
  scripts: {
18
18
  dev: "meridian dev",
19
19
  build: "meridian build",
20
- start: "meridian dev",
20
+ start: "meridian start",
21
21
  "db:migrate": "meridian db:migrate",
22
22
  "db:generate": "meridian db:generate",
23
23
  ...vars.seedDemo ? { "seed:demo": "node --import tsx/esm src/scripts/seed-demo.ts" } : {}
package/dist/cli.js CHANGED
@@ -14,17 +14,18 @@ import {
14
14
  toKebabCase,
15
15
  toPascalCase,
16
16
  writeFile
17
- } from "./chunk-EE7FQVVB.js";
17
+ } from "./chunk-FNX5ZWEV.js";
18
18
 
19
19
  // src/cli.ts
20
20
  import { Command } from "commander";
21
- import chalk13 from "chalk";
21
+ import chalk14 from "chalk";
22
22
 
23
23
  // src/commands/dev.ts
24
24
  import path2 from "path";
25
25
  import { existsSync as existsSync2 } from "fs";
26
26
  import chalk2 from "chalk";
27
27
  import { execa } from "execa";
28
+ import dotenv2 from "dotenv";
28
29
 
29
30
  // src/commands/serve-dashboard.ts
30
31
  import path from "path";
@@ -226,6 +227,7 @@ async function runDev() {
226
227
  console.error(chalk2.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
227
228
  process.exit(1);
228
229
  }
230
+ dotenv2.config({ path: path2.join(rootDir, ".env") });
229
231
  const mainTs = path2.join(rootDir, "src", "main.ts");
230
232
  if (!existsSync2(mainTs)) {
231
233
  console.error(chalk2.red(` \u2716 Entry point not found: ${mainTs}`));
@@ -234,9 +236,10 @@ async function runDev() {
234
236
  const dashboardDist = path2.join(rootDir, "node_modules", "@meridianjs", "admin-dashboard", "dist");
235
237
  const hasDashboard = existsSync2(dashboardDist);
236
238
  const { apiPort, dashboardPort } = await readProjectPorts(rootDir);
239
+ const apiUrl = process.env.API_URL ?? `http://localhost:${apiPort}`;
237
240
  let dashServer = null;
238
241
  if (hasDashboard) {
239
- dashServer = await startDashboardServer(dashboardDist, dashboardPort, apiPort);
242
+ dashServer = await startDashboardServer(dashboardDist, dashboardPort, apiPort, "localhost", null, apiUrl);
240
243
  console.log(
241
244
  chalk2.dim(" \u2192 API: ") + chalk2.cyan(`http://localhost:${apiPort}`) + chalk2.dim(" dashboard: ") + chalk2.cyan(`http://localhost:${dashboardPort}`)
242
245
  );
@@ -271,39 +274,98 @@ async function runDev() {
271
274
  process.exit(apiProc.exitCode ?? 0);
272
275
  }
273
276
 
274
- // src/commands/build.ts
277
+ // src/commands/start.ts
278
+ import path3 from "path";
279
+ import { existsSync as existsSync3 } from "fs";
275
280
  import chalk3 from "chalk";
276
281
  import { execa as execa2 } from "execa";
277
- async function runBuild() {
282
+ import dotenv3 from "dotenv";
283
+ async function runStart() {
278
284
  const rootDir = findProjectRoot();
279
285
  if (!rootDir) {
280
286
  console.error(chalk3.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
281
287
  process.exit(1);
282
288
  }
283
- console.log(chalk3.dim(" \u2192 Type-checking project..."));
289
+ dotenv3.config({ path: path3.join(rootDir, ".env") });
290
+ const mainTs = path3.join(rootDir, "src", "main.ts");
291
+ if (!existsSync3(mainTs)) {
292
+ console.error(chalk3.red(` \u2716 Entry point not found: ${mainTs}`));
293
+ process.exit(1);
294
+ }
295
+ const dashboardDist = path3.join(rootDir, "node_modules", "@meridianjs", "admin-dashboard", "dist");
296
+ const hasDashboard = existsSync3(dashboardDist);
297
+ const { apiPort, dashboardPort } = await readProjectPorts(rootDir);
298
+ const apiUrl = process.env.API_URL ?? `http://localhost:${apiPort}`;
299
+ let dashServer = null;
300
+ if (hasDashboard) {
301
+ dashServer = await startDashboardServer(dashboardDist, dashboardPort, apiPort, "localhost", null, apiUrl);
302
+ console.log(
303
+ chalk3.dim(" \u2192 API: ") + chalk3.cyan(`http://localhost:${apiPort}`) + chalk3.dim(" dashboard: ") + chalk3.cyan(`http://localhost:${dashboardPort}`)
304
+ );
305
+ } else {
306
+ console.log(chalk3.dim(` \u2192 API: http://localhost:${apiPort}`));
307
+ }
308
+ console.log();
309
+ const apiProc = execa2(
310
+ "node",
311
+ ["--import", "tsx/esm", mainTs],
312
+ {
313
+ cwd: rootDir,
314
+ stdio: "inherit",
315
+ env: { ...process.env, NODE_ENV: "production", FORCE_COLOR: "1" }
316
+ }
317
+ );
318
+ const shutdown = (signal) => {
319
+ dashServer?.close();
320
+ apiProc.kill(signal);
321
+ process.exit(0);
322
+ };
323
+ process.on("SIGINT", () => shutdown("SIGINT"));
324
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
325
+ await apiProc.catch((err) => {
326
+ if (err.signal === "SIGINT" || err.signal === "SIGTERM") {
327
+ dashServer?.close();
328
+ process.exit(0);
329
+ }
330
+ throw err;
331
+ });
332
+ dashServer?.close();
333
+ process.exit(apiProc.exitCode ?? 0);
334
+ }
335
+
336
+ // src/commands/build.ts
337
+ import chalk4 from "chalk";
338
+ import { execa as execa3 } from "execa";
339
+ async function runBuild() {
340
+ const rootDir = findProjectRoot();
341
+ if (!rootDir) {
342
+ console.error(chalk4.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
343
+ process.exit(1);
344
+ }
345
+ console.log(chalk4.dim(" \u2192 Type-checking project..."));
284
346
  console.log();
285
- const result = await execa2("npx", ["tsc", "--noEmit"], {
347
+ const result = await execa3("npx", ["tsc", "--noEmit"], {
286
348
  cwd: rootDir,
287
349
  stdio: "inherit"
288
350
  }).catch((err) => err);
289
351
  if (result.exitCode !== 0) {
290
352
  console.log();
291
- console.error(chalk3.red(" \u2716 Type check failed"));
353
+ console.error(chalk4.red(" \u2716 Type check failed"));
292
354
  process.exit(result.exitCode ?? 1);
293
355
  }
294
356
  console.log();
295
- console.log(chalk3.green(" \u2713 Type check passed"));
357
+ console.log(chalk4.green(" \u2713 Type check passed"));
296
358
  }
297
359
 
298
360
  // src/commands/db-migrate.ts
299
- import path3 from "path";
300
- import chalk4 from "chalk";
361
+ import path4 from "path";
362
+ import chalk5 from "chalk";
301
363
  import ora from "ora";
302
- import { execa as execa3 } from "execa";
364
+ import { execa as execa4 } from "execa";
303
365
  async function runDbMigrate() {
304
366
  const rootDir = findProjectRoot();
305
367
  if (!rootDir) {
306
- console.error(chalk4.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
368
+ console.error(chalk5.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
307
369
  process.exit(1);
308
370
  }
309
371
  const spinner = ora("Synchronizing database schema...").start();
@@ -321,11 +383,11 @@ await app.stop()
321
383
  process.exit(0)
322
384
  `;
323
385
  const { randomBytes } = await import("crypto");
324
- const scriptPath = path3.join(rootDir, `.meridian-migrate-${randomBytes(8).toString("hex")}.mjs`);
386
+ const scriptPath = path4.join(rootDir, `.meridian-migrate-${randomBytes(8).toString("hex")}.mjs`);
325
387
  const { writeFile: writeFile2, unlink } = await import("fs/promises");
326
388
  await writeFile2(scriptPath, script, { encoding: "utf-8", mode: 384 });
327
389
  try {
328
- await execa3("node", ["--import", "tsx/esm", scriptPath], {
390
+ await execa4("node", ["--import", "tsx/esm", scriptPath], {
329
391
  cwd: rootDir,
330
392
  stdio: "pipe",
331
393
  env: { ...process.env, NODE_ENV: "development" }
@@ -334,7 +396,7 @@ process.exit(0)
334
396
  } catch (err) {
335
397
  spinner.fail("Schema migration failed");
336
398
  console.error();
337
- if (err.stderr) console.error(chalk4.red(err.stderr));
399
+ if (err.stderr) console.error(chalk5.red(err.stderr));
338
400
  if (err.stdout) console.error(err.stdout);
339
401
  process.exit(1);
340
402
  } finally {
@@ -343,23 +405,23 @@ process.exit(0)
343
405
  }
344
406
 
345
407
  // src/commands/db-generate.ts
346
- import path4 from "path";
408
+ import path5 from "path";
347
409
  import fs2 from "fs/promises";
348
- import chalk5 from "chalk";
410
+ import chalk6 from "chalk";
349
411
  async function runDbGenerate(migrationName) {
350
412
  const rootDir = findProjectRoot();
351
413
  if (!rootDir) {
352
- console.error(chalk5.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
414
+ console.error(chalk6.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
353
415
  process.exit(1);
354
416
  }
355
417
  if (!migrationName) {
356
- console.error(chalk5.red(" \u2716 Migration name is required. Usage: meridian db:generate <name>"));
418
+ console.error(chalk6.red(" \u2716 Migration name is required. Usage: meridian db:generate <name>"));
357
419
  process.exit(1);
358
420
  }
359
421
  const safeName = migrationName.toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_");
360
422
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.Z]/g, "").slice(0, 14);
361
423
  const fileName = `${timestamp}_${safeName}.ts`;
362
- const migrationsDir = path4.join(rootDir, "src", "migrations");
424
+ const migrationsDir = path5.join(rootDir, "src", "migrations");
363
425
  await fs2.mkdir(migrationsDir, { recursive: true });
364
426
  const content = `/**
365
427
  * Migration: ${safeName}
@@ -378,87 +440,87 @@ export async function down(): Promise<void> {
378
440
  // Write your rollback SQL here
379
441
  }
380
442
  `;
381
- const filePath = path4.join(migrationsDir, fileName);
443
+ const filePath = path5.join(migrationsDir, fileName);
382
444
  await fs2.writeFile(filePath, content, "utf-8");
383
- console.log(chalk5.green(` \u2713 Created migration: src/migrations/${fileName}`));
445
+ console.log(chalk6.green(` \u2713 Created migration: src/migrations/${fileName}`));
384
446
  console.log();
385
- console.log(chalk5.dim(" Note: Meridian auto-syncs schema on startup via updateSchema()."));
386
- console.log(chalk5.dim(" Use this file for custom DDL that requires manual control."));
447
+ console.log(chalk6.dim(" Note: Meridian auto-syncs schema on startup via updateSchema()."));
448
+ console.log(chalk6.dim(" Use this file for custom DDL that requires manual control."));
387
449
  }
388
450
 
389
451
  // src/commands/generate/module.ts
390
- import path5 from "path";
391
- import { existsSync as existsSync3 } from "fs";
392
- import chalk6 from "chalk";
452
+ import path6 from "path";
453
+ import { existsSync as existsSync4 } from "fs";
454
+ import chalk7 from "chalk";
393
455
  async function generateModule(name) {
394
456
  const rootDir = findProjectRoot();
395
457
  if (!rootDir) {
396
- console.error(chalk6.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
458
+ console.error(chalk7.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
397
459
  process.exit(1);
398
460
  }
399
461
  if (!name) {
400
- console.error(chalk6.red(" \u2716 Module name is required. Usage: meridian generate module <name>"));
462
+ console.error(chalk7.red(" \u2716 Module name is required. Usage: meridian generate module <name>"));
401
463
  process.exit(1);
402
464
  }
403
465
  const kebab = toKebabCase(name);
404
466
  const pascal = toPascalCase(kebab);
405
- const moduleDir = path5.join(rootDir, "src", "modules", kebab);
406
- if (existsSync3(moduleDir)) {
407
- console.error(chalk6.red(` \u2716 Module directory already exists: src/modules/${kebab}`));
467
+ const moduleDir = path6.join(rootDir, "src", "modules", kebab);
468
+ if (existsSync4(moduleDir)) {
469
+ console.error(chalk7.red(` \u2716 Module directory already exists: src/modules/${kebab}`));
408
470
  process.exit(1);
409
471
  }
410
- await writeFile(path5.join(moduleDir, "index.ts"), renderModuleIndex(kebab, pascal));
411
- await writeFile(path5.join(moduleDir, `models/${kebab}.ts`), renderModuleModel(kebab, pascal));
412
- await writeFile(path5.join(moduleDir, `loaders/default.ts`), renderModuleLoader(kebab, pascal));
413
- await writeFile(path5.join(moduleDir, "service.ts"), renderModuleService(kebab, pascal));
414
- console.log(chalk6.green(` \u2713 Generated module: src/modules/${kebab}/`));
472
+ await writeFile(path6.join(moduleDir, "index.ts"), renderModuleIndex(kebab, pascal));
473
+ await writeFile(path6.join(moduleDir, `models/${kebab}.ts`), renderModuleModel(kebab, pascal));
474
+ await writeFile(path6.join(moduleDir, `loaders/default.ts`), renderModuleLoader(kebab, pascal));
475
+ await writeFile(path6.join(moduleDir, "service.ts"), renderModuleService(kebab, pascal));
476
+ console.log(chalk7.green(` \u2713 Generated module: src/modules/${kebab}/`));
415
477
  console.log();
416
478
  console.log(" Files created:");
417
- console.log(chalk6.dim(` src/modules/${kebab}/index.ts`));
418
- console.log(chalk6.dim(` src/modules/${kebab}/models/${kebab}.ts`));
419
- console.log(chalk6.dim(` src/modules/${kebab}/loaders/default.ts`));
420
- console.log(chalk6.dim(` src/modules/${kebab}/service.ts`));
479
+ console.log(chalk7.dim(` src/modules/${kebab}/index.ts`));
480
+ console.log(chalk7.dim(` src/modules/${kebab}/models/${kebab}.ts`));
481
+ console.log(chalk7.dim(` src/modules/${kebab}/loaders/default.ts`));
482
+ console.log(chalk7.dim(` src/modules/${kebab}/service.ts`));
421
483
  console.log();
422
484
  console.log(" Next steps:");
423
- console.log(chalk6.dim(` 1. Add the module to your meridian.config.ts:`));
424
- console.log(chalk6.dim(` { resolve: "./src/modules/${kebab}" }`));
425
- console.log(chalk6.dim(` 2. Run \`npm run db:migrate\` to sync the schema`));
485
+ console.log(chalk7.dim(` 1. Add the module to your meridian.config.ts:`));
486
+ console.log(chalk7.dim(` { resolve: "./src/modules/${kebab}" }`));
487
+ console.log(chalk7.dim(` 2. Run \`npm run db:migrate\` to sync the schema`));
426
488
  }
427
489
 
428
490
  // src/commands/generate/workflow.ts
429
- import path6 from "path";
430
- import { existsSync as existsSync4 } from "fs";
431
- import chalk7 from "chalk";
491
+ import path7 from "path";
492
+ import { existsSync as existsSync5 } from "fs";
493
+ import chalk8 from "chalk";
432
494
  async function generateWorkflow(name) {
433
495
  const rootDir = findProjectRoot();
434
496
  if (!rootDir) {
435
- console.error(chalk7.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
497
+ console.error(chalk8.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
436
498
  process.exit(1);
437
499
  }
438
500
  if (!name) {
439
- console.error(chalk7.red(" \u2716 Workflow name is required. Usage: meridian generate workflow <name>"));
501
+ console.error(chalk8.red(" \u2716 Workflow name is required. Usage: meridian generate workflow <name>"));
440
502
  process.exit(1);
441
503
  }
442
504
  const kebab = toKebabCase(name);
443
505
  const pascal = toPascalCase(kebab);
444
- const filePath = path6.join(rootDir, "src", "workflows", `${kebab}.ts`);
445
- if (existsSync4(filePath)) {
446
- console.error(chalk7.red(` \u2716 Workflow already exists: src/workflows/${kebab}.ts`));
506
+ const filePath = path7.join(rootDir, "src", "workflows", `${kebab}.ts`);
507
+ if (existsSync5(filePath)) {
508
+ console.error(chalk8.red(` \u2716 Workflow already exists: src/workflows/${kebab}.ts`));
447
509
  process.exit(1);
448
510
  }
449
511
  const camel = pascal.charAt(0).toLowerCase() + pascal.slice(1);
450
512
  await writeFile(filePath, renderWorkflow(kebab, pascal));
451
- console.log(chalk7.green(` \u2713 Generated workflow: src/workflows/${kebab}.ts`));
513
+ console.log(chalk8.green(` \u2713 Generated workflow: src/workflows/${kebab}.ts`));
452
514
  console.log();
453
515
  console.log(" Usage:");
454
- console.log(chalk7.dim(` import { ${camel}Workflow } from "./workflows/${kebab}.js"`));
455
- console.log(chalk7.dim(` const { result } = await ${camel}Workflow(req.scope).run({ input: {...} })`));
516
+ console.log(chalk8.dim(` import { ${camel}Workflow } from "./workflows/${kebab}.js"`));
517
+ console.log(chalk8.dim(` const { result } = await ${camel}Workflow(req.scope).run({ input: {...} })`));
456
518
  }
457
519
 
458
520
  // src/commands/generate/plugin.ts
459
- import path7 from "path";
460
- import { existsSync as existsSync5 } from "fs";
461
- import chalk8 from "chalk";
521
+ import path8 from "path";
522
+ import { existsSync as existsSync6 } from "fs";
523
+ import chalk9 from "chalk";
462
524
  function renderPluginIndex(_name, pascalName) {
463
525
  return `import { fileURLToPath } from "node:url"
464
526
  import path from "node:path"
@@ -495,158 +557,158 @@ export const GET = async (req: any, res: Response) => {
495
557
  async function generatePlugin(name) {
496
558
  const rootDir = findProjectRoot();
497
559
  if (!rootDir) {
498
- console.error(chalk8.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
560
+ console.error(chalk9.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
499
561
  process.exit(1);
500
562
  }
501
563
  if (!name) {
502
- console.error(chalk8.red(" \u2716 Plugin name is required. Usage: meridian generate plugin <name>"));
564
+ console.error(chalk9.red(" \u2716 Plugin name is required. Usage: meridian generate plugin <name>"));
503
565
  process.exit(1);
504
566
  }
505
567
  const kebab = toKebabCase(name);
506
568
  const pascal = toPascalCase(kebab);
507
- const pluginDir = path7.join(rootDir, "src", "plugins", kebab);
508
- if (existsSync5(pluginDir)) {
509
- console.error(chalk8.red(` \u2716 Plugin directory already exists: src/plugins/${kebab}`));
569
+ const pluginDir = path8.join(rootDir, "src", "plugins", kebab);
570
+ if (existsSync6(pluginDir)) {
571
+ console.error(chalk9.red(` \u2716 Plugin directory already exists: src/plugins/${kebab}`));
510
572
  process.exit(1);
511
573
  }
512
- await writeFile(path7.join(pluginDir, "index.ts"), renderPluginIndex(kebab, pascal));
574
+ await writeFile(path8.join(pluginDir, "index.ts"), renderPluginIndex(kebab, pascal));
513
575
  await writeFile(
514
- path7.join(pluginDir, "api", "admin", kebab, "route.ts"),
576
+ path8.join(pluginDir, "api", "admin", kebab, "route.ts"),
515
577
  renderPluginRoute(kebab)
516
578
  );
517
- console.log(chalk8.green(` \u2713 Generated plugin: src/plugins/${kebab}/`));
579
+ console.log(chalk9.green(` \u2713 Generated plugin: src/plugins/${kebab}/`));
518
580
  console.log();
519
581
  console.log(" Files created:");
520
- console.log(chalk8.dim(` src/plugins/${kebab}/index.ts`));
521
- console.log(chalk8.dim(` src/plugins/${kebab}/api/admin/${kebab}/route.ts`));
582
+ console.log(chalk9.dim(` src/plugins/${kebab}/index.ts`));
583
+ console.log(chalk9.dim(` src/plugins/${kebab}/api/admin/${kebab}/route.ts`));
522
584
  console.log();
523
585
  console.log(" Next steps:");
524
- console.log(chalk8.dim(` 1. Add the plugin to your meridian.config.ts:`));
525
- console.log(chalk8.dim(` plugins: [{ resolve: "./src/plugins/${kebab}" }]`));
526
- console.log(chalk8.dim(` 2. Start the dev server: \`npm run dev\``));
586
+ console.log(chalk9.dim(` 1. Add the plugin to your meridian.config.ts:`));
587
+ console.log(chalk9.dim(` plugins: [{ resolve: "./src/plugins/${kebab}" }]`));
588
+ console.log(chalk9.dim(` 2. Start the dev server: \`npm run dev\``));
527
589
  }
528
590
 
529
591
  // src/commands/generate/subscriber.ts
530
- import path8 from "path";
531
- import { existsSync as existsSync6 } from "fs";
532
- import chalk9 from "chalk";
592
+ import path9 from "path";
593
+ import { existsSync as existsSync7 } from "fs";
594
+ import chalk10 from "chalk";
533
595
  async function generateSubscriber(eventName) {
534
596
  const rootDir = findProjectRoot();
535
597
  if (!rootDir) {
536
- console.error(chalk9.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
598
+ console.error(chalk10.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
537
599
  process.exit(1);
538
600
  }
539
601
  if (!eventName) {
540
- console.error(chalk9.red(" \u2716 Event name is required. Usage: meridian generate subscriber <event>"));
602
+ console.error(chalk10.red(" \u2716 Event name is required. Usage: meridian generate subscriber <event>"));
541
603
  process.exit(1);
542
604
  }
543
605
  const fileName = toKebabCase(eventName.replace(/\./g, "-"));
544
- const filePath = path8.join(rootDir, "src", "subscribers", `${fileName}.ts`);
545
- if (existsSync6(filePath)) {
546
- console.error(chalk9.red(` \u2716 Subscriber already exists: src/subscribers/${fileName}.ts`));
606
+ const filePath = path9.join(rootDir, "src", "subscribers", `${fileName}.ts`);
607
+ if (existsSync7(filePath)) {
608
+ console.error(chalk10.red(` \u2716 Subscriber already exists: src/subscribers/${fileName}.ts`));
547
609
  process.exit(1);
548
610
  }
549
611
  await writeFile(filePath, renderSubscriber(eventName));
550
- console.log(chalk9.green(` \u2713 Generated subscriber: src/subscribers/${fileName}.ts`));
612
+ console.log(chalk10.green(` \u2713 Generated subscriber: src/subscribers/${fileName}.ts`));
551
613
  console.log();
552
614
  console.log(" Listens for event:");
553
- console.log(chalk9.dim(` "${eventName}"`));
615
+ console.log(chalk10.dim(` "${eventName}"`));
554
616
  console.log();
555
617
  console.log(" The file is auto-loaded by the framework on next dev restart.");
556
618
  }
557
619
 
558
620
  // src/commands/generate/job.ts
559
- import path9 from "path";
560
- import { existsSync as existsSync7 } from "fs";
561
- import chalk10 from "chalk";
621
+ import path10 from "path";
622
+ import { existsSync as existsSync8 } from "fs";
623
+ import chalk11 from "chalk";
562
624
  async function generateJob(name, schedule) {
563
625
  const rootDir = findProjectRoot();
564
626
  if (!rootDir) {
565
- console.error(chalk10.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
627
+ console.error(chalk11.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
566
628
  process.exit(1);
567
629
  }
568
630
  if (!name) {
569
- console.error(chalk10.red(" \u2716 Job name is required. Usage: meridian generate job <name>"));
631
+ console.error(chalk11.red(" \u2716 Job name is required. Usage: meridian generate job <name>"));
570
632
  process.exit(1);
571
633
  }
572
634
  const kebab = toKebabCase(name);
573
- const filePath = path9.join(rootDir, "src", "jobs", `${kebab}.ts`);
574
- if (existsSync7(filePath)) {
575
- console.error(chalk10.red(` \u2716 Job already exists: src/jobs/${kebab}.ts`));
635
+ const filePath = path10.join(rootDir, "src", "jobs", `${kebab}.ts`);
636
+ if (existsSync8(filePath)) {
637
+ console.error(chalk11.red(` \u2716 Job already exists: src/jobs/${kebab}.ts`));
576
638
  process.exit(1);
577
639
  }
578
640
  await writeFile(filePath, renderJob(kebab, schedule));
579
- console.log(chalk10.green(` \u2713 Generated job: src/jobs/${kebab}.ts`));
641
+ console.log(chalk11.green(` \u2713 Generated job: src/jobs/${kebab}.ts`));
580
642
  console.log();
581
643
  console.log(" Schedule:");
582
- console.log(chalk10.dim(` ${schedule}`));
644
+ console.log(chalk11.dim(` ${schedule}`));
583
645
  console.log();
584
646
  console.log(" The job is auto-loaded by the framework on next dev restart.");
585
647
  }
586
648
 
587
649
  // src/commands/generate/route.ts
588
- import path10 from "path";
589
- import { existsSync as existsSync8 } from "fs";
590
- import chalk11 from "chalk";
650
+ import path11 from "path";
651
+ import { existsSync as existsSync9 } from "fs";
652
+ import chalk12 from "chalk";
591
653
  var VALID_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
592
654
  async function generateRoute(routePath, methods) {
593
655
  const rootDir = findProjectRoot();
594
656
  if (!rootDir) {
595
- console.error(chalk11.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
657
+ console.error(chalk12.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
596
658
  process.exit(1);
597
659
  }
598
660
  if (!routePath) {
599
- console.error(chalk11.red(" \u2716 Route path is required. Usage: meridian generate route <path>"));
661
+ console.error(chalk12.red(" \u2716 Route path is required. Usage: meridian generate route <path>"));
600
662
  process.exit(1);
601
663
  }
602
664
  const normalized = routePath.replace(/^\//, "");
603
- const filePath = path10.join(rootDir, "src", "api", normalized, "route.ts");
604
- const resolvedFile = path10.resolve(filePath);
605
- const resolvedBase = path10.resolve(rootDir, "src", "api");
606
- if (!resolvedFile.startsWith(resolvedBase + path10.sep)) {
607
- console.error(chalk11.red(" \u2716 Invalid route path: must resolve within src/api/"));
665
+ const filePath = path11.join(rootDir, "src", "api", normalized, "route.ts");
666
+ const resolvedFile = path11.resolve(filePath);
667
+ const resolvedBase = path11.resolve(rootDir, "src", "api");
668
+ if (!resolvedFile.startsWith(resolvedBase + path11.sep)) {
669
+ console.error(chalk12.red(" \u2716 Invalid route path: must resolve within src/api/"));
608
670
  process.exit(1);
609
671
  }
610
- if (existsSync8(filePath)) {
611
- console.error(chalk11.red(` \u2716 Route already exists: src/api/${normalized}/route.ts`));
672
+ if (existsSync9(filePath)) {
673
+ console.error(chalk12.red(` \u2716 Route already exists: src/api/${normalized}/route.ts`));
612
674
  process.exit(1);
613
675
  }
614
676
  const normalizedMethods = methods.map((m) => m.toUpperCase());
615
677
  const invalid = normalizedMethods.filter((m) => !VALID_METHODS.includes(m));
616
678
  if (invalid.length > 0) {
617
- console.error(chalk11.red(` \u2716 Invalid HTTP methods: ${invalid.join(", ")}. Valid: ${VALID_METHODS.join(", ")}`));
679
+ console.error(chalk12.red(` \u2716 Invalid HTTP methods: ${invalid.join(", ")}. Valid: ${VALID_METHODS.join(", ")}`));
618
680
  process.exit(1);
619
681
  }
620
682
  await writeFile(filePath, renderRoute(normalizedMethods));
621
- console.log(chalk11.green(` \u2713 Generated route: src/api/${normalized}/route.ts`));
683
+ console.log(chalk12.green(` \u2713 Generated route: src/api/${normalized}/route.ts`));
622
684
  console.log();
623
685
  console.log(" Handlers exported:");
624
686
  for (const m of normalizedMethods) {
625
- console.log(chalk11.dim(` ${m} /${normalized}`));
687
+ console.log(chalk12.dim(` ${m} /${normalized}`));
626
688
  }
627
689
  console.log();
628
690
  console.log(" The route is auto-loaded by the framework on next dev restart.");
629
691
  }
630
692
 
631
693
  // src/commands/user-create.ts
632
- import path11 from "path";
633
- import chalk12 from "chalk";
694
+ import path12 from "path";
695
+ import chalk13 from "chalk";
634
696
  import ora2 from "ora";
635
697
  import prompts from "prompts";
636
- import { execa as execa4 } from "execa";
698
+ import { execa as execa5 } from "execa";
637
699
  var ROLES = ["super-admin", "admin", "moderator", "member"];
638
700
  async function runUserCreate(opts) {
639
701
  const rootDir = findProjectRoot();
640
702
  if (!rootDir) {
641
703
  console.error(
642
- chalk12.red(
704
+ chalk13.red(
643
705
  " \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"
644
706
  )
645
707
  );
646
708
  process.exit(1);
647
709
  }
648
710
  if (opts.role && !ROLES.includes(opts.role)) {
649
- console.error(chalk12.red(` \u2716 Invalid role "${opts.role}". Must be one of: ${ROLES.join(", ")}`));
711
+ console.error(chalk13.red(` \u2716 Invalid role "${opts.role}". Must be one of: ${ROLES.join(", ")}`));
650
712
  process.exit(1);
651
713
  }
652
714
  const response = await prompts(
@@ -703,7 +765,7 @@ async function runUserCreate(opts) {
703
765
  ],
704
766
  {
705
767
  onCancel: () => {
706
- console.log(chalk12.yellow("\n Cancelled."));
768
+ console.log(chalk13.yellow("\n Cancelled."));
707
769
  process.exit(0);
708
770
  }
709
771
  }
@@ -744,11 +806,11 @@ await app.stop()
744
806
  process.exit(output.success ? 0 : 1)
745
807
  `;
746
808
  const { randomBytes } = await import("crypto");
747
- const scriptPath = path11.join(rootDir, `.meridian-user-create-${randomBytes(8).toString("hex")}.mjs`);
809
+ const scriptPath = path12.join(rootDir, `.meridian-user-create-${randomBytes(8).toString("hex")}.mjs`);
748
810
  const { writeFile: writeFile2, unlink } = await import("fs/promises");
749
811
  await writeFile2(scriptPath, script, { encoding: "utf-8", mode: 384 });
750
812
  try {
751
- const result = await execa4("node", ["--import", "tsx/esm", scriptPath], {
813
+ const result = await execa5("node", ["--import", "tsx/esm", scriptPath], {
752
814
  cwd: rootDir,
753
815
  stdio: "pipe",
754
816
  env: { ...process.env, NODE_ENV: "development", MERIDIAN_USER_PASSWORD: password }
@@ -757,7 +819,7 @@ process.exit(output.success ? 0 : 1)
757
819
  const output = JSON.parse(lines[lines.length - 1]);
758
820
  if (output.success) {
759
821
  spinner.succeed(
760
- `User created: ${chalk12.green(output.user.email)} (${chalk12.cyan(role)})`
822
+ `User created: ${chalk13.green(output.user.email)} (${chalk13.cyan(role)})`
761
823
  );
762
824
  } else {
763
825
  spinner.fail(output.error ?? "Failed to create user");
@@ -769,12 +831,12 @@ process.exit(output.success ? 0 : 1)
769
831
  try {
770
832
  const lines = err.stdout.trim().split("\n");
771
833
  const output = JSON.parse(lines[lines.length - 1]);
772
- console.error(chalk12.red(` ${output.error ?? err.stdout}`));
834
+ console.error(chalk13.red(` ${output.error ?? err.stdout}`));
773
835
  } catch {
774
- console.error(chalk12.red(` ${err.stdout}`));
836
+ console.error(chalk13.red(` ${err.stdout}`));
775
837
  }
776
838
  }
777
- if (err.stderr) console.error(chalk12.red(err.stderr));
839
+ if (err.stderr) console.error(chalk13.red(err.stderr));
778
840
  process.exit(1);
779
841
  } finally {
780
842
  await unlink(scriptPath).catch(() => null);
@@ -796,6 +858,12 @@ program.command("dev").description("Start the development server").action(() =>
796
858
  process.exit(1);
797
859
  });
798
860
  });
861
+ program.command("start").description("Start the server in production mode").action(() => {
862
+ runStart().catch((err) => {
863
+ console.error(err);
864
+ process.exit(1);
865
+ });
866
+ });
799
867
  program.command("build").description("Type-check the project").action(() => {
800
868
  runBuild().catch((err) => {
801
869
  console.error(err);
@@ -817,7 +885,7 @@ program.command("db:generate <name>").description("Generate a new migration file
817
885
  program.command("serve-dashboard").description("Serve the admin dashboard as a static site").option("-p, --port <port>", "Port to serve on", "5174").action((options) => {
818
886
  const port = Number(options.port);
819
887
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
820
- console.error(chalk13.red(` \u2716 Invalid port: ${options.port}`));
888
+ console.error(chalk14.red(` \u2716 Invalid port: ${options.port}`));
821
889
  process.exit(1);
822
890
  }
823
891
  runServeDashboard(port).catch((err) => {
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runNew
4
- } from "./chunk-EE7FQVVB.js";
4
+ } from "./chunk-FNX5ZWEV.js";
5
5
 
6
6
  // src/index.ts
7
7
  var projectName = process.argv[2];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-meridian-app",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Create a new Meridian project or manage an existing one",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",