@cedarjs/vite 5.0.0-canary.13889 → 5.0.0-canary.13892
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/apiDevMiddleware.d.ts +15 -0
- package/dist/apiDevMiddleware.d.ts.map +1 -0
- package/dist/{apiDevServer.js → apiDevMiddleware.js} +81 -101
- package/dist/build/build.d.ts +1 -1
- package/dist/build/build.d.ts.map +1 -1
- package/dist/build/build.js +2 -0
- package/dist/buildApp.d.ts +15 -0
- package/dist/buildApp.d.ts.map +1 -0
- package/dist/buildApp.js +150 -0
- package/dist/cedar-unified-dev.js +59 -5
- package/dist/cjs/{apiDevServer.js → apiDevMiddleware.js} +88 -104
- package/dist/cjs/build/build.js +3 -0
- package/dist/cjs/buildApp.js +181 -0
- package/dist/cjs/cedar-unified-dev.js +59 -5
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/plugins/vite-plugin-cedar-cjs-compat.js +341 -0
- package/dist/cjs/plugins/vite-plugin-cedar-wait-for-api-server.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/plugins/vite-plugin-cedar-cjs-compat.d.ts +23 -0
- package/dist/plugins/vite-plugin-cedar-cjs-compat.d.ts.map +1 -0
- package/dist/plugins/vite-plugin-cedar-cjs-compat.js +307 -0
- package/dist/plugins/vite-plugin-cedar-wait-for-api-server.d.ts.map +1 -1
- package/dist/plugins/vite-plugin-cedar-wait-for-api-server.js +2 -1
- package/package.json +15 -19
- package/dist/apiDevServer.d.ts +0 -18
- package/dist/apiDevServer.d.ts.map +0 -1
- package/dist/cjs/plugins/vite-plugin-cedar-dev-dispatcher.js +0 -223
- package/dist/plugins/vite-plugin-cedar-dev-dispatcher.d.ts +0 -3
- package/dist/plugins/vite-plugin-cedar-dev-dispatcher.d.ts.map +0 -1
- package/dist/plugins/vite-plugin-cedar-dev-dispatcher.js +0 -189
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ViteDevServer } from 'vite';
|
|
2
|
+
export declare function loadApiFunctions(viteServer: ViteDevServer): Promise<void>;
|
|
3
|
+
export declare function createApiViteServer(): Promise<ViteDevServer>;
|
|
4
|
+
export declare function setupHmrHandlers(viteServer: ViteDevServer): void;
|
|
5
|
+
/**
|
|
6
|
+
* Creates a fetch-native handler for API requests.
|
|
7
|
+
* Routes GraphQL to Yoga and Lambda functions to their handlers.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createApiFetchHandler(): (request: Request) => Promise<Response>;
|
|
10
|
+
export declare function startApiDevMiddleware(): Promise<{
|
|
11
|
+
viteServer: ViteDevServer;
|
|
12
|
+
close: () => Promise<void>;
|
|
13
|
+
handler: (request: Request) => Promise<Response>;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=apiDevMiddleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiDevMiddleware.d.ts","sourceRoot":"","sources":["../src/apiDevMiddleware.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,MAAM,CAAA;AA2BrD,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,aAAa,iBAe/D;AA0FD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAuElE;AA0BD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,aAAa,GAAG,IAAI,CA0EhE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,KAIrB,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAoEnD;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IACrD,UAAU,EAAE,aAAa,CAAA;IACzB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACjD,CAAC,CAcD"}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import { glob } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
-
import fastifyUrlData from "@fastify/url-data";
|
|
5
4
|
import ansis from "ansis";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import { createServer as createViteServer, normalizePath } from "vite";
|
|
9
|
-
import { requestHandler } from "@cedarjs/api-server/requestHandlers";
|
|
5
|
+
import { normalizePath } from "vite";
|
|
6
|
+
import { buildCedarContext, wrapLegacyHandler } from "@cedarjs/api/runtime";
|
|
10
7
|
import {
|
|
11
8
|
getApiSideBabelPlugins,
|
|
12
9
|
transformWithBabel
|
|
@@ -56,13 +53,6 @@ async function internalLoadApiFunctions(viteServer) {
|
|
|
56
53
|
} catch {
|
|
57
54
|
srcFunctions = [];
|
|
58
55
|
}
|
|
59
|
-
const graphqlFunctionIndex = srcFunctions.findIndex(
|
|
60
|
-
(f) => path.basename(f).startsWith("graphql.")
|
|
61
|
-
);
|
|
62
|
-
if (graphqlFunctionIndex > 0) {
|
|
63
|
-
const [graphqlFn] = srcFunctions.splice(graphqlFunctionIndex, 1);
|
|
64
|
-
srcFunctions.unshift(graphqlFn);
|
|
65
|
-
}
|
|
66
56
|
console.log(ansis.dim.italic("Importing Server Functions... "));
|
|
67
57
|
const tsImport = Date.now();
|
|
68
58
|
let extractedGraphqlOptions = null;
|
|
@@ -88,7 +78,7 @@ async function internalLoadApiFunctions(viteServer) {
|
|
|
88
78
|
);
|
|
89
79
|
} else {
|
|
90
80
|
console.warn(
|
|
91
|
-
`[
|
|
81
|
+
`[apiDevMiddleware] No handler export found in function: ${fnPath}`
|
|
92
82
|
);
|
|
93
83
|
}
|
|
94
84
|
if (routeName === "graphql" && "__rw_graphqlOptions" in mod) {
|
|
@@ -97,7 +87,7 @@ async function internalLoadApiFunctions(viteServer) {
|
|
|
97
87
|
} catch (err) {
|
|
98
88
|
viteServer.ssrFixStacktrace(err);
|
|
99
89
|
console.error(
|
|
100
|
-
`[
|
|
90
|
+
`[apiDevMiddleware] Failed to load function "${routeName}" from ${fnPath}:`,
|
|
101
91
|
err
|
|
102
92
|
);
|
|
103
93
|
}
|
|
@@ -106,56 +96,29 @@ async function internalLoadApiFunctions(viteServer) {
|
|
|
106
96
|
if (extractedGraphqlOptions) {
|
|
107
97
|
const { yoga } = await createGraphQLYoga(extractedGraphqlOptions);
|
|
108
98
|
graphqlYoga = yoga;
|
|
99
|
+
} else {
|
|
100
|
+
graphqlYoga = null;
|
|
109
101
|
}
|
|
110
102
|
console.log(
|
|
111
103
|
ansis.dim.italic("...Done importing in " + (Date.now() - tsImport) + " ms")
|
|
112
104
|
);
|
|
113
105
|
}
|
|
114
|
-
function
|
|
115
|
-
const requestBody = req.method === "GET" || req.method === "HEAD" ? void 0 : typeof req.body === "string" ? req.body : req.body ? JSON.stringify(req.body) : void 0;
|
|
116
|
-
const href = `${req.protocol}://${req.host}${req.raw.url ?? "/"}`;
|
|
117
|
-
return new Request(href, {
|
|
118
|
-
method: req.method,
|
|
119
|
-
headers: req.headers,
|
|
120
|
-
body: requestBody
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
async function startApiDevServer(port) {
|
|
106
|
+
async function createApiViteServer() {
|
|
124
107
|
const cedarPaths = getPaths();
|
|
125
108
|
const cedarConfig = getConfig();
|
|
126
|
-
const apiPort = port || cedarConfig.api.port || 8911;
|
|
127
|
-
const apiHost = cedarConfig.api.host || "::";
|
|
128
109
|
const isEsm = projectSideIsEsm("api");
|
|
129
110
|
const normalizedBase = normalizePath(cedarPaths.base);
|
|
130
|
-
const normalizedApiSrc = normalizePath(cedarPaths.api.src);
|
|
131
|
-
const normalizedApiBase = normalizePath(cedarPaths.api.base);
|
|
132
|
-
const viteServer = await createViteDevServer(
|
|
133
|
-
cedarPaths,
|
|
134
|
-
cedarConfig,
|
|
135
|
-
isEsm,
|
|
136
|
-
normalizedBase
|
|
137
|
-
);
|
|
138
|
-
console.log(ansis.dim.italic("Starting API dev server..."));
|
|
139
|
-
await loadApiFunctions(viteServer);
|
|
140
|
-
setupHmrHandlers(viteServer, normalizedApiSrc, normalizedApiBase);
|
|
141
|
-
const app = await createFastifyApp(apiPort, apiHost);
|
|
142
|
-
const close = async () => {
|
|
143
|
-
await app.close();
|
|
144
|
-
await viteServer.close();
|
|
145
|
-
};
|
|
146
|
-
return { viteServer, close };
|
|
147
|
-
}
|
|
148
|
-
async function createViteDevServer(cedarPaths, cedarConfig, projectIsEsm, normalizedBase) {
|
|
149
111
|
const babelPlugins = getApiSideBabelPlugins({
|
|
150
112
|
openTelemetry: (cedarConfig.experimental?.opentelemetry?.enabled ?? false) && (cedarConfig.experimental?.opentelemetry?.wrapApi ?? false),
|
|
151
|
-
projectIsEsm
|
|
113
|
+
projectIsEsm: isEsm
|
|
152
114
|
});
|
|
153
115
|
const workspacePkgSourceMap = Object.fromEntries(
|
|
154
116
|
Object.entries(getWorkspacePackageAliases(cedarPaths, cedarConfig)).map(
|
|
155
117
|
([name, sourceFile]) => [name, normalizePath(sourceFile)]
|
|
156
118
|
)
|
|
157
119
|
);
|
|
158
|
-
const
|
|
120
|
+
const { createServer: createViteServer } = await import("vite");
|
|
121
|
+
return createViteServer({
|
|
159
122
|
configFile: false,
|
|
160
123
|
root: cedarPaths.api.base,
|
|
161
124
|
appType: "custom",
|
|
@@ -165,10 +128,6 @@ async function createViteDevServer(cedarPaths, cedarConfig, projectIsEsm, normal
|
|
|
165
128
|
middlewareMode: true
|
|
166
129
|
},
|
|
167
130
|
resolve: {
|
|
168
|
-
// Map workspace package names directly to their TypeScript source entry
|
|
169
|
-
// files. This is processed by Vite's built-in alias plugin (enforce:
|
|
170
|
-
// 'pre') which runs before vite:resolve and correctly intercepts imports
|
|
171
|
-
// in the SSR module runner context.
|
|
172
131
|
alias: workspacePkgSourceMap
|
|
173
132
|
},
|
|
174
133
|
plugins: [
|
|
@@ -203,7 +162,6 @@ async function createViteDevServer(cedarPaths, cedarConfig, projectIsEsm, normal
|
|
|
203
162
|
}
|
|
204
163
|
]
|
|
205
164
|
});
|
|
206
|
-
return viteServer;
|
|
207
165
|
}
|
|
208
166
|
function invalidateApiModules(viteServer, normalizedApiSrc) {
|
|
209
167
|
const invalidated = /* @__PURE__ */ new Set();
|
|
@@ -223,7 +181,10 @@ function invalidateApiModules(viteServer, normalizedApiSrc) {
|
|
|
223
181
|
}
|
|
224
182
|
}
|
|
225
183
|
}
|
|
226
|
-
function setupHmrHandlers(viteServer
|
|
184
|
+
function setupHmrHandlers(viteServer) {
|
|
185
|
+
const cedarPaths = getPaths();
|
|
186
|
+
const normalizedApiSrc = normalizePath(cedarPaths.api.src);
|
|
187
|
+
const normalizedApiBase = normalizePath(cedarPaths.api.base);
|
|
227
188
|
viteServer.watcher.on("change", async (filePath) => {
|
|
228
189
|
const normalizedFilePath = normalizePath(filePath);
|
|
229
190
|
if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
|
|
@@ -276,60 +237,79 @@ function setupHmrHandlers(viteServer, normalizedApiSrc, normalizedApiBase) {
|
|
|
276
237
|
await loadApiFunctions(viteServer);
|
|
277
238
|
});
|
|
278
239
|
}
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
240
|
+
function createApiFetchHandler() {
|
|
241
|
+
const cedarConfig = getConfig();
|
|
242
|
+
const apiUrlPrefix = cedarConfig.web.apiUrl.replace(/\/$/, "");
|
|
243
|
+
return async (request) => {
|
|
244
|
+
const url = new URL(request.url);
|
|
245
|
+
let pathname = url.pathname;
|
|
246
|
+
if (pathname.startsWith(apiUrlPrefix + "/")) {
|
|
247
|
+
pathname = pathname.slice(apiUrlPrefix.length);
|
|
248
|
+
} else if (pathname === apiUrlPrefix) {
|
|
249
|
+
pathname = "/";
|
|
250
|
+
}
|
|
251
|
+
if (pathname === "/graphql" || pathname.startsWith("/graphql/")) {
|
|
252
|
+
if (!graphqlYoga) {
|
|
253
|
+
return new Response(
|
|
254
|
+
JSON.stringify({ error: "GraphQL Yoga instance not initialized" }),
|
|
255
|
+
{ status: 503, headers: { "Content-Type": "application/json" } }
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
const yoga = graphqlYoga;
|
|
259
|
+
return getAsyncStoreInstance().run(/* @__PURE__ */ new Map(), async () => {
|
|
260
|
+
return yoga.handle(request, { request });
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const match = pathname.match(/^\/([^/]+)(?:\/.*)?$/);
|
|
264
|
+
if (!match) {
|
|
265
|
+
return new Response("Not Found", { status: 404 });
|
|
266
|
+
}
|
|
267
|
+
const routeName = match[1];
|
|
291
268
|
const handler = LAMBDA_FUNCTIONS[routeName];
|
|
292
269
|
if (!handler) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
270
|
+
return new Response(
|
|
271
|
+
JSON.stringify({
|
|
272
|
+
error: `Function "${routeName}" was not found.`,
|
|
273
|
+
availableFunctions: Object.keys(LAMBDA_FUNCTIONS)
|
|
274
|
+
}),
|
|
275
|
+
{ status: 404, headers: { "Content-Type": "application/json" } }
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const ctx = await buildCedarContext(request, {
|
|
280
|
+
params: { routeName }
|
|
299
281
|
});
|
|
300
|
-
|
|
282
|
+
const cedarHandler = wrapLegacyHandler(handler);
|
|
283
|
+
return await cedarHandler(request, ctx);
|
|
284
|
+
} catch (err) {
|
|
285
|
+
console.error(
|
|
286
|
+
`[apiDevMiddleware] Error handling function "${routeName}":`,
|
|
287
|
+
err
|
|
288
|
+
);
|
|
289
|
+
return new Response(
|
|
290
|
+
JSON.stringify({
|
|
291
|
+
error: err instanceof Error ? err.message : "Internal Server Error"
|
|
292
|
+
}),
|
|
293
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
294
|
+
);
|
|
301
295
|
}
|
|
302
|
-
return requestHandler(req, reply, handler);
|
|
303
296
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
});
|
|
313
|
-
return response;
|
|
297
|
+
}
|
|
298
|
+
async function startApiDevMiddleware() {
|
|
299
|
+
const viteServer = await createApiViteServer();
|
|
300
|
+
console.log(ansis.dim.italic("Starting API dev server..."));
|
|
301
|
+
await loadApiFunctions(viteServer);
|
|
302
|
+
setupHmrHandlers(viteServer);
|
|
303
|
+
const close = async () => {
|
|
304
|
+
await viteServer.close();
|
|
314
305
|
};
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
app.all("/:routeName", lambdaRequestHandler);
|
|
318
|
-
app.all("/:routeName/*", lambdaRequestHandler);
|
|
319
|
-
app.addHook("onListen", (done) => {
|
|
320
|
-
const addr = app.server.address();
|
|
321
|
-
const listenPort = addr && typeof addr === "object" ? addr.port : apiPort;
|
|
322
|
-
console.log(
|
|
323
|
-
`API dev server listening at ${ansis.magenta(`http://localhost:${listenPort}/`)}`
|
|
324
|
-
);
|
|
325
|
-
console.log(
|
|
326
|
-
`GraphQL endpoint at ${ansis.magenta(`http://localhost:${listenPort}/graphql`)}`
|
|
327
|
-
);
|
|
328
|
-
done();
|
|
329
|
-
});
|
|
330
|
-
await app.listen({ port: apiPort, host: apiHost });
|
|
331
|
-
return app;
|
|
306
|
+
const handler = createApiFetchHandler();
|
|
307
|
+
return { viteServer, close, handler };
|
|
332
308
|
}
|
|
333
309
|
export {
|
|
334
|
-
|
|
310
|
+
createApiFetchHandler,
|
|
311
|
+
createApiViteServer,
|
|
312
|
+
loadApiFunctions,
|
|
313
|
+
setupHmrHandlers,
|
|
314
|
+
startApiDevMiddleware
|
|
335
315
|
};
|
package/dist/build/build.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { buildCedarApp } from '../buildApp.js';
|
|
1
2
|
interface BuildOptions {
|
|
2
3
|
verbose?: boolean;
|
|
3
4
|
}
|
|
@@ -6,5 +7,4 @@ interface BuildOptions {
|
|
|
6
7
|
* because we want to set the process.cwd to web.base
|
|
7
8
|
*/
|
|
8
9
|
export declare const buildWeb: ({ verbose }: BuildOptions) => Promise<import("rollup").RollupOutput | import("rollup").RollupOutput[] | import("rollup").RollupWatcher>;
|
|
9
|
-
export {};
|
|
10
10
|
//# sourceMappingURL=build.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/build/build.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAU,aAAa,YAAY,8GAoBvD,CAAA"}
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/build/build.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAU,aAAa,YAAY,8GAoBvD,CAAA"}
|
package/dist/build/build.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getPaths } from "@cedarjs/project-config";
|
|
2
|
+
import { buildCedarApp } from "../buildApp.js";
|
|
2
3
|
const buildWeb = async ({ verbose }) => {
|
|
3
4
|
const { build } = await import("vite");
|
|
4
5
|
const viteConfig = getPaths().web.viteConfig;
|
|
@@ -17,5 +18,6 @@ const buildWeb = async ({ verbose }) => {
|
|
|
17
18
|
});
|
|
18
19
|
};
|
|
19
20
|
export {
|
|
21
|
+
buildCedarApp,
|
|
20
22
|
buildWeb
|
|
21
23
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface BuildCedarAppOptions {
|
|
2
|
+
verbose?: boolean;
|
|
3
|
+
workspace?: string[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Unified build for Cedar apps using Vite's builder API.
|
|
7
|
+
*
|
|
8
|
+
* Declares `client` and `api` environments and builds them in a single
|
|
9
|
+
* orchestrated pass. The web client is built from the project's web Vite
|
|
10
|
+
* config. The API is built as an SSR environment with Babel transforms and
|
|
11
|
+
* `src/` import redirection so it resolves correctly even though the builder
|
|
12
|
+
* root is the web source directory.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildCedarApp({ verbose, workspace, }?: BuildCedarAppOptions): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=buildApp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildApp.d.ts","sourceRoot":"","sources":["../src/buildApp.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CAAC,EAClC,OAAe,EACf,SAA0B,GAC3B,GAAE,oBAAyB,iBA+J3B"}
|
package/dist/buildApp.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createBuilder, normalizePath } from "vite";
|
|
4
|
+
import {
|
|
5
|
+
getApiSideBabelPlugins,
|
|
6
|
+
transformWithBabel
|
|
7
|
+
} from "@cedarjs/babel-config";
|
|
8
|
+
import { findApiFiles } from "@cedarjs/internal/dist/files.js";
|
|
9
|
+
import { getConfig, getPaths, projectSideIsEsm } from "@cedarjs/project-config";
|
|
10
|
+
import { getWorkspacePackageAliases } from "./lib/workspacePackageAliases.js";
|
|
11
|
+
function resolveWithExtensions(id) {
|
|
12
|
+
if (fs.existsSync(id)) {
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
for (const ext of [".js", ".ts", ".jsx", ".tsx", ".mjs", ".mts"]) {
|
|
16
|
+
const withExt = id + ext;
|
|
17
|
+
if (fs.existsSync(withExt)) {
|
|
18
|
+
return withExt;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
async function buildCedarApp({
|
|
24
|
+
verbose = false,
|
|
25
|
+
workspace = ["api", "web"]
|
|
26
|
+
} = {}) {
|
|
27
|
+
const cedarPaths = getPaths();
|
|
28
|
+
const cedarConfig = getConfig();
|
|
29
|
+
const environments = {};
|
|
30
|
+
if (workspace.includes("web")) {
|
|
31
|
+
environments.client = {
|
|
32
|
+
build: {
|
|
33
|
+
outDir: cedarPaths.web.dist
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (workspace.includes("api")) {
|
|
38
|
+
const isEsm = projectSideIsEsm("api");
|
|
39
|
+
const format = isEsm ? "es" : "cjs";
|
|
40
|
+
const apiFiles = findApiFiles();
|
|
41
|
+
const input = {};
|
|
42
|
+
for (const f of apiFiles) {
|
|
43
|
+
const key = path.relative(cedarPaths.api.src, f).replace(/\.(ts|tsx|mts|js|jsx|mjs)$/, "");
|
|
44
|
+
input[key] = f;
|
|
45
|
+
}
|
|
46
|
+
environments.api = {
|
|
47
|
+
build: {
|
|
48
|
+
ssr: true,
|
|
49
|
+
sourcemap: true,
|
|
50
|
+
outDir: cedarPaths.api.dist,
|
|
51
|
+
emptyOutDir: true,
|
|
52
|
+
rollupOptions: {
|
|
53
|
+
input,
|
|
54
|
+
output: {
|
|
55
|
+
format,
|
|
56
|
+
preserveModules: true,
|
|
57
|
+
preserveModulesRoot: cedarPaths.api.src,
|
|
58
|
+
entryFileNames: "[name].js"
|
|
59
|
+
},
|
|
60
|
+
external: (id) => {
|
|
61
|
+
if (id.startsWith("node:")) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (!id.startsWith(".") && !path.isAbsolute(id)) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const babelPlugins = workspace.includes("api") ? getApiSideBabelPlugins({
|
|
74
|
+
openTelemetry: (cedarConfig.experimental?.opentelemetry?.enabled ?? false) && (cedarConfig.experimental?.opentelemetry?.wrapApi ?? false),
|
|
75
|
+
projectIsEsm: projectSideIsEsm("api")
|
|
76
|
+
}) : null;
|
|
77
|
+
const workspacePkgSourceMap = workspace.includes("api") ? Object.fromEntries(
|
|
78
|
+
Object.entries(getWorkspacePackageAliases(cedarPaths, cedarConfig)).map(
|
|
79
|
+
([name, sourceFile]) => [name, normalizePath(sourceFile)]
|
|
80
|
+
)
|
|
81
|
+
) : {};
|
|
82
|
+
const plugins = [
|
|
83
|
+
{
|
|
84
|
+
name: "cedar-build-app-cleanup",
|
|
85
|
+
configResolved(config) {
|
|
86
|
+
if (!workspace.includes("web") && config.environments.client) {
|
|
87
|
+
delete config.environments.client;
|
|
88
|
+
}
|
|
89
|
+
if (!environments.ssr && config.environments.ssr) {
|
|
90
|
+
delete config.environments.ssr;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
];
|
|
95
|
+
if (workspace.includes("api")) {
|
|
96
|
+
plugins.push({
|
|
97
|
+
name: "cedar-api-src-redirect",
|
|
98
|
+
enforce: "pre",
|
|
99
|
+
resolveId(id, importer) {
|
|
100
|
+
if (!importer?.startsWith(cedarPaths.api.src)) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
if (id.startsWith("src/")) {
|
|
104
|
+
return resolveWithExtensions(
|
|
105
|
+
path.join(cedarPaths.api.src, id.slice(4))
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (babelPlugins) {
|
|
112
|
+
plugins.push({
|
|
113
|
+
name: "cedar-vite-api-babel-transform",
|
|
114
|
+
async transform(_code, id) {
|
|
115
|
+
if (!/\.(js|ts|tsx|jsx)$/.test(id)) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (id.includes("node_modules")) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
if (!normalizePath(id).startsWith(normalizePath(cedarPaths.api.base))) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const transformedCode = await transformWithBabel(id, babelPlugins);
|
|
125
|
+
if (transformedCode?.code) {
|
|
126
|
+
return {
|
|
127
|
+
code: transformedCode.code,
|
|
128
|
+
map: transformedCode.map ?? null
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const builder = await createBuilder({
|
|
137
|
+
configFile: cedarPaths.web.viteConfig,
|
|
138
|
+
envFile: false,
|
|
139
|
+
logLevel: verbose ? "info" : "warn",
|
|
140
|
+
environments,
|
|
141
|
+
resolve: {
|
|
142
|
+
alias: workspacePkgSourceMap
|
|
143
|
+
},
|
|
144
|
+
plugins
|
|
145
|
+
});
|
|
146
|
+
return builder.buildApp();
|
|
147
|
+
}
|
|
148
|
+
export {
|
|
149
|
+
buildCedarApp
|
|
150
|
+
};
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createServerAdapter } from "@whatwg-node/server";
|
|
2
3
|
import { createServer } from "vite";
|
|
3
4
|
import yargsParser from "yargs-parser";
|
|
4
5
|
import { getPaths, getConfig } from "@cedarjs/project-config";
|
|
5
|
-
import {
|
|
6
|
+
import { startApiDevMiddleware } from "./apiDevMiddleware.js";
|
|
7
|
+
function isViteInternalRequest(url) {
|
|
8
|
+
const pathname = url.split("?")[0];
|
|
9
|
+
return pathname.startsWith("/@") || pathname.startsWith("/__vite") || pathname.startsWith("/__hmr");
|
|
10
|
+
}
|
|
11
|
+
function isApiRequest(url, apiUrl, apiGqlUrl) {
|
|
12
|
+
return url === apiUrl || url.startsWith(apiUrl + "/") || url.startsWith(apiUrl + "?") || url === apiGqlUrl || url.startsWith(apiGqlUrl + "/") || url.startsWith(apiGqlUrl + "?");
|
|
13
|
+
}
|
|
6
14
|
const startUnifiedDevServer = async () => {
|
|
15
|
+
process.env.__CEDAR_UNIFIED_DEV = "true";
|
|
7
16
|
const rwPaths = getPaths();
|
|
8
17
|
const cedarConfig = getConfig();
|
|
9
18
|
const configFile = rwPaths.web.viteConfig;
|
|
@@ -14,7 +23,7 @@ const startUnifiedDevServer = async () => {
|
|
|
14
23
|
force: forceOptimize,
|
|
15
24
|
debug,
|
|
16
25
|
port: portArg,
|
|
17
|
-
apiPort:
|
|
26
|
+
apiPort: _apiPortArg,
|
|
18
27
|
_: _positional,
|
|
19
28
|
...serverArgs
|
|
20
29
|
} = yargsParser(process.argv.slice(2), {
|
|
@@ -22,8 +31,8 @@ const startUnifiedDevServer = async () => {
|
|
|
22
31
|
number: ["port", "apiPort"]
|
|
23
32
|
});
|
|
24
33
|
const webPort = portArg ?? cedarConfig.web.port ?? 8910;
|
|
25
|
-
const
|
|
26
|
-
const
|
|
34
|
+
const { close: closeApi, handler: apiHandler } = await startApiDevMiddleware();
|
|
35
|
+
const apiAdapter = createServerAdapter(apiHandler);
|
|
27
36
|
const devServer = await createServer({
|
|
28
37
|
configFile,
|
|
29
38
|
// env file is handled by Cedar's plugins
|
|
@@ -36,7 +45,52 @@ const startUnifiedDevServer = async () => {
|
|
|
36
45
|
port: webPort,
|
|
37
46
|
...serverArgs
|
|
38
47
|
},
|
|
39
|
-
logLevel: debug ? "info" : void 0
|
|
48
|
+
logLevel: debug ? "info" : void 0,
|
|
49
|
+
plugins: [
|
|
50
|
+
{
|
|
51
|
+
name: "cedar-api-middleware",
|
|
52
|
+
apply: "serve",
|
|
53
|
+
configureServer(server) {
|
|
54
|
+
const apiUrl = cedarConfig.web.apiUrl.replace(/\/$/, "");
|
|
55
|
+
const apiGqlUrl = cedarConfig.web.apiGraphQLUrl ?? apiUrl + "/graphql";
|
|
56
|
+
server.middlewares.use(
|
|
57
|
+
async (req, res, next) => {
|
|
58
|
+
const url = req.url ?? "/";
|
|
59
|
+
if (isViteInternalRequest(url)) {
|
|
60
|
+
return next();
|
|
61
|
+
}
|
|
62
|
+
if (!isApiRequest(url, apiUrl, apiGqlUrl)) {
|
|
63
|
+
return next();
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await apiAdapter(req, res);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
console.error(
|
|
69
|
+
"[cedar-api-middleware] Error handling API request:",
|
|
70
|
+
err
|
|
71
|
+
);
|
|
72
|
+
if (!res.headersSent) {
|
|
73
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
74
|
+
}
|
|
75
|
+
res.end(
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
{
|
|
78
|
+
errors: [
|
|
79
|
+
{
|
|
80
|
+
message: err instanceof Error ? err.message : "Internal Server Error"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
null,
|
|
85
|
+
2
|
|
86
|
+
)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
]
|
|
40
94
|
});
|
|
41
95
|
await devServer.listen();
|
|
42
96
|
process.stdin.on("data", async (data) => {
|