@cedarjs/cli 5.0.0-canary.13899 → 5.0.0-canary.13902
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/commands/serve.js +215 -20
- package/package.json +13 -13
package/dist/commands/serve.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fork } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
import net from "node:net";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { terminalLink } from "termi-link";
|
|
5
6
|
import * as apiServerCLIConfig from "@cedarjs/api-server/apiCliConfig";
|
|
@@ -18,7 +19,14 @@ const builder = async (yargs) => {
|
|
|
18
19
|
yargs.command({
|
|
19
20
|
command: "$0",
|
|
20
21
|
description: bothServerCLIConfig.description,
|
|
21
|
-
builder:
|
|
22
|
+
builder: (yargs2) => {
|
|
23
|
+
bothServerCLIConfig.builder(yargs2);
|
|
24
|
+
return yargs2.option("ud", {
|
|
25
|
+
description: "Use the Universal Deploy server (srvx) for the API side. The web side is served by the existing static file server. Pass --ud to opt in; the default is Fastify for both sides.",
|
|
26
|
+
type: "boolean",
|
|
27
|
+
default: false
|
|
28
|
+
});
|
|
29
|
+
},
|
|
22
30
|
handler: async (argv) => {
|
|
23
31
|
recordTelemetryAttributes({
|
|
24
32
|
command: "serve",
|
|
@@ -26,6 +34,110 @@ const builder = async (yargs) => {
|
|
|
26
34
|
host: argv.host,
|
|
27
35
|
socket: argv.socket
|
|
28
36
|
});
|
|
37
|
+
if (argv.ud) {
|
|
38
|
+
if (argv.port) {
|
|
39
|
+
console.error(
|
|
40
|
+
c.error(
|
|
41
|
+
"\n The --port flag is not supported with --ud. Use --web-port and --api-port instead.\n"
|
|
42
|
+
)
|
|
43
|
+
);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
const udEntryPath = path.join(getPaths().api.dist, "ud", "index.js");
|
|
47
|
+
if (!fs.existsSync(udEntryPath)) {
|
|
48
|
+
console.error(
|
|
49
|
+
c.error(
|
|
50
|
+
`
|
|
51
|
+
Universal Deploy server entry not found at ${udEntryPath}.
|
|
52
|
+
Please run \`yarn cedar build --ud\` before serving.
|
|
53
|
+
`
|
|
54
|
+
)
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
const webDistIndexHtml = path.join(getPaths().web.dist, "index.html");
|
|
59
|
+
if (!fs.existsSync(webDistIndexHtml)) {
|
|
60
|
+
console.error(
|
|
61
|
+
c.error(
|
|
62
|
+
"\n Web build artifacts not found.\n Please run `yarn cedar build` before serving.\n"
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
if (serverFileExists()) {
|
|
68
|
+
console.warn(
|
|
69
|
+
c.warning(
|
|
70
|
+
"\n Note: api/src/server.ts was detected. This file is a Fastify concept and will be ignored when using --ud. You are testing the experimental UD support, so the behavior will not match your production Fastify setup.\n"
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const { getAPIHost, getAPIPort, getWebHost, getWebPort } = await import("@cedarjs/api-server/cliHelpers");
|
|
75
|
+
const apiPort = argv.apiPort ?? getAPIPort();
|
|
76
|
+
const apiHost = argv.apiHost ?? getAPIHost();
|
|
77
|
+
const webPort = argv.webPort ?? getWebPort();
|
|
78
|
+
const webHost = argv.webHost ?? getWebHost();
|
|
79
|
+
const apiRootPath = argv.apiRootPath ?? "/";
|
|
80
|
+
const apiProxyTarget = [
|
|
81
|
+
"http://",
|
|
82
|
+
apiHost.includes(":") ? `[${apiHost}]` : apiHost,
|
|
83
|
+
":",
|
|
84
|
+
apiPort,
|
|
85
|
+
apiRootPath
|
|
86
|
+
].join("");
|
|
87
|
+
const { redwoodFastifyWeb } = await import("@cedarjs/fastify-web");
|
|
88
|
+
const { createFastifyInstance } = await import("@cedarjs/api-server/fastify");
|
|
89
|
+
const webFastify = await createFastifyInstance();
|
|
90
|
+
webFastify.register(redwoodFastifyWeb, {
|
|
91
|
+
redwood: {
|
|
92
|
+
apiProxyTarget
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
await webFastify.listen({
|
|
96
|
+
port: webPort,
|
|
97
|
+
host: webHost
|
|
98
|
+
});
|
|
99
|
+
const child = fork(
|
|
100
|
+
udEntryPath,
|
|
101
|
+
["--port", String(apiPort), "--host", apiHost],
|
|
102
|
+
{
|
|
103
|
+
execArgv: process.execArgv,
|
|
104
|
+
env: {
|
|
105
|
+
...process.env,
|
|
106
|
+
NODE_ENV: process.env.NODE_ENV ?? "production",
|
|
107
|
+
PORT: String(apiPort),
|
|
108
|
+
HOST: apiHost
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
child.on("error", (err) => {
|
|
113
|
+
console.error(
|
|
114
|
+
c.error(`
|
|
115
|
+
Failed to start UD API server: ${err.message}
|
|
116
|
+
`)
|
|
117
|
+
);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
});
|
|
120
|
+
child.on("exit", (code) => {
|
|
121
|
+
if (code !== 0) {
|
|
122
|
+
console.error(
|
|
123
|
+
c.error(`
|
|
124
|
+
UD API server exited with code ${code}
|
|
125
|
+
`)
|
|
126
|
+
);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
console.log(`Web server listening at http://${webHost}:${webPort}`);
|
|
131
|
+
process.stdout.write(
|
|
132
|
+
`API server starting at http://${apiHost}:${apiPort}...`
|
|
133
|
+
);
|
|
134
|
+
await waitForPort(apiHost, apiPort);
|
|
135
|
+
process.stdout.write(
|
|
136
|
+
`\rAPI server listening at http://${apiHost}:${apiPort}
|
|
137
|
+
`
|
|
138
|
+
);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
29
141
|
if (serverFileExists()) {
|
|
30
142
|
const serveBothHandlers = await import("./serveBothHandler.js");
|
|
31
143
|
await serveBothHandlers.bothServerFileHandler(argv);
|
|
@@ -71,7 +183,7 @@ const builder = async (yargs) => {
|
|
|
71
183
|
c.error(
|
|
72
184
|
`
|
|
73
185
|
Universal Deploy server entry not found at ${udEntryPath}.
|
|
74
|
-
Please run \`yarn cedar build
|
|
186
|
+
Please run \`yarn cedar build --ud\` before serving.
|
|
75
187
|
`
|
|
76
188
|
)
|
|
77
189
|
);
|
|
@@ -84,17 +196,34 @@ const builder = async (yargs) => {
|
|
|
84
196
|
if (argv.host) {
|
|
85
197
|
udArgs.push("--host", argv.host);
|
|
86
198
|
}
|
|
199
|
+
const child = fork(udEntryPath, udArgs, {
|
|
200
|
+
execArgv: process.execArgv,
|
|
201
|
+
env: {
|
|
202
|
+
...process.env,
|
|
203
|
+
NODE_ENV: process.env.NODE_ENV ?? "production",
|
|
204
|
+
PORT: argv.port ? String(argv.port) : process.env.PORT,
|
|
205
|
+
HOST: argv.host ?? process.env.HOST
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
child.on("error", (err) => {
|
|
209
|
+
console.error(
|
|
210
|
+
c.error(`
|
|
211
|
+
Failed to start UD server: ${err.message}
|
|
212
|
+
`)
|
|
213
|
+
);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
});
|
|
216
|
+
const apiPort = argv.port ?? parseInt(process.env.PORT ?? "8911", 10);
|
|
217
|
+
const apiHost = argv.host ?? process.env.HOST ?? "localhost";
|
|
218
|
+
process.stdout.write(
|
|
219
|
+
`API server starting at http://${apiHost}:${apiPort}...`
|
|
220
|
+
);
|
|
221
|
+
await waitForPort(apiHost, apiPort);
|
|
222
|
+
process.stdout.write(
|
|
223
|
+
`\rAPI server listening at http://${apiHost}:${apiPort}
|
|
224
|
+
`
|
|
225
|
+
);
|
|
87
226
|
await new Promise((resolve, reject) => {
|
|
88
|
-
const child = fork(udEntryPath, udArgs, {
|
|
89
|
-
execArgv: process.execArgv,
|
|
90
|
-
env: {
|
|
91
|
-
...process.env,
|
|
92
|
-
NODE_ENV: process.env.NODE_ENV ?? "production",
|
|
93
|
-
PORT: argv.port ? String(argv.port) : process.env.PORT,
|
|
94
|
-
HOST: argv.host ?? process.env.HOST
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
child.on("error", reject);
|
|
98
227
|
child.on("exit", (code) => {
|
|
99
228
|
if (code !== 0) {
|
|
100
229
|
reject(new Error(`UD server exited with code ${code}`));
|
|
@@ -166,6 +295,20 @@ const builder = async (yargs) => {
|
|
|
166
295
|
);
|
|
167
296
|
process.exit(1);
|
|
168
297
|
}
|
|
298
|
+
if (argv.ud) {
|
|
299
|
+
const udEntryPath = path.join(getPaths().api.dist, "ud", "index.js");
|
|
300
|
+
if (!fs.existsSync(udEntryPath)) {
|
|
301
|
+
console.error(
|
|
302
|
+
c.error(
|
|
303
|
+
`
|
|
304
|
+
Universal Deploy server entry not found at ${udEntryPath}.
|
|
305
|
+
Please run \`yarn cedar build --ud\` before serving.
|
|
306
|
+
`
|
|
307
|
+
)
|
|
308
|
+
);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
169
312
|
}
|
|
170
313
|
if (positionalArgs.length === 1) {
|
|
171
314
|
if (!apiSideExists && !rscEnabled) {
|
|
@@ -176,14 +319,38 @@ const builder = async (yargs) => {
|
|
|
176
319
|
);
|
|
177
320
|
process.exit(1);
|
|
178
321
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
322
|
+
if (argv.ud) {
|
|
323
|
+
const udEntryPath = path.join(getPaths().api.dist, "ud", "index.js");
|
|
324
|
+
if (!fs.existsSync(udEntryPath)) {
|
|
325
|
+
console.error(
|
|
326
|
+
c.error(
|
|
327
|
+
`
|
|
328
|
+
Universal Deploy server entry not found at ${udEntryPath}.
|
|
329
|
+
Please run \`yarn cedar build --ud\` before serving.
|
|
330
|
+
`
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
const webDistIndexHtml = path.join(getPaths().web.dist, "index.html");
|
|
336
|
+
if (!fs.existsSync(webDistIndexHtml)) {
|
|
337
|
+
console.error(
|
|
338
|
+
c.error(
|
|
339
|
+
"\n Web build artifacts not found.\n Please run `yarn cedar build` before serving.\n"
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
process.exit(1);
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
const apiExistsButIsNotBuilt = apiSideExists && !fs.existsSync(getPaths().api.dist);
|
|
346
|
+
if (apiExistsButIsNotBuilt || !webSideIsBuilt(streamingEnabled || rscEnabled)) {
|
|
347
|
+
console.error(
|
|
348
|
+
c.error(
|
|
349
|
+
"\nPlease run `yarn cedar build` before trying to serve your Cedar app.\n"
|
|
350
|
+
)
|
|
351
|
+
);
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
187
354
|
}
|
|
188
355
|
}
|
|
189
356
|
if (!process.env.NODE_ENV) {
|
|
@@ -205,6 +372,34 @@ function webSideIsBuilt(isStreamingOrRSC) {
|
|
|
205
372
|
return fs.existsSync(path.join(getPaths().web.dist, "index.html"));
|
|
206
373
|
}
|
|
207
374
|
}
|
|
375
|
+
function waitForPort(host, port) {
|
|
376
|
+
const maxAttempts = 50;
|
|
377
|
+
const intervalMs = 200;
|
|
378
|
+
return new Promise((resolve, reject) => {
|
|
379
|
+
let attempts = 0;
|
|
380
|
+
const tryConnect = () => {
|
|
381
|
+
attempts++;
|
|
382
|
+
const socket = net.createConnection({ host, port });
|
|
383
|
+
socket.on("connect", () => {
|
|
384
|
+
socket.destroy();
|
|
385
|
+
resolve();
|
|
386
|
+
});
|
|
387
|
+
socket.on("error", () => {
|
|
388
|
+
socket.destroy();
|
|
389
|
+
if (attempts >= maxAttempts) {
|
|
390
|
+
reject(
|
|
391
|
+
new Error(
|
|
392
|
+
`API server did not become ready on port ${port} after ${maxAttempts * intervalMs}ms`
|
|
393
|
+
)
|
|
394
|
+
);
|
|
395
|
+
} else {
|
|
396
|
+
setTimeout(tryConnect, intervalMs);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
tryConnect();
|
|
401
|
+
});
|
|
402
|
+
}
|
|
208
403
|
export {
|
|
209
404
|
builder,
|
|
210
405
|
command,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "5.0.0-canary.
|
|
3
|
+
"version": "5.0.0-canary.13902+61d1e11811",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@babel/parser": "7.29.2",
|
|
35
35
|
"@babel/preset-typescript": "7.28.5",
|
|
36
|
-
"@cedarjs/api-server": "5.0.0-canary.
|
|
37
|
-
"@cedarjs/cli-helpers": "5.0.0-canary.
|
|
38
|
-
"@cedarjs/fastify-web": "5.0.0-canary.
|
|
39
|
-
"@cedarjs/internal": "5.0.0-canary.
|
|
40
|
-
"@cedarjs/prerender": "5.0.0-canary.
|
|
41
|
-
"@cedarjs/project-config": "5.0.0-canary.
|
|
42
|
-
"@cedarjs/structure": "5.0.0-canary.
|
|
43
|
-
"@cedarjs/telemetry": "5.0.0-canary.
|
|
44
|
-
"@cedarjs/utils": "5.0.0-canary.
|
|
45
|
-
"@cedarjs/vite": "5.0.0-canary.
|
|
46
|
-
"@cedarjs/web-server": "5.0.0-canary.
|
|
36
|
+
"@cedarjs/api-server": "5.0.0-canary.13902",
|
|
37
|
+
"@cedarjs/cli-helpers": "5.0.0-canary.13902",
|
|
38
|
+
"@cedarjs/fastify-web": "5.0.0-canary.13902",
|
|
39
|
+
"@cedarjs/internal": "5.0.0-canary.13902",
|
|
40
|
+
"@cedarjs/prerender": "5.0.0-canary.13902",
|
|
41
|
+
"@cedarjs/project-config": "5.0.0-canary.13902",
|
|
42
|
+
"@cedarjs/structure": "5.0.0-canary.13902",
|
|
43
|
+
"@cedarjs/telemetry": "5.0.0-canary.13902",
|
|
44
|
+
"@cedarjs/utils": "5.0.0-canary.13902",
|
|
45
|
+
"@cedarjs/vite": "5.0.0-canary.13902",
|
|
46
|
+
"@cedarjs/web-server": "5.0.0-canary.13902",
|
|
47
47
|
"@listr2/prompt-adapter-enquirer": "4.2.1",
|
|
48
48
|
"@opentelemetry/api": "1.9.0",
|
|
49
49
|
"@opentelemetry/core": "1.30.1",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "61d1e11811bdc624db5b3aab49346430cfc963bc"
|
|
112
112
|
}
|