oxidejs 0.3.1 → 0.3.2

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
@@ -201,6 +201,7 @@ The generated `__asset` function uses `path.join` — not `path.resolve` — so
201
201
  - Batch requests capped at 20 items (both HTTP and WebSocket transports).
202
202
  - Effect `Defect` / `Cause` payloads are scrubbed before they leave the endpoint. Clients see plain JSON-RPC errors (`code` + `message` only). Thrown messages become `Internal error` (`-32603`). Unknown methods → `-32601`; invalid params → `-32602`.
203
203
  - `actions.sameOrigin` defaults to `true`. Requests without both `Origin` and `Sec-Fetch-Site` are rejected when that check is on.
204
+ - StackBlitz WebContainers do not keep `AsyncLocalStorage` across `async/await`. Oxide detects `process.versions.webcontainer` and falls back to a sync request store, capturing context before Effect schedules work and serializing handler entry so concurrent requests do not stomp that store. Stream pulls re-enter the captured store. This is a demo/dev workaround, not a concurrency model for production.
204
205
 
205
206
  ### Host header
206
207
 
@@ -1,3 +1,4 @@
1
+ import { n as inWebcontainer } from "./context-DQDDwFYi.mjs";
1
2
  import { Effect, Layer, Scope, Stream } from "effect";
2
3
  import { RpcClient, RpcSchema, RpcSerialization } from "effect/unstable/rpc";
3
4
  import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
@@ -6,20 +7,37 @@ import { Socket } from "effect/unstable/socket";
6
7
  function asyncGenToStream(gen) {
7
8
  return Stream.fromAsyncIterable(gen, (error) => error instanceof Error ? error : new Error(String(error)));
8
9
  }
10
+ /** Serialize WebContainer stream pulls so the shared syncStore is not stomped. */
11
+ let pullTail = Promise.resolve();
9
12
  /**
10
- * Re-enter `run` for every generator pull so AsyncLocalStorage request context
11
- * stays available across yields (Effect may drain the stream after the outer ALS scope ends).
13
+ * Re-enter `run` for every generator pull so request context stays available
14
+ * across yields (Effect may drain the stream after the outer ALS scope ends;
15
+ * WebContainer also loses ALS across awaits, so `run` must reinstall the store).
16
+ * On WebContainer, pulls are serialized through settlement so concurrent streams
17
+ * cannot replace the sync fallback mid-pull. `withRequestEntry` is unchanged.
12
18
  */
13
19
  function bindAsyncGenContext(gen, run) {
20
+ const runPull = (fn) => {
21
+ if (!inWebcontainer()) return run(fn);
22
+ let release;
23
+ const gate = new Promise((resolve) => {
24
+ release = resolve;
25
+ });
26
+ const prev = pullTail;
27
+ pullTail = gate;
28
+ return prev.then(() => Promise.resolve(run(fn))).finally(() => {
29
+ release();
30
+ });
31
+ };
14
32
  return {
15
- next: (value) => run(() => gen.next(value)),
16
- return: (value) => run(() => gen.return(value)),
17
- throw: (error) => run(() => gen.throw(error)),
33
+ next: (value) => runPull(() => gen.next(value)),
34
+ return: (value) => runPull(() => gen.return(value)),
35
+ throw: (error) => runPull(() => gen.throw(error)),
18
36
  [Symbol.asyncIterator]() {
19
37
  return this;
20
38
  },
21
39
  async [Symbol.asyncDispose]() {
22
- await run(() => gen.return(void 0));
40
+ await runPull(() => gen.return(void 0));
23
41
  }
24
42
  };
25
43
  }
@@ -52,6 +52,15 @@ type ActionContext = {
52
52
  fetchCtx?: ExecutionContext;
53
53
  [key: string]: unknown;
54
54
  };
