@dropthis/cli 0.23.0 → 0.24.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/README.md +2 -2
- package/dist/cli.cjs +35 -47
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +34 -5
- package/node_modules/@dropthis/node/dist/{drops-DNwOp7g_.d.cts → drops-BVoN5MaZ.d.cts} +55 -8
- package/node_modules/@dropthis/node/dist/{drops-DNwOp7g_.d.ts → drops-BVoN5MaZ.d.ts} +55 -8
- package/node_modules/@dropthis/node/dist/edge.cjs +44 -16
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.cts +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.ts +1 -1
- package/node_modules/@dropthis/node/dist/edge.mjs +44 -16
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.cjs +50 -16
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +8 -2
- package/node_modules/@dropthis/node/dist/index.d.ts +8 -2
- package/node_modules/@dropthis/node/dist/index.mjs +50 -16
- package/node_modules/@dropthis/node/dist/index.mjs.map +1 -1
- package/node_modules/@dropthis/node/package.json +1 -1
- package/package.json +2 -2
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<p align="center"><img src="https://dropthis.app/icon-512.png" width="76" height="76" alt="dropthis" /></p>
|
|
2
|
+
|
|
1
3
|
# @dropthis/node
|
|
2
4
|
|
|
3
5
|
Official Node.js SDK for [dropthis](https://dropthis.app) -- the publish layer between AI and the internet. One API call in, one URL out.
|
|
@@ -275,6 +277,15 @@ if (result.error) {
|
|
|
275
277
|
|
|
276
278
|
Local input validation errors (e.g. `file_not_found`) are also returned as `{ error: { code: "file_not_found", ... } }` rather than thrown -- except for `prepare()`, which throws `PublishInputError`.
|
|
277
279
|
|
|
280
|
+
`error.retryable` tells an agent whether retrying is worthwhile. The SDK marks its own
|
|
281
|
+
transient failures `retryable: true` only when retrying is safe: a `GET` `timeout` /
|
|
282
|
+
`network_error`, any request you sent with an `idempotencyKey`, or a signed-upload `5xx`.
|
|
283
|
+
A bare (non-idempotent) `POST`/`PATCH`/`DELETE` timeout is left unmarked because the
|
|
284
|
+
server may have applied it before the connection dropped. Server-side errors carry
|
|
285
|
+
whatever `retryable` the API returns (the SDK never overrides it). `publish()` and
|
|
286
|
+
`updateContent()` are always safe to retry — each derives a stable idempotency key, so a
|
|
287
|
+
retried publish never creates a duplicate drop.
|
|
288
|
+
|
|
278
289
|
## Configuration
|
|
279
290
|
|
|
280
291
|
```typescript
|
|
@@ -313,14 +324,21 @@ List results support auto-pagination:
|
|
|
313
324
|
|
|
314
325
|
```typescript
|
|
315
326
|
const page = await dropthis.drops.list();
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
//
|
|
319
|
-
|
|
320
|
-
console.log(drop.url);
|
|
327
|
+
const all = await page.data.autoPagingToArray({ limit: 100 });
|
|
328
|
+
if (all.error) {
|
|
329
|
+
// a later page failed to fetch — inspect all.error.code / statusCode / requestId
|
|
330
|
+
} else {
|
|
331
|
+
for (const drop of all.data) console.log(drop.url);
|
|
321
332
|
}
|
|
322
333
|
```
|
|
323
334
|
|
|
335
|
+
Like every call in this SDK, `autoPagingToArray()` **never throws** for an API error — it
|
|
336
|
+
returns the same `{ data, error }` result shape. On success you get `{ data: items, error: null }`;
|
|
337
|
+
if fetching a later page fails you get `{ data: null, error }` carrying the underlying
|
|
338
|
+
`code` / `statusCode` / `retryable` / `requestId`. So you can never be handed a silently
|
|
339
|
+
truncated list, and you never have to wrap pagination in `try/catch`. (For manual control,
|
|
340
|
+
loop on `dropthis.drops.list({ cursor })` and check each result's `.error`.)
|
|
341
|
+
|
|
324
342
|
> To change a drop's content, use `client.drops.updateContent(dropId, newInput)`. `drops.updateSettings()` is for settings only (title, visibility, password, noindex, expiresAt, metadata).
|
|
325
343
|
|
|
326
344
|
### deployments
|
|
@@ -352,6 +370,8 @@ await dropthis.auth.verifyEmailOtp({ email: "you@example.com", code: "123456" })
|
|
|
352
370
|
await dropthis.auth.logout(); // 204 No Content — data is null
|
|
353
371
|
```
|
|
354
372
|
|
|
373
|
+
> On a failed verify the error `code` is `otp_expired` (no active code — request a new one) or `otp_invalid` (wrong digits — re-check, don't auto-resend). 401 on either.
|
|
374
|
+
|
|
355
375
|
### apiKeys
|
|
356
376
|
|
|
357
377
|
```typescript
|
|
@@ -464,11 +484,20 @@ import type {
|
|
|
464
484
|
PublishInput,
|
|
465
485
|
PublishFileInput,
|
|
466
486
|
ListPage,
|
|
487
|
+
KeyType,
|
|
488
|
+
RevokeImpact,
|
|
467
489
|
CreateUploadSessionRequest,
|
|
468
490
|
CreateUploadSessionResponse,
|
|
469
491
|
} from "@dropthis/node";
|
|
470
492
|
```
|
|
471
493
|
|
|
494
|
+
`PublishInputError` (thrown only for programmer errors when building a publish input,
|
|
495
|
+
never for API failures) is a runtime export:
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
import { PublishInputError } from "@dropthis/node";
|
|
499
|
+
```
|
|
500
|
+
|
|
472
501
|
## Agent skills
|
|
473
502
|
|
|
474
503
|
For AI coding agents (Cursor, Claude Code, Windsurf, etc.), install the [dropthis-skills](https://github.com/dropthis-dev/dropthis-skills) package:
|
|
@@ -77,6 +77,10 @@ type DropResponse = {
|
|
|
77
77
|
noindex: boolean;
|
|
78
78
|
passwordProtected: boolean;
|
|
79
79
|
metadata: Record<string, unknown>;
|
|
80
|
+
/** When the drop was last updated (content or settings), ISO 8601. */
|
|
81
|
+
updatedAt: string;
|
|
82
|
+
/** Origin that created the drop (e.g. "api", "cli", "mcp"); null/omitted when unattributed. */
|
|
83
|
+
source?: string | null;
|
|
80
84
|
object: string;
|
|
81
85
|
accessible: boolean;
|
|
82
86
|
persistent: boolean;
|
|
@@ -131,8 +135,7 @@ type ListPage<T> = {
|
|
|
131
135
|
nextCursor: string | null;
|
|
132
136
|
autoPagingToArray(options?: {
|
|
133
137
|
limit?: number;
|
|
134
|
-
}): Promise<T[]
|
|
135
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
138
|
+
}): Promise<DropthisResult<T[]>>;
|
|
136
139
|
};
|
|
137
140
|
type Action = {
|
|
138
141
|
code: string;
|
|
@@ -142,7 +145,8 @@ type Action = {
|
|
|
142
145
|
message: string;
|
|
143
146
|
};
|
|
144
147
|
type EmailOtpResponse = {
|
|
145
|
-
|
|
148
|
+
/** Always `true` on success; optional because the server defaults it. */
|
|
149
|
+
ok?: true;
|
|
146
150
|
expiresIn: number;
|
|
147
151
|
nextAction?: Action | null;
|
|
148
152
|
};
|
|
@@ -152,12 +156,35 @@ type SessionResponse = {
|
|
|
152
156
|
accountId: string;
|
|
153
157
|
isNewAccount: boolean;
|
|
154
158
|
expiresIn: number;
|
|
159
|
+
/**
|
|
160
|
+
* Rotating refresh token for a console browser session. Present when a session is
|
|
161
|
+
* started (email/verify, refresh); `null`/omitted for non-session token issuance.
|
|
162
|
+
*/
|
|
163
|
+
refreshToken?: string | null;
|
|
155
164
|
};
|
|
165
|
+
/**
|
|
166
|
+
* Why an API key exists. `standard` keys are created by the user (CLI/SDK/manual);
|
|
167
|
+
* `mcp_oauth` keys are minted per connected client by the MCP OAuth flow and carry a
|
|
168
|
+
* more generous quota.
|
|
169
|
+
*/
|
|
170
|
+
type KeyType = "standard" | "mcp_oauth";
|
|
171
|
+
/** What breaks when a key is revoked. */
|
|
172
|
+
type RevokeImpact = "disconnects_app" | "breaks_automation";
|
|
156
173
|
type ApiKeyResponse = {
|
|
157
174
|
object: "api_key";
|
|
158
175
|
id: string;
|
|
159
176
|
keyLast4: string;
|
|
160
177
|
label: string;
|
|
178
|
+
/** Human-facing credential name: the user's label for `standard` keys, the connected client name for `mcp_oauth` keys. */
|
|
179
|
+
appName: string;
|
|
180
|
+
/** Why the key exists (drives quota accounting). */
|
|
181
|
+
keyType: KeyType;
|
|
182
|
+
/** Scopes granted to this key. */
|
|
183
|
+
scopes: string[];
|
|
184
|
+
/** When the key was last used to authenticate, ISO 8601; null/omitted if never used. */
|
|
185
|
+
lastUsedAt?: string | null;
|
|
186
|
+
/** What breaks if this key is revoked. */
|
|
187
|
+
revokeImpact: RevokeImpact;
|
|
161
188
|
createdAt: string;
|
|
162
189
|
};
|
|
163
190
|
type ApiKeyCreatedResponse = ApiKeyResponse & {
|
|
@@ -252,9 +279,17 @@ type CreateUploadSessionFileResponse = {
|
|
|
252
279
|
type UploadSessionFileResponse = {
|
|
253
280
|
fileId: string;
|
|
254
281
|
path: string;
|
|
255
|
-
|
|
256
|
-
|
|
282
|
+
/** Declared MIME type; `null`/omitted for remote-fetch files until ingested. */
|
|
283
|
+
contentType?: string | null;
|
|
284
|
+
/** Declared byte size; `null`/omitted for remote-fetch files until ingested. */
|
|
285
|
+
sizeBytes?: number | null;
|
|
257
286
|
objectKey: string;
|
|
287
|
+
/** How the file enters staging: "client_put" (client PUTs bytes) or "remote_fetch" (server fetches sourceUrl). */
|
|
288
|
+
origin: "client_put" | "remote_fetch";
|
|
289
|
+
/** Ingest lifecycle state for remote-fetch files (e.g. "pending" | "fetching" | "fetched" | "failed"). */
|
|
290
|
+
state: string;
|
|
291
|
+
/** Public http(s) URL the server fetches into staging; `null`/omitted for client-put files. */
|
|
292
|
+
sourceUrl?: string | null;
|
|
258
293
|
verified: boolean;
|
|
259
294
|
};
|
|
260
295
|
type UploadSessionResponse = {
|
|
@@ -696,17 +731,29 @@ declare class CursorPage<T> implements ListPage<T> {
|
|
|
696
731
|
readonly data: T[];
|
|
697
732
|
readonly hasMore: boolean;
|
|
698
733
|
readonly nextCursor: string | null;
|
|
734
|
+
/** Response headers from the fetch that produced this page. */
|
|
735
|
+
readonly headers: Record<string, string>;
|
|
699
736
|
private readonly fetchNextPage;
|
|
700
737
|
constructor(input: {
|
|
701
738
|
data: T[];
|
|
702
739
|
hasMore: boolean;
|
|
703
740
|
nextCursor: string | null;
|
|
741
|
+
headers?: Record<string, string>;
|
|
704
742
|
fetchNextPage?: (() => Promise<DropthisResult<CursorPage<T>>>) | undefined;
|
|
705
743
|
});
|
|
744
|
+
/**
|
|
745
|
+
* Collect items across every page into a single array.
|
|
746
|
+
*
|
|
747
|
+
* No-throw, consistent with the rest of the SDK's {@link DropthisResult}
|
|
748
|
+
* contract: returns `{ data: items, error: null }` on success, or
|
|
749
|
+
* `{ data: null, error }` if fetching a later page fails — never a thrown
|
|
750
|
+
* exception, and never a silently truncated list. Inspect `.error`
|
|
751
|
+
* (`code`/`statusCode`/`retryable`/`requestId`) exactly as you would for any
|
|
752
|
+
* other call. Pass `limit` to stop once that many items are collected.
|
|
753
|
+
*/
|
|
706
754
|
autoPagingToArray(options?: {
|
|
707
755
|
limit?: number;
|
|
708
|
-
}): Promise<T[]
|
|
709
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
756
|
+
}): Promise<DropthisResult<T[]>>;
|
|
710
757
|
}
|
|
711
758
|
|
|
712
759
|
/**
|
|
@@ -794,4 +841,4 @@ declare class DropsResource<TInput = PublishInput> {
|
|
|
794
841
|
delete(dropId: string): Promise<DropthisResult<null>>;
|
|
795
842
|
}
|
|
796
843
|
|
|
797
|
-
export { type AccountLimits as A, type PreparedUploadFile as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PublishFileInput as F, type GetContentOptions as G, type PublishInput as H, type InMemoryPublishInput as I, type PublishOptions as J, type
|
|
844
|
+
export { type AccountLimits as A, type PreparedUploadFile as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PublishFileInput as F, type GetContentOptions as G, type PublishInput as H, type InMemoryPublishInput as I, type PublishOptions as J, type KeyType as K, type Limitations as L, type RequestOptions as M, type NextHint as N, type RevokeImpact as O, type PrepareOptions as P, type SessionResponse as Q, type RequestControls as R, SHARED_POOL as S, type TierInfo as T, Transport as U, type UpdateContentOptions as V, type UploadManifestFile as W, type UploadSessionFileResponse as X, type UploadSessionResponse as Y, type UploadTarget as Z, AccountResource as a, type AccountResponse as b, type ActionResolve as c, ApiKeysResource as d, type CreateUploadSessionResponse as e, CursorPage as f, type DeploymentContentManifest as g, DeploymentsResource as h, type DnsRecord as i, type DomainDeletedResponse as j, type DomainListResponse as k, type DomainResponse as l, DomainsResource as m, type DropAction as n, type DropContentFile as o, type DropDeploymentResponse as p, type DropOptions as q, type DropResponse as r, DropsResource as s, type DropthisClientOptions as t, type DropthisErrorResponse as u, type DropthisResult as v, type ListDeploymentsParams as w, type ListDeploymentsResponse as x, type ListPage as y, type PreparedPublishRequest as z };
|
|
@@ -77,6 +77,10 @@ type DropResponse = {
|
|
|
77
77
|
noindex: boolean;
|
|
78
78
|
passwordProtected: boolean;
|
|
79
79
|
metadata: Record<string, unknown>;
|
|
80
|
+
/** When the drop was last updated (content or settings), ISO 8601. */
|
|
81
|
+
updatedAt: string;
|
|
82
|
+
/** Origin that created the drop (e.g. "api", "cli", "mcp"); null/omitted when unattributed. */
|
|
83
|
+
source?: string | null;
|
|
80
84
|
object: string;
|
|
81
85
|
accessible: boolean;
|
|
82
86
|
persistent: boolean;
|
|
@@ -131,8 +135,7 @@ type ListPage<T> = {
|
|
|
131
135
|
nextCursor: string | null;
|
|
132
136
|
autoPagingToArray(options?: {
|
|
133
137
|
limit?: number;
|
|
134
|
-
}): Promise<T[]
|
|
135
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
138
|
+
}): Promise<DropthisResult<T[]>>;
|
|
136
139
|
};
|
|
137
140
|
type Action = {
|
|
138
141
|
code: string;
|
|
@@ -142,7 +145,8 @@ type Action = {
|
|
|
142
145
|
message: string;
|
|
143
146
|
};
|
|
144
147
|
type EmailOtpResponse = {
|
|
145
|
-
|
|
148
|
+
/** Always `true` on success; optional because the server defaults it. */
|
|
149
|
+
ok?: true;
|
|
146
150
|
expiresIn: number;
|
|
147
151
|
nextAction?: Action | null;
|
|
148
152
|
};
|
|
@@ -152,12 +156,35 @@ type SessionResponse = {
|
|
|
152
156
|
accountId: string;
|
|
153
157
|
isNewAccount: boolean;
|
|
154
158
|
expiresIn: number;
|
|
159
|
+
/**
|
|
160
|
+
* Rotating refresh token for a console browser session. Present when a session is
|
|
161
|
+
* started (email/verify, refresh); `null`/omitted for non-session token issuance.
|
|
162
|
+
*/
|
|
163
|
+
refreshToken?: string | null;
|
|
155
164
|
};
|
|
165
|
+
/**
|
|
166
|
+
* Why an API key exists. `standard` keys are created by the user (CLI/SDK/manual);
|
|
167
|
+
* `mcp_oauth` keys are minted per connected client by the MCP OAuth flow and carry a
|
|
168
|
+
* more generous quota.
|
|
169
|
+
*/
|
|
170
|
+
type KeyType = "standard" | "mcp_oauth";
|
|
171
|
+
/** What breaks when a key is revoked. */
|
|
172
|
+
type RevokeImpact = "disconnects_app" | "breaks_automation";
|
|
156
173
|
type ApiKeyResponse = {
|
|
157
174
|
object: "api_key";
|
|
158
175
|
id: string;
|
|
159
176
|
keyLast4: string;
|
|
160
177
|
label: string;
|
|
178
|
+
/** Human-facing credential name: the user's label for `standard` keys, the connected client name for `mcp_oauth` keys. */
|
|
179
|
+
appName: string;
|
|
180
|
+
/** Why the key exists (drives quota accounting). */
|
|
181
|
+
keyType: KeyType;
|
|
182
|
+
/** Scopes granted to this key. */
|
|
183
|
+
scopes: string[];
|
|
184
|
+
/** When the key was last used to authenticate, ISO 8601; null/omitted if never used. */
|
|
185
|
+
lastUsedAt?: string | null;
|
|
186
|
+
/** What breaks if this key is revoked. */
|
|
187
|
+
revokeImpact: RevokeImpact;
|
|
161
188
|
createdAt: string;
|
|
162
189
|
};
|
|
163
190
|
type ApiKeyCreatedResponse = ApiKeyResponse & {
|
|
@@ -252,9 +279,17 @@ type CreateUploadSessionFileResponse = {
|
|
|
252
279
|
type UploadSessionFileResponse = {
|
|
253
280
|
fileId: string;
|
|
254
281
|
path: string;
|
|
255
|
-
|
|
256
|
-
|
|
282
|
+
/** Declared MIME type; `null`/omitted for remote-fetch files until ingested. */
|
|
283
|
+
contentType?: string | null;
|
|
284
|
+
/** Declared byte size; `null`/omitted for remote-fetch files until ingested. */
|
|
285
|
+
sizeBytes?: number | null;
|
|
257
286
|
objectKey: string;
|
|
287
|
+
/** How the file enters staging: "client_put" (client PUTs bytes) or "remote_fetch" (server fetches sourceUrl). */
|
|
288
|
+
origin: "client_put" | "remote_fetch";
|
|
289
|
+
/** Ingest lifecycle state for remote-fetch files (e.g. "pending" | "fetching" | "fetched" | "failed"). */
|
|
290
|
+
state: string;
|
|
291
|
+
/** Public http(s) URL the server fetches into staging; `null`/omitted for client-put files. */
|
|
292
|
+
sourceUrl?: string | null;
|
|
258
293
|
verified: boolean;
|
|
259
294
|
};
|
|
260
295
|
type UploadSessionResponse = {
|
|
@@ -696,17 +731,29 @@ declare class CursorPage<T> implements ListPage<T> {
|
|
|
696
731
|
readonly data: T[];
|
|
697
732
|
readonly hasMore: boolean;
|
|
698
733
|
readonly nextCursor: string | null;
|
|
734
|
+
/** Response headers from the fetch that produced this page. */
|
|
735
|
+
readonly headers: Record<string, string>;
|
|
699
736
|
private readonly fetchNextPage;
|
|
700
737
|
constructor(input: {
|
|
701
738
|
data: T[];
|
|
702
739
|
hasMore: boolean;
|
|
703
740
|
nextCursor: string | null;
|
|
741
|
+
headers?: Record<string, string>;
|
|
704
742
|
fetchNextPage?: (() => Promise<DropthisResult<CursorPage<T>>>) | undefined;
|
|
705
743
|
});
|
|
744
|
+
/**
|
|
745
|
+
* Collect items across every page into a single array.
|
|
746
|
+
*
|
|
747
|
+
* No-throw, consistent with the rest of the SDK's {@link DropthisResult}
|
|
748
|
+
* contract: returns `{ data: items, error: null }` on success, or
|
|
749
|
+
* `{ data: null, error }` if fetching a later page fails — never a thrown
|
|
750
|
+
* exception, and never a silently truncated list. Inspect `.error`
|
|
751
|
+
* (`code`/`statusCode`/`retryable`/`requestId`) exactly as you would for any
|
|
752
|
+
* other call. Pass `limit` to stop once that many items are collected.
|
|
753
|
+
*/
|
|
706
754
|
autoPagingToArray(options?: {
|
|
707
755
|
limit?: number;
|
|
708
|
-
}): Promise<T[]
|
|
709
|
-
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
756
|
+
}): Promise<DropthisResult<T[]>>;
|
|
710
757
|
}
|
|
711
758
|
|
|
712
759
|
/**
|
|
@@ -794,4 +841,4 @@ declare class DropsResource<TInput = PublishInput> {
|
|
|
794
841
|
delete(dropId: string): Promise<DropthisResult<null>>;
|
|
795
842
|
}
|
|
796
843
|
|
|
797
|
-
export { type AccountLimits as A, type PreparedUploadFile as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PublishFileInput as F, type GetContentOptions as G, type PublishInput as H, type InMemoryPublishInput as I, type PublishOptions as J, type
|
|
844
|
+
export { type AccountLimits as A, type PreparedUploadFile as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PublishFileInput as F, type GetContentOptions as G, type PublishInput as H, type InMemoryPublishInput as I, type PublishOptions as J, type KeyType as K, type Limitations as L, type RequestOptions as M, type NextHint as N, type RevokeImpact as O, type PrepareOptions as P, type SessionResponse as Q, type RequestControls as R, SHARED_POOL as S, type TierInfo as T, Transport as U, type UpdateContentOptions as V, type UploadManifestFile as W, type UploadSessionFileResponse as X, type UploadSessionResponse as Y, type UploadTarget as Z, AccountResource as a, type AccountResponse as b, type ActionResolve as c, ApiKeysResource as d, type CreateUploadSessionResponse as e, CursorPage as f, type DeploymentContentManifest as g, DeploymentsResource as h, type DnsRecord as i, type DomainDeletedResponse as j, type DomainListResponse as k, type DomainResponse as l, DomainsResource as m, type DropAction as n, type DropContentFile as o, type DropDeploymentResponse as p, type DropOptions as q, type DropResponse as r, DropsResource as s, type DropthisClientOptions as t, type DropthisErrorResponse as u, type DropthisResult as v, type ListDeploymentsParams as w, type ListDeploymentsResponse as x, type ListPage as y, type PreparedPublishRequest as z };
|
|
@@ -636,30 +636,50 @@ var CursorPage = class {
|
|
|
636
636
|
data;
|
|
637
637
|
hasMore;
|
|
638
638
|
nextCursor;
|
|
639
|
+
/** Response headers from the fetch that produced this page. */
|
|
640
|
+
headers;
|
|
639
641
|
fetchNextPage;
|
|
640
642
|
constructor(input) {
|
|
641
643
|
this.data = input.data;
|
|
642
644
|
this.hasMore = input.hasMore;
|
|
643
645
|
this.nextCursor = input.nextCursor;
|
|
646
|
+
this.headers = input.headers ?? {};
|
|
644
647
|
this.fetchNextPage = input.fetchNextPage;
|
|
645
648
|
}
|
|
649
|
+
/**
|
|
650
|
+
* Collect items across every page into a single array.
|
|
651
|
+
*
|
|
652
|
+
* No-throw, consistent with the rest of the SDK's {@link DropthisResult}
|
|
653
|
+
* contract: returns `{ data: items, error: null }` on success, or
|
|
654
|
+
* `{ data: null, error }` if fetching a later page fails — never a thrown
|
|
655
|
+
* exception, and never a silently truncated list. Inspect `.error`
|
|
656
|
+
* (`code`/`statusCode`/`retryable`/`requestId`) exactly as you would for any
|
|
657
|
+
* other call. Pass `limit` to stop once that many items are collected.
|
|
658
|
+
*/
|
|
646
659
|
async autoPagingToArray(options = {}) {
|
|
647
|
-
const
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
if (options.limit !== void 0 && items.length >= options.limit) break;
|
|
660
|
+
const { limit } = options;
|
|
661
|
+
if (limit !== void 0 && limit <= 0) {
|
|
662
|
+
return { data: [], error: null, headers: this.headers };
|
|
651
663
|
}
|
|
652
|
-
|
|
653
|
-
}
|
|
654
|
-
async *[Symbol.asyncIterator]() {
|
|
655
|
-
for (const item of this.data) yield item;
|
|
664
|
+
const items = [];
|
|
656
665
|
let current = this;
|
|
657
|
-
|
|
666
|
+
let lastHeaders = this.headers;
|
|
667
|
+
while (current) {
|
|
668
|
+
for (const item of current.data) {
|
|
669
|
+
items.push(item);
|
|
670
|
+
if (limit !== void 0 && items.length >= limit) {
|
|
671
|
+
return { data: items, error: null, headers: lastHeaders };
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (!current.hasMore || !current.fetchNextPage) break;
|
|
658
675
|
const next = await current.fetchNextPage();
|
|
659
|
-
if (next.error)
|
|
676
|
+
if (next.error) {
|
|
677
|
+
return { data: null, error: next.error, headers: next.headers };
|
|
678
|
+
}
|
|
679
|
+
lastHeaders = next.headers;
|
|
660
680
|
current = next.data;
|
|
661
|
-
for (const item of current.data) yield item;
|
|
662
681
|
}
|
|
682
|
+
return { data: items, error: null, headers: lastHeaders };
|
|
663
683
|
}
|
|
664
684
|
};
|
|
665
685
|
|
|
@@ -728,6 +748,7 @@ var DropsResource = class {
|
|
|
728
748
|
data: result.data.drops,
|
|
729
749
|
nextCursor: result.data.nextCursor,
|
|
730
750
|
hasMore: result.data.nextCursor !== null,
|
|
751
|
+
headers: result.headers,
|
|
731
752
|
fetchNextPage: result.data.nextCursor ? () => this.list({ ...params, cursor: result.data.nextCursor }) : void 0
|
|
732
753
|
});
|
|
733
754
|
return { data: page, error: null, headers: result.headers };
|
|
@@ -871,7 +892,7 @@ function toSnakeCase(value) {
|
|
|
871
892
|
|
|
872
893
|
// src/transport.ts
|
|
873
894
|
var DEFAULT_BASE_URL = "https://api.dropthis.app";
|
|
874
|
-
var SDK_VERSION = "0.
|
|
895
|
+
var SDK_VERSION = "0.22.0";
|
|
875
896
|
var Transport = class {
|
|
876
897
|
apiKey;
|
|
877
898
|
baseUrl;
|
|
@@ -910,7 +931,10 @@ var Transport = class {
|
|
|
910
931
|
`signed_upload_${response.status}`,
|
|
911
932
|
text || response.statusText,
|
|
912
933
|
response.status,
|
|
913
|
-
|
|
934
|
+
// A 5xx from object storage is a transient upstream failure — safe to
|
|
935
|
+
// re-PUT. A 4xx (e.g. 403 expired/denied signed URL) won't fix itself on
|
|
936
|
+
// a blind retry, so leave it unmarked.
|
|
937
|
+
{ headers: responseHeaders, retryable: response.status >= 500 }
|
|
914
938
|
);
|
|
915
939
|
}
|
|
916
940
|
return {
|
|
@@ -925,7 +949,8 @@ var Transport = class {
|
|
|
925
949
|
return createErrorResult(
|
|
926
950
|
error instanceof Error && error.name === "AbortError" ? "timeout" : "network_error",
|
|
927
951
|
message,
|
|
928
|
-
null
|
|
952
|
+
null,
|
|
953
|
+
{ retryable: true }
|
|
929
954
|
);
|
|
930
955
|
} finally {
|
|
931
956
|
clearTimeout(timeout);
|
|
@@ -982,7 +1007,8 @@ var Transport = class {
|
|
|
982
1007
|
return createErrorResult(
|
|
983
1008
|
error instanceof Error && error.name === "AbortError" ? "timeout" : "network_error",
|
|
984
1009
|
message,
|
|
985
|
-
null
|
|
1010
|
+
null,
|
|
1011
|
+
{ retryable: true }
|
|
986
1012
|
);
|
|
987
1013
|
} finally {
|
|
988
1014
|
clearTimeout(timeout);
|
|
@@ -1043,10 +1069,12 @@ var Transport = class {
|
|
|
1043
1069
|
};
|
|
1044
1070
|
} catch (error) {
|
|
1045
1071
|
const message = error instanceof Error && error.name === "AbortError" ? "Request timed out" : error instanceof Error ? error.message : "Network error";
|
|
1072
|
+
const retrySafe = method.toUpperCase() === "GET" || options.idempotencyKey !== void 0;
|
|
1046
1073
|
return createErrorResult(
|
|
1047
1074
|
error instanceof Error && error.name === "AbortError" ? "timeout" : "network_error",
|
|
1048
1075
|
message,
|
|
1049
|
-
null
|
|
1076
|
+
null,
|
|
1077
|
+
retrySafe ? { retryable: true } : {}
|
|
1050
1078
|
);
|
|
1051
1079
|
} finally {
|
|
1052
1080
|
clearTimeout(timeout);
|