oxidejs 0.1.8 → 0.1.10

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 CHANGED
@@ -95,7 +95,7 @@ const stream = await ticks(10, { signal: ac.signal });
95
95
  ac.abort();
96
96
  ```
97
97
 
98
- `vite dev` and `rsbuild dev` serve the endpoint via middleware. `actions: "http"` (default) serves `/__oxide/action`; `actions: "ws"` uses a WebSocket instead (needs `crossws`; not with `preset: "celld"`). `actions.sameOrigin` defaults to `true` for both transports; set it to `false` only when you intentionally accept cross-origin requests. Set `actions.path` to move the endpoint. `actionHeaders` are static headers on the shared HTTP client.
98
+ `vite dev` and `rsbuild dev` serve the endpoint via middleware. `actions: "http"` (default) serves `/__oxide/action`; `actions: "ws"` uses a WebSocket instead (needs `crossws`; not with `preset: "celld"`). `actions.sameOrigin` defaults to `true` for both transports; set it to `false` only when you intentionally accept cross-origin requests. Set `actions.path` to move the endpoint. `actionHeaders` are static headers on the shared HTTP client and are ignored for WebSocket actions.
99
99
 
100
100
  ## Rsbuild
101
101
 
@@ -129,6 +129,23 @@ Same factory as Vite: client stubs, `/__oxide/action`, and `dist/server.js`.
129
129
  | `emitConfig` | `true` on `celld` | Set `false` to skip `wrangler.jsonc` |
130
130
  | `actions` | `"http"` | `"ws"` needs `crossws`; object form: `{ transport, path, sameOrigin }` (`sameOrigin: true`) |
131
131
  | `actionHeaders` | — | Static headers on the HTTP client |
132
+ | `middleware` | `[]` | Default-exported production fetch middleware, run in order before actions and server entry |
133
+
134
+ `middleware` modules receive `(request, { env, ctx })`. They run in array order before actions, the server entry, and assets. Return a `Response` to stop the chain or `undefined` to continue.
135
+
136
+ ```ts
137
+ // src/auth.ts
138
+ export default function auth(request: Request) {
139
+ if (!request.headers.has("authorization")) {
140
+ return new Response("Unauthorized", { status: 401 });
141
+ }
142
+ }
143
+
144
+ // vite.config.ts
145
+ oxide({ middleware: ["./src/auth.ts"] });
146
+ ```
147
+
148
+ This option applies to production builds; use Connect middleware in Vite or Rsbuild during development.
132
149
 
133
150
  `main` is always `./server.js`. `assets` is added only when `index.html` exists. Unknown wrangler keys fail at build time.
134
151
 
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-C3ualQ39.mjs";
1
+ import { a as OxidejsWranglerOptions, i as OxidejsPreset, n as OxidejsActionTransport, o as ResolvedOptions, r as OxidejsOptions, t as OxidejsActionHeaders } from "./types-CMEB9B4S.mjs";
2
2
  import { UnpluginFactory } from "unplugin";
3
3
  //#region src/context.d.ts
4
4
  type ExecutionContext = {
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-Cg_j9ZsH.mjs";
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-CkhMD9M5.mjs";
2
2
  export { action, oxidejs as default, oxidejs, unpluginFactory, useCtx, useEnv, useFetchCtx, useRequest, vite };
@@ -1,4 +1,4 @@
1
- import { r as OxidejsOptions } from "./types-C3ualQ39.mjs";
1
+ import { r as OxidejsOptions } from "./types-CMEB9B4S.mjs";
2
2
  //#region src/rsbuild.d.ts
3
3
  declare const _default: (options?: OxidejsOptions | undefined) => any;
4
4
  //#endregion
package/dist/rsbuild.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./src-Cg_j9ZsH.mjs";
1
+ import { t as oxidejs } from "./src-CkhMD9M5.mjs";
2
2
  //#region src/rsbuild.ts
3
3
  var rsbuild_default = oxidejs.rsbuild;
4
4
  //#endregion
@@ -89,7 +89,7 @@ export const client = createClient(${JSON.stringify(opts)});
89
89
  `;
90
90
  }
