@shipstatic/types 2.5.0-beta.9 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -6
- package/dist/index.d.ts +595 -77
- package/dist/index.js +495 -17
- package/package.json +6 -1
- package/src/index.ts +840 -73
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,28 @@ export declare const DeploymentStatus: {
|
|
|
12
12
|
readonly DELETING: "deleting";
|
|
13
13
|
};
|
|
14
14
|
export type DeploymentStatusType = (typeof DeploymentStatus)[keyof typeof DeploymentStatus];
|
|
15
|
+
/**
|
|
16
|
+
* Which client made a deployment — the origin-tracking vocabulary.
|
|
17
|
+
*
|
|
18
|
+
* A closed set with many authors: the CLI, the SDK, the dashboard, both MCP
|
|
19
|
+
* transports, the GitHub Action, the n8n node and the VS Code extension each
|
|
20
|
+
* name themselves here. It lived in the API's config until 2026-08-06, where
|
|
21
|
+
* being server-side made it unenforceable in the one direction that matters —
|
|
22
|
+
* every client wrote a bare string, and a value outside the set was **silently
|
|
23
|
+
* dropped** by the server, so a typo did not fail anywhere. It stopped
|
|
24
|
+
* recording where deploys came from and said nothing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const DeploymentVia: {
|
|
27
|
+
readonly WEB: "web";
|
|
28
|
+
readonly SDK: "sdk";
|
|
29
|
+
readonly CLI: "cli";
|
|
30
|
+
readonly MCP: "mcp";
|
|
31
|
+
readonly GIT: "git";
|
|
32
|
+
readonly N8N: "n8n";
|
|
33
|
+
readonly GPT: "gpt";
|
|
34
|
+
readonly VSC: "vsc";
|
|
35
|
+
};
|
|
36
|
+
export type DeploymentViaType = (typeof DeploymentVia)[keyof typeof DeploymentVia];
|
|
15
37
|
/**
|
|
16
38
|
* Core deployment object - used in both API responses and SDK
|
|
17
39
|
*/
|
|
@@ -32,7 +54,15 @@ export interface Deployment {
|
|
|
32
54
|
readonly password: boolean;
|
|
33
55
|
/** Labels for categorization and filtering (lowercase, alphanumeric with separators). Always present, empty array when none. */
|
|
34
56
|
labels: string[];
|
|
35
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* The client/tool that created this deployment, null if unknown.
|
|
59
|
+
*
|
|
60
|
+
* Deliberately wider than {@link DeploymentViaType}: this is stored data,
|
|
61
|
+
* and rows predate the vocabulary being closed. Narrowing the ENTITY would
|
|
62
|
+
* be a claim about every row already in the database; narrowing the
|
|
63
|
+
* REQUEST option ({@link DeploymentUploadOptions.via}) is a claim about
|
|
64
|
+
* what a client may send, which is ours to make.
|
|
65
|
+
*/
|
|
36
66
|
readonly via: string | null;
|
|
37
67
|
/** Unix timestamp (seconds) when deployment was created */
|
|
38
68
|
readonly created: number;
|
|
@@ -62,14 +92,33 @@ export interface DeploymentCreateResponse extends Deployment {
|
|
|
62
92
|
* beside every page read, which is precisely what keyset pagination exists
|
|
63
93
|
* to avoid. Counts live on the resource that summarises the collection —
|
|
64
94
|
* `GET /account`'s `usage` for one caller, `GET /admin/stats` platform-wide.
|
|
65
|
-
*
|
|
66
|
-
* The operator lists (`/admin/*`) answer this same shape behind the prefix;
|
|
67
|
-
* their types live in `web/my`, not here — see `CLAUDE.md`, "Admin types".
|
|
68
95
|
*/
|
|
69
96
|
export interface ListResponse {
|
|
70
97
|
/** Opaque cursor from this page; `null` on the last page. */
|
|
71
98
|
cursor: string | null;
|
|
72
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Pagination options for every list endpoint. The response's `cursor` feeds
|
|
102
|
+
* the next request; a `null` cursor means the last page. Omitting both
|
|
103
|
+
* returns the server's default first page.
|
|
104
|
+
*
|
|
105
|
+
* A list answers `{ <collection>, cursor }` and nothing else — `cursor`
|
|
106
|
+
* carries the entire has-more signal, so no redundant boolean, and no
|
|
107
|
+
* `total`. **A count is an aggregate over a collection, not a property of a
|
|
108
|
+
* page:** including one makes every read pay for a full scan it did not ask
|
|
109
|
+
* for, which is precisely the cost keyset pagination exists to avoid.
|
|
110
|
+
*
|
|
111
|
+
* Counts therefore live on the summary resource that owns them —
|
|
112
|
+
* `GET /account` (`usage`) for a caller's own totals, `GET /admin/stats` for
|
|
113
|
+
* platform-wide ones. Ask for a count when you want a count; ask for a page
|
|
114
|
+
* when you want a page.
|
|
115
|
+
*/
|
|
116
|
+
export interface ListOptions {
|
|
117
|
+
/** Maximum number of items to return in one page. */
|
|
118
|
+
limit?: number;
|
|
119
|
+
/** Opaque cursor from the previous page's response. */
|
|
120
|
+
cursor?: string;
|
|
121
|
+
}
|
|
73
122
|
/**
|
|
74
123
|
* Response for listing deployments
|
|
75
124
|
*/
|
|
@@ -77,6 +126,42 @@ export interface DeploymentListResponse extends ListResponse {
|
|
|
77
126
|
/** Array of deployments */
|
|
78
127
|
deployments: Deployment[];
|
|
79
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Acknowledgement of `DELETE /deployments/:deployment` — and the shape every
|
|
131
|
+
* mutation with no entity left to return follows.
|
|
132
|
+
*
|
|
133
|
+
* **The law:** a mutation answers with the resource it affected. If the
|
|
134
|
+
* resource still exists, that means the entity itself (`Deployment`,
|
|
135
|
+
* `Domain`, …). Otherwise it means this: the resource noun carrying the
|
|
136
|
+
* item's canonical key, plus the resource's own state field — and ONLY when
|
|
137
|
+
* the resource survived in a transitional state, as an async deletion's does.
|
|
138
|
+
* Where the resource is simply gone, the key alone is the whole answer
|
|
139
|
+
* ({@link DomainDeleteResponse}, {@link TokenDeleteResponse}).
|
|
140
|
+
*
|
|
141
|
+
* Put positively: **an acknowledgement is a projection of the resource** —
|
|
142
|
+
* its key, plus its own state field where the state changed. That is the
|
|
143
|
+
* test to apply, and it is sharper than "no constant", which this shape
|
|
144
|
+
* would fail on its own terms: `status` here is the literal `'deleting'` on
|
|
145
|
+
* every success, exactly as fixed as a `changed: true` would be.
|
|
146
|
+
*
|
|
147
|
+
* The difference is not how predictable the value is, it is what the field
|
|
148
|
+
* IS. `status` is the deployment's own field — the same one `GET
|
|
149
|
+
* /deployments/:deployment` returns — so this response is `Deployment`
|
|
150
|
+
* narrowed to two members, and a client renders it with the code it already
|
|
151
|
+
* has. `changed: true`, `queued: true` and `success: true` are not fields of
|
|
152
|
+
* any entity; they exist only to assert that the call worked, which the
|
|
153
|
+
* status code already said. Sync versus accepted is likewise the status
|
|
154
|
+
* code's job — 200 versus 202 — not a boolean's.
|
|
155
|
+
*
|
|
156
|
+
* No prose either (`message`): an acknowledgement is data, and each surface
|
|
157
|
+
* composes its own copy.
|
|
158
|
+
*/
|
|
159
|
+
export interface DeploymentDeleteResponse {
|
|
160
|
+
/** The deployment hostname that was marked for removal */
|
|
161
|
+
readonly deployment: string;
|
|
162
|
+
/** The state the deployment is in while background cleanup runs */
|
|
163
|
+
readonly status: DeploymentStatusType;
|
|
164
|
+
}
|
|
80
165
|
/**
|
|
81
166
|
* Domain status constants
|
|
82
167
|
*
|
|
@@ -134,6 +219,25 @@ export interface DomainListResponse extends ListResponse {
|
|
|
134
219
|
/** Array of domains */
|
|
135
220
|
domains: Domain[];
|
|
136
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Acknowledgement of `DELETE /domains/:domain`. The row is gone, so there is
|
|
224
|
+
* no state to state — the canonical domain name is the whole answer. See
|
|
225
|
+
* {@link DeploymentDeleteResponse} for the law.
|
|
226
|
+
*/
|
|
227
|
+
export interface DomainDeleteResponse {
|
|
228
|
+
/** The domain name that was removed, normalized */
|
|
229
|
+
readonly domain: string;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Acknowledgement of `POST /domains/:domain/verify` (202). The DNS check is
|
|
233
|
+
* queued, not performed — the accepted status code says so, and the domain's
|
|
234
|
+
* own status is unchanged until the check runs, which is why none is stated
|
|
235
|
+
* here. See {@link DeploymentDeleteResponse} for the law.
|
|
236
|
+
*/
|
|
237
|
+
export interface DomainVerifyResponse {
|
|
238
|
+
/** The domain whose DNS verification was queued, normalized */
|
|
239
|
+
readonly domain: string;
|
|
240
|
+
}
|
|
137
241
|
/**
|
|
138
242
|
* DNS record types supported for domain configuration
|
|
139
243
|
*/
|
|
@@ -159,16 +263,46 @@ export interface DnsProvider {
|
|
|
159
263
|
/**
|
|
160
264
|
* Response for domain DNS provider lookup
|
|
161
265
|
*/
|
|
266
|
+
/**
|
|
267
|
+
* What a DNS lookup found for a domain. An envelope rather than a bare
|
|
268
|
+
* {@link DnsProvider} because a lookup can succeed and learn more than the
|
|
269
|
+
* provider later; the shape is named so a consumer can hold one.
|
|
270
|
+
*/
|
|
271
|
+
export interface DnsLookup {
|
|
272
|
+
/** The provider serving this domain's DNS, absent when unidentified */
|
|
273
|
+
provider?: DnsProvider;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
277
|
+
* "A report answers a question").
|
|
278
|
+
*/
|
|
162
279
|
export interface DomainDnsResponse {
|
|
163
280
|
/** The domain name */
|
|
164
281
|
domain: string;
|
|
165
282
|
/** DNS provider information, null if not yet looked up */
|
|
166
|
-
dns:
|
|
167
|
-
|
|
168
|
-
|
|
283
|
+
dns: DnsLookup | null;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Response for `GET /domains/:domain/share` — the domain plus the salted
|
|
287
|
+
* hash that lets someone else complete its DNS setup without an account.
|
|
288
|
+
*
|
|
289
|
+
* `/admin/domains/:domain/share` answers the same shape, which is the admin
|
|
290
|
+
* law working: the operator surface is the public grammar with a prefix.
|
|
291
|
+
*
|
|
292
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
293
|
+
* "A report answers a question").
|
|
294
|
+
*/
|
|
295
|
+
export interface DomainShareResponse {
|
|
296
|
+
/** The domain the setup link is for */
|
|
297
|
+
readonly domain: string;
|
|
298
|
+
/** The salted setup hash that authorizes the share */
|
|
299
|
+
readonly hash: string;
|
|
169
300
|
}
|
|
170
301
|
/**
|
|
171
302
|
* Response for domain DNS records
|
|
303
|
+
*
|
|
304
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
305
|
+
* "A report answers a question").
|
|
172
306
|
*/
|
|
173
307
|
export interface DomainRecordsResponse {
|
|
174
308
|
/** The domain name */
|
|
@@ -179,7 +313,92 @@ export interface DomainRecordsResponse {
|
|
|
179
313
|
records: DnsRecord[];
|
|
180
314
|
}
|
|
181
315
|
/**
|
|
182
|
-
*
|
|
316
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
317
|
+
*
|
|
318
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
319
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
320
|
+
* API would reject the same value the same way.
|
|
321
|
+
*/
|
|
322
|
+
export declare const IDEMPOTENCY_KEY_CONSTRAINTS: {
|
|
323
|
+
/**
|
|
324
|
+
* HTTP header name. Here for the same reason {@link CALLER.HEADER} is: a
|
|
325
|
+
* wire header has two ends, and the package that owns the value's format
|
|
326
|
+
* is the only place both ends can read its name from.
|
|
327
|
+
*/
|
|
328
|
+
readonly HEADER: "Idempotency-Key";
|
|
329
|
+
readonly MAX_LENGTH: 256;
|
|
330
|
+
/** How long a stored 201 stays replayable. */
|
|
331
|
+
readonly WINDOW_SECONDS: number;
|
|
332
|
+
};
|
|
333
|
+
/**
|
|
334
|
+
* Normalize a `via` value from any transport — trimmed, lowercased, and a
|
|
335
|
+
* member of {@link DeploymentVia}, or `undefined`.
|
|
336
|
+
*
|
|
337
|
+
* A format rule by this package's own test: a client can decide offline
|
|
338
|
+
* whether a value is well-formed, and the API reaches the same verdict on the
|
|
339
|
+
* same input. It lived server-side until 2026-08-06, which meant clients could
|
|
340
|
+
* only learn their label was unusable by noticing analytics had gone quiet.
|
|
341
|
+
*
|
|
342
|
+
* **Not knowing your `via` is not an error** — an unrecognized value yields
|
|
343
|
+
* `undefined` rather than throwing, because origin tracking is telemetry and a
|
|
344
|
+
* deploy must never fail over it. A caller that has an honest default should
|
|
345
|
+
* prefer it (`normalizeVia(process.env.SHIP_VIA) ?? DeploymentVia.CLI`): the
|
|
346
|
+
* deploy really did come from the CLI, so recording that beats recording
|
|
347
|
+
* nothing.
|
|
348
|
+
*/
|
|
349
|
+
export declare function normalizeVia(value: unknown): DeploymentViaType | undefined;
|
|
350
|
+
/**
|
|
351
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
352
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
353
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
354
|
+
*/
|
|
355
|
+
export declare function validateIdempotencyKey(value: unknown): string | undefined;
|
|
356
|
+
/**
|
|
357
|
+
* Response for `GET /labels` — every label in use across the caller's
|
|
358
|
+
* deployments, domains and tokens, grouped and ordered by last use.
|
|
359
|
+
*
|
|
360
|
+
* The one plural noun outside the list contract, deliberately: labels have
|
|
361
|
+
* no identity, no row and no `created`, so there is nothing for a keyset
|
|
362
|
+
* cursor to resume after, and its consumer is an autocomplete that wants the
|
|
363
|
+
* whole set. Bounded by `PAGINATION.GLOBAL_LIMIT` rather than paginated.
|
|
364
|
+
*
|
|
365
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
366
|
+
* "A report answers a question").
|
|
367
|
+
*/
|
|
368
|
+
export interface LabelsResponse {
|
|
369
|
+
readonly labels: string[];
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Response for `POST /setup` — the DNS instructions for one domain, written
|
|
373
|
+
* for a human to follow at their registrar.
|
|
374
|
+
*
|
|
375
|
+
* `custom` is the provider-specific walkthrough when the provider is known;
|
|
376
|
+
* `generic` always answers, so a caller never has nothing to show.
|
|
377
|
+
*
|
|
378
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
379
|
+
* "A report answers a question").
|
|
380
|
+
*/
|
|
381
|
+
export interface SetupInstructionsResponse {
|
|
382
|
+
/** The domain the instructions are for — a report names its subject */
|
|
383
|
+
readonly domain: string;
|
|
384
|
+
/** One-line summary of what to do */
|
|
385
|
+
readonly tldr: string;
|
|
386
|
+
/** Provider-specific instructions, null when the provider is unknown */
|
|
387
|
+
readonly custom: string | null;
|
|
388
|
+
/** Provider-agnostic instructions — always present */
|
|
389
|
+
readonly generic: string;
|
|
390
|
+
/** The identified DNS provider, null when unknown */
|
|
391
|
+
readonly provider: string | null;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* `POST /domains/validate` — a report answering "is this name usable, and if
|
|
395
|
+
* not, why".
|
|
396
|
+
*
|
|
397
|
+
* An unusable name is a legitimate ANSWER, not a failure, so this is a 200 and
|
|
398
|
+
* the verdict rides the body. `reason` was named `error` until 2026-07-29,
|
|
399
|
+
* which collided with {@link ErrorResponse}'s reserved key — there `error` is
|
|
400
|
+
* an `ErrorType` a client branches on, here it is prose a client displays, and
|
|
401
|
+
* one key cannot mean both. See {@link DeploymentDeleteResponse} for the law.
|
|
183
402
|
*/
|
|
184
403
|
export interface DomainValidateResponse {
|
|
185
404
|
/** Whether the domain is valid */
|
|
@@ -188,19 +407,13 @@ export interface DomainValidateResponse {
|
|
|
188
407
|
normalized: string | null;
|
|
189
408
|
/** Whether the domain is available, null when invalid */
|
|
190
409
|
available: boolean | null;
|
|
191
|
-
/**
|
|
192
|
-
|
|
410
|
+
/** Why the name is unusable, null when valid — displayed verbatim. */
|
|
411
|
+
reason: string | null;
|
|
193
412
|
}
|
|
194
413
|
/**
|
|
195
414
|
* Core deploy token object - used in both API responses and SDK.
|
|
196
415
|
*
|
|
197
|
-
*
|
|
198
|
-
* `Deployment`, `Domain`, `Account`, `Activity` and this. It was once called
|
|
199
|
-
* `TokenListItem`, named for the surface that returned it rather than for
|
|
200
|
-
* what it is, which is exactly why {@link TokenCreateResponse} used to
|
|
201
|
-
* restate its fields instead of extending it.
|
|
202
|
-
*
|
|
203
|
-
* The token itself is never here. The secret is shown once at creation
|
|
416
|
+
* The secret is never here: it is shown once at creation
|
|
204
417
|
* ({@link TokenCreateResponse.secret}) and never again, so an entity read
|
|
205
418
|
* carries only the management identifier and lifecycle metadata.
|
|
206
419
|
*/
|
|
@@ -233,6 +446,15 @@ export interface TokenCreateResponse extends Token {
|
|
|
233
446
|
/** The raw credential value (shown once at creation, then never again) */
|
|
234
447
|
readonly secret: string;
|
|
235
448
|
}
|
|
449
|
+
/**
|
|
450
|
+
* Acknowledgement of `DELETE /tokens/:token`. The credential is revoked and
|
|
451
|
+
* its row is gone, so the management identifier is the whole answer. See
|
|
452
|
+
* {@link DeploymentDeleteResponse} for the law.
|
|
453
|
+
*/
|
|
454
|
+
export interface TokenDeleteResponse {
|
|
455
|
+
/** The 7-char management identifier that was revoked */
|
|
456
|
+
readonly token: string;
|
|
457
|
+
}
|
|
236
458
|
/**
|
|
237
459
|
* Account plan constants
|
|
238
460
|
*/
|
|
@@ -322,6 +544,35 @@ export interface AccountGetResponse extends Account {
|
|
|
322
544
|
/** Present only during read-only admin impersonation: the operator's account id. */
|
|
323
545
|
readonly impersonatedBy?: string;
|
|
324
546
|
}
|
|
547
|
+
/**
|
|
548
|
+
* Acknowledgement of `DELETE /account` (202). Termination is asynchronous —
|
|
549
|
+
* a cleanup consumer finishes the job — so the account survives long enough
|
|
550
|
+
* to state the plan it is transitioning through. `plan` is the account's
|
|
551
|
+
* state field, the way `status` is a deployment's. See
|
|
552
|
+
* {@link DeploymentDeleteResponse} for the law.
|
|
553
|
+
*/
|
|
554
|
+
export interface AccountDeleteResponse {
|
|
555
|
+
/** The account that was marked for termination */
|
|
556
|
+
readonly account: string;
|
|
557
|
+
/** The plan the account is in while cleanup runs */
|
|
558
|
+
readonly plan: AccountPlanType;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Response from `PUT /account/key` — the account's single API key, minted in
|
|
562
|
+
* place of whatever was there before.
|
|
563
|
+
*
|
|
564
|
+
* There is no entity to return: only the key's last-4 `hint` is durable
|
|
565
|
+
* (`Account.hint`), and the plaintext exists exactly once, in this response.
|
|
566
|
+
* The raw credential is `secret` on every surface that mints one — the same
|
|
567
|
+
* field `TokenCreateResponse` carries — because one concept gets one name.
|
|
568
|
+
*
|
|
569
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
570
|
+
* "A report answers a question").
|
|
571
|
+
*/
|
|
572
|
+
export interface AccountKeyResponse {
|
|
573
|
+
/** The raw API key (shown once at mint, then never again) */
|
|
574
|
+
readonly secret: string;
|
|
575
|
+
}
|
|
325
576
|
/**
|
|
326
577
|
* Account-specific configuration overrides
|
|
327
578
|
* Allows per-account customization of limits without changing plan
|
|
@@ -338,6 +589,97 @@ export interface AccountOverrides {
|
|
|
338
589
|
/** Override for maximum total deployment size in bytes */
|
|
339
590
|
totalSize?: number;
|
|
340
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Every path the public API answers on, declared once.
|
|
594
|
+
*
|
|
595
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
596
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
597
|
+
* rename meant finding all four. The first three now read this table.
|
|
598
|
+
*
|
|
599
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
600
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
601
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
602
|
+
* than keeping it uniform.
|
|
603
|
+
*
|
|
604
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
605
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
606
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
607
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
608
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
609
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
610
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
611
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
612
|
+
* than merely asserted.
|
|
613
|
+
*
|
|
614
|
+
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
615
|
+
* to `web/my`, for the same reason its row types do: this package is
|
|
616
|
+
* published, and the operator surface is not public (see `CLAUDE.md`, "Admin
|
|
617
|
+
* types"). A path here is a promise to every npm consumer; `/admin` is a
|
|
618
|
+
* promise to one dashboard.
|
|
619
|
+
*
|
|
620
|
+
* Item paths are functions rather than templates so the key is interpolated
|
|
621
|
+
* in one place, encoded the same way by every caller.
|
|
622
|
+
*/
|
|
623
|
+
export declare const API_PATHS: {
|
|
624
|
+
readonly DEPLOYMENTS: "/deployments";
|
|
625
|
+
readonly DEPLOYMENT: (deployment: string) => string;
|
|
626
|
+
readonly DEPLOYMENT_CONFIG: (deployment: string) => string;
|
|
627
|
+
readonly DOMAINS: "/domains";
|
|
628
|
+
readonly DOMAIN: (domain: string) => string;
|
|
629
|
+
readonly DOMAIN_VERIFY: (domain: string) => string;
|
|
630
|
+
readonly DOMAIN_DNS: (domain: string) => string;
|
|
631
|
+
readonly DOMAIN_RECORDS: (domain: string) => string;
|
|
632
|
+
readonly DOMAIN_SHARE: (domain: string) => string;
|
|
633
|
+
readonly DOMAIN_PROPAGATION: (domain: string) => string;
|
|
634
|
+
readonly DOMAINS_VALIDATE: "/domains/validate";
|
|
635
|
+
readonly TOKENS: "/tokens";
|
|
636
|
+
readonly TOKEN: (token: string) => string;
|
|
637
|
+
readonly ACCOUNT: "/account";
|
|
638
|
+
readonly ACCOUNT_KEY: "/account/key";
|
|
639
|
+
readonly ACCOUNT_CLAIM: "/account/claim";
|
|
640
|
+
readonly ACTIVITIES: "/activities";
|
|
641
|
+
readonly LABELS: "/labels";
|
|
642
|
+
readonly LIMITS: "/limits";
|
|
643
|
+
readonly PING: "/ping";
|
|
644
|
+
readonly SETUP: "/setup";
|
|
645
|
+
readonly SPA_CHECK: "/spa-check";
|
|
646
|
+
readonly UPLOAD: "/upload";
|
|
647
|
+
};
|
|
648
|
+
/**
|
|
649
|
+
* The deploy request's multipart field names — the other half of the wire
|
|
650
|
+
* surface beside {@link API_PATHS}. `POST /deployments` (and the first-party
|
|
651
|
+
* `/upload`) is multipart/form-data, and these are the names the API reads.
|
|
652
|
+
*
|
|
653
|
+
* Declared once because the body has three independent WRITERS — the SDK's
|
|
654
|
+
* Node and browser body builders, and the n8n community node's hand-rolled
|
|
655
|
+
* client (which cannot import this under n8n Cloud's zero-dependency rule,
|
|
656
|
+
* and fences its restated copy instead) — and until this export every writer
|
|
657
|
+
* restated the strings the API parses, with nothing comparing them.
|
|
658
|
+
*
|
|
659
|
+
* `FILES` carries one entry per file (the API reads it with `getAll`); every
|
|
660
|
+
* other field is single. The `@internal` flags are serialized as the literal
|
|
661
|
+
* string `'true'` and belong to first-party surfaces only.
|
|
662
|
+
*/
|
|
663
|
+
export declare const DEPLOY_FIELDS: {
|
|
664
|
+
/** One entry per file — read with `getAll`. */
|
|
665
|
+
readonly FILES: "files[]";
|
|
666
|
+
/** JSON array of MD5 hex digests, index-aligned with `FILES`. */
|
|
667
|
+
readonly CHECKSUMS: "checksums";
|
|
668
|
+
/** JSON array of label strings. */
|
|
669
|
+
readonly LABELS: "labels";
|
|
670
|
+
/** The deploying surface's {@link DeploymentVia} member. */
|
|
671
|
+
readonly VIA: "via";
|
|
672
|
+
/** Plaintext password — the API hashes it server-side. */
|
|
673
|
+
readonly PASSWORD: "password";
|
|
674
|
+
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
675
|
+
readonly BUILD: "build";
|
|
676
|
+
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
677
|
+
readonly PRERENDER: "prerender";
|
|
678
|
+
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
679
|
+
readonly SPA: "spa";
|
|
680
|
+
/** @internal reCAPTCHA proof — `web/www`'s public uploader only. */
|
|
681
|
+
readonly CAPTCHA: "captcha";
|
|
682
|
+
};
|
|
341
683
|
/**
|
|
342
684
|
* All possible error types in the ShipStatic platform.
|
|
343
685
|
*
|
|
@@ -348,7 +690,15 @@ export interface AccountOverrides {
|
|
|
348
690
|
* (`DeploymentStatus`, `DomainStatus`, `AccountPlan`, `AuthMethod`) follow.
|
|
349
691
|
*/
|
|
350
692
|
export declare const ErrorType: {
|
|
351
|
-
/**
|
|
693
|
+
/**
|
|
694
|
+
* Validation failed. Input shape is wrong.
|
|
695
|
+
*
|
|
696
|
+
* Carries 400 when an API judged it — including a client-side pre-check of a
|
|
697
|
+
* rule the server enforces too, which keeps the error identical wherever it
|
|
698
|
+
* was caught. **Statusless** when a client rejects something no API judges,
|
|
699
|
+
* such as a CLI's own command grammar: `status` is documented "(API
|
|
700
|
+
* contexts)" on `ErrorResponse`, so there is none to report.
|
|
701
|
+
*/
|
|
352
702
|
readonly Validation: "validation_failed";
|
|
353
703
|
/** Resource not found (404). */
|
|
354
704
|
readonly NotFound: "not_found";
|
|
@@ -362,6 +712,17 @@ export declare const ErrorType: {
|
|
|
362
712
|
readonly Business: "business_logic_error";
|
|
363
713
|
/** API server error (500). Generic server-side fault. */
|
|
364
714
|
readonly Api: "internal_server_error";
|
|
715
|
+
/**
|
|
716
|
+
* The platform is closed for maintenance (503). A deliberate operator
|
|
717
|
+
* state, not a fault — nothing errored; the API is refusing work on
|
|
718
|
+
* purpose, and deployed sites keep serving throughout.
|
|
719
|
+
*
|
|
720
|
+
* Distinct from `Api` at 503, which the platform already uses for a
|
|
721
|
+
* dependency that failed (moderation unavailable). A consumer has to tell
|
|
722
|
+
* "we closed the door" from "something broke": the two get opposite words
|
|
723
|
+
* and opposite retry behaviour.
|
|
724
|
+
*/
|
|
725
|
+
readonly Maintenance: "maintenance";
|
|
365
726
|
/** Network/connection error. Client-side only — set by HTTP clients on fetch failure; never produced server-side. */
|
|
366
727
|
readonly Network: "network_error";
|
|
367
728
|
/** Operation was cancelled. Client-side only — set on `AbortSignal` abort; never produced server-side. */
|
|
@@ -428,7 +789,8 @@ export declare class ShipError extends Error {
|
|
|
428
789
|
* Routing:
|
|
429
790
|
* - Already a `ShipError` → returned as-is (caller's intent preserved)
|
|
430
791
|
* - `AbortError` → `ShipError.cancelled(...)`
|
|
431
|
-
* -
|
|
792
|
+
* - A transport failure → `ShipError.network(...)` — see `isTransportFailure`
|
|
793
|
+
* for what each runtime offers as evidence
|
|
432
794
|
* - Any other `Error` → `ShipError(Api, ...)` (no HTTP status — fetch never reached the server)
|
|
433
795
|
* - Anything else (string, undefined, etc.) → `ShipError(Api, ...)`
|
|
434
796
|
*
|
|
@@ -461,6 +823,16 @@ export declare class ShipError extends Error {
|
|
|
461
823
|
static file(message: string, details?: unknown): ShipError;
|
|
462
824
|
static config(message: string, details?: unknown): ShipError;
|
|
463
825
|
static api(message: string, status?: number, details?: unknown): ShipError;
|
|
826
|
+
/**
|
|
827
|
+
* The platform is closed for maintenance (503).
|
|
828
|
+
*
|
|
829
|
+
* `message` is REQUIRED and has no default here. The API is the only
|
|
830
|
+
* producer of that sentence, and a default in this file would be a second
|
|
831
|
+
* owner of one fact — see CLAUDE.md, "The Constellation Law" (stopping
|
|
832
|
+
* rule). It is also the one factory whose status is fixed rather than
|
|
833
|
+
* defaulted: a maintenance refusal is 503 or it is not this error.
|
|
834
|
+
*/
|
|
835
|
+
static maintenance(message: string, details?: unknown): ShipError;
|
|
464
836
|
/**
|
|
465
837
|
* The caller is at fault — by HTTP's own definition of a 4xx, or by a type
|
|
466
838
|
* that is client-attributable without ever having a status (`Config`,
|
|
@@ -499,6 +871,9 @@ export declare function isShipError(error: unknown): error is ShipError;
|
|
|
499
871
|
*
|
|
500
872
|
* These are the *platform's* posted caps for the current account — server
|
|
501
873
|
* truth delivered at runtime, never hard-coded on the client.
|
|
874
|
+
*
|
|
875
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
876
|
+
* "A report answers a question").
|
|
502
877
|
*/
|
|
503
878
|
export interface PlatformLimits {
|
|
504
879
|
/** Maximum size in bytes for a single file. */
|
|
@@ -532,6 +907,28 @@ export declare const BLOCKED_EXTENSIONS: ReadonlySet<string>;
|
|
|
532
907
|
* isBlockedExtension('README') // false
|
|
533
908
|
*/
|
|
534
909
|
export declare function isBlockedExtension(filename: string): boolean;
|
|
910
|
+
/**
|
|
911
|
+
* The `accept` attribute value for a browser file picker offering web files.
|
|
912
|
+
*
|
|
913
|
+
* **This is a hint, never a rule.** `BLOCKED_EXTENSIONS` is the platform's
|
|
914
|
+
* gate and the only thing that decides what may be hosted; this constant
|
|
915
|
+
* decides what a *file dialog* shows first. The two are not two halves of one
|
|
916
|
+
* policy, and this one must never be consulted to accept or reject a file.
|
|
917
|
+
*
|
|
918
|
+
* The distinction is structural, not stylistic. `accept` can express only an
|
|
919
|
+
* allowlist, while the platform's rule is a blocklist — so this list is
|
|
920
|
+
* necessarily *narrower* than what the platform hosts, and reading it as
|
|
921
|
+
* authority would reject files the platform serves happily. It is also not
|
|
922
|
+
* enforcement in the browser's own terms: every file dialog offers an
|
|
923
|
+
* all-files escape, and **drag-and-drop ignores `accept` entirely**. The
|
|
924
|
+
* dropzone and the picker must reach the same verdict on the same files, and
|
|
925
|
+
* they do — because the verdict is `validateFiles`, downstream of both.
|
|
926
|
+
*
|
|
927
|
+
* Kept beside `BLOCKED_EXTENSIONS` so one file holds both, which is what lets
|
|
928
|
+
* `tests/validation-constants.test.ts` fence the invariant that matters: the
|
|
929
|
+
* picker must never offer a file the platform will refuse.
|
|
930
|
+
*/
|
|
931
|
+
export declare const WEB_FILE_ACCEPT: string;
|
|
535
932
|
/**
|
|
536
933
|
* Characters that are unsafe in filenames for static hosting.
|
|
537
934
|
*
|
|
@@ -569,13 +966,20 @@ export declare const UNBUILT_PROJECT_MARKERS: ReadonlySet<string>;
|
|
|
569
966
|
*/
|
|
570
967
|
export declare function hasUnbuiltMarker(filePath: string): boolean;
|
|
571
968
|
/**
|
|
572
|
-
*
|
|
969
|
+
* `GET /ping` — a report of the server clock.
|
|
970
|
+
*
|
|
971
|
+
* Liveness is the STATUS CODE's answer, not a field's: a 200 means reachable,
|
|
972
|
+
* and any other outcome throws before a body is read. So the body carries the
|
|
973
|
+
* one thing a status code cannot — the server's own clock, which is what lets a
|
|
974
|
+
* client detect skew against a token expiry. It read `{ success: true,
|
|
975
|
+
* timestamp? }` until 2026-07-29, where `success` was a literal constant in the
|
|
976
|
+
* route (zero bits, and the platform's own named anti-pattern) while the field
|
|
977
|
+
* that IS the payload was optional. See {@link DeploymentDeleteResponse} for
|
|
978
|
+
* the law, and `tests/response-shapes.test.ts` for the fence that holds it.
|
|
573
979
|
*/
|
|
574
980
|
export interface PingResponse {
|
|
575
|
-
/** Always true if service is healthy */
|
|
576
|
-
success: boolean;
|
|
577
981
|
/** Server time in unix seconds — the one wire unit for timestamps. */
|
|
578
|
-
timestamp
|
|
982
|
+
readonly timestamp: number;
|
|
579
983
|
}
|
|
580
984
|
/**
|
|
581
985
|
* Where human identity is mounted on the API host. The API mounts Better
|
|
@@ -605,30 +1009,35 @@ export declare const AuthMethod: {
|
|
|
605
1009
|
};
|
|
606
1010
|
export type AuthMethodType = (typeof AuthMethod)[keyof typeof AuthMethod];
|
|
607
1011
|
/**
|
|
608
|
-
* Shape constants for API keys (`ship-{
|
|
1012
|
+
* Shape constants for API keys (`ship-{32 hex chars}`).
|
|
609
1013
|
* Single source of truth used by validation utilities and auth middleware.
|
|
610
1014
|
*/
|
|
611
1015
|
export declare const API_KEY: {
|
|
612
1016
|
/** Prefix that identifies an API key. */
|
|
613
1017
|
readonly PREFIX: "ship-";
|
|
614
1018
|
/** Number of hex characters following the prefix. */
|
|
615
|
-
readonly HEX_LENGTH:
|
|
616
|
-
/** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH =
|
|
617
|
-
readonly TOTAL_LENGTH:
|
|
1019
|
+
readonly HEX_LENGTH: 32;
|
|
1020
|
+
/** Total length of an API key including prefix (`PREFIX.length + HEX_LENGTH = 37`). */
|
|
1021
|
+
readonly TOTAL_LENGTH: 37;
|
|
618
1022
|
/** Number of trailing characters used to display a redacted hint (e.g. last 4). */
|
|
619
1023
|
readonly HINT_LENGTH: 4;
|
|
620
1024
|
};
|
|
621
1025
|
/**
|
|
622
|
-
* Shape constants for deploy tokens (`deploy-{
|
|
1026
|
+
* Shape constants for deploy tokens (`deploy-{32 hex chars}`).
|
|
623
1027
|
* Single source of truth used by validation utilities and auth middleware.
|
|
1028
|
+
*
|
|
1029
|
+
* Deliberately the same width as `API_KEY`: both are minted by one generator
|
|
1030
|
+
* and classified by prefix alone, so a length that differed between them
|
|
1031
|
+
* would be a second thing to know about a credential whose prefix already
|
|
1032
|
+
* says what it is.
|
|
624
1033
|
*/
|
|
625
1034
|
export declare const DEPLOY_TOKEN: {
|
|
626
1035
|
/** Prefix that identifies a deploy token. */
|
|
627
1036
|
readonly PREFIX: "deploy-";
|
|
628
1037
|
/** Number of hex characters following the prefix. */
|
|
629
|
-
readonly HEX_LENGTH:
|
|
630
|
-
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH =
|
|
631
|
-
readonly TOTAL_LENGTH:
|
|
1038
|
+
readonly HEX_LENGTH: 32;
|
|
1039
|
+
/** Total length of a deploy token including prefix (`PREFIX.length + HEX_LENGTH = 39`). */
|
|
1040
|
+
readonly TOTAL_LENGTH: 39;
|
|
632
1041
|
};
|
|
633
1042
|
/**
|
|
634
1043
|
* Shape constants for caller identifiers (the `X-Caller` instance-identity
|
|
@@ -697,6 +1106,26 @@ export declare const SPA_DEFAULT_CONFIG: {
|
|
|
697
1106
|
readonly destination: "/index.html";
|
|
698
1107
|
}];
|
|
699
1108
|
};
|
|
1109
|
+
/**
|
|
1110
|
+
* The `/spa-check` pre-flight's client-side envelope: which file is the
|
|
1111
|
+
* check's subject, and how large it may be before a client skips the call.
|
|
1112
|
+
*
|
|
1113
|
+
* One fact with three holders until this export — the API's config declared
|
|
1114
|
+
* the cap, the SDK's `checkSPA` hardcoded `100 * 1024`, and prose restated
|
|
1115
|
+
* "100KB". `INDEX_FILE` is the selection rule (the file whose content rides
|
|
1116
|
+
* `SPACheckRequest.index`), restated by every client that builds the request.
|
|
1117
|
+
*
|
|
1118
|
+
* Neither member is a validation boundary: a client over the cap simply
|
|
1119
|
+
* skips the pre-flight, because the server answers an oversized index
|
|
1120
|
+
* `isSPA: false` anyway. A consumer that cannot import this (n8n) needs no
|
|
1121
|
+
* size copy at all — outcome parity is the server's, not the client's.
|
|
1122
|
+
*/
|
|
1123
|
+
export declare const SPA_CHECK_CONSTRAINTS: {
|
|
1124
|
+
/** The file whose content is the check's subject. */
|
|
1125
|
+
readonly INDEX_FILE: "index.html";
|
|
1126
|
+
/** Skip the pre-flight above this size — the server would answer false. */
|
|
1127
|
+
readonly MAX_INDEX_BYTES: number;
|
|
1128
|
+
};
|
|
700
1129
|
/**
|
|
701
1130
|
* Assert that a ship.json file is *syntactically* loadable. Syntax only —
|
|
702
1131
|
* never schema.
|
|
@@ -769,16 +1198,26 @@ export interface SPACheckRequest {
|
|
|
769
1198
|
/**
|
|
770
1199
|
* Response from SPA check endpoint
|
|
771
1200
|
*/
|
|
1201
|
+
/**
|
|
1202
|
+
* Which of the classifier's tiers reached the verdict, and why. Named rather
|
|
1203
|
+
* than inline so the API's own `checkSPA` can return `SPACheckResponse`
|
|
1204
|
+
* instead of restating its shape.
|
|
1205
|
+
*/
|
|
1206
|
+
export interface SPACheckDebug {
|
|
1207
|
+
/** Which tier made the detection */
|
|
1208
|
+
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
1209
|
+
/** The reason for the detection result */
|
|
1210
|
+
reason: string;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* A report: it answers a question and carries only the answer (`CLAUDE.md`,
|
|
1214
|
+
* "A report answers a question").
|
|
1215
|
+
*/
|
|
772
1216
|
export interface SPACheckResponse {
|
|
773
1217
|
/** Whether the project is detected as a Single Page Application */
|
|
774
1218
|
isSPA: boolean;
|
|
775
1219
|
/** Debugging information about detection */
|
|
776
|
-
debug:
|
|
777
|
-
/** Which tier made the detection: 'exclusions', 'inclusions', 'scoring', 'ai', or 'fallback' */
|
|
778
|
-
tier: 'exclusions' | 'inclusions' | 'scoring' | 'ai' | 'fallback';
|
|
779
|
-
/** The reason for the detection result */
|
|
780
|
-
reason: string;
|
|
781
|
-
};
|
|
1220
|
+
debug: SPACheckDebug;
|
|
782
1221
|
}
|
|
783
1222
|
/**
|
|
784
1223
|
* Represents a file that has been processed and is ready for deploy.
|
|
@@ -811,6 +1250,50 @@ export interface StaticFile {
|
|
|
811
1250
|
}
|
|
812
1251
|
/** Default API URL if not otherwise configured. */
|
|
813
1252
|
export declare const DEFAULT_API = "https://api.shipstatic.com";
|
|
1253
|
+
/**
|
|
1254
|
+
* The Node SDK's ambient configuration pair — the ONLY environment variables
|
|
1255
|
+
* the SDK reads, and therefore the COMPLETE list an embedding host must
|
|
1256
|
+
* scrub (per `npm/ship`'s strict-isolation contract, scrubbing is the host's
|
|
1257
|
+
* job, not the SDK's). A host that derives its scrub from this object's
|
|
1258
|
+
* values — as the VS Code extension's child-process env block does — picks
|
|
1259
|
+
* up a grown contract at the next pin bump instead of by remembered prose.
|
|
1260
|
+
*
|
|
1261
|
+
* Browser builds read no environment at all, and the CLI-only variables
|
|
1262
|
+
* (`SHIP_PASSWORD`, `SHIP_VIA`) are deliberately NOT here: they are the
|
|
1263
|
+
* CLI's operational levers, not the SDK's ambient contract — see
|
|
1264
|
+
* `npm/ship/CLAUDE.md`, "CLI-only env vars".
|
|
1265
|
+
*/
|
|
1266
|
+
export declare const SHIP_ENV: {
|
|
1267
|
+
/** The one credential slot — any platform token. */
|
|
1268
|
+
readonly TOKEN: "SHIP_TOKEN";
|
|
1269
|
+
/** The API endpoint override. */
|
|
1270
|
+
readonly API_URL: "SHIP_API_URL";
|
|
1271
|
+
};
|
|
1272
|
+
/**
|
|
1273
|
+
* Where a human creates an API key — the console deep link quoted by every
|
|
1274
|
+
* surface that teaches authentication (the CLI's config wizard, the VS Code
|
|
1275
|
+
* and n8n listings, the n8n rate-limit hint and credential copy). Written
|
|
1276
|
+
* out in five files across three repos until this export.
|
|
1277
|
+
*
|
|
1278
|
+
* Production-branded by design: published artifacts name the product, never
|
|
1279
|
+
* an environment (root `CLAUDE.md`, "Environment-Aware URLs").
|
|
1280
|
+
*/
|
|
1281
|
+
export declare const MY_API_KEY_URL = "https://my.shipstatic.com/api-key";
|
|
1282
|
+
/**
|
|
1283
|
+
* How long an anonymous deployment lives before it expires.
|
|
1284
|
+
*
|
|
1285
|
+
* The lifetime of the public tier, and one fact with several readers. The API
|
|
1286
|
+
* stamps a deployment's `expires` from it and gives a claim code exactly the
|
|
1287
|
+
* same window — a live site with a dead claim link is a coherence bug, so the
|
|
1288
|
+
* two are one constant rather than two that agree. Both MCP transports quote
|
|
1289
|
+
* the duration in prose an agent reads, and derive it from here rather than
|
|
1290
|
+
* writing it out, which they did in eight places until this export existed.
|
|
1291
|
+
*
|
|
1292
|
+
* Seconds, spelled in the name: this platform has both second- and
|
|
1293
|
+
* millisecond-valued durations, and the pair is only safe when each says which
|
|
1294
|
+
* it is.
|
|
1295
|
+
*/
|
|
1296
|
+
export declare const PUBLIC_DEPLOYMENT_TTL_SECONDS: number;
|
|
814
1297
|
/**
|
|
815
1298
|
* Universal deploy input — the union of every shape the SDK accepts.
|
|
816
1299
|
*
|
|
@@ -829,8 +1312,12 @@ export type DeployInput = File[] | string | string[];
|
|
|
829
1312
|
export interface DeploymentUploadOptions {
|
|
830
1313
|
/** Optional labels for categorization and filtering */
|
|
831
1314
|
labels?: string[];
|
|
832
|
-
/**
|
|
833
|
-
|
|
1315
|
+
/**
|
|
1316
|
+
* Which client is making this deploy. Closed, because the server silently
|
|
1317
|
+
* ignores anything outside the set — so an unchecked string turned a typo
|
|
1318
|
+
* into missing analytics rather than an error. See {@link DeploymentVia}.
|
|
1319
|
+
*/
|
|
1320
|
+
via?: DeploymentViaType;
|
|
834
1321
|
/**
|
|
835
1322
|
* Optional password that protects this deployment.
|
|
836
1323
|
*
|
|
@@ -850,28 +1337,52 @@ export interface DeploymentUploadOptions {
|
|
|
850
1337
|
spa?: boolean;
|
|
851
1338
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
852
1339
|
captcha?: string;
|
|
1340
|
+
/**
|
|
1341
|
+
* Makes this deploy replayable instead of repeatable.
|
|
1342
|
+
*
|
|
1343
|
+
* A deploy is not naturally idempotent: a client-side timeout on a slow
|
|
1344
|
+
* one leaves the caller unable to tell "it never landed" from "it landed
|
|
1345
|
+
* and the response was lost", and retrying produces a second deployment.
|
|
1346
|
+
* Send the same key on the retry and the platform replays the original
|
|
1347
|
+
* 201 verbatim rather than creating anything
|
|
1348
|
+
* ({@link IDEMPOTENCY_KEY_CONSTRAINTS.WINDOW_SECONDS}).
|
|
1349
|
+
*
|
|
1350
|
+
* **Agents are the audience.** A human notices a duplicate; an automated
|
|
1351
|
+
* retry does not. Pick a key that identifies the ATTEMPT — a run id, a
|
|
1352
|
+
* commit sha, a uuid minted before the first try — never one minted fresh
|
|
1353
|
+
* on each retry, which would defeat the point.
|
|
1354
|
+
*
|
|
1355
|
+
* The replay is per-caller, and it stores successes only: a failed deploy
|
|
1356
|
+
* retries fresh under the same key.
|
|
1357
|
+
*/
|
|
1358
|
+
idempotencyKey?: string;
|
|
853
1359
|
}
|
|
854
1360
|
/**
|
|
855
|
-
*
|
|
856
|
-
* the next request; a `null` cursor means the last page. Omitting both
|
|
857
|
-
* returns the server's default first page.
|
|
1361
|
+
* What a caller may change on an existing deployment.
|
|
858
1362
|
*
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1363
|
+
* Labels and nothing else: a deployment's content is immutable by design, so
|
|
1364
|
+
* this is the whole mutable surface rather than a subset someone chose.
|
|
1365
|
+
*/
|
|
1366
|
+
export interface DeploymentSetOptions {
|
|
1367
|
+
labels: string[];
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* What `domains.set()` may create or change. Every field is optional because
|
|
1371
|
+
* the call is a natural-key upsert: omitting `deployment` reserves the
|
|
1372
|
+
* domain, naming one links or re-points it, and labels travel either way.
|
|
864
1373
|
*
|
|
865
|
-
*
|
|
866
|
-
* `
|
|
867
|
-
* platform-wide ones. Ask for a count when you want a count; ask for a page
|
|
868
|
-
* when you want a page.
|
|
1374
|
+
* `deployment` is deliberately not nullable — unlinking is refused (400).
|
|
1375
|
+
* See `npm/ship/CLAUDE.md`, "Domain Write Semantics".
|
|
869
1376
|
*/
|
|
870
|
-
export interface
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1377
|
+
export interface DomainSetOptions {
|
|
1378
|
+
deployment?: string;
|
|
1379
|
+
labels?: string[];
|
|
1380
|
+
}
|
|
1381
|
+
/** What a caller may set when minting a deploy token. */
|
|
1382
|
+
export interface TokenCreateOptions {
|
|
1383
|
+
/** Seconds until expiry; omit for a token that never expires. */
|
|
1384
|
+
ttl?: number;
|
|
1385
|
+
labels?: string[];
|
|
875
1386
|
}
|
|
876
1387
|
/**
|
|
877
1388
|
* Deployment resource interface - the contract all implementations must follow.
|
|
@@ -885,32 +1396,22 @@ export interface DeploymentResource<UploadOptions extends DeploymentUploadOption
|
|
|
885
1396
|
upload: (input: DeployInput, options?: UploadOptions) => Promise<DeploymentCreateResponse>;
|
|
886
1397
|
list: (options?: ListOptions) => Promise<DeploymentListResponse>;
|
|
887
1398
|
get: (id: string) => Promise<Deployment>;
|
|
888
|
-
set: (id: string, options:
|
|
889
|
-
|
|
890
|
-
}) => Promise<Deployment>;
|
|
891
|
-
remove: (id: string) => Promise<void>;
|
|
1399
|
+
set: (id: string, options: DeploymentSetOptions) => Promise<Deployment>;
|
|
1400
|
+
delete: (id: string) => Promise<DeploymentDeleteResponse>;
|
|
892
1401
|
}
|
|
893
1402
|
/**
|
|
894
1403
|
* Domain resource interface - the contract all implementations must follow
|
|
895
1404
|
*/
|
|
896
1405
|
export interface DomainResource {
|
|
897
|
-
set: (name: string, options?:
|
|
898
|
-
deployment?: string;
|
|
899
|
-
labels?: string[];
|
|
900
|
-
}) => Promise<DomainSetResult>;
|
|
1406
|
+
set: (name: string, options?: DomainSetOptions) => Promise<DomainSetResult>;
|
|
901
1407
|
list: (options?: ListOptions) => Promise<DomainListResponse>;
|
|
902
1408
|
get: (name: string) => Promise<Domain>;
|
|
903
|
-
|
|
904
|
-
verify: (name: string) => Promise<
|
|
905
|
-
message: string;
|
|
906
|
-
}>;
|
|
1409
|
+
delete: (name: string) => Promise<DomainDeleteResponse>;
|
|
1410
|
+
verify: (name: string) => Promise<DomainVerifyResponse>;
|
|
907
1411
|
validate: (name: string) => Promise<DomainValidateResponse>;
|
|
908
1412
|
dns: (name: string) => Promise<DomainDnsResponse>;
|
|
909
1413
|
records: (name: string) => Promise<DomainRecordsResponse>;
|
|
910
|
-
share: (name: string) => Promise<
|
|
911
|
-
domain: string;
|
|
912
|
-
hash: string;
|
|
913
|
-
}>;
|
|
1414
|
+
share: (name: string) => Promise<DomainShareResponse>;
|
|
914
1415
|
}
|
|
915
1416
|
/**
|
|
916
1417
|
* Account resource interface - the contract all implementations must follow
|
|
@@ -922,12 +1423,10 @@ export interface AccountResource {
|
|
|
922
1423
|
* Token resource interface - the contract all implementations must follow
|
|
923
1424
|
*/
|
|
924
1425
|
export interface TokenResource {
|
|
925
|
-
create: (options?:
|
|
926
|
-
ttl?: number;
|
|
927
|
-
labels?: string[];
|
|
928
|
-
}) => Promise<TokenCreateResponse>;
|
|
1426
|
+
create: (options?: TokenCreateOptions) => Promise<TokenCreateResponse>;
|
|
929
1427
|
list: (options?: ListOptions) => Promise<TokenListResponse>;
|
|
930
|
-
|
|
1428
|
+
get: (token: string) => Promise<Token>;
|
|
1429
|
+
delete: (token: string) => Promise<TokenDeleteResponse>;
|
|
931
1430
|
}
|
|
932
1431
|
/**
|
|
933
1432
|
* Billing status response from GET /billing/status
|
|
@@ -947,6 +1446,25 @@ export interface BillingStatus {
|
|
|
947
1446
|
/** Link to Creem customer portal for billing management, null if unavailable */
|
|
948
1447
|
portal: string | null;
|
|
949
1448
|
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Acknowledgement of `POST /billing/cancel`.
|
|
1451
|
+
*
|
|
1452
|
+
* Cancelling leaves no billing entity to return, so it answers with the
|
|
1453
|
+
* account and the one field of the account the call changed — the plan it
|
|
1454
|
+
* landed on. See {@link DeploymentDeleteResponse} for the law.
|
|
1455
|
+
*
|
|
1456
|
+
* This read `{ success: true, message: 'Subscription canceled successfully…' }`
|
|
1457
|
+
* until 2026-07-29, an anonymous shape that `web/my` redeclared inline and
|
|
1458
|
+
* whose prose no surface ever displayed: both callers await the promise and
|
|
1459
|
+
* discard the body, then compose their own toast. The message was written,
|
|
1460
|
+
* serialized, and thrown away on every cancellation.
|
|
1461
|
+
*/
|
|
1462
|
+
export interface BillingCancelResponse {
|
|
1463
|
+
/** The account whose subscription was cancelled */
|
|
1464
|
+
readonly account: string;
|
|
1465
|
+
/** The plan the account now holds — `free` on a successful cancellation */
|
|
1466
|
+
readonly plan: AccountPlanType;
|
|
1467
|
+
}
|
|
950
1468
|
/**
|
|
951
1469
|
* Checkout session response from POST /billing/checkout
|
|
952
1470
|
*/
|