oxidejs 0.3.2 → 0.3.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/dist/rpc.d.mts CHANGED
@@ -1,42 +1,46 @@
1
- import { t as ActionContext } from "./context-Ct8u5XUC.mjs";
1
+ import { r as OxidejsJson } from "./types-BaZeMYcP.mjs";
2
+ import { n as ActionContextValue, t as ActionContext } from "./context-CmChiQ2W.mjs";
2
3
  import { RpcClientOptions, createClient } from "./rpc/client.mjs";
3
4
  import { Layer, Stream } from "effect";
4
5
  import { Rpc, RpcGroup } from "effect/unstable/rpc";
5
6
  //#region src/rpc/server.d.ts
6
- type ActionHandlerOptions = {
7
+ interface ActionHandlerOptions {
8
+ createContext?: (req: Request) => ActionContext | Promise<ActionContext>;
7
9
  path?: string;
8
10
  sameOrigin?: boolean;
9
11
  transport?: "http" | "ws";
10
- createContext?: (req: Request) => ActionContext | Promise<ActionContext>;
11
- };
12
+ }
12
13
  type ActionGroup = RpcGroup.RpcGroup<Rpc.Any>;
13
- declare function createActionHandler(group: ActionGroup, handlers: Layer.Layer<unknown, unknown, unknown>, options?: ActionHandlerOptions): (request: Request) => Promise<Response>;
14
- declare function disposeActionHandler(group: ActionGroup, path?: string, transport?: "http" | "ws"): Promise<void>;
14
+ declare const createActionHandler: (group: ActionGroup, handlers: Layer.Layer<unknown, unknown, unknown>, options?: ActionHandlerOptions) => (request: Request) => Promise<Response>;
15
+ declare const disposeActionHandler: (group: ActionGroup, path?: string, transport?: "http" | "ws") => Promise<void>;
15
16
  //#endregion
16
17
  //#region src/rpc/ws.d.ts
