@ramonyx/bundler 1.1.0 → 1.2.0

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/dev.d.ts CHANGED
@@ -1,11 +1,23 @@
1
1
  import { type ModuleImporter } from "@ramonyx/compiler";
2
+ import type { FetchHandler } from "@ramonyx/core";
2
3
  import { type PluginOption } from "vite";
3
4
  import { type DevtoolsCollector } from "./devtools.js";
4
5
  export interface DevServerOptions {
5
6
  readonly appDir: string;
6
- /** URL server SSR yang diproksikan (mis. "http://localhost:3000"). */
7
- readonly target: string;
7
+ /**
8
+ * Mode terintegrasi: factory handler SSR. Vite berjalan sebagai middleware di server yang
9
+ * sama; `target` tidak dipakai.
10
+ */
11
+ readonly handler?: (context: {
12
+ readonly importer: ModuleImporter;
13
+ readonly devtools: DevtoolsCollector;
14
+ }) => FetchHandler | Promise<FetchHandler>;
15
+ /** Mode proxy lama: URL server SSR terpisah (mis. "http://localhost:3000"). */
16
+ readonly target?: string;
17
+ /** Port HTTP server (mode terintegrasi: port publik/dev). */
8
18
  readonly port?: number;
19
+ /** Interface bind; default localhost. */
20
+ readonly host?: string;
9
21
  /** Plugin Vite tambahan (dari plugin Ramonyx — ADR-0067). */
10
22
  readonly plugins?: readonly PluginOption[];
11
23
  }
@@ -13,13 +25,19 @@ export interface DevServer {
13
25
  readonly url: string;
14
26
  /** Importer untuk compiler: modul mengikuti module graph Vite (invalidasi saat file berubah). */
15
27
  readonly importer: ModuleImporter;
16
- readonly target: string;
28
+ /** Hanya ada di mode proxy lama. */
29
+ readonly target?: string;
17
30
  /** Kolektor panel devtools (ADR-0077) — pasang `hooks`/`middleware`-nya ke handler aplikasi. */
18
31
  readonly devtools: DevtoolsCollector;
19
32
  close(): Promise<void>;
20
33
  }
21
34
  /**
22
- * Dev server: Vite (transform + HMR) sebagai front, proxy ke server SSR.
35
+ * Dev server: Vite (transform + HMR) dan SSR.
36
+ *
37
+ * - Mode terintegrasi (`handler`): satu HTTP server/port; Vite middleware + HMR WebSocket
38
+ * menempel ke server yang sama, SSR menjadi middleware terakhir.
39
+ * - Mode proxy lama (`target`): Vite port terpisah memproksikan request ke SSR.
40
+ *
23
41
  * Modul halaman/manifest dimuat lewat `vite.ssrLoadModule` agar SSR ikut segar saat file berubah
24
42
  * (tanpa restart); perubahan di `src/routes` meregenerasi entry client + full-reload browser.
25
43
  */
package/dist/dev.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
3
+ import { createServer as createHttpServer } from "node:http";
3
4
  import { extname, join, relative } from "node:path";
4
5
  import { Readable } from "node:stream";
5
6
  import { pipeline } from "node:stream/promises";
7
+ import { createNodeRequestListener } from "@ramonyx/adapter-runtime";
6
8
  import { generateClientEntry, listApiRoutes, loadPageRoutes, RouteManifestError, } from "@ramonyx/compiler";
7
9
  import { createServer } from "vite";
8
10
  import { createDevtoolsCollector, devtoolsPanelHtml } from "./devtools.js";
@@ -134,8 +136,28 @@ async function proxyToSsr(target, req, res, next) {
134
136
  next(error);
135
137
  }
136
138
  }
