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.
- package/dist/{chunk-U5TMTVEV.js → chunk-IGLMECMQ.js} +8 -2
- package/dist/cli.js +36 -8
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -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(
|
|
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-
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
|
|
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