17
- type WsPeer = {
18
- request?: Request;
19
- context: Record<string, unknown>;
20
- send: (data: unknown) => unknown;
18
+ interface WsPeerContext {
19
+ [key: string]: ActionContextValue;
20
+ }
21
+ interface WsPeer {
22
+ context: WsPeerContext;
21
23
  /** Optional: register a listener when the peer disconnects. */
22
24
  onClose?: (fn: () => void) => void;
23
- };
24
- type WsMessage = {
25
+ request?: Request;
26
+ send: (data: string) => void;
27
+ }
28
+ interface WsMessage {
25
29
  text: () => string;
26
- };
27
- type WsHooksOptions = {
30
+ }
31
+ interface WsHooksOptions {
32
+ createContext?: (peer: WsPeer) => ActionContext | Promise<ActionContext>;
33
+ maxMessageSize?: number;
28
34
  path?: string;
29
35
  sameOrigin?: boolean;
30
- maxMessageSize?: number;
31
- createContext?: (peer: WsPeer) => ActionContext | Promise<ActionContext>;
32
- };
33
- declare function createWsHooks(group: RpcGroup.RpcGroup<Rpc.Any>, handlers: Layer.Layer<unknown, unknown, unknown>, options?: WsHooksOptions): {
34
- upgrade(req: Request): Response | undefined;
36
+ }
37
+ declare const createWsHooks: (group: RpcGroup.RpcGroup<Rpc.Any>, handlers: Layer.Layer<unknown, unknown, unknown>, options?: WsHooksOptions) => {
35
38
  message(peer: WsPeer, message: WsMessage): Promise<void>;
39
+ upgrade(req: Request): Response | undefined;
36
40
  };
37
41
  //#endregion
38
42
  //#region src/rpc/stream.d.ts
39
- declare function asyncGenToStream<T>(gen: AsyncGenerator<T, unknown, unknown>): Stream.Stream<T, Error, never>;
43
+ declare const asyncGenToStream: <T>(gen: AsyncGenerator<T, unknown, unknown>) => Stream.Stream<T, Error, never>;
40
44
  /**
41
45
  * Re-enter `run` for every generator pull so request context stays available
42
46
  * across yields (Effect may drain the stream after the outer ALS scope ends;
@@ -44,35 +48,37 @@ declare function asyncGenToStream<T>(gen: AsyncGenerator<T, unknown, unknown>):
44
48
  * On WebContainer, pulls are serialized through settlement so concurrent streams
45
49
  * cannot replace the sync fallback mid-pull. `withRequestEntry` is unchanged.
46
50
  */
47
- declare function bindAsyncGenContext<T>(gen: AsyncGenerator<T, unknown, unknown>, run: <R>(fn: () => R) => R): AsyncGenerator<T, unknown, unknown>;
51
+ declare const bindAsyncGenContext: <T>(gen: AsyncGenerator<T, unknown, unknown>, run: <R>(fn: () => R) => R) => AsyncGenerator<T, unknown, unknown>;
48
52
  /** Create a generator inside `run`, then keep every subsequent pull inside `run`. */
49
- declare function asyncGenToStreamInContext<T>(create: () => AsyncGenerator<T, unknown, unknown>, run: <R>(fn: () => R) => R): Stream.Stream<T, Error, never>;
50
- declare function streamToAsyncGen<T>(stream: Stream.Stream<T>): AsyncIterable<T>;
53
+ declare const asyncGenToStreamInContext: <T>(create: () => AsyncGenerator<T, unknown, unknown>, run: <R>(fn: () => R) => R) => Stream.Stream<T, Error, never>;
54
+ declare const streamToAsyncGen: <T>(stream: Stream.Stream<T>) => AsyncIterable<T>;
51
55
  //#endregion
52
56
  //#region src/rpc/scrub.d.ts
57
+ /** JSON-RPC request/response id. */
58
+ type JsonRpcId = string | number | null;
53
59
  /** Mutable repair state so each Defect can claim a distinct originating request id. */
54
- type IdRepairState = {
60
+ interface IdRepairState {
55
61
  /** Request ids not yet claimed by a terminal (non-chunk) response. */
56
- remaining: Set<unknown>;
57
- };
62
+ remaining: Set<JsonRpcId>;
63
+ }
58
64
  /**
59
65
  * Scrub one JSON-RPC response object.
60
66
  * Effect encodes Defects with `id: -32603`; reclaim the originating request id from `state.remaining`.
61
67
  */
62
- declare function scrubRpcMessage(msg: unknown, requestIds?: readonly unknown[], state?: IdRepairState): unknown;
68
+ declare const scrubRpcMessage: (msg: OxidejsJson, requestIds?: readonly JsonRpcId[], state?: IdRepairState) => OxidejsJson;
63
69
  /**
64
70
  * Rewrite a JSON / NDJSON body so clients never see Effect `_tag` / `data` trees.
65
71
  * Accepts a single object, a JSON array, or newline-delimited frames.
66
72
  */
67
- declare function scrubRpcJson(body: string, requestIds?: readonly unknown[]): string;
73
+ declare const scrubRpcJson: (body: string, requestIds?: readonly JsonRpcId[]) => string;
68
74
  /** Collect JSON-RPC request ids from a unary object or batch array body. */
69
- declare function extractJsonRpcRequestIds(body: ArrayBuffer | Uint8Array | string): unknown[];
75
+ declare const extractJsonRpcRequestIds: (body: ArrayBuffer | Uint8Array | string) => JsonRpcId[];
70
76
  /** Ensure a body is a valid NDJSON frame (Effect's ndJsonRpc decode requires a trailing newline). */
71
- declare function ensureNdjsonBody(buf: ArrayBuffer): Uint8Array<ArrayBuffer>;
77
+ declare const ensureNdjsonBody: (buf: ArrayBuffer) => Uint8Array<ArrayBuffer>;
72
78
  /**
73
79
  * TransformStream that scrubs Effect defect payloads one NDJSON line at a time,
74
80
  * so long-running stream actions stay incremental.
75
81
  */
76
- declare function scrubNdjsonTransform(requestIds?: readonly unknown[]): TransformStream<Uint8Array, Uint8Array>;
82
+ declare const scrubNdjsonTransform: (requestIds?: readonly JsonRpcId[]) => TransformStream<Uint8Array, Uint8Array>;
77
83
  //#endregion
78
84
  export { type ActionHandlerOptions, type RpcClientOptions, type WsHooksOptions, asyncGenToStream, asyncGenToStreamInContext, bindAsyncGenContext, createActionHandler, createClient, createWsHooks, disposeActionHandler, ensureNdjsonBody, extractJsonRpcRequestIds, scrubNdjsonTransform, scrubRpcJson, scrubRpcMessage, streamToAsyncGen };
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-tYqxQToi.mjs";
2
- import { a as streamToAsyncGen, i as bindAsyncGenContext, n as asyncGenToStream, r as asyncGenToStreamInContext, t as createClient } from "./client-BgBfkZDx.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-gCOSJXql.mjs";
2
+ import { a as streamToAsyncGen, i as bindAsyncGenContext, n as asyncGenToStream, r as asyncGenToStreamInContext, t as createClient } from "./client-DOfB6wxk.mjs";
3
3
  export { asyncGenToStream, asyncGenToStreamInContext, bindAsyncGenContext, createActionHandler, createClient, createWsHooks, disposeActionHandler, ensureNdjsonBody, extractJsonRpcRequestIds, scrubNdjsonTransform, scrubRpcJson, scrubRpcMessage, streamToAsyncGen };
@@ -1,4 +1,4 @@
1
- import { r as OxidejsOptions } from "./types-BM4NAnzy.mjs";
1
+ import { i as OxidejsOptions } from "./types-BaZeMYcP.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 "./plugin-CurpVnGn.mjs";
1
+ import { t as oxidejs } from "./plugin-BIb3YnN7.mjs";
2
2
  //#region src/rsbuild.ts
3
3
  var rsbuild_default = oxidejs.rsbuild;
4
4
  //#endregion
@@ -1,13 +1,21 @@
1
1
  //#region src/types.d.ts
2
2
  type OxidejsPreset = "fetch" | "celld";
3
+ /** JSON-compatible value used for opaque wrangler / env bags. */
4
+ type OxidejsJson = string | number | boolean | null | OxidejsJson[] | {
5
+ [key: string]: OxidejsJson;
6
+ };
3
7
  interface OxidejsWranglerOptions {
4
8
  name: string;
5
9
  compatibility_date: string;
6
10
  compatibility_flags?: string[];
7
- durable_objects?: Record<string, unknown>;
8
- migrations?: unknown[];
9
- services?: unknown[];
10
- vars?: Record<string, unknown>;
11
+ durable_objects?: {
12
+ [key: string]: OxidejsJson;
13
+ };
14
+ migrations?: OxidejsJson[];
15
+ services?: OxidejsJson[];
16
+ vars?: {
17
+ [key: string]: OxidejsJson;
18
+ };
11
19
  }
12
20
  type OxidejsActionTransport = "http" | "ws";
13
21
  /** `actions` config: transport string, or an object with `transport`, `path`, `sameOrigin`. */
@@ -19,7 +27,9 @@ type OxidejsActions = OxidejsActionTransport | {
19
27
  sameOrigin?: boolean;
20
28
  };
21
29
  /** Static headers inlined into the shared action client. Functions cannot ship to the browser. */
22
- type OxidejsActionHeaders = Record<string, string> | [string, string][];
30
+ type OxidejsActionHeaders = {
31
+ [key: string]: string;
32
+ } | [string, string][];
23
33
  interface OxidejsOptions {
24
34
  /** "fetch" (default) skips wrangler.jsonc and serves client assets. "celld" emits wrangler.jsonc. */
25
35
  preset?: OxidejsPreset;
@@ -55,7 +65,9 @@ interface OxidejsOptions {
55
65
  notFound?: string;
56
66
  /** Extra env passed as the second argument to fetch(request, env, ctx) on
57
67
  * the Node fetch preset — read it with useEnv(). */
58
- env?: Record<string, unknown>;
68
+ env?: {
69
+ [key: string]: OxidejsJson;
70
+ };
59
71
  }
60
72
  interface ResolvedOptions {
61
73
  root: string;
@@ -85,7 +97,9 @@ interface ResolvedOptions {
85
97
  imports: string[];
86
98
  bodyLimit: number;
87
99
  notFound: string | undefined;
88
- env: Record<string, unknown> | undefined;
100
+ env: {
101
+ [key: string]: OxidejsJson;
102
+ } | undefined;
89
103
  }
90
104
  //#endregion
91
- export { OxidejsWranglerOptions as a, OxidejsPreset as i, OxidejsActionTransport as n, ResolvedOptions as o, OxidejsOptions as r, OxidejsActionHeaders as t };
105
+ export { OxidejsPreset as a, OxidejsOptions as i, OxidejsActionTransport as n, OxidejsWranglerOptions as o, OxidejsJson as r, ResolvedOptions as s, OxidejsActionHeaders as t };
package/dist/vite.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { r as OxidejsOptions } from "./types-BM4NAnzy.mjs";
1
+ import { i as OxidejsOptions } from "./types-BaZeMYcP.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 "./plugin-CurpVnGn.mjs";
1
+ import { t as oxidejs } from "./plugin-BIb3YnN7.mjs";
2
2
  //#region src/vite.ts
3
3
  var vite_default = oxidejs.vite;
4
4
  //#endregion
@@ -1,5 +1,5 @@
1
1
  //#region src/worker-dom.d.ts
2
2
  /** Install a minimal DOM on `globalThis` for Ilha `renderToString` in Workers. */
3
- declare function ensureWorkerDom(): void;
3
+ declare const ensureWorkerDom: () => void;
4
4
  //#endregion
5
5
  export { ensureWorkerDom };
@@ -1,16 +1,23 @@
1
1
  import * as linkedom from "linkedom";
2
2
  //#region src/worker-dom.ts
3
+ const SKIP_LINKEDOM_KEYS = /* @__PURE__ */ new Set([
4
+ "parseHTML",
5
+ "parseJSON",
6
+ "toJSON",
7
+ "Document"
8
+ ]);
3
9
  /** Install a minimal DOM on `globalThis` for Ilha `renderToString` in Workers. */
4
- function ensureWorkerDom() {
5
- if (typeof globalThis.document !== "undefined") return;
10
+ const ensureWorkerDom = function ensureWorkerDom() {
11
+ if (globalThis.document !== void 0) return;
6
12
  const window = linkedom.parseHTML("<!DOCTYPE html><html><body></body></html>");
7
- const g = globalThis;
8
- g.document = window.document;
9
- g.window = window;
13
+ Reflect.set(globalThis, "document", window.document);
14
+ Reflect.set(globalThis, "window", window);
10
15
  for (const [key, value] of Object.entries(linkedom)) {
11
- if (key === "parseHTML" || key === "parseJSON" || key === "toJSON" || key === "Document") continue;
12
- if (typeof value === "function" && /^[A-Z]/.test(key)) g[key] = value;
16
+ if (SKIP_LINKEDOM_KEYS.has(key)) continue;
17
+ if (!/^[A-Z]/u.test(key)) continue;
18
+ if (!("prototype" in value)) continue;
19
+ Reflect.set(globalThis, key, value);
13
20
  }
14
- }
21
+ };
15
22
  //#endregion
16
23
  export { ensureWorkerDom };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxidejs",
3
- "version": "0.3.2",
3
+ "version": "0.3.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",
@@ -93,6 +93,6 @@
93
93
  }
94
94
  },
95
95
  "engines": {
96
- "node": ">=20"
96
+ "node": ">=20.11"
97
97
  }
98
98
  }
