@openhandle/sdk 0.5.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/LICENSE +21 -0
- package/README.md +239 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +31 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/operations.d.ts +1830 -0
- package/dist/generated/operations.d.ts.map +1 -0
- package/dist/generated/operations.js +2455 -0
- package/dist/generated/operations.js.map +1 -0
- package/dist/generated/public-types.d.ts +679 -0
- package/dist/generated/public-types.d.ts.map +1 -0
- package/dist/generated/public-types.js +3 -0
- package/dist/generated/public-types.js.map +1 -0
- package/dist/generated/resources.d.ts +1949 -0
- package/dist/generated/resources.d.ts.map +1 -0
- package/dist/generated/resources.js +3 -0
- package/dist/generated/resources.js.map +1 -0
- package/dist/generated/schema.d.ts +30218 -0
- package/dist/generated/schema.d.ts.map +1 -0
- package/dist/generated/schema.js +3 -0
- package/dist/generated/schema.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/references.d.ts +3 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +162 -0
- package/dist/references.js.map +1 -0
- package/dist/runtime.d.ts +16 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +230 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +99 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenHandle
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# OpenHandle TypeScript SDK
|
|
2
|
+
|
|
3
|
+
The official TypeScript and JavaScript client for the OpenHandle API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @openhandle/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The package is also compatible with npm, Yarn, and Bun.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Create a Test key in the [Openhandle dashboard](https://app.openhandle.dev),
|
|
16
|
+
store it as `OPENHANDLE_TEST_KEY`, and create one reusable client:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { OpenHandle } from '@openhandle/sdk';
|
|
20
|
+
|
|
21
|
+
const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_TEST_KEY! });
|
|
22
|
+
const profile = openhandle.instagram.profile('northstar_forge_test');
|
|
23
|
+
|
|
24
|
+
const response = await profile.get();
|
|
25
|
+
const posts = await profile.posts.list({ freshness: '24h' });
|
|
26
|
+
|
|
27
|
+
console.log(response.data.handle, posts.data.length);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The key selects the environment. `oh_test_` keys return deterministic synthetic
|
|
31
|
+
data with a `$0.000` actual charge; `oh_live_` keys use real public identifiers
|
|
32
|
+
and normal billing. Never ship an API key in a browser or mobile bundle.
|
|
33
|
+
|
|
34
|
+
See the [API reference](https://openhandle.dev/docs/api-reference) for a typed
|
|
35
|
+
SDK example for every operation.
|
|
36
|
+
|
|
37
|
+
## Resource selection
|
|
38
|
+
|
|
39
|
+
The SDK follows one predictable grammar:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
openhandle.<platform>.<resource>(reference).<subresource>.<operation>(options)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Only terminal operations such as `get`, `list`, `search`, and `fetch` perform
|
|
46
|
+
network requests. Selecting a resource is synchronous and reusable:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const post = openhandle.instagram.post('Db04otPRpRH');
|
|
50
|
+
|
|
51
|
+
const details = await post.get();
|
|
52
|
+
const comments = await post.comments.list();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Profile strings are usernames, including all-numeric usernames. Use an
|
|
56
|
+
explicit reference for platform IDs and URLs:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
openhandle.instagram.profile({ id: '25025320' });
|
|
60
|
+
openhandle.instagram.profile({ url: 'https://www.instagram.com/openai/' });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Platform IDs are opaque strings. Numeric ID values are rejected.
|
|
64
|
+
|
|
65
|
+
Use `fetch` when the URL's platform or resource is not known:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const response = await openhandle.fetch('https://www.instagram.com/p/Db04otPRpRH/', {
|
|
69
|
+
freshness: '24h',
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Responses and billing
|
|
74
|
+
|
|
75
|
+
Successful responses preserve the public envelope and add normalized request
|
|
76
|
+
metadata:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const response = await openhandle.instagram.profile('northstar_forge_test').get();
|
|
80
|
+
|
|
81
|
+
response.data; // Typed, camel-cased resource
|
|
82
|
+
response.platform;
|
|
83
|
+
response.resource;
|
|
84
|
+
response.capturedAt;
|
|
85
|
+
response.source;
|
|
86
|
+
response.requestId;
|
|
87
|
+
response.billing.cost;
|
|
88
|
+
response.billing.environment;
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Unavailable metrics are `null`, never `0`. Monetary values are decimal strings
|
|
92
|
+
so applications do not lose precision.
|
|
93
|
+
|
|
94
|
+
## Pagination
|
|
95
|
+
|
|
96
|
+
List operations return a typed page with its opaque cursor and a lazy `next()`
|
|
97
|
+
helper:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
let page = await openhandle.instagram.profile('northstar_forge_test').posts.list();
|
|
101
|
+
|
|
102
|
+
while (true) {
|
|
103
|
+
for (const post of page.data) {
|
|
104
|
+
console.log(post.id);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const nextPage = await page.next();
|
|
108
|
+
if (!nextPage) break;
|
|
109
|
+
page = nextPage;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Each call to `next()` that fetches a page is one request. It returns `null`
|
|
114
|
+
without a request after the final page.
|
|
115
|
+
|
|
116
|
+
## Errors and retries
|
|
117
|
+
|
|
118
|
+
API failures throw `OpenHandleError`. Branch on `code`, never `message`, and
|
|
119
|
+
include `requestId` in logs or support requests:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { OpenHandleError } from '@openhandle/sdk';
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
await openhandle.instagram.profile('quiet_harbor_test').get();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (error instanceof OpenHandleError) {
|
|
128
|
+
console.error(error.code, error.status, error.retryable, error.requestId);
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The client retries explicitly retryable API failures and transient Fetch
|
|
135
|
+
failures up to `maxRetries`. It honors `Retry-After` and uses capped exponential
|
|
136
|
+
backoff with jitter. Reference-validation errors occur before a request and are
|
|
137
|
+
available as `OpenHandleReferenceError` and `ReferenceMismatchError`.
|
|
138
|
+
|
|
139
|
+
## Configuration
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const openhandle = new OpenHandle({
|
|
143
|
+
apiKey: process.env.OPENHANDLE_TEST_KEY!,
|
|
144
|
+
baseUrl: 'https://api.openhandle.dev',
|
|
145
|
+
maxRetries: 2,
|
|
146
|
+
timeoutMs: 30_000,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
await openhandle.instagram.profile('northstar_forge_test').get({
|
|
150
|
+
maxRetries: 0,
|
|
151
|
+
signal: abortController.signal,
|
|
152
|
+
timeoutMs: 10_000,
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
| Option | Default | Meaning |
|
|
157
|
+
|---|---:|---|
|
|
158
|
+
| `apiKey` | required | Secret Test or Live API key |
|
|
159
|
+
| `baseUrl` | `https://api.openhandle.dev` | API origin, useful for proxies and tests |
|
|
160
|
+
| `fetch` | `globalThis.fetch` | Custom Fetch implementation |
|
|
161
|
+
| `maxRetries` | `2` | Retry attempts after the initial request |
|
|
162
|
+
| `timeoutMs` | `30000` | Timeout for each request attempt |
|
|
163
|
+
|
|
164
|
+
`maxRetries`, `timeoutMs`, and an `AbortSignal` can also be supplied per
|
|
165
|
+
operation. Per-operation values override client defaults.
|
|
166
|
+
|
|
167
|
+
## Runtime support
|
|
168
|
+
|
|
169
|
+
The package is ESM-only and supports Node.js 20 or newer. It also works with
|
|
170
|
+
runtimes that provide the standard Fetch and AbortSignal APIs.
|
|
171
|
+
|
|
172
|
+
## TypeScript conventions
|
|
173
|
+
|
|
174
|
+
Request options and response fields use camel case. The exported `components`
|
|
175
|
+
type represents the raw OpenAPI wire schema; terminal SDK operation return
|
|
176
|
+
types apply the camel-case transformation automatically.
|
|
177
|
+
|
|
178
|
+
The root package also exports camel-cased model types and named aliases for
|
|
179
|
+
every operation. These are useful for wrappers, caches, callbacks, and public
|
|
180
|
+
function signatures:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
import type {
|
|
184
|
+
InstagramProfile,
|
|
185
|
+
InstagramProfilePostsOptions,
|
|
186
|
+
InstagramProfilePostsPage,
|
|
187
|
+
InstagramProfileResponse,
|
|
188
|
+
} from '@openhandle/sdk';
|
|
189
|
+
|
|
190
|
+
async function getProfile(): Promise<InstagramProfileResponse> {
|
|
191
|
+
return openhandle.instagram.profile('northstar_forge_test').get();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function readProfile(profile: InstagramProfile) {
|
|
195
|
+
return profile.handle;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Operation names omit the terminal `get` or `list`: for example,
|
|
200
|
+
`instagram.profile.posts.list` produces `InstagramProfilePostsOptions` and
|
|
201
|
+
`InstagramProfilePostsPage`. Search terminals keep `Search` in the name when
|
|
202
|
+
needed to avoid ambiguity.
|
|
203
|
+
|
|
204
|
+
For example:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const result = await openhandle.instagram.profile('northstar_forge_test').posts.list({
|
|
208
|
+
freshness: '24h',
|
|
209
|
+
since: '2026-08-01T00:00:00Z',
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
result.data[0]?.publishedAt;
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
The SDK is generated from the pinned OpenAPI document in
|
|
218
|
+
[`openapi/openhandle.json`](./openapi/openhandle.json). The generator, runtime,
|
|
219
|
+
tests, and generated output are all kept in this repository so releases are
|
|
220
|
+
reproducible without access to the private OpenHandle API implementation.
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
pnpm install
|
|
224
|
+
pnpm generate
|
|
225
|
+
pnpm test
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`pnpm generate:check` fails when the committed generated files do not match the
|
|
229
|
+
pinned OpenAPI document.
|
|
230
|
+
|
|
231
|
+
## Releases
|
|
232
|
+
|
|
233
|
+
Conventional commits feed an automated release pull request. Merging that pull
|
|
234
|
+
request creates a `v*` tag; the tag workflow tests and publishes the package to
|
|
235
|
+
npm using trusted publishing. Registry credentials are not stored in GitHub.
|
|
236
|
+
|
|
237
|
+
## License
|
|
238
|
+
|
|
239
|
+
[MIT](./LICENSE)
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface OpenHandleErrorInput {
|
|
2
|
+
cause?: unknown;
|
|
3
|
+
code: string;
|
|
4
|
+
details?: Record<string, unknown>;
|
|
5
|
+
message: string;
|
|
6
|
+
requestId?: string;
|
|
7
|
+
retryable?: boolean;
|
|
8
|
+
retryAfter?: number;
|
|
9
|
+
status?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class OpenHandleError extends Error {
|
|
12
|
+
readonly code: string;
|
|
13
|
+
readonly details?: Record<string, unknown>;
|
|
14
|
+
readonly requestId?: string;
|
|
15
|
+
readonly retryable: boolean;
|
|
16
|
+
readonly retryAfter?: number;
|
|
17
|
+
readonly status?: number;
|
|
18
|
+
constructor(input: OpenHandleErrorInput);
|
|
19
|
+
}
|
|
20
|
+
export declare class OpenHandleReferenceError extends TypeError {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
export declare class ReferenceMismatchError extends OpenHandleReferenceError {
|
|
24
|
+
constructor(expectedPlatform: string, expectedResource: string, actualPlatform: string, actualResource: string);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBAEb,KAAK,EAAE,oBAAoB;CAU1C;AAED,qBAAa,wBAAyB,SAAQ,SAAS;gBACvC,OAAO,EAAE,MAAM;CAI9B;AAED,qBAAa,sBAAuB,SAAQ,wBAAwB;gBACpD,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM;CAIjH"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class OpenHandleError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
details;
|
|
4
|
+
requestId;
|
|
5
|
+
retryable;
|
|
6
|
+
retryAfter;
|
|
7
|
+
status;
|
|
8
|
+
constructor(input) {
|
|
9
|
+
super(input.message, { cause: input.cause });
|
|
10
|
+
this.name = 'OpenHandleError';
|
|
11
|
+
this.code = input.code;
|
|
12
|
+
this.details = input.details;
|
|
13
|
+
this.requestId = input.requestId;
|
|
14
|
+
this.retryable = input.retryable ?? false;
|
|
15
|
+
this.retryAfter = input.retryAfter;
|
|
16
|
+
this.status = input.status;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class OpenHandleReferenceError extends TypeError {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'OpenHandleReferenceError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class ReferenceMismatchError extends OpenHandleReferenceError {
|
|
26
|
+
constructor(expectedPlatform, expectedResource, actualPlatform, actualResource) {
|
|
27
|
+
super(`Expected a ${expectedPlatform} ${expectedResource} URL, received a ${actualPlatform} ${actualResource} URL.`);
|
|
28
|
+
this.name = 'ReferenceMismatchError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC7B,IAAI,CAAS;IACb,OAAO,CAA2B;IAClC,SAAS,CAAU;IACnB,SAAS,CAAU;IACnB,UAAU,CAAU;IACpB,MAAM,CAAU;IAEzB,YAAY,KAA2B;QACnC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,CAAC;CACJ;AAED,MAAM,OAAO,wBAAyB,SAAQ,SAAS;IACnD,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IAC3C,CAAC;CACJ;AAED,MAAM,OAAO,sBAAuB,SAAQ,wBAAwB;IAChE,YAAY,gBAAwB,EAAE,gBAAwB,EAAE,cAAsB,EAAE,cAAsB;QAC1G,KAAK,CAAC,cAAc,gBAAgB,IAAI,gBAAgB,oBAAoB,cAAc,IAAI,cAAc,OAAO,CAAC,CAAC;QACrH,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACzC,CAAC;CACJ"}
|