@opendatalabs/connect 0.5.0 → 0.6.0-canary.e07e97e

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.
Files changed (68) hide show
  1. package/README.md +180 -51
  2. package/dist/core/constants.d.ts +32 -2
  3. package/dist/core/constants.d.ts.map +1 -1
  4. package/dist/core/constants.js +24 -2
  5. package/dist/core/constants.js.map +1 -1
  6. package/dist/core/errors.d.ts +43 -2
  7. package/dist/core/errors.d.ts.map +1 -1
  8. package/dist/core/errors.js +39 -0
  9. package/dist/core/errors.js.map +1 -1
  10. package/dist/core/grants.d.ts +19 -0
  11. package/dist/core/grants.d.ts.map +1 -0
  12. package/dist/core/grants.js +31 -0
  13. package/dist/core/grants.js.map +1 -0
  14. package/dist/core/index.d.ts +3 -2
  15. package/dist/core/index.d.ts.map +1 -1
  16. package/dist/core/index.js +3 -2
  17. package/dist/core/index.js.map +1 -1
  18. package/dist/core/types.d.ts +62 -1
  19. package/dist/core/types.d.ts.map +1 -1
  20. package/dist/react/ConnectButton.d.ts +16 -1
  21. package/dist/react/ConnectButton.d.ts.map +1 -1
  22. package/dist/react/ConnectButton.js +12 -5
  23. package/dist/react/ConnectButton.js.map +1 -1
  24. package/dist/react/index.d.ts +1 -0
  25. package/dist/react/index.d.ts.map +1 -1
  26. package/dist/react/index.js +1 -0
  27. package/dist/react/index.js.map +1 -1
  28. package/dist/react/useVanaConnect.d.ts +35 -2
  29. package/dist/react/useVanaConnect.d.ts.map +1 -1
  30. package/dist/react/useVanaConnect.js +36 -8
  31. package/dist/react/useVanaConnect.js.map +1 -1
  32. package/dist/react/useVanaData.d.ts +69 -0
  33. package/dist/react/useVanaData.d.ts.map +1 -0
  34. package/dist/react/useVanaData.js +131 -0
  35. package/dist/react/useVanaData.js.map +1 -0
  36. package/dist/server/config.d.ts +36 -0
  37. package/dist/server/config.d.ts.map +1 -0
  38. package/dist/server/config.js +44 -0
  39. package/dist/server/config.js.map +1 -0
  40. package/dist/server/connect.d.ts +40 -1
  41. package/dist/server/connect.d.ts.map +1 -1
  42. package/dist/server/connect.js +64 -6
  43. package/dist/server/connect.js.map +1 -1
  44. package/dist/server/data-client.d.ts +17 -0
  45. package/dist/server/data-client.d.ts.map +1 -1
  46. package/dist/server/data-client.js +24 -7
  47. package/dist/server/data-client.js.map +1 -1
  48. package/dist/server/index.d.ts +3 -1
  49. package/dist/server/index.d.ts.map +1 -1
  50. package/dist/server/index.js +3 -1
  51. package/dist/server/index.js.map +1 -1
  52. package/dist/server/manifest-signer.d.ts +22 -0
  53. package/dist/server/manifest-signer.d.ts.map +1 -1
  54. package/dist/server/manifest-signer.js +22 -0
  55. package/dist/server/manifest-signer.js.map +1 -1
  56. package/dist/server/request-signer.d.ts +18 -0
  57. package/dist/server/request-signer.d.ts.map +1 -1
  58. package/dist/server/request-signer.js +6 -0
  59. package/dist/server/request-signer.js.map +1 -1
  60. package/dist/server/session-relay.d.ts +30 -2
  61. package/dist/server/session-relay.d.ts.map +1 -1
  62. package/dist/server/session-relay.js +12 -4
  63. package/dist/server/session-relay.js.map +1 -1
  64. package/dist/server/webhook.d.ts +11 -0
  65. package/dist/server/webhook.d.ts.map +1 -0
  66. package/dist/server/webhook.js +18 -0
  67. package/dist/server/webhook.js.map +1 -0
  68. package/package.json +3 -4