package/virtual.d.ts CHANGED
@@ -1,13 +1,26 @@
1
1
  declare module "virtual:oxide/actions" {
2
- import type { Rpc, RpcGroup } from "effect/unstable/rpc";
3
2
  import type { Layer } from "effect";
3
+ import type { Rpc, RpcGroup } from "effect/unstable/rpc";
4
4
 
5
5
  const actionsGroup: RpcGroup.RpcGroup<Rpc.Any>;
6
- export const actionsHandlers: Layer.Layer<unknown, unknown, unknown>;
6
+ export const actionsHandlers: Layer.Layer<Rpc.Any, never, never>;
7
7
  export default actionsGroup;
8
8
  export { actionsGroup as actions };
9
9
  }
10
10
 
11
11
  declare module "virtual:oxide/client" {
12
- export const client: Record<string, Record<string, (...args: unknown[]) => Promise<unknown>>>;
12
+ type ActionValue =
13
+ | string
14
+ | number
15
+ | boolean
16
+ | null
17
+ | ActionValue[]
18
+ | { [key: string]: ActionValue };
19
+ type ActionFn = (
20
+ ...args: ActionValue[]
21
+ ) =>
22
+ | Promise<ActionValue>
23
+ | AsyncGenerator<ActionValue, ActionValue | undefined, undefined>;
24
+ type ActionModule = Record<string, ActionFn>;
25
+ export const client: Record<string, ActionModule>;
13
26
  }
