@cedarjs/cli 4.0.0-canary.13868 → 4.0.0-canary.13870
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.
|
@@ -20,6 +20,7 @@ import { loadAndValidateSdls } from "@cedarjs/internal/dist/validateSchema";
|
|
|
20
20
|
import { detectPrerenderRoutes } from "@cedarjs/prerender/detection";
|
|
21
21
|
import {} from "@cedarjs/project-config";
|
|
22
22
|
import { timedTelemetry } from "@cedarjs/telemetry";
|
|
23
|
+
import { buildUDApiServer } from "@cedarjs/vite/buildUDApiServer";
|
|
23
24
|
import { generatePrismaCommand } from "../../lib/generatePrismaClient.js";
|
|
24
25
|
import { getPaths, getConfig } from "../../lib/index.js";
|
|
25
26
|
import { buildPackagesTask } from "./buildPackagesTask.js";
|
|
@@ -76,7 +77,8 @@ const handler = async ({
|
|
|
76
77
|
workspace = ["api", "web", "packages/*"],
|
|
77
78
|
verbose = false,
|
|
78
79
|
prisma = true,
|
|
79
|
-
prerender = true
|
|
80
|
+
prerender = true,
|
|
81
|
+
ud = false
|
|
80
82
|
}) => {
|
|
81
83
|
recordTelemetryAttributes({
|
|
82
84
|
command: "build",
|
|
@@ -161,6 +163,11 @@ Run ` + c.info(formatCedarCommand(["build"])) + " (without specifying a workspac
|
|
|
161
163
|
title: "Verifying graphql schema...",
|
|
162
164
|
task: loadAndValidateSdls
|
|
163
165
|
},
|
|
166
|
+
// The API build has two sequential steps:
|
|
167
|
+
// 1. esbuild compiles api/src/** → api/dist/ (functions, services, etc.)
|
|
168
|
+
// 2. Vite wraps api/dist/functions/ into a self-contained UD Node server
|
|
169
|
+
// entry at api/dist/ud/index.js for `cedar serve api`
|
|
170
|
+
// Step 2 depends on step 1 having completed.
|
|
164
171
|
workspace.includes("api") && {
|
|
165
172
|
title: "Building API...",
|
|
166
173
|
task: async () => {
|
|
@@ -168,6 +175,12 @@ Run ` + c.info(formatCedarCommand(["build"])) + " (without specifying a workspac
|
|
|
168
175
|
await buildApiWithVite();
|
|
169
176
|
}
|
|
170
177
|
},
|
|
178
|
+
ud && workspace.includes("api") && {
|
|
179
|
+
title: "Bundling API server entry (Universal Deploy)...",
|
|
180
|
+
task: async () => {
|
|
181
|
+
await buildUDApiServer({ verbose });
|
|
182
|
+
}
|
|
183
|
+
},
|
|
171
184
|
workspace.includes("web") && {
|
|
172
185
|
title: "Building Web...",
|
|
173
186
|
task: async () => {
|
package/dist/commands/build.js
CHANGED
|
@@ -25,6 +25,10 @@ const builder = (yargs) => {
|
|
|
25
25
|
alias: "db",
|
|
26
26
|
default: true,
|
|
27
27
|
description: "Generate the Prisma client"
|
|
28
|
+
}).option("ud", {
|
|
29
|
+
type: "boolean",
|
|
30
|
+
default: false,
|
|
31
|
+
description: "Build the Universal Deploy server entry (api/dist/ud/index.js)."
|
|
28
32
|
}).middleware(() => {
|
|
29
33
|
const check = checkNodeVersion();
|
|
30
34
|
if (check.ok) {
|
|
@@ -18,7 +18,8 @@ const handler = async ({
|
|
|
18
18
|
workspace = ["api", "web", "packages/*"],
|
|
19
19
|
forward = "",
|
|
20
20
|
generate = true,
|
|
21
|
-
apiDebugPort
|
|
21
|
+
apiDebugPort,
|
|
22
|
+
ud = false
|
|
22
23
|
}) => {
|
|
23
24
|
recordTelemetryAttributes({
|
|
24
25
|
command: "dev",
|
|
@@ -28,22 +29,26 @@ const handler = async ({
|
|
|
28
29
|
const cedarPaths = getPaths();
|
|
29
30
|
const serverFile = serverFileExists();
|
|
30
31
|
const apiPreferredPort = parseInt(String(getConfig().api.port));
|
|
32
|
+
let apiAvailablePort;
|
|
33
|
+
let apiPortChangeNeeded = false;
|
|
34
|
+
if (workspace.includes("api")) {
|
|
35
|
+
if (!serverFile) {
|
|
36
|
+
apiAvailablePort = await getFreePort(apiPreferredPort);
|
|
37
|
+
if (apiAvailablePort === -1) {
|
|
38
|
+
exitWithError(void 0, {
|
|
39
|
+
message: `Could not determine a free port for the api server`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
apiPortChangeNeeded = apiAvailablePort !== apiPreferredPort;
|
|
43
|
+
} else {
|
|
44
|
+
apiAvailablePort = apiPreferredPort;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
31
47
|
let webPreferredPort = parseInt(
|
|
32
48
|
String(getConfig().web.port)
|
|
33
49
|
);
|
|
34
|
-
let apiAvailablePort = apiPreferredPort;
|
|
35
|
-
let apiPortChangeNeeded = false;
|
|
36
50
|
let webAvailablePort = webPreferredPort;
|
|
37
51
|
let webPortChangeNeeded = false;
|
|
38
|
-
if (workspace.includes("api") && !serverFile) {
|
|
39
|
-
apiAvailablePort = await getFreePort(apiPreferredPort);
|
|
40
|
-
if (apiAvailablePort === -1) {
|
|
41
|
-
exitWithError(void 0, {
|
|
42
|
-
message: `Could not determine a free port for the api server`
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
apiPortChangeNeeded = apiAvailablePort !== apiPreferredPort;
|
|
46
|
-
}
|
|
47
52
|
if (workspace.includes("web")) {
|
|
48
53
|
const forwardedPortMatches = [
|
|
49
54
|
...forward.matchAll(/\-\-port(\=|\s)(?<port>[^\s]*)/g)
|
|
@@ -52,10 +57,10 @@ const handler = async ({
|
|
|
52
57
|
const port = forwardedPortMatches.pop()?.groups?.port;
|
|
53
58
|
webPreferredPort = port ? parseInt(port, 10) : void 0;
|
|
54
59
|
}
|
|
55
|
-
webAvailablePort = await getFreePort(
|
|
56
|
-
|
|
57
|
-
apiAvailablePort
|
|
58
|
-
|
|
60
|
+
webAvailablePort = await getFreePort(
|
|
61
|
+
webPreferredPort,
|
|
62
|
+
apiAvailablePort !== void 0 ? [apiPreferredPort, apiAvailablePort] : [apiPreferredPort]
|
|
63
|
+
);
|
|
59
64
|
if (webAvailablePort === -1) {
|
|
60
65
|
exitWithError(void 0, {
|
|
61
66
|
message: `Could not determine a free port for the web server`
|
|
@@ -63,21 +68,17 @@ const handler = async ({
|
|
|
63
68
|
}
|
|
64
69
|
webPortChangeNeeded = webAvailablePort !== webPreferredPort;
|
|
65
70
|
}
|
|
66
|
-
if (
|
|
71
|
+
if (webPortChangeNeeded) {
|
|
67
72
|
const message = [
|
|
68
|
-
"The currently configured
|
|
69
|
-
"unavailable. Suggested
|
|
70
|
-
"cedar.toml (or redwood.toml)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
"The currently configured port for the development server is",
|
|
74
|
+
"unavailable. Suggested change to your port, which can be changed in",
|
|
75
|
+
"cedar.toml (or redwood.toml):\n",
|
|
76
|
+
` - Web to use port ${webAvailablePort} instead`,
|
|
77
|
+
"of your currently configured",
|
|
78
|
+
`${webPreferredPort}
|
|
74
79
|
`,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
webPortChangeNeeded && `${webPreferredPort}
|
|
78
|
-
`,
|
|
79
|
-
"\nCannot run the development server until your configured ports are",
|
|
80
|
-
"changed or become available."
|
|
80
|
+
"\nCannot run the development server until your configured port is",
|
|
81
|
+
"changed or becomes available."
|
|
81
82
|
].filter(Boolean).join(" ");
|
|
82
83
|
exitWithError(void 0, { message });
|
|
83
84
|
}
|
|
@@ -89,19 +90,8 @@ const handler = async ({
|
|
|
89
90
|
errorTelemetry(process.argv, `Error generating prisma client: ${message}`);
|
|
90
91
|
console.error(c.error(message));
|
|
91
92
|
}
|
|
92
|
-
if (!serverFile) {
|
|
93
|
-
try {
|
|
94
|
-
await shutdownPort(apiAvailablePort);
|
|
95
|
-
} catch (e) {
|
|
96
|
-
const message = getErrorMessage(e);
|
|
97
|
-
errorTelemetry(process.argv, `Error shutting down "api": ${message}`);
|
|
98
|
-
console.error(
|
|
99
|
-
`Error whilst shutting down "api" port: ${c.error(message)}`
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
93
|
}
|
|
104
|
-
if (workspace.includes("web")) {
|
|
94
|
+
if (workspace.includes("web") && webAvailablePort !== void 0) {
|
|
105
95
|
try {
|
|
106
96
|
await shutdownPort(webAvailablePort);
|
|
107
97
|
} catch (e) {
|
|
@@ -127,6 +117,9 @@ const handler = async ({
|
|
|
127
117
|
fs.readFileSync(rootPackageJsonPath, "utf8")
|
|
128
118
|
);
|
|
129
119
|
const buildUnifiedDevCommand = () => {
|
|
120
|
+
if (!ud) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
130
123
|
if (streamingSsrEnabled) {
|
|
131
124
|
return null;
|
|
132
125
|
}
|
|
@@ -149,6 +142,20 @@ const handler = async ({
|
|
|
149
142
|
].join(" ").replace(/\s+/g, " ").trim();
|
|
150
143
|
};
|
|
151
144
|
const unifiedDevCommand = buildUnifiedDevCommand();
|
|
145
|
+
if (!unifiedDevCommand && apiPortChangeNeeded) {
|
|
146
|
+
const message = [
|
|
147
|
+
"The currently configured port for the development server is",
|
|
148
|
+
"unavailable. Suggested change to your port, which can be changed in",
|
|
149
|
+
"cedar.toml (or redwood.toml):\n",
|
|
150
|
+
` - API to use port ${apiAvailablePort} instead`,
|
|
151
|
+
"of your currently configured",
|
|
152
|
+
`${apiPreferredPort}
|
|
153
|
+
`,
|
|
154
|
+
"\nCannot run the development server until your configured port is",
|
|
155
|
+
"changed or becomes available."
|
|
156
|
+
].filter(Boolean).join(" ");
|
|
157
|
+
exitWithError(void 0, { message });
|
|
158
|
+
}
|
|
152
159
|
const jobs = [];
|
|
153
160
|
if (unifiedDevCommand) {
|
|
154
161
|
jobs.push({
|
package/dist/commands/dev.js
CHANGED
|
@@ -24,6 +24,10 @@ const builder = (yargs) => {
|
|
|
24
24
|
}).option("apiDebugPort", {
|
|
25
25
|
type: "number",
|
|
26
26
|
description: "Port on which to expose API server debugger. If you supply the flag with no value it defaults to 1 prepended to the api port (e.g. api port 8913 -> debug port 18913)."
|
|
27
|
+
}).option("ud", {
|
|
28
|
+
type: "boolean",
|
|
29
|
+
default: false,
|
|
30
|
+
description: "Use the unified Vite dev server that handles both web and API in a single process (experimental)."
|
|
27
31
|
}).middleware(() => {
|
|
28
32
|
const check = checkNodeVersion();
|
|
29
33
|
if (check.ok) {
|
package/dist/commands/serve.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { fork } from "node:child_process";
|
|
1
2
|
import fs from "node:fs";
|
|
2
|
-
import path from "path";
|
|
3
|
+
import path from "node:path";
|
|
3
4
|
import { terminalLink } from "termi-link";
|
|
4
5
|
import * as apiServerCLIConfig from "@cedarjs/api-server/apiCliConfig";
|
|
5
6
|
import * as bothServerCLIConfig from "@cedarjs/api-server/bothCliConfig";
|
|
@@ -43,7 +44,18 @@ const builder = async (yargs) => {
|
|
|
43
44
|
}).command({
|
|
44
45
|
command: "api",
|
|
45
46
|
description: apiServerCLIConfig.description,
|
|
46
|
-
builder:
|
|
47
|
+
builder: (yargs2) => {
|
|
48
|
+
if (typeof apiServerCLIConfig.builder === "function") {
|
|
49
|
+
apiServerCLIConfig.builder(yargs2);
|
|
50
|
+
}
|
|
51
|
+
return yargs2.option("ud", {
|
|
52
|
+
// UD serving is opt-in. Pass --ud to use the new srvx server instead
|
|
53
|
+
// of the legacy Fastify server.
|
|
54
|
+
description: "Use the Universal Deploy server (srvx). Pass --ud to opt in; the default is Fastify.",
|
|
55
|
+
type: "boolean",
|
|
56
|
+
default: false
|
|
57
|
+
});
|
|
58
|
+
},
|
|
47
59
|
handler: async (argv) => {
|
|
48
60
|
recordTelemetryAttributes({
|
|
49
61
|
command: "serve",
|
|
@@ -52,6 +64,47 @@ const builder = async (yargs) => {
|
|
|
52
64
|
socket: argv.socket,
|
|
53
65
|
apiRootPath: argv.apiRootPath
|
|
54
66
|
});
|
|
67
|
+
if (argv.ud) {
|
|
68
|
+
const udEntryPath = path.join(getPaths().api.dist, "ud", "index.js");
|
|
69
|
+
if (!fs.existsSync(udEntryPath)) {
|
|
70
|
+
console.error(
|
|
71
|
+
c.error(
|
|
72
|
+
`
|
|
73
|
+
Universal Deploy server entry not found at ${udEntryPath}.
|
|
74
|
+
Please run \`yarn cedar build api\` before serving.
|
|
75
|
+
`
|
|
76
|
+
)
|
|
77
|
+
);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
const udArgs = [];
|
|
81
|
+
if (argv.port) {
|
|
82
|
+
udArgs.push("--port", String(argv.port));
|
|
83
|
+
}
|
|
84
|
+
if (argv.host) {
|
|
85
|
+
udArgs.push("--host", argv.host);
|
|
86
|
+
}
|
|
87
|
+
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
|
+
child.on("exit", (code) => {
|
|
99
|
+
if (code !== 0) {
|
|
100
|
+
reject(new Error(`UD server exited with code ${code}`));
|
|
101
|
+
} else {
|
|
102
|
+
resolve();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
55
108
|
if (serverFileExists()) {
|
|
56
109
|
const { apiServerFileHandler } = await import("./serveApiHandler.js");
|
|
57
110
|
await apiServerFileHandler(argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cedarjs/cli",
|
|
3
|
-
"version": "4.0.0-canary.
|
|
3
|
+
"version": "4.0.0-canary.13870+b45da21869",
|
|
4
4
|
"description": "The CedarJS Command Line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@babel/parser": "7.29.2",
|
|
35
35
|
"@babel/preset-typescript": "7.28.5",
|
|
36
|
-
"@cedarjs/api-server": "4.0.0-canary.
|
|
37
|
-
"@cedarjs/cli-helpers": "4.0.0-canary.
|
|
38
|
-
"@cedarjs/fastify-web": "4.0.0-canary.
|
|
39
|
-
"@cedarjs/internal": "4.0.0-canary.
|
|
40
|
-
"@cedarjs/prerender": "4.0.0-canary.
|
|
41
|
-
"@cedarjs/project-config": "4.0.0-canary.
|
|
42
|
-
"@cedarjs/structure": "4.0.0-canary.
|
|
43
|
-
"@cedarjs/telemetry": "4.0.0-canary.
|
|
44
|
-
"@cedarjs/utils": "4.0.0-canary.
|
|
45
|
-
"@cedarjs/web-server": "4.0.0-canary.
|
|
36
|
+
"@cedarjs/api-server": "4.0.0-canary.13870",
|
|
37
|
+
"@cedarjs/cli-helpers": "4.0.0-canary.13870",
|
|
38
|
+
"@cedarjs/fastify-web": "4.0.0-canary.13870",
|
|
39
|
+
"@cedarjs/internal": "4.0.0-canary.13870",
|
|
40
|
+
"@cedarjs/prerender": "4.0.0-canary.13870",
|
|
41
|
+
"@cedarjs/project-config": "4.0.0-canary.13870",
|
|
42
|
+
"@cedarjs/structure": "4.0.0-canary.13870",
|
|
43
|
+
"@cedarjs/telemetry": "4.0.0-canary.13870",
|
|
44
|
+
"@cedarjs/utils": "4.0.0-canary.13870",
|
|
45
|
+
"@cedarjs/web-server": "4.0.0-canary.13870",
|
|
46
46
|
"@listr2/prompt-adapter-enquirer": "4.2.1",
|
|
47
47
|
"@opentelemetry/api": "1.9.0",
|
|
48
48
|
"@opentelemetry/core": "1.30.1",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "b45da21869cec79bedc40b47868d54fd598786ac"
|
|
112
112
|
}
|