139
+ /** Mode proxy lama: Vite dan SSR berjalan di port berbeda. */
140
+ function ssrProxyPlugin(target) {
141
+ return {
142
+ name: "ramonyx-ssr-proxy",
143
+ configureServer(server) {
144
+ server.middlewares.use((req, res, next) => {
145
+ if (req.url === undefined || isViteRequest(req.url)) {
146
+ next();
147
+ return;
148
+ }
149
+ void proxyToSsr(target, req, res, next);
150
+ });
151
+ },
152
+ };
153
+ }
137
154
  /**
138
- * Dev server: Vite (transform + HMR) sebagai front, proxy ke server SSR.
155
+ * Dev server: Vite (transform + HMR) dan SSR.
156
+ *
157
+ * - Mode terintegrasi (`handler`): satu HTTP server/port; Vite middleware + HMR WebSocket
158
+ * menempel ke server yang sama, SSR menjadi middleware terakhir.
159
+ * - Mode proxy lama (`target`): Vite port terpisah memproksikan request ke SSR.
160
+ *
139
161
  * Modul halaman/manifest dimuat lewat `vite.ssrLoadModule` agar SSR ikut segar saat file berubah
140
162
  * (tanpa restart); perubahan di `src/routes` meregenerasi entry client + full-reload browser.
141
163
  */
@@ -171,13 +193,24 @@ export async function createDevServer(options) {
171
193
  }
172
194
  devtools.setAssets(entries);
173
195
  };
196
+ const integrated = options.handler !== undefined;
197
+ const proxyTarget = options.target;
198
+ if (!integrated && proxyTarget === undefined) {
199
+ throw new Error("createDevServer: butuh `handler` (mode terintegrasi) atau `target` (mode proxy)");
200
+ }
201
+ const integratedServer = integrated ? createHttpServer() : undefined;
174
202
  const vite = await createServer({
175
203
  configFile: false,
176
204
  root: appDir,
177
205
  appType: "custom",
178
206
  logLevel: "info",
179
207
  esbuild: { jsx: "automatic" },
180
- server: { port: options.port ?? 5173 },
208
+ server: integrated
209
+ ? {
210
+ middlewareMode: { server: integratedServer },
211
+ ws: { server: integratedServer },
212
+ }
213
+ : { port: options.port ?? 5173 },
181
214
  plugins: [
182
215
  ...(options.plugins ?? []),
183
216
  serverOnlyPlugin(),
@@ -207,18 +240,7 @@ export async function createDevServer(options) {
207
240
  });
208
241
  },
209
242
  },
210
- {
211
- name: "ramonyx-ssr-proxy",
212
- configureServer(server) {
213
- server.middlewares.use((req, res, next) => {
214
- if (req.url === undefined || isViteRequest(req.url)) {
215
- next();
216
- return;
217
- }
218
- void proxyToSsr(options.target, req, res, next);
219
- });
220
- },
221
- },
243
+ ...(integrated ? [] : [ssrProxyPlugin(proxyTarget)]),
222
244
  ],
223
245
  });
224
246
  const importer = async (absolute, label) => {
@@ -261,6 +283,56 @@ export async function createDevServer(options) {
261
283
  vite.ws.send({ type: "full-reload" });
262
284
  });
263
285
  });
286
+ if (integrated) {
287
+ const server = integratedServer;
288
+ const fetchHandler = await options.handler?.({ importer, devtools });
289
+ if (fetchHandler === undefined) {
290
+ throw new Error("createDevServer: handler tidak mengembalikan FetchHandler");
291
+ }
292
+ // SSR adalah middleware terakhir: request yang tidak ditangani Vite/plugin masuk ke app.
293
+ vite.middlewares.use(createNodeRequestListener(fetchHandler, { onError: console.error }));
294
+ server.on("request", (req, res) => {
295
+ vite.middlewares(req, res, (error) => {
296
+ if (error) {
297
+ console.error(error);
298
+ if (!res.headersSent) {
299
+ res.writeHead(500, { "content-type": "application/json" });
300
+ }
301
+ res.end(JSON.stringify({ error: "Internal Server Error" }));
302
+ return;
303
+ }
304
+ if (!res.headersSent) {
305
+ res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
306
+ }
307
+ res.end("Not found");
308
+ });
309
+ });
310
+ await new Promise((resolve, reject) => {
311
+ server.once("error", reject);
312
+ server.listen(options.port ?? 3000, options.host ?? "localhost", () => {
313
+ server.off("error", reject);
314
+ resolve();
315
+ });
316
+ });
317
+ const address = server.address();
318
+ const port = typeof address === "object" && address !== null ? address.port : (options.port ?? 3000);
319
+ const host = options.host === undefined ||
320
+ options.host === "0.0.0.0" ||
321
+ options.host === "::" ||
322
+ options.host === "127.0.0.1"
323
+ ? "localhost"
324
+ : options.host;
325
+ return {
326
+ url: `http://${host}:${port}`,
327
+ importer,
328
+ devtools,
329
+ close: async () => {
330
+ server.closeAllConnections();
331
+ await new Promise((resolve) => server.close(() => resolve()));
332
+ await vite.close();
333
+ },
334
+ };
335
+ }
264
336
  await vite.listen();
