@shipstatic/types 0.9.5 → 0.9.6
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 +4 -1
- package/dist/index.d.ts +8 -9
- package/dist/index.js +15 -25
- package/package.json +1 -1
- package/src/index.ts +15 -29
package/README.md
CHANGED
|
@@ -43,7 +43,8 @@ if (isShipError(error)) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
if (error.isClientError()) { /* Business | Config | File | Validation */ }
|
|
46
|
-
if (error.isAuthError())
|
|
46
|
+
if (error.isAuthError()) { /* handle auth */ }
|
|
47
|
+
if (error.type === ErrorType.Validation) { /* specific-type checks */ }
|
|
47
48
|
```
|
|
48
49
|
|
|
49
50
|
**HTTP client integration.** Both producer and consumer sides of the wire have first-class helpers, so every HTTP client across the platform reconstructs the same `ShipError` shape:
|
|
@@ -54,6 +55,8 @@ return c.json(error.toResponse(), error.status ?? 500);
|
|
|
54
55
|
|
|
55
56
|
// Consumer side — two symmetric helpers cover both HTTP error modes:
|
|
56
57
|
|
|
58
|
+
// Both helpers take an optional operationName for context-aware fallback messages.
|
|
59
|
+
|
|
57
60
|
// 1. Server returned a non-OK response
|
|
58
61
|
if (!response.ok) {
|
|
59
62
|
throw await ShipError.fromHttpResponse(response, 'Get account');
|
package/dist/index.d.ts
CHANGED
|
@@ -354,8 +354,8 @@ export declare class ShipError extends Error {
|
|
|
354
354
|
* Construct a `ShipError` from an HTTP error response.
|
|
355
355
|
*
|
|
356
356
|
* Best-effort body parse for `{ message, error?, details? }`. Message
|
|
357
|
-
* resolution: `body.message` → `body.error` → `
|
|
358
|
-
*
|
|
357
|
+
* resolution: `body.message` → `body.error` → `"<operationName> failed with
|
|
358
|
+
* status <N>"`.
|
|
359
359
|
*
|
|
360
360
|
* Type resolution: trusts `body.error` when it's a known `ErrorType`
|
|
361
361
|
* (preserves the wire's intent — server's `ShipError.validation(...)`
|
|
@@ -363,10 +363,13 @@ export declare class ShipError extends Error {
|
|
|
363
363
|
* status-derived (401 → Authentication, 429 → RateLimit, else → Api) for
|
|
364
364
|
* non-API responses (CDN errors, intermediaries) or malformed bodies.
|
|
365
365
|
*
|
|
366
|
+
* `operationName` (e.g. `"Get account"`) is used to compose the fallback
|
|
367
|
+
* message. Defaults to `"Request"`. Same convention as `fromFetchError`.
|
|
368
|
+
*
|
|
366
369
|
* Async because it reads the response body. Returns rather than throws so
|
|
367
370
|
* callers can compose; most will `throw await ShipError.fromHttpResponse(...)`.
|
|
368
371
|
*/
|
|
369
|
-
static fromHttpResponse(response: Response,
|
|
372
|
+
static fromHttpResponse(response: Response, operationName?: string): Promise<ShipError>;
|
|
370
373
|
/**
|
|
371
374
|
* Construct a `ShipError` from an error caught around a `fetch()` call.
|
|
372
375
|
*
|
|
@@ -391,18 +394,14 @@ export declare class ShipError extends Error {
|
|
|
391
394
|
static rateLimit(message?: string): ShipError;
|
|
392
395
|
static authentication(message?: string, details?: any): ShipError;
|
|
393
396
|
static business(message: string, status?: number): ShipError;
|
|
394
|
-
static network(message: string,
|
|
397
|
+
static network(message: string, details?: any): ShipError;
|
|
395
398
|
static cancelled(message: string): ShipError;
|
|
396
|
-
static file(message: string,
|
|
399
|
+
static file(message: string, details?: any): ShipError;
|
|
397
400
|
static config(message: string, details?: any): ShipError;
|
|
398
401
|
static api(message: string, status?: number): ShipError;
|
|
399
|
-
get filePath(): string | undefined;
|
|
400
402
|
isClientError(): boolean;
|
|
401
403
|
isNetworkError(): boolean;
|
|
402
404
|
isAuthError(): boolean;
|
|
403
|
-
isValidationError(): boolean;
|
|
404
|
-
isFileError(): boolean;
|
|
405
|
-
isConfigError(): boolean;
|
|
406
405
|
isType(errorType: ErrorType): boolean;
|
|
407
406
|
}
|
|
408
407
|
/**
|
package/dist/index.js
CHANGED
|
@@ -132,8 +132,8 @@ export class ShipError extends Error {
|
|
|
132
132
|
* Construct a `ShipError` from an HTTP error response.
|
|
133
133
|
*
|
|
134
134
|
* Best-effort body parse for `{ message, error?, details? }`. Message
|
|
135
|
-
* resolution: `body.message` → `body.error` → `
|
|
136
|
-
*
|
|
135
|
+
* resolution: `body.message` → `body.error` → `"<operationName> failed with
|
|
136
|
+
* status <N>"`.
|
|
137
137
|
*
|
|
138
138
|
* Type resolution: trusts `body.error` when it's a known `ErrorType`
|
|
139
139
|
* (preserves the wire's intent — server's `ShipError.validation(...)`
|
|
@@ -141,10 +141,13 @@ export class ShipError extends Error {
|
|
|
141
141
|
* status-derived (401 → Authentication, 429 → RateLimit, else → Api) for
|
|
142
142
|
* non-API responses (CDN errors, intermediaries) or malformed bodies.
|
|
143
143
|
*
|
|
144
|
+
* `operationName` (e.g. `"Get account"`) is used to compose the fallback
|
|
145
|
+
* message. Defaults to `"Request"`. Same convention as `fromFetchError`.
|
|
146
|
+
*
|
|
144
147
|
* Async because it reads the response body. Returns rather than throws so
|
|
145
148
|
* callers can compose; most will `throw await ShipError.fromHttpResponse(...)`.
|
|
146
149
|
*/
|
|
147
|
-
static async fromHttpResponse(response,
|
|
150
|
+
static async fromHttpResponse(response, operationName) {
|
|
148
151
|
let message;
|
|
149
152
|
let details;
|
|
150
153
|
let bodyType;
|
|
@@ -171,9 +174,9 @@ export class ShipError extends Error {
|
|
|
171
174
|
}
|
|
172
175
|
}
|
|
173
176
|
catch {
|
|
174
|
-
// Body unreadable; fall through to
|
|
177
|
+
// Body unreadable; fall through to operationName-derived message.
|
|
175
178
|
}
|
|
176
|
-
message = message ||
|
|
179
|
+
message = message || `${operationName || 'Request'} failed with status ${response.status}`;
|
|
177
180
|
const type = bodyType ?? (response.status === 401 ? ErrorType.Authentication :
|
|
178
181
|
response.status === 429 ? ErrorType.RateLimit :
|
|
179
182
|
ErrorType.Api);
|
|
@@ -206,7 +209,7 @@ export class ShipError extends Error {
|
|
|
206
209
|
return ShipError.cancelled(`${op} was cancelled`);
|
|
207
210
|
}
|
|
208
211
|
if (cause instanceof TypeError && cause.message.includes('fetch')) {
|
|
209
|
-
return ShipError.network(`${op} failed: ${cause.message}`, cause);
|
|
212
|
+
return ShipError.network(`${op} failed: ${cause.message}`, { cause });
|
|
210
213
|
}
|
|
211
214
|
return new ShipError(ErrorType.Api, `${op} failed: ${cause.message}`);
|
|
212
215
|
}
|
|
@@ -229,14 +232,14 @@ export class ShipError extends Error {
|
|
|
229
232
|
static business(message, status = 400) {
|
|
230
233
|
return new ShipError(ErrorType.Business, message, status);
|
|
231
234
|
}
|
|
232
|
-
static network(message,
|
|
233
|
-
return new ShipError(ErrorType.Network, message, undefined,
|
|
235
|
+
static network(message, details) {
|
|
236
|
+
return new ShipError(ErrorType.Network, message, undefined, details);
|
|
234
237
|
}
|
|
235
238
|
static cancelled(message) {
|
|
236
239
|
return new ShipError(ErrorType.Cancelled, message);
|
|
237
240
|
}
|
|
238
|
-
static file(message,
|
|
239
|
-
return new ShipError(ErrorType.File, message, undefined,
|
|
241
|
+
static file(message, details) {
|
|
242
|
+
return new ShipError(ErrorType.File, message, undefined, details);
|
|
240
243
|
}
|
|
241
244
|
static config(message, details) {
|
|
242
245
|
return new ShipError(ErrorType.Config, message, undefined, details);
|
|
@@ -244,11 +247,8 @@ export class ShipError extends Error {
|
|
|
244
247
|
static api(message, status = 500) {
|
|
245
248
|
return new ShipError(ErrorType.Api, message, status);
|
|
246
249
|
}
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
return this.details?.filePath;
|
|
250
|
-
}
|
|
251
|
-
// Helper methods for error type checking using categorization
|
|
250
|
+
// Semantic-category type guards. For specific-type checks, use
|
|
251
|
+
// `error.type === ErrorType.X` directly or the generic `isType(t)`.
|
|
252
252
|
isClientError() {
|
|
253
253
|
return ERROR_CATEGORIES.client.has(this.type);
|
|
254
254
|
}
|
|
@@ -258,16 +258,6 @@ export class ShipError extends Error {
|
|
|
258
258
|
isAuthError() {
|
|
259
259
|
return ERROR_CATEGORIES.auth.has(this.type);
|
|
260
260
|
}
|
|
261
|
-
isValidationError() {
|
|
262
|
-
return this.type === ErrorType.Validation;
|
|
263
|
-
}
|
|
264
|
-
isFileError() {
|
|
265
|
-
return this.type === ErrorType.File;
|
|
266
|
-
}
|
|
267
|
-
isConfigError() {
|
|
268
|
-
return this.type === ErrorType.Config;
|
|
269
|
-
}
|
|
270
|
-
// Generic type checker
|
|
271
261
|
isType(errorType) {
|
|
272
262
|
return this.type === errorType;
|
|
273
263
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -448,8 +448,8 @@ export class ShipError extends Error {
|
|
|
448
448
|
* Construct a `ShipError` from an HTTP error response.
|
|
449
449
|
*
|
|
450
450
|
* Best-effort body parse for `{ message, error?, details? }`. Message
|
|
451
|
-
* resolution: `body.message` → `body.error` → `
|
|
452
|
-
*
|
|
451
|
+
* resolution: `body.message` → `body.error` → `"<operationName> failed with
|
|
452
|
+
* status <N>"`.
|
|
453
453
|
*
|
|
454
454
|
* Type resolution: trusts `body.error` when it's a known `ErrorType`
|
|
455
455
|
* (preserves the wire's intent — server's `ShipError.validation(...)`
|
|
@@ -457,12 +457,15 @@ export class ShipError extends Error {
|
|
|
457
457
|
* status-derived (401 → Authentication, 429 → RateLimit, else → Api) for
|
|
458
458
|
* non-API responses (CDN errors, intermediaries) or malformed bodies.
|
|
459
459
|
*
|
|
460
|
+
* `operationName` (e.g. `"Get account"`) is used to compose the fallback
|
|
461
|
+
* message. Defaults to `"Request"`. Same convention as `fromFetchError`.
|
|
462
|
+
*
|
|
460
463
|
* Async because it reads the response body. Returns rather than throws so
|
|
461
464
|
* callers can compose; most will `throw await ShipError.fromHttpResponse(...)`.
|
|
462
465
|
*/
|
|
463
466
|
static async fromHttpResponse(
|
|
464
467
|
response: Response,
|
|
465
|
-
|
|
468
|
+
operationName?: string,
|
|
466
469
|
): Promise<ShipError> {
|
|
467
470
|
let message: string | undefined;
|
|
468
471
|
let details: unknown;
|
|
@@ -486,10 +489,10 @@ export class ShipError extends Error {
|
|
|
486
489
|
if (text) message = text;
|
|
487
490
|
}
|
|
488
491
|
} catch {
|
|
489
|
-
// Body unreadable; fall through to
|
|
492
|
+
// Body unreadable; fall through to operationName-derived message.
|
|
490
493
|
}
|
|
491
494
|
|
|
492
|
-
message = message ||
|
|
495
|
+
message = message || `${operationName || 'Request'} failed with status ${response.status}`;
|
|
493
496
|
|
|
494
497
|
const type = bodyType ?? (
|
|
495
498
|
response.status === 401 ? ErrorType.Authentication :
|
|
@@ -528,7 +531,7 @@ export class ShipError extends Error {
|
|
|
528
531
|
return ShipError.cancelled(`${op} was cancelled`);
|
|
529
532
|
}
|
|
530
533
|
if (cause instanceof TypeError && cause.message.includes('fetch')) {
|
|
531
|
-
return ShipError.network(`${op} failed: ${cause.message}`, cause);
|
|
534
|
+
return ShipError.network(`${op} failed: ${cause.message}`, { cause });
|
|
532
535
|
}
|
|
533
536
|
return new ShipError(ErrorType.Api, `${op} failed: ${cause.message}`);
|
|
534
537
|
}
|
|
@@ -558,16 +561,16 @@ export class ShipError extends Error {
|
|
|
558
561
|
return new ShipError(ErrorType.Business, message, status);
|
|
559
562
|
}
|
|
560
563
|
|
|
561
|
-
static network(message: string,
|
|
562
|
-
return new ShipError(ErrorType.Network, message, undefined,
|
|
564
|
+
static network(message: string, details?: any): ShipError {
|
|
565
|
+
return new ShipError(ErrorType.Network, message, undefined, details);
|
|
563
566
|
}
|
|
564
567
|
|
|
565
568
|
static cancelled(message: string): ShipError {
|
|
566
569
|
return new ShipError(ErrorType.Cancelled, message);
|
|
567
570
|
}
|
|
568
571
|
|
|
569
|
-
static file(message: string,
|
|
570
|
-
return new ShipError(ErrorType.File, message, undefined,
|
|
572
|
+
static file(message: string, details?: any): ShipError {
|
|
573
|
+
return new ShipError(ErrorType.File, message, undefined, details);
|
|
571
574
|
}
|
|
572
575
|
|
|
573
576
|
static config(message: string, details?: any): ShipError {
|
|
@@ -578,12 +581,8 @@ export class ShipError extends Error {
|
|
|
578
581
|
return new ShipError(ErrorType.Api, message, status);
|
|
579
582
|
}
|
|
580
583
|
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
return this.details?.filePath;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// Helper methods for error type checking using categorization
|
|
584
|
+
// Semantic-category type guards. For specific-type checks, use
|
|
585
|
+
// `error.type === ErrorType.X` directly or the generic `isType(t)`.
|
|
587
586
|
isClientError(): boolean {
|
|
588
587
|
return ERROR_CATEGORIES.client.has(this.type);
|
|
589
588
|
}
|
|
@@ -596,19 +595,6 @@ export class ShipError extends Error {
|
|
|
596
595
|
return ERROR_CATEGORIES.auth.has(this.type);
|
|
597
596
|
}
|
|
598
597
|
|
|
599
|
-
isValidationError(): boolean {
|
|
600
|
-
return this.type === ErrorType.Validation;
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
isFileError(): boolean {
|
|
604
|
-
return this.type === ErrorType.File;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
isConfigError(): boolean {
|
|
608
|
-
return this.type === ErrorType.Config;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Generic type checker
|
|
612
598
|
isType(errorType: ErrorType): boolean {
|
|
613
599
|
return this.type === errorType;
|
|
614
600
|
}
|