@hunt-labs/bytekit-sdk 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +180 -0
- package/README.md +82 -0
- package/dist/client.d.ts +34 -1
- package/dist/client.js +27 -2
- package/dist/generated/api.d.ts +45 -9
- package/dist/resources/scrape.d.ts +0 -13
- package/dist/resources/scrape.js +0 -13
- package/dist/resources/screenshots.d.ts +9 -2
- package/dist/resources/screenshots.js +15 -2
- package/dist/version.d.ts +8 -0
- package/dist/version.js +12 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,181 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
This file records only the delta between versions. For how to use the package
|
|
9
9
|
today, see [README.md](./README.md), which remains the authoritative usage guide.
|
|
10
10
|
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [0.7.1] - 2026-08-11
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Generated types follow the spec's corrected error and format vocabularies** (#2959). Two
|
|
18
|
+
vocabulary corrections in `docs/api/openapi.yaml` flow through `src/generated/api.d.ts`:
|
|
19
|
+
- `ScrapeErrorEnvelope.error.code` no longer lists `quota_exhausted`. The API has emitted
|
|
20
|
+
`quota_exceeded` since #1539 and there is no throw site for `quota_exhausted` anywhere in
|
|
21
|
+
the gateway, so this removes a code that has never been sent — not one that stops being
|
|
22
|
+
sent. A consumer switching on it was matching a branch that could not be reached; the
|
|
23
|
+
live code for an exceeded quota is `quota_exceeded`. `invalid_url`, which the API does
|
|
24
|
+
emit, is unchanged and still listed.
|
|
25
|
+
- `createBulk`'s `formats` now spells the raw-HTML value `raw_html`, matching `ScrapeRequest`
|
|
26
|
+
and `createScrapeBulk`. `/v1/bulk` previously accepted only the internal `rawHtml`
|
|
27
|
+
spelling and the spec documented that; it now accepts both, so the one endpoint that
|
|
28
|
+
disagreed with the rest of the surface no longer does. `rawHtml` keeps working.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`ByteKitError.headers` — the failing response's headers, so you can write your own backoff**
|
|
33
|
+
(#2957). This SDK performs exactly one `fetch` per call and never retries, deliberately, so that
|
|
34
|
+
retry policy stays the caller's. But the policy was unwritable: `ByteKitError` carried no
|
|
35
|
+
headers and `requestWithResponse` returns headers only on 2xx — which a rate-limited request
|
|
36
|
+
never reaches — so `Retry-After` and the `X-RateLimit-*` family were unreachable through the SDK
|
|
37
|
+
at every entry point. `err.headers` closes that:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
if (err instanceof ByteKitError && err.status === 429) {
|
|
41
|
+
const waitMs = Number(err.headers?.get('Retry-After') ?? 1) * 1000;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It is the runtime's own `Headers` object rather than a snapshot, so `get()` stays
|
|
46
|
+
case-insensitive whatever casing the wire used. **Strictly additive**: it is optional and last
|
|
47
|
+
on the constructor, follows the same `declare` discipline `details` uses, and an error
|
|
48
|
+
constructed without one carries no `headers` key at all — `'headers' in err`, spreads and
|
|
49
|
+
`JSON.stringify` are unchanged for every pre-existing construction, as are `status`, `code`,
|
|
50
|
+
`message`, `details` and both 2xx return shapes. Only **response** headers are exposed;
|
|
51
|
+
`Authorization` rides on the request and is never reachable through it.
|
|
52
|
+
`ByteKitConnectionError` is unchanged — no response, no headers to carry.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **`screenshots.getWithResponse`'s docstring no longer promises headers that endpoint never
|
|
57
|
+
emits** (#2957). The JSDoc — the one an IDE surfaces on hover, and the one the published SDK
|
|
58
|
+
reference is generated from — claimed the documented `X-Screenshot-*` / `X-Raw-Bytes` /
|
|
59
|
+
`X-Billable-Bytes` / `X-Billing-Multiplier` headers "are on `headers`". They are not:
|
|
60
|
+
`GET /v1/screenshots/{id}` is declared with **no** `X-*` response headers, which is what
|
|
61
|
+
`ByteKit.requestWithResponse`'s own doc comment and the README have said all along, and what a
|
|
62
|
+
live GET confirms. Documentation only — no signature, return type or runtime behavior changed.
|
|
63
|
+
`screenshots.createWithResponse` (`POST /v1/screenshots`) really does emit that family, and its
|
|
64
|
+
docstring still says so.
|
|
65
|
+
|
|
66
|
+
- **README documents the `signal`-vs-`timeoutMs` precedence and the `requestTimeoutMs` escape
|
|
67
|
+
hatch** (#2957). Passing your own `AbortSignal` silently disables the constructor's `timeoutMs`
|
|
68
|
+
— the signal becomes the request's only abort source, so a client built with `timeoutMs: 200`
|
|
69
|
+
waits indefinitely if the signal never fires. That precedence was documented on
|
|
70
|
+
`RequestOptions.signal` in the types, where only a reader already inspecting the option would
|
|
71
|
+
meet it, and nowhere in the README. A new "Timeouts and cancellation" section states it with the
|
|
72
|
+
full four-row precedence table and shows `requestTimeoutMs` composed alongside a caller signal
|
|
73
|
+
(the request then aborts on whichever fires first). No behavior changed — the precedence is what
|
|
74
|
+
it always was.
|
|
75
|
+
|
|
76
|
+
- **`ScrapeWarning.code` now carries all 12 codes the server can emit** (#2948). The generated
|
|
77
|
+
union in `src/generated/api.d.ts` listed 10. `low_quality_extraction` and
|
|
78
|
+
`fragment_menu_stripped` — added to the server-side emitter union by #1701 — never reached
|
|
79
|
+
`docs/api/openapi.yaml`, so every regeneration since faithfully reproduced the gap and the
|
|
80
|
+
exported type was non-exhaustive: a `switch` over `warning.code` that TypeScript proved
|
|
81
|
+
exhaustive would silently fall through on a warning the API really returns. Widening the spec
|
|
82
|
+
and regenerating fixes the type; no runtime code changed. The other 10 codes are unaffected.
|
|
83
|
+
|
|
84
|
+
- **Gateway wire-type correction: `billing_multiplier` is a JSON number on `scrape.get()` again**
|
|
85
|
+
(#2954). `GET /v1/scrape/{id}` (and `GET /v1/scrape/bulk/{id}` items) were serializing
|
|
86
|
+
`billing_multiplier` as a JSON string (e.g. `"0.50"`) instead of a number — the pg driver
|
|
87
|
+
returns the underlying `NUMERIC(10,2)` column as a string, and the gateway's GET serializer
|
|
88
|
+
passed it through unconverted, while `POST /v1/scrape`'s create-path value (computed in JS) was
|
|
89
|
+
already correct. Fixed upstream in the gateway; this SDK required no code change, only removal
|
|
90
|
+
of the `KNOWN DRIFT (#2426)` JSDoc on `ScrapeResource.get()` that documented the workaround —
|
|
91
|
+
the static `number` type this SDK has shipped all along is accurate again. A caller that was
|
|
92
|
+
defensively coercing with `Number(...)` per the old note does not need to change anything; a
|
|
93
|
+
caller relying on the exact string form `"0.50"` (rather than doing arithmetic) will now see
|
|
94
|
+
`0.5`.
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
|
|
98
|
+
- **Alignment release — no consumer-visible change _in the alignment itself_** (the `#2948` type
|
|
99
|
+
widening above is a separate, deliberate change under this same version). `0.7.0` published to npm at
|
|
100
|
+
`2026-08-11T21:17:42.790Z`. Two doc comments, in `src/client.ts` and `src/version.ts`, were
|
|
101
|
+
reworded **after** the commit that introduced the `0.7.0` version string — they had re-spelled
|
|
102
|
+
the `X-ByteKit-Client` header name in prose, which issue #2905's pre-merge gate 1 counts. No
|
|
103
|
+
exported function, type, or runtime behavior differs from `0.7.0`.
|
|
104
|
+
|
|
105
|
+
This release exists because `check-release-drift` (#2680) is version-gated and anchors on the
|
|
106
|
+
commit that introduced a version, not on the commit whose tree was actually published. Once
|
|
107
|
+
`0.7.0` reached npm, any shipped-file change after that anchor reads as post-release drift.
|
|
108
|
+
Bumping moves the anchor past those comments. The published `0.7.0` artifact is **not** stale in
|
|
109
|
+
any way a consumer can observe — the divergence is comment text only.
|
|
110
|
+
|
|
111
|
+
## [0.7.0] - 2026-08-11
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- **Every outbound request now carries `X-ByteKit-Client: sdk_ts/<version>`.** The SDK identifies
|
|
116
|
+
itself with the sanctioned `client_surface` marker (issue #2905, slice 2 of #2701), so requests
|
|
117
|
+
made through `@hunt-labs/bytekit-sdk` are distinguishable from raw API calls in ByteKit's own
|
|
118
|
+
analytics instead of all resolving to `api_direct`. `sdk_ts` is a member of the closed
|
|
119
|
+
`client_surface` vocabulary declared in issue #2904; the version affix is this package's own
|
|
120
|
+
version, baked in at build time from `package.json`.
|
|
121
|
+
|
|
122
|
+
Set at exactly ONE place — the header literal inside the private transport every request funnels
|
|
123
|
+
through — so it rides on the JSON path, the raw `/v1/fetch` path and every resource method
|
|
124
|
+
alike. **Nothing else about a request changed:** same `Authorization` and `Content-Type`, same
|
|
125
|
+
body bytes, same client-side abort budget, same error taxonomy, same return shapes. The marker
|
|
126
|
+
carries no caller data and cannot be set, overridden or read by callers — there is no
|
|
127
|
+
`headers` option on `ByteKitOptions` or `RequestOptions`.
|
|
128
|
+
|
|
129
|
+
Minor rather than patch because the wire format of every request changes, even though no
|
|
130
|
+
documented API does. A gateway that does not yet recognize the header ignores it.
|
|
131
|
+
|
|
132
|
+
- `SDK_VERSION` — an internal, build-time-generated constant (`src/version.ts`, written by
|
|
133
|
+
`pnpm gen:version` from `package.json` and gated by `src/__tests__/version-parity.test.ts`).
|
|
134
|
+
It backs the marker's version affix. **Not part of the public export surface**;
|
|
135
|
+
`package.json`'s `version` field remains the only version consumers should read.
|
|
136
|
+
|
|
137
|
+
### Unchanged
|
|
138
|
+
|
|
139
|
+
- **Still ZERO runtime dependencies.** The `client_surface` vocabulary lives in an internal,
|
|
140
|
+
unpublished workspace package, so the emitted value is a string literal here and the binding to
|
|
141
|
+
that registry is a test-only import. `dependencies` stays empty, asserted by
|
|
142
|
+
`src/__tests__/package-manifest.test.ts`.
|
|
143
|
+
|
|
144
|
+
## [0.6.2] - 2026-08-11 [NEVER PUBLISHED]
|
|
145
|
+
|
|
146
|
+
**This version was cut but NEVER PUBLISHED — npm `latest` went from 0.6.1 straight to 0.7.0.**
|
|
147
|
+
The two documentation/regeneration changes below reached consumers in the **0.7.0** artifact,
|
|
148
|
+
which contains all of them. Nothing under this heading is missing from 0.7.0, and nothing is
|
|
149
|
+
installable at 0.6.2: `npm i @hunt-labs/bytekit-sdk@0.6.2` fails.
|
|
150
|
+
|
|
151
|
+
Why it was stranded: 0.6.2 was cut for two `src/generated/api.d.ts` regenerations, and the next
|
|
152
|
+
change (issue #2905's new outbound request header) altered the wire format of every request —
|
|
153
|
+
additive behavior that belongs at a MINOR, not a patch. Folding it into the still-unpublished
|
|
154
|
+
0.6.2 would have shipped a new request header to consumers pinning `^0.6.1` unannounced, so 0.7.0
|
|
155
|
+
was cut instead and this heading annotated per `ci/scripts/check-release-drift.sh`'s
|
|
156
|
+
reconciliation form (#2680).
|
|
157
|
+
|
|
158
|
+
### Documentation
|
|
159
|
+
|
|
160
|
+
- **`AccountSessionResponse.has_activity` now documents what it actually means.** The generated
|
|
161
|
+
type's JSDoc previously said the flag was true once the account had "ever recorded billable
|
|
162
|
+
activity", which read as "ever made a request". It is true only once a request has
|
|
163
|
+
**successfully completed and been charged credits** — a request that failed does not flip it,
|
|
164
|
+
even when its bandwidth was billed (issue #2890). The doc comment also now states the
|
|
165
|
+
all-time (never windowed) scope and the up-to-one-rollup lag, so a caller polling it after a
|
|
166
|
+
first request knows `false` can mean "not visible yet" rather than "never made a request".
|
|
167
|
+
Regenerated from `docs/api/openapi.yaml`; the emitted TYPE is unchanged
|
|
168
|
+
(`has_activity: boolean`), so this release is source-compatible in both directions.
|
|
169
|
+
|
|
170
|
+
### Changed
|
|
171
|
+
|
|
172
|
+
- Regenerated `src/generated/api.d.ts` from `docs/api/openapi.yaml` after issue #2904 declared the
|
|
173
|
+
optional `X-ByteKit-Client` request header as `components.parameters.ClientSurfaceMarker`. The
|
|
174
|
+
regeneration is ADDITIVE and touches no method signature: one entry appears under
|
|
175
|
+
`components["parameters"]`, because the parameter is deliberately `$ref`-ed from no operation.
|
|
176
|
+
**No consumer-visible change** — no exported function, type or runtime behavior differs from
|
|
177
|
+
0.6.1. The entry exists because `check-release-drift` (#2680) requires a version bump for any
|
|
178
|
+
post-release change to a shipped file, and the publish pipeline is version-gated.
|
|
179
|
+
|
|
180
|
+
Documented under 0.6.2 alongside the #2890 regeneration above, rather than under a 0.6.3 of its
|
|
181
|
+
own, because 0.6.2 has been CUT BUT NOT PUBLISHED (npm `latest` is 0.6.1). Both regenerations
|
|
182
|
+
therefore ship in the same single artifact. Numbering this 0.6.3 would leave 0.6.2 documented and
|
|
183
|
+
unpublishable — the version-gated pipeline would publish 0.6.3 and skip it — which is precisely
|
|
184
|
+
the phantom-version class #2680 exists to kill, and `check-release-drift` rejects it by name.
|
|
185
|
+
|
|
11
186
|
## [0.6.1] - 2026-08-10
|
|
12
187
|
|
|
13
188
|
### Changed
|
|
@@ -332,6 +507,11 @@ against 0.1.0 — read each one before upgrading.
|
|
|
332
507
|
(scrape, screenshot, search, and related endpoints), published under the original
|
|
333
508
|
`@rapidcrawl/sdk` name.
|
|
334
509
|
|
|
510
|
+
[Unreleased]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
511
|
+
[0.7.1]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
512
|
+
[0.7.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
513
|
+
[0.6.2]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
514
|
+
[0.6.1]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
335
515
|
[0.6.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
336
516
|
[0.5.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
|
337
517
|
[0.4.0]: https://github.com/Hunt-Labs-Inc/ByteKit/tree/main/packages/sdk-typescript
|
package/README.md
CHANGED
|
@@ -233,6 +233,56 @@ These siblings are purely additive: they issue the identical request and accept
|
|
|
233
233
|
identical options as their base methods, and `data` is exactly what the base method
|
|
234
234
|
resolves to — no existing return type changes.
|
|
235
235
|
|
|
236
|
+
## Timeouts and cancellation
|
|
237
|
+
|
|
238
|
+
Every request carries a **client-side** abort budget covering the whole HTTP
|
|
239
|
+
round-trip — time-to-headers _and_ the response body read. It defaults to
|
|
240
|
+
120000 ms and is set on the constructor:
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { ByteKit } from '@hunt-labs/bytekit-sdk';
|
|
244
|
+
|
|
245
|
+
const bounded = new ByteKit({
|
|
246
|
+
apiKey: process.env.BYTEKIT_API_KEY!,
|
|
247
|
+
timeoutMs: 30_000, // client-side abort budget for every call; 0 disables it
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`timeoutMs` is **not** `ScrapeOpts.timeout_ms`. The former is how long this SDK
|
|
252
|
+
waits on the wire; the latter is the server-side budget the gateway applies to
|
|
253
|
+
the scrape itself.
|
|
254
|
+
|
|
255
|
+
### `signal` replaces the default timeout — `requestTimeoutMs` keeps it
|
|
256
|
+
|
|
257
|
+
Passing your own `AbortSignal` **silently disables the constructor's
|
|
258
|
+
`timeoutMs`**: the signal becomes the request's only abort source, so a client
|
|
259
|
+
built with `timeoutMs: 200` waits indefinitely if the signal never fires. That
|
|
260
|
+
is deliberate — a caller who brought their own cancellation owns it — but it is
|
|
261
|
+
easy to hit by accident. The escape hatch is `requestTimeoutMs`, which is
|
|
262
|
+
composed _with_ your signal rather than replaced by it, so the request aborts on
|
|
263
|
+
whichever fires first:
|
|
264
|
+
|
|
265
|
+
| `signal` | `requestTimeoutMs` | what bounds the request |
|
|
266
|
+
| -------- | ------------------ | ------------------------------- |
|
|
267
|
+
| absent | absent | the constructor's `timeoutMs` |
|
|
268
|
+
| absent | present | `requestTimeoutMs` |
|
|
269
|
+
| present | absent | your signal **only** — no timer |
|
|
270
|
+
| present | present | whichever fires first |
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
const controller = new AbortController();
|
|
274
|
+
|
|
275
|
+
// Cancellable AND bounded: aborts on controller.abort() or after 5 s.
|
|
276
|
+
await client.scrape.create(
|
|
277
|
+
{ url: 'https://example.com' },
|
|
278
|
+
{ signal: controller.signal, requestTimeoutMs: 5_000 },
|
|
279
|
+
);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
`0` at either level means "no SDK-side timeout". A request that never produced
|
|
283
|
+
an HTTP response at all throws `ByteKitConnectionError`, whose `code`
|
|
284
|
+
distinguishes `'timeout'` from `'aborted'` and `'connection'`.
|
|
285
|
+
|
|
236
286
|
## Error handling
|
|
237
287
|
|
|
238
288
|
Any 4xx/5xx response throws a `ByteKitError` carrying the HTTP status and
|
|
@@ -286,6 +336,38 @@ body instead (`/v1/search` returns `502 {"error":"search_provider_error"}`);
|
|
|
286
336
|
those carry no structured detail, so `err.details` stays `undefined` there —
|
|
287
337
|
`err.code` is still the machine-readable reason.
|
|
288
338
|
|
|
339
|
+
### Rate limits, `Retry-After`, and your own backoff
|
|
340
|
+
|
|
341
|
+
This SDK performs **exactly one** `fetch` per call and never retries — retry
|
|
342
|
+
policy stays yours. To make that policy writable, `err.headers` carries the
|
|
343
|
+
response headers of the failing request, so `Retry-After` and the
|
|
344
|
+
`X-RateLimit-*` family are readable straight off the error:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import { ByteKit, ByteKitError } from '@hunt-labs/bytekit-sdk';
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
await client.scrape.create({ url: 'https://example.com' });
|
|
351
|
+
} catch (err) {
|
|
352
|
+
if (err instanceof ByteKitError && err.status === 429) {
|
|
353
|
+
const retryAfter = err.headers?.get('Retry-After'); // string | null | undefined
|
|
354
|
+
const waitMs =
|
|
355
|
+
retryAfter === null || retryAfter === undefined ? 1000 : Number(retryAfter) * 1000;
|
|
356
|
+
console.error(`rate limited; retry in ${waitMs}ms`, err.headers?.get('X-RateLimit-Remaining'));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
It is the runtime's own `Headers` object, so `get()` is case-insensitive —
|
|
362
|
+
`get('Retry-After')` and `get('retry-after')` are the same lookup. It is present
|
|
363
|
+
on every error thrown from a real HTTP response and `undefined` on an error you
|
|
364
|
+
constructed yourself, which is why the reads above are optional-chained. Only
|
|
365
|
+
**response** headers are here: `Authorization` rides on the request and is never
|
|
366
|
+
reachable through it. `status`, `code`, `message` and `details` are unchanged.
|
|
367
|
+
|
|
368
|
+
`ByteKitConnectionError` — thrown when no HTTP response was produced at all —
|
|
369
|
+
carries no headers, because there was no response to read them from.
|
|
370
|
+
|
|
289
371
|
## Documentation
|
|
290
372
|
|
|
291
373
|
Full API reference: [bytekit.com/docs](https://bytekit.com/docs).
|
package/dist/client.d.ts
CHANGED
|
@@ -119,7 +119,40 @@ export declare class ByteKitError extends Error {
|
|
|
119
119
|
* so the key exists only when the envelope really supplied one.
|
|
120
120
|
*/
|
|
121
121
|
readonly details?: ByteKitErrorDetails;
|
|
122
|
-
|
|
122
|
+
/**
|
|
123
|
+
* The RESPONSE headers of the failing HTTP response (issue #2957).
|
|
124
|
+
*
|
|
125
|
+
* This SDK performs exactly ONE `fetch` per call and never retries — a deliberate
|
|
126
|
+
* design, so that retry policy stays the caller's. That is only a defensible position
|
|
127
|
+
* if the caller can actually IMPLEMENT a policy, and until this field existed they
|
|
128
|
+
* could not: `requestWithResponse` returns headers on 2xx only, and a rate-limited
|
|
129
|
+
* request never reaches a 2xx. `Retry-After` and the `X-RateLimit-*` family were
|
|
130
|
+
* therefore unreachable through the SDK at every entry point.
|
|
131
|
+
*
|
|
132
|
+
* ```ts
|
|
133
|
+
* catch (err) {
|
|
134
|
+
* if (err instanceof ByteKitError && err.status === 429) {
|
|
135
|
+
* const wait = Number(err.headers?.get('Retry-After') ?? 1) * 1000;
|
|
136
|
+
* }
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* It is the runtime's own `Headers` object, carried by reference rather than
|
|
141
|
+
* snapshotted into a plain record, so `get()` stays CASE-INSENSITIVE per the WHATWG
|
|
142
|
+
* spec — `get('Retry-After')` and `get('retry-after')` are the same lookup whatever
|
|
143
|
+
* casing undici put on the wire (E1). Only RESPONSE headers are here; `Authorization`
|
|
144
|
+
* lives on the REQUEST and is never reachable through it, exactly as for
|
|
145
|
+
* {@link ApiResponse.headers}.
|
|
146
|
+
*
|
|
147
|
+
* Present on every error thrown from a real HTTP response, and absent on an error
|
|
148
|
+
* constructed by hand without one. `declare` is load-bearing for the same reason it is
|
|
149
|
+
* on `details` above: `target: ES2022` turns on `useDefineForClassFields`, so a plain
|
|
150
|
+
* `headers?: …` declaration would emit a class field and DEFINE the key as `undefined`
|
|
151
|
+
* on every instance, changing `'headers' in err`, spreads and `JSON.stringify` output
|
|
152
|
+
* for every error that carries none.
|
|
153
|
+
*/
|
|
154
|
+
readonly headers?: Headers;
|
|
155
|
+
constructor(status: number, code: string, message: string, details?: ByteKitErrorDetails, headers?: Headers);
|
|
123
156
|
}
|
|
124
157
|
/**
|
|
125
158
|
* Thrown when the request never produced an HTTP response at all — DNS, socket, TLS,
|
package/dist/client.js
CHANGED
|
@@ -8,6 +8,7 @@ import { SearchResource } from './resources/search.js';
|
|
|
8
8
|
import { AccountResource } from './resources/account.js';
|
|
9
9
|
import { UsageResource } from './resources/usage.js';
|
|
10
10
|
import { WebhooksResource } from './resources/webhooks.js';
|
|
11
|
+
import { SDK_VERSION } from './version.js';
|
|
11
12
|
const DEFAULT_BASE_URL = 'https://api.bytekit.com';
|
|
12
13
|
/**
|
|
13
14
|
* Default client-side request timeout (2 minutes).
|
|
@@ -21,7 +22,7 @@ const DEFAULT_TIMEOUT_MS = 120_000;
|
|
|
21
22
|
export class ByteKitError extends Error {
|
|
22
23
|
status;
|
|
23
24
|
code;
|
|
24
|
-
constructor(status, code, message, details) {
|
|
25
|
+
constructor(status, code, message, details, headers) {
|
|
25
26
|
super(message);
|
|
26
27
|
this.name = 'ByteKitError';
|
|
27
28
|
this.status = status;
|
|
@@ -31,6 +32,11 @@ export class ByteKitError extends Error {
|
|
|
31
32
|
if (details !== undefined) {
|
|
32
33
|
this.details = details;
|
|
33
34
|
}
|
|
35
|
+
// Same discipline for the #2957 additive field: `headers` is OPTIONAL and LAST, so
|
|
36
|
+
// every pre-existing three- and four-argument construction is byte-identical.
|
|
37
|
+
if (headers !== undefined) {
|
|
38
|
+
this.headers = headers;
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
@@ -362,6 +368,20 @@ export class ByteKit {
|
|
|
362
368
|
headers: {
|
|
363
369
|
Authorization: `Bearer ${this.apiKey}`,
|
|
364
370
|
'Content-Type': 'application/json',
|
|
371
|
+
// The client_surface marker (issue #2905, slice 2 of #2701). Its NAME is
|
|
372
|
+
// `CLIENT_SURFACE_HEADER` and its `<surface>/<version>` shape and closed vocabulary
|
|
373
|
+
// `CLIENT_SURFACES` are declared in `@bytekit/analytics-contract` — deliberately
|
|
374
|
+
// spelled as literals HERE and not imported, because this package publishes with ZERO
|
|
375
|
+
// runtime dependencies and a `workspace:*` dependency on that private, unpublished
|
|
376
|
+
// package would break the published artifact. The binding to the registry is a
|
|
377
|
+
// TEST-ONLY import, in `client-surface-marker.test.ts`.
|
|
378
|
+
//
|
|
379
|
+
// This is the SINGLE emit site by construction: `send()` is the one transport both
|
|
380
|
+
// `request()` and `requestRaw()` funnel through, so a per-resource or per-method emit
|
|
381
|
+
// would be a duplicate rather than a completeness fix (#2905 E4). The ticket's pre-merge
|
|
382
|
+
// gate 1 counts occurrences of the header name in non-test `src/` and expects exactly
|
|
383
|
+
// one — the line below — which is why the prose above names the constant instead.
|
|
384
|
+
'X-ByteKit-Client': `sdk_ts/${SDK_VERSION}`,
|
|
365
385
|
},
|
|
366
386
|
};
|
|
367
387
|
if (body !== undefined) {
|
|
@@ -416,7 +436,12 @@ export class ByteKit {
|
|
|
416
436
|
// leave defaults — including when the error body itself stalls and the
|
|
417
437
|
// budget aborts the read (#2546), so a stuck 500 still surfaces its status.
|
|
418
438
|
}
|
|
419
|
-
|
|
439
|
+
// `response.headers` is attached to EVERY non-2xx, from this one throw site —
|
|
440
|
+
// the canonical-envelope arm, the flat vendor-masked arm and the unparseable-body
|
|
441
|
+
// `catch` above all land here, so a rate-limited caller can read `Retry-After`
|
|
442
|
+
// whatever shape the error body took (#2957). It is the response's own `Headers`
|
|
443
|
+
// instance, so lookups stay case-insensitive (E1).
|
|
444
|
+
throw new ByteKitError(response.status, code, message, details, response.headers);
|
|
420
445
|
}
|
|
421
446
|
try {
|
|
422
447
|
return await readBody(response);
|
package/dist/generated/api.d.ts
CHANGED
|
@@ -1351,11 +1351,21 @@ export interface components {
|
|
|
1351
1351
|
* @example 100000000000
|
|
1352
1352
|
*/
|
|
1353
1353
|
included_bytes: number;
|
|
1354
|
+
/**
|
|
1355
|
+
* @description Included credits per period.
|
|
1356
|
+
* @example 100000
|
|
1357
|
+
*/
|
|
1358
|
+
included_credits: number;
|
|
1354
1359
|
/**
|
|
1355
1360
|
* @description Bandwidth top-up price per MB, in cents.
|
|
1356
1361
|
* @example 0.25
|
|
1357
1362
|
*/
|
|
1358
1363
|
topup_price_per_mb_cents: number;
|
|
1364
|
+
/**
|
|
1365
|
+
* @description Credit top-up price per 1,000 credits, in cents.
|
|
1366
|
+
* @example 150
|
|
1367
|
+
*/
|
|
1368
|
+
credit_topup_price_per_k_cents: number;
|
|
1359
1369
|
/** @example 50 */
|
|
1360
1370
|
max_concurrency: number;
|
|
1361
1371
|
/** @example 50 */
|
|
@@ -1568,7 +1578,7 @@ export interface components {
|
|
|
1568
1578
|
};
|
|
1569
1579
|
ScrapeWarning: {
|
|
1570
1580
|
/** @enum {string} */
|
|
1571
|
-
code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed";
|
|
1581
|
+
code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed" | "low_quality_extraction" | "fragment_menu_stripped";
|
|
1572
1582
|
message: string;
|
|
1573
1583
|
element: string | null;
|
|
1574
1584
|
};
|
|
@@ -1720,7 +1730,7 @@ export interface components {
|
|
|
1720
1730
|
stats?: components["schemas"]["ScrapeStats"];
|
|
1721
1731
|
/** @description Token-budget accounting. Present only when `token_budget` was supplied in the request. Contains `kept` (tokens in returned markdown), `total` (tokens in full pre-truncation markdown), and `truncated` (whether output was cut). Absent on uncapped requests to avoid noise. */
|
|
1722
1732
|
markdown_tokens?: components["schemas"]["ScrapeMarkdownTokens"];
|
|
1723
|
-
/** @description The multiplier applied to wire bytes to compute `billed_bytes` for this call (
|
|
1733
|
+
/** @description The multiplier applied to wire bytes to compute `billed_bytes` for this call (1.0-2.0 for format combinations on a cache miss). The value is pre-clean-markdown: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this number, and that surcharge is carried by neither this field nor the `X-Billing-Multiplier` response header — so on a successful clean neither surface predicts the amount you are billed. This field reports the BASE-endpoint composition, so every cache hit reads a flat 0.5 here whatever formats were requested — the per-endpoint format factor is applied later, at report time, by `GET /v1/usage/by-endpoint`. It can therefore differ from the `X-Billing-Multiplier` response header, which carries the composed real-endpoint value: a markdown cache hit reads 0.5 in this field and 0.75 in that header. Present whenever this call's billing amount has been finalized; omitted if unavailable. */
|
|
1724
1734
|
billing_multiplier?: number;
|
|
1725
1735
|
/** @description The actual bandwidth billed for this call — `round(content_length * billing_multiplier)`. Present alongside `billing_multiplier`. */
|
|
1726
1736
|
billed_bytes?: number;
|
|
@@ -1770,7 +1780,7 @@ export interface components {
|
|
|
1770
1780
|
id: string | null;
|
|
1771
1781
|
error: {
|
|
1772
1782
|
/** @enum {string} */
|
|
1773
|
-
code: "validation_error" | "invalid_url" | "request_too_large" | "
|
|
1783
|
+
code: "validation_error" | "invalid_url" | "request_too_large" | "payload_too_large" | "unsupported_content_type" | "rate_limited" | "upstream_error" | "blocked" | "timeout" | "internal_error";
|
|
1774
1784
|
message: string;
|
|
1775
1785
|
http_status?: number;
|
|
1776
1786
|
/** Format: date-time */
|
|
@@ -2495,7 +2505,7 @@ export interface components {
|
|
|
2495
2505
|
terms_version: string;
|
|
2496
2506
|
/** Format: date-time */
|
|
2497
2507
|
created_at: string;
|
|
2498
|
-
/** @description True once the account has
|
|
2508
|
+
/** @description True once the account has SUCCESSFULLY COMPLETED at least one billable request (a scrape/screenshot/fetch/… that settled and was charged credits), regardless of whether it was authenticated with a Clerk session or an API key. All-time — never windowed. A request that failed does not flip it, even when its bandwidth was billed: the monitor terminal-preflight-failure path records bytes without credits, and only the credited settlement counts here. Powers the dashboard onboarding gate — the app shows the guided onboarding flow until this is true, then the dashboard. Lags by up to one usage rollup: the completion service writes the row after the response is returned, so a just-completed first request may still read false for a moment. Treat that as "not visible yet", never as "this account has never made a request". */
|
|
2499
2509
|
has_activity: boolean;
|
|
2500
2510
|
};
|
|
2501
2511
|
/** @description Partial update payload for PATCH /v1/account. All fields are optional; at least one of name, email, or notifications must be provided. */
|
|
@@ -2538,19 +2548,45 @@ export interface components {
|
|
|
2538
2548
|
used_bytes: number;
|
|
2539
2549
|
limit_bytes: number;
|
|
2540
2550
|
remaining_bytes: number;
|
|
2551
|
+
/** @description Total spendable bytes remaining across purchased top-up and starter-grant lots, after active refund reservations. */
|
|
2541
2552
|
topup_bytes: number;
|
|
2553
|
+
/** @description Bytes remaining in purchased top-up lots, after active refund reservations. Starter-grant bytes are excluded. */
|
|
2554
|
+
purchased_topup_bytes: number;
|
|
2555
|
+
/** @description Bytes remaining in starter-grant lots, after active refund reservations. Purchased top-up bytes are excluded. */
|
|
2556
|
+
granted_topup_bytes: number;
|
|
2542
2557
|
rollover_bytes: number;
|
|
2543
2558
|
};
|
|
2544
2559
|
CreditBalance: {
|
|
2545
2560
|
used: number;
|
|
2546
2561
|
limit: number;
|
|
2547
2562
|
remaining: number;
|
|
2563
|
+
/** @description Total spendable credits remaining across purchased top-up and starter-grant lots, after active refund reservations. */
|
|
2548
2564
|
topup_credits: number;
|
|
2565
|
+
/** @description Credits remaining in purchased top-up lots, after active refund reservations. Starter-grant credits are excluded. */
|
|
2566
|
+
purchased_topup_credits: number;
|
|
2567
|
+
/** @description Credits remaining in starter-grant lots, after active refund reservations. Purchased top-up credits are excluded. */
|
|
2568
|
+
granted_topup_credits: number;
|
|
2549
2569
|
rollover_credits: number;
|
|
2550
2570
|
};
|
|
2551
2571
|
};
|
|
2552
2572
|
responses: never;
|
|
2553
2573
|
parameters: {
|
|
2574
|
+
/**
|
|
2575
|
+
* @description Optional. Identifies which published ByteKit client sent the request, as
|
|
2576
|
+
* `<surface>/<version>`. The surface comes from a closed set — `api_direct`, `sdk_ts`,
|
|
2577
|
+
* `sdk_python`, `cli`, `mcp` — and the version affix is the emitting client's own version.
|
|
2578
|
+
*
|
|
2579
|
+
* You do not need to send this. ByteKit's own clients set it for you, and a request that
|
|
2580
|
+
* omits it is authenticated, rate-limited, quota-checked, billed and answered exactly as one
|
|
2581
|
+
* that sends it. Requests without the header are attributed to `api_direct`.
|
|
2582
|
+
*
|
|
2583
|
+
* A header that is absent, unrecognized or malformed is attributed to `api_direct` and the
|
|
2584
|
+
* value you sent is discarded — never stored and never logged. The header never changes how a
|
|
2585
|
+
* request is routed, priced or prioritised, and `User-Agent` is never used as a substitute
|
|
2586
|
+
* for it.
|
|
2587
|
+
* @example sdk_ts/1.4.0
|
|
2588
|
+
*/
|
|
2589
|
+
ClientSurfaceMarker: string;
|
|
2554
2590
|
FetchUrl: string;
|
|
2555
2591
|
FetchFormat: "markdown" | "html";
|
|
2556
2592
|
FetchCountry: string;
|
|
@@ -3293,7 +3329,7 @@ export interface operations {
|
|
|
3293
3329
|
"X-Raw-Bytes"?: number;
|
|
3294
3330
|
/** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
|
|
3295
3331
|
"X-Billable-Bytes"?: number;
|
|
3296
|
-
/** @description Bandwidth cost multiplier (e.g. 1.0 for raw_html-only, 1.5 for +markdown/html). Cache hits compose the endpoint format factor: raw 0.5, markdown 0.75. */
|
|
3332
|
+
/** @description Bandwidth cost multiplier (e.g. 1.0 for raw_html-only, 1.5 for +markdown/html). Cache hits compose the endpoint format factor: raw 0.5, markdown 0.75. Excludes the `clean_markdown` surcharge, exactly like the `billing_multiplier` body field: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this header's value, so neither surface predicts the amount you are billed. */
|
|
3297
3333
|
"X-Billing-Multiplier"?: number;
|
|
3298
3334
|
/** @description Credits charged for this scrape (multiplier applied to base 1.0 per format). */
|
|
3299
3335
|
"X-Scrape-Credits-Charged"?: number;
|
|
@@ -4131,7 +4167,7 @@ export interface operations {
|
|
|
4131
4167
|
* "device": "desktop",
|
|
4132
4168
|
* "country": "US",
|
|
4133
4169
|
* "formats": [
|
|
4134
|
-
* "
|
|
4170
|
+
* "raw_html"
|
|
4135
4171
|
* ],
|
|
4136
4172
|
* "device_scale_factor": 2
|
|
4137
4173
|
* },
|
|
@@ -4168,7 +4204,7 @@ export interface operations {
|
|
|
4168
4204
|
language?: string | null;
|
|
4169
4205
|
dark_mode?: boolean;
|
|
4170
4206
|
/** @description Scrape output formats (scrape entries). */
|
|
4171
|
-
formats?: ("
|
|
4207
|
+
formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
|
|
4172
4208
|
/** @enum {string} */
|
|
4173
4209
|
wait_until?: "load" | "domcontentloaded" | "networkidle";
|
|
4174
4210
|
wait_for_selector?: string | null;
|
|
@@ -4221,7 +4257,7 @@ export interface operations {
|
|
|
4221
4257
|
language?: string | null;
|
|
4222
4258
|
/** @default false */
|
|
4223
4259
|
dark_mode?: boolean;
|
|
4224
|
-
formats?: ("
|
|
4260
|
+
formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
|
|
4225
4261
|
/**
|
|
4226
4262
|
* @default load
|
|
4227
4263
|
* @enum {string}
|
|
@@ -5466,7 +5502,7 @@ export interface operations {
|
|
|
5466
5502
|
raw_bytes?: number | null;
|
|
5467
5503
|
/** @description Billable bytes — raw_bytes × billing_multiplier, rounded. Mirrors the X-Billable-Bytes response header. null while pending/failed. */
|
|
5468
5504
|
billable_bytes?: number | null;
|
|
5469
|
-
/** @description Billing multiplier applied to raw_bytes (e.g. 1.0 for raw scrape, 1.5 for markdown/screenshot)
|
|
5505
|
+
/** @description Billing multiplier applied to raw_bytes (e.g. 1.0 for raw scrape, 1.5 for markdown/screenshot). Unlike the scrape response body field of the same name, this row reports the real-endpoint composition — the one the X-Billing-Multiplier response header carries — so cache hits compose the endpoint format factor and a markdown cache hit reads 0.75 here while the response body field reads 0.5. Mirrors the X-Billing-Multiplier response header. null while pending/failed. */
|
|
5470
5506
|
billing_multiplier?: number | null;
|
|
5471
5507
|
duration_ms?: number | null;
|
|
5472
5508
|
/** @description How the request originated (single/bulk/monitor). */
|
|
@@ -118,19 +118,6 @@ export declare class ScrapeResource {
|
|
|
118
118
|
create(opts: ScrapeOpts, requestOptions?: RequestOptions): Promise<ScrapeCreateResponse>;
|
|
119
119
|
/**
|
|
120
120
|
* GET /v1/scrape/{id} — poll a scrape by ID
|
|
121
|
-
*
|
|
122
|
-
* KNOWN DRIFT (#2426): live staging spot-checks (two independent fetches)
|
|
123
|
-
* found the gateway serializes `billing_multiplier` as a JSON **string**
|
|
124
|
-
* (e.g. `"0.50"`) on this GET path, while the OpenAPI spec — and this
|
|
125
|
-
* derived `ScrapeGetResponse` type — declare it `number`. `POST /v1/scrape`'s
|
|
126
|
-
* success envelope for the same job serializes the identical field as a
|
|
127
|
-
* proper number, so the drift is specific to the GET path (likely a Postgres
|
|
128
|
-
* NUMERIC column round-tripping as a string on this query path). A consumer
|
|
129
|
-
* doing arithmetic on `billing_multiplier` after `get()` (e.g.
|
|
130
|
-
* `content_length * billing_multiplier`) should coerce with `Number(...)`
|
|
131
|
-
* defensively rather than trust the static type. This is a gateway/worker
|
|
132
|
-
* serialization bug, not a client bug — the fix belongs upstream in the
|
|
133
|
-
* gateway and is out of this ticket's scope.
|
|
134
121
|
*/
|
|
135
122
|
get(id: ScrapeId, requestOptions?: RequestOptions): Promise<ScrapeGetResponse>;
|
|
136
123
|
}
|
package/dist/resources/scrape.js
CHANGED
|
@@ -21,19 +21,6 @@ export class ScrapeResource {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* GET /v1/scrape/{id} — poll a scrape by ID
|
|
24
|
-
*
|
|
25
|
-
* KNOWN DRIFT (#2426): live staging spot-checks (two independent fetches)
|
|
26
|
-
* found the gateway serializes `billing_multiplier` as a JSON **string**
|
|
27
|
-
* (e.g. `"0.50"`) on this GET path, while the OpenAPI spec — and this
|
|
28
|
-
* derived `ScrapeGetResponse` type — declare it `number`. `POST /v1/scrape`'s
|
|
29
|
-
* success envelope for the same job serializes the identical field as a
|
|
30
|
-
* proper number, so the drift is specific to the GET path (likely a Postgres
|
|
31
|
-
* NUMERIC column round-tripping as a string on this query path). A consumer
|
|
32
|
-
* doing arithmetic on `billing_multiplier` after `get()` (e.g.
|
|
33
|
-
* `content_length * billing_multiplier`) should coerce with `Number(...)`
|
|
34
|
-
* defensively rather than trust the static type. This is a gateway/worker
|
|
35
|
-
* serialization bug, not a client bug — the fix belongs upstream in the
|
|
36
|
-
* gateway and is out of this ticket's scope.
|
|
37
24
|
*/
|
|
38
25
|
get(id, requestOptions) {
|
|
39
26
|
return this.client.request('GET', buildPath('/v1/scrape/{id}', { segments: { id } }), undefined, requestOptions);
|
|
@@ -90,8 +90,15 @@ export declare class ScreenshotsResource {
|
|
|
90
90
|
*
|
|
91
91
|
* Same request as `screenshots.get`, and `data` is exactly what `get()`
|
|
92
92
|
* resolves to (including the #2027 failed-envelope arm). `get()`'s own return type is
|
|
93
|
-
* UNCHANGED; this is an additive sibling.
|
|
94
|
-
*
|
|
93
|
+
* UNCHANGED; this is an additive sibling.
|
|
94
|
+
*
|
|
95
|
+
* Call it for the typed body, NOT for header metadata: the spec declares
|
|
96
|
+
* `GET /v1/screenshots/{id}` with NO `X-*` response headers, and a live GET returns
|
|
97
|
+
* none, so `headers` carries only the transport's own entries (`Content-Type`, …).
|
|
98
|
+
* The `X-Screenshot-*` / `X-Raw-Bytes` / `X-Billable-Bytes` / `X-Billing-Multiplier`
|
|
99
|
+
* family is emitted by `POST /v1/screenshots` — use `screenshots.createWithResponse`
|
|
100
|
+
* to read it (issue #2957). This matches `ByteKit.requestWithResponse` and the README,
|
|
101
|
+
* which are the truth for what this endpoint emits.
|
|
95
102
|
*/
|
|
96
103
|
getWithResponse(id: ScreenshotId, requestOptions?: RequestOptions): Promise<ApiResponse<ScreenshotGetResponse>>;
|
|
97
104
|
}
|
|
@@ -50,9 +50,22 @@ export class ScreenshotsResource {
|
|
|
50
50
|
*
|
|
51
51
|
* Same request as `screenshots.get`, and `data` is exactly what `get()`
|
|
52
52
|
* resolves to (including the #2027 failed-envelope arm). `get()`'s own return type is
|
|
53
|
-
* UNCHANGED; this is an additive sibling.
|
|
54
|
-
*
|
|
53
|
+
* UNCHANGED; this is an additive sibling.
|
|
54
|
+
*
|
|
55
|
+
* Call it for the typed body, NOT for header metadata: the spec declares
|
|
56
|
+
* `GET /v1/screenshots/{id}` with NO `X-*` response headers, and a live GET returns
|
|
57
|
+
* none, so `headers` carries only the transport's own entries (`Content-Type`, …).
|
|
58
|
+
* The `X-Screenshot-*` / `X-Raw-Bytes` / `X-Billable-Bytes` / `X-Billing-Multiplier`
|
|
59
|
+
* family is emitted by `POST /v1/screenshots` — use `screenshots.createWithResponse`
|
|
60
|
+
* to read it (issue #2957). This matches `ByteKit.requestWithResponse` and the README,
|
|
61
|
+
* which are the truth for what this endpoint emits.
|
|
55
62
|
*/
|
|
63
|
+
// NOTE (#2957): the doc block above deliberately spells sibling method names in plain
|
|
64
|
+
// backticks rather than as JSDoc link tags. `scripts/generate-docs.ts` copies these
|
|
65
|
+
// comments verbatim into the published reference and DROPS a link tag without emitting
|
|
66
|
+
// anything in its place, leaving a dangling "use to read it" — the very class of broken
|
|
67
|
+
// doc this correction exists to remove. Keep it a `//` comment: the generator would
|
|
68
|
+
// publish it too if it were part of the block.
|
|
56
69
|
getWithResponse(id, requestOptions) {
|
|
57
70
|
return this.client.requestWithResponse('GET', buildPath('/v1/screenshots/{id}', { segments: { id } }), undefined, requestOptions);
|
|
58
71
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published version of `@hunt-labs/bytekit-sdk`, baked in at build time.
|
|
3
|
+
*
|
|
4
|
+
* Used for the version affix of the client-surface marker (`sdk_ts/<version>`) that every
|
|
5
|
+
* outbound request carries — see the emit site in `client.ts`. The header name is spelled
|
|
6
|
+
* only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SDK_VERSION = "0.7.1";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// GENERATED FILE — do not edit by hand.
|
|
2
|
+
// Regenerate with `pnpm --filter @hunt-labs/bytekit-sdk gen:version` (also chained into `build`).
|
|
3
|
+
// Source of truth: this package's `package.json` "version" field.
|
|
4
|
+
// Guarded by `src/__tests__/version-parity.test.ts` (issue #2905, failure mode E5).
|
|
5
|
+
/**
|
|
6
|
+
* The published version of `@hunt-labs/bytekit-sdk`, baked in at build time.
|
|
7
|
+
*
|
|
8
|
+
* Used for the version affix of the client-surface marker (`sdk_ts/<version>`) that every
|
|
9
|
+
* outbound request carries — see the emit site in `client.ts`. The header name is spelled
|
|
10
|
+
* only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
|
|
11
|
+
*/
|
|
12
|
+
export const SDK_VERSION = '0.7.1';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hunt-labs/bytekit-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Official TypeScript SDK for the ByteKit API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -48,8 +48,9 @@
|
|
|
48
48
|
"url": "https://bytekit.com/contact"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
|
-
"build": "rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json && mkdir -p dist/generated && cp src/generated/api.d.ts dist/generated/api.d.ts",
|
|
51
|
+
"build": "pnpm gen:version && rm -rf dist tsconfig.tsbuildinfo tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json && mkdir -p dist/generated && cp src/generated/api.d.ts dist/generated/api.d.ts",
|
|
52
52
|
"gen:types": "openapi-typescript ../../docs/api/openapi.yaml -o src/generated/api.d.ts",
|
|
53
|
+
"gen:version": "tsx scripts/gen-version.ts",
|
|
53
54
|
"gen:types-check": "pnpm gen:types && git diff --exit-code src/generated/api.d.ts",
|
|
54
55
|
"generate:docs": "tsx scripts/generate-docs.ts",
|
|
55
56
|
"typecheck": "tsc --noEmit",
|