create-meridian-app 0.1.13 → 0.1.14

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.
@@ -419,6 +419,8 @@ ${handlers.join("\n\n")}
419
419
 
420
420
  // src/utils.ts
421
421
  import path from "path";
422
+ import os from "os";
423
+ import { randomBytes } from "crypto";
422
424
  import fs from "fs/promises";
423
425
  import { existsSync } from "fs";
424
426
  import { execa } from "execa";
@@ -462,8 +464,8 @@ process.stdout.write(JSON.stringify({
462
464
  dashboardPort: c?.admin?.port ?? 5174,
463
465
  }))
464
466
  `;
465
- const scriptPath = path.join(rootDir, ".meridian-ports-tmp.mjs");
466
- await fs.writeFile(scriptPath, script, "utf-8");
467
+ const scriptPath = path.join(os.tmpdir(), `meridian-ports-${randomBytes(8).toString("hex")}.mjs`);
468
+ await fs.writeFile(scriptPath, script, { encoding: "utf-8", mode: 384 });
467
469
  try {
468
470
  const result = await execa("node", ["--import", "tsx/esm", scriptPath], { cwd: rootDir });
469
471
  return JSON.parse(result.stdout);
@@ -480,6 +482,10 @@ async function runNew(projectName) {
480
482
  console.log(chalk.bold(" Create Meridian App"));
481
483
  console.log();
482
484
  let name = projectName;
485
+ if (name && !/^[a-z0-9-_]+$/.test(name)) {
486
+ console.error(chalk.red(" \u2716 Project name must contain only lowercase letters, numbers, hyphens, and underscores"));
487
+ process.exit(1);
488
+ }
483
489
  if (!name) {
484
490
  const res = await prompts(
485
491
  {
package/dist/cli.js CHANGED
@@ -14,10 +14,11 @@ import {
14
14
  toKebabCase,
15
15
  toPascalCase,
16
16
  writeFile
17
- } from "./chunk-U5TMTVEV.js";
17
+ } from "./chunk-IGLMECMQ.js";
18
18
 
19
19
  // src/cli.ts
20
20
  import { Command } from "commander";
21
+ import chalk13 from "chalk";
21
22
 
22
23
  // src/commands/dev.ts
23
24
  import path2 from "path";
@@ -131,6 +132,13 @@ function startDashboardServer(distDir, port, apiPort, apiHost = "localhost", adm
131
132
  return;
132
133
  }
133
134
  let filePath = path.join(distDir, urlPath === "/" ? "index.html" : urlPath);
135
+ const resolvedFile = path.resolve(filePath);
136
+ const resolvedDist = path.resolve(distDir);
137
+ if (!resolvedFile.startsWith(resolvedDist + path.sep) && resolvedFile !== resolvedDist) {
138
+ res.writeHead(403);
139
+ res.end("Forbidden");
140
+ return;
141
+ }
134
142
  if (!existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
135
143
  filePath = path.join(distDir, "index.html");
136
144
  }
@@ -306,9 +314,11 @@ const app = await bootstrap({ rootDir: ${JSON.stringify(rootDir)} })
306
314
  await app.stop()
307
315
  process.exit(0)
308
316
  `;
309
- const scriptPath = path3.join(rootDir, ".meridian-migrate-tmp.mjs");
317
+ const { randomBytes } = await import("crypto");
318
+ const { tmpdir } = await import("os");
319
+ const scriptPath = path3.join(tmpdir(), `meridian-migrate-${randomBytes(8).toString("hex")}.mjs`);
310
320
  const { writeFile: writeFile2, unlink } = await import("fs/promises");