55
+ /** Current request context: ALS first, then the WebContainer sync fallback. */
56
+ declare function getRequestStore(): ActionContext;
57
+ /**
58
+ * Run `fn` with `store` on ALS and the sync fallback. On WebContainer the sync
59
+ * slot is restored only after an async `fn` settles (streams capture the store
60
+ * at invoke time and re-enter via this helper on each pull). Sync returns and
61
+ * throws restore immediately so a completed request is not left visible.
62
+ */
63
+ declare function withRequestStore<T>(ctx: ActionContext, fn: () => T): T;
55
64
  /** Current RPC or host request context. Throws outside request handling. */
56
65
  declare function useCtx<C extends ActionContext = ActionContext>(): C;
57
66
  /** Current server `Request`. Available in actions, SSR, and frame renders. */
@@ -61,4 +70,4 @@ declare function useEnv<E = unknown>(): E | undefined;
61
70
  /** Worker `ctx` from `fetch(request, env, ctx)` (`waitUntil`). `undefined` on Node. */
62
71
  declare function useFetchCtx(): ExecutionContext | undefined;
63
72
  //#endregion
64
- export { useFetchCtx as a, ServerActionHandle as c, brandServerAction as d, wrapClientRpc as f, useEnv as i, StreamActionHandle as l, ExecutionContext as n, useRequest as o, wrapClientStreamRpc as p, useCtx as r, ACTION_CALL as s, ActionContext as t, action as u };
73
+ export { useEnv as a, withRequestStore as c, StreamActionHandle as d, action as f, wrapClientStreamRpc as h, useCtx as i, ACTION_CALL as l, wrapClientRpc as m, ExecutionContext as n, useFetchCtx as o, brandServerAction as p, getRequestStore as r, useRequest as s, ActionContext as t, ServerActionHandle as u };
@@ -0,0 +1,100 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import process from "node:process";
3
+ //#region src/context.ts
4
+ const ALS_KEY = Symbol.for("oxidejs.requestContext");
5
+ const FETCH_KEY = Symbol.for("oxidejs.fetch");
6
+ /** StackBlitz WebContainers lose AsyncLocalStorage across `async/await`. */
7
+ const inWebcontainer = () => {
8
+ if (typeof process === "undefined") return false;
9
+ const versions = process.versions;
10
+ return Boolean(versions.webcontainer);
11
+ };
12
+ /** Module fallback when ALS does not survive awaits (WebContainer). */
13
+ let syncStore = null;
14
+ /** Serialize handler *entry* on WebContainer so syncStore is not stomped. */
15
+ let entryTail = Promise.resolve();
16
+ function als() {
17
+ const g = globalThis;
18
+ return g[ALS_KEY] ??= new AsyncLocalStorage();
19
+ }
20
+ const isPromiseLike = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
21
+ /** Current request context: ALS first, then the WebContainer sync fallback. */
22
+ function getRequestStore() {
23
+ const current = als().getStore() ?? syncStore;
24
+ if (!current) throw new Error("oxidejs: request context is unavailable");
25
+ return current;
26
+ }
27
+ function store() {
28
+ return getRequestStore();
29
+ }
30
+ /**
31
+ * Run `fn` with `store` on ALS and the sync fallback. On WebContainer the sync
32
+ * slot is restored only after an async `fn` settles (streams capture the store
33
+ * at invoke time and re-enter via this helper on each pull). Sync returns and
34
+ * throws restore immediately so a completed request is not left visible.
35
+ */
36
+ function withRequestStore(ctx, fn) {
37
+ const previous = syncStore;
38
+ syncStore = ctx;
39
+ let deferRestore = false;
40
+ try {
41
+ const result = als().run(ctx, fn);
42
+ if (inWebcontainer() && isPromiseLike(result)) {
43
+ deferRestore = true;
44
+ return Promise.resolve(result).finally(() => {
45
+ if (syncStore === ctx) syncStore = previous;
46
+ });
47
+ }
48
+ return result;
49
+ } finally {
50
+ if (!deferRestore) syncStore = previous;
51
+ }
52
+ }
53
+ /**
54
+ * Serialize async work that installs request context on WebContainer.
55
+ * Release as soon as `fn` settles — do not wait for streamed response bodies.
56
+ */
57
+ async function withRequestEntry(fn) {
58
+ if (!inWebcontainer()) return fn();
59
+ let release;
60
+ const gate = new Promise((resolve) => {
61
+ release = resolve;
62
+ });
63
+ const previous = entryTail;
64
+ entryTail = gate;
65
+ await previous;
66
+ try {
67
+ return await fn();
68
+ } finally {
69
+ release();
70
+ }
71
+ }
72
+ /** Current RPC or host request context. Throws outside request handling. */
73
+ function useCtx() {
74
+ return store();
75
+ }
76
+ /** Current server `Request`. Available in actions, SSR, and frame renders. */
77
+ function useRequest() {
78
+ return store().req;
79
+ }
80
+ /** Worker `env` from `fetch(request, env, ctx)`. `undefined` on the Node fetch preset. */
81
+ function useEnv() {
82
+ return store().env;
83
+ }
84
+ /** Worker `ctx` from `fetch(request, env, ctx)` (`waitUntil`). `undefined` on Node. */
85
+ function useFetchCtx() {
86
+ return store().fetchCtx;
87
+ }
88
+ function runWithRequest(req, fn, extra) {
89
+ return withRequestStore({
90
+ ...extra,
91
+ req
92
+ }, fn);
93
+ }
94
+ const HOOK_KEY = Symbol.for("oxidejs.runWithRequest");
95
+ globalThis[HOOK_KEY] ??= (req, fn) => {
96
+ const extra = req[FETCH_KEY];
97
+ return runWithRequest(req, fn, extra);
98
+ };
99
+ //#endregion
100
+ export { useEnv as a, withRequestEntry as c, useCtx as i, withRequestStore as l, inWebcontainer as n, useFetchCtx as o, runWithRequest as r, useRequest as s, getRequestStore as t };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { a as useFetchCtx, c as ServerActionHandle, d as brandServerAction, f as wrapClientRpc, i as useEnv, l as StreamActionHandle, n as ExecutionContext, o as useRequest, p as wrapClientStreamRpc, r as useCtx, s as ACTION_CALL, t as ActionContext, u as action } from "./context-C1UFQ0Zc.mjs";
1
+ import { a as useEnv, c as withRequestStore, d as StreamActionHandle, f as action, h as wrapClientStreamRpc, i as useCtx, l as ACTION_CALL, m as wrapClientRpc, n as ExecutionContext, o as useFetchCtx, p as brandServerAction, r as getRequestStore, s as useRequest, t as ActionContext, u as ServerActionHandle } from "./context-Ct8u5XUC.mjs";
2
2
  import { a as OxidejsWranglerOptions, i as OxidejsPreset, n as OxidejsActionTransport, o as ResolvedOptions, r as OxidejsOptions, t as OxidejsActionHeaders } from "./types-BM4NAnzy.mjs";
