oxidejs 0.1.10 → 0.2.1
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/README.md +26 -5
- package/dist/index.d.mts +9 -12
- package/dist/index.mjs +1 -1
- package/dist/rsbuild.d.mts +1 -1
- package/dist/rsbuild.mjs +2 -1
- package/dist/{src-CkhMD9M5.mjs → src-CsQ-6GnW.mjs} +126 -16
- package/dist/{types-CMEB9B4S.d.mts → types-BM4NAnzy.d.mts} +24 -2
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -76,15 +76,15 @@ export default {
|
|
|
76
76
|
};
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
`action()` is identity — it
|
|
79
|
+
`action()` is runtime identity — it marks the export and adds a typed transport-only `{ signal }` argument. Wrap `async function*` in it to stream over tacho SSE. Inside server code, always read the non-optional signal from `useRequest().signal`:
|
|
80
80
|
|
|
81
81
|
```ts
|
|
82
82
|
// src/test.server.ts
|
|
83
|
-
import { action } from "oxidejs";
|
|
84
|
-
import type { ActionOptions } from "oxidejs";
|
|
83
|
+
import { action, useRequest } from "oxidejs";
|
|
85
84
|
|
|
86
|
-
export const ticks = action(async function* (n: number
|
|
87
|
-
|
|
85
|
+
export const ticks = action(async function* (n: number) {
|
|
86
|
+
const { signal } = useRequest();
|
|
87
|
+
for (let i = 0; i < n && !signal.aborted; i++) yield i;
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
// src/client.ts
|
|
@@ -113,6 +113,27 @@ Same factory as Vite: client stubs, `/__oxide/action`, and `dist/server.js`.
|
|
|
113
113
|
|
|
114
114
|
## Options
|
|
115
115
|
|
|
116
|
+
### `middleware` and `imports`
|
|
117
|
+
|
|
118
|
+
\`\`\`ts
|
|
119
|
+
oxide({
|
|
120
|
+
middleware: ["@ilha/router/ssr"], // string or { module, imports }
|
|
121
|
+
imports: ["./side-effects"], // side-effect modules loaded at startup
|
|
122
|
+
})
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
Middleware handlers run in production before the action gate; the same specifiers are loaded through the SSR graph in dev, so dev and prod behave identically. Middleware entries may carry their own \`imports\`.
|
|
126
|
+
|
|
127
|
+
### Other server options
|
|
128
|
+
|
|
129
|
+
| Option | Type | Default | Description |
|
|
130
|
+
| ------------- | ------ | ------- | -------------------------------------------------------------------- |
|
|
131
|
+
| \`bodyLimit\` | number | 1048576 | Max request body size (Node preset); larger requests get 413 |
|
|
132
|
+
| \`notFound\` | string | — | Custom HTML 404 body when no route or asset matches |
|
|
133
|
+
| \`env\` | object | — | Passed as \`env\` to \`fetch(request, env, ctx)\` on the Node preset |
|
|
134
|
+
|
|
135
|
+
## Options
|
|
136
|
+
|
|
116
137
|
| Option | Default | Notes |
|
|
117
138
|
| ------------------------------ | ------------------------ | ------------------------------------------------------------------------------------------- |
|
|
118
139
|
| `preset` | `"fetch"` | `"fetch"` or `"celld"` |
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as OxidejsWranglerOptions, i as OxidejsPreset, n as OxidejsActionTransport, o as ResolvedOptions, r as OxidejsOptions, t as OxidejsActionHeaders } from "./types-
|
|
1
|
+
import { a as OxidejsWranglerOptions, i as OxidejsPreset, n as OxidejsActionTransport, o as ResolvedOptions, r as OxidejsOptions, t as OxidejsActionHeaders } from "./types-BM4NAnzy.mjs";
|
|
2
2
|
import { UnpluginFactory } from "unplugin";
|
|
3
3
|
//#region src/context.d.ts
|
|
4
4
|
type ExecutionContext = {
|
|
@@ -12,28 +12,25 @@ type ActionContext = {
|
|
|
12
12
|
fetchCtx?: ExecutionContext;
|
|
13
13
|
[key: string]: unknown;
|
|
14
14
|
};
|
|
15
|
-
/** Current tacho
|
|
15
|
+
/** Current tacho or host request context. Throws outside request handling. */
|
|
16
16
|
declare function useCtx<C extends ActionContext = ActionContext>(): C;
|
|
17
|
-
/** Current
|
|
17
|
+
/** Current server `Request`. Available in actions, SSR, and frame renders. */
|
|
18
18
|
declare function useRequest(): Request;
|
|
19
19
|
/** Worker `env` from `fetch(request, env, ctx)`. `undefined` on the Node fetch preset. */
|
|
20
20
|
declare function useEnv<E = unknown>(): E | undefined;
|
|
21
21
|
/** Worker `ctx` from `fetch(request, env, ctx)` (`waitUntil`). Not tacho `ctx`. `undefined` on Node. */
|
|
22
22
|
declare function useFetchCtx(): ExecutionContext | undefined;
|
|
23
|
-
/** Optional last argument on a `*.server.ts` export so the client can pass `{ signal }`. */
|
|
24
|
-
type ActionOptions = {
|
|
25
|
-
signal?: AbortSignal;
|
|
26
|
-
};
|
|
27
23
|
/**
|
|
28
|
-
* Marks a `*.server.ts` export as a remote RPC action.
|
|
29
|
-
*
|
|
30
|
-
* server-local. Wrap async functions and async generators.
|
|
24
|
+
* Marks a `*.server.ts` export as a remote RPC action. Runtime identity; the
|
|
25
|
+
* second call signature adds the transport-only `{ signal }` argument.
|
|
31
26
|
*/
|
|
32
|
-
declare function action<
|
|
27
|
+
declare function action<Args extends unknown[], Result>(fn: (...args: Args) => Result): typeof fn & ((...args: [...Args, options: {
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
}]) => Result);
|
|
33
30
|
//#endregion
|
|
34
31
|
//#region src/index.d.ts
|
|
35
32
|
declare const unpluginFactory: UnpluginFactory<OxidejsOptions | undefined>;
|
|
36
33
|
declare const oxidejs: import("unplugin").UnpluginInstance<OxidejsOptions | undefined, boolean>;
|
|
37
34
|
declare const vite: (options?: OxidejsOptions | undefined) => import("vite").Plugin<any> | import("vite").Plugin<any>[];
|
|
38
35
|
//#endregion
|
|
39
|
-
export { type ActionContext, type
|
|
36
|
+
export { type ActionContext, type ExecutionContext, type OxidejsActionHeaders, type OxidejsActionTransport, type OxidejsOptions, type OxidejsPreset, type OxidejsWranglerOptions, type ResolvedOptions, action, oxidejs as default, oxidejs, unpluginFactory, useCtx, useEnv, useFetchCtx, useRequest, vite };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as useCtx, c as useRequest, i as action, n as unpluginFactory, o as useEnv, r as vite, s as useFetchCtx, t as oxidejs } from "./src-
|
|
1
|
+
import { a as useCtx, c as useRequest, i as action, n as unpluginFactory, o as useEnv, r as vite, s as useFetchCtx, t as oxidejs } from "./src-CsQ-6GnW.mjs";
|
|
2
2
|
export { action, oxidejs as default, oxidejs, unpluginFactory, useCtx, useEnv, useFetchCtx, useRequest, vite };
|
package/dist/rsbuild.d.mts
CHANGED
package/dist/rsbuild.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { t as oxidejs } from "./src-
|
|
1
|
+
import { t as oxidejs } from "./src-CsQ-6GnW.mjs";
|
|
2
2
|
//#region src/rsbuild.ts
|
|
3
|
+
/** @experimental Rsbuild integration is not yet implemented. */
|
|
3
4
|
var rsbuild_default = oxidejs.rsbuild;
|
|
4
5
|
//#endregion
|
|
5
6
|
export { rsbuild_default as default };
|
|
@@ -3,7 +3,41 @@ import path from "node:path";
|
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
|
+
//#region \0rolldown/runtime.js
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __exportAll = (all, no_symbols) => {
|
|
9
|
+
let target = {};
|
|
10
|
+
for (var name in all) __defProp(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true
|
|
13
|
+
});
|
|
14
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
15
|
+
return target;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
6
18
|
//#region src/actions.ts
|
|
19
|
+
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
20
|
+
ACTION_PATH: () => ACTION_PATH,
|
|
21
|
+
RESOLVED_VIRTUAL_ACTIONS_ID: () => RESOLVED_VIRTUAL_ACTIONS_ID,
|
|
22
|
+
RESOLVED_VIRTUAL_CLIENT_ID: () => RESOLVED_VIRTUAL_CLIENT_ID,
|
|
23
|
+
RESOLVED_VIRTUAL_WORKER_ID: () => RESOLVED_VIRTUAL_WORKER_ID,
|
|
24
|
+
VIRTUAL_ACTIONS_ID: () => VIRTUAL_ACTIONS_ID,
|
|
25
|
+
VIRTUAL_CLIENT_ID: () => VIRTUAL_CLIENT_ID,
|
|
26
|
+
VIRTUAL_WORKER_ID: () => VIRTUAL_WORKER_ID,
|
|
27
|
+
generateActionsModule: () => generateActionsModule,
|
|
28
|
+
generateClientModule: () => generateClientModule,
|
|
29
|
+
generateClientStub: () => generateClientStub,
|
|
30
|
+
generateWorkerWrapper: () => generateWorkerWrapper,
|
|
31
|
+
isServerFileId: () => isServerFileId,
|
|
32
|
+
loadClientStub: () => loadClientStub,
|
|
33
|
+
moduleKey: () => moduleKey,
|
|
34
|
+
nodeToWebRequest: () => nodeToWebRequest,
|
|
35
|
+
parseExportedNames: () => parseExportedNames,
|
|
36
|
+
pluginShouldStub: () => pluginShouldStub,
|
|
37
|
+
scanServerFiles: () => scanServerFiles,
|
|
38
|
+
sendWebResponseFrom: () => sendWebResponseFrom,
|
|
39
|
+
shouldStubServerModule: () => shouldStubServerModule
|
|
40
|
+
});
|
|
7
41
|
const VIRTUAL_ACTIONS_ID = "virtual:oxide/actions";
|
|
8
42
|
const RESOLVED_VIRTUAL_ACTIONS_ID = `\0${VIRTUAL_ACTIONS_ID}`;
|
|
9
43
|
const VIRTUAL_WORKER_ID = "virtual:oxide/worker";
|
|
@@ -175,6 +209,8 @@ function generateWorkerWrapper(userWorkerAbs, opts = {}) {
|
|
|
175
209
|
const serveAssets = preset === "fetch" && (opts.hasClient === true || opts.hasPublic === true);
|
|
176
210
|
const hasActions = opts.hasActions !== false;
|
|
177
211
|
const ws = hasActions && opts.actions === "ws";
|
|
212
|
+
const bodyLimit = opts.bodyLimit ?? 1048576;
|
|
213
|
+
const nfBlock = `const __nf = ${`() => new Response(${JSON.stringify(opts.notFound ?? "<h1>404 Not Found</h1>")}, { status: 404, headers: { "content-type": "text/html; charset=utf-8" } })`};\n`;
|
|
178
214
|
const assetBlock = serveAssets ? `import { readFile } from "node:fs/promises";
|
|
179
215
|
import { extname, join } from "node:path";
|
|
180
216
|
const __assets = join(import.meta.dirname, ${JSON.stringify(clientDir)});
|
|
@@ -207,24 +243,31 @@ async function __asset(request, spa) {
|
|
|
207
243
|
const headers = { "content-type": __types[extname(file)] ?? "application/octet-stream" };
|
|
208
244
|
const cache = __cache(file);
|
|
209
245
|
if (cache) headers["cache-control"] = cache;
|
|
246
|
+
const etag = '"' + body.length.toString(16) + "-" + file + '"';
|
|
247
|
+
headers["etag"] = etag;
|
|
248
|
+
if (request.headers.get("if-none-match") === etag) {
|
|
249
|
+
return new Response(null, { status: 304, headers });
|
|
250
|
+
}
|
|
210
251
|
return new Response(body, { headers });
|
|
211
252
|
} catch {
|
|
212
253
|
return;
|
|
213
254
|
}
|
|
214
255
|
}
|
|
215
256
|
` : "";
|
|
257
|
+
const envJson = JSON.stringify(opts.env ?? {});
|
|
216
258
|
const afterAction = serveAssets ? `if (typeof user.fetch === "function") {
|
|
217
|
-
const hit = await user.fetch(request, env, ctx);
|
|
259
|
+
const hit = await user.fetch(request, env ?? ${envJson}, ctx);
|
|
218
260
|
if (hit) return hit;
|
|
219
261
|
}
|
|
220
|
-
return (await __asset(request)) ?? (__nav(request) ? await __asset(request, true) : undefined) ??
|
|
262
|
+
return (await __asset(request)) ?? (__nav(request) ? await __asset(request, true) : undefined) ?? __nf();` : `return typeof user.fetch === "function"
|
|
221
263
|
? user.fetch(request, env, ctx)
|
|
222
|
-
:
|
|
264
|
+
: __nf();`;
|
|
223
265
|
const listen = preset === "fetch" ? `
|
|
224
266
|
import { createServer } from "node:http";
|
|
225
267
|
import { pathToFileURL } from "node:url";
|
|
226
268
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
227
269
|
const port = Number(process.env.PORT) || 3000;
|
|
270
|
+
const bodyLimit = ${bodyLimit};
|
|
228
271
|
const server = createServer(async (req, res) => {
|
|
229
272
|
const url = \`http://\${req.headers.host ?? "localhost"}\${req.url ?? "/"}\`;
|
|
230
273
|
const headers = new Headers();
|
|
@@ -237,7 +280,13 @@ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
|
|
|
237
280
|
req.once("aborted", () => ac.abort());
|
|
238
281
|
const method = req.method ?? "GET";
|
|
239
282
|
const chunks = [];
|
|
240
|
-
|
|
283
|
+
let size = 0;
|
|
284
|
+
if (method !== "GET" && method !== "HEAD") for await (const chunk of req) {
|
|
285
|
+
size += chunk.length;
|
|
286
|
+
// Bound request buffering — unbounded bodies are a memory DoS vector.
|
|
287
|
+
if (size > ${bodyLimit}) { res.statusCode = 413; res.end(); return; }
|
|
288
|
+
chunks.push(chunk);
|
|
289
|
+
}
|
|
241
290
|
const init = { method, headers, signal: ac.signal };
|
|
242
291
|
if (chunks.length) init.body = Buffer.concat(chunks);
|
|
243
292
|
const response = await app.fetch(new Request(url, init));
|
|
@@ -260,6 +309,12 @@ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
|
|
|
260
309
|
});` : ""}
|
|
261
310
|
server.listen(port, () => console.log(\`oxidejs listening on \${port}\`));
|
|
262
311
|
}
|
|
312
|
+
for (const signal of ["SIGTERM", "SIGINT"]) {
|
|
313
|
+
process.on(signal, () => {
|
|
314
|
+
server.close(() => process.exit(0));
|
|
315
|
+
setTimeout(() => process.exit(0), 5000).unref();
|
|
316
|
+
});
|
|
317
|
+
}
|
|
263
318
|
` : "";
|
|
264
319
|
const actionImports = hasActions ? ws ? `import { handle as handleWs } from "tacho/transport/ws";
|
|
265
320
|
import actions from ${JSON.stringify(VIRTUAL_ACTIONS_ID)};
|
|
@@ -270,22 +325,26 @@ const __fetch = Symbol.for("oxidejs.fetch");
|
|
|
270
325
|
const __rpc = handle(actions, { path: ${JSON.stringify(actionPath)}${sameOrigin ? `, sameOrigin: true` : ``}, createContext: (req) => req[__fetch] ?? {} });
|
|
271
326
|
` : "";
|
|
272
327
|
const actionGate = hasActions && !ws ? `if (new URL(request.url).pathname === ${JSON.stringify(actionPath)}) {
|
|
273
|
-
request[__fetch] = { env, fetchCtx: ctx };
|
|
274
328
|
return __rpc(request);
|
|
275
329
|
}
|
|
276
330
|
` : "";
|
|
277
|
-
const
|
|
331
|
+
const ILHA_SSR_IMPLICIT = ["ilha:pages/server", "ilha:loaders"];
|
|
332
|
+
const middlewareImports = (opts.middleware ?? []).map((m) => typeof m === "string" ? {
|
|
333
|
+
module: m,
|
|
334
|
+
imports: m === "@ilha/router/ssr" ? ILHA_SSR_IMPLICIT : []
|
|
335
|
+
} : m).map((m, i) => (m.imports ?? []).map((spec) => `import ${JSON.stringify(spec)};`).join("\n") + `\nimport __mw${i} from ${JSON.stringify(m.module)};`).join("\n") + "\n";
|
|
278
336
|
const middlewareList = (opts.middleware ?? []).map((_, i) => `__mw${i}`).join(", ");
|
|
279
337
|
const middlewareGate = opts.middleware?.length ? `for (const __mw of [${middlewareList}]) {
|
|
280
338
|
const hit = await __mw(request, { env, ctx });
|
|
281
339
|
if (hit) return hit;
|
|
282
340
|
}
|
|
283
341
|
` : "";
|
|
284
|
-
return `export * from ${JSON.stringify(userWorkerAbs)};
|
|
342
|
+
return `${(opts.imports ?? []).map((spec) => `import ${JSON.stringify(spec)};`).join("\n")}export * from ${JSON.stringify(userWorkerAbs)};
|
|
285
343
|
import user from ${JSON.stringify(userWorkerAbs)};
|
|
286
|
-
${middlewareImports}${actionImports}${assetBlock}const app = {
|
|
344
|
+
${middlewareImports}${actionImports}${assetBlock}${nfBlock}const app = {
|
|
287
345
|
...user,
|
|
288
346
|
async fetch(request, env, ctx) {
|
|
347
|
+
request[__fetch] = { env, fetchCtx: ctx };
|
|
289
348
|
${middlewareGate}${actionGate}${afterAction}
|
|
290
349
|
},
|
|
291
350
|
};
|
|
@@ -470,7 +529,11 @@ function resolveOptions(raw, root, config) {
|
|
|
470
529
|
actionPath,
|
|
471
530
|
actionSameOrigin,
|
|
472
531
|
actionHeaders: raw?.actionHeaders,
|
|
473
|
-
middleware: raw?.middleware ?? []
|
|
532
|
+
middleware: raw?.middleware ?? [],
|
|
533
|
+
imports: raw?.imports ?? [],
|
|
534
|
+
bodyLimit: raw?.bodyLimit ?? 1048576,
|
|
535
|
+
notFound: raw?.notFound,
|
|
536
|
+
env: raw?.env
|
|
474
537
|
};
|
|
475
538
|
}
|
|
476
539
|
function copyPublicDir(opts) {
|
|
@@ -615,20 +678,21 @@ function applyRsbuildEnvironments(config, opts) {
|
|
|
615
678
|
//#endregion
|
|
616
679
|
//#region src/context.ts
|
|
617
680
|
const ALS_KEY = Symbol.for("oxidejs.requestContext");
|
|
681
|
+
const FETCH_KEY = Symbol.for("oxidejs.fetch");
|
|
618
682
|
function als() {
|
|
619
683
|
const g = globalThis;
|
|
620
684
|
return g[ALS_KEY] ??= new AsyncLocalStorage();
|
|
621
685
|
}
|
|
622
686
|
function store() {
|
|
623
687
|
const current = als().getStore();
|
|
624
|
-
if (!current) throw new Error("oxidejs:
|
|
688
|
+
if (!current) throw new Error("oxidejs: request context is unavailable");
|
|
625
689
|
return current;
|
|
626
690
|
}
|
|
627
|
-
/** Current tacho
|
|
691
|
+
/** Current tacho or host request context. Throws outside request handling. */
|
|
628
692
|
function useCtx() {
|
|
629
693
|
return store();
|
|
630
694
|
}
|
|
631
|
-
/** Current
|
|
695
|
+
/** Current server `Request`. Available in actions, SSR, and frame renders. */
|
|
632
696
|
function useRequest() {
|
|
633
697
|
return store().req;
|
|
634
698
|
}
|
|
@@ -640,10 +704,20 @@ function useEnv() {
|
|
|
640
704
|
function useFetchCtx() {
|
|
641
705
|
return store().fetchCtx;
|
|
642
706
|
}
|
|
707
|
+
function runWithRequest(req, fn, extra) {
|
|
708
|
+
return als().run({
|
|
709
|
+
...extra,
|
|
710
|
+
req
|
|
711
|
+
}, fn);
|
|
712
|
+
}
|
|
713
|
+
const HOOK_KEY = Symbol.for("oxidejs.runWithRequest");
|
|
714
|
+
globalThis[HOOK_KEY] ??= (req, fn) => {
|
|
715
|
+
const extra = req[FETCH_KEY];
|
|
716
|
+
return runWithRequest(req, fn, extra);
|
|
717
|
+
};
|
|
643
718
|
/**
|
|
644
|
-
* Marks a `*.server.ts` export as a remote RPC action.
|
|
645
|
-
*
|
|
646
|
-
* server-local. Wrap async functions and async generators.
|
|
719
|
+
* Marks a `*.server.ts` export as a remote RPC action. Runtime identity; the
|
|
720
|
+
* second call signature adds the transport-only `{ signal }` argument.
|
|
647
721
|
*/
|
|
648
722
|
function action(fn) {
|
|
649
723
|
return fn;
|
|
@@ -745,7 +819,11 @@ const unpluginFactory = (options) => {
|
|
|
745
819
|
actions: resolved.actions,
|
|
746
820
|
actionPath: resolved.actionPath,
|
|
747
821
|
actionSameOrigin: resolved.actionSameOrigin,
|
|
748
|
-
middleware: resolved.middleware
|
|
822
|
+
middleware: resolved.middleware,
|
|
823
|
+
imports: resolved.imports,
|
|
824
|
+
bodyLimit: resolved.bodyLimit,
|
|
825
|
+
notFound: resolved.notFound,
|
|
826
|
+
env: resolved.env
|
|
749
827
|
});
|
|
750
828
|
}
|
|
751
829
|
if (isServerFileId(id) && pluginShouldStub(this, extra)) {
|
|
@@ -779,6 +857,38 @@ const unpluginFactory = (options) => {
|
|
|
779
857
|
const loadRouter = async () => {
|
|
780
858
|
return (await server.ssrLoadModule(VIRTUAL_ACTIONS_ID)).default;
|
|
781
859
|
};
|
|
860
|
+
if ((resolved?.middleware?.length ?? 0) > 0 || (resolved?.imports?.length ?? 0) > 0) (async () => {
|
|
861
|
+
try {
|
|
862
|
+
for (const spec of resolved.imports ?? []) await server.ssrLoadModule(spec);
|
|
863
|
+
const handlers = [];
|
|
864
|
+
for (const entry of resolved.middleware ?? []) {
|
|
865
|
+
const spec2 = typeof entry === "string" ? entry : entry.module;
|
|
866
|
+
const mod = await server.ssrLoadModule(spec2);
|
|
867
|
+
if (typeof mod.default !== "function") continue;
|
|
868
|
+
const fn = mod.default;
|
|
869
|
+
handlers.push((request) => Promise.resolve(fn(request)));
|
|
870
|
+
}
|
|
871
|
+
if (handlers.length === 0) return;
|
|
872
|
+
const { nodeToWebRequest, sendWebResponseFrom } = await Promise.resolve().then(() => actions_exports);
|
|
873
|
+
server.middlewares.use((creq, cres, next) => {
|
|
874
|
+
(async () => {
|
|
875
|
+
try {
|
|
876
|
+
const request = await nodeToWebRequest(creq);
|
|
877
|
+
for (const handler of handlers) {
|
|
878
|
+
const hit = await handler(request);
|
|
879
|
+
if (hit) return sendWebResponseFrom(creq, cres, hit);
|
|
880
|
+
}
|
|
881
|
+
next();
|
|
882
|
+
} catch (error) {
|
|
883
|
+
cres.statusCode = 500;
|
|
884
|
+
cres.end(String(error));
|
|
885
|
+
}
|
|
886
|
+
})();
|
|
887
|
+
});
|
|
888
|
+
} catch (error) {
|
|
889
|
+
server.config.logger.error("oxidejs: failed to wire dev middleware: " + String(error));
|
|
890
|
+
}
|
|
891
|
+
})();
|
|
782
892
|
if (resolved?.actions === "ws") attachActionUpgrade(server.httpServer, loadRouter, resolved.actionPath, resolved.actionSameOrigin);
|
|
783
893
|
else server.middlewares.use(actionMiddleware(loadRouter, resolved.actionPath, resolved.actionSameOrigin));
|
|
784
894
|
},
|
|
@@ -40,7 +40,22 @@ interface OxidejsOptions {
|
|
|
40
40
|
/** Module specifiers whose default export is `(request, ctx) => Response | undefined | Promise<Response | undefined>`.
|
|
41
41
|
* Tried in order at the top of the production fetch handler; a Response short-circuits.
|
|
42
42
|
* Dev servers use connect middleware instead. */
|
|
43
|
-
middleware?: string
|
|
43
|
+
middleware?: (string | {
|
|
44
|
+
module: string;
|
|
45
|
+
imports?: string[];
|
|
46
|
+
})[];
|
|
47
|
+
/** Module specifiers imported for side effects at the top of the production
|
|
48
|
+
* server bundle (e.g. virtual modules that self-register handlers). */
|
|
49
|
+
imports?: string[];
|
|
50
|
+
/** Max request body size in bytes (Node preset). Larger requests get 413.
|
|
51
|
+
* Default: 1048576 (1 MiB). */
|
|
52
|
+
bodyLimit?: number;
|
|
53
|
+
/** Custom 404 body (HTML) served when no route, asset, or user fetch
|
|
54
|
+
* handled the request (fetch preset with client assets). */
|
|
55
|
+
notFound?: string;
|
|
56
|
+
/** Extra env passed as the second argument to fetch(request, env, ctx) on
|
|
57
|
+
* the Node fetch preset — read it with useEnv(). */
|
|
58
|
+
env?: Record<string, unknown>;
|
|
44
59
|
}
|
|
45
60
|
interface ResolvedOptions {
|
|
46
61
|
root: string;
|
|
@@ -63,7 +78,14 @@ interface ResolvedOptions {
|
|
|
63
78
|
/** Reject cross-origin action requests (CSRF defense). Default: true. */
|
|
64
79
|
actionSameOrigin: boolean;
|
|
65
80
|
actionHeaders: OxidejsActionHeaders | undefined;
|
|
66
|
-
middleware: string
|
|
81
|
+
middleware: (string | {
|
|
82
|
+
module: string;
|
|
83
|
+
imports?: string[];
|
|
84
|
+
})[];
|
|
85
|
+
imports: string[];
|
|
86
|
+
bodyLimit: number;
|
|
87
|
+
notFound: string | undefined;
|
|
88
|
+
env: Record<string, unknown> | undefined;
|
|
67
89
|
}
|
|
68
90
|
//#endregion
|
|
69
91
|
export { OxidejsWranglerOptions as a, OxidejsPreset as i, OxidejsActionTransport as n, ResolvedOptions as o, OxidejsOptions as r, OxidejsActionHeaders as t };
|
package/dist/vite.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as OxidejsOptions } from "./types-
|
|
1
|
+
import { r as OxidejsOptions } from "./types-BM4NAnzy.mjs";
|
|
2
2
|
//#region src/vite.d.ts
|
|
3
3
|
declare const _default: (options?: OxidejsOptions | undefined) => import("vite").Plugin<any> | import("vite").Plugin<any>[];
|
|
4
4
|
//#endregion
|
package/dist/vite.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxidejs",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Vite/Rsbuild plugin. One build → dist/server.js + optional client. Server actions via *.server.ts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"unplugin": "^3.3.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"tacho": "^0.
|
|
62
|
+
"tacho": "^0.5.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@rsbuild/core": "*",
|