@shipstatic/types 2.5.0-beta.12 → 2.5.0-beta.13
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 +1 -0
- package/dist/index.d.ts +55 -5
- package/dist/index.js +50 -5
- package/package.json +1 -1
- package/src/index.ts +72 -5
package/README.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -52,11 +52,24 @@ export interface DeploymentCreateResponse extends Deployment {
|
|
|
52
52
|
/**
|
|
53
53
|
* Every path the public API answers on, declared once.
|
|
54
54
|
*
|
|
55
|
-
* The URL surface
|
|
56
|
-
*
|
|
57
|
-
* rename meant finding all four.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
55
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
56
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
57
|
+
* rename meant finding all four. The first three now read this table.
|
|
58
|
+
*
|
|
59
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
60
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
61
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
62
|
+
* than keeping it uniform.
|
|
63
|
+
*
|
|
64
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
65
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
66
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
67
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
68
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
69
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
70
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
71
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
72
|
+
* than merely asserted.
|
|
60
73
|
*
|
|
61
74
|
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
62
75
|
* to `web/my`, for the same reason its row types do: this package is
|
|
@@ -293,6 +306,24 @@ export interface DomainRecordsResponse {
|
|
|
293
306
|
/** Required DNS records for configuration */
|
|
294
307
|
records: DnsRecord[];
|
|
295
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
311
|
+
*
|
|
312
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
313
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
314
|
+
* API would reject the same value the same way.
|
|
315
|
+
*/
|
|
316
|
+
export declare const IDEMPOTENCY_KEY_CONSTRAINTS: {
|
|
317
|
+
readonly MAX_LENGTH: 256;
|
|
318
|
+
/** How long a stored 201 stays replayable. */
|
|
319
|
+
readonly WINDOW_SECONDS: number;
|
|
320
|
+
};
|
|
321
|
+
/**
|
|
322
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
323
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
324
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
325
|
+
*/
|
|
326
|
+
export declare function validateIdempotencyKey(value: unknown): string | undefined;
|
|
296
327
|
/**
|
|
297
328
|
* Response for `GET /labels` — every label in use across the caller's
|
|
298
329
|
* deployments, domains and tokens, grouped and ordered by last use.
|
|
@@ -1029,6 +1060,25 @@ export interface DeploymentUploadOptions {
|
|
|
1029
1060
|
spa?: boolean;
|
|
1030
1061
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
1031
1062
|
captcha?: string;
|
|
1063
|
+
/**
|
|
1064
|
+
* Makes this deploy replayable instead of repeatable.
|
|
1065
|
+
*
|
|
1066
|
+
* A deploy is not naturally idempotent: a client-side timeout on a slow
|
|
1067
|
+
* one leaves the caller unable to tell "it never landed" from "it landed
|
|
1068
|
+
* and the response was lost", and retrying produces a second deployment.
|
|
1069
|
+
* Send the same key on the retry and the platform replays the original
|
|
1070
|
+
* 201 verbatim rather than creating anything
|
|
1071
|
+
* ({@link IDEMPOTENCY_KEY_CONSTRAINTS.WINDOW_SECONDS}).
|
|
1072
|
+
*
|
|
1073
|
+
* **Agents are the audience.** A human notices a duplicate; an automated
|
|
1074
|
+
* retry does not. Pick a key that identifies the ATTEMPT — a run id, a
|
|
1075
|
+
* commit sha, a uuid minted before the first try — never one that varies
|
|
1076
|
+
* per attempt, which would defeat the point.
|
|
1077
|
+
*
|
|
1078
|
+
* The replay is per-caller, and it stores successes only: a failed deploy
|
|
1079
|
+
* retries fresh under the same key.
|
|
1080
|
+
*/
|
|
1081
|
+
idempotencyKey?: string;
|
|
1032
1082
|
}
|
|
1033
1083
|
/**
|
|
1034
1084
|
* Pagination options for every list endpoint. The response's `cursor` feeds
|
package/dist/index.js
CHANGED
|
@@ -17,11 +17,24 @@ export const DeploymentStatus = {
|
|
|
17
17
|
/**
|
|
18
18
|
* Every path the public API answers on, declared once.
|
|
19
19
|
*
|
|
20
|
-
* The URL surface
|
|
21
|
-
*
|
|
22
|
-
* rename meant finding all four.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
21
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
22
|
+
* rename meant finding all four. The first three now read this table.
|
|
23
|
+
*
|
|
24
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
25
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
26
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
27
|
+
* than keeping it uniform.
|
|
28
|
+
*
|
|
29
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
30
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
31
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
32
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
33
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
34
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
35
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
36
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
37
|
+
* than merely asserted.
|
|
25
38
|
*
|
|
26
39
|
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
27
40
|
* to `web/my`, for the same reason its row types do: this package is
|
|
@@ -74,6 +87,38 @@ export const DomainStatus = {
|
|
|
74
87
|
SUCCESS: 'success',
|
|
75
88
|
PAUSED: 'paused',
|
|
76
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
92
|
+
*
|
|
93
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
94
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
95
|
+
* API would reject the same value the same way.
|
|
96
|
+
*/
|
|
97
|
+
export const IDEMPOTENCY_KEY_CONSTRAINTS = {
|
|
98
|
+
MAX_LENGTH: 256,
|
|
99
|
+
/** How long a stored 201 stays replayable. */
|
|
100
|
+
WINDOW_SECONDS: 24 * 60 * 60,
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
104
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
105
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
106
|
+
*/
|
|
107
|
+
export function validateIdempotencyKey(value) {
|
|
108
|
+
if (value === undefined || value === null)
|
|
109
|
+
return undefined;
|
|
110
|
+
if (typeof value !== 'string') {
|
|
111
|
+
throw ShipError.validation('Idempotency key must be a string.');
|
|
112
|
+
}
|
|
113
|
+
const key = value.trim();
|
|
114
|
+
if (!key) {
|
|
115
|
+
throw ShipError.validation('Idempotency key must not be empty.');
|
|
116
|
+
}
|
|
117
|
+
if (key.length > IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH) {
|
|
118
|
+
throw ShipError.validation(`Idempotency key must be at most ${IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH} characters.`);
|
|
119
|
+
}
|
|
120
|
+
return key;
|
|
121
|
+
}
|
|
77
122
|
// =============================================================================
|
|
78
123
|
// ACCOUNT TYPES
|
|
79
124
|
// =============================================================================
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -61,11 +61,24 @@ export interface DeploymentCreateResponse extends Deployment {
|
|
|
61
61
|
/**
|
|
62
62
|
* Every path the public API answers on, declared once.
|
|
63
63
|
*
|
|
64
|
-
* The URL surface
|
|
65
|
-
*
|
|
66
|
-
* rename meant finding all four.
|
|
67
|
-
*
|
|
68
|
-
*
|
|
64
|
+
* The URL surface was written out in four places — the API's mounts, the
|
|
65
|
+
* SDK's client, the dashboard's client, and the post-deploy smoke — so a
|
|
66
|
+
* rename meant finding all four. The first three now read this table.
|
|
67
|
+
*
|
|
68
|
+
* The smoke (`cloudflare/api/smoke.mjs`) deliberately still spells its own:
|
|
69
|
+
* five of its nine paths are `/admin/*`, which this table excludes by
|
|
70
|
+
* design, and splitting one list between a registry and literals reads worse
|
|
71
|
+
* than keeping it uniform.
|
|
72
|
+
*
|
|
73
|
+
* **What this guarantees, exactly.** Collection paths are mounted from here,
|
|
74
|
+
* so producer and consumer cannot diverge. Item paths are declared here and
|
|
75
|
+
* consumed by clients, but the API spells them relative to their mount
|
|
76
|
+
* (`/:deployment/config`), so the table does not *generate* them — it is
|
|
77
|
+
* held to them by `api/tests/architecture/api-paths.test.ts`, which fails if
|
|
78
|
+
* any entry names a path no route answers. Some entries have no client yet
|
|
79
|
+
* (`DEPLOYMENT_CONFIG`, `DOMAIN_PROPAGATION` — endpoints the SDK
|
|
80
|
+
* deliberately does not reach); the fence is what keeps those honest rather
|
|
81
|
+
* than merely asserted.
|
|
69
82
|
*
|
|
70
83
|
* **The operator surface is deliberately absent.** `/admin/*` paths belong
|
|
71
84
|
* to `web/my`, for the same reason its row types do: this package is
|
|
@@ -324,6 +337,41 @@ export interface DomainRecordsResponse {
|
|
|
324
337
|
records: DnsRecord[];
|
|
325
338
|
}
|
|
326
339
|
|
|
340
|
+
/**
|
|
341
|
+
* The envelope an `Idempotency-Key` must fit, and how long a replay lasts.
|
|
342
|
+
*
|
|
343
|
+
* Format lives here rather than on the server alone by the format-vs-policy
|
|
344
|
+
* rule: a client can decide offline whether a key is well-formed, and the
|
|
345
|
+
* API would reject the same value the same way.
|
|
346
|
+
*/
|
|
347
|
+
export const IDEMPOTENCY_KEY_CONSTRAINTS = {
|
|
348
|
+
MAX_LENGTH: 256,
|
|
349
|
+
/** How long a stored 201 stays replayable. */
|
|
350
|
+
WINDOW_SECONDS: 24 * 60 * 60,
|
|
351
|
+
} as const;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Validate an idempotency key, returning the trimmed value or `undefined`
|
|
355
|
+
* when none was supplied. Throws {@link ShipError.validation} when the value
|
|
356
|
+
* cannot be sent — the same verdict the API would reach, reached earlier.
|
|
357
|
+
*/
|
|
358
|
+
export function validateIdempotencyKey(value: unknown): string | undefined {
|
|
359
|
+
if (value === undefined || value === null) return undefined;
|
|
360
|
+
if (typeof value !== 'string') {
|
|
361
|
+
throw ShipError.validation('Idempotency key must be a string.');
|
|
362
|
+
}
|
|
363
|
+
const key = value.trim();
|
|
364
|
+
if (!key) {
|
|
365
|
+
throw ShipError.validation('Idempotency key must not be empty.');
|
|
366
|
+
}
|
|
367
|
+
if (key.length > IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH) {
|
|
368
|
+
throw ShipError.validation(
|
|
369
|
+
`Idempotency key must be at most ${IDEMPOTENCY_KEY_CONSTRAINTS.MAX_LENGTH} characters.`,
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
return key;
|
|
373
|
+
}
|
|
374
|
+
|
|
327
375
|
/**
|
|
328
376
|
* Response for `GET /labels` — every label in use across the caller's
|
|
329
377
|
* deployments, domains and tokens, grouped and ordered by last use.
|
|
@@ -1534,6 +1582,25 @@ export interface DeploymentUploadOptions {
|
|
|
1534
1582
|
spa?: boolean;
|
|
1535
1583
|
/** @internal reCAPTCHA proof for the anonymous human deploy channel. Only available via /upload endpoint. */
|
|
1536
1584
|
captcha?: string;
|
|
1585
|
+
/**
|
|
1586
|
+
* Makes this deploy replayable instead of repeatable.
|
|
1587
|
+
*
|
|
1588
|
+
* A deploy is not naturally idempotent: a client-side timeout on a slow
|
|
1589
|
+
* one leaves the caller unable to tell "it never landed" from "it landed
|
|
1590
|
+
* and the response was lost", and retrying produces a second deployment.
|
|
1591
|
+
* Send the same key on the retry and the platform replays the original
|
|
1592
|
+
* 201 verbatim rather than creating anything
|
|
1593
|
+
* ({@link IDEMPOTENCY_KEY_CONSTRAINTS.WINDOW_SECONDS}).
|
|
1594
|
+
*
|
|
1595
|
+
* **Agents are the audience.** A human notices a duplicate; an automated
|
|
1596
|
+
* retry does not. Pick a key that identifies the ATTEMPT — a run id, a
|
|
1597
|
+
* commit sha, a uuid minted before the first try — never one that varies
|
|
1598
|
+
* per attempt, which would defeat the point.
|
|
1599
|
+
*
|
|
1600
|
+
* The replay is per-caller, and it stores successes only: a failed deploy
|
|
1601
|
+
* retries fresh under the same key.
|
|
1602
|
+
*/
|
|
1603
|
+
idempotencyKey?: string;
|
|
1537
1604
|
}
|
|
1538
1605
|
|
|
1539
1606
|
/**
|