@cedarjs/vite 4.0.0-canary.13862 → 4.0.0-canary.13864

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.
@@ -0,0 +1,18 @@
1
+ import type { ViteDevServer } from 'vite';
2
+ /**
3
+ * Start the Cedar API dev server using Vite's SSR module runner for HMR.
4
+ *
5
+ * This replaces the previous system of:
6
+ * nodemon → api-server-watch (chokidar + esbuild + forked child process)
7
+ *
8
+ * With:
9
+ * Vite SSR dev server (module graph + HMR) + Fastify (same process)
10
+ *
11
+ * When API source files change, Vite invalidates the affected modules and
12
+ * re-loads them on the next call – no process restart needed.
13
+ */
14
+ export declare function startApiDevServer(port: number): Promise<{
15
+ viteServer: ViteDevServer;
16
+ close: () => Promise<void>;
17
+ }>;
18
+ //# sourceMappingURL=apiDevServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiDevServer.d.ts","sourceRoot":"","sources":["../src/apiDevServer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,MAAM,CAAA;AAsLrD;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7D,UAAU,EAAE,aAAa,CAAA;IACzB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3B,CAAC,CAiCD"}
@@ -0,0 +1,335 @@
1
+ import { glob } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import fastifyUrlData from "@fastify/url-data";
5
+ import ansis from "ansis";
6
+ import fastify from "fastify";
7
+ import fastifyRawBody from "fastify-raw-body";
8
+ import { createServer as createViteServer, normalizePath } from "vite";
9
+ import { requestHandler } from "@cedarjs/api-server/requestHandlers";
10
+ import {
11
+ getApiSideBabelPlugins,
12
+ transformWithBabel
13
+ } from "@cedarjs/babel-config";
14
+ import { getAsyncStoreInstance } from "@cedarjs/context/dist/store";
15
+ import { createGraphQLYoga } from "@cedarjs/graphql-server";
16
+ import { getConfig, getPaths, projectSideIsEsm } from "@cedarjs/project-config";
17
+ import { getWorkspacePackageAliases } from "./lib/workspacePackageAliases.js";
18
+ const LAMBDA_FUNCTIONS = {};
19
+ let graphqlYoga = null;
20
+ let loadApiFunctionsInFlight = null;
21
+ let needsReloadAfterInFlight = false;
22
+ async function loadApiFunctions(viteServer) {
23
+ if (loadApiFunctionsInFlight) {
24
+ needsReloadAfterInFlight = true;
25
+ return;
26
+ }
27
+ do {
28
+ needsReloadAfterInFlight = false;
29
+ loadApiFunctionsInFlight = internalLoadApiFunctions(viteServer);
30
+ try {
31
+ await loadApiFunctionsInFlight;
32
+ } finally {
33
+ loadApiFunctionsInFlight = null;
34
+ }
35
+ } while (needsReloadAfterInFlight);
36
+ }
37
+ async function internalLoadApiFunctions(viteServer) {
38
+ const cedarPaths = getPaths();
39
+ for (const key of Object.keys(LAMBDA_FUNCTIONS)) {
40
+ delete LAMBDA_FUNCTIONS[key];
41
+ }
42
+ let srcFunctions = [];
43
+ try {
44
+ srcFunctions = await Array.fromAsync(
45
+ glob("**/*.{ts,tsx,js,jsx}", {
46
+ cwd: cedarPaths.api.functions,
47
+ exclude: [
48
+ "**/*.test.{ts,tsx,js,jsx}",
49
+ "**/*.scenarios.{ts,tsx,js,jsx}",
50
+ "**/*.fixtures.{ts,tsx,js,jsx}",
51
+ "**/*.d.ts"
52
+ ]
53
+ }),
54
+ (entry) => path.join(cedarPaths.api.functions, entry)
55
+ );
56
+ } catch {
57
+ srcFunctions = [];
58
+ }
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
+ console.log(ansis.dim.italic("Importing Server Functions... "));
67
+ const tsImport = Date.now();
68
+ let extractedGraphqlOptions = null;
69
+ const imports = srcFunctions.map(async (fnPath) => {
70
+ const ts = Date.now();
71
+ const routeName = path.basename(fnPath).replace(/\.(ts|tsx|js|jsx)$/, "");
72
+ try {
73
+ const mod = await viteServer.ssrLoadModule(pathToFileURL(fnPath).href);
74
+ const handler = (() => {
75
+ if ("handler" in mod) {
76
+ return mod.handler;
77
+ }
78
+ if ("default" in mod && mod.default && "handler" in mod.default) {
79
+ return mod.default.handler;
80
+ }
81
+ return void 0;
82
+ })();
83
+ if (handler) {
84
+ LAMBDA_FUNCTIONS[routeName] = handler;
85
+ console.log(
86
+ ansis.magenta("/" + routeName),
87
+ ansis.dim.italic(Date.now() - ts + " ms")
88
+ );
89
+ } else {
90
+ console.warn(
91
+ `[apiDevServer] No handler export found in function: ${fnPath}`
92
+ );
93
+ }
94
+ if (routeName === "graphql" && "__rw_graphqlOptions" in mod) {
95
+ extractedGraphqlOptions = mod.__rw_graphqlOptions;
96
+ }
97
+ } catch (err) {
98
+ viteServer.ssrFixStacktrace(err);
99
+ console.error(
100
+ `[apiDevServer] Failed to load function "${routeName}" from ${fnPath}:`,
101
+ err
102
+ );
103
+ }
104
+ });
105
+ await Promise.all(imports);
106
+ if (extractedGraphqlOptions) {
107
+ const { yoga } = await createGraphQLYoga(extractedGraphqlOptions);
108
+ graphqlYoga = yoga;
109
+ }
110
+ console.log(
111
+ ansis.dim.italic("...Done importing in " + (Date.now() - tsImport) + " ms")
112
+ );
113
+ }
114
+ function createFetchRequestFromFastify(req) {
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) {
124
+ const cedarPaths = getPaths();
125
+ const cedarConfig = getConfig();
126
+ const apiPort = port || cedarConfig.api.port || 8911;
127
+ const apiHost = cedarConfig.api.host || "::";
128
+ const isEsm = projectSideIsEsm("api");
129
+ 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
+ const babelPlugins = getApiSideBabelPlugins({
150
+ openTelemetry: (cedarConfig.experimental?.opentelemetry?.enabled ?? false) && (cedarConfig.experimental?.opentelemetry?.wrapApi ?? false),
151
+ projectIsEsm
152
+ });
153
+ const workspacePkgSourceMap = Object.fromEntries(
154
+ Object.entries(getWorkspacePackageAliases(cedarPaths, cedarConfig)).map(
155
+ ([name, sourceFile]) => [name, normalizePath(sourceFile)]
156
+ )
157
+ );
158
+ const viteServer = await createViteServer({
159
+ configFile: false,
160
+ root: cedarPaths.api.base,
161
+ appType: "custom",
162
+ clearScreen: false,
163
+ logLevel: "warn",
164
+ server: {
165
+ middlewareMode: true
166
+ },
167
+ 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
+ alias: workspacePkgSourceMap
173
+ },
174
+ plugins: [
175
+ {
176
+ name: "cedar-api-babel-transform",
177
+ async transform(_code, id) {
178
+ if (!/\.(ts|tsx|js|jsx)$/.test(id)) {
179
+ return null;
180
+ }
181
+ if (id.includes("node_modules")) {
182
+ return null;
183
+ }
184
+ if (!id.startsWith(normalizedBase)) {
185
+ return null;
186
+ }
187
+ try {
188
+ const result = await transformWithBabel(id, babelPlugins);
189
+ if (!result?.code) {
190
+ return null;
191
+ }
192
+ return {
193
+ code: result.code,
194
+ map: result.map ?? null
195
+ };
196
+ } catch (err) {
197
+ this.warn(
198
+ `[cedar-api-babel-transform] Failed to transform ${id}: ${String(err)}`
199
+ );
200
+ return null;
201
+ }
202
+ }
203
+ }
204
+ ]
205
+ });
206
+ return viteServer;
207
+ }
208
+ function invalidateApiModules(viteServer, normalizedApiSrc) {
209
+ const invalidated = /* @__PURE__ */ new Set();
210
+ const invalidateWithImporters = (mod) => {
211
+ if (!mod || invalidated.has(mod.id ?? mod.url)) {
212
+ return;
213
+ }
214
+ invalidated.add(mod.id ?? mod.url);
215
+ viteServer.moduleGraph.invalidateModule(mod);
216
+ for (const importer of mod.importers) {
217
+ invalidateWithImporters(importer);
218
+ }
219
+ };
220
+ for (const mod of viteServer.moduleGraph.idToModuleMap.values()) {
221
+ if (mod.id?.startsWith(normalizedApiSrc)) {
222
+ invalidateWithImporters(mod);
223
+ }
224
+ }
225
+ }
226
+ function setupHmrHandlers(viteServer, normalizedApiSrc, normalizedApiBase) {
227
+ viteServer.watcher.on("change", async (filePath) => {
228
+ const normalizedFilePath = normalizePath(filePath);
229
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
230
+ return;
231
+ }
232
+ const displayPath = path.relative(normalizedApiBase, normalizedFilePath);
233
+ console.log(ansis.dim(`[change] ${displayPath}`));
234
+ const fileUrl = pathToFileURL(normalizedFilePath).href;
235
+ const mod = viteServer.moduleGraph.getModuleById(normalizedFilePath) ?? viteServer.moduleGraph.getModuleById(fileUrl);
236
+ if (mod) {
237
+ const invalidated = /* @__PURE__ */ new Set();
238
+ const invalidateWithImporters = (m) => {
239
+ if (!m || invalidated.has(m.id ?? m.url)) {
240
+ return;
241
+ }
242
+ invalidated.add(m.id ?? m.url);
243
+ viteServer.moduleGraph.invalidateModule(m);
244
+ for (const importer of m.importers) {
245
+ invalidateWithImporters(importer);
246
+ }
247
+ };
248
+ invalidateWithImporters(mod);
249
+ }
250
+ await loadApiFunctions(viteServer);
251
+ });
252
+ viteServer.watcher.on("add", async (filePath) => {
253
+ const normalizedFilePath = normalizePath(filePath);
254
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
255
+ return;
256
+ }
257
+ console.log(
258
+ ansis.dim(
259
+ `[add] ${path.relative(normalizedApiBase, normalizedFilePath)}`
260
+ )
261
+ );
262
+ invalidateApiModules(viteServer, normalizedApiSrc);
263
+ await loadApiFunctions(viteServer);
264
+ });
265
+ viteServer.watcher.on("unlink", async (filePath) => {
266
+ const normalizedFilePath = normalizePath(filePath);
267
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
268
+ return;
269
+ }
270
+ console.log(
271
+ ansis.dim(
272
+ `[unlink] ${path.relative(normalizedApiBase, normalizedFilePath)}`
273
+ )
274
+ );
275
+ invalidateApiModules(viteServer, normalizedApiSrc);
276
+ await loadApiFunctions(viteServer);
277
+ });
278
+ }
279
+ async function createFastifyApp(apiPort, apiHost) {
280
+ const logLevel = process.env.NODE_ENV === "development" ? "debug" : "info";
281
+ const app = fastify({ logger: { level: logLevel } });
282
+ await app.register(fastifyRawBody);
283
+ app.register(fastifyUrlData);
284
+ app.addContentTypeParser(
285
+ ["application/x-www-form-urlencoded", "multipart/form-data"],
286
+ { parseAs: "string" },
287
+ app.defaultTextParser
288
+ );
289
+ const lambdaRequestHandler = async (req, reply) => {
290
+ const { routeName } = req.params;
291
+ const handler = LAMBDA_FUNCTIONS[routeName];
292
+ if (!handler) {
293
+ const errorMessage = `Function "${routeName}" was not found.`;
294
+ req.log.error(errorMessage);
295
+ reply.status(404);
296
+ reply.send({
297
+ error: errorMessage,
298
+ availableFunctions: Object.keys(LAMBDA_FUNCTIONS)
299
+ });
300
+ return;
301
+ }
302
+ return requestHandler(req, reply, handler);
303
+ };
304
+ const graphqlHandler = async (req, reply) => {
305
+ if (!graphqlYoga) {
306
+ return reply.status(503).send({ error: "GraphQL Yoga instance not initialized" });
307
+ }
308
+ const request = createFetchRequestFromFastify(req);
309
+ const yoga = graphqlYoga;
310
+ const response = await getAsyncStoreInstance().run(/* @__PURE__ */ new Map(), async () => {
311
+ return yoga.handle(request, { req, reply });
312
+ });
313
+ return response;
314
+ };
315
+ app.all("/graphql", graphqlHandler);
316
+ app.all("/graphql/*", graphqlHandler);
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;
332
+ }
333
+ export {
334
+ startApiDevServer
335
+ };
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cedar-unified-dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cedar-unified-dev.d.ts","sourceRoot":"","sources":["../src/cedar-unified-dev.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from "vite";
3
+ import yargsParser from "yargs-parser";
4
+ import { getPaths, getConfig } from "@cedarjs/project-config";
5
+ import { startApiDevServer } from "./apiDevServer.js";
6
+ const startUnifiedDevServer = async () => {
7
+ const rwPaths = getPaths();
8
+ const cedarConfig = getConfig();
9
+ const configFile = rwPaths.web.viteConfig;
10
+ if (!configFile) {
11
+ throw new Error("Could not locate your web/vite.config.{js,ts} file");
12
+ }
13
+ const {
14
+ force: forceOptimize,
15
+ debug,
16
+ port: portArg,
17
+ apiPort: apiPortArg,
18
+ _: _positional,
19
+ ...serverArgs
20
+ } = yargsParser(process.argv.slice(2), {
21
+ boolean: ["https", "open", "strictPort", "force", "cors", "debug"],
22
+ number: ["port", "apiPort"]
23
+ });
24
+ const webPort = portArg ?? cedarConfig.web.port ?? 8910;
25
+ const apiPort = apiPortArg ?? cedarConfig.api.port ?? 8911;
26
+ const { close: closeApi } = await startApiDevServer(apiPort);
27
+ const devServer = await createServer({
28
+ configFile,
29
+ // env file is handled by Cedar's plugins
30
+ envFile: false,
31
+ optimizeDeps: {
32
+ // This is the only value that isn't a server option
33
+ force: forceOptimize
34
+ },
35
+ server: {
36
+ port: webPort,
37
+ ...serverArgs
38
+ },
39
+ logLevel: debug ? "info" : void 0
40
+ });
41
+ await devServer.listen();
42
+ process.stdin.on("data", async (data) => {
43
+ const str = data.toString().trim().toLowerCase();
44
+ if (str === "rs" || str === "restart") {
45
+ await devServer.restart(true);
46
+ }
47
+ });
48
+ devServer.printUrls();
49
+ if (debug) {
50
+ console.log("~~~ Vite Server Config ~~~");
51
+ console.log(JSON.stringify(devServer.config, null, 2));
52
+ console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~");
53
+ }
54
+ const shutdown = async () => {
55
+ await devServer.close();
56
+ await closeApi();
57
+ process.exit(0);
58
+ };
59
+ process.on("SIGINT", shutdown);
60
+ process.on("SIGTERM", shutdown);
61
+ };
62
+ startUnifiedDevServer().catch((err) => {
63
+ console.error("Failed to start unified dev server:", err);
64
+ process.exit(1);
65
+ });
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var apiDevServer_exports = {};
30
+ __export(apiDevServer_exports, {
31
+ startApiDevServer: () => startApiDevServer
32
+ });
33
+ module.exports = __toCommonJS(apiDevServer_exports);
34
+ var import_promises = require("node:fs/promises");
35
+ var import_node_path = __toESM(require("node:path"), 1);
36
+ var import_node_url = require("node:url");
37
+ var import_url_data = __toESM(require("@fastify/url-data"), 1);
38
+ var import_ansis = __toESM(require("ansis"), 1);
39
+ var import_fastify = __toESM(require("fastify"), 1);
40
+ var import_fastify_raw_body = __toESM(require("fastify-raw-body"), 1);
41
+ var import_vite = require("vite");
42
+ var import_requestHandlers = require("@cedarjs/api-server/requestHandlers");
43
+ var import_babel_config = require("@cedarjs/babel-config");
44
+ var import_store = require("@cedarjs/context/dist/store");
45
+ var import_graphql_server = require("@cedarjs/graphql-server");
46
+ var import_project_config = require("@cedarjs/project-config");
47
+ var import_workspacePackageAliases = require("./lib/workspacePackageAliases.js");
48
+ const LAMBDA_FUNCTIONS = {};
49
+ let graphqlYoga = null;
50
+ let loadApiFunctionsInFlight = null;
51
+ let needsReloadAfterInFlight = false;
52
+ async function loadApiFunctions(viteServer) {
53
+ if (loadApiFunctionsInFlight) {
54
+ needsReloadAfterInFlight = true;
55
+ return;
56
+ }
57
+ do {
58
+ needsReloadAfterInFlight = false;
59
+ loadApiFunctionsInFlight = internalLoadApiFunctions(viteServer);
60
+ try {
61
+ await loadApiFunctionsInFlight;
62
+ } finally {
63
+ loadApiFunctionsInFlight = null;
64
+ }
65
+ } while (needsReloadAfterInFlight);
66
+ }
67
+ async function internalLoadApiFunctions(viteServer) {
68
+ const cedarPaths = (0, import_project_config.getPaths)();
69
+ for (const key of Object.keys(LAMBDA_FUNCTIONS)) {
70
+ delete LAMBDA_FUNCTIONS[key];
71
+ }
72
+ let srcFunctions = [];
73
+ try {
74
+ srcFunctions = await Array.fromAsync(
75
+ (0, import_promises.glob)("**/*.{ts,tsx,js,jsx}", {
76
+ cwd: cedarPaths.api.functions,
77
+ exclude: [
78
+ "**/*.test.{ts,tsx,js,jsx}",
79
+ "**/*.scenarios.{ts,tsx,js,jsx}",
80
+ "**/*.fixtures.{ts,tsx,js,jsx}",
81
+ "**/*.d.ts"
82
+ ]
83
+ }),
84
+ (entry) => import_node_path.default.join(cedarPaths.api.functions, entry)
85
+ );
86
+ } catch {
87
+ srcFunctions = [];
88
+ }
89
+ const graphqlFunctionIndex = srcFunctions.findIndex(
90
+ (f) => import_node_path.default.basename(f).startsWith("graphql.")
91
+ );
92
+ if (graphqlFunctionIndex > 0) {
93
+ const [graphqlFn] = srcFunctions.splice(graphqlFunctionIndex, 1);
94
+ srcFunctions.unshift(graphqlFn);
95
+ }
96
+ console.log(import_ansis.default.dim.italic("Importing Server Functions... "));
97
+ const tsImport = Date.now();
98
+ let extractedGraphqlOptions = null;
99
+ const imports = srcFunctions.map(async (fnPath) => {
100
+ const ts = Date.now();
101
+ const routeName = import_node_path.default.basename(fnPath).replace(/\.(ts|tsx|js|jsx)$/, "");
102
+ try {
103
+ const mod = await viteServer.ssrLoadModule((0, import_node_url.pathToFileURL)(fnPath).href);
104
+ const handler = (() => {
105
+ if ("handler" in mod) {
106
+ return mod.handler;
107
+ }
108
+ if ("default" in mod && mod.default && "handler" in mod.default) {
109
+ return mod.default.handler;
110
+ }
111
+ return void 0;
112
+ })();
113
+ if (handler) {
114
+ LAMBDA_FUNCTIONS[routeName] = handler;
115
+ console.log(
116
+ import_ansis.default.magenta("/" + routeName),
117
+ import_ansis.default.dim.italic(Date.now() - ts + " ms")
118
+ );
119
+ } else {
120
+ console.warn(
121
+ `[apiDevServer] No handler export found in function: ${fnPath}`
122
+ );
123
+ }
124
+ if (routeName === "graphql" && "__rw_graphqlOptions" in mod) {
125
+ extractedGraphqlOptions = mod.__rw_graphqlOptions;
126
+ }
127
+ } catch (err) {
128
+ viteServer.ssrFixStacktrace(err);
129
+ console.error(
130
+ `[apiDevServer] Failed to load function "${routeName}" from ${fnPath}:`,
131
+ err
132
+ );
133
+ }
134
+ });
135
+ await Promise.all(imports);
136
+ if (extractedGraphqlOptions) {
137
+ const { yoga } = await (0, import_graphql_server.createGraphQLYoga)(extractedGraphqlOptions);
138
+ graphqlYoga = yoga;
139
+ }
140
+ console.log(
141
+ import_ansis.default.dim.italic("...Done importing in " + (Date.now() - tsImport) + " ms")
142
+ );
143
+ }
144
+ function createFetchRequestFromFastify(req) {
145
+ const requestBody = req.method === "GET" || req.method === "HEAD" ? void 0 : typeof req.body === "string" ? req.body : req.body ? JSON.stringify(req.body) : void 0;
146
+ const href = `${req.protocol}://${req.host}${req.raw.url ?? "/"}`;
147
+ return new Request(href, {
148
+ method: req.method,
149
+ headers: req.headers,
150
+ body: requestBody
151
+ });
152
+ }
153
+ async function startApiDevServer(port) {
154
+ const cedarPaths = (0, import_project_config.getPaths)();
155
+ const cedarConfig = (0, import_project_config.getConfig)();
156
+ const apiPort = port || cedarConfig.api.port || 8911;
157
+ const apiHost = cedarConfig.api.host || "::";
158
+ const isEsm = (0, import_project_config.projectSideIsEsm)("api");
159
+ const normalizedBase = (0, import_vite.normalizePath)(cedarPaths.base);
160
+ const normalizedApiSrc = (0, import_vite.normalizePath)(cedarPaths.api.src);
161
+ const normalizedApiBase = (0, import_vite.normalizePath)(cedarPaths.api.base);
162
+ const viteServer = await createViteDevServer(
163
+ cedarPaths,
164
+ cedarConfig,
165
+ isEsm,
166
+ normalizedBase
167
+ );
168
+ console.log(import_ansis.default.dim.italic("Starting API dev server..."));
169
+ await loadApiFunctions(viteServer);
170
+ setupHmrHandlers(viteServer, normalizedApiSrc, normalizedApiBase);
171
+ const app = await createFastifyApp(apiPort, apiHost);
172
+ const close = async () => {
173
+ await app.close();
174
+ await viteServer.close();
175
+ };
176
+ return { viteServer, close };
177
+ }
178
+ async function createViteDevServer(cedarPaths, cedarConfig, projectIsEsm, normalizedBase) {
179
+ const babelPlugins = (0, import_babel_config.getApiSideBabelPlugins)({
180
+ openTelemetry: (cedarConfig.experimental?.opentelemetry?.enabled ?? false) && (cedarConfig.experimental?.opentelemetry?.wrapApi ?? false),
181
+ projectIsEsm
182
+ });
183
+ const workspacePkgSourceMap = Object.fromEntries(
184
+ Object.entries((0, import_workspacePackageAliases.getWorkspacePackageAliases)(cedarPaths, cedarConfig)).map(
185
+ ([name, sourceFile]) => [name, (0, import_vite.normalizePath)(sourceFile)]
186
+ )
187
+ );
188
+ const viteServer = await (0, import_vite.createServer)({
189
+ configFile: false,
190
+ root: cedarPaths.api.base,
191
+ appType: "custom",
192
+ clearScreen: false,
193
+ logLevel: "warn",
194
+ server: {
195
+ middlewareMode: true
196
+ },
197
+ resolve: {
198
+ // Map workspace package names directly to their TypeScript source entry
199
+ // files. This is processed by Vite's built-in alias plugin (enforce:
200
+ // 'pre') which runs before vite:resolve and correctly intercepts imports
201
+ // in the SSR module runner context.
202
+ alias: workspacePkgSourceMap
203
+ },
204
+ plugins: [
205
+ {
206
+ name: "cedar-api-babel-transform",
207
+ async transform(_code, id) {
208
+ if (!/\.(ts|tsx|js|jsx)$/.test(id)) {
209
+ return null;
210
+ }
211
+ if (id.includes("node_modules")) {
212
+ return null;
213
+ }
214
+ if (!id.startsWith(normalizedBase)) {
215
+ return null;
216
+ }
217
+ try {
218
+ const result = await (0, import_babel_config.transformWithBabel)(id, babelPlugins);
219
+ if (!result?.code) {
220
+ return null;
221
+ }
222
+ return {
223
+ code: result.code,
224
+ map: result.map ?? null
225
+ };
226
+ } catch (err) {
227
+ this.warn(
228
+ `[cedar-api-babel-transform] Failed to transform ${id}: ${String(err)}`
229
+ );
230
+ return null;
231
+ }
232
+ }
233
+ }
234
+ ]
235
+ });
236
+ return viteServer;
237
+ }
238
+ function invalidateApiModules(viteServer, normalizedApiSrc) {
239
+ const invalidated = /* @__PURE__ */ new Set();
240
+ const invalidateWithImporters = (mod) => {
241
+ if (!mod || invalidated.has(mod.id ?? mod.url)) {
242
+ return;
243
+ }
244
+ invalidated.add(mod.id ?? mod.url);
245
+ viteServer.moduleGraph.invalidateModule(mod);
246
+ for (const importer of mod.importers) {
247
+ invalidateWithImporters(importer);
248
+ }
249
+ };
250
+ for (const mod of viteServer.moduleGraph.idToModuleMap.values()) {
251
+ if (mod.id?.startsWith(normalizedApiSrc)) {
252
+ invalidateWithImporters(mod);
253
+ }
254
+ }
255
+ }
256
+ function setupHmrHandlers(viteServer, normalizedApiSrc, normalizedApiBase) {
257
+ viteServer.watcher.on("change", async (filePath) => {
258
+ const normalizedFilePath = (0, import_vite.normalizePath)(filePath);
259
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
260
+ return;
261
+ }
262
+ const displayPath = import_node_path.default.relative(normalizedApiBase, normalizedFilePath);
263
+ console.log(import_ansis.default.dim(`[change] ${displayPath}`));
264
+ const fileUrl = (0, import_node_url.pathToFileURL)(normalizedFilePath).href;
265
+ const mod = viteServer.moduleGraph.getModuleById(normalizedFilePath) ?? viteServer.moduleGraph.getModuleById(fileUrl);
266
+ if (mod) {
267
+ const invalidated = /* @__PURE__ */ new Set();
268
+ const invalidateWithImporters = (m) => {
269
+ if (!m || invalidated.has(m.id ?? m.url)) {
270
+ return;
271
+ }
272
+ invalidated.add(m.id ?? m.url);
273
+ viteServer.moduleGraph.invalidateModule(m);
274
+ for (const importer of m.importers) {
275
+ invalidateWithImporters(importer);
276
+ }
277
+ };
278
+ invalidateWithImporters(mod);
279
+ }
280
+ await loadApiFunctions(viteServer);
281
+ });
282
+ viteServer.watcher.on("add", async (filePath) => {
283
+ const normalizedFilePath = (0, import_vite.normalizePath)(filePath);
284
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
285
+ return;
286
+ }
287
+ console.log(
288
+ import_ansis.default.dim(
289
+ `[add] ${import_node_path.default.relative(normalizedApiBase, normalizedFilePath)}`
290
+ )
291
+ );
292
+ invalidateApiModules(viteServer, normalizedApiSrc);
293
+ await loadApiFunctions(viteServer);
294
+ });
295
+ viteServer.watcher.on("unlink", async (filePath) => {
296
+ const normalizedFilePath = (0, import_vite.normalizePath)(filePath);
297
+ if (!normalizedFilePath.startsWith(normalizedApiSrc)) {
298
+ return;
299
+ }
300
+ console.log(
301
+ import_ansis.default.dim(
302
+ `[unlink] ${import_node_path.default.relative(normalizedApiBase, normalizedFilePath)}`
303
+ )
304
+ );
305
+ invalidateApiModules(viteServer, normalizedApiSrc);
306
+ await loadApiFunctions(viteServer);
307
+ });
308
+ }
309
+ async function createFastifyApp(apiPort, apiHost) {
310
+ const logLevel = process.env.NODE_ENV === "development" ? "debug" : "info";
311
+ const app = (0, import_fastify.default)({ logger: { level: logLevel } });
312
+ await app.register(import_fastify_raw_body.default);
313
+ app.register(import_url_data.default);
314
+ app.addContentTypeParser(
315
+ ["application/x-www-form-urlencoded", "multipart/form-data"],
316
+ { parseAs: "string" },
317
+ app.defaultTextParser
318
+ );
319
+ const lambdaRequestHandler = async (req, reply) => {
320
+ const { routeName } = req.params;
321
+ const handler = LAMBDA_FUNCTIONS[routeName];
322
+ if (!handler) {
323
+ const errorMessage = `Function "${routeName}" was not found.`;
324
+ req.log.error(errorMessage);
325
+ reply.status(404);
326
+ reply.send({
327
+ error: errorMessage,
328
+ availableFunctions: Object.keys(LAMBDA_FUNCTIONS)
329
+ });
330
+ return;
331
+ }
332
+ return (0, import_requestHandlers.requestHandler)(req, reply, handler);
333
+ };
334
+ const graphqlHandler = async (req, reply) => {
335
+ if (!graphqlYoga) {
336
+ return reply.status(503).send({ error: "GraphQL Yoga instance not initialized" });
337
+ }
338
+ const request = createFetchRequestFromFastify(req);
339
+ const yoga = graphqlYoga;
340
+ const response = await (0, import_store.getAsyncStoreInstance)().run(/* @__PURE__ */ new Map(), async () => {
341
+ return yoga.handle(request, { req, reply });
342
+ });
343
+ return response;
344
+ };
345
+ app.all("/graphql", graphqlHandler);
346
+ app.all("/graphql/*", graphqlHandler);
347
+ app.all("/:routeName", lambdaRequestHandler);
348
+ app.all("/:routeName/*", lambdaRequestHandler);
349
+ app.addHook("onListen", (done) => {
350
+ const addr = app.server.address();
351
+ const listenPort = addr && typeof addr === "object" ? addr.port : apiPort;
352
+ console.log(
353
+ `API dev server listening at ${import_ansis.default.magenta(`http://localhost:${listenPort}/`)}`
354
+ );
355
+ console.log(
356
+ `GraphQL endpoint at ${import_ansis.default.magenta(`http://localhost:${listenPort}/graphql`)}`
357
+ );
358
+ done();
359
+ });
360
+ await app.listen({ port: apiPort, host: apiHost });
361
+ return app;
362
+ }
363
+ // Annotate the CommonJS export names for ESM import in node:
364
+ 0 && (module.exports = {
365
+ startApiDevServer
366
+ });
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+ var import_vite = require("vite");
26
+ var import_yargs_parser = __toESM(require("yargs-parser"), 1);
27
+ var import_project_config = require("@cedarjs/project-config");
28
+ var import_apiDevServer = require("./apiDevServer.js");
29
+ const startUnifiedDevServer = async () => {
30
+ const rwPaths = (0, import_project_config.getPaths)();
31
+ const cedarConfig = (0, import_project_config.getConfig)();
32
+ const configFile = rwPaths.web.viteConfig;
33
+ if (!configFile) {
34
+ throw new Error("Could not locate your web/vite.config.{js,ts} file");
35
+ }
36
+ const {
37
+ force: forceOptimize,
38
+ debug,
39
+ port: portArg,
40
+ apiPort: apiPortArg,
41
+ _: _positional,
42
+ ...serverArgs
43
+ } = (0, import_yargs_parser.default)(process.argv.slice(2), {
44
+ boolean: ["https", "open", "strictPort", "force", "cors", "debug"],
45
+ number: ["port", "apiPort"]
46
+ });
47
+ const webPort = portArg ?? cedarConfig.web.port ?? 8910;
48
+ const apiPort = apiPortArg ?? cedarConfig.api.port ?? 8911;
49
+ const { close: closeApi } = await (0, import_apiDevServer.startApiDevServer)(apiPort);
50
+ const devServer = await (0, import_vite.createServer)({
51
+ configFile,
52
+ // env file is handled by Cedar's plugins
53
+ envFile: false,
54
+ optimizeDeps: {
55
+ // This is the only value that isn't a server option
56
+ force: forceOptimize
57
+ },
58
+ server: {
59
+ port: webPort,
60
+ ...serverArgs
61
+ },
62
+ logLevel: debug ? "info" : void 0
63
+ });
64
+ await devServer.listen();
65
+ process.stdin.on("data", async (data) => {
66
+ const str = data.toString().trim().toLowerCase();
67
+ if (str === "rs" || str === "restart") {
68
+ await devServer.restart(true);
69
+ }
70
+ });
71
+ devServer.printUrls();
72
+ if (debug) {
73
+ console.log("~~~ Vite Server Config ~~~");
74
+ console.log(JSON.stringify(devServer.config, null, 2));
75
+ console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~");
76
+ }
77
+ const shutdown = async () => {
78
+ await devServer.close();
79
+ await closeApi();
80
+ process.exit(0);
81
+ };
82
+ process.on("SIGINT", shutdown);
83
+ process.on("SIGTERM", shutdown);
84
+ };
85
+ startUnifiedDevServer().catch((err) => {
86
+ console.error("Failed to start unified dev server:", err);
87
+ process.exit(1);
88
+ });
@@ -34,8 +34,10 @@ module.exports = __toCommonJS(getMergedConfig_exports);
34
34
  var import_node_path = __toESM(require("node:path"), 1);
