create-next-imagicma 0.1.9 → 0.1.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-next-imagicma",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-next-imagicma": "./bin/create-next-imagicma.mjs"
@@ -8,6 +8,11 @@ const LAUNCH_TOKEN_FILE = path.resolve(
8
8
  ".imagicma",
9
9
  "launch-token.json",
10
10
  );
11
+ const RUNTIME_ENV_FILE = path.resolve(
12
+ process.cwd(),
13
+ ".imagicma",
14
+ "runtime.env",
15
+ );
11
16
 
12
17
  function isScriptLaunch(mode: "dev" | "start") {
13
18
  return (
@@ -51,18 +56,47 @@ async function assertStartAuthorized() {
51
56
  );
52
57
  }
53
58
 
54
- function resolveRuntimePort(raw = process.env.PORT) {
55
- if (raw === undefined || raw === null || raw === "") {
56
- throw new Error("[imagicma] 缺少端口配置:请通过 PORT 提供运行时端口");
59
+ async function readRuntimeEnvPort() {
60
+ try {
61
+ const raw = await fs.readFile(RUNTIME_ENV_FILE, "utf8");
62
+ const lines = raw.split(/\r?\n/);
63
+ for (const line of lines) {
64
+ const trimmed = line.trim();
65
+ if (!trimmed || trimmed.startsWith("#")) continue;
66
+ const separatorIndex = trimmed.indexOf("=");
67
+ if (separatorIndex <= 0) continue;
68
+ const key = trimmed.slice(0, separatorIndex).trim();
69
+ if (key !== "PORT") continue;
70
+ return trimmed.slice(separatorIndex + 1).trim();
71
+ }
72
+ } catch (error) {
73
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
74
+ return null;
75
+ }
76
+ throw error;
77
+ }
78
+
79
+ return null;
80
+ }
81
+
82
+ async function resolveRuntimePort(raw = process.env.PORT) {
83
+ let candidate = raw;
84
+ if (candidate === undefined || candidate === null || candidate === "") {
85
+ candidate = await readRuntimeEnvPort();
86
+ }
87
+
88
+ if (candidate === undefined || candidate === null || candidate === "") {
89
+ throw new Error("[imagicma] 缺少端口配置:请通过 .imagicma/runtime.env 或 PORT 提供运行时端口");
57
90
  }
58
91
 
59
- const port = Number(raw);
92
+ const port = Number(candidate);
60
93
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
61
94
  throw new Error(
62
- `[imagicma] 无效端口配置:PORT=${JSON.stringify(raw)}(期望 1-65535 的整数)`,
95
+ `[imagicma] 无效端口配置:PORT=${JSON.stringify(candidate)}(期望 1-65535 的整数)`,
63
96
  );
64
97
  }
65
98
 
99
+ process.env.PORT = String(port);
66
100
  return port;
67
101
  }
68
102
 
@@ -70,7 +104,7 @@ async function main() {
70
104
  await assertStartAuthorized();
71
105
 
72
106
  const app = createApp({ serveClient: true });
73
- const port = resolveRuntimePort();
107
+ const port = await resolveRuntimePort();
74
108
 
75
109
  serve(
76
110
  {
@@ -14,6 +14,11 @@ const LAUNCH_TOKEN_FILE = path.resolve(
14
14
  ".imagicma",
15
15
  "launch-token.json",
16
16
  );
17
+ const RUNTIME_ENV_FILE = path.resolve(
18
+ __dirname,
19
+ ".imagicma",
20
+ "runtime.env",
21
+ );
17
22
 
18
23
  function isScriptLaunch(mode: "dev" | "start") {
19
24
  return (
@@ -22,18 +27,47 @@ function isScriptLaunch(mode: "dev" | "start") {
22
27
  );
23
28
  }
24
29
 
25
- function resolveRuntimePort(raw = process.env.PORT) {
26
- if (raw === undefined || raw === null || raw === "") {
27
- throw new Error("[imagicma] 缺少端口配置:请通过 PORT 提供运行时端口");
30
+ async function readRuntimeEnvPort() {
31
+ try {
32
+ const raw = await fs.readFile(RUNTIME_ENV_FILE, "utf8");
33
+ const lines = raw.split(/\r?\n/);
34
+ for (const line of lines) {
35
+ const trimmed = line.trim();
36
+ if (!trimmed || trimmed.startsWith("#")) continue;
37
+ const separatorIndex = trimmed.indexOf("=");
38
+ if (separatorIndex <= 0) continue;
39
+ const key = trimmed.slice(0, separatorIndex).trim();
40
+ if (key !== "PORT") continue;
41
+ return trimmed.slice(separatorIndex + 1).trim();
42
+ }
43
+ } catch (error) {
44
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
45
+ return null;
46
+ }
47
+ throw error;
48
+ }
49
+
50
+ return null;
51
+ }
52
+
53
+ async function resolveRuntimePort(raw = process.env.PORT) {
54
+ let candidate = raw;
55
+ if (candidate === undefined || candidate === null || candidate === "") {
56
+ candidate = await readRuntimeEnvPort();
57
+ }
58
+
59
+ if (candidate === undefined || candidate === null || candidate === "") {
60
+ throw new Error("[imagicma] 缺少端口配置:请通过 .imagicma/runtime.env 或 PORT 提供运行时端口");
28
61
  }
29
62
 
30
- const port = Number(raw);
63
+ const port = Number(candidate);
31
64
  if (!Number.isInteger(port) || port < 1 || port > 65535) {
32
65
  throw new Error(
33
- `[imagicma] 无效端口配置:PORT=${JSON.stringify(raw)}(期望 1-65535 的整数)`,
66
+ `[imagicma] 无效端口配置:PORT=${JSON.stringify(candidate)}(期望 1-65535 的整数)`,
34
67
  );
35
68
  }
36
69
 
70
+ process.env.PORT = String(port);
37
71
  return port;
38
72
  }
39
73
 
@@ -73,7 +107,7 @@ async function assertLaunchAuthorized(mode: "dev" | "start") {
73
107
  }
74
108
 
75
109
  export default defineConfig(async ({ command }) => {
76
- const runtimePort = command === "serve" ? resolveRuntimePort() : null;
110
+ const runtimePort = command === "serve" ? await resolveRuntimePort() : null;
77
111
  const enableComponentDebugger = command === "serve";
78
112
  const componentDebugger =
79
113
  enableComponentDebugger