oxidejs 0.2.0 → 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 CHANGED
@@ -76,15 +76,15 @@ export default {
76
76
  };
77
77
  ```
78
78
 
79
- `action()` is identity — it only marks the export. Wrap `async function*` in it to stream over tacho SSE. `oxidejs/tsconfig` makes `await ticks()` typecheck. Pass `{ signal }` last on any action to abort the fetch. Types come from the real `*.server.ts`, so declare the last argument there:
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, _opts?: ActionOptions) {
87
- for (let i = 0; i < n; i++) yield i;
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
package/dist/index.d.mts CHANGED
@@ -12,28 +12,25 @@ type ActionContext = {
12
12
  fetchCtx?: ExecutionContext;
13
13
  [key: string]: unknown;
14
14
  };
15
- /** Current tacho `ctx`. Throws outside `*.server.ts` running over `/__oxide/action`. */
15
+ /** Current tacho or host request context. Throws outside request handling. */
16
16
  declare function useCtx<C extends ActionContext = ActionContext>(): C;
17
- /** Current action `Request`. Throws outside `*.server.ts` running over `/__oxide/action`. */
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. Identity: returns `fn` unchanged.
29
- * Only exports wrapped in `action()` become callable over the wire; other exports stay
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<T>(fn: T): T;
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 ActionOptions, 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 };
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-zvdCGkyp.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-CsQ-6GnW.mjs";
2
2
  export { action, oxidejs as default, oxidejs, unpluginFactory, useCtx, useEnv, useFetchCtx, useRequest, vite };
package/dist/rsbuild.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./src-zvdCGkyp.mjs";
1
+ import { t as oxidejs } from "./src-CsQ-6GnW.mjs";
2
2
  //#region src/rsbuild.ts
3
3
  /** @experimental Rsbuild integration is not yet implemented. */
4
4
  var rsbuild_default = oxidejs.rsbuild;
@@ -210,7 +210,7 @@ function generateWorkerWrapper(userWorkerAbs, opts = {}) {
210
210
  const hasActions = opts.hasActions !== false;
211
211
  const ws = hasActions && opts.actions === "ws";
212
212
  const bodyLimit = opts.bodyLimit ?? 1048576;
213
- const __nf = `() => new Response(${JSON.stringify(opts.notFound ?? "<h1>404 Not Found</h1>")}, { status: 404, headers: { "content-type": "text/html; charset=utf-8" } })`;
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`;
214
214
  const assetBlock = serveAssets ? `import { readFile } from "node:fs/promises";
215
215
  import { extname, join } from "node:path";
216
216
  const __assets = join(import.meta.dirname, ${JSON.stringify(clientDir)});
@@ -253,7 +253,6 @@ async function __asset(request, spa) {
253
253
  return;
254
254
  }
255
255
  }
256
- const __nf = ${__nf};
257
256
  ` : "";
258
257
  const envJson = JSON.stringify(opts.env ?? {});
259
258
  const afterAction = serveAssets ? `if (typeof user.fetch === "function") {
@@ -326,7 +325,6 @@ const __fetch = Symbol.for("oxidejs.fetch");
326
325
  const __rpc = handle(actions, { path: ${JSON.stringify(actionPath)}${sameOrigin ? `, sameOrigin: true` : ``}, createContext: (req) => req[__fetch] ?? {} });
327
326
  ` : "";
328
327
  const actionGate = hasActions && !ws ? `if (new URL(request.url).pathname === ${JSON.stringify(actionPath)}) {
329
- request[__fetch] = { env, fetchCtx: ctx };
330
328
  return __rpc(request);
331
329
  }
332
330
  ` : "";
@@ -343,9 +341,10 @@ const __rpc = handle(actions, { path: ${JSON.stringify(actionPath)}${sameOrigin
343
341
  ` : "";
344
342
  return `${(opts.imports ?? []).map((spec) => `import ${JSON.stringify(spec)};`).join("\n")}export * from ${JSON.stringify(userWorkerAbs)};
345
343
  import user from ${JSON.stringify(userWorkerAbs)};
346
- ${middlewareImports}${actionImports}${assetBlock}const app = {
344
+ ${middlewareImports}${actionImports}${assetBlock}${nfBlock}const app = {
347
345
  ...user,
348
346
  async fetch(request, env, ctx) {
347
+ request[__fetch] = { env, fetchCtx: ctx };
349
348
  ${middlewareGate}${actionGate}${afterAction}
350
349
  },
351
350
  };
@@ -679,20 +678,21 @@ function applyRsbuildEnvironments(config, opts) {
679
678
  //#endregion
680
679
  //#region src/context.ts
681
680
  const ALS_KEY = Symbol.for("oxidejs.requestContext");
681
+ const FETCH_KEY = Symbol.for("oxidejs.fetch");
682
682
  function als() {
683
683
  const g = globalThis;
684
684
  return g[ALS_KEY] ??= new AsyncLocalStorage();
685
685
  }
686
686
  function store() {
687
687
  const current = als().getStore();
688
- if (!current) throw new Error("oxidejs: useRequest() called outside an action");
688
+ if (!current) throw new Error("oxidejs: request context is unavailable");
689
689
  return current;
690
690
  }
691
- /** Current tacho `ctx`. Throws outside `*.server.ts` running over `/__oxide/action`. */
691
+ /** Current tacho or host request context. Throws outside request handling. */
692
692
  function useCtx() {
693
693
  return store();
694
694
  }
695
- /** Current action `Request`. Throws outside `*.server.ts` running over `/__oxide/action`. */
695
+ /** Current server `Request`. Available in actions, SSR, and frame renders. */
696
696
  function useRequest() {
697
697
  return store().req;
698
698
  }
@@ -704,10 +704,20 @@ function useEnv() {
704
704
  function useFetchCtx() {
705
705
  return store().fetchCtx;
706
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
+ };
707
718
  /**
708
- * Marks a `*.server.ts` export as a remote RPC action. Identity: returns `fn` unchanged.
709
- * Only exports wrapped in `action()` become callable over the wire; other exports stay
710
- * 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.
711
721
  */
712
722
  function action(fn) {
713
723
  return fn;
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./src-zvdCGkyp.mjs";
1
+ import { t as oxidejs } from "./src-CsQ-6GnW.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.2.0",
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.4.3"
62
+ "tacho": "^0.5.0"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "@rsbuild/core": "*",