3
- export { ACTION_CALL, type ActionContext, type ExecutionContext, type OxidejsActionHeaders, type OxidejsActionTransport, type OxidejsOptions, type OxidejsPreset, type OxidejsWranglerOptions, type ResolvedOptions, type ServerActionHandle, type StreamActionHandle, action, brandServerAction, useCtx, useEnv, useFetchCtx, useRequest, wrapClientRpc, wrapClientStreamRpc };
3
+ export { ACTION_CALL, type ActionContext, type ExecutionContext, type OxidejsActionHeaders, type OxidejsActionTransport, type OxidejsOptions, type OxidejsPreset, type OxidejsWranglerOptions, type ResolvedOptions, type ServerActionHandle, type StreamActionHandle, action, brandServerAction, getRequestStore, useCtx, useEnv, useFetchCtx, useRequest, withRequestStore, wrapClientRpc, wrapClientStreamRpc };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as useRequest, i as useFetchCtx, n as useCtx, r as useEnv } from "./context-zrTZyYpF.mjs";
1
+ import { a as useEnv, i as useCtx, l as withRequestStore, o as useFetchCtx, s as useRequest, t as getRequestStore } from "./context-DQDDwFYi.mjs";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Atom from "effect/unstable/reactivity/Atom";
4
4
  import * as Registry from "effect/unstable/reactivity/AtomRegistry";