265
337
  const address = vite.httpServer?.address();
266
338
  const port = typeof address === "object" && address !== null ? address.port : (options.port ?? 5173);
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../packages/bundler/src/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport type { ServerResponse } from \"node:http\";\nimport { extname, join, relative } from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport {\n generateClientEntry,\n listApiRoutes,\n loadPageRoutes,\n type ModuleImporter,\n RouteManifestError,\n} from \"@ramonyx/compiler\";\nimport { type Connect, createServer, type Plugin, type PluginOption } from \"vite\";\nimport { createDevtoolsCollector, type DevtoolsCollector, devtoolsPanelHtml } from \"./devtools.ts\";\nimport { readAssetManifest } from \"./manifest.ts\";\nimport { serverOnlyPlugin } from \"./server-only.ts\";\n\nexport interface DevServerOptions {\n readonly appDir: string;\n /** URL server SSR yang diproksikan (mis. \"http://localhost:3000\"). */\n readonly target: string;\n readonly port?: number;\n /** Plugin Vite tambahan (dari plugin Ramonyx — ADR-0067). */\n readonly plugins?: readonly PluginOption[];\n}\n\nexport interface DevServer {\n readonly url: string;\n /** Importer untuk compiler: modul mengikuti module graph Vite (invalidasi saat file berubah). */\n readonly importer: ModuleImporter;\n readonly target: string;\n /** Kolektor panel devtools (ADR-0077) — pasang `hooks`/`middleware`-nya ke handler aplikasi. */\n readonly devtools: DevtoolsCollector;\n close(): Promise<void>;\n}\n\nconst ENTRY_FILE = \"client-entry.ts\";\n\nconst DEV_ASSET_TYPES: Record<string, string> = {\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".otf\": \"font/otf\",\n};\n\n/**\n * Dev: sajikan `src/assets/**` apa adanya di `/assets/*` (tanpa hash) — paritas dengan\n * resolver aset dev (`createAssetResolver(..., { fallbackToPath: true })`, ADR-0069).\n */\nfunction assetsDevPlugin(appDir: string): Plugin {\n return {\n name: \"ramonyx-assets-dev\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? \"\";\n if (!url.startsWith(\"/assets/\")) {\n next();\n return;\n }\n let rel: string;\n try {\n rel = decodeURIComponent(url.slice(\"/assets/\".length).split(\"?\")[0] ?? \"\");\n } catch {\n next();\n return;\n }\n if (rel.length === 0 || rel.includes(\"..\")) {\n next();\n return;\n }\n const file = join(appDir, \"src\", \"assets\", rel);\n if (!existsSync(file)) {\n next();\n return;\n }\n void readFile(file)\n .then((data) => {\n res.setHeader(\n \"content-type\",\n DEV_ASSET_TYPES[extname(file).toLowerCase()] ?? \"application/octet-stream\",\n );\n res.setHeader(\"cache-control\", \"no-cache\");\n res.end(data);\n })\n .catch(() => next());\n });\n },\n };\n}\n\n/** Path yang dimiliki Vite (jangan diproksikan ke SSR). */\nfunction isViteRequest(url: string): boolean {\n const path = url.split(\"?\")[0] ?? \"\";\n return (\n path.startsWith(\"/@\") ||\n path.startsWith(\"/node_modules/\") ||\n path.startsWith(\"/.ramonyx/\") ||\n path.startsWith(\"/src/\") ||\n path === \"/favicon.ico\"\n );\n}\n\nconst HOP_BY_HOP = new Set([\n \"connection\",\n \"keep-alive\",\n \"transfer-encoding\",\n \"content-length\",\n \"content-encoding\",\n]);\n\n/**\n * Proxy manual ke SSR (bukan `server.proxy` Vite): request non-Vite diteruskan dengan `fetch`,\n * respons dipipe kembali apa adanya. Body request non-GET/HEAD dialirkan via `Readable.toWeb`.\n */\nasync function proxyToSsr(\n target: string,\n req: Connect.IncomingMessage,\n res: ServerResponse,\n next: Connect.NextFunction,\n): Promise<void> {\n try {\n const url = new URL(req.url ?? \"/\", target);\n const headers = new Headers();\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(name, item);\n }\n } else {\n headers.set(name, value);\n }\n }\n // Tandai request yang datang lewat Vite. SSR langsung di port 3000 tidak punya entry klien.\n headers.set(\"x-ramonyx-dev-proxy\", \"1\");\n\n const method = req.method ?? \"GET\";\n const init: RequestInit & { duplex?: \"half\" } = {\n method,\n headers,\n redirect: \"manual\",\n };\n if (method !== \"GET\" && method !== \"HEAD\") {\n init.body = Readable.toWeb(req) as unknown as BodyInit;\n init.duplex = \"half\";\n }\n\n const response = await fetch(url, init);\n res.statusCode = response.status;\n response.headers.forEach((value, name) => {\n if (name !== \"set-cookie\" && !HOP_BY_HOP.has(name)) {\n res.setHeader(name, value);\n }\n });\n const cookies = response.headers.getSetCookie();\n if (cookies.length > 0) {\n res.setHeader(\"set-cookie\", cookies);\n }\n\n if (response.body === null) {\n res.end();\n return;\n }\n await pipeline(Readable.fromWeb(response.body as never), res);\n } catch (error) {\n next(error);\n }\n}\n\n/**\n * Dev server: Vite (transform + HMR) sebagai front, proxy ke server SSR.\n * Modul halaman/manifest dimuat lewat `vite.ssrLoadModule` agar SSR ikut segar saat file berubah\n * (tanpa restart); perubahan di `src/routes` meregenerasi entry client + full-reload browser.\n */\nexport async function createDevServer(options: DevServerOptions): Promise<DevServer> {\n const appDir = options.appDir;\n const entryDir = join(appDir, \".ramonyx\");\n const entryFile = join(entryDir, ENTRY_FILE);\n const routesDir = join(appDir, \"src\", \"routes\");\n\n const devtools = createDevtoolsCollector();\n const clientDir = join(appDir, \"dist\", \"client\");\n\n /** Ukuran bundel/aset dari manifest build (bila sudah pernah dibangun). */\n const refreshAssets = async (): Promise<void> => {\n const manifest = await readAssetManifest(clientDir);\n if (manifest === null) {\n devtools.setAssets([]);\n return;\n }\n const names = new Set<string>([manifest.client, ...manifest.files]);\n const entries: { name: string; bytes: number }[] = [];\n for (const name of names) {\n try {\n const info = await stat(join(clientDir, name));\n entries.push({ name, bytes: info.size });\n } catch {\n // berkas hilang (mis. dibersihkan) — lewati\n }\n }\n if (manifest.assets !== undefined) {\n for (const entry of Object.values(manifest.assets)) {\n entries.push({ name: entry.file, bytes: entry.bytes });\n }\n }\n devtools.setAssets(entries);\n };\n\n const vite = await createServer({\n configFile: false,\n root: appDir,\n appType: \"custom\",\n logLevel: \"info\",\n esbuild: { jsx: \"automatic\" },\n server: { port: options.port ?? 5173 },\n plugins: [\n ...(options.plugins ?? []),\n serverOnlyPlugin(),\n assetsDevPlugin(appDir),\n {\n name: \"ramonyx-devtools\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const path = (req.url ?? \"\").split(\"?\")[0] ?? \"\";\n if (path === \"/__ramonyx/devtools\") {\n res.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n res.setHeader(\"cache-control\", \"no-store\");\n res.end(devtoolsPanelHtml());\n return;\n }\n if (path === \"/__ramonyx/data\") {\n void refreshAssets()\n .catch(() => undefined)\n .then(() => {\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.setHeader(\"cache-control\", \"no-store\");\n res.end(JSON.stringify(devtools.snapshot()));\n });\n return;\n }\n next();\n });\n },\n },\n {\n name: \"ramonyx-ssr-proxy\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n if (req.url === undefined || isViteRequest(req.url)) {\n next();\n return;\n }\n void proxyToSsr(options.target, req, res, next);\n });\n },\n },\n ],\n });\n\n const importer: ModuleImporter = async (absolute, label) => {\n try {\n return (await vite.ssrLoadModule(absolute)) as Record<string, unknown>;\n } catch (error) {\n throw new RouteManifestError(\n `[dev] gagal memuat ${label} (${relative(appDir, absolute) || absolute}) via Vite: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n }\n };\n\n const regenerateEntry = async (): Promise<void> => {\n const [pages, apiRoutes] = await Promise.all([\n loadPageRoutes({ dir: routesDir, importer }),\n listApiRoutes({ dir: routesDir, importer }),\n ]);\n devtools.setRoutes([\n ...pages.map((page) => ({\n path: page.path,\n kind: \"page\" as const,\n ...(page.pageFile !== undefined ? { file: relative(appDir, page.pageFile) } : {}),\n })),\n ...apiRoutes.map((route) => ({\n path: route.routePath,\n kind: \"api\" as const,\n methods: route.methods,\n file: relative(appDir, route.file),\n })),\n ]);\n await mkdir(entryDir, { recursive: true });\n await writeFile(entryFile, generateClientEntry(pages, { from: entryDir }));\n };\n await regenerateEntry();\n\n vite.watcher.on(\"all\", (_event, file) => {\n if (!file.startsWith(routesDir)) {\n return;\n }\n void regenerateEntry()\n .catch(() => undefined)\n .finally(() => {\n vite.ws.send({ type: \"full-reload\" });\n });\n });\n\n await vite.listen();\n const address = vite.httpServer?.address();\n const port =\n typeof address === \"object\" && address !== null ? address.port : (options.port ?? 5173);\n\n return {\n url: `http://localhost:${port}`,\n importer,\n target: options.target,\n devtools,\n close: () => vite.close(),\n };\n}\n"]}
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../packages/bundler/src/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { createServer as createHttpServer, type ServerResponse } from \"node:http\";\nimport { extname, join, relative } from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { createNodeRequestListener } from \"@ramonyx/adapter-runtime\";\nimport {\n generateClientEntry,\n listApiRoutes,\n loadPageRoutes,\n type ModuleImporter,\n RouteManifestError,\n} from \"@ramonyx/compiler\";\nimport type { FetchHandler } from \"@ramonyx/core\";\nimport { type Connect, createServer, type Plugin, type PluginOption } from \"vite\";\nimport { createDevtoolsCollector, type DevtoolsCollector, devtoolsPanelHtml } from \"./devtools.ts\";\nimport { readAssetManifest } from \"./manifest.ts\";\nimport { serverOnlyPlugin } from \"./server-only.ts\";\n\nexport interface DevServerOptions {\n readonly appDir: string;\n /**\n * Mode terintegrasi: factory handler SSR. Vite berjalan sebagai middleware di server yang\n * sama; `target` tidak dipakai.\n */\n readonly handler?: (context: {\n readonly importer: ModuleImporter;\n readonly devtools: DevtoolsCollector;\n }) => FetchHandler | Promise<FetchHandler>;\n /** Mode proxy lama: URL server SSR terpisah (mis. \"http://localhost:3000\"). */\n readonly target?: string;\n /** Port HTTP server (mode terintegrasi: port publik/dev). */\n readonly port?: number;\n /** Interface bind; default localhost. */\n readonly host?: string;\n /** Plugin Vite tambahan (dari plugin Ramonyx — ADR-0067). */\n readonly plugins?: readonly PluginOption[];\n}\n\nexport interface DevServer {\n readonly url: string;\n /** Importer untuk compiler: modul mengikuti module graph Vite (invalidasi saat file berubah). */\n readonly importer: ModuleImporter;\n /** Hanya ada di mode proxy lama. */\n readonly target?: string;\n /** Kolektor panel devtools (ADR-0077) — pasang `hooks`/`middleware`-nya ke handler aplikasi. */\n readonly devtools: DevtoolsCollector;\n close(): Promise<void>;\n}\n\nconst ENTRY_FILE = \"client-entry.ts\";\n\nconst DEV_ASSET_TYPES: Record<string, string> = {\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".otf\": \"font/otf\",\n};\n\n/**\n * Dev: sajikan `src/assets/**` apa adanya di `/assets/*` (tanpa hash) — paritas dengan\n * resolver aset dev (`createAssetResolver(..., { fallbackToPath: true })`, ADR-0069).\n */\nfunction assetsDevPlugin(appDir: string): Plugin {\n return {\n name: \"ramonyx-assets-dev\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? \"\";\n if (!url.startsWith(\"/assets/\")) {\n next();\n return;\n }\n let rel: string;\n try {\n rel = decodeURIComponent(url.slice(\"/assets/\".length).split(\"?\")[0] ?? \"\");\n } catch {\n next();\n return;\n }\n if (rel.length === 0 || rel.includes(\"..\")) {\n next();\n return;\n }\n const file = join(appDir, \"src\", \"assets\", rel);\n if (!existsSync(file)) {\n next();\n return;\n }\n void readFile(file)\n .then((data) => {\n res.setHeader(\n \"content-type\",\n DEV_ASSET_TYPES[extname(file).toLowerCase()] ?? \"application/octet-stream\",\n );\n res.setHeader(\"cache-control\", \"no-cache\");\n res.end(data);\n })\n .catch(() => next());\n });\n },\n };\n}\n\n/** Path yang dimiliki Vite (jangan diproksikan ke SSR). */\nfunction isViteRequest(url: string): boolean {\n const path = url.split(\"?\")[0] ?? \"\";\n return (\n path.startsWith(\"/@\") ||\n path.startsWith(\"/node_modules/\") ||\n path.startsWith(\"/.ramonyx/\") ||\n path.startsWith(\"/src/\") ||\n path === \"/favicon.ico\"\n );\n}\n\nconst HOP_BY_HOP = new Set([\n \"connection\",\n \"keep-alive\",\n \"transfer-encoding\",\n \"content-length\",\n \"content-encoding\",\n]);\n\n/**\n * Proxy manual ke SSR (bukan `server.proxy` Vite): request non-Vite diteruskan dengan `fetch`,\n * respons dipipe kembali apa adanya. Body request non-GET/HEAD dialirkan via `Readable.toWeb`.\n */\nasync function proxyToSsr(\n target: string,\n req: Connect.IncomingMessage,\n res: ServerResponse,\n next: Connect.NextFunction,\n): Promise<void> {\n try {\n const url = new URL(req.url ?? \"/\", target);\n const headers = new Headers();\n for (const [name, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(name, item);\n }\n } else {\n headers.set(name, value);\n }\n }\n // Tandai request yang datang lewat Vite. SSR langsung di port 3000 tidak punya entry klien.\n headers.set(\"x-ramonyx-dev-proxy\", \"1\");\n\n const method = req.method ?? \"GET\";\n const init: RequestInit & { duplex?: \"half\" } = {\n method,\n headers,\n redirect: \"manual\",\n };\n if (method !== \"GET\" && method !== \"HEAD\") {\n init.body = Readable.toWeb(req) as unknown as BodyInit;\n init.duplex = \"half\";\n }\n\n const response = await fetch(url, init);\n res.statusCode = response.status;\n response.headers.forEach((value, name) => {\n if (name !== \"set-cookie\" && !HOP_BY_HOP.has(name)) {\n res.setHeader(name, value);\n }\n });\n const cookies = response.headers.getSetCookie();\n if (cookies.length > 0) {\n res.setHeader(\"set-cookie\", cookies);\n }\n\n if (response.body === null) {\n res.end();\n return;\n }\n await pipeline(Readable.fromWeb(response.body as never), res);\n } catch (error) {\n next(error);\n }\n}\n\n/** Mode proxy lama: Vite dan SSR berjalan di port berbeda. */\nfunction ssrProxyPlugin(target: string): Plugin {\n return {\n name: \"ramonyx-ssr-proxy\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n if (req.url === undefined || isViteRequest(req.url)) {\n next();\n return;\n }\n void proxyToSsr(target, req, res, next);\n });\n },\n };\n}\n\n/**\n * Dev server: Vite (transform + HMR) dan SSR.\n *\n * - Mode terintegrasi (`handler`): satu HTTP server/port; Vite middleware + HMR WebSocket\n * menempel ke server yang sama, SSR menjadi middleware terakhir.\n * - Mode proxy lama (`target`): Vite port terpisah memproksikan request ke SSR.\n *\n * Modul halaman/manifest dimuat lewat `vite.ssrLoadModule` agar SSR ikut segar saat file berubah\n * (tanpa restart); perubahan di `src/routes` meregenerasi entry client + full-reload browser.\n */\nexport async function createDevServer(options: DevServerOptions): Promise<DevServer> {\n const appDir = options.appDir;\n const entryDir = join(appDir, \".ramonyx\");\n const entryFile = join(entryDir, ENTRY_FILE);\n const routesDir = join(appDir, \"src\", \"routes\");\n\n const devtools = createDevtoolsCollector();\n const clientDir = join(appDir, \"dist\", \"client\");\n\n /** Ukuran bundel/aset dari manifest build (bila sudah pernah dibangun). */\n const refreshAssets = async (): Promise<void> => {\n const manifest = await readAssetManifest(clientDir);\n if (manifest === null) {\n devtools.setAssets([]);\n return;\n }\n const names = new Set<string>([manifest.client, ...manifest.files]);\n const entries: { name: string; bytes: number }[] = [];\n for (const name of names) {\n try {\n const info = await stat(join(clientDir, name));\n entries.push({ name, bytes: info.size });\n } catch {\n // berkas hilang (mis. dibersihkan) — lewati\n }\n }\n if (manifest.assets !== undefined) {\n for (const entry of Object.values(manifest.assets)) {\n entries.push({ name: entry.file, bytes: entry.bytes });\n }\n }\n devtools.setAssets(entries);\n };\n\n const integrated = options.handler !== undefined;\n const proxyTarget = options.target;\n if (!integrated && proxyTarget === undefined) {\n throw new Error(\n \"createDevServer: butuh `handler` (mode terintegrasi) atau `target` (mode proxy)\",\n );\n }\n const integratedServer = integrated ? createHttpServer() : undefined;\n const vite = await createServer({\n configFile: false,\n root: appDir,\n appType: \"custom\",\n logLevel: \"info\",\n esbuild: { jsx: \"automatic\" },\n server: integrated\n ? {\n middlewareMode: { server: integratedServer as ReturnType<typeof createHttpServer> },\n ws: { server: integratedServer as ReturnType<typeof createHttpServer> },\n }\n : { port: options.port ?? 5173 },\n plugins: [\n ...(options.plugins ?? []),\n serverOnlyPlugin(),\n assetsDevPlugin(appDir),\n {\n name: \"ramonyx-devtools\",\n configureServer(server) {\n server.middlewares.use((req, res, next) => {\n const path = (req.url ?? \"\").split(\"?\")[0] ?? \"\";\n if (path === \"/__ramonyx/devtools\") {\n res.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n res.setHeader(\"cache-control\", \"no-store\");\n res.end(devtoolsPanelHtml());\n return;\n }\n if (path === \"/__ramonyx/data\") {\n void refreshAssets()\n .catch(() => undefined)\n .then(() => {\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.setHeader(\"cache-control\", \"no-store\");\n res.end(JSON.stringify(devtools.snapshot()));\n });\n return;\n }\n next();\n });\n },\n },\n ...(integrated ? [] : [ssrProxyPlugin(proxyTarget as string)]),\n ],\n });\n\n const importer: ModuleImporter = async (absolute, label) => {\n try {\n return (await vite.ssrLoadModule(absolute)) as Record<string, unknown>;\n } catch (error) {\n throw new RouteManifestError(\n `[dev] gagal memuat ${label} (${relative(appDir, absolute) || absolute}) via Vite: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n }\n };\n\n const regenerateEntry = async (): Promise<void> => {\n const [pages, apiRoutes] = await Promise.all([\n loadPageRoutes({ dir: routesDir, importer }),\n listApiRoutes({ dir: routesDir, importer }),\n ]);\n devtools.setRoutes([\n ...pages.map((page) => ({\n path: page.path,\n kind: \"page\" as const,\n ...(page.pageFile !== undefined ? { file: relative(appDir, page.pageFile) } : {}),\n })),\n ...apiRoutes.map((route) => ({\n path: route.routePath,\n kind: \"api\" as const,\n methods: route.methods,\n file: relative(appDir, route.file),\n })),\n ]);\n await mkdir(entryDir, { recursive: true });\n await writeFile(entryFile, generateClientEntry(pages, { from: entryDir }));\n };\n await regenerateEntry();\n\n vite.watcher.on(\"all\", (_event, file) => {\n if (!file.startsWith(routesDir)) {\n return;\n }\n void regenerateEntry()\n .catch(() => undefined)\n .finally(() => {\n vite.ws.send({ type: \"full-reload\" });\n });\n });\n\n if (integrated) {\n const server = integratedServer as ReturnType<typeof createHttpServer>;\n const fetchHandler = await options.handler?.({ importer, devtools });\n if (fetchHandler === undefined) {\n throw new Error(\"createDevServer: handler tidak mengembalikan FetchHandler\");\n }\n // SSR adalah middleware terakhir: request yang tidak ditangani Vite/plugin masuk ke app.\n vite.middlewares.use(createNodeRequestListener(fetchHandler, { onError: console.error }));\n server.on(\"request\", (req, res) => {\n vite.middlewares(req, res, (error: unknown) => {\n if (error) {\n console.error(error);\n if (!res.headersSent) {\n res.writeHead(500, { \"content-type\": \"application/json\" });\n }\n res.end(JSON.stringify({ error: \"Internal Server Error\" }));\n return;\n }\n if (!res.headersSent) {\n res.writeHead(404, { \"content-type\": \"text/plain; charset=utf-8\" });\n }\n res.end(\"Not found\");\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(options.port ?? 3000, options.host ?? \"localhost\", () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n const address = server.address();\n const port =\n typeof address === \"object\" && address !== null ? address.port : (options.port ?? 3000);\n const host =\n options.host === undefined ||\n options.host === \"0.0.0.0\" ||\n options.host === \"::\" ||\n options.host === \"127.0.0.1\"\n ? \"localhost\"\n : options.host;\n\n return {\n url: `http://${host}:${port}`,\n importer,\n devtools,\n close: async () => {\n server.closeAllConnections();\n await new Promise<void>((resolve) => server.close(() => resolve()));\n await vite.close();\n },\n };\n }\n\n await vite.listen();\n const address = vite.httpServer?.address();\n const port =\n typeof address === \"object\" && address !== null ? address.port : (options.port ?? 5173);\n\n return {\n url: `http://localhost:${port}`,\n importer,\n target: options.target,\n devtools,\n close: () => vite.close(),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ramonyx/bundler",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Build pipeline for Ramonyx: Vite client bundles, edge builds, static prerender, and plugin hooks.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,8 +19,9 @@
19
19
  "node": ">=24"
20
20
  },
21
21
  "dependencies": {
22
- "@ramonyx/compiler": "^1.1.0",
23
- "@ramonyx/core": "^1.1.0",
22
+ "@ramonyx/adapter-runtime": "^1.2.0",
23
+ "@ramonyx/compiler": "^1.2.0",
24
+ "@ramonyx/core": "^1.2.0",
24
25
  "vite": "8.3.4"
25
26
  },
26
27
  "publishConfig": {