311
- await writeFile2(scriptPath, script, "utf-8");
321
+ await writeFile2(scriptPath, script, { encoding: "utf-8", mode: 384 });
312
322
  try {
313
323
  await execa3("node", ["--import", "tsx/esm", scriptPath], {
314
324
  cwd: rootDir,
@@ -586,6 +596,12 @@ async function generateRoute(routePath, methods) {
586
596
  }
587
597
  const normalized = routePath.replace(/^\//, "");
588
598
  const filePath = path10.join(rootDir, "src", "api", normalized, "route.ts");
599
+ const resolvedFile = path10.resolve(filePath);
600
+ const resolvedBase = path10.resolve(rootDir, "src", "api");
601
+ if (!resolvedFile.startsWith(resolvedBase + path10.sep)) {
602
+ console.error(chalk11.red(" \u2716 Invalid route path: must resolve within src/api/"));
603
+ process.exit(1);
604
+ }
589
605
  if (existsSync8(filePath)) {
590
606
  console.error(chalk11.red(` \u2716 Route already exists: src/api/${normalized}/route.ts`));
591
607
  process.exit(1);
@@ -613,6 +629,7 @@ import chalk12 from "chalk";
613
629
  import ora2 from "ora";
614
630
  import prompts from "prompts";
615
631
  import { execa as execa4 } from "execa";
632
+ var ROLES = ["super-admin", "admin", "moderator", "member"];
616
633
  async function runUserCreate(opts) {
617
634
  const rootDir = findProjectRoot();
618
635
  if (!rootDir) {
@@ -623,6 +640,10 @@ async function runUserCreate(opts) {
623
640
  );
624
641
  process.exit(1);
625
642
  }
643
+ if (opts.role && !ROLES.includes(opts.role)) {
644
+ console.error(chalk12.red(` \u2716 Invalid role "${opts.role}". Must be one of: ${ROLES.join(", ")}`));
645
+ process.exit(1);
646
+ }
626
647
  const response = await prompts(
627
648
  [
628
649
  {
@@ -703,7 +724,7 @@ let output
703
724
  try {
704
725
  const result = await authService.register({
705
726
  email: ${JSON.stringify(email)},
706
- password: ${JSON.stringify(password)},
727
+ password: process.env.MERIDIAN_USER_PASSWORD,
707
728
  first_name: ${JSON.stringify(first_name || null)},
708
729
  last_name: ${JSON.stringify(last_name || null)},
709
730
  role: ${JSON.stringify(role)},
@@ -717,14 +738,16 @@ console.log(JSON.stringify(output))
717
738
  await app.stop()
718
739
  process.exit(output.success ? 0 : 1)
719
740
  `;
720
- const scriptPath = path11.join(rootDir, ".meridian-user-create-tmp.mjs");
741
+ const { randomBytes } = await import("crypto");
742
+ const { tmpdir } = await import("os");
743
+ const scriptPath = path11.join(tmpdir(), `meridian-user-create-${randomBytes(8).toString("hex")}.mjs`);
721
744
  const { writeFile: writeFile2, unlink } = await import("fs/promises");
722
- await writeFile2(scriptPath, script, "utf-8");
745
+ await writeFile2(scriptPath, script, { encoding: "utf-8", mode: 384 });
723
746
  try {
724
747
  const result = await execa4("node", ["--import", "tsx/esm", scriptPath], {
725
748
  cwd: rootDir,
726
749
  stdio: "pipe",
727
- env: { ...process.env, NODE_ENV: "development" }
750
+ env: { ...process.env, NODE_ENV: "development", MERIDIAN_USER_PASSWORD: password }
728
751
  });
729
752
  const lines = result.stdout.trim().split("\n");
730
753
  const output = JSON.parse(lines[lines.length - 1]);
@@ -788,7 +811,12 @@ program.command("db:generate <name>").description("Generate a new migration file
788
811
  });
789
812
  });
790
813
  program.command("serve-dashboard").description("Serve the admin dashboard as a static site").option("-p, --port <port>", "Port to serve on", "5174").action((options) => {
791
- runServeDashboard(Number(options.port)).catch((err) => {
814
+ const port = Number(options.port);
815
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
816
+ console.error(chalk13.red(` \u2716 Invalid port: ${options.port}`));
817
+ process.exit(1);
818
+ }
819
+ runServeDashboard(port).catch((err) => {
792
820
  console.error(err);
793
821
  process.exit(1);
794
822
  });
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runNew
4
- } from "./chunk-U5TMTVEV.js";
4
+ } from "./chunk-IGLMECMQ.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.13",
3
+ "version": "0.1.14",
4
4
  "description": "Create a new Meridian project or manage an existing one",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",