@shipstatic/types 0.9.7 → 0.9.9
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 +10 -1
- package/dist/index.d.ts +18 -4
- package/dist/index.js +33 -8
- package/package.json +1 -1
- package/src/index.ts +38 -9
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ try { response = await fetch(url); }
|
|
|
68
68
|
catch (cause) { throw ShipError.fromFetchError(cause, 'Get account'); }
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
`fromHttpResponse` trusts the body's `error` field when it's a known server-producible `ErrorType` — so a server's `ShipError.validation(...)` round-trips back to `ErrorType.Validation` on the client. For non-API responses (CDN errors, intermediaries) or malformed bodies it falls back to status-derived (401 → `Authentication`, 429 → `RateLimit`, else → `Api`). Body's `message` and `details` are preserved best-effort.
|
|
71
|
+
`fromHttpResponse` trusts the body's `error` field when it's a known server-producible `ErrorType` — so a server's `ShipError.validation(...)` round-trips back to `ErrorType.Validation` on the client. For non-API responses (CDN errors, intermediaries) or malformed bodies it falls back to status-derived (401 → `Authentication`, 403 → `Forbidden`, 429 → `RateLimit`, else → `Api`). Client-only types (`Network`, `Cancelled`, `File`, `Config`) are filtered out of the trusted set. Body's `message` and `details` are preserved best-effort.
|
|
72
72
|
|
|
73
73
|
`fromFetchError` routes by the thrown cause: an existing `ShipError` is returned unchanged, `AbortError` becomes `Cancelled`, a fetch `TypeError` becomes `Network`, anything else becomes `Api` (with no HTTP status — the request never reached the server).
|
|
74
74
|
|
|
@@ -159,6 +159,15 @@ import {
|
|
|
159
159
|
} from '@shipstatic/types';
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
+
### Password Utilities
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import {
|
|
166
|
+
PASSWORD_CONSTRAINTS, // { MIN_LENGTH: 6, MAX_LENGTH: 128 }
|
|
167
|
+
validatePassword, // (value: unknown) => string | undefined
|
|
168
|
+
} from '@shipstatic/types';
|
|
169
|
+
```
|
|
170
|
+
|
|
162
171
|
### Constants
|
|
163
172
|
|
|
164
173
|
```typescript
|
package/dist/index.d.ts
CHANGED
|
@@ -397,7 +397,7 @@ export declare class ShipError extends Error {
|
|
|
397
397
|
static validation(message: string, details?: unknown): ShipError;
|
|
398
398
|
static notFound(resource: string, id?: string): ShipError;
|
|
399
399
|
static forbidden(message: string, details?: unknown): ShipError;
|
|
400
|
-
static rateLimit(message?: string): ShipError;
|
|
400
|
+
static rateLimit(message?: string, details?: unknown): ShipError;
|
|
401
401
|
/**
|
|
402
402
|
* Construct an Authentication (401) error.
|
|
403
403
|
*
|
|
@@ -412,12 +412,12 @@ export declare class ShipError extends Error {
|
|
|
412
412
|
* `internal`. Other `details` keys round-trip normally.
|
|
413
413
|
*/
|
|
414
414
|
static authentication(message?: string, details?: unknown): ShipError;
|
|
415
|
-
static business(message: string, status?: number): ShipError;
|
|
415
|
+
static business(message: string, status?: number, details?: unknown): ShipError;
|
|
416
416
|
static network(message: string, details?: unknown): ShipError;
|
|
417
|
-
static cancelled(message: string): ShipError;
|
|
417
|
+
static cancelled(message: string, details?: unknown): ShipError;
|
|
418
418
|
static file(message: string, details?: unknown): ShipError;
|
|
419
419
|
static config(message: string, details?: unknown): ShipError;
|
|
420
|
-
static api(message: string, status?: number): ShipError;
|
|
420
|
+
static api(message: string, status?: number, details?: unknown): ShipError;
|
|
421
421
|
isClientError(): boolean;
|
|
422
422
|
isNetworkError(): boolean;
|
|
423
423
|
isAuthError(): boolean;
|
|
@@ -1012,3 +1012,17 @@ export declare const PASSWORD_CONSTRAINTS: {
|
|
|
1012
1012
|
/** Maximum password length in characters */
|
|
1013
1013
|
readonly MAX_LENGTH: 128;
|
|
1014
1014
|
};
|
|
1015
|
+
/**
|
|
1016
|
+
* Validate an optional deployment password and return it normalized.
|
|
1017
|
+
*
|
|
1018
|
+
* Absent (`undefined` / `null`) → returns `undefined`; an unprotected
|
|
1019
|
+
* deployment is a valid choice. Present → must be a string within
|
|
1020
|
+
* `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim —
|
|
1021
|
+
* significant. Throws `ShipError.validation` on breach.
|
|
1022
|
+
*
|
|
1023
|
+
* Single source of truth shared by SDK (client-side validation, return
|
|
1024
|
+
* ignored) and API (server-side enforcement, return threaded into config).
|
|
1025
|
+
* Length is part of the wire-format contract; strength rules, if added later,
|
|
1026
|
+
* stay server-side. See `CLAUDE.md` "Validation: format vs policy".
|
|
1027
|
+
*/
|
|
1028
|
+
export declare function validatePassword(value: unknown): string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -247,8 +247,8 @@ export class ShipError extends Error {
|
|
|
247
247
|
static forbidden(message, details) {
|
|
248
248
|
return new ShipError(ErrorType.Forbidden, message, 403, details);
|
|
249
249
|
}
|
|
250
|
-
static rateLimit(message = "Too many requests") {
|
|
251
|
-
return new ShipError(ErrorType.RateLimit, message, 429);
|
|
250
|
+
static rateLimit(message = "Too many requests", details) {
|
|
251
|
+
return new ShipError(ErrorType.RateLimit, message, 429, details);
|
|
252
252
|
}
|
|
253
253
|
/**
|
|
254
254
|
* Construct an Authentication (401) error.
|
|
@@ -266,14 +266,14 @@ export class ShipError extends Error {
|
|
|
266
266
|
static authentication(message = "Authentication required", details) {
|
|
267
267
|
return new ShipError(ErrorType.Authentication, message, 401, details);
|
|
268
268
|
}
|
|
269
|
-
static business(message, status = 400) {
|
|
270
|
-
return new ShipError(ErrorType.Business, message, status);
|
|
269
|
+
static business(message, status = 400, details) {
|
|
270
|
+
return new ShipError(ErrorType.Business, message, status, details);
|
|
271
271
|
}
|
|
272
272
|
static network(message, details) {
|
|
273
273
|
return new ShipError(ErrorType.Network, message, undefined, details);
|
|
274
274
|
}
|
|
275
|
-
static cancelled(message) {
|
|
276
|
-
return new ShipError(ErrorType.Cancelled, message);
|
|
275
|
+
static cancelled(message, details) {
|
|
276
|
+
return new ShipError(ErrorType.Cancelled, message, undefined, details);
|
|
277
277
|
}
|
|
278
278
|
static file(message, details) {
|
|
279
279
|
return new ShipError(ErrorType.File, message, undefined, details);
|
|
@@ -281,8 +281,8 @@ export class ShipError extends Error {
|
|
|
281
281
|
static config(message, details) {
|
|
282
282
|
return new ShipError(ErrorType.Config, message, undefined, details);
|
|
283
283
|
}
|
|
284
|
-
static api(message, status = 500) {
|
|
285
|
-
return new ShipError(ErrorType.Api, message, status);
|
|
284
|
+
static api(message, status = 500, details) {
|
|
285
|
+
return new ShipError(ErrorType.Api, message, status, details);
|
|
286
286
|
}
|
|
287
287
|
// Semantic-category type guards. For specific-type checks, use
|
|
288
288
|
// `error.type === ErrorType.X` directly or the generic `isType(t)`.
|
|
@@ -661,3 +661,28 @@ export const PASSWORD_CONSTRAINTS = {
|
|
|
661
661
|
/** Maximum password length in characters */
|
|
662
662
|
MAX_LENGTH: 128,
|
|
663
663
|
};
|
|
664
|
+
/**
|
|
665
|
+
* Validate an optional deployment password and return it normalized.
|
|
666
|
+
*
|
|
667
|
+
* Absent (`undefined` / `null`) → returns `undefined`; an unprotected
|
|
668
|
+
* deployment is a valid choice. Present → must be a string within
|
|
669
|
+
* `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim —
|
|
670
|
+
* significant. Throws `ShipError.validation` on breach.
|
|
671
|
+
*
|
|
672
|
+
* Single source of truth shared by SDK (client-side validation, return
|
|
673
|
+
* ignored) and API (server-side enforcement, return threaded into config).
|
|
674
|
+
* Length is part of the wire-format contract; strength rules, if added later,
|
|
675
|
+
* stay server-side. See `CLAUDE.md` "Validation: format vs policy".
|
|
676
|
+
*/
|
|
677
|
+
export function validatePassword(value) {
|
|
678
|
+
if (value === undefined || value === null)
|
|
679
|
+
return undefined;
|
|
680
|
+
if (typeof value !== 'string') {
|
|
681
|
+
throw ShipError.validation('Password must be a string');
|
|
682
|
+
}
|
|
683
|
+
if (value.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
|
|
684
|
+
value.length > PASSWORD_CONSTRAINTS.MAX_LENGTH) {
|
|
685
|
+
throw ShipError.validation(`Password must be between ${PASSWORD_CONSTRAINTS.MIN_LENGTH} and ${PASSWORD_CONSTRAINTS.MAX_LENGTH} characters`);
|
|
686
|
+
}
|
|
687
|
+
return value;
|
|
688
|
+
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -574,8 +574,8 @@ export class ShipError extends Error {
|
|
|
574
574
|
return new ShipError(ErrorType.Forbidden, message, 403, details);
|
|
575
575
|
}
|
|
576
576
|
|
|
577
|
-
static rateLimit(message: string = "Too many requests"): ShipError {
|
|
578
|
-
return new ShipError(ErrorType.RateLimit, message, 429);
|
|
577
|
+
static rateLimit(message: string = "Too many requests", details?: unknown): ShipError {
|
|
578
|
+
return new ShipError(ErrorType.RateLimit, message, 429, details);
|
|
579
579
|
}
|
|
580
580
|
|
|
581
581
|
/**
|
|
@@ -595,16 +595,16 @@ export class ShipError extends Error {
|
|
|
595
595
|
return new ShipError(ErrorType.Authentication, message, 401, details);
|
|
596
596
|
}
|
|
597
597
|
|
|
598
|
-
static business(message: string, status: number = 400): ShipError {
|
|
599
|
-
return new ShipError(ErrorType.Business, message, status);
|
|
598
|
+
static business(message: string, status: number = 400, details?: unknown): ShipError {
|
|
599
|
+
return new ShipError(ErrorType.Business, message, status, details);
|
|
600
600
|
}
|
|
601
601
|
|
|
602
602
|
static network(message: string, details?: unknown): ShipError {
|
|
603
603
|
return new ShipError(ErrorType.Network, message, undefined, details);
|
|
604
604
|
}
|
|
605
605
|
|
|
606
|
-
static cancelled(message: string): ShipError {
|
|
607
|
-
return new ShipError(ErrorType.Cancelled, message);
|
|
606
|
+
static cancelled(message: string, details?: unknown): ShipError {
|
|
607
|
+
return new ShipError(ErrorType.Cancelled, message, undefined, details);
|
|
608
608
|
}
|
|
609
609
|
|
|
610
610
|
static file(message: string, details?: unknown): ShipError {
|
|
@@ -615,8 +615,8 @@ export class ShipError extends Error {
|
|
|
615
615
|
return new ShipError(ErrorType.Config, message, undefined, details);
|
|
616
616
|
}
|
|
617
617
|
|
|
618
|
-
static api(message: string, status: number = 500): ShipError {
|
|
619
|
-
return new ShipError(ErrorType.Api, message, status);
|
|
618
|
+
static api(message: string, status: number = 500, details?: unknown): ShipError {
|
|
619
|
+
return new ShipError(ErrorType.Api, message, status, details);
|
|
620
620
|
}
|
|
621
621
|
|
|
622
622
|
// Semantic-category type guards. For specific-type checks, use
|
|
@@ -1524,4 +1524,33 @@ export const PASSWORD_CONSTRAINTS = {
|
|
|
1524
1524
|
MIN_LENGTH: 6,
|
|
1525
1525
|
/** Maximum password length in characters */
|
|
1526
1526
|
MAX_LENGTH: 128,
|
|
1527
|
-
} as const;
|
|
1527
|
+
} as const;
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* Validate an optional deployment password and return it normalized.
|
|
1531
|
+
*
|
|
1532
|
+
* Absent (`undefined` / `null`) → returns `undefined`; an unprotected
|
|
1533
|
+
* deployment is a valid choice. Present → must be a string within
|
|
1534
|
+
* `PASSWORD_CONSTRAINTS` length bounds. Whitespace is preserved verbatim —
|
|
1535
|
+
* significant. Throws `ShipError.validation` on breach.
|
|
1536
|
+
*
|
|
1537
|
+
* Single source of truth shared by SDK (client-side validation, return
|
|
1538
|
+
* ignored) and API (server-side enforcement, return threaded into config).
|
|
1539
|
+
* Length is part of the wire-format contract; strength rules, if added later,
|
|
1540
|
+
* stay server-side. See `CLAUDE.md` "Validation: format vs policy".
|
|
1541
|
+
*/
|
|
1542
|
+
export function validatePassword(value: unknown): string | undefined {
|
|
1543
|
+
if (value === undefined || value === null) return undefined;
|
|
1544
|
+
if (typeof value !== 'string') {
|
|
1545
|
+
throw ShipError.validation('Password must be a string');
|
|
1546
|
+
}
|
|
1547
|
+
if (
|
|
1548
|
+
value.length < PASSWORD_CONSTRAINTS.MIN_LENGTH ||
|
|
1549
|
+
value.length > PASSWORD_CONSTRAINTS.MAX_LENGTH
|
|
1550
|
+
) {
|
|
1551
|
+
throw ShipError.validation(
|
|
1552
|
+
`Password must be between ${PASSWORD_CONSTRAINTS.MIN_LENGTH} and ${PASSWORD_CONSTRAINTS.MAX_LENGTH} characters`,
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
return value;
|
|
1556
|
+
}
|