91
91
  function generateClientStub(mod) {
92
- const lines = [`import { client } from ${JSON.stringify(VIRTUAL_CLIENT_ID)};`];
92
+ const lines = [`// oxidejs:client-stub`, `import { client } from ${JSON.stringify(VIRTUAL_CLIENT_ID)};`];
93
93
  for (const name of mod.exports) lines.push(`export const ${name} = (...args) => {
94
94
  const opts = args.at(-1);
95
95
  // ponytail: peel last { signal } only. A lone payload { signal: AbortSignal } is treated as CallOptions.
@@ -273,13 +273,20 @@ const __rpc = handle(actions, { path: ${JSON.stringify(actionPath)}${sameOrigin
273
273
  request[__fetch] = { env, fetchCtx: ctx };
274
274
  return __rpc(request);
275
275
  }
276
+ ` : "";
277
+ const middlewareImports = (opts.middleware ?? []).map((spec, i) => `import __mw${i} from ${JSON.stringify(spec)};`).join("\n");
278
+ const middlewareList = (opts.middleware ?? []).map((_, i) => `__mw${i}`).join(", ");
279
+ const middlewareGate = opts.middleware?.length ? `for (const __mw of [${middlewareList}]) {
280
+ const hit = await __mw(request, { env, ctx });
281
+ if (hit) return hit;
282
+ }
276
283
  ` : "";
277
284
  return `export * from ${JSON.stringify(userWorkerAbs)};
278
285
  import user from ${JSON.stringify(userWorkerAbs)};
279
- ${actionImports}${assetBlock}const app = {
286
+ ${middlewareImports}${actionImports}${assetBlock}const app = {
280
287
  ...user,
281
288
  async fetch(request, env, ctx) {
282
- ${actionGate}${afterAction}
289
+ ${middlewareGate}${actionGate}${afterAction}
283
290
  },
284
291
  };
285
292
  export default app;
@@ -462,7 +469,8 @@ function resolveOptions(raw, root, config) {
462
469
  actions,
463
470
  actionPath,
464
471
  actionSameOrigin,
465
- actionHeaders: raw?.actionHeaders
472
+ actionHeaders: raw?.actionHeaders,
473
+ middleware: raw?.middleware ?? []
466
474
  };
467
475
  }
468
476
  function copyPublicDir(opts) {
@@ -736,7 +744,8 @@ const unpluginFactory = (options) => {
736
744
  hasActions: modules.length > 0,
737
745
  actions: resolved.actions,
738
746
  actionPath: resolved.actionPath,
739
- actionSameOrigin: resolved.actionSameOrigin
747
+ actionSameOrigin: resolved.actionSameOrigin,
748
+ middleware: resolved.middleware
740
749
  });
741
750
  }
742
751
  if (isServerFileId(id) && pluginShouldStub(this, extra)) {
@@ -746,7 +755,7 @@ const unpluginFactory = (options) => {
746
755
  }
747
756
  },
748
757
  transform(code, id, extra) {
749
- if (!isServerFileId(id) || !pluginShouldStub(this, extra)) return;
758
+ if (!isServerFileId(id) || !pluginShouldStub(this, extra) || code.startsWith("// oxidejs:client-stub\n")) return;
750
759
  return generateClientStub({
751
760
  key: moduleKey(id.split("?")[0] ?? id),
752
761
  exports: parseExportedNames(code)
@@ -37,6 +37,10 @@ interface OxidejsOptions {
37
37
  actions?: OxidejsActions;
38
38
  /** Extra headers on the shared HTTP action client. Ignored when `actions` is "ws". */
39
39
  actionHeaders?: OxidejsActionHeaders;
40
+ /** Module specifiers whose default export is `(request, ctx) => Response | undefined | Promise<Response | undefined>`.
41
+ * Tried in order at the top of the production fetch handler; a Response short-circuits.
42
+ * Dev servers use connect middleware instead. */
43
+ middleware?: string[];
40
44
  }
41
45
  interface ResolvedOptions {
42
46
  root: string;
@@ -59,6 +63,7 @@ interface ResolvedOptions {
59
63
  /** Reject cross-origin action requests (CSRF defense). Default: true. */
60
64
  actionSameOrigin: boolean;
61
65
  actionHeaders: OxidejsActionHeaders | undefined;
66
+ middleware: string[];
62
67
  }
63
68
  //#endregion
64
69
  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-C3ualQ39.mjs";
1
+ import { r as OxidejsOptions } from "./types-CMEB9B4S.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
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./src-Cg_j9ZsH.mjs";
1
+ import { t as oxidejs } from "./src-CkhMD9M5.mjs";
2
2
  //#region src/vite.ts
3
3
  var vite_default = oxidejs.vite;
4
4
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxidejs",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Vite/Rsbuild plugin. One build → dist/server.js + optional client. Server actions via *.server.ts.",
5
5
  "keywords": [
6
6
  "cloudflare",