35
35
  var import_vite = require("vite");
36
36
  var import_project_config = require("@cedarjs/project-config");
37
+ var import_workspacePackageAliases = require("./workspacePackageAliases.js");
37
38
  function getMergedConfig(cedarConfig, cedarPaths) {
38
39
  return (userConfig, env) => {
40
+ const workspaceAliases = env.command === "serve" ? (0, import_workspacePackageAliases.getWorkspacePackageAliases)(cedarPaths, cedarConfig) : {};
39
41
  let apiHost = process.env.REDWOOD_API_HOST;
40
42
  apiHost ??= cedarConfig.api.host;
41
43
  apiHost ??= process.env.NODE_ENV === "production" ? "0.0.0.0" : "127.0.0.1";
@@ -49,6 +51,9 @@ function getMergedConfig(cedarConfig, cedarPaths) {
49
51
  }
50
52
  const defaultCedarViteConfig = {
51
53
  root: cedarPaths.web.src,
54
+ resolve: {
55
+ alias: workspaceAliases
56
+ },
52
57
  // @MARK: when we have these aliases, the warnings from the FE server go
53
58
  // away BUT, if you have imports like this:
54
59
  // ```
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var workspacePackageAliases_exports = {};
30
+ __export(workspacePackageAliases_exports, {
31
+ getWorkspacePackageAliases: () => getWorkspacePackageAliases
32
+ });
33
+ module.exports = __toCommonJS(workspacePackageAliases_exports);
34
+ var import_node_fs = __toESM(require("node:fs"), 1);
35
+ var import_node_path = __toESM(require("node:path"), 1);
36
+ var import_vite = require("vite");
37
+ function findSourceEntry(pkgDir, pkgJson) {
38
+ let distEntry = null;
39
+ if (typeof pkgJson.main === "string") {
40
+ distEntry = pkgJson.main;
41
+ } else if (pkgJson.exports) {
42
+ const root = pkgJson.exports["."];
43
+ if (typeof root === "string") {
44
+ distEntry = root;
45
+ } else if (root && typeof root === "object") {
46
+ const rootObj = root;
47
+ if (typeof rootObj["default"] === "string") {
48
+ distEntry = rootObj["default"];
49
+ }
50
+ }
51
+ }
52
+ if (!distEntry) {
53
+ return null;
54
+ }
55
+ const withoutLeadingDot = distEntry.replace(/^\.\//, "");
56
+ const withoutExt = withoutLeadingDot.replace(/\.(js|cjs|mjs)$/, "");
57
+ const srcBase = withoutExt.replace(/^dist\//, "src/");
58
+ for (const ext of [".ts", ".tsx", ".mts", ".js", ".jsx", ".mjs"]) {
59
+ const candidate = import_node_path.default.join(pkgDir, srcBase + ext);
60
+ if (import_node_fs.default.existsSync(candidate)) {
61
+ return (0, import_vite.normalizePath)(candidate);
62
+ }
63
+ }
64
+ return null;
65
+ }
66
+ function getWorkspacePackageAliases(cedarPaths, cedarConfig) {
67
+ if (!cedarConfig.experimental?.packagesWorkspace?.enabled) {
68
+ return {};
69
+ }
70
+ if (!cedarPaths.packages || !import_node_fs.default.existsSync(cedarPaths.packages)) {
71
+ return {};
72
+ }
73
+ try {
74
+ const rootPkgPath = import_node_path.default.join(cedarPaths.base, "package.json");
75
+ const rootPkg = JSON.parse(import_node_fs.default.readFileSync(rootPkgPath, "utf-8"));
76
+ if (!Array.isArray(rootPkg.workspaces) || rootPkg.workspaces.length <= 2) {
77
+ return {};
78
+ }
79
+ const nonApiWebWorkspaces = rootPkg.workspaces.filter(
80
+ (w) => w !== "api" && w !== "web"
81
+ );
82
+ if (nonApiWebWorkspaces.length === 0) {
83
+ return {};
84
+ }
85
+ const entries = import_node_fs.default.readdirSync(cedarPaths.packages, { withFileTypes: true });
86
+ const aliases = {};
87
+ for (const entry of entries) {
88
+ if (!entry.isDirectory()) {
89
+ continue;
90
+ }
91
+ const pkgDir = import_node_path.default.join(cedarPaths.packages, entry.name);
92
+ const pkgJsonPath = import_node_path.default.join(pkgDir, "package.json");
93
+ if (!import_node_fs.default.existsSync(pkgJsonPath)) {
94
+ continue;
95
+ }
96
+ const pkgJson = JSON.parse(import_node_fs.default.readFileSync(pkgJsonPath, "utf-8"));
97
+ if (!pkgJson.name) {
98
+ continue;
99
+ }
100
+ const sourceEntry = findSourceEntry(pkgDir, pkgJson);
101
+ if (sourceEntry) {
102
+ aliases[pkgJson.name] = sourceEntry;
103
+ }
104
+ }
105
+ return aliases;
106
+ } catch {
107
+ return {};
108
+ }
109
+ }
110
+ // Annotate the CommonJS export names for ESM import in node:
111
+ 0 && (module.exports = {
112
+ getWorkspacePackageAliases
113
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"getMergedConfig.d.ts","sourceRoot":"","sources":["../../src/lib/getMergedConfig.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAO5D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,IAC5D,YAAY,cAAc,EAAE,KAAK,SAAS,KAAG,cAAc,CA0GpE"}
1
+ {"version":3,"file":"getMergedConfig.d.ts","sourceRoot":"","sources":["../../src/lib/getMergedConfig.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAS5D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,IAC5D,YAAY,cAAc,EAAE,KAAK,SAAS,KAAG,cAAc,CAqHpE"}
@@ -5,8 +5,10 @@ import {
5
5
  getEnvVarDefinitions,
6
6
  getPaths
7
7
  } from "@cedarjs/project-config";
8
+ import { getWorkspacePackageAliases } from "./workspacePackageAliases.js";
8
9
  function getMergedConfig(cedarConfig, cedarPaths) {
9
10
  return (userConfig, env) => {
11
+ const workspaceAliases = env.command === "serve" ? getWorkspacePackageAliases(cedarPaths, cedarConfig) : {};
10
12
  let apiHost = process.env.REDWOOD_API_HOST;
11
13
  apiHost ??= cedarConfig.api.host;
12
14
  apiHost ??= process.env.NODE_ENV === "production" ? "0.0.0.0" : "127.0.0.1";
@@ -20,6 +22,9 @@ function getMergedConfig(cedarConfig, cedarPaths) {
20
22
  }
21
23
  const defaultCedarViteConfig = {
22
24
  root: cedarPaths.web.src,
25
+ resolve: {
26
+ alias: workspaceAliases
27
+ },
23
28
  // @MARK: when we have these aliases, the warnings from the FE server go
24
29
  // away BUT, if you have imports like this:
25
30
  // ```
@@ -0,0 +1,18 @@
1
+ import type { Config, Paths } from '@cedarjs/project-config';
2
+ /**
3
+ * Mirrors the logic used in buildHandler.ts / buildPackagesTask.js:
4
+ * - Only runs when `experimental.packagesWorkspace.enabled` is true
5
+ * - Reads the root package.json workspaces array to find non-api/web entries
6
+ * - Enumerates the packages/ directory to get each package's name and
7
+ * inferred TypeScript source entry
8
+ *
9
+ * Returns a map of package name → absolute source file path suitable for use
10
+ * as Vite `resolve.alias` entries. This allows the Vite dev server to resolve
11
+ * workspace package imports directly to their TypeScript source without
12
+ * requiring a prior build step (i.e. without needing `dist/` to exist).
13
+ *
14
+ * This is intentionally synchronous so it can be used in contexts such as
15
+ * `getMergedConfig` which are called synchronously by Vite.
16
+ */
17
+ export declare function getWorkspacePackageAliases(cedarPaths: Paths, cedarConfig: Config): Record<string, string>;
18
+ //# sourceMappingURL=workspacePackageAliases.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspacePackageAliases.d.ts","sourceRoot":"","sources":["../../src/lib/workspacePackageAliases.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AA2D5D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,KAAK,EACjB,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiExB"}
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { normalizePath } from "vite";
4
+ function findSourceEntry(pkgDir, pkgJson) {
5
+ let distEntry = null;
6
+ if (typeof pkgJson.main === "string") {
7
+ distEntry = pkgJson.main;
8
+ } else if (pkgJson.exports) {
9
+ const root = pkgJson.exports["."];
10
+ if (typeof root === "string") {
11
+ distEntry = root;
12
+ } else if (root && typeof root === "object") {
13
+ const rootObj = root;
14
+ if (typeof rootObj["default"] === "string") {
15
+ distEntry = rootObj["default"];
16
+ }
17
+ }
18
+ }
19
+ if (!distEntry) {
20
+ return null;
21
+ }
22
+ const withoutLeadingDot = distEntry.replace(/^\.\//, "");
23
+ const withoutExt = withoutLeadingDot.replace(/\.(js|cjs|mjs)$/, "");
24
+ const srcBase = withoutExt.replace(/^dist\//, "src/");
25
+ for (const ext of [".ts", ".tsx", ".mts", ".js", ".jsx", ".mjs"]) {
26
+ const candidate = path.join(pkgDir, srcBase + ext);
27
+ if (fs.existsSync(candidate)) {
28
+ return normalizePath(candidate);
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ function getWorkspacePackageAliases(cedarPaths, cedarConfig) {
34
+ if (!cedarConfig.experimental?.packagesWorkspace?.enabled) {
35
+ return {};
36
+ }
37
+ if (!cedarPaths.packages || !fs.existsSync(cedarPaths.packages)) {
38
+ return {};
39
+ }
40
+ try {
41
+ const rootPkgPath = path.join(cedarPaths.base, "package.json");
42
+ const rootPkg = JSON.parse(fs.readFileSync(rootPkgPath, "utf-8"));
43
+ if (!Array.isArray(rootPkg.workspaces) || rootPkg.workspaces.length <= 2) {
44
+ return {};
45
+ }
46
+ const nonApiWebWorkspaces = rootPkg.workspaces.filter(
47
+ (w) => w !== "api" && w !== "web"
48
+ );
49
+ if (nonApiWebWorkspaces.length === 0) {
50
+ return {};
51
+ }
52
+ const entries = fs.readdirSync(cedarPaths.packages, { withFileTypes: true });
53
+ const aliases = {};
54
+ for (const entry of entries) {
55
+ if (!entry.isDirectory()) {
56
+ continue;
57
+ }
58
+ const pkgDir = path.join(cedarPaths.packages, entry.name);
59
+ const pkgJsonPath = path.join(pkgDir, "package.json");
60
+ if (!fs.existsSync(pkgJsonPath)) {
61
+ continue;
62
+ }
63
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
64
+ if (!pkgJson.name) {
65
+ continue;
66
+ }
67
+ const sourceEntry = findSourceEntry(pkgDir, pkgJson);
68
+ if (sourceEntry) {
69
+ aliases[pkgJson.name] = sourceEntry;
70
+ }
71
+ }
72
+ return aliases;
73
+ } catch {
74
+ return {};
75
+ }
76
+ }
77
+ export {
78
+ getWorkspacePackageAliases
79
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedarjs/vite",
3
- "version": "4.0.0-canary.13862+892b5320e6",
3
+ "version": "4.0.0-canary.13864+6143202249",
4
4
  "description": "Vite configuration package for CedarJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,6 +25,12 @@
25
25
  "types": "./dist/api/vite-plugin-cedar-vitest-api-preset.d.ts",
26
26
  "default": "./dist/api/vite-plugin-cedar-vitest-api-preset.js"
27
27
  },
28
+ "./apiDevServer": {
29
+ "import": {
30
+ "types": "./dist/apiDevServer.d.ts",
31
+ "default": "./dist/apiDevServer.js"
32
+ }
33
+ },
28
34
  "./client": {
29
35
  "require": "./dist/cjs/client.js",
30
36
  "import": "./dist/client.js"
@@ -42,12 +48,14 @@
42
48
  "bin": {
43
49
  "cedar-dev-fe": "./dist/devFeServer.js",
44
50
  "cedar-serve-fe": "./dist/runFeServer.js",
51
+ "cedar-unified-dev": "./dist/cedar-unified-dev.js",
45
52
  "cedar-vite-build": "./bins/cedar-vite-build.mjs",
46
53
  "cedar-vite-dev": "./bins/cedar-vite-dev.mjs",
47
54
  "vite": "./bins/vite.mjs"
48
55
  },
49
56
  "files": [
50
57
  "dist",
58
+ "bins",
51
59
  "inject"
52
60
  ],
53
61
  "scripts": {
@@ -64,25 +72,32 @@
64
72
  "@babel/generator": "7.29.1",
65
73
  "@babel/parser": "7.29.2",
66
74
  "@babel/traverse": "7.29.0",
67
- "@cedarjs/auth": "4.0.0-canary.13862",
68
- "@cedarjs/babel-config": "4.0.0-canary.13862",
69
- "@cedarjs/cookie-jar": "4.0.0-canary.13862",
70
- "@cedarjs/internal": "4.0.0-canary.13862",
71
- "@cedarjs/project-config": "4.0.0-canary.13862",
72
- "@cedarjs/server-store": "4.0.0-canary.13862",
73
- "@cedarjs/testing": "4.0.0-canary.13862",
74
- "@cedarjs/web": "4.0.0-canary.13862",
75
+ "@cedarjs/api-server": "4.0.0-canary.13864",
76
+ "@cedarjs/auth": "4.0.0-canary.13864",
77
+ "@cedarjs/babel-config": "4.0.0-canary.13864",
78
+ "@cedarjs/context": "4.0.0-canary.13864",
79
+ "@cedarjs/cookie-jar": "4.0.0-canary.13864",
80
+ "@cedarjs/graphql-server": "4.0.0-canary.13864",
81
+ "@cedarjs/internal": "4.0.0-canary.13864",
82
+ "@cedarjs/project-config": "4.0.0-canary.13864",
83
+ "@cedarjs/server-store": "4.0.0-canary.13864",
84
+ "@cedarjs/testing": "4.0.0-canary.13864",
85
+ "@cedarjs/web": "4.0.0-canary.13864",
86
+ "@fastify/url-data": "6.0.3",
75
87
  "@swc/core": "1.15.30",
76
88
  "@vitejs/plugin-react": "4.7.0",
77
89
  "@whatwg-node/fetch": "0.10.13",
78
90
  "@whatwg-node/server": "0.10.18",
79
91
  "acorn-loose": "8.5.2",
92
+ "ansis": "4.2.0",
80
93
  "buffer": "6.0.3",
81
94
  "busboy": "^1.6.0",
82
95
  "cookie": "1.1.1",
83
96
  "dotenv-defaults": "5.0.2",
84
97
  "execa": "5.1.1",
85
98
  "express": "4.22.1",
99
+ "fastify": "5.8.5",
100
+ "fastify-raw-body": "5.0.0",
86
101
  "find-my-way": "8.2.2",
87
102
  "http-proxy-middleware": "3.0.5",
88
103
  "isbot": "5.1.39",
@@ -98,6 +113,7 @@
98
113
  "devDependencies": {
99
114
  "@arethetypeswrong/cli": "0.18.2",
100
115
  "@hyrious/esbuild-plugin-commonjs": "0.2.6",
116
+ "@types/aws-lambda": "8.10.161",
101
117
  "@types/busboy": "^1",
102
118
  "@types/express": "4",
103
119
  "@types/react": "^18.2.55",
@@ -118,5 +134,5 @@
118
134
  "publishConfig": {
119
135
  "access": "public"
120
136
  },
121
- "gitHead": "892b5320e602fc6013a521f2dbf1de5dbceb5014"
137
+ "gitHead": "614320224990c781870b0f412c3fd5a058de64e5"
122
138
  }