@shipstatic/types 2.7.0-beta.3 → 2.7.0-beta.4
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/dist/index.d.ts +68 -0
- package/dist/index.js +78 -3
- package/package.json +1 -1
- package/src/index.ts +102 -3
package/dist/index.d.ts
CHANGED
|
@@ -671,6 +671,12 @@ export declare const DEPLOY_FIELDS: {
|
|
|
671
671
|
readonly VIA: "via";
|
|
672
672
|
/** Plaintext password — the API hashes it server-side. */
|
|
673
673
|
readonly PASSWORD: "password";
|
|
674
|
+
/**
|
|
675
|
+
* Requested lifetime in SECONDS — a duration, never an instant. The API
|
|
676
|
+
* computes and stores the expiry, so the wire carries no client clock.
|
|
677
|
+
* See {@link validateTtl}.
|
|
678
|
+
*/
|
|
679
|
+
readonly TTL: "ttl";
|
|
674
680
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
675
681
|
readonly BUILD: "build";
|
|
676
682
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
@@ -1259,6 +1265,47 @@ export declare function validateApiUrl(apiUrl: string): void;
|
|
|
1259
1265
|
* Example: "happy-cat-abc1234.shipstatic.com"
|
|
1260
1266
|
*/
|
|
1261
1267
|
export declare function isDeployment(input: string): boolean;
|
|
1268
|
+
/**
|
|
1269
|
+
* The envelope a requested lifetime must fit — one word, one grammar, wherever
|
|
1270
|
+
* the platform lets a caller choose how long something lives.
|
|
1271
|
+
*
|
|
1272
|
+
* Two resources wear it: `TokenCreateOptions.ttl` and
|
|
1273
|
+
* `DeploymentUploadOptions.ttl`. It lives here rather than on the server by
|
|
1274
|
+
* the format-vs-policy rule — a client can decide offline whether a duration
|
|
1275
|
+
* is well-formed, and the API rejects the same value the same way. What is
|
|
1276
|
+
* NOT here is any per-plan ceiling: no such policy exists, and one delivered
|
|
1277
|
+
* speculatively through `/limits` would be an owner for a decision nobody has
|
|
1278
|
+
* made.
|
|
1279
|
+
*/
|
|
1280
|
+
export declare const TTL_CONSTRAINTS: {
|
|
1281
|
+
/**
|
|
1282
|
+
* Shortest requestable lifetime, in seconds. One rather than zero: a
|
|
1283
|
+
* deployment that expires the instant it is created is not a shorter lease,
|
|
1284
|
+
* it is a deploy that was never live, and `0` is how an unset variable
|
|
1285
|
+
* arrives.
|
|
1286
|
+
*/
|
|
1287
|
+
readonly MIN_SECONDS: 1;
|
|
1288
|
+
/** Longest requestable lifetime, in seconds — one year. */
|
|
1289
|
+
readonly MAX_SECONDS: number;
|
|
1290
|
+
};
|
|
1291
|
+
/**
|
|
1292
|
+
* Validate a requested lifetime in SECONDS and return it, or `undefined` when
|
|
1293
|
+
* none was asked for.
|
|
1294
|
+
*
|
|
1295
|
+
* **A duration, never an instant.** The caller says how long; the server owns
|
|
1296
|
+
* what time it is and stamps the expiry — so a client's clock, however wrong,
|
|
1297
|
+
* cannot shorten or extend a lease. That is the tokens precedent, and it is
|
|
1298
|
+
* why this rule measures a count of seconds rather than checking a timestamp
|
|
1299
|
+
* against `now`.
|
|
1300
|
+
*
|
|
1301
|
+
* Fractions are refused rather than rounded: a caller who wrote `1.5` meant
|
|
1302
|
+
* something the wire cannot carry, and silently choosing `1` or `2` for them
|
|
1303
|
+
* is a decision the platform has no standing to make.
|
|
1304
|
+
*
|
|
1305
|
+
* Single source of truth shared by the API (the tokens route and the deploy
|
|
1306
|
+
* schema), the SDK's request boundary, and the CLI's parser.
|
|
1307
|
+
*/
|
|
1308
|
+
export declare function validateTtl(value: unknown): number | undefined;
|
|
1262
1309
|
/**
|
|
1263
1310
|
* Request payload for SPA check endpoint
|
|
1264
1311
|
*/
|
|
@@ -1391,6 +1438,27 @@ export interface DeploymentUploadOptions {
|
|
|
1391
1438
|
* into missing analytics rather than an error. See {@link DeploymentVia}.
|
|
1392
1439
|
*/
|
|
1393
1440
|
via?: DeploymentViaType;
|
|
1441
|
+
/**
|
|
1442
|
+
* Seconds until this deployment expires; omit for one that never does.
|
|
1443
|
+
*
|
|
1444
|
+
* The platform reclaims it when the time is up — an ephemeral deployment,
|
|
1445
|
+
* chosen by the deployer rather than by the identity. The same word and the
|
|
1446
|
+
* same grammar as {@link TokenCreateOptions.ttl}, bounded by
|
|
1447
|
+
* {@link TTL_CONSTRAINTS}.
|
|
1448
|
+
*
|
|
1449
|
+
* **Requires a credential.** An anonymous deploy has no deployer, and the
|
|
1450
|
+
* platform owns anonymous lifetime as policy
|
|
1451
|
+
* ({@link PUBLIC_DEPLOYMENT_TTL_SECONDS}) — so a ttl on one is refused
|
|
1452
|
+
* rather than honoured or ignored.
|
|
1453
|
+
*
|
|
1454
|
+
* **A deployment carrying one cannot be linked to a domain.** A domain is a
|
|
1455
|
+
* commitment and a deadline is its opposite; the API refuses the link, which
|
|
1456
|
+
* is what keeps the reaper from tearing a live domain's target away.
|
|
1457
|
+
*
|
|
1458
|
+
* Immutable, like every other field of a deployment: to keep something
|
|
1459
|
+
* longer, redeploy.
|
|
1460
|
+
*/
|
|
1461
|
+
ttl?: number;
|
|
1394
1462
|
/**
|
|
1395
1463
|
* Optional password that protects this deployment.
|
|
1396
1464
|
*
|
package/dist/index.js
CHANGED
|
@@ -214,6 +214,12 @@ export const DEPLOY_FIELDS = {
|
|
|
214
214
|
VIA: 'via',
|
|
215
215
|
/** Plaintext password — the API hashes it server-side. */
|
|
216
216
|
PASSWORD: 'password',
|
|
217
|
+
/**
|
|
218
|
+
* Requested lifetime in SECONDS — a duration, never an instant. The API
|
|
219
|
+
* computes and stores the expiry, so the wire carries no client clock.
|
|
220
|
+
* See {@link validateTtl}.
|
|
221
|
+
*/
|
|
222
|
+
TTL: 'ttl',
|
|
217
223
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
218
224
|
BUILD: 'build',
|
|
219
225
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
@@ -415,9 +421,24 @@ const MAX_FOREIGN_MESSAGE_LENGTH = 200;
|
|
|
415
421
|
* that runtime (`cloudflare/mcp`) reaches the API through a service BINDING,
|
|
416
422
|
* which is in-process and does not produce transport rejections at all.
|
|
417
423
|
*
|
|
418
|
-
* The
|
|
419
|
-
*
|
|
420
|
-
*
|
|
424
|
+
* **The `TokenProvider` case stopped being a trade when clients gained
|
|
425
|
+
* retries.** A caller's provider that throws a coded error is typed `Network`
|
|
426
|
+
* here, which was recorded as "both are wrong for it; `Network` is the cheaper
|
|
427
|
+
* wrong" — written when the classification decided only what a surface would
|
|
428
|
+
* SAY. It now also decides whether the call is retried, and that turns the
|
|
429
|
+
* cheaper wrong into the right answer: a `TokenProvider` is where minting and
|
|
430
|
+
* refresh live, so the common one is an OAuth refresh over the network, and a
|
|
431
|
+
* transient failure there is precisely what another attempt repairs.
|
|
432
|
+
*
|
|
433
|
+
* The residual cost is a deterministic provider fault — a genuinely missing
|
|
434
|
+
* keychain entry — invoking the provider three times over a few hundred
|
|
435
|
+
* milliseconds before failing with the same error. No request leaves the
|
|
436
|
+
* process on any of them. That is the cheap direction of a bet whose other
|
|
437
|
+
* side is a refused deploy, and suppressing it would need a way to mark
|
|
438
|
+
* credential faults non-retryable: machinery with one holder, refused by the
|
|
439
|
+
* estate's stopping rule. Provider failures that carry no code are `Api` and
|
|
440
|
+
* are not retried at all, and a provider yielding nothing is `Authentication`
|
|
441
|
+
* by the fail-closed invariant, which is likewise terminal.
|
|
421
442
|
*/
|
|
422
443
|
function isTransportFailure(cause) {
|
|
423
444
|
const code = cause.code;
|
|
@@ -1311,6 +1332,60 @@ export function validateApiUrl(apiUrl) {
|
|
|
1311
1332
|
export function isDeployment(input) {
|
|
1312
1333
|
return /^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(input);
|
|
1313
1334
|
}
|
|
1335
|
+
/**
|
|
1336
|
+
* The envelope a requested lifetime must fit — one word, one grammar, wherever
|
|
1337
|
+
* the platform lets a caller choose how long something lives.
|
|
1338
|
+
*
|
|
1339
|
+
* Two resources wear it: `TokenCreateOptions.ttl` and
|
|
1340
|
+
* `DeploymentUploadOptions.ttl`. It lives here rather than on the server by
|
|
1341
|
+
* the format-vs-policy rule — a client can decide offline whether a duration
|
|
1342
|
+
* is well-formed, and the API rejects the same value the same way. What is
|
|
1343
|
+
* NOT here is any per-plan ceiling: no such policy exists, and one delivered
|
|
1344
|
+
* speculatively through `/limits` would be an owner for a decision nobody has
|
|
1345
|
+
* made.
|
|
1346
|
+
*/
|
|
1347
|
+
export const TTL_CONSTRAINTS = {
|
|
1348
|
+
/**
|
|
1349
|
+
* Shortest requestable lifetime, in seconds. One rather than zero: a
|
|
1350
|
+
* deployment that expires the instant it is created is not a shorter lease,
|
|
1351
|
+
* it is a deploy that was never live, and `0` is how an unset variable
|
|
1352
|
+
* arrives.
|
|
1353
|
+
*/
|
|
1354
|
+
MIN_SECONDS: 1,
|
|
1355
|
+
/** Longest requestable lifetime, in seconds — one year. */
|
|
1356
|
+
MAX_SECONDS: 365 * 24 * 60 * 60,
|
|
1357
|
+
};
|
|
1358
|
+
/**
|
|
1359
|
+
* Validate a requested lifetime in SECONDS and return it, or `undefined` when
|
|
1360
|
+
* none was asked for.
|
|
1361
|
+
*
|
|
1362
|
+
* **A duration, never an instant.** The caller says how long; the server owns
|
|
1363
|
+
* what time it is and stamps the expiry — so a client's clock, however wrong,
|
|
1364
|
+
* cannot shorten or extend a lease. That is the tokens precedent, and it is
|
|
1365
|
+
* why this rule measures a count of seconds rather than checking a timestamp
|
|
1366
|
+
* against `now`.
|
|
1367
|
+
*
|
|
1368
|
+
* Fractions are refused rather than rounded: a caller who wrote `1.5` meant
|
|
1369
|
+
* something the wire cannot carry, and silently choosing `1` or `2` for them
|
|
1370
|
+
* is a decision the platform has no standing to make.
|
|
1371
|
+
*
|
|
1372
|
+
* Single source of truth shared by the API (the tokens route and the deploy
|
|
1373
|
+
* schema), the SDK's request boundary, and the CLI's parser.
|
|
1374
|
+
*/
|
|
1375
|
+
export function validateTtl(value) {
|
|
1376
|
+
if (value === undefined || value === null)
|
|
1377
|
+
return undefined;
|
|
1378
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
1379
|
+
throw ShipError.validation('TTL must be a number of seconds');
|
|
1380
|
+
}
|
|
1381
|
+
if (!Number.isInteger(value)) {
|
|
1382
|
+
throw ShipError.validation('TTL must be a whole number of seconds');
|
|
1383
|
+
}
|
|
1384
|
+
if (value < TTL_CONSTRAINTS.MIN_SECONDS || value > TTL_CONSTRAINTS.MAX_SECONDS) {
|
|
1385
|
+
throw ShipError.validation(`TTL must be between ${TTL_CONSTRAINTS.MIN_SECONDS} and ${TTL_CONSTRAINTS.MAX_SECONDS} seconds`);
|
|
1386
|
+
}
|
|
1387
|
+
return value;
|
|
1388
|
+
}
|
|
1314
1389
|
// =============================================================================
|
|
1315
1390
|
// PLATFORM CONSTANTS
|
|
1316
1391
|
// =============================================================================
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -756,6 +756,12 @@ export const DEPLOY_FIELDS = {
|
|
|
756
756
|
VIA: 'via',
|
|
757
757
|
/** Plaintext password — the API hashes it server-side. */
|
|
758
758
|
PASSWORD: 'password',
|
|
759
|
+
/**
|
|
760
|
+
* Requested lifetime in SECONDS — a duration, never an instant. The API
|
|
761
|
+
* computes and stores the expiry, so the wire carries no client clock.
|
|
762
|
+
* See {@link validateTtl}.
|
|
763
|
+
*/
|
|
764
|
+
TTL: 'ttl',
|
|
759
765
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
760
766
|
BUILD: 'build',
|
|
761
767
|
/** @internal Server-processing flag — first-party `/upload` only. */
|
|
@@ -968,9 +974,24 @@ const MAX_FOREIGN_MESSAGE_LENGTH = 200;
|
|
|
968
974
|
* that runtime (`cloudflare/mcp`) reaches the API through a service BINDING,
|
|
969
975
|
* which is in-process and does not produce transport rejections at all.
|
|
970
976
|
*
|
|
971
|
-
* The
|
|
972
|
-
*
|
|
973
|
-
*
|
|
977
|
+
* **The `TokenProvider` case stopped being a trade when clients gained
|
|
978
|
+
* retries.** A caller's provider that throws a coded error is typed `Network`
|
|
979
|
+
* here, which was recorded as "both are wrong for it; `Network` is the cheaper
|
|
980
|
+
* wrong" — written when the classification decided only what a surface would
|
|
981
|
+
* SAY. It now also decides whether the call is retried, and that turns the
|
|
982
|
+
* cheaper wrong into the right answer: a `TokenProvider` is where minting and
|
|
983
|
+
* refresh live, so the common one is an OAuth refresh over the network, and a
|
|
984
|
+
* transient failure there is precisely what another attempt repairs.
|
|
985
|
+
*
|
|
986
|
+
* The residual cost is a deterministic provider fault — a genuinely missing
|
|
987
|
+
* keychain entry — invoking the provider three times over a few hundred
|
|
988
|
+
* milliseconds before failing with the same error. No request leaves the
|
|
989
|
+
* process on any of them. That is the cheap direction of a bet whose other
|
|
990
|
+
* side is a refused deploy, and suppressing it would need a way to mark
|
|
991
|
+
* credential faults non-retryable: machinery with one holder, refused by the
|
|
992
|
+
* estate's stopping rule. Provider failures that carry no code are `Api` and
|
|
993
|
+
* are not retried at all, and a provider yielding nothing is `Authentication`
|
|
994
|
+
* by the fail-closed invariant, which is likewise terminal.
|
|
974
995
|
*/
|
|
975
996
|
function isTransportFailure(cause: Error): boolean {
|
|
976
997
|
const code = (cause as { code?: unknown }).code;
|
|
@@ -2033,6 +2054,63 @@ export function isDeployment(input: string): boolean {
|
|
|
2033
2054
|
return /^[a-z]+-[a-z]+-[a-z0-9]{7}(\.[a-z0-9.-]+)?$/i.test(input);
|
|
2034
2055
|
}
|
|
2035
2056
|
|
|
2057
|
+
/**
|
|
2058
|
+
* The envelope a requested lifetime must fit — one word, one grammar, wherever
|
|
2059
|
+
* the platform lets a caller choose how long something lives.
|
|
2060
|
+
*
|
|
2061
|
+
* Two resources wear it: `TokenCreateOptions.ttl` and
|
|
2062
|
+
* `DeploymentUploadOptions.ttl`. It lives here rather than on the server by
|
|
2063
|
+
* the format-vs-policy rule — a client can decide offline whether a duration
|
|
2064
|
+
* is well-formed, and the API rejects the same value the same way. What is
|
|
2065
|
+
* NOT here is any per-plan ceiling: no such policy exists, and one delivered
|
|
2066
|
+
* speculatively through `/limits` would be an owner for a decision nobody has
|
|
2067
|
+
* made.
|
|
2068
|
+
*/
|
|
2069
|
+
export const TTL_CONSTRAINTS = {
|
|
2070
|
+
/**
|
|
2071
|
+
* Shortest requestable lifetime, in seconds. One rather than zero: a
|
|
2072
|
+
* deployment that expires the instant it is created is not a shorter lease,
|
|
2073
|
+
* it is a deploy that was never live, and `0` is how an unset variable
|
|
2074
|
+
* arrives.
|
|
2075
|
+
*/
|
|
2076
|
+
MIN_SECONDS: 1,
|
|
2077
|
+
/** Longest requestable lifetime, in seconds — one year. */
|
|
2078
|
+
MAX_SECONDS: 365 * 24 * 60 * 60,
|
|
2079
|
+
} as const;
|
|
2080
|
+
|
|
2081
|
+
/**
|
|
2082
|
+
* Validate a requested lifetime in SECONDS and return it, or `undefined` when
|
|
2083
|
+
* none was asked for.
|
|
2084
|
+
*
|
|
2085
|
+
* **A duration, never an instant.** The caller says how long; the server owns
|
|
2086
|
+
* what time it is and stamps the expiry — so a client's clock, however wrong,
|
|
2087
|
+
* cannot shorten or extend a lease. That is the tokens precedent, and it is
|
|
2088
|
+
* why this rule measures a count of seconds rather than checking a timestamp
|
|
2089
|
+
* against `now`.
|
|
2090
|
+
*
|
|
2091
|
+
* Fractions are refused rather than rounded: a caller who wrote `1.5` meant
|
|
2092
|
+
* something the wire cannot carry, and silently choosing `1` or `2` for them
|
|
2093
|
+
* is a decision the platform has no standing to make.
|
|
2094
|
+
*
|
|
2095
|
+
* Single source of truth shared by the API (the tokens route and the deploy
|
|
2096
|
+
* schema), the SDK's request boundary, and the CLI's parser.
|
|
2097
|
+
*/
|
|
2098
|
+
export function validateTtl(value: unknown): number | undefined {
|
|
2099
|
+
if (value === undefined || value === null) return undefined;
|
|
2100
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
2101
|
+
throw ShipError.validation('TTL must be a number of seconds');
|
|
2102
|
+
}
|
|
2103
|
+
if (!Number.isInteger(value)) {
|
|
2104
|
+
throw ShipError.validation('TTL must be a whole number of seconds');
|
|
2105
|
+
}
|
|
2106
|
+
if (value < TTL_CONSTRAINTS.MIN_SECONDS || value > TTL_CONSTRAINTS.MAX_SECONDS) {
|
|
2107
|
+
throw ShipError.validation(
|
|
2108
|
+
`TTL must be between ${TTL_CONSTRAINTS.MIN_SECONDS} and ${TTL_CONSTRAINTS.MAX_SECONDS} seconds`,
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
return value;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2036
2114
|
// =============================================================================
|
|
2037
2115
|
// SPA CHECK TYPES
|
|
2038
2116
|
// =============================================================================
|
|
@@ -2190,6 +2268,27 @@ export interface DeploymentUploadOptions {
|
|
|
2190
2268
|
* into missing analytics rather than an error. See {@link DeploymentVia}.
|
|
2191
2269
|
*/
|
|
2192
2270
|
via?: DeploymentViaType;
|
|
2271
|
+
/**
|
|
2272
|
+
* Seconds until this deployment expires; omit for one that never does.
|
|
2273
|
+
*
|
|
2274
|
+
* The platform reclaims it when the time is up — an ephemeral deployment,
|
|
2275
|
+
* chosen by the deployer rather than by the identity. The same word and the
|
|
2276
|
+
* same grammar as {@link TokenCreateOptions.ttl}, bounded by
|
|
2277
|
+
* {@link TTL_CONSTRAINTS}.
|
|
2278
|
+
*
|
|
2279
|
+
* **Requires a credential.** An anonymous deploy has no deployer, and the
|
|
2280
|
+
* platform owns anonymous lifetime as policy
|
|
2281
|
+
* ({@link PUBLIC_DEPLOYMENT_TTL_SECONDS}) — so a ttl on one is refused
|
|
2282
|
+
* rather than honoured or ignored.
|
|
2283
|
+
*
|
|
2284
|
+
* **A deployment carrying one cannot be linked to a domain.** A domain is a
|
|
2285
|
+
* commitment and a deadline is its opposite; the API refuses the link, which
|
|
2286
|
+
* is what keeps the reaper from tearing a live domain's target away.
|
|
2287
|
+
*
|
|
2288
|
+
* Immutable, like every other field of a deployment: to keep something
|
|
2289
|
+
* longer, redeploy.
|
|
2290
|
+
*/
|
|
2291
|
+
ttl?: number;
|
|
2193
2292
|
/**
|
|
2194
2293
|
* Optional password that protects this deployment.
|
|
2195
2294
|
*
|