@opendatalabs/vana-sdk 3.20.1 → 3.22.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/README.md +64 -0
- package/dist/direct/access-request-client.cjs +100 -2
- package/dist/direct/access-request-client.cjs.map +1 -1
- package/dist/direct/access-request-client.d.ts +23 -1
- package/dist/direct/access-request-client.js +98 -1
- package/dist/direct/access-request-client.js.map +1 -1
- package/dist/direct/controller.cjs +4 -0
- package/dist/direct/controller.cjs.map +1 -1
- package/dist/direct/controller.d.ts +10 -1
- package/dist/direct/controller.js +6 -1
- package/dist/direct/controller.js.map +1 -1
- package/dist/direct/types.cjs.map +1 -1
- package/dist/direct/types.d.ts +45 -0
- package/dist/direct/types.js.map +1 -1
- package/dist/index.browser.d.ts +2 -1
- package/dist/index.browser.js +186 -0
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +196 -0
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +2 -1
- package/dist/index.node.js +186 -0
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/derivative-questions.cjs +22 -0
- package/dist/protocol/derivative-questions.cjs.map +1 -1
- package/dist/protocol/derivative-questions.d.ts +53 -0
- package/dist/protocol/derivative-questions.js +19 -0
- package/dist/protocol/derivative-questions.js.map +1 -1
- package/dist/protocol/derivative-status.cjs +209 -0
- package/dist/protocol/derivative-status.cjs.map +1 -0
- package/dist/protocol/derivative-status.d.ts +196 -0
- package/dist/protocol/derivative-status.js +190 -0
- package/dist/protocol/derivative-status.js.map +1 -0
- package/dist/protocol/derivative-status.test.d.ts +1 -0
- package/dist/server.cjs +4 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +4 -2
- package/dist/server.js.map +1 -1
- package/dist/tests/mock-personal-server.d.ts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derivative status: the lifecycle of the question behind a derived scope,
|
|
3
|
+
* as the party that READS the answer sees it.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* A builder registers a question with {@link registerQuestion} and follows it
|
|
7
|
+
* with {@link waitForQuestion}, both of which need a write session. The app
|
|
8
|
+
* that only consumes the answer holds no write entry at all — a consent flow
|
|
9
|
+
* grants it a bare read on the derived scope — so it cannot open one, and
|
|
10
|
+
* `GET /v1/data/<derivedScope>` answers 404 for all three of "computing right
|
|
11
|
+
* now", "failed but retrying" and "failed for good".
|
|
12
|
+
*
|
|
13
|
+
* `GET /v1/derivatives/status?derivedScope=<scope>` is that reader's view.
|
|
14
|
+
* Authorization is the data read's (a live grant covering the derived scope,
|
|
15
|
+
* or the owner), nothing is served and nothing is charged, and the view is
|
|
16
|
+
* deliberately narrow: lifecycle, a coarse {@link DerivativeErrorCode} and
|
|
17
|
+
* the next retry. The question text, the source scopes, the question id, the
|
|
18
|
+
* registrar and the server's raw error string stay owner-only.
|
|
19
|
+
*
|
|
20
|
+
* Requires `personal-server-ts` with the status route; an older Personal
|
|
21
|
+
* Server answers 404 for the route itself.
|
|
22
|
+
*
|
|
23
|
+
* @category Protocol
|
|
24
|
+
*/
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
import { type QuestionStatus } from "./derivative-questions.js";
|
|
27
|
+
import { type ResolveWriteSignerOptions, type WriteSignerSource } from "./write-signer.js";
|
|
28
|
+
export { DERIVATIVE_ERROR_CODES, DerivativeErrorCodeSchema, type DerivativeErrorCode, } from "./derivative-questions.js";
|
|
29
|
+
/** The reader-facing status route. */
|
|
30
|
+
export declare const DERIVATIVE_STATUS_PATH = "/v1/derivatives/status";
|
|
31
|
+
/** How long {@link waitForDerivativeStatus} polls before giving up. */
|
|
32
|
+
export declare const DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 120000;
|
|
33
|
+
/**
|
|
34
|
+
* How long {@link waitForDerivativeStatus} waits between polls when the
|
|
35
|
+
* server names no retry time of its own.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2000;
|
|
38
|
+
/**
|
|
39
|
+
* The status of the derived scope, not of one registration: when several
|
|
40
|
+
* questions write the same scope, the server reports the most optimistic
|
|
41
|
+
* true state, because serving data is registration-agnostic.
|
|
42
|
+
*/
|
|
43
|
+
export declare const DerivativeStatusSchema: z.ZodObject<{
|
|
44
|
+
derivedScope: z.ZodString;
|
|
45
|
+
status: z.ZodEnum<{
|
|
46
|
+
pending: "pending";
|
|
47
|
+
ready: "ready";
|
|
48
|
+
failed: "failed";
|
|
49
|
+
stale: "stale";
|
|
50
|
+
}>;
|
|
51
|
+
lastComputedAt: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
|
|
52
|
+
derivedVersion: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodNumber>>, z.ZodTransform<number | null, number | null | undefined>>;
|
|
53
|
+
derivedCollectedAt: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null, string | null | undefined>>;
|
|
54
|
+
errorCode: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
55
|
+
internal: "internal";
|
|
56
|
+
inference_unavailable: "inference_unavailable";
|
|
57
|
+
source_missing: "source_missing";
|
|
58
|
+
grant_invalid: "grant_invalid";
|
|
59
|
+
}>>>, z.ZodTransform<NonNullable<"internal" | "inference_unavailable" | "source_missing" | "grant_invalid"> | null, "internal" | "inference_unavailable" | "source_missing" | "grant_invalid" | null | undefined>>;
|
|
60
|
+
retryAfterSeconds: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodNumber>>, z.ZodTransform<number | null, number | null | undefined>>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
/** @see {@link DerivativeStatusSchema} */
|
|
63
|
+
export type DerivativeStatus = z.infer<typeof DerivativeStatusSchema>;
|
|
64
|
+
/** What {@link getDerivativeStatus} needs to sign and send one read. */
|
|
65
|
+
export interface GetDerivativeStatusParams extends ResolveWriteSignerOptions {
|
|
66
|
+
/** Personal Server origin, e.g. `https://ps.example.com`. */
|
|
67
|
+
personalServerUrl: string;
|
|
68
|
+
/** The derived scope whose question to observe. */
|
|
69
|
+
derivedScope: string;
|
|
70
|
+
/**
|
|
71
|
+
* A grant covering the derived scope, sent as the signed `grantId` claim.
|
|
72
|
+
* Omit only when the signer is the Personal Server's owner, who is
|
|
73
|
+
* authorized without one.
|
|
74
|
+
*/
|
|
75
|
+
grantId?: string;
|
|
76
|
+
/** Reader key: a viem `LocalAccount`, `WalletClient`, or `{ signMessage }`. */
|
|
77
|
+
signer: WriteSignerSource;
|
|
78
|
+
/** Web3Signed audience; defaults to `personalServerUrl`. */
|
|
79
|
+
audience?: string;
|
|
80
|
+
/** `fetch` to use; defaults to `globalThis.fetch`. */
|
|
81
|
+
fetch?: typeof fetch;
|
|
82
|
+
/** Extra request headers. */
|
|
83
|
+
headers?: HeadersInit;
|
|
84
|
+
/** Aborts the request in flight. */
|
|
85
|
+
signal?: AbortSignal;
|
|
86
|
+
}
|
|
87
|
+
/** What {@link waitForDerivativeStatus} polls with. */
|
|
88
|
+
export interface WaitForDerivativeStatusParams extends GetDerivativeStatusParams {
|
|
89
|
+
/** Give up after this long (default 120s). */
|
|
90
|
+
timeoutMs?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Wait between polls when the server names no retry time (default 2s).
|
|
93
|
+
* A `retryAfterSeconds` from the server replaces this outright, longer or
|
|
94
|
+
* shorter: it is when the next compute actually happens.
|
|
95
|
+
*/
|
|
96
|
+
pollIntervalMs?: number;
|
|
97
|
+
/**
|
|
98
|
+
* Aborts the wait, and the request in flight with it: the signal is passed
|
|
99
|
+
* to every poll, so an abort during a stalled request does not sit until
|
|
100
|
+
* the transport gives up.
|
|
101
|
+
*/
|
|
102
|
+
signal?: AbortSignal;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The request target for a status read: the query carries the derived scope,
|
|
106
|
+
* the signed `uri` does not.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* Like every Web3Signed read (data, lineage), the Personal Server verifies
|
|
110
|
+
* the signature over the PATH; per-scope authorization is enforced live
|
|
111
|
+
* against the caller's grant on each request, so the query needs no
|
|
112
|
+
* signature to be safe. Only the write path signs path AND query, where a
|
|
113
|
+
* parameter decides what is written.
|
|
114
|
+
*/
|
|
115
|
+
export declare function derivativeStatusTarget(derivedScope: string): string;
|
|
116
|
+
/**
|
|
117
|
+
* Is this a state the reader can act on?
|
|
118
|
+
*
|
|
119
|
+
* @remarks
|
|
120
|
+
* `ready` means the derived scope has an answer to read. A `failed` status
|
|
121
|
+
* is settled only when no retry is pending: with `retryAfterSeconds` set the
|
|
122
|
+
* Personal Server will compute again on its own, so the answer may still
|
|
123
|
+
* arrive. `pending` and `stale` are always in flight.
|
|
124
|
+
*/
|
|
125
|
+
export declare function isDerivativeStatusSettled(status: DerivativeStatus): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Read the lifecycle of the question behind a derived scope.
|
|
128
|
+
*
|
|
129
|
+
* @remarks
|
|
130
|
+
* Sends `GET /v1/derivatives/status?derivedScope=<scope>` with a Web3Signed
|
|
131
|
+
* `Authorization` header carrying `grantId`, the same authentication a data
|
|
132
|
+
* read uses. Nothing is charged: the route authorizes, it does not serve
|
|
133
|
+
* data, so a priced grant raises no 402 here.
|
|
134
|
+
*
|
|
135
|
+
* @returns The status of the derived scope. When several registrations write
|
|
136
|
+
* it, the most optimistic true state answers — `ready`, then `stale`, then
|
|
137
|
+
* `pending`, then `failed` — because a duplicate that never wrote anything
|
|
138
|
+
* must not report away an answer the scope has.
|
|
139
|
+
* @throws {DerivativeQuestionNotFoundError} 404: the caller may read the
|
|
140
|
+
* scope but no question stands behind it (and, on an older Personal
|
|
141
|
+
* Server, the route itself is unknown).
|
|
142
|
+
* @throws {WriteForbiddenError} 403: the grant does not cover the derived
|
|
143
|
+
* scope. The check runs before any store lookup, so a caller cannot probe
|
|
144
|
+
* which scopes have questions.
|
|
145
|
+
* @throws {DerivativeQuestionRejectedError} On any other non-2xx answer or
|
|
146
|
+
* an unparseable body.
|
|
147
|
+
* @throws {WriteTransportError} When `fetch` itself failed.
|
|
148
|
+
* @throws {WriteRequestError} On a missing `derivedScope` or no `fetch`.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* const status = await getDerivativeStatus({
|
|
153
|
+
* personalServerUrl: "https://ps.example.com",
|
|
154
|
+
* derivedScope: "coach.weekly",
|
|
155
|
+
* grantId,
|
|
156
|
+
* signer,
|
|
157
|
+
* });
|
|
158
|
+
* if (status.status === "ready") {
|
|
159
|
+
* const record = await readPersonalServerData({ ... });
|
|
160
|
+
* } else if (status.retryAfterSeconds !== null) {
|
|
161
|
+
* // Computing or retrying: come back then.
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export declare function getDerivativeStatus(params: GetDerivativeStatusParams): Promise<DerivativeStatus>;
|
|
166
|
+
/**
|
|
167
|
+
* Poll {@link getDerivativeStatus} until the derived scope has an answer or
|
|
168
|
+
* has stopped trying to get one.
|
|
169
|
+
*
|
|
170
|
+
* @remarks
|
|
171
|
+
* Returns as soon as {@link isDerivativeStatusSettled} holds: `ready`, or
|
|
172
|
+
* `failed` with no retry pending. A failure the server will retry is not a
|
|
173
|
+
* result, so the wait continues through it — on the server's own cadence,
|
|
174
|
+
* because `retryAfterSeconds` is when the next compute actually happens and
|
|
175
|
+
* polling faster only spends requests. A failed status is returned, not
|
|
176
|
+
* thrown: the reader branches on `errorCode`.
|
|
177
|
+
*
|
|
178
|
+
* @returns The settled status.
|
|
179
|
+
* @throws {DerivativeQuestionTimeoutError} When the budget ran out first.
|
|
180
|
+
* The question keeps computing on the server; call again.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* const status = await waitForDerivativeStatus({
|
|
185
|
+
* personalServerUrl,
|
|
186
|
+
* derivedScope: "coach.weekly",
|
|
187
|
+
* grantId,
|
|
188
|
+
* signer,
|
|
189
|
+
* timeoutMs: 60_000,
|
|
190
|
+
* });
|
|
191
|
+
* if (status.status !== "ready") console.log(status.errorCode);
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export declare function waitForDerivativeStatus(params: WaitForDerivativeStatusParams): Promise<DerivativeStatus>;
|
|
195
|
+
/** Statuses that mean a compute is in flight. @see {@link QuestionStatus} */
|
|
196
|
+
export type PendingDerivativeStatus = Extract<QuestionStatus, "pending" | "stale">;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { buildWeb3SignedHeader } from "../auth/web3-signed-builder.js";
|
|
3
|
+
import {
|
|
4
|
+
DerivativeQuestionRejectedError,
|
|
5
|
+
DerivativeQuestionTimeoutError,
|
|
6
|
+
WriteRequestError,
|
|
7
|
+
WriteTransportError
|
|
8
|
+
} from "../errors.js";
|
|
9
|
+
import {
|
|
10
|
+
DerivativeErrorCodeSchema,
|
|
11
|
+
personalServerErrorFromQuestionResponse,
|
|
12
|
+
QuestionStatusSchema
|
|
13
|
+
} from "./derivative-questions.js";
|
|
14
|
+
import {
|
|
15
|
+
resolveWriteSigner
|
|
16
|
+
} from "./write-signer.js";
|
|
17
|
+
import {
|
|
18
|
+
DERIVATIVE_ERROR_CODES,
|
|
19
|
+
DerivativeErrorCodeSchema as DerivativeErrorCodeSchema2
|
|
20
|
+
} from "./derivative-questions.js";
|
|
21
|
+
const DERIVATIVE_STATUS_PATH = "/v1/derivatives/status";
|
|
22
|
+
const DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 12e4;
|
|
23
|
+
const DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2e3;
|
|
24
|
+
const nullable = (schema) => schema.nullish().transform((value) => value ?? null);
|
|
25
|
+
const DerivativeStatusSchema = z.object({
|
|
26
|
+
derivedScope: z.string().min(1),
|
|
27
|
+
status: QuestionStatusSchema,
|
|
28
|
+
/** When the last compute finished, or `null` if none ever has. */
|
|
29
|
+
lastComputedAt: nullable(z.string()),
|
|
30
|
+
/** Local version of the derived record the last compute wrote. */
|
|
31
|
+
derivedVersion: nullable(z.number()),
|
|
32
|
+
derivedCollectedAt: nullable(z.string()),
|
|
33
|
+
/** The failure class; `null` unless `status` is `failed`. */
|
|
34
|
+
errorCode: nullable(DerivativeErrorCodeSchema),
|
|
35
|
+
/**
|
|
36
|
+
* Seconds until the Personal Server's next automatic retry, or `null` when
|
|
37
|
+
* none is pending or running — the terminal signature. Poll on this cadence
|
|
38
|
+
* rather than guessing one.
|
|
39
|
+
*/
|
|
40
|
+
retryAfterSeconds: nullable(z.number())
|
|
41
|
+
});
|
|
42
|
+
function derivativeStatusTarget(derivedScope) {
|
|
43
|
+
return `${DERIVATIVE_STATUS_PATH}?derivedScope=${encodeURIComponent(derivedScope)}`;
|
|
44
|
+
}
|
|
45
|
+
function normalizeBaseUrl(url) {
|
|
46
|
+
return url.replace(/\/+$/, "");
|
|
47
|
+
}
|
|
48
|
+
function resolveFetch(fetchFn) {
|
|
49
|
+
const resolved = fetchFn ?? globalThis.fetch;
|
|
50
|
+
if (resolved === void 0) {
|
|
51
|
+
throw new WriteRequestError("No fetch implementation available");
|
|
52
|
+
}
|
|
53
|
+
return resolved;
|
|
54
|
+
}
|
|
55
|
+
function requireDerivedScope(derivedScope) {
|
|
56
|
+
if (typeof derivedScope !== "string" || derivedScope.length === 0) {
|
|
57
|
+
throw new WriteRequestError("derivedScope is required");
|
|
58
|
+
}
|
|
59
|
+
return derivedScope;
|
|
60
|
+
}
|
|
61
|
+
function sleep(ms, signal) {
|
|
62
|
+
if (ms <= 0) return Promise.resolve();
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
const timer = setTimeout(() => {
|
|
65
|
+
signal?.removeEventListener("abort", onAbort);
|
|
66
|
+
resolve();
|
|
67
|
+
}, ms);
|
|
68
|
+
const onAbort = () => {
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
reject(abortError(signal));
|
|
71
|
+
};
|
|
72
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function timeoutError(latest, timeoutMs) {
|
|
76
|
+
return new DerivativeQuestionTimeoutError(
|
|
77
|
+
`Derived scope ${latest.derivedScope} was still ${latest.status} after ${timeoutMs}ms`,
|
|
78
|
+
{
|
|
79
|
+
derivedScope: latest.derivedScope,
|
|
80
|
+
status: latest.status,
|
|
81
|
+
errorCode: latest.errorCode,
|
|
82
|
+
retryAfterSeconds: latest.retryAfterSeconds,
|
|
83
|
+
timeoutMs
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
function abortError(signal) {
|
|
88
|
+
const reason = signal?.reason;
|
|
89
|
+
return reason instanceof Error ? reason : new WriteRequestError("Derivative status wait was aborted");
|
|
90
|
+
}
|
|
91
|
+
function isDerivativeStatusSettled(status) {
|
|
92
|
+
if (status.status === "ready") return true;
|
|
93
|
+
return status.status === "failed" && status.retryAfterSeconds === null;
|
|
94
|
+
}
|
|
95
|
+
async function getDerivativeStatus(params) {
|
|
96
|
+
const derivedScope = requireDerivedScope(params.derivedScope);
|
|
97
|
+
const fetchFn = resolveFetch(params.fetch);
|
|
98
|
+
const baseUrl = normalizeBaseUrl(params.personalServerUrl);
|
|
99
|
+
const signer = resolveWriteSigner(params.signer, { account: params.account });
|
|
100
|
+
const headers = new Headers(params.headers);
|
|
101
|
+
headers.set(
|
|
102
|
+
"Authorization",
|
|
103
|
+
await buildWeb3SignedHeader({
|
|
104
|
+
signMessage: signer.signMessage,
|
|
105
|
+
aud: params.audience ?? baseUrl,
|
|
106
|
+
method: "GET",
|
|
107
|
+
uri: DERIVATIVE_STATUS_PATH,
|
|
108
|
+
grantId: params.grantId
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
let response;
|
|
112
|
+
try {
|
|
113
|
+
response = await fetchFn(
|
|
114
|
+
`${baseUrl}${derivativeStatusTarget(derivedScope)}`,
|
|
115
|
+
{
|
|
116
|
+
method: "GET",
|
|
117
|
+
headers,
|
|
118
|
+
...params.signal ? { signal: params.signal } : {}
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
throw new WriteTransportError(
|
|
123
|
+
`Derivative status read failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
124
|
+
1,
|
|
125
|
+
err
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
throw await personalServerErrorFromQuestionResponse(
|
|
130
|
+
response
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
let body;
|
|
134
|
+
try {
|
|
135
|
+
body = await response.json();
|
|
136
|
+
} catch (err) {
|
|
137
|
+
throw new DerivativeQuestionRejectedError(
|
|
138
|
+
"Derivative status response is not JSON",
|
|
139
|
+
response.status,
|
|
140
|
+
null,
|
|
141
|
+
{ cause: err instanceof Error ? err.message : String(err) }
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
const parsed = DerivativeStatusSchema.safeParse(body);
|
|
145
|
+
if (!parsed.success) {
|
|
146
|
+
throw new DerivativeQuestionRejectedError(
|
|
147
|
+
"Derivative status response is not a status view",
|
|
148
|
+
response.status,
|
|
149
|
+
null,
|
|
150
|
+
{ issues: parsed.error.issues }
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return parsed.data;
|
|
154
|
+
}
|
|
155
|
+
async function waitForDerivativeStatus(params) {
|
|
156
|
+
const timeoutMs = Math.max(
|
|
157
|
+
0,
|
|
158
|
+
params.timeoutMs ?? DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS
|
|
159
|
+
);
|
|
160
|
+
const pollIntervalMs = Math.max(
|
|
161
|
+
0,
|
|
162
|
+
params.pollIntervalMs ?? DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS
|
|
163
|
+
);
|
|
164
|
+
const deadline = Date.now() + timeoutMs;
|
|
165
|
+
for (; ; ) {
|
|
166
|
+
if (params.signal?.aborted) throw abortError(params.signal);
|
|
167
|
+
const latest = await getDerivativeStatus(params);
|
|
168
|
+
if (isDerivativeStatusSettled(latest)) return latest;
|
|
169
|
+
const remaining = deadline - Date.now();
|
|
170
|
+
if (remaining <= 0) throw timeoutError(latest, timeoutMs);
|
|
171
|
+
const waitMs = latest.retryAfterSeconds === null ? pollIntervalMs : latest.retryAfterSeconds * 1e3;
|
|
172
|
+
if (waitMs > remaining) {
|
|
173
|
+
throw timeoutError(latest, timeoutMs);
|
|
174
|
+
}
|
|
175
|
+
await sleep(waitMs, params.signal);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
export {
|
|
179
|
+
DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS,
|
|
180
|
+
DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS,
|
|
181
|
+
DERIVATIVE_ERROR_CODES,
|
|
182
|
+
DERIVATIVE_STATUS_PATH,
|
|
183
|
+
DerivativeErrorCodeSchema2 as DerivativeErrorCodeSchema,
|
|
184
|
+
DerivativeStatusSchema,
|
|
185
|
+
derivativeStatusTarget,
|
|
186
|
+
getDerivativeStatus,
|
|
187
|
+
isDerivativeStatusSettled,
|
|
188
|
+
waitForDerivativeStatus
|
|
189
|
+
};
|
|
190
|
+
//# sourceMappingURL=derivative-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/derivative-status.ts"],"sourcesContent":["/**\n * Derivative status: the lifecycle of the question behind a derived scope,\n * as the party that READS the answer sees it.\n *\n * @remarks\n * A builder registers a question with {@link registerQuestion} and follows it\n * with {@link waitForQuestion}, both of which need a write session. The app\n * that only consumes the answer holds no write entry at all — a consent flow\n * grants it a bare read on the derived scope — so it cannot open one, and\n * `GET /v1/data/<derivedScope>` answers 404 for all three of \"computing right\n * now\", \"failed but retrying\" and \"failed for good\".\n *\n * `GET /v1/derivatives/status?derivedScope=<scope>` is that reader's view.\n * Authorization is the data read's (a live grant covering the derived scope,\n * or the owner), nothing is served and nothing is charged, and the view is\n * deliberately narrow: lifecycle, a coarse {@link DerivativeErrorCode} and\n * the next retry. The question text, the source scopes, the question id, the\n * registrar and the server's raw error string stay owner-only.\n *\n * Requires `personal-server-ts` with the status route; an older Personal\n * Server answers 404 for the route itself.\n *\n * @category Protocol\n */\n\nimport { z } from \"zod\";\nimport { buildWeb3SignedHeader } from \"../auth/web3-signed-builder\";\nimport {\n DerivativeQuestionRejectedError,\n DerivativeQuestionTimeoutError,\n WriteRequestError,\n WriteTransportError,\n type PersonalServerWriteError,\n} from \"../errors\";\nimport {\n DerivativeErrorCodeSchema,\n personalServerErrorFromQuestionResponse,\n QuestionStatusSchema,\n type QuestionStatus,\n} from \"./derivative-questions\";\nimport {\n resolveWriteSigner,\n type ResolveWriteSignerOptions,\n type WriteSignerSource,\n} from \"./write-signer\";\n\nexport {\n DERIVATIVE_ERROR_CODES,\n DerivativeErrorCodeSchema,\n type DerivativeErrorCode,\n} from \"./derivative-questions\";\n\n/** The reader-facing status route. */\nexport const DERIVATIVE_STATUS_PATH = \"/v1/derivatives/status\";\n\n/** How long {@link waitForDerivativeStatus} polls before giving up. */\nexport const DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS = 120_000;\n\n/**\n * How long {@link waitForDerivativeStatus} waits between polls when the\n * server names no retry time of its own.\n */\nexport const DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS = 2_000;\n\nconst nullable = <T extends z.ZodTypeAny>(schema: T) =>\n schema\n .nullish()\n .transform((value: z.infer<T> | null | undefined) => value ?? null);\n\n/**\n * The status of the derived scope, not of one registration: when several\n * questions write the same scope, the server reports the most optimistic\n * true state, because serving data is registration-agnostic.\n */\nexport const DerivativeStatusSchema = z.object({\n derivedScope: z.string().min(1),\n status: QuestionStatusSchema,\n /** When the last compute finished, or `null` if none ever has. */\n lastComputedAt: nullable(z.string()),\n /** Local version of the derived record the last compute wrote. */\n derivedVersion: nullable(z.number()),\n derivedCollectedAt: nullable(z.string()),\n /** The failure class; `null` unless `status` is `failed`. */\n errorCode: nullable(DerivativeErrorCodeSchema),\n /**\n * Seconds until the Personal Server's next automatic retry, or `null` when\n * none is pending or running — the terminal signature. Poll on this cadence\n * rather than guessing one.\n */\n retryAfterSeconds: nullable(z.number()),\n});\n\n/** @see {@link DerivativeStatusSchema} */\nexport type DerivativeStatus = z.infer<typeof DerivativeStatusSchema>;\n\n/** What {@link getDerivativeStatus} needs to sign and send one read. */\nexport interface GetDerivativeStatusParams extends ResolveWriteSignerOptions {\n /** Personal Server origin, e.g. `https://ps.example.com`. */\n personalServerUrl: string;\n /** The derived scope whose question to observe. */\n derivedScope: string;\n /**\n * A grant covering the derived scope, sent as the signed `grantId` claim.\n * Omit only when the signer is the Personal Server's owner, who is\n * authorized without one.\n */\n grantId?: string;\n /** Reader key: a viem `LocalAccount`, `WalletClient`, or `{ signMessage }`. */\n signer: WriteSignerSource;\n /** Web3Signed audience; defaults to `personalServerUrl`. */\n audience?: string;\n /** `fetch` to use; defaults to `globalThis.fetch`. */\n fetch?: typeof fetch;\n /** Extra request headers. */\n headers?: HeadersInit;\n /** Aborts the request in flight. */\n signal?: AbortSignal;\n}\n\n/** What {@link waitForDerivativeStatus} polls with. */\nexport interface WaitForDerivativeStatusParams extends GetDerivativeStatusParams {\n /** Give up after this long (default 120s). */\n timeoutMs?: number;\n /**\n * Wait between polls when the server names no retry time (default 2s).\n * A `retryAfterSeconds` from the server replaces this outright, longer or\n * shorter: it is when the next compute actually happens.\n */\n pollIntervalMs?: number;\n /**\n * Aborts the wait, and the request in flight with it: the signal is passed\n * to every poll, so an abort during a stalled request does not sit until\n * the transport gives up.\n */\n signal?: AbortSignal;\n}\n\n/**\n * The request target for a status read: the query carries the derived scope,\n * the signed `uri` does not.\n *\n * @remarks\n * Like every Web3Signed read (data, lineage), the Personal Server verifies\n * the signature over the PATH; per-scope authorization is enforced live\n * against the caller's grant on each request, so the query needs no\n * signature to be safe. Only the write path signs path AND query, where a\n * parameter decides what is written.\n */\nexport function derivativeStatusTarget(derivedScope: string): string {\n return `${DERIVATIVE_STATUS_PATH}?derivedScope=${encodeURIComponent(derivedScope)}`;\n}\n\nfunction normalizeBaseUrl(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n\nfunction resolveFetch(fetchFn: typeof fetch | undefined): typeof fetch {\n const resolved = fetchFn ?? globalThis.fetch;\n if (resolved === undefined) {\n throw new WriteRequestError(\"No fetch implementation available\");\n }\n return resolved;\n}\n\nfunction requireDerivedScope(derivedScope: string): string {\n if (typeof derivedScope !== \"string\" || derivedScope.length === 0) {\n // The server answers 400 DERIVATIVE_DERIVED_SCOPE_REQUIRED; refuse before\n // signing rather than spend a signature on a request that cannot pass.\n throw new WriteRequestError(\"derivedScope is required\");\n }\n return derivedScope;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(abortError(signal));\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction timeoutError(\n latest: DerivativeStatus,\n timeoutMs: number,\n): DerivativeQuestionTimeoutError {\n return new DerivativeQuestionTimeoutError(\n `Derived scope ${latest.derivedScope} was still ${latest.status} after ${timeoutMs}ms`,\n {\n derivedScope: latest.derivedScope,\n status: latest.status,\n errorCode: latest.errorCode,\n retryAfterSeconds: latest.retryAfterSeconds,\n timeoutMs,\n },\n );\n}\n\nfunction abortError(signal?: AbortSignal): Error {\n const reason = signal?.reason;\n return reason instanceof Error\n ? reason\n : new WriteRequestError(\"Derivative status wait was aborted\");\n}\n\n/**\n * Is this a state the reader can act on?\n *\n * @remarks\n * `ready` means the derived scope has an answer to read. A `failed` status\n * is settled only when no retry is pending: with `retryAfterSeconds` set the\n * Personal Server will compute again on its own, so the answer may still\n * arrive. `pending` and `stale` are always in flight.\n */\nexport function isDerivativeStatusSettled(status: DerivativeStatus): boolean {\n if (status.status === \"ready\") return true;\n return status.status === \"failed\" && status.retryAfterSeconds === null;\n}\n\n/**\n * Read the lifecycle of the question behind a derived scope.\n *\n * @remarks\n * Sends `GET /v1/derivatives/status?derivedScope=<scope>` with a Web3Signed\n * `Authorization` header carrying `grantId`, the same authentication a data\n * read uses. Nothing is charged: the route authorizes, it does not serve\n * data, so a priced grant raises no 402 here.\n *\n * @returns The status of the derived scope. When several registrations write\n * it, the most optimistic true state answers — `ready`, then `stale`, then\n * `pending`, then `failed` — because a duplicate that never wrote anything\n * must not report away an answer the scope has.\n * @throws {DerivativeQuestionNotFoundError} 404: the caller may read the\n * scope but no question stands behind it (and, on an older Personal\n * Server, the route itself is unknown).\n * @throws {WriteForbiddenError} 403: the grant does not cover the derived\n * scope. The check runs before any store lookup, so a caller cannot probe\n * which scopes have questions.\n * @throws {DerivativeQuestionRejectedError} On any other non-2xx answer or\n * an unparseable body.\n * @throws {WriteTransportError} When `fetch` itself failed.\n * @throws {WriteRequestError} On a missing `derivedScope` or no `fetch`.\n *\n * @example\n * ```typescript\n * const status = await getDerivativeStatus({\n * personalServerUrl: \"https://ps.example.com\",\n * derivedScope: \"coach.weekly\",\n * grantId,\n * signer,\n * });\n * if (status.status === \"ready\") {\n * const record = await readPersonalServerData({ ... });\n * } else if (status.retryAfterSeconds !== null) {\n * // Computing or retrying: come back then.\n * }\n * ```\n */\nexport async function getDerivativeStatus(\n params: GetDerivativeStatusParams,\n): Promise<DerivativeStatus> {\n const derivedScope = requireDerivedScope(params.derivedScope);\n const fetchFn = resolveFetch(params.fetch);\n const baseUrl = normalizeBaseUrl(params.personalServerUrl);\n const signer = resolveWriteSigner(params.signer, { account: params.account });\n const headers = new Headers(params.headers);\n headers.set(\n \"Authorization\",\n await buildWeb3SignedHeader({\n signMessage: signer.signMessage,\n aud: params.audience ?? baseUrl,\n method: \"GET\",\n uri: DERIVATIVE_STATUS_PATH,\n grantId: params.grantId,\n }),\n );\n\n let response: Response;\n try {\n response = await fetchFn(\n `${baseUrl}${derivativeStatusTarget(derivedScope)}`,\n {\n method: \"GET\",\n headers,\n ...(params.signal ? { signal: params.signal } : {}),\n },\n );\n } catch (err) {\n throw new WriteTransportError(\n `Derivative status read failed: ${err instanceof Error ? err.message : String(err)}`,\n 1,\n err,\n );\n }\n if (!response.ok) {\n throw (await personalServerErrorFromQuestionResponse(\n response,\n )) as PersonalServerWriteError;\n }\n let body: unknown;\n try {\n body = await response.json();\n } catch (err) {\n throw new DerivativeQuestionRejectedError(\n \"Derivative status response is not JSON\",\n response.status,\n null,\n { cause: err instanceof Error ? err.message : String(err) },\n );\n }\n const parsed = DerivativeStatusSchema.safeParse(body);\n if (!parsed.success) {\n throw new DerivativeQuestionRejectedError(\n \"Derivative status response is not a status view\",\n response.status,\n null,\n { issues: parsed.error.issues },\n );\n }\n return parsed.data;\n}\n\n/**\n * Poll {@link getDerivativeStatus} until the derived scope has an answer or\n * has stopped trying to get one.\n *\n * @remarks\n * Returns as soon as {@link isDerivativeStatusSettled} holds: `ready`, or\n * `failed` with no retry pending. A failure the server will retry is not a\n * result, so the wait continues through it — on the server's own cadence,\n * because `retryAfterSeconds` is when the next compute actually happens and\n * polling faster only spends requests. A failed status is returned, not\n * thrown: the reader branches on `errorCode`.\n *\n * @returns The settled status.\n * @throws {DerivativeQuestionTimeoutError} When the budget ran out first.\n * The question keeps computing on the server; call again.\n *\n * @example\n * ```typescript\n * const status = await waitForDerivativeStatus({\n * personalServerUrl,\n * derivedScope: \"coach.weekly\",\n * grantId,\n * signer,\n * timeoutMs: 60_000,\n * });\n * if (status.status !== \"ready\") console.log(status.errorCode);\n * ```\n */\nexport async function waitForDerivativeStatus(\n params: WaitForDerivativeStatusParams,\n): Promise<DerivativeStatus> {\n const timeoutMs = Math.max(\n 0,\n params.timeoutMs ?? DEFAULT_DERIVATIVE_STATUS_TIMEOUT_MS,\n );\n const pollIntervalMs = Math.max(\n 0,\n params.pollIntervalMs ?? DEFAULT_DERIVATIVE_STATUS_POLL_INTERVAL_MS,\n );\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n if (params.signal?.aborted) throw abortError(params.signal);\n const latest = await getDerivativeStatus(params);\n if (isDerivativeStatusSettled(latest)) return latest;\n const remaining = deadline - Date.now();\n if (remaining <= 0) throw timeoutError(latest, timeoutMs);\n // The server's scheduled retry decides the cadence outright, in both\n // directions: a caller's longer pollIntervalMs would sit past a retry\n // that has already produced an answer, and a shorter one would ask\n // before anything can have changed. pollIntervalMs is the cadence for\n // the case where the server named none.\n const waitMs =\n latest.retryAfterSeconds === null\n ? pollIntervalMs\n : latest.retryAfterSeconds * 1000;\n if (waitMs > remaining) {\n // The budget cannot cover the next cadence, so the poll after this\n // sleep would land before anything could have changed. Give up now\n // instead of spending a request to say the same thing.\n throw timeoutError(latest, timeoutMs);\n }\n await sleep(waitMs, params.signal);\n }\n}\n\n/** Statuses that mean a compute is in flight. @see {@link QuestionStatus} */\nexport type PendingDerivativeStatus = Extract<\n QuestionStatus,\n \"pending\" | \"stale\"\n>;\n"],"mappings":"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","names":["DerivativeErrorCodeSchema"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/server.cjs
CHANGED
|
@@ -55,7 +55,8 @@ __export(server_exports, {
|
|
|
55
55
|
scopeMatchesPattern: () => import_scopes.scopeMatchesPattern,
|
|
56
56
|
toDirectFeeBreakdown: () => import_escrow_payment.toDirectFeeBreakdown,
|
|
57
57
|
toDirectPaymentReceipt: () => import_escrow_payment.toDirectPaymentReceipt,
|
|
58
|
-
tryGrantPermissions: () => import_scope_actions.tryGrantPermissions
|
|
58
|
+
tryGrantPermissions: () => import_scope_actions.tryGrantPermissions,
|
|
59
|
+
validateAccessRequestQuestions: () => import_access_request_client.validateAccessRequestQuestions
|
|
59
60
|
});
|
|
60
61
|
module.exports = __toCommonJS(server_exports);
|
|
61
62
|
var import_controller = require("./direct/controller");
|
|
@@ -106,6 +107,7 @@ var import_types = require("./direct/types");
|
|
|
106
107
|
scopeMatchesPattern,
|
|
107
108
|
toDirectFeeBreakdown,
|
|
108
109
|
toDirectPaymentReceipt,
|
|
109
|
-
tryGrantPermissions
|
|
110
|
+
tryGrantPermissions,
|
|
111
|
+
validateAccessRequestQuestions
|
|
110
112
|
});
|
|
111
113
|
//# sourceMappingURL=server.cjs.map
|
package/dist/server.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server entry point for the Vana SDK direct Data Portability flow.\n *\n * @remarks\n * Exposes {@link createDirectDataController} and its supporting types/errors.\n * This is a Node/server entry point — it owns the app private key and must never\n * be imported into browser code.\n *\n * @example\n * ```typescript\n * import { createDirectDataController } from \"@opendatalabs/vana-sdk/server\";\n *\n * export const vana = createDirectDataController({\n * env: process.env.VANA_ENV === \"dev\" ? \"dev\" : \"production\",\n * appPrivateKey: process.env.VANA_APP_PRIVATE_KEY!,\n * app: { id: \"notes-lens\", name: \"Notes Lens\", homepageUrl: process.env.VANA_APP_URL! },\n * source: \"icloud_notes\",\n * scopes: [\"icloud_notes.notes\"],\n * });\n * ```\n *\n * @category Direct\n * @module server\n */\n\nexport {\n createDirectDataController,\n type DirectDataController,\n type DirectDataControllerConfig,\n type DirectEscrowConfig,\n} from \"./direct/controller\";\n\n// Lower-level building blocks (advanced use / custom transports).\nexport {\n createDefaultAccessRequestClient,\n buildApprovalUrl,\n type DefaultAccessRequestClientOptions,\n type FetchLike,\n} from \"./direct/access-request-client\";\nexport {\n buildPersonalServerDataReadRequest,\n readPersonalServerData,\n parsePersonalServerPaymentRequired,\n dataPathForScope,\n type PersonalServerDataReadRequest,\n type PersonalServerReadResult,\n type PersonalServerFetch,\n type PersonalServerTransportRetryOptions,\n type FetchResponseLike,\n} from \"./direct/personal-server-read\";\n// Escrow-backed payment (built on protocol/escrow).\nexport {\n authorizeEscrowPayment,\n authorizeGrantPayment,\n buildEscrowPaymentHeader,\n buildGrantPaymentHeader,\n paymentResponseMetadataFromHeader,\n toDirectPaymentReceipt,\n toDirectFeeBreakdown,\n createDefaultNonceSource,\n DATA_ACCESS_OP_TYPE,\n GRANT_OP_TYPE,\n type EscrowPaymentConfig,\n type EscrowPaymentHeaderConfig,\n type SignTypedDataFn,\n type PaymentNonceSource,\n} from \"./direct/escrow-payment\";\nexport {\n getDirectEndpoints,\n PRODUCTION_ENDPOINTS,\n DEV_ENDPOINTS,\n} from \"./direct/endpoints\";\n// Grant scope entries: the `[operation:]scope` vocabulary the controller's\n// `scopes` are written in, so a backend can build and read them without\n// reaching for a platform entry point.\nexport {\n ScopeSchema,\n parseScope,\n scopeMatchesPattern,\n scopeCoveredByGrant,\n type Scope,\n type ParsedScope,\n} from \"./protocol/scopes\";\nexport {\n SCOPE_ACTIONS,\n InvalidScopeEntryError,\n parseScopeEntry,\n formatScopeEntry,\n grantPermissions,\n permissionsToScopes,\n tryGrantPermissions,\n hasAction,\n type ScopeAction,\n type ParsedScopeEntry,\n type GrantPermission,\n} from \"./protocol/scope-actions\";\n\n// Errors\nexport {\n DirectConfigError,\n AccessNotApprovedError,\n ScopeNotApprovedError,\n PersonalServerReadError,\n PaymentRequiredError,\n} from \"./direct/errors\";\n\n// Shared types\nexport type {\n DirectEnv,\n DirectNetwork,\n DirectAppConfig,\n ForegroundDelivery,\n AppIdentity,\n DirectServiceEndpoints,\n AccessRequest,\n AccessRequestStatus,\n AccessRequestStatusValue,\n ApprovedDataResult,\n MultiScopeDataResult,\n AccessRequestClient,\n DirectOpTypeValue,\n PersonalServerDataAccessPaymentOperation,\n PersonalServerGrantPaymentOperation,\n PersonalServerPaymentOperation,\n PersonalServerPaymentRequired,\n DirectPaymentReceipt,\n DirectPaymentResponseMetadata,\n DirectFeeBreakdown,\n} from \"./direct/types\";\n\n// Op-type vocabulary constant.\nexport { DirectOpType } from \"./direct/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBA,wBAKO;AAGP,
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server entry point for the Vana SDK direct Data Portability flow.\n *\n * @remarks\n * Exposes {@link createDirectDataController} and its supporting types/errors.\n * This is a Node/server entry point — it owns the app private key and must never\n * be imported into browser code.\n *\n * @example\n * ```typescript\n * import { createDirectDataController } from \"@opendatalabs/vana-sdk/server\";\n *\n * export const vana = createDirectDataController({\n * env: process.env.VANA_ENV === \"dev\" ? \"dev\" : \"production\",\n * appPrivateKey: process.env.VANA_APP_PRIVATE_KEY!,\n * app: { id: \"notes-lens\", name: \"Notes Lens\", homepageUrl: process.env.VANA_APP_URL! },\n * source: \"icloud_notes\",\n * scopes: [\"icloud_notes.notes\"],\n * });\n * ```\n *\n * @category Direct\n * @module server\n */\n\nexport {\n createDirectDataController,\n type DirectDataController,\n type DirectDataControllerConfig,\n type DirectEscrowConfig,\n} from \"./direct/controller\";\n\n// Lower-level building blocks (advanced use / custom transports).\nexport {\n createDefaultAccessRequestClient,\n buildApprovalUrl,\n validateAccessRequestQuestions,\n type DefaultAccessRequestClientOptions,\n type FetchLike,\n} from \"./direct/access-request-client\";\nexport {\n buildPersonalServerDataReadRequest,\n readPersonalServerData,\n parsePersonalServerPaymentRequired,\n dataPathForScope,\n type PersonalServerDataReadRequest,\n type PersonalServerReadResult,\n type PersonalServerFetch,\n type PersonalServerTransportRetryOptions,\n type FetchResponseLike,\n} from \"./direct/personal-server-read\";\n// Escrow-backed payment (built on protocol/escrow).\nexport {\n authorizeEscrowPayment,\n authorizeGrantPayment,\n buildEscrowPaymentHeader,\n buildGrantPaymentHeader,\n paymentResponseMetadataFromHeader,\n toDirectPaymentReceipt,\n toDirectFeeBreakdown,\n createDefaultNonceSource,\n DATA_ACCESS_OP_TYPE,\n GRANT_OP_TYPE,\n type EscrowPaymentConfig,\n type EscrowPaymentHeaderConfig,\n type SignTypedDataFn,\n type PaymentNonceSource,\n} from \"./direct/escrow-payment\";\nexport {\n getDirectEndpoints,\n PRODUCTION_ENDPOINTS,\n DEV_ENDPOINTS,\n} from \"./direct/endpoints\";\n// Grant scope entries: the `[operation:]scope` vocabulary the controller's\n// `scopes` are written in, so a backend can build and read them without\n// reaching for a platform entry point.\nexport {\n ScopeSchema,\n parseScope,\n scopeMatchesPattern,\n scopeCoveredByGrant,\n type Scope,\n type ParsedScope,\n} from \"./protocol/scopes\";\nexport {\n SCOPE_ACTIONS,\n InvalidScopeEntryError,\n parseScopeEntry,\n formatScopeEntry,\n grantPermissions,\n permissionsToScopes,\n tryGrantPermissions,\n hasAction,\n type ScopeAction,\n type ParsedScopeEntry,\n type GrantPermission,\n} from \"./protocol/scope-actions\";\n\n// Errors\nexport {\n DirectConfigError,\n AccessNotApprovedError,\n ScopeNotApprovedError,\n PersonalServerReadError,\n PaymentRequiredError,\n} from \"./direct/errors\";\n\n// Shared types\nexport type {\n DirectEnv,\n DirectNetwork,\n DirectAppConfig,\n ForegroundDelivery,\n AppIdentity,\n DirectServiceEndpoints,\n AccessRequest,\n AccessRequestQuestion,\n AccessRequestStatus,\n AccessRequestStatusValue,\n ApprovedDataResult,\n MultiScopeDataResult,\n AccessRequestClient,\n DirectOpTypeValue,\n PersonalServerDataAccessPaymentOperation,\n PersonalServerGrantPaymentOperation,\n PersonalServerPaymentOperation,\n PersonalServerPaymentRequired,\n DirectPaymentReceipt,\n DirectPaymentResponseMetadata,\n DirectFeeBreakdown,\n} from \"./direct/types\";\n\n// Op-type vocabulary constant.\nexport { DirectOpType } from \"./direct/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBA,wBAKO;AAGP,mCAMO;AACP,kCAUO;AAEP,4BAeO;AACP,uBAIO;AAIP,oBAOO;AACP,2BAYO;AAGP,oBAMO;AA4BP,mBAA6B;","names":[]}
|
package/dist/server.d.ts
CHANGED
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
* @module server
|
|
24
24
|
*/
|
|
25
25
|
export { createDirectDataController, type DirectDataController, type DirectDataControllerConfig, type DirectEscrowConfig, } from "./direct/controller.js";
|
|
26
|
-
export { createDefaultAccessRequestClient, buildApprovalUrl, type DefaultAccessRequestClientOptions, type FetchLike, } from "./direct/access-request-client.js";
|
|
26
|
+
export { createDefaultAccessRequestClient, buildApprovalUrl, validateAccessRequestQuestions, type DefaultAccessRequestClientOptions, type FetchLike, } from "./direct/access-request-client.js";
|
|
27
27
|
export { buildPersonalServerDataReadRequest, readPersonalServerData, parsePersonalServerPaymentRequired, dataPathForScope, type PersonalServerDataReadRequest, type PersonalServerReadResult, type PersonalServerFetch, type PersonalServerTransportRetryOptions, type FetchResponseLike, } from "./direct/personal-server-read.js";
|
|
28
28
|
export { authorizeEscrowPayment, authorizeGrantPayment, buildEscrowPaymentHeader, buildGrantPaymentHeader, paymentResponseMetadataFromHeader, toDirectPaymentReceipt, toDirectFeeBreakdown, createDefaultNonceSource, DATA_ACCESS_OP_TYPE, GRANT_OP_TYPE, type EscrowPaymentConfig, type EscrowPaymentHeaderConfig, type SignTypedDataFn, type PaymentNonceSource, } from "./direct/escrow-payment.js";
|
|
29
29
|
export { getDirectEndpoints, PRODUCTION_ENDPOINTS, DEV_ENDPOINTS, } from "./direct/endpoints.js";
|
|
30
30
|
export { ScopeSchema, parseScope, scopeMatchesPattern, scopeCoveredByGrant, type Scope, type ParsedScope, } from "./protocol/scopes.js";
|
|
31
31
|
export { SCOPE_ACTIONS, InvalidScopeEntryError, parseScopeEntry, formatScopeEntry, grantPermissions, permissionsToScopes, tryGrantPermissions, hasAction, type ScopeAction, type ParsedScopeEntry, type GrantPermission, } from "./protocol/scope-actions.js";
|
|
32
32
|
export { DirectConfigError, AccessNotApprovedError, ScopeNotApprovedError, PersonalServerReadError, PaymentRequiredError, } from "./direct/errors.js";
|
|
33
|
-
export type { DirectEnv, DirectNetwork, DirectAppConfig, ForegroundDelivery, AppIdentity, DirectServiceEndpoints, AccessRequest, AccessRequestStatus, AccessRequestStatusValue, ApprovedDataResult, MultiScopeDataResult, AccessRequestClient, DirectOpTypeValue, PersonalServerDataAccessPaymentOperation, PersonalServerGrantPaymentOperation, PersonalServerPaymentOperation, PersonalServerPaymentRequired, DirectPaymentReceipt, DirectPaymentResponseMetadata, DirectFeeBreakdown, } from "./direct/types.js";
|
|
33
|
+
export type { DirectEnv, DirectNetwork, DirectAppConfig, ForegroundDelivery, AppIdentity, DirectServiceEndpoints, AccessRequest, AccessRequestQuestion, AccessRequestStatus, AccessRequestStatusValue, ApprovedDataResult, MultiScopeDataResult, AccessRequestClient, DirectOpTypeValue, PersonalServerDataAccessPaymentOperation, PersonalServerGrantPaymentOperation, PersonalServerPaymentOperation, PersonalServerPaymentRequired, DirectPaymentReceipt, DirectPaymentResponseMetadata, DirectFeeBreakdown, } from "./direct/types.js";
|
|
34
34
|
export { DirectOpType } from "./direct/types.js";
|
package/dist/server.js
CHANGED
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
} from "./direct/controller.js";
|
|
4
4
|
import {
|
|
5
5
|
createDefaultAccessRequestClient,
|
|
6
|
-
buildApprovalUrl
|
|
6
|
+
buildApprovalUrl,
|
|
7
|
+
validateAccessRequestQuestions
|
|
7
8
|
} from "./direct/access-request-client.js";
|
|
8
9
|
import {
|
|
9
10
|
buildPersonalServerDataReadRequest,
|
|
@@ -90,6 +91,7 @@ export {
|
|
|
90
91
|
scopeMatchesPattern,
|
|
91
92
|
toDirectFeeBreakdown,
|
|
92
93
|
toDirectPaymentReceipt,
|
|
93
|
-
tryGrantPermissions
|
|
94
|
+
tryGrantPermissions,
|
|
95
|
+
validateAccessRequestQuestions
|
|
94
96
|
};
|
|
95
97
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server entry point for the Vana SDK direct Data Portability flow.\n *\n * @remarks\n * Exposes {@link createDirectDataController} and its supporting types/errors.\n * This is a Node/server entry point — it owns the app private key and must never\n * be imported into browser code.\n *\n * @example\n * ```typescript\n * import { createDirectDataController } from \"@opendatalabs/vana-sdk/server\";\n *\n * export const vana = createDirectDataController({\n * env: process.env.VANA_ENV === \"dev\" ? \"dev\" : \"production\",\n * appPrivateKey: process.env.VANA_APP_PRIVATE_KEY!,\n * app: { id: \"notes-lens\", name: \"Notes Lens\", homepageUrl: process.env.VANA_APP_URL! },\n * source: \"icloud_notes\",\n * scopes: [\"icloud_notes.notes\"],\n * });\n * ```\n *\n * @category Direct\n * @module server\n */\n\nexport {\n createDirectDataController,\n type DirectDataController,\n type DirectDataControllerConfig,\n type DirectEscrowConfig,\n} from \"./direct/controller\";\n\n// Lower-level building blocks (advanced use / custom transports).\nexport {\n createDefaultAccessRequestClient,\n buildApprovalUrl,\n type DefaultAccessRequestClientOptions,\n type FetchLike,\n} from \"./direct/access-request-client\";\nexport {\n buildPersonalServerDataReadRequest,\n readPersonalServerData,\n parsePersonalServerPaymentRequired,\n dataPathForScope,\n type PersonalServerDataReadRequest,\n type PersonalServerReadResult,\n type PersonalServerFetch,\n type PersonalServerTransportRetryOptions,\n type FetchResponseLike,\n} from \"./direct/personal-server-read\";\n// Escrow-backed payment (built on protocol/escrow).\nexport {\n authorizeEscrowPayment,\n authorizeGrantPayment,\n buildEscrowPaymentHeader,\n buildGrantPaymentHeader,\n paymentResponseMetadataFromHeader,\n toDirectPaymentReceipt,\n toDirectFeeBreakdown,\n createDefaultNonceSource,\n DATA_ACCESS_OP_TYPE,\n GRANT_OP_TYPE,\n type EscrowPaymentConfig,\n type EscrowPaymentHeaderConfig,\n type SignTypedDataFn,\n type PaymentNonceSource,\n} from \"./direct/escrow-payment\";\nexport {\n getDirectEndpoints,\n PRODUCTION_ENDPOINTS,\n DEV_ENDPOINTS,\n} from \"./direct/endpoints\";\n// Grant scope entries: the `[operation:]scope` vocabulary the controller's\n// `scopes` are written in, so a backend can build and read them without\n// reaching for a platform entry point.\nexport {\n ScopeSchema,\n parseScope,\n scopeMatchesPattern,\n scopeCoveredByGrant,\n type Scope,\n type ParsedScope,\n} from \"./protocol/scopes\";\nexport {\n SCOPE_ACTIONS,\n InvalidScopeEntryError,\n parseScopeEntry,\n formatScopeEntry,\n grantPermissions,\n permissionsToScopes,\n tryGrantPermissions,\n hasAction,\n type ScopeAction,\n type ParsedScopeEntry,\n type GrantPermission,\n} from \"./protocol/scope-actions\";\n\n// Errors\nexport {\n DirectConfigError,\n AccessNotApprovedError,\n ScopeNotApprovedError,\n PersonalServerReadError,\n PaymentRequiredError,\n} from \"./direct/errors\";\n\n// Shared types\nexport type {\n DirectEnv,\n DirectNetwork,\n DirectAppConfig,\n ForegroundDelivery,\n AppIdentity,\n DirectServiceEndpoints,\n AccessRequest,\n AccessRequestStatus,\n AccessRequestStatusValue,\n ApprovedDataResult,\n MultiScopeDataResult,\n AccessRequestClient,\n DirectOpTypeValue,\n PersonalServerDataAccessPaymentOperation,\n PersonalServerGrantPaymentOperation,\n PersonalServerPaymentOperation,\n PersonalServerPaymentRequired,\n DirectPaymentReceipt,\n DirectPaymentResponseMetadata,\n DirectFeeBreakdown,\n} from \"./direct/types\";\n\n// Op-type vocabulary constant.\nexport { DirectOpType } from \"./direct/types\";\n"],"mappings":"AAyBA;AAAA,EACE;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server entry point for the Vana SDK direct Data Portability flow.\n *\n * @remarks\n * Exposes {@link createDirectDataController} and its supporting types/errors.\n * This is a Node/server entry point — it owns the app private key and must never\n * be imported into browser code.\n *\n * @example\n * ```typescript\n * import { createDirectDataController } from \"@opendatalabs/vana-sdk/server\";\n *\n * export const vana = createDirectDataController({\n * env: process.env.VANA_ENV === \"dev\" ? \"dev\" : \"production\",\n * appPrivateKey: process.env.VANA_APP_PRIVATE_KEY!,\n * app: { id: \"notes-lens\", name: \"Notes Lens\", homepageUrl: process.env.VANA_APP_URL! },\n * source: \"icloud_notes\",\n * scopes: [\"icloud_notes.notes\"],\n * });\n * ```\n *\n * @category Direct\n * @module server\n */\n\nexport {\n createDirectDataController,\n type DirectDataController,\n type DirectDataControllerConfig,\n type DirectEscrowConfig,\n} from \"./direct/controller\";\n\n// Lower-level building blocks (advanced use / custom transports).\nexport {\n createDefaultAccessRequestClient,\n buildApprovalUrl,\n validateAccessRequestQuestions,\n type DefaultAccessRequestClientOptions,\n type FetchLike,\n} from \"./direct/access-request-client\";\nexport {\n buildPersonalServerDataReadRequest,\n readPersonalServerData,\n parsePersonalServerPaymentRequired,\n dataPathForScope,\n type PersonalServerDataReadRequest,\n type PersonalServerReadResult,\n type PersonalServerFetch,\n type PersonalServerTransportRetryOptions,\n type FetchResponseLike,\n} from \"./direct/personal-server-read\";\n// Escrow-backed payment (built on protocol/escrow).\nexport {\n authorizeEscrowPayment,\n authorizeGrantPayment,\n buildEscrowPaymentHeader,\n buildGrantPaymentHeader,\n paymentResponseMetadataFromHeader,\n toDirectPaymentReceipt,\n toDirectFeeBreakdown,\n createDefaultNonceSource,\n DATA_ACCESS_OP_TYPE,\n GRANT_OP_TYPE,\n type EscrowPaymentConfig,\n type EscrowPaymentHeaderConfig,\n type SignTypedDataFn,\n type PaymentNonceSource,\n} from \"./direct/escrow-payment\";\nexport {\n getDirectEndpoints,\n PRODUCTION_ENDPOINTS,\n DEV_ENDPOINTS,\n} from \"./direct/endpoints\";\n// Grant scope entries: the `[operation:]scope` vocabulary the controller's\n// `scopes` are written in, so a backend can build and read them without\n// reaching for a platform entry point.\nexport {\n ScopeSchema,\n parseScope,\n scopeMatchesPattern,\n scopeCoveredByGrant,\n type Scope,\n type ParsedScope,\n} from \"./protocol/scopes\";\nexport {\n SCOPE_ACTIONS,\n InvalidScopeEntryError,\n parseScopeEntry,\n formatScopeEntry,\n grantPermissions,\n permissionsToScopes,\n tryGrantPermissions,\n hasAction,\n type ScopeAction,\n type ParsedScopeEntry,\n type GrantPermission,\n} from \"./protocol/scope-actions\";\n\n// Errors\nexport {\n DirectConfigError,\n AccessNotApprovedError,\n ScopeNotApprovedError,\n PersonalServerReadError,\n PaymentRequiredError,\n} from \"./direct/errors\";\n\n// Shared types\nexport type {\n DirectEnv,\n DirectNetwork,\n DirectAppConfig,\n ForegroundDelivery,\n AppIdentity,\n DirectServiceEndpoints,\n AccessRequest,\n AccessRequestQuestion,\n AccessRequestStatus,\n AccessRequestStatusValue,\n ApprovedDataResult,\n MultiScopeDataResult,\n AccessRequestClient,\n DirectOpTypeValue,\n PersonalServerDataAccessPaymentOperation,\n PersonalServerGrantPaymentOperation,\n PersonalServerPaymentOperation,\n PersonalServerPaymentRequired,\n DirectPaymentReceipt,\n DirectPaymentResponseMetadata,\n DirectFeeBreakdown,\n} from \"./direct/types\";\n\n// Op-type vocabulary constant.\nexport { DirectOpType } from \"./direct/types\";\n"],"mappings":"AAyBA;AAAA,EACE;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4BP,SAAS,oBAAoB;","names":[]}
|
|
@@ -84,6 +84,13 @@ export interface MockQuestion {
|
|
|
84
84
|
};
|
|
85
85
|
status: "pending" | "ready" | "failed" | "stale";
|
|
86
86
|
error: string | null;
|
|
87
|
+
/** The coarse failure class the status route serves; null unless failed. */
|
|
88
|
+
errorCode: "inference_unavailable" | "source_missing" | "grant_invalid" | "internal" | null;
|
|
89
|
+
/**
|
|
90
|
+
* What the status route reports as the next automatic retry. The mock has
|
|
91
|
+
* no scheduler, so a test sets it through `settleQuestion`.
|
|
92
|
+
*/
|
|
93
|
+
retryAfterSeconds: number | null;
|
|
87
94
|
createdAt: string;
|
|
88
95
|
updatedAt: string;
|
|
89
96
|
lastComputedAt: string | null;
|
|
@@ -126,6 +133,8 @@ export interface MockPersonalServer {
|
|
|
126
133
|
} | {
|
|
127
134
|
status: "failed";
|
|
128
135
|
error: string;
|
|
136
|
+
errorCode?: MockQuestion["errorCode"];
|
|
137
|
+
retryAfterSeconds?: number | null;
|
|
129
138
|
} | {
|
|
130
139
|
status: "stale" | "pending";
|
|
131
140
|
}): void;
|