@@ -1,166 +0,0 @@
1
- import { n as inWebcontainer } from "./context-DQDDwFYi.mjs";
2
- import { Effect, Layer, Scope, Stream } from "effect";
3
- import { RpcClient, RpcSchema, RpcSerialization } from "effect/unstable/rpc";
4
- import { FetchHttpClient, HttpClient, HttpClientRequest } from "effect/unstable/http";
5
- import { Socket } from "effect/unstable/socket";
6
- //#region src/rpc/stream.ts
7
- function asyncGenToStream(gen) {
8
- return Stream.fromAsyncIterable(gen, (error) => error instanceof Error ? error : new Error(String(error)));
9
- }
10
- /** Serialize WebContainer stream pulls so the shared syncStore is not stomped. */
11
- let pullTail = Promise.resolve();
12
- /**
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.
18
- */
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
- };
32
- return {
33
- next: (value) => runPull(() => gen.next(value)),
34
- return: (value) => runPull(() => gen.return(value)),
35
- throw: (error) => runPull(() => gen.throw(error)),
36
- [Symbol.asyncIterator]() {
37
- return this;
38
- },
39
- async [Symbol.asyncDispose]() {
40
- await runPull(() => gen.return(void 0));
41
- }
42
- };
43
- }
44
- /** Create a generator inside `run`, then keep every subsequent pull inside `run`. */
45
- function asyncGenToStreamInContext(create, run) {
46
- return asyncGenToStream(bindAsyncGenContext(run(create), run));
47
- }
48
- function streamToAsyncGen(stream) {
49
- return Stream.toAsyncIterable(stream);
50
- }
51
- //#endregion
52
- //#region src/rpc/client.ts
53
- const clientCache = /* @__PURE__ */ new Map();
54
- let nextGroupId = 0;
55
- function cacheKey(group, options) {
56
- const headerKey = options.headers ? Object.entries(options.headers).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join("&") : "";
57
- let groupId = group.__oxideClientId;
58
- if (groupId === void 0) {
59
- groupId = ++nextGroupId;
60
- group.__oxideClientId = groupId;
61
- }
62
- return `${groupId}|${options.transport ?? "http"}|${options.url}|${headerKey}`;
63
- }
64
- function httpLayer(options) {
65
- const headers = options.headers;
66
- return RpcClient.layerProtocolHttp({
67
- url: options.url,
68
- ...headers ? { transformClient: (client) => HttpClient.mapRequest(client, (req) => {
69
- for (const [key, value] of Object.entries(headers)) req = HttpClientRequest.setHeader(req, key, value);
70
- return req;
71
- }) } : {}
72
- }).pipe(Layer.provide(RpcSerialization.layerNdJsonRpc()), Layer.provide(FetchHttpClient.layer));
73
- }
74
- function wsLayer(url) {
75
- return RpcClient.layerProtocolSocket().pipe(Layer.provide(RpcSerialization.layerNdJsonRpc()), Layer.provide(Socket.layerWebSocket(url)), Layer.provide(Socket.layerWebSocketConstructorGlobal));
76
- }
77
- function clientLayer(options) {
78
- return options.transport === "ws" ? wsLayer(options.url) : httpLayer(options);
79
- }
80
- function loadClient(group, options) {
81
- return Effect.gen(function* () {
82
- const scope = yield* Scope.make();
83
- const context = yield* Scope.provide(scope)(Layer.build(clientLayer(options)));
84
- return yield* Scope.provide(scope)(RpcClient.make(group).pipe(Effect.provide(context)));
85
- });
86
- }
87
- function isStreamResult(value) {
88
- return Stream.isStream(value);
89
- }
90
- function isStreamTag(group, tag) {
91
- const rpc = group.requests.get(tag);
92
- if (!rpc?.successSchema) return false;
93
- return RpcSchema.isStreamSchema(rpc.successSchema);
94
- }
95
- function streamToAsyncGenerator(stream, signal) {
96
- const iterable = streamToAsyncGen(stream);
97
- return (async function* () {
98
- if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
99
- const iterator = iterable[Symbol.asyncIterator]();
100
- const onAbort = () => {
101
- iterator.return?.();
102
- };
103
- signal?.addEventListener("abort", onAbort, { once: true });
104
- try {
105
- while (true) {
106
- if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
107
- const next = await iterator.next();
108
- if (next.done) return void 0;
109
- yield next.value;
110
- }
111
- } finally {
112
- signal?.removeEventListener("abort", onAbort);
113
- }
114
- })();
115
- }
116
- function callFlat(client, tag, args, callOpts) {
117
- const caller = client[tag];
118
- if (!caller) return Promise.reject(/* @__PURE__ */ new Error(`Unknown action ${tag}`));
119
- const result = caller({ args }, callOpts);
120
- if (isStreamResult(result)) return streamToAsyncGenerator(result, callOpts?.signal);
121
- return Effect.runPromise(result, { signal: callOpts?.signal });
122
- }
123
- function nestClient(group, flat) {
124
- const nested = {};
125
- for (const tag of group.requests.keys()) {
126
- const dot = tag.indexOf(".");
127
- if (dot === -1) continue;
128
- const mod = tag.slice(0, dot);
129
- const name = tag.slice(dot + 1);
130
- nested[mod] ??= {};
131
- nested[mod][name] = (...args) => {
132
- const opts = args.at(-1);
133
- const hasSignal = opts && typeof opts === "object" && "signal" in opts && opts.signal instanceof AbortSignal && Object.keys(opts).length === 1;
134
- const params = hasSignal ? args.slice(0, -1) : args;
135
- return callFlat(flat, tag, params, hasSignal ? opts : void 0);
136
- };
137
- }
138
- return nested;
139
- }
140
- function createClient(group, options) {
141
- const key = cacheKey(group, options);
142
- let entry = clientCache.get(key);
143
- if (!entry) {
144
- entry = { pending: Effect.runPromise(loadClient(group, options)).then((flat) => {
145
- return nestClient(group, flat);
146
- }).catch((error) => {
147
- clientCache.delete(key);
148
- throw error;
149
- }) };
150
- clientCache.set(key, entry);
151
- }
152
- return new Proxy({}, { get(_target, mod) {
153
- if (typeof mod !== "string") return void 0;
154
- return new Proxy({}, { get(_inner, name) {
155
- if (typeof name !== "string") return void 0;
156
- if (isStreamTag(group, `${mod}.${name}`)) return (...args) => (async function* () {
157
- const out = (await entry.pending)[mod]?.[name]?.(...args);
158
- if (!out) throw new Error(`Unknown action ${mod}.${name}`);
159
- yield* out;
160
- })();
161
- return (...args) => entry.pending.then((client) => client[mod]?.[name]?.(...args) ?? Promise.reject(/* @__PURE__ */ new Error(`Unknown action ${mod}.${name}`)));
162
- } });
163
- } });
164
- }
165
- //#endregion
166
- export { streamToAsyncGen as a, bindAsyncGenContext as i, asyncGenToStream as n, asyncGenToStreamInContext as r, createClient as t };
@@ -1,73 +0,0 @@
1
- import * as Atom from "effect/unstable/reactivity/Atom";
2
- import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
3
- //#region src/action.d.ts
4
- declare const ACTION_CALL: unique symbol;
5
- type CallOptions = {
6
- signal?: AbortSignal;
7
- };
8
- type ServerActionHandle<Args extends unknown[], A> = {
9
- (...args: Args | [...Args, CallOptions]): Promise<A>;
10
- set(...args: Args): Promise<A>;
11
- bind(...args: Args): (...ev: unknown[]) => void;
12
- with(...args: Args): (...ev: unknown[]) => void;
13
- /** Last `AsyncResult` for this action's client atom (does not invoke RPC). */
14
- readonly result: AsyncResult.AsyncResult<A, unknown>;
15
- readonly atom: Atom.Atom<unknown>;
16
- readonly $$atom: 1;
17
- };
18
- type StreamActionHandle<Args extends unknown[], Y, R = void> = {
19
- (...args: Args | [...Args, CallOptions]): AsyncGenerator<Y, R, undefined>;
20
- set(...args: Args): AsyncGenerator<Y, R, undefined>;
21
- bind(...args: Args): (...ev: unknown[]) => void;
22
- with(...args: Args): (...ev: unknown[]) => void;
23
- readonly atom: undefined;
24
- readonly $$atom: 1;
25
- };
26
- /** Attach an ilha server-island capture key to an action handle. */
27
- declare function brandServerAction<Args extends unknown[], A>(key: string, handle: ServerActionHandle<Args, A>): ServerActionHandle<Args, A>;
28
- /** Wrap an RPC caller as an `Atom.fn`-shaped client action handle. */
29
- declare function wrapClientRpc<Args extends unknown[], A>(rpc: (...args: Args | [...Args, CallOptions]) => Promise<A>): ServerActionHandle<Args, A>;
30
- /**
31
- * Wrap a streaming RPC caller so the client handle returns an async generator
32
- * (awaiting the underlying client lazily), not `Promise<AsyncGenerator>`.
33
- */
34
- declare function wrapClientStreamRpc<Args extends unknown[], Y, R = void>(rpc: (...args: Args | [...Args, CallOptions]) => AsyncGenerator<Y, R, undefined>): StreamActionHandle<Args, Y, R>;
35
- /**
36
- * Marks a `*.server.ts` export as a remote RPC action. On the server the
37
- * underlying function runs locally; on the client the build replaces the module
38
- * with an `Atom.fn`-shaped RPC handle (`set`, `bind`, `result`).
39
- */
40
- declare function action<Args extends unknown[], Y, R = void>(fn: (...args: Args) => AsyncGenerator<Y, R, unknown>): StreamActionHandle<Args, Y, R>;
41
- declare function action<Args extends unknown[], Result>(fn: (...args: Args) => Result): ServerActionHandle<Args, Awaited<Result>>;
42
- //#endregion
43
- //#region src/context.d.ts
44
- type ExecutionContext = {
45
- waitUntil?(promise: Promise<unknown>): void;
46
- passThroughOnException?(): void;
47
- };
48
- /** RPC procedure request context. Starts as `{ req }` plus Worker extras. Middleware can add fields. */
49
- type ActionContext = {
50
- req: Request;
51
- env?: unknown;
52
- fetchCtx?: ExecutionContext;
53
- [key: string]: unknown;
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;
64
- /** Current RPC or host request context. Throws outside request handling. */
65
- declare function useCtx<C extends ActionContext = ActionContext>(): C;
66
- /** Current server `Request`. Available in actions, SSR, and frame renders. */
67
- declare function useRequest(): Request;
68
- /** Worker `env` from `fetch(request, env, ctx)`. `undefined` on the Node fetch preset. */
69
- declare function useEnv<E = unknown>(): E | undefined;
70
- /** Worker `ctx` from `fetch(request, env, ctx)` (`waitUntil`). `undefined` on Node. */
71
- declare function useFetchCtx(): ExecutionContext | undefined;
72
- //#endregion
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 };