oxidejs 0.2.1 → 0.2.3
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 +11 -33
- package/dist/index.mjs +1 -1
- package/dist/rsbuild.mjs +1 -2
- package/dist/{src-CsQ-6GnW.mjs → src-D-qdNVqg.mjs} +55 -28
- package/dist/vite.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -113,27 +113,6 @@ 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
|
-
|
|
137
116
|
| Option | Default | Notes |
|
|
138
117
|
| ------------------------------ | ------------------------ | ------------------------------------------------------------------------------------------- |
|
|
139
118
|
| `preset` | `"fetch"` | `"fetch"` or `"celld"` |
|
|
@@ -150,23 +129,22 @@ Middleware handlers run in production before the action gate; the same specifier
|
|
|
150
129
|
| `emitConfig` | `true` on `celld` | Set `false` to skip `wrangler.jsonc` |
|
|
151
130
|
| `actions` | `"http"` | `"ws"` needs `crossws`; object form: `{ transport, path, sameOrigin }` (`sameOrigin: true`) |
|
|
152
131
|
| `actionHeaders` | — | Static headers on the HTTP client |
|
|
153
|
-
| `middleware` | `[]` |
|
|
132
|
+
| `middleware` | `[]` | Fetch middleware, run in order before actions and the server entry |
|
|
133
|
+
| `imports` | `[]` | Modules imported for side effects at server startup |
|
|
134
|
+
| `bodyLimit` | `1048576` | Max Node request body size; larger requests get 413 |
|
|
135
|
+
| `notFound` | — | Custom HTML 404 body when no route or asset matches |
|
|
136
|
+
| `env` | — | Node preset value passed to `fetch(request, env, ctx)` |
|
|
154
137
|
|
|
155
|
-
`middleware`
|
|
138
|
+
### `middleware` and `imports`
|
|
156
139
|
|
|
157
140
|
```ts
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// vite.config.ts
|
|
166
|
-
oxide({ middleware: ["./src/auth.ts"] });
|
|
141
|
+
oxide({
|
|
142
|
+
middleware: ["@ilha/router/ssr"], // string or { module, imports }
|
|
143
|
+
imports: ["./side-effects"],
|
|
144
|
+
});
|
|
167
145
|
```
|
|
168
146
|
|
|
169
|
-
|
|
147
|
+
Middleware modules receive `(request, { env, ctx })`. They run before actions, the server entry, and assets. Return a `Response` to stop the chain or `undefined` to continue. Vite loads the same modules through its SSR graph in development. Middleware entries may carry their own `imports`.
|
|
170
148
|
|
|
171
149
|
`main` is always `./server.js`. `assets` is added only when `index.html` exists. Unknown wrangler keys fail at build time.
|
|
172
150
|
|
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-D-qdNVqg.mjs";
|
|
2
2
|
export { action, oxidejs as default, oxidejs, unpluginFactory, useCtx, useEnv, useFetchCtx, useRequest, vite };
|
package/dist/rsbuild.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { t as oxidejs } from "./src-
|
|
1
|
+
import { t as oxidejs } from "./src-D-qdNVqg.mjs";
|
|
2
2
|
//#region src/rsbuild.ts
|
|
3
|
-
/** @experimental Rsbuild integration is not yet implemented. */
|
|
4
3
|
var rsbuild_default = oxidejs.rsbuild;
|
|
5
4
|
//#endregion
|
|
6
5
|
export { rsbuild_default as default };
|
|
@@ -21,6 +21,7 @@ var actions_exports = /* @__PURE__ */ __exportAll({
|
|
|
21
21
|
RESOLVED_VIRTUAL_ACTIONS_ID: () => RESOLVED_VIRTUAL_ACTIONS_ID,
|
|
22
22
|
RESOLVED_VIRTUAL_CLIENT_ID: () => RESOLVED_VIRTUAL_CLIENT_ID,
|
|
23
23
|
RESOLVED_VIRTUAL_WORKER_ID: () => RESOLVED_VIRTUAL_WORKER_ID,
|
|
24
|
+
RequestBodyTooLargeError: () => RequestBodyTooLargeError,
|
|
24
25
|
VIRTUAL_ACTIONS_ID: () => VIRTUAL_ACTIONS_ID,
|
|
25
26
|
VIRTUAL_CLIENT_ID: () => VIRTUAL_CLIENT_ID,
|
|
26
27
|
VIRTUAL_WORKER_ID: () => VIRTUAL_WORKER_ID,
|
|
@@ -399,7 +400,8 @@ function loadClientStub(id) {
|
|
|
399
400
|
exports: parseExportedNames(fs.readFileSync(file, "utf8"))
|
|
400
401
|
});
|
|
401
402
|
}
|
|
402
|
-
|
|
403
|
+
var RequestBodyTooLargeError = class extends Error {};
|
|
404
|
+
async function nodeToWebRequest(req, maxBytes = Number.POSITIVE_INFINITY) {
|
|
403
405
|
const url = `http://${req.headers.host ?? "localhost"}${req.url ?? "/"}`;
|
|
404
406
|
const headers = new Headers();
|
|
405
407
|
for (const [key, value] of Object.entries(req.headers)) {
|
|
@@ -417,7 +419,13 @@ async function nodeToWebRequest(req) {
|
|
|
417
419
|
};
|
|
418
420
|
if (method === "GET" || method === "HEAD") return new Request(url, init);
|
|
419
421
|
const chunks = [];
|
|
420
|
-
|
|
422
|
+
let size = 0;
|
|
423
|
+
for await (const chunk of req) {
|
|
424
|
+
const buffer = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
425
|
+
size += buffer.length;
|
|
426
|
+
if (size > maxBytes) throw new RequestBodyTooLargeError();
|
|
427
|
+
chunks.push(buffer);
|
|
428
|
+
}
|
|
421
429
|
const body = Buffer.concat(chunks);
|
|
422
430
|
if (body.length > 0) init.body = body;
|
|
423
431
|
return new Request(url, init);
|
|
@@ -724,7 +732,7 @@ function action(fn) {
|
|
|
724
732
|
}
|
|
725
733
|
//#endregion
|
|
726
734
|
//#region src/index.ts
|
|
727
|
-
function actionMiddleware(loadRouter, path, sameOrigin) {
|
|
735
|
+
function actionMiddleware(loadRouter, path, sameOrigin, bodyLimit) {
|
|
728
736
|
return (req, res, next) => {
|
|
729
737
|
if ((req.url ?? "").split("?")[0] !== path) {
|
|
730
738
|
next();
|
|
@@ -738,8 +746,13 @@ function actionMiddleware(loadRouter, path, sameOrigin) {
|
|
|
738
746
|
await sendWebResponseFrom(req, res, await handle(await loadRouter(), {
|
|
739
747
|
path,
|
|
740
748
|
...sameOrigin ? { sameOrigin: true } : {}
|
|
741
|
-
})(await nodeToWebRequest(req)));
|
|
742
|
-
})().catch(
|
|
749
|
+
})(await nodeToWebRequest(req, bodyLimit)));
|
|
750
|
+
})().catch((error) => {
|
|
751
|
+
if (error instanceof RequestBodyTooLargeError) {
|
|
752
|
+
res.statusCode = 413;
|
|
753
|
+
res.end();
|
|
754
|
+
} else next(error);
|
|
755
|
+
});
|
|
743
756
|
};
|
|
744
757
|
}
|
|
745
758
|
function attachActionUpgrade(httpServer, loadRouter, path, sameOrigin) {
|
|
@@ -857,40 +870,54 @@ const unpluginFactory = (options) => {
|
|
|
857
870
|
const loadRouter = async () => {
|
|
858
871
|
return (await server.ssrLoadModule(VIRTUAL_ACTIONS_ID)).default;
|
|
859
872
|
};
|
|
860
|
-
|
|
873
|
+
const wireActions = () => server.middlewares.use(actionMiddleware(loadRouter, resolved.actionPath, resolved.actionSameOrigin, resolved.bodyLimit));
|
|
874
|
+
if (resolved?.actions === "ws") {
|
|
875
|
+
attachActionUpgrade(server.httpServer, loadRouter, resolved.actionPath, resolved.actionSameOrigin);
|
|
876
|
+
return;
|
|
877
|
+
}
|
|
878
|
+
if ((resolved?.middleware?.length ?? 0) === 0 && (resolved?.imports?.length ?? 0) === 0) {
|
|
879
|
+
wireActions();
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
(async () => {
|
|
861
883
|
try {
|
|
862
884
|
for (const spec of resolved.imports ?? []) await server.ssrLoadModule(spec);
|
|
863
885
|
const handlers = [];
|
|
864
886
|
for (const entry of resolved.middleware ?? []) {
|
|
865
|
-
const
|
|
866
|
-
const mod = await server.ssrLoadModule(
|
|
887
|
+
const spec = typeof entry === "string" ? entry : entry.module;
|
|
888
|
+
const mod = await server.ssrLoadModule(spec);
|
|
867
889
|
if (typeof mod.default !== "function") continue;
|
|
868
890
|
const fn = mod.default;
|
|
869
|
-
handlers.push((request) => Promise.resolve(fn(request)));
|
|
891
|
+
handlers.push((request, context) => Promise.resolve(fn(request, context)));
|
|
870
892
|
}
|
|
871
|
-
if (handlers.length
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
893
|
+
if (handlers.length > 0) {
|
|
894
|
+
const { nodeToWebRequest, sendWebResponseFrom } = await Promise.resolve().then(() => actions_exports);
|
|
895
|
+
server.middlewares.use((creq, cres, next) => {
|
|
896
|
+
(async () => {
|
|
897
|
+
try {
|
|
898
|
+
const request = await nodeToWebRequest(creq, resolved.bodyLimit);
|
|
899
|
+
const context = {
|
|
900
|
+
env: resolved.env,
|
|
901
|
+
ctx: void 0
|
|
902
|
+
};
|
|
903
|
+
for (const handler of handlers) {
|
|
904
|
+
const hit = await handler(request, context);
|
|
905
|
+
if (hit) return sendWebResponseFrom(creq, cres, hit);
|
|
906
|
+
}
|
|
907
|
+
next();
|
|
908
|
+
} catch (error) {
|
|
909
|
+
cres.statusCode = error instanceof RequestBodyTooLargeError ? 413 : 500;
|
|
910
|
+
cres.end(error instanceof RequestBodyTooLargeError ? void 0 : String(error));
|
|
880
911
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
cres.end(String(error));
|
|
885
|
-
}
|
|
886
|
-
})();
|
|
887
|
-
});
|
|
912
|
+
})();
|
|
913
|
+
});
|
|
914
|
+
}
|
|
888
915
|
} catch (error) {
|
|
889
916
|
server.config.logger.error("oxidejs: failed to wire dev middleware: " + String(error));
|
|
917
|
+
} finally {
|
|
918
|
+
wireActions();
|
|
890
919
|
}
|
|
891
920
|
})();
|
|
892
|
-
if (resolved?.actions === "ws") attachActionUpgrade(server.httpServer, loadRouter, resolved.actionPath, resolved.actionSameOrigin);
|
|
893
|
-
else server.middlewares.use(actionMiddleware(loadRouter, resolved.actionPath, resolved.actionSameOrigin));
|
|
894
921
|
},
|
|
895
922
|
configurePreviewServer(server) {
|
|
896
923
|
if (resolved?.preset !== "fetch") return;
|
|
@@ -907,7 +934,7 @@ const unpluginFactory = (options) => {
|
|
|
907
934
|
return (await loadActions(resolved?.root ?? process.cwd())).default;
|
|
908
935
|
};
|
|
909
936
|
if (resolved?.actions === "ws") attachActionUpgrade(server.httpServer, loadRouter, resolved.actionPath, resolved.actionSameOrigin);
|
|
910
|
-
else server.middlewares.use(actionMiddleware(loadRouter, resolved.actionPath, resolved.actionSameOrigin));
|
|
937
|
+
else server.middlewares.use(actionMiddleware(loadRouter, resolved.actionPath, resolved.actionSameOrigin, resolved.bodyLimit));
|
|
911
938
|
});
|
|
912
939
|
api.onBeforeStartPreviewServer?.(({ server }) => {
|
|
913
940
|
if (resolved?.preset !== "fetch") return;
|
package/dist/vite.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxidejs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
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.6.1"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@rsbuild/core": "*",
|