package/README.md CHANGED
@@ -1,44 +1,103 @@
1
- # @opendatalabs/connect
1
+ # Vana Connect SDK
2
2
 
3
- SDK for integrating Vana Data Portability "Connect data" flows into builder applications.
3
+ Let your users bring their own data to your app.
4
4
 
5
- ## Installation
5
+ ## What problem this solves
6
+
7
+ Your users already have rich personal data — ChatGPT conversations, Instagram activity, Gmail, purchase history — but it's locked inside the platforms that collected it. As a builder, you can't easily use that data to personalize onboarding, tailor recommendations, or skip lengthy signup forms.
8
+
9
+ **Data portability** means users can export their data from these platforms and grant your app scoped access to it — with their explicit consent, cryptographic verification, and full control over what's shared and when to revoke it.
10
+
11
+ Today, getting access to user data means asking for manual file uploads (high friction), scraping on their behalf (fragile and legally risky), or negotiating enterprise API deals (slow and expensive). This SDK gives you a standardized way to request and receive personal data through Vana's [Data Portability Protocol](https://docs.vana.org/), handling session creation, grant verification, and data fetching in three function calls.
12
+
13
+ ## How it works
14
+
15
+ ```
16
+ Your App Vana Protocol
17
+ ────────────────────────────── ──────────────────────────────
18
+
19
+ 1. connect({ scopes })
20
+ → creates session
21
+ → returns deep link ──▶ 2. User opens DataConnect
22
+ reviews scopes, exports data,
23
+ approves grant
24
+
25
+ 3. Poll resolves with grant ◀── Grant signed & registered
26
+
27
+ 4. getData({ grant }) ──▶ 5. Personal Server returns
28
+ → structured JSON user data over TLS
29
+ ```
30
+
31
+ The [Data Portability Protocol](https://docs.vana.org/) defines how users collect data from platforms, store it under their control (on-device or hosted), and grant third-party apps scoped access. This SDK handles session creation, cryptographic request signing, polling, and data fetching. You write three function calls; the protocol handles the rest.
32
+
33
+ ## Getting started
34
+
35
+ The fastest way to get up and running is with the **Next.js starter** — a complete working app with session creation, polling, data fetching, manifest signing, and webhook handling already wired up:
6
36
 
7
37
  ```bash
8
- npm install @opendatalabs/connect
38
+ git clone https://github.com/vana-com/vana-connect.git
39
+ cd vana-connect/examples/nextjs-starter
40
+ cp .env.local.example .env.local
41
+ # Edit .env.local with your private key and APP_URL
42
+ pnpm install
43
+ pnpm dev
9
44
  ```
10
45
 
11
- ## Entrypoints
46
+ For local development, use the pre-registered dev key in .env.local
12
47
 
13
- | Entrypoint | Environment | Description |
14
- | ------------------------------ | ----------- | ----------------------------------------------------------------- |
15
- | `@opendatalabs/connect/server` | Node.js | `connect()`, `getData()`, `signVanaManifest()`, low-level clients |
16
- | `@opendatalabs/connect/react` | Browser | Polling hook, connect button |
17
- | `@opendatalabs/connect/core` | Universal | Shared types, errors, and constants |
48
+ ```
49
+ VANA_PRIVATE_KEY=0x3c05ac1a00546bc0b1b8d3a11fb908409005fac3f26d25f70711e4f632e720d3
50
+ APP_URL=http://localhost:3001
51
+ ```
18
52
 
19
- ## Quick Start
53
+ See [`examples/nextjs-starter`](./examples/nextjs-starter) for full details.
20
54
 
21
- ### 1. Initialize a session (server)
55
+ ---
56
+
57
+ ## Manual integration
58
+
59
+ If you prefer to integrate the SDK into an existing project, follow the steps below.
60
+
61
+ ### Installation
62
+
63
+ ```bash
64
+ pnpm add @opendatalabs/connect
65
+ ```
66
+
67
+ ### Package manager
68
+
69
+ This repo is pnpm-only for local development and examples. Use `pnpm` commands, not `npm`.
70
+
71
+ ### Prerequisites
72
+
73
+ First, register your app in the [Developer Portal](https://vana-developers.replit.app/). You will need to provide the URL where your app will be deployed, and then be given a private key after registration.
74
+
75
+ ### Quickstart
76
+
77
+ #### 1. Create a session (server)
22
78
 
23
79
  ```typescript
24
80
  import { connect } from "@opendatalabs/connect/server";
25
81
 
26
82
  const session = await connect({
27
- privateKey: process.env.VANA_PRIVATE_KEY as `0x${string}`,
83
+ privateKey: process.env.VANA_APP_PRIVATE_KEY as `0x${string}`,
28
84
  scopes: ["chatgpt.conversations"],
85
+ webhookUrl: "https://yourapp.com/api/webhook", // optional, data can be pushed to a web hook after a grant is approved
86
+ appUserId: "yourapp-user-42", // optional: this is used to corelate your app user with the data they provided
29
87
  });
30
88
 
31
- // session.sessionId — pass to the client for polling
32
- // session.deepLinkUrl surface to the user (QR code, deep link, etc.)
33
- // session.expiresAt session expiration timestamp
89
+ // Return to your frontend:
90
+ // session.sessionId used for polling
91
+ // session.deepLinkUrl opens the DataConnect App
92
+ // session.expiresAt — ISO 8601 expiration
34
93
  ```
35
94
 
36
- ### 2. Poll for approval (client)
95
+ #### 2. Poll for user approval (client)
37
96
 
38
97
  ```tsx
39
98
  import { useVanaConnect } from "@opendatalabs/connect/react";
40
99
 
41
- function ConnectPage({ sessionId }: { sessionId: string }) {
100
+ function ConnectData({ sessionId }: { sessionId: string }) {
42
101
  const { connect, status, grant, deepLinkUrl } = useVanaConnect();
43
102
 
44
103
  useEffect(() => {
@@ -46,69 +105,139 @@ function ConnectPage({ sessionId }: { sessionId: string }) {
46
105
  }, [sessionId]);
47
106
 
48
107
  if (status === "waiting" && deepLinkUrl) {
49
- return <a href={deepLinkUrl}>Open Vana Desktop App</a>;
108
+ return <a href={deepLinkUrl}>Connect your data</a>;
50
109
  }
51
-
52
110
  if (status === "approved" && grant) {
53
- return <p>Connected! Grant: {grant.grantId}</p>;
111
+ // grant.grantId, grant.userAddress, grant.scopes are available
112
+ return <p>Connected.</p>;
54
113
  }
55
-
56
- return <p>Status: {status}</p>;
114
+ return <p>{status}</p>;
57
115
  }
58
116
  ```
59
117
 
60
- ### 3. Fetch data (server)
118
+ Or use the pre-built button:
119
+
120
+ ```tsx
121
+ import { ConnectButton } from "@opendatalabs/connect/react";
122
+
123
+ <ConnectButton
124
+ sessionId={sessionId}
125
+ onComplete={(grant) => saveGrant(grant)}
126
+ onError={(err) => console.error(err)}
127
+ />;
128
+ ```
129
+
130
+ #### 3. Fetch user data (server)
61
131
 
62
132
  ```typescript
63
133
  import { getData } from "@opendatalabs/connect/server";
64
134
 
65
135
  const data = await getData({
66
- privateKey: process.env.VANA_PRIVATE_KEY as `0x${string}`,
67
- grant, // GrantPayload from the approval step
136
+ privateKey: process.env.VANA_APP_PRIVATE_KEY as `0x${string}`,
137
+ grant, // GrantPayload from step 2
68
138
  });
69
139
 
70
- // data is a Map<string, unknown> keyed by scope
140
+ // Record<string, unknown> keyed by scope
141
+ const conversations = data["chatgpt.conversations"];
71
142
  ```
72
143
 
73
- ### Options
144
+ #### Web App Manifest
145
+
146
+ The DataConnect App verifies your identity by fetching your manifest. Use `signVanaManifest()` to generate it:
74
147
 
75
148
  ```typescript
76
- // connect() options
77
- await connect({
78
- privateKey: "0x...",
79
- scopes: ["chatgpt.conversations"],
80
- webhookUrl: "https://...", // optional webhook for session events
81
- appUserId: "user-42", // optional app-level user ID
149
+ import { signVanaManifest } from "@opendatalabs/connect/server";
150
+
151
+ // In your manifest route handler (e.g. Next.js /manifest.json/route.ts):
152
+ const vanaBlock = await signVanaManifest({
153
+ privateKey: process.env.VANA_APP_PRIVATE_KEY as `0x${string}`,
154
+ appUrl: "https://yourapp.com",
155
+ privacyPolicyUrl: "https://yourapp.com/privacy",
156
+ termsUrl: "https://yourapp.com/terms",
157
+ supportUrl: "https://yourapp.com/support",
158
+ webhookUrl: "https://yourapp.com/api/webhook",
82
159
  });
160
+
161
+ const manifest = {
162
+ name: "Your App",
163
+ short_name: "YourApp",
164
+ start_url: "/",
165
+ display: "standalone",
166
+ vana: vanaBlock, // signed identity block
167
+ };
83
168
  ```
84
169
 
85
- ### 4. Sign a web app manifest (server)
170
+ Make sure your HTML includes `<link rel="manifest" href="/manifest.json">`.
171
+
172
+ ## Connectors
173
+
174
+ Available data connectors and their scopes (schema definitions):
175
+ [`vana-com/data-connectors/schemas`](https://github.com/vana-com/data-connectors/tree/main/schemas)
176
+
177
+ ## API Reference
178
+
179
+ ### Entrypoints
180
+
181
+ | Import | Environment | Exports |
182
+ | ------------------------------ | ----------- | ----------------------------------------------------------------- |
183
+ | `@opendatalabs/connect/server` | Node.js | `connect()`, `getData()`, `signVanaManifest()`, low-level clients |
184
+ | `@opendatalabs/connect/react` | Browser | `useVanaConnect()`, `useVanaData()`, `ConnectButton` |
185
+ | `@opendatalabs/connect/core` | Universal | Types, `ConnectError`, constants |
186
+
187
+ ### `connect(config): Promise<SessionInitResult>`
188
+
189
+ Creates a session on the Session Relay. Returns `sessionId`, `deepLinkUrl`, and `expiresAt`.
190
+
191
+ | Param | Type | Required | Description |
192
+ | ------------ | ------------------- | -------- | ---------------------------------------------------------------------- |
193
+ | `privateKey` | `` `0x${string}` `` | Yes | Builder private key |
194
+ | `scopes` | `string[]` | Yes | Data scopes to request |
195
+ | `webhookUrl` | `string` | No | Public HTTPS URL for grant event notifications (localhost is rejected) |
196
+ | `appUserId` | `string` | No | Your app's user ID for correlation |
197
+
198
+ ### `getData(config): Promise<Record<string, unknown>>`
199
+
200
+ Fetches user data from their Personal Server using a signed grant.
201
+
202
+ | Param | Type | Required | Description |
203
+ | ------------ | ------------------- | -------- | ---------------------------- |
204
+ | `privateKey` | `` `0x${string}` `` | Yes | Builder private key |
205
+ | `grant` | `GrantPayload` | Yes | Grant from the approval step |
206
+
207
+ ### `useVanaConnect(config?): UseVanaConnectResult`
208
+
209
+ React hook that polls the Session Relay and manages connection state.
86
210
 
87
211
  ```typescript
88
- import { signVanaManifest } from "@opendatalabs/connect/server";
212
+ const { connect, status, grant, error, deepLinkUrl, reset } = useVanaConnect();
213
+ ```
89
214
 
90
- const vanaBlock = await signVanaManifest({
91
- privateKey: process.env.VANA_PRIVATE_KEY as `0x${string}`,
92
- appUrl: "https://your-app.example.com",
93
- privacyPolicyUrl: "https://your-app.example.com/privacy",
94
- termsUrl: "https://your-app.example.com/terms",
95
- supportUrl: "https://your-app.example.com/support",
96
- webhookUrl: "https://your-app.example.com/api/webhook",
97
- });
215
+ `status` transitions: `idle` &rarr; `connecting` &rarr; `waiting` &rarr; `approved` | `denied` | `expired` | `error`
98
216
 
99
- // Include vanaBlock in your W3C Web App Manifest as the "vana" key
100
- // The Desktop App fetches this manifest to verify builder identity
217
+ ### `GrantPayload`
218
+
219
+ Returned when a user approves access:
220
+
221
+ ```typescript
222
+ interface GrantPayload {
223
+ grantId: string; // on-chain permission ID
224
+ userAddress: string; // user's wallet address
225
+ builderAddress: string; // your registered address
226
+ scopes: string[]; // approved data scopes
227
+ serverAddress?: string; // user's Personal Server
228
+ appUserId?: string; // your app's user ID (if provided)
229
+ }
101
230
  ```
102
231
 
103
- ### Advanced (Low-Level APIs)
232
+ ### Low-level clients
104
233
 
105
- For full control, the low-level factories are still available:
234
+ For full control over individual protocol interactions:
106
235
 
107
236
  ```typescript
108
237
  import {
109
- createSessionRelay,
110
- createDataClient,
111
- createRequestSigner,
238
+ createRequestSigner, // Web3Signed header generation
239
+ createSessionRelay, // Session Relay HTTP client
240
+ createDataClient, // Data Gateway HTTP client
112
241
  } from "@opendatalabs/connect/server";
113
242
  ```
114
243
 
@@ -1,3 +1,33 @@
1
- export declare const SESSION_RELAY_URL = "https://session-relay-git-dev-opendatalabs.vercel.app";
2
- export declare const GATEWAY_URL = "https://data-gateway-env-dev-opendatalabs.vercel.app";
1
+ /** SDK environment selector. */
2
+ export type VanaEnvironment = "dev" | "prod";
3
+ /** URL configuration for each SDK environment. */
4
+ export declare const ENV_CONFIG: {
5
+ readonly dev: {
6
+ readonly sessionRelayUrl: "https://dev.session-relay.vana.org";
7
+ readonly gatewayUrl: "https://dev.data-gateway.vana.org";
8
+ readonly accountUrl: "https://account-dev.vana.org";
9
+ };
10
+ readonly prod: {
11
+ readonly sessionRelayUrl: "https://session-relay.vana.org";
12
+ readonly gatewayUrl: "https://data-gateway.vana.org";
13
+ readonly accountUrl: "https://account.vana.org";
14
+ };
15
+ };
16
+ /** Default environment used when none is specified. */
17
+ export declare const DEFAULT_ENVIRONMENT: VanaEnvironment;
18
+ /**
19
+ * Returns the URL configuration for the given environment.
20
+ *
21
+ * @param environment - `"dev"` or `"prod"`. Defaults to {@link DEFAULT_ENVIRONMENT}.
22
+ * @returns An object with `sessionRelayUrl` and `gatewayUrl`.
23
+ */
24
+ export declare function getEnvConfig(environment?: VanaEnvironment): {
25
+ readonly sessionRelayUrl: "https://dev.session-relay.vana.org";
26
+ readonly gatewayUrl: "https://dev.data-gateway.vana.org";
27
+ readonly accountUrl: "https://account-dev.vana.org";
28
+ } | {
29
+ readonly sessionRelayUrl: "https://session-relay.vana.org";
30
+ readonly gatewayUrl: "https://data-gateway.vana.org";
31
+ readonly accountUrl: "https://account.vana.org";
32
+ };
3
33
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/core/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,0DAC2B,CAAC;AAC1D,eAAO,MAAM,WAAW,yDACgC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/core/constants.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,CAAC;AAE7C,kDAAkD;AAClD,eAAO,MAAM,UAAU;;;;;;;;;;;CAWb,CAAC;AAEX,uDAAuD;AACvD,eAAO,MAAM,mBAAmB,EAAE,eAAwB,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,WAAW,CAAC,EAAE,eAAe;;;;;;;;EAEzD"}
@@ -1,3 +1,25 @@
1
- export const SESSION_RELAY_URL = "https://session-relay-git-dev-opendatalabs.vercel.app";
2
- export const GATEWAY_URL = "https://data-gateway-env-dev-opendatalabs.vercel.app";
1
+ /** URL configuration for each SDK environment. */
2
+ export const ENV_CONFIG = {
3
+ dev: {
4
+ sessionRelayUrl: "https://dev.session-relay.vana.org",
5
+ gatewayUrl: "https://dev.data-gateway.vana.org",
6
+ accountUrl: "https://account-dev.vana.org",
7
+ },
8
+ prod: {
9
+ sessionRelayUrl: "https://session-relay.vana.org",
10
+ gatewayUrl: "https://data-gateway.vana.org",
11
+ accountUrl: "https://account.vana.org",
12
+ },
13
+ };
14
+ /** Default environment used when none is specified. */
15
+ export const DEFAULT_ENVIRONMENT = "prod";
16
+ /**
17
+ * Returns the URL configuration for the given environment.
18
+ *
19
+ * @param environment - `"dev"` or `"prod"`. Defaults to {@link DEFAULT_ENVIRONMENT}.
20
+ * @returns An object with `sessionRelayUrl` and `gatewayUrl`.
21
+ */
22
+ export function getEnvConfig(environment) {
23
+ return ENV_CONFIG[environment ?? DEFAULT_ENVIRONMENT];
24
+ }
3
25
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/core/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAC5B,uDAAuD,CAAC;AAC1D,MAAM,CAAC,MAAM,WAAW,GACtB,sDAAsD,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/core/constants.ts"],"names":[],"mappings":"AAGA,kDAAkD;AAClD,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,GAAG,EAAE;QACH,eAAe,EAAE,oCAAoC;QACrD,UAAU,EAAE,mCAAmC;QAC/C,UAAU,EAAE,8BAA8B;KAC3C;IACD,IAAI,EAAE;QACJ,eAAe,EAAE,gCAAgC;QACjD,UAAU,EAAE,+BAA+B;QAC3C,UAAU,EAAE,0BAA0B;KACvC;CACO,CAAC;AAEX,uDAAuD;AACvD,MAAM,CAAC,MAAM,mBAAmB,GAAoB,MAAM,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,WAA6B;IACxD,OAAO,UAAU,CAAC,WAAW,IAAI,mBAAmB,CAAC,CAAC;AACxD,CAAC"}
@@ -1,6 +1,47 @@
1
+ /**
2
+ * Known error codes thrown by the SDK.
3
+ *
4
+ * Use these constants for typed `catch` handling instead of comparing raw strings.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { ConnectError, ConnectErrorCode } from "@opendatalabs/connect/core";
9
+ *
10
+ * try {
11
+ * await getData({ privateKey, grant });
12
+ * } catch (err) {
13
+ * if (err instanceof ConnectError && err.code === ConnectErrorCode.SERVER_NOT_FOUND) {
14
+ * // handle missing server
15
+ * }
16
+ * }
17
+ * ```
18
+ */
19
+ export declare const ConnectErrorCode: {
20
+ readonly SESSION_INIT_FAILED: "SESSION_INIT_FAILED";
21
+ readonly SESSION_EXPIRED: "SESSION_EXPIRED";
22
+ readonly POLL_FAILED: "POLL_FAILED";
23
+ readonly POLL_TIMEOUT: "POLL_TIMEOUT";
24
+ readonly SERVER_NOT_FOUND: "SERVER_NOT_FOUND";
25
+ readonly GATEWAY_ERROR: "GATEWAY_ERROR";
26
+ readonly DATA_FETCH_FAILED: "DATA_FETCH_FAILED";
27
+ readonly LIST_SCOPES_FAILED: "LIST_SCOPES_FAILED";
28
+ readonly LIST_VERSIONS_FAILED: "LIST_VERSIONS_FAILED";
29
+ readonly CONFIG_INVALID: "CONFIG_INVALID";
30
+ readonly WEBHOOK_INVALID: "WEBHOOK_INVALID";
31
+ };
32
+ /** Union type of all known error code string values. */
33
+ export type ConnectErrorCode = (typeof ConnectErrorCode)[keyof typeof ConnectErrorCode];
34
+ /**
35
+ * Error class thrown by all SDK operations.
36
+ *
37
+ * Includes a typed {@link code} for programmatic handling and an optional
38
+ * {@link statusCode} from HTTP responses.
39
+ */
1
40
  export declare class ConnectError extends Error {
2
- readonly code: string;
41
+ /** Machine-readable error code. One of {@link ConnectErrorCode} or an arbitrary server-returned string. */
42
+ readonly code: ConnectErrorCode | (string & {});
43
+ /** HTTP status code from the upstream response, if applicable. */
3
44
  readonly statusCode?: number;
4
- constructor(message: string, code: string, statusCode?: number);
45
+ constructor(message: string, code: ConnectErrorCode | (string & {}), statusCode?: number);
5
46
  }
6
47
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAM/D"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CAYnB,CAAC;AAEX,wDAAwD;AACxD,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,2GAA2G;IAC3G,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAChD,kEAAkE;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM;CAOtB"}
@@ -1,5 +1,44 @@
1
+ /**
2
+ * Known error codes thrown by the SDK.
3
+ *
4
+ * Use these constants for typed `catch` handling instead of comparing raw strings.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { ConnectError, ConnectErrorCode } from "@opendatalabs/connect/core";
9
+ *
10
+ * try {
11
+ * await getData({ privateKey, grant });
12
+ * } catch (err) {
13
+ * if (err instanceof ConnectError && err.code === ConnectErrorCode.SERVER_NOT_FOUND) {
14
+ * // handle missing server
15
+ * }
16
+ * }
17
+ * ```
18
+ */
19
+ export const ConnectErrorCode = {
20
+ SESSION_INIT_FAILED: "SESSION_INIT_FAILED",
21
+ SESSION_EXPIRED: "SESSION_EXPIRED",
22
+ POLL_FAILED: "POLL_FAILED",
23
+ POLL_TIMEOUT: "POLL_TIMEOUT",
24
+ SERVER_NOT_FOUND: "SERVER_NOT_FOUND",
25
+ GATEWAY_ERROR: "GATEWAY_ERROR",
26
+ DATA_FETCH_FAILED: "DATA_FETCH_FAILED",
27
+ LIST_SCOPES_FAILED: "LIST_SCOPES_FAILED",
28
+ LIST_VERSIONS_FAILED: "LIST_VERSIONS_FAILED",
29
+ CONFIG_INVALID: "CONFIG_INVALID",
30
+ WEBHOOK_INVALID: "WEBHOOK_INVALID",
31
+ };
32
+ /**
33
+ * Error class thrown by all SDK operations.
34
+ *
35
+ * Includes a typed {@link code} for programmatic handling and an optional
36
+ * {@link statusCode} from HTTP responses.
37
+ */
1
38
  export class ConnectError extends Error {
39
+ /** Machine-readable error code. One of {@link ConnectErrorCode} or an arbitrary server-returned string. */
2
40
  code;
41
+ /** HTTP status code from the upstream response, if applicable. */
3
42
  statusCode;
4
43
  constructor(message, code, statusCode) {
5
44
  super(message);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,UAAU,CAAU;IAE7B,YAAY,OAAe,EAAE,IAAY,EAAE,UAAmB;QAC5D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,mBAAmB,EAAE,qBAAqB;IAC1C,eAAe,EAAE,iBAAiB;IAClC,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;IAC5B,gBAAgB,EAAE,kBAAkB;IACpC,aAAa,EAAE,eAAe;IAC9B,iBAAiB,EAAE,mBAAmB;IACtC,kBAAkB,EAAE,oBAAoB;IACxC,oBAAoB,EAAE,sBAAsB;IAC5C,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;CAC1B,CAAC;AAMX;;;;;GAKG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,2GAA2G;IAClG,IAAI,CAAmC;IAChD,kEAAkE;IACzD,UAAU,CAAU;IAE7B,YACE,OAAe,EACf,IAAsC,EACtC,UAAmB;QAEnB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { GrantPayload } from "./types.js";
2
+ /**
3
+ * Type guard that checks whether an unknown value has the shape of a {@link GrantPayload}.
4
+ *
5
+ * Validates the presence and types of required fields: `grantId`, `userAddress`,
6
+ * `builderAddress`, and `scopes` (non-empty string array).
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const body = await request.json();
11
+ * if (!isValidGrant(body.grant)) {
12
+ * return NextResponse.json({ error: "Invalid grant" }, { status: 400 });
13
+ * }
14
+ * // body.grant is now typed as GrantPayload
15
+ * const data = await getData({ privateKey, grant: body.grant });
16
+ * ```
17
+ */
18
+ export declare function isValidGrant(value: unknown): value is GrantPayload;
19
+ //# sourceMappingURL=grants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../../src/core/grants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAgBlE"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Type guard that checks whether an unknown value has the shape of a {@link GrantPayload}.
3
+ *
4
+ * Validates the presence and types of required fields: `grantId`, `userAddress`,
5
+ * `builderAddress`, and `scopes` (non-empty string array).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const body = await request.json();
10
+ * if (!isValidGrant(body.grant)) {
11
+ * return NextResponse.json({ error: "Invalid grant" }, { status: 400 });
12
+ * }
13
+ * // body.grant is now typed as GrantPayload
14
+ * const data = await getData({ privateKey, grant: body.grant });
15
+ * ```
16
+ */
17
+ export function isValidGrant(value) {
18
+ if (value === null || typeof value !== "object")
19
+ return false;
20
+ const obj = value;
21
+ return (typeof obj.grantId === "string" &&
22
+ obj.grantId.length > 0 &&
23
+ typeof obj.userAddress === "string" &&
24
+ obj.userAddress.length > 0 &&
25
+ typeof obj.builderAddress === "string" &&
26
+ obj.builderAddress.length > 0 &&
27
+ Array.isArray(obj.scopes) &&
28
+ obj.scopes.length > 0 &&
29
+ obj.scopes.every((s) => typeof s === "string" && s.length > 0));
30
+ }
31
+ //# sourceMappingURL=grants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grants.js","sourceRoot":"","sources":["../../src/core/grants.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAE7C,OAAO,CACL,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QACtB,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;QACnC,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAC1B,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ;QACtC,GAAG,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;QAC7B,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QACrB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CACxE,CAAC;AACJ,CAAC"}
@@ -1,4 +1,5 @@
1
- export { ConnectError } from "./errors.js";
2
- export { SESSION_RELAY_URL, GATEWAY_URL } from "./constants.js";
1
+ export { ConnectError, ConnectErrorCode } from "./errors.js";
2
+ export { isValidGrant } from "./grants.js";
3
+ export { getEnvConfig, ENV_CONFIG, DEFAULT_ENVIRONMENT, type VanaEnvironment, } from "./constants.js";
3
4
  export type { ConnectionStatus, SessionInitParams, SessionInitResult, SessionPollResult, GrantPayload, DataFetchParams, RequestSignerConfig, SessionRelayConfig, DataClientConfig, ConnectConfig, GetDataConfig, VanaManifestConfig, VanaManifestBlock, } from "./types.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,YAAY,CAAC"}
@@ -1,3 +1,4 @@
1
- export { ConnectError } from "./errors.js";
2
- export { SESSION_RELAY_URL, GATEWAY_URL } from "./constants.js";
1
+ export { ConnectError, ConnectErrorCode } from "./errors.js";
2
+ export { isValidGrant } from "./grants.js";
3
+ export { getEnvConfig, ENV_CONFIG, DEFAULT_ENVIRONMENT, } from "./constants.js";
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,UAAU,EACV,mBAAmB,GAEpB,MAAM,gBAAgB,CAAC"}