@@ -105,4 +105,4 @@ function action(fn) {
105
105
  }))), invoke);
106
106
  }
107
107
  //#endregion
108
- export { ACTION_CALL, action, brandServerAction, useCtx, useEnv, useFetchCtx, useRequest, wrapClientRpc, wrapClientStreamRpc };
108
+ export { ACTION_CALL, action, brandServerAction, getRequestStore, useCtx, useEnv, useFetchCtx, useRequest, withRequestStore, wrapClientRpc, wrapClientStreamRpc };
@@ -1,4 +1,4 @@
1
- import { A as pluginShouldStub, C as isServerFileId, D as nodeToWebRequest, E as moduleKey, M as sendWebResponseFrom, O as parseExportedNames, S as generateWorkerWrapper, T as matchesActionPath, b as generateClientModule, d as RESOLVED_VIRTUAL_CLIENT_ID, f as RESOLVED_VIRTUAL_WORKER_ID, g as VIRTUAL_WORKER_ID, j as scanServerFiles, k as parseStreamExports, l as ACTION_PATH, m as VIRTUAL_ACTIONS_ID, n as createActionHandler, p as RequestBodyTooLargeError, t as createWsHooks, u as RESOLVED_VIRTUAL_ACTIONS_ID, v as generateActionsClientModule, w as loadClientStub, x as generateClientStub, y as generateActionsModule } from "./rpc-DzUkWWgQ.mjs";
1
+ import { A as pluginShouldStub, C as isServerFileId, D as nodeToWebRequest, E as moduleKey, M as sendWebResponseFrom, O as parseExportedNames, S as generateWorkerWrapper, T as matchesActionPath, b as generateClientModule, d as RESOLVED_VIRTUAL_CLIENT_ID, f as RESOLVED_VIRTUAL_WORKER_ID, g as VIRTUAL_WORKER_ID, j as scanServerFiles, k as parseStreamExports, l as ACTION_PATH, m as VIRTUAL_ACTIONS_ID, n as createActionHandler, p as RequestBodyTooLargeError, t as createWsHooks, u as RESOLVED_VIRTUAL_ACTIONS_ID, v as generateActionsClientModule, w as loadClientStub, x as generateClientStub, y as generateActionsModule } from "./rpc-tYqxQToi.mjs";
2
2
  import { ensureWorkerDom } from "./worker-dom.mjs";
3
3
  import { createUnplugin } from "unplugin";
4
4
  import fs from "node:fs";
@@ -531,7 +531,7 @@ const unpluginFactory = (options) => {
531
531
  next();
532
532
  return;
533
533
  }
534
- const { nodeToWebRequest, sendWebResponseFrom } = await import("./rpc-DzUkWWgQ.mjs").then((n) => n._);
534
+ const { nodeToWebRequest, sendWebResponseFrom } = await import("./rpc-tYqxQToi.mjs").then((n) => n._);
535
535
  const request = await nodeToWebRequest(creq, resolved.bodyLimit);
536
536
  const context = {
537
537
  env: resolved.env,
package/dist/plugin.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as unpluginFactory, r as vite, t as oxidejs } from "./plugin-HZKRDuCS.mjs";
1
+ import { n as unpluginFactory, r as vite, t as oxidejs } from "./plugin-CurpVnGn.mjs";
2
2
  export { oxidejs as default, oxidejs, unpluginFactory, vite };
