experimental-a2 0.2.0 → 0.4.0
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/CHANGELOG.md +169 -0
- package/dist/ai-B4YhEnfw.d.ts +333 -0
- package/dist/ai-server.d.ts +48 -9
- package/dist/ai-server.js +121 -49
- package/dist/ai.d.ts +2 -303
- package/dist/ai.js +231 -86
- package/dist/cli-B3VuxoDe.js +597 -0
- package/dist/cli-bin.d.ts +1 -0
- package/dist/cli-bin.js +5 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +2 -0
- package/dist/client-BrfDXQ8A.d.ts +155 -0
- package/dist/client-Bt4tAKi9.js +798 -0
- package/dist/client.d.ts +2 -90
- package/dist/client.js +1 -409
- package/dist/{contract-CG_adnu_.js → contract-48bUMgcL.js} +10 -2
- package/dist/{contract-C_3dIIEU.d.ts → contract-jIfaR085.d.ts} +62 -8
- package/dist/devtools-J_jZ2vQf.d.ts +151 -0
- package/dist/devtools-kJJaORn-.js +338 -0
- package/dist/devtools-server.browser.js +1 -1
- package/dist/devtools-server.d.ts +2 -2
- package/dist/devtools-server.js +224 -43
- package/dist/devtools.d.ts +2 -0
- package/dist/devtools.js +2 -0
- package/dist/{errors-BJRMd-h6.js → errors-BQuJpe82.js} +4 -4
- package/dist/{errors-xL_JTXsY.d.ts → errors-W6nwJ-fm.d.ts} +1 -1
- package/dist/http.d.ts +71 -13
- package/dist/http.js +302 -41
- package/dist/{idempotent-replay-BMyHrP0L.js → idempotent-replay-DuqEkYA7.js} +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/{inspection-E7qbD0Xj.js → inspection-DaxB5jM2.js} +2 -1
- package/dist/internal-aEotMzu_.js +209 -0
- package/dist/otel.d.ts +1 -1
- package/dist/platform-B4TnJtWu.js +32 -0
- package/dist/react.d.ts +37 -14
- package/dist/react.js +26 -15
- package/dist/scheduler-qstash.d.ts +78 -0
- package/dist/scheduler-qstash.js +499 -0
- package/dist/scheduler-task-BpzhPnRS.js +54 -0
- package/dist/{recovery-vercel.d.ts → scheduler-vercel.d.ts} +17 -24
- package/dist/scheduler-vercel.js +226 -0
- package/dist/server-CcNnFnoW.js +1405 -0
- package/dist/server-YtPq7hjw.d.ts +260 -0
- package/dist/server.d.ts +4 -155
- package/dist/server.js +2 -2
- package/dist/{log-ldf5g8Cx.d.ts → store-C3sNAaBT.d.ts} +111 -35
- package/dist/{log-yJbXUf72.js → store-N8PXxDAS.js} +1 -1
- package/dist/store-codec-DTG0Ftek.js +8 -0
- package/dist/store-memory.d.ts +11 -0
- package/dist/{log-memory.js → store-memory.js} +127 -24
- package/dist/{log-polling-6COoN60V.js → store-polling-DgrrAE3d.js} +7 -6
- package/dist/{log-postgres.d.ts → store-postgres.d.ts} +6 -6
- package/dist/{log-postgres.js → store-postgres.js} +158 -24
- package/dist/{log-redis.js → store-redis-core-DWqx3F47.js} +294 -156
- package/dist/store-redis-http.d.ts +21 -0
- package/dist/store-redis-http.js +70 -0
- package/dist/store-redis.d.ts +37 -0
- package/dist/store-redis.js +298 -0
- package/dist/{log-sqlite.d.ts → store-sqlite.d.ts} +6 -6
- package/dist/{log-sqlite.js → store-sqlite.js} +116 -22
- package/dist/{telemetry-Cso0qyHQ.d.ts → telemetry-BjYHTfh2.d.ts} +1 -1
- package/dist/testing.browser.d.ts +1 -0
- package/dist/testing.browser.js +4 -0
- package/dist/testing.d.ts +31 -0
- package/dist/testing.js +101 -0
- package/dist/wire-DCUZBUlT.js +222 -0
- package/docs/01-quickstart.mdx +4 -5
- package/docs/concepts/01-contracts.mdx +21 -17
- package/docs/concepts/02-handlers.mdx +7 -7
- package/docs/concepts/03-durability.mdx +26 -29
- package/docs/concepts/04-state.mdx +18 -21
- package/docs/guides/01-timers.mdx +154 -54
- package/docs/guides/02-cancellation.mdx +30 -4
- package/docs/guides/03-react.mdx +20 -21
- package/docs/guides/04-local-first.mdx +1 -1
- package/docs/guides/05-production.mdx +321 -60
- package/docs/guides/06-ai-agents.mdx +249 -49
- package/docs/guides/07-devtools.mdx +137 -12
- package/docs/guides/08-application-data.mdx +1 -1
- package/docs/guides/09-presence.mdx +284 -0
- package/docs/guides/10-transports.mdx +131 -0
- package/docs/index.mdx +22 -46
- package/docs/reference/01-api.mdx +751 -102
- package/docs/reference/02-errors.mdx +10 -5
- package/package.json +23 -6
- package/dist/internal-D6wNxTck.js +0 -36
- package/dist/log-memory.d.ts +0 -11
- package/dist/log-redis.d.ts +0 -31
- package/dist/recovery-vercel.js +0 -119
- package/dist/server-DJgD2YWP.js +0 -877
- package/dist/wire-BVsgR8o9.js +0 -62
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/platform.ts
|
|
2
|
+
const SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
|
|
3
|
+
function requestContext() {
|
|
4
|
+
try {
|
|
5
|
+
return Reflect.get(globalThis, SYMBOL_FOR_REQ_CONTEXT)?.get?.() ?? {};
|
|
6
|
+
} catch {
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** The current invocation's Vercel deployment identity, when available. */
|
|
11
|
+
function platformVercelOidcToken() {
|
|
12
|
+
try {
|
|
13
|
+
const token = requestContext().headers?.["x-vercel-oidc-token"];
|
|
14
|
+
return typeof token === "string" && token.length > 0 ? token : null;
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function platformWaitUntil(promise) {
|
|
20
|
+
try {
|
|
21
|
+
requestContext().waitUntil?.(promise);
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
/** The invocation's termination time in epoch ms, or null if unknowable. */
|
|
25
|
+
function invocationDeadlineMs() {
|
|
26
|
+
const deadline = requestContext().deadline;
|
|
27
|
+
if (deadline === void 0 || deadline === null) return null;
|
|
28
|
+
const ms = new Date(deadline).getTime();
|
|
29
|
+
return Number.isNaN(ms) ? null : ms;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { platformVercelOidcToken as n, platformWaitUntil as r, invocationDeadlineMs as t };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as EventDefs, c as Reducer, r as ContractEvent, t as AppendInput } from "./contract-
|
|
2
|
-
import {
|
|
1
|
+
import { a as EventDefs, c as PresencePatch, d as WithPresence, o as PresenceDefs, p as Reducer, r as ContractEvent, s as PresenceMap, t as AppendInput } from "./contract-jIfaR085.js";
|
|
2
|
+
import { a as Connection, c as PushResult, t as A2Client } from "./client-BrfDXQ8A.js";
|
|
3
3
|
import { ReactElement, ReactNode } from "react";
|
|
4
4
|
//#region src/react.d.ts
|
|
5
5
|
type SessionProviderProps<D extends EventDefs, S> = {
|
|
@@ -13,10 +13,33 @@ type SessionProviderProps<D extends EventDefs, S> = {
|
|
|
13
13
|
initialIndex: number;
|
|
14
14
|
/** Server-rendered event history through `initialIndex`. */
|
|
15
15
|
initialEvents?: ContractEvent<D>[];
|
|
16
|
+
/**
|
|
17
|
+
* This client's presence identity — required to call `setPresence`.
|
|
18
|
+
* Caller-supplied (a user id, a tab nonce, a guest name): A2 does
|
|
19
|
+
* not invent an identity story.
|
|
20
|
+
*/
|
|
21
|
+
participant?: string;
|
|
16
22
|
children?: ReactNode;
|
|
17
23
|
};
|
|
18
24
|
type BoundSessionProviderProps<D extends EventDefs, S> = Omit<SessionProviderProps<D, S>, "api">;
|
|
19
|
-
|
|
25
|
+
/**
|
|
26
|
+
* The presence members of the hook result — intersected in via
|
|
27
|
+
* `WithPresence`, so they exist exactly when the contract declares
|
|
28
|
+
* presence fields (the reducer is the client's typed handle on it).
|
|
29
|
+
*/
|
|
30
|
+
type UseSessionPresence<P extends PresenceDefs> = {
|
|
31
|
+
/** The replicated presence map, this client included (local echo). */
|
|
32
|
+
presence: PresenceMap<P>;
|
|
33
|
+
/**
|
|
34
|
+
* Fire-and-forget: validated locally, echoed into the map
|
|
35
|
+
* immediately, coalesced on the wire to a fixed cadence (a leading
|
|
36
|
+
* send immediately, then at most one merged send per interval;
|
|
37
|
+
* later values win per field), stamped with the frontier at send
|
|
38
|
+
* time as `seen`. Requires the provider's `participant`.
|
|
39
|
+
*/
|
|
40
|
+
setPresence: (values: PresencePatch<P>["values"]) => void;
|
|
41
|
+
};
|
|
42
|
+
type UseSessionResult<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>> = WithPresence<P, UseSessionPresence<P>> & {
|
|
20
43
|
/** The live view, folded through the shared reducer. */
|
|
21
44
|
state: S;
|
|
22
45
|
/** The raw observed feed `state` is folded from. */
|
|
@@ -36,19 +59,19 @@ type UseSessionResult<D extends EventDefs, S> = {
|
|
|
36
59
|
*/
|
|
37
60
|
push: (...events: AppendInput<D>[]) => PushResult<D>;
|
|
38
61
|
};
|
|
39
|
-
type A2React<D extends EventDefs, S
|
|
62
|
+
type A2React<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>> = {
|
|
40
63
|
SessionProvider: (props: SessionProviderProps<D, S>) => ReactElement;
|
|
41
|
-
useSession: () => UseSessionResult<D, S>;
|
|
64
|
+
useSession: () => UseSessionResult<D, S, P>;
|
|
42
65
|
};
|
|
43
|
-
type BoundA2React<D extends EventDefs, S
|
|
66
|
+
type BoundA2React<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>> = {
|
|
44
67
|
SessionProvider: (props: BoundSessionProviderProps<D, S>) => ReactElement;
|
|
45
|
-
useSession: () => UseSessionResult<D, S>;
|
|
68
|
+
useSession: () => UseSessionResult<D, S, P>;
|
|
46
69
|
};
|
|
47
|
-
declare function createReact<D extends EventDefs, S
|
|
48
|
-
client: A2Client<D, S>;
|
|
49
|
-
}): BoundA2React<D, S>;
|
|
50
|
-
declare function createReact<D extends EventDefs, S
|
|
51
|
-
reducer: Reducer<D, S>;
|
|
52
|
-
}): A2React<D, S>;
|
|
70
|
+
declare function createReact<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>>(options: {
|
|
71
|
+
client: A2Client<D, S, P>;
|
|
72
|
+
}): BoundA2React<D, S, P>;
|
|
73
|
+
declare function createReact<D extends EventDefs, S, P extends PresenceDefs = Record<never, never>>(options: {
|
|
74
|
+
reducer: Reducer<D, S, P>;
|
|
75
|
+
}): A2React<D, S, P>;
|
|
53
76
|
//#endregion
|
|
54
|
-
export { A2React, BoundA2React, BoundSessionProviderProps, SessionProviderProps, UseSessionResult, createReact };
|
|
77
|
+
export { A2React, BoundA2React, BoundSessionProviderProps, SessionProviderProps, UseSessionPresence, UseSessionResult, createReact };
|
package/dist/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createClient } from "./client.js";
|
|
2
|
+
import { t as createClient } from "./client-Bt4tAKi9.js";
|
|
3
3
|
import { createContext, createElement, useContext, useEffect, useMemo, useSyncExternalStore } from "react";
|
|
4
4
|
//#region src/react.ts
|
|
5
5
|
/**
|
|
@@ -17,13 +17,14 @@ import { createContext, createElement, useContext, useEffect, useMemo, useSyncEx
|
|
|
17
17
|
function createReact(options) {
|
|
18
18
|
const Context = createContext(null);
|
|
19
19
|
const providerMounts = /* @__PURE__ */ new WeakMap();
|
|
20
|
-
const resolveSession = "client" in options ? (sessionId, _api, initialState, initialIndex, initialEvents) => options.client.session(sessionId, {
|
|
20
|
+
const resolveSession = "client" in options ? (sessionId, _api, initialState, initialIndex, initialEvents, participant) => options.client.session(sessionId, {
|
|
21
21
|
initialState,
|
|
22
22
|
initialIndex,
|
|
23
|
-
...initialEvents === void 0 ? {} : { initialEvents }
|
|
23
|
+
...initialEvents === void 0 ? {} : { initialEvents },
|
|
24
|
+
...participant === void 0 ? {} : { participant }
|
|
24
25
|
}) : (() => {
|
|
25
26
|
const clients = /* @__PURE__ */ new Map();
|
|
26
|
-
return (sessionId, api, initialState, initialIndex, initialEvents) => {
|
|
27
|
+
return (sessionId, api, initialState, initialIndex, initialEvents, participant) => {
|
|
27
28
|
if (api === void 0) throw new TypeError("SessionProvider requires api when createReact binds a reducer");
|
|
28
29
|
let client = clients.get(api);
|
|
29
30
|
if (!client) {
|
|
@@ -36,19 +37,21 @@ function createReact(options) {
|
|
|
36
37
|
return client.session(sessionId, {
|
|
37
38
|
initialState,
|
|
38
39
|
initialIndex,
|
|
39
|
-
...initialEvents === void 0 ? {} : { initialEvents }
|
|
40
|
+
...initialEvents === void 0 ? {} : { initialEvents },
|
|
41
|
+
...participant === void 0 ? {} : { participant }
|
|
40
42
|
});
|
|
41
43
|
};
|
|
42
44
|
})();
|
|
43
45
|
function SessionProvider(props) {
|
|
44
|
-
const { sessionId, initialState, initialIndex, initialEvents } = props;
|
|
46
|
+
const { sessionId, initialState, initialIndex, initialEvents, participant } = props;
|
|
45
47
|
const api = "api" in props ? props.api : void 0;
|
|
46
|
-
const client = useMemo(() => resolveSession(sessionId, api, initialState, initialIndex, initialEvents), [
|
|
48
|
+
const client = useMemo(() => resolveSession(sessionId, api, initialState, initialIndex, initialEvents, participant), [
|
|
47
49
|
sessionId,
|
|
48
50
|
api,
|
|
49
51
|
initialState,
|
|
50
52
|
initialIndex,
|
|
51
|
-
initialEvents
|
|
53
|
+
initialEvents,
|
|
54
|
+
participant
|
|
52
55
|
]);
|
|
53
56
|
useEffect(() => {
|
|
54
57
|
const mounts = providerMounts.get(client) ?? 0;
|
|
@@ -68,13 +71,21 @@ function createReact(options) {
|
|
|
68
71
|
const client = useContext(Context);
|
|
69
72
|
if (!client) throw new Error("useSession must be rendered inside its matching SessionProvider");
|
|
70
73
|
const snapshot = useSyncExternalStore(client.subscribe, client.getSnapshot, client.getSnapshot);
|
|
71
|
-
return useMemo(() =>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
return useMemo(() => {
|
|
75
|
+
const { setPresence } = client;
|
|
76
|
+
const { presence } = snapshot;
|
|
77
|
+
return {
|
|
78
|
+
state: snapshot.state,
|
|
79
|
+
events: snapshot.events,
|
|
80
|
+
index: snapshot.index,
|
|
81
|
+
connection: snapshot.connection,
|
|
82
|
+
push: client.push,
|
|
83
|
+
...setPresence && presence ? {
|
|
84
|
+
presence,
|
|
85
|
+
setPresence
|
|
86
|
+
} : {}
|
|
87
|
+
};
|
|
88
|
+
}, [snapshot, client]);
|
|
78
89
|
}
|
|
79
90
|
return {
|
|
80
91
|
SessionProvider,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { i as Clock } from "./store-C3sNAaBT.js";
|
|
2
|
+
import { D as SchedulerTask, t as A2Scheduler } from "./server-YtPq7hjw.js";
|
|
3
|
+
//#region src/scheduler-qstash.d.ts
|
|
4
|
+
type QStashStoreOutage = {
|
|
5
|
+
version: 1;
|
|
6
|
+
/** Zero is the first successor created for a store outage. */
|
|
7
|
+
generation: number;
|
|
8
|
+
/** The first failing drain task's due time. Append identity lives on the task. */
|
|
9
|
+
rootDueAt?: number;
|
|
10
|
+
};
|
|
11
|
+
type QStashMessage = SchedulerTask & {
|
|
12
|
+
/** Provider-private state authenticated as part of QStash's signed body. */
|
|
13
|
+
_a2QStash?: QStashStoreOutage;
|
|
14
|
+
};
|
|
15
|
+
type QStashPublishRequest = {
|
|
16
|
+
url: string;
|
|
17
|
+
body: QStashMessage;
|
|
18
|
+
/** Headers the transport must deliver to the callback. */
|
|
19
|
+
headers?: Readonly<Record<string, string>>;
|
|
20
|
+
/** Header names the transport must redact from provider dashboard/API views. */
|
|
21
|
+
redact?: {
|
|
22
|
+
header: readonly string[];
|
|
23
|
+
};
|
|
24
|
+
/** Whole-second Unix timestamp. Omitted for an immediate delivery. */
|
|
25
|
+
notBefore?: number;
|
|
26
|
+
deduplicationId: string;
|
|
27
|
+
/** Delivery retries after the initial attempt. */
|
|
28
|
+
retries?: number;
|
|
29
|
+
};
|
|
30
|
+
/** The request shape passed to an injected `@upstash/qstash` client. */
|
|
31
|
+
type QStashClientPublishRequest = Omit<QStashPublishRequest, "headers" | "redact"> & {
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
redact?: {
|
|
34
|
+
header: string[];
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/** The outbound part of `@upstash/qstash` used by the built-in transport. */
|
|
38
|
+
type QStashPublishingClient = {
|
|
39
|
+
publishJSON(request: QStashClientPublishRequest): Promise<unknown>;
|
|
40
|
+
};
|
|
41
|
+
type QStashVerifyRequest = {
|
|
42
|
+
signature: string;
|
|
43
|
+
/** The untouched request body covered by the signature. */
|
|
44
|
+
body: string;
|
|
45
|
+
/** Exact destination URL, checked against the signature subject. */
|
|
46
|
+
url: string;
|
|
47
|
+
upstashRegion?: string;
|
|
48
|
+
};
|
|
49
|
+
/** The small part of `@upstash/qstash` this adapter needs. */
|
|
50
|
+
type QStashTransport = {
|
|
51
|
+
publish(request: QStashPublishRequest): Promise<unknown>;
|
|
52
|
+
verify(request: QStashVerifyRequest): Promise<boolean>;
|
|
53
|
+
};
|
|
54
|
+
type QStashSchedulerOptions = {
|
|
55
|
+
/** Exact URL mounted with `schedulerHandler(...)`. Inferred in local dev and on Vercel. */
|
|
56
|
+
url?: string;
|
|
57
|
+
/** QStash API token. Default: `QSTASH_TOKEN`. */
|
|
58
|
+
token?: string;
|
|
59
|
+
/** QStash signing key. Default: `QSTASH_CURRENT_SIGNING_KEY`. */
|
|
60
|
+
currentSigningKey?: string;
|
|
61
|
+
/** Next QStash signing key. Default: `QSTASH_NEXT_SIGNING_KEY`. */
|
|
62
|
+
nextSigningKey?: string;
|
|
63
|
+
/** Delivery retries after the initial attempt. Default: provider default. */
|
|
64
|
+
retries?: number;
|
|
65
|
+
/** Maximum callback body and outbound task with outage headroom. Default 1 MiB. */
|
|
66
|
+
maxBodyBytes?: number;
|
|
67
|
+
/** Static callback headers. QStash receives them; A2 requests dashboard/API redaction. */
|
|
68
|
+
headers?: Readonly<Record<string, string>>;
|
|
69
|
+
/** Injectable publishing client. The built-in receiver still verifies callbacks. */
|
|
70
|
+
client?: QStashPublishingClient;
|
|
71
|
+
/** Injectable transport (tests). Default: `@upstash/qstash`. */
|
|
72
|
+
transport?: QStashTransport;
|
|
73
|
+
/** Injectable clock for due-time calculations (tests). */
|
|
74
|
+
clock?: Clock;
|
|
75
|
+
};
|
|
76
|
+
declare function qstash(options?: QStashSchedulerOptions): A2Scheduler;
|
|
77
|
+
//#endregion
|
|
78
|
+
export { QStashClientPublishRequest, QStashPublishRequest, QStashPublishingClient, QStashSchedulerOptions, QStashTransport, QStashVerifyRequest, qstash };
|