create-meridian-app 0.1.1 → 0.1.3

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.
@@ -4,7 +4,7 @@ import { existsSync as existsSync2 } from "fs";
4
4
  import ora from "ora";
5
5
  import chalk from "chalk";
6
6
  import prompts from "prompts";
7
- import { execa } from "execa";
7
+ import { execa as execa2 } from "execa";
8
8
 
9
9
  // src/templates/index.ts
10
10
  function renderPackageJson(vars) {
@@ -81,6 +81,9 @@ export default defineConfig({
81
81
  httpPort: Number(process.env.PORT) || ${vars.httpPort},
82
82
  jwtSecret: process.env.JWT_SECRET ?? "changeme-replace-in-production",
83
83
  },
84
+ admin: {
85
+ port: Number(process.env.DASHBOARD_PORT) || ${vars.dashboardPort},
86
+ },
84
87
  modules: [
85
88
  { resolve: "@meridianjs/event-bus-local" },
86
89
  { resolve: "@meridianjs/user" },
@@ -163,7 +166,8 @@ function renderEnvExample(vars) {
163
166
  DATABASE_URL=${vars.databaseUrl}
164
167
  PORT=${vars.httpPort}
165
168
  JWT_SECRET=changeme-replace-in-production
166
- `;
169
+ ${vars.dashboard ? `DASHBOARD_PORT=${vars.dashboardPort}` : ""}
170
+ `.trimEnd() + "\n";
167
171
  }
168
172
  function renderReadme(vars) {
169
173
  return `# ${vars.name}
@@ -317,6 +321,7 @@ export const ${camelName}Workflow = createWorkflow(
317
321
  import path from "path";
318
322
  import fs from "fs/promises";
319
323
  import { existsSync } from "fs";
324
+ import { execa } from "execa";
320
325
  function toPascalCase(str) {
321
326
  return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^(.)/, (_, c) => c.toUpperCase());
322
327
  }
@@ -345,6 +350,29 @@ function findProjectRoot(startDir = process.cwd()) {
345
350
  dir = parent;
346
351
  }
347
352
  }
353
+ async function readProjectPorts(rootDir) {
354
+ const defaults = { apiPort: 9e3, dashboardPort: 5174 };
355
+ const configPath = path.join(rootDir, "meridian.config.ts");
356
+ if (!existsSync(configPath)) return defaults;
357
+ const script = `
358
+ import cfg from "${configPath.replace(/\\/g, "/")}"
359
+ const c = cfg.default ?? cfg
360
+ process.stdout.write(JSON.stringify({
361
+ apiPort: c?.projectConfig?.httpPort ?? 9000,
362
+ dashboardPort: c?.admin?.port ?? 5174,
363
+ }))
364
+ `;
365
+ const scriptPath = path.join(rootDir, ".meridian-ports-tmp.mjs");
366
+ await fs.writeFile(scriptPath, script, "utf-8");
367
+ try {
368
+ const result = await execa("node", ["--import", "tsx/esm", scriptPath], { cwd: rootDir });
369
+ return JSON.parse(result.stdout);
370
+ } catch {
371
+ return defaults;
372
+ } finally {
373
+ await fs.unlink(scriptPath).catch(() => null);
374
+ }
375
+ }
348
376
 
349
377
  // src/commands/new.ts
350
378
  async function runNew(projectName) {
@@ -392,7 +420,7 @@ async function runNew(projectName) {
392
420
  {
393
421
  type: "number",
394
422
  name: "httpPort",
395
- message: "HTTP port",
423
+ message: "API port",
396
424
  initial: 9e3
397
425
  },
398
426
  {
@@ -401,6 +429,12 @@ async function runNew(projectName) {
401
429
  message: "Install admin dashboard?",
402
430
  initial: true
403
431
  },
432
+ {
433
+ type: (prev) => prev ? "number" : null,
434
+ name: "dashboardPort",
435
+ message: "Dashboard port",
436
+ initial: 5174
437
+ },
404
438
  {
405
439
  type: "confirm",
406
440
  name: "installDeps",
@@ -414,7 +448,8 @@ async function runNew(projectName) {
414
448
  name,
415
449
  databaseUrl: answers.databaseUrl,
416
450
  httpPort: answers.httpPort,
417
- dashboard: answers.dashboard
451
+ dashboard: answers.dashboard,
452
+ dashboardPort: answers.dashboardPort ?? 5174
418
453
  };
419
454
  const spinner = ora("Scaffolding project...").start();
420
455
  try {
@@ -443,7 +478,7 @@ async function runNew(projectName) {
443
478
  if (answers.installDeps) {
444
479
  const installSpinner = ora("Installing dependencies...").start();
445
480
  try {
446
- await execa("npm", ["install"], { cwd: targetDir, stdio: "pipe" });
481
+ await execa2("npm", ["install"], { cwd: targetDir, stdio: "pipe" });
447
482
  installSpinner.succeed("Dependencies installed");
448
483
  } catch (err) {
449
484
  installSpinner.warn("npm install failed \u2014 run it manually");
@@ -472,5 +507,6 @@ export {
472
507
  toKebabCase,
473
508
  writeFile,
474
509
  findProjectRoot,
510
+ readProjectPorts,
475
511
  runNew
476
512
  };
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  findProjectRoot,
4
+ readProjectPorts,
4
5
  renderModuleIndex,
5
6
  renderModuleLoader,
6
7
  renderModuleModel,
@@ -10,7 +11,7 @@ import {
10
11
  toKebabCase,
11
12
  toPascalCase,
12
13
  writeFile
13
- } from "./chunk-FNFHDPFG.js";
14
+ } from "./chunk-AVRGW4UO.js";
14
15
 
15
16
  // src/cli.ts
16
17
  import { Command } from "commander";
@@ -40,7 +41,8 @@ var MIME_TYPES = {
40
41
  ".woff": "font/woff",
41
42
  ".woff2": "font/woff2"
42
43
  };
43
- function startDashboardServer(distDir, port) {
44
+ function startDashboardServer(distDir, port, apiPort, apiHost = "localhost") {
45
+ const configScript = `<script>window.__MERIDIAN_CONFIG__ = { apiUrl: "http://${apiHost}:${apiPort}" };</script>`;
44
46
  return new Promise((resolve, reject) => {
45
47
  const server = http.createServer((req, res) => {
46
48
  const urlPath = (req.url ?? "/").split("?")[0];
@@ -49,6 +51,19 @@ function startDashboardServer(distDir, port) {
49
51
  filePath = path.join(distDir, "index.html");
50
52
  }
51
53
  const ext = path.extname(filePath);
54
+ if (ext === ".html") {
55
+ try {
56
+ const html = fs.readFileSync(filePath, "utf-8");
57
+ const injected = html.replace("<head>", `<head>
58
+ ${configScript}`);
59
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
60
+ res.end(injected);
61
+ } catch {
62
+ res.writeHead(404);
63
+ res.end("Not found");
64
+ }
65
+ return;
66
+ }
52
67
  const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
53
68
  fs.readFile(filePath, (err, data) => {
54
69
  if (err) {
@@ -64,7 +79,7 @@ function startDashboardServer(distDir, port) {
64
79
  server.on("error", reject);
65
80
  });
66
81
  }
67
- async function runServeDashboard(port = 5174) {
82
+ async function runServeDashboard(portOverride) {
68
83
  const rootDir = findProjectRoot();
69
84
  if (!rootDir) {
70
85
  console.error(chalk.red(" \u2716 Could not find meridian.config.ts. Are you inside a Meridian project?"));
@@ -76,8 +91,11 @@ async function runServeDashboard(port = 5174) {
76
91
  console.error(chalk.dim(" Run: npm install @meridianjs/admin-dashboard"));
77
92
  process.exit(1);
78
93
  }
79
- const server = await startDashboardServer(distDir, port);
80
- console.log(chalk.green(" \u2714 Admin dashboard running on ") + chalk.cyan(`http://localhost:${port}`));
94
+ const { apiPort, dashboardPort } = await readProjectPorts(rootDir);
95
+ const port = portOverride ?? dashboardPort;
96
+ const server = await startDashboardServer(distDir, port, apiPort);
97
+ console.log(chalk.green(" \u2714 Admin dashboard: ") + chalk.cyan(`http://localhost:${port}`));
98
+ console.log(chalk.dim(` \u2192 API: http://localhost:${apiPort}`));
81
99
  const shutdown = () => {
82
100
  server.close();
83
101
  process.exit(0);
@@ -100,13 +118,15 @@ async function runDev() {
100
118
  }
101
119
  const dashboardDist = path2.join(rootDir, "node_modules", "@meridianjs", "admin-dashboard", "dist");
102
120
  const hasDashboard = existsSync2(dashboardDist);
103
- const dashPort = Number(process.env.DASHBOARD_PORT ?? 5174);
121
+ const { apiPort, dashboardPort } = await readProjectPorts(rootDir);
104
122
  let dashServer = null;
105
123
  if (hasDashboard) {
106
- dashServer = await startDashboardServer(dashboardDist, dashPort);
107
- console.log(chalk2.dim(` \u2192 API server`) + chalk2.dim(` + `) + chalk2.dim(`admin dashboard on `) + chalk2.cyan(`http://localhost:${dashPort}`));
124
+ dashServer = await startDashboardServer(dashboardDist, dashboardPort, apiPort);
125
+ console.log(
126
+ chalk2.dim(" \u2192 API: ") + chalk2.cyan(`http://localhost:${apiPort}`) + chalk2.dim(" dashboard: ") + chalk2.cyan(`http://localhost:${dashboardPort}`)
127
+ );
108
128
  } else {
109
- console.log(chalk2.dim(` \u2192 Starting API server from ${rootDir}`));
129
+ console.log(chalk2.dim(` \u2192 API: http://localhost:${apiPort}`));
110
130
  }
111
131
  console.log();
112
132
  const apiProc = execa(
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runNew
4
- } from "./chunk-FNFHDPFG.js";
4
+ } from "./chunk-AVRGW4UO.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.1",
3
+ "version": "0.1.3",
4
4
  "description": "Create a new Meridian project or manage an existing one",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",