@@ -1,2 +1,2 @@
1
- import { t as createClient } from "../client-C-s6XXpS.mjs";
1
+ import { t as createClient } from "../client-BgBfkZDx.mjs";
2
2
  export { createClient };
@@ -1,4 +1,4 @@
1
- import { t as runWithRequest } from "./context-zrTZyYpF.mjs";
1
+ import { c as withRequestEntry, r as runWithRequest } from "./context-DQDDwFYi.mjs";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { Layer } from "effect";
@@ -188,17 +188,11 @@ function generateActionsModule(modules, opts) {
188
188
  `import { Effect } from "effect";`,
189
189
  `import { Schema } from "effect";`,
190
190
  `import { Rpc, RpcGroup } from "effect/unstable/rpc";`,
191
- `import { AsyncLocalStorage } from "node:async_hooks";`,
191
+ `import { getRequestStore, withRequestStore } from "oxidejs";`,
192
192
  `import { asyncGenToStreamInContext } from "oxidejs/rpc";`,
193
- `const __alsKey = Symbol.for("oxidejs.requestContext");`,
194
- `const __als = globalThis[__alsKey] ??= new AsyncLocalStorage();`,
195
- `const __store = () => {`,
196
- ` const ctx = __als.getStore();`,
197
- ` if (!ctx) throw new Error("oxidejs: request context is unavailable");`,
198
- ` return ctx;`,
199
- `};`,
200
- `const __run = (fn) =>`,
201
- ` Effect.promise(() => __als.run(__store(), fn)).pipe(`,
193
+ `const __run = (fn) => {`,
194
+ ` const __s = getRequestStore();`,
195
+ ` return Effect.promise(() => withRequestStore(__s, fn)).pipe(`,
202
196
  ` Effect.map((value) => {`,
203
197
  ` if (value instanceof Response) {`,
204
198
  ` console.error("oxidejs: action() returned a Response; actions must return serializable data. Return a Response from src/server.ts for raw HTTP responses.");`,
@@ -207,7 +201,8 @@ function generateActionsModule(modules, opts) {
207
201
  ` return value === undefined ? null : value;`,
208
202
  ` }),`,
209
203
  ` );`,
210
- `const __withStore = (store, fn) => __als.run(store, fn);`
204
+ `};`,
205
+ `const __withStore = (store, fn) => withRequestStore(store, fn);`
211
206
  ];
212
207
  const rpcNames = [];
213
208
  const aliases = modules.map((mod, i) => {
@@ -231,7 +226,7 @@ function generateActionsModule(modules, opts) {
231
226
  for (const { alias, mod } of aliases) for (const name of mod.exports) {
232
227
  const tag = `${mod.key}.${name}`;
233
228
  const stream = mod.streams?.includes(name) ?? false;
234
- lines.push(stream ? ` ${JSON.stringify(tag)}: ({ args }) => { const __s = __store(); return asyncGenToStreamInContext(() => ${alias}[${JSON.stringify(name)}].apply(null, args), (fn) => __withStore(__s, fn)); },` : ` ${JSON.stringify(tag)}: ({ args }) => __run(() => ${alias}[${JSON.stringify(name)}].apply(null, args)),`);
229
+ lines.push(stream ? ` ${JSON.stringify(tag)}: ({ args }) => { const __s = getRequestStore(); return asyncGenToStreamInContext(() => ${alias}[${JSON.stringify(name)}].apply(null, args), (fn) => __withStore(__s, fn)); },` : ` ${JSON.stringify(tag)}: ({ args }) => __run(() => ${alias}[${JSON.stringify(name)}].apply(null, args)),`);
235
230
  }
236
231
  lines.push(`});`);
237
232
  lines.push(`export default actionsGroup;`);
@@ -757,23 +752,25 @@ function createActionHandler(group, handlers, options = {}) {
757
752
  if (!matchesActionPath(new URL(request.url).pathname, path)) return new Response("Not Found", { status: 404 });
758
753
  if (transport === "http" && request.method !== "POST") return methodNotAllowed();
759
754
  if (sameOrigin && !isSameOrigin(request)) return forbidden();
760
- const rawBody = ensureNdjsonBody(await request.arrayBuffer());
761
- const requestIds = extractJsonRpcRequestIds(rawBody);
762
- const headers = new Headers(request.headers);
763
- headers.set("content-type", NDJSON_CONTENT);
764
- const forwarded = new Request(request.url, {
765
- method: request.method,
766
- headers,
767
- body: rawBody,
768
- signal: request.signal
755
+ return withRequestEntry(async () => {
756
+ const rawBody = ensureNdjsonBody(await request.arrayBuffer());
757
+ const requestIds = extractJsonRpcRequestIds(rawBody);
758
+ const headers = new Headers(request.headers);
759
+ headers.set("content-type", NDJSON_CONTENT);
760
+ const forwarded = new Request(request.url, {
761
+ method: request.method,
762
+ headers,
763
+ body: rawBody,
764
+ signal: request.signal
765
+ });
766
+ const extra = await options.createContext?.(forwarded) ?? {};
767
+ const { handler } = bundleFor(group, handlers, path, transport);
768
+ const response = await runWithRequest(forwarded, () => handler(forwarded), extra);
769
+ const contentType = response.headers.get("content-type") ?? "";
770
+ if (contentType.includes("application/json-rpc") || contentType.includes("ndjson")) return scrubJsonResponse(response, requestIds);
771
+ if (contentType.includes("json")) return scrubBufferedJson(response, requestIds);
772
+ return response;
769
773
  });
770
- const extra = await options.createContext?.(forwarded) ?? {};
771
- const { handler } = bundleFor(group, handlers, path, transport);
772
- const response = await runWithRequest(forwarded, () => handler(forwarded), extra);
773
- const contentType = response.headers.get("content-type") ?? "";
774
- if (contentType.includes("application/json-rpc") || contentType.includes("ndjson")) return scrubJsonResponse(response, requestIds);
775
- if (contentType.includes("json")) return scrubBufferedJson(response, requestIds);
776
- return response;
777
774
  };
778
775
  }
779
776
  function disposeActionHandler(group, path = ACTION_PATH, transport = "http") {
package/dist/rpc.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as ActionContext } from "./context-C1UFQ0Zc.mjs";
1
+ import { t as ActionContext } from "./context-Ct8u5XUC.mjs";
2
2
  import { RpcClientOptions, createClient } from "./rpc/client.mjs";
3
3
  import { Layer, Stream } from "effect";
4
4
  import { Rpc, RpcGroup } from "effect/unstable/rpc";
@@ -38,8 +38,11 @@ declare function createWsHooks(group: RpcGroup.RpcGroup<Rpc.Any>, handlers: Laye
38
38
  //#region src/rpc/stream.d.ts
39
39
  declare function asyncGenToStream<T>(gen: AsyncGenerator<T, unknown, unknown>): Stream.Stream<T, Error, never>;
40
40
  /**
41
- * Re-enter `run` for every generator pull so AsyncLocalStorage request context
42
- * stays available across yields (Effect may drain the stream after the outer ALS scope ends).
41
+ * Re-enter `run` for every generator pull so request context stays available
42
+ * across yields (Effect may drain the stream after the outer ALS scope ends;
43
+ * WebContainer also loses ALS across awaits, so `run` must reinstall the store).
44
+ * On WebContainer, pulls are serialized through settlement so concurrent streams
45
+ * cannot replace the sync fallback mid-pull. `withRequestEntry` is unchanged.
43
46
  */
44
47
  declare function bindAsyncGenContext<T>(gen: AsyncGenerator<T, unknown, unknown>, run: <R>(fn: () => R) => R): AsyncGenerator<T, unknown, unknown>;
45
48
  /** Create a generator inside `run`, then keep every subsequent pull inside `run`. */
package/dist/rpc.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { a as extractJsonRpcRequestIds, c as scrubRpcMessage, i as ensureNdjsonBody, n as createActionHandler, o as scrubNdjsonTransform, r as disposeActionHandler, s as scrubRpcJson, t as createWsHooks } from "./rpc-DzUkWWgQ.mjs";
2
- import { a as streamToAsyncGen, i as bindAsyncGenContext, n as asyncGenToStream, r as asyncGenToStreamInContext, t as createClient } from "./client-C-s6XXpS.mjs";
1
+ import { a as extractJsonRpcRequestIds, c as scrubRpcMessage, i as ensureNdjsonBody, n as createActionHandler, o as scrubNdjsonTransform, r as disposeActionHandler, s as scrubRpcJson, t as createWsHooks } from "./rpc-tYqxQToi.mjs";
2
+ import { a as streamToAsyncGen, i as bindAsyncGenContext, n as asyncGenToStream, r as asyncGenToStreamInContext, t as createClient } from "./client-BgBfkZDx.mjs";
3
3
  export { asyncGenToStream, asyncGenToStreamInContext, bindAsyncGenContext, createActionHandler, createClient, createWsHooks, disposeActionHandler, ensureNdjsonBody, extractJsonRpcRequestIds, scrubNdjsonTransform, scrubRpcJson, scrubRpcMessage, streamToAsyncGen };
package/dist/rsbuild.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./plugin-HZKRDuCS.mjs";
1
+ import { t as oxidejs } from "./plugin-CurpVnGn.mjs";
2
2
  //#region src/rsbuild.ts
3
3
  var rsbuild_default = oxidejs.rsbuild;
4
4
  //#endregion
package/dist/vite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as oxidejs } from "./plugin-HZKRDuCS.mjs";
1
+ import { t as oxidejs } from "./plugin-CurpVnGn.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.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Vite/Rsbuild plugin. One build → dist/server.js + optional client. Server actions via *.server.ts.",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -1,42 +0,0 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- //#region src/context.ts
3
- const ALS_KEY = Symbol.for("oxidejs.requestContext");
4
- const FETCH_KEY = Symbol.for("oxidejs.fetch");
5
- function als() {
6
- const g = globalThis;
7
- return g[ALS_KEY] ??= new AsyncLocalStorage();
8
- }
9
- function store() {
10
- const current = als().getStore();
11
- if (!current) throw new Error("oxidejs: request context is unavailable");
12
- return current;
13
- }
14
- /** Current RPC or host request context. Throws outside request handling. */
15
- function useCtx() {
16
- return store();
17
- }
18
- /** Current server `Request`. Available in actions, SSR, and frame renders. */
19
- function useRequest() {
20
- return store().req;
21
- }
22
- /** Worker `env` from `fetch(request, env, ctx)`. `undefined` on the Node fetch preset. */
23
- function useEnv() {
24
- return store().env;
25
- }
26
- /** Worker `ctx` from `fetch(request, env, ctx)` (`waitUntil`). `undefined` on Node. */
27
- function useFetchCtx() {
28
- return store().fetchCtx;
29
- }
30
- function runWithRequest(req, fn, extra) {
31
- return als().run({
32
- ...extra,
33
- req
34
- }, fn);
35
- }
36
- const HOOK_KEY = Symbol.for("oxidejs.runWithRequest");
37
- globalThis[HOOK_KEY] ??= (req, fn) => {
38
- const extra = req[FETCH_KEY];
39
- return runWithRequest(req, fn, extra);
40
- };
41
- //#endregion
42
- export { useRequest as a, useFetchCtx as i, useCtx as n, useEnv as r, runWithRequest as t };