@hashrytech/quick-components-kit 0.19.12 → 0.19.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/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/lib/api/client.ts
|
|
2
2
|
import { redirect } from "@sveltejs/kit";
|
|
3
|
-
import { getProblemDetail } from "./problem-details.js";
|
|
3
|
+
import { getProblemDetail, isProblemDetail } from "./problem-details.js";
|
|
4
4
|
import { browser } from "$app/environment";
|
|
5
5
|
/**
|
|
6
6
|
* Custom error class for API responses.
|
|
@@ -283,14 +283,13 @@ export class FetchClient {
|
|
|
283
283
|
const isApiError = error instanceof FetchError;
|
|
284
284
|
const status = isApiError ? error.status : 503; // Service Unavailable fallback
|
|
285
285
|
const message = error instanceof Error ? error.message : 'Unexpected error occurred';
|
|
286
|
-
const
|
|
287
|
-
await this.emit('onError',
|
|
288
|
-
|
|
289
|
-
this.evaluateRedirect(errorObj, status);
|
|
286
|
+
const problemError = isApiError && error.json && isProblemDetail(error.json) ? error.json : getProblemDetail({ status, title: "Server fetch error", type: "/exceptions/fetch-error/", detail: message });
|
|
287
|
+
await this.emit('onError', problemError);
|
|
288
|
+
this.evaluateRedirect(problemError, status);
|
|
290
289
|
return {
|
|
291
290
|
ok: false,
|
|
292
291
|
status,
|
|
293
|
-
error:
|
|
292
|
+
error: problemError
|
|
294
293
|
};
|
|
295
294
|
}
|
|
296
295
|
}
|
|
@@ -60,3 +60,22 @@ export declare function getProblemDetail(input: {
|
|
|
60
60
|
type?: string;
|
|
61
61
|
[key: string]: string | number | undefined;
|
|
62
62
|
}): ProblemDetail;
|
|
63
|
+
/**
|
|
64
|
+
* Type guard for RFC 7807 "Problem Details" objects.
|
|
65
|
+
*
|
|
66
|
+
* Why:
|
|
67
|
+
* - Network errors and server responses can be `unknown` at the callsite.
|
|
68
|
+
* - This guard lets TypeScript safely narrow `unknown` to `ProblemDetail`
|
|
69
|
+
* so you can access `title`, `status`, etc. without extra checks.
|
|
70
|
+
*
|
|
71
|
+
* Contract (RFC 7807):
|
|
72
|
+
* - `title`: human-readable summary (required string)
|
|
73
|
+
* - `status`: HTTP status code (required number)
|
|
74
|
+
* - `type`, `detail`, `instance`: optional strings
|
|
75
|
+
* - Implementations may include arbitrary extension members (we allow them).
|
|
76
|
+
*
|
|
77
|
+
* Note:
|
|
78
|
+
* - Some backends serialize `status` as a string. If that happens in your stack,
|
|
79
|
+
* consider accepting `"number-like"` values or coercing before validation.
|
|
80
|
+
*/
|
|
81
|
+
export declare function isProblemDetail(v: unknown): v is ProblemDetail;
|
|
@@ -78,3 +78,36 @@ export function getProblemDetail(input) {
|
|
|
78
78
|
}
|
|
79
79
|
return problem;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Type guard for RFC 7807 "Problem Details" objects.
|
|
83
|
+
*
|
|
84
|
+
* Why:
|
|
85
|
+
* - Network errors and server responses can be `unknown` at the callsite.
|
|
86
|
+
* - This guard lets TypeScript safely narrow `unknown` to `ProblemDetail`
|
|
87
|
+
* so you can access `title`, `status`, etc. without extra checks.
|
|
88
|
+
*
|
|
89
|
+
* Contract (RFC 7807):
|
|
90
|
+
* - `title`: human-readable summary (required string)
|
|
91
|
+
* - `status`: HTTP status code (required number)
|
|
92
|
+
* - `type`, `detail`, `instance`: optional strings
|
|
93
|
+
* - Implementations may include arbitrary extension members (we allow them).
|
|
94
|
+
*
|
|
95
|
+
* Note:
|
|
96
|
+
* - Some backends serialize `status` as a string. If that happens in your stack,
|
|
97
|
+
* consider accepting `"number-like"` values or coercing before validation.
|
|
98
|
+
*/
|
|
99
|
+
export function isProblemDetail(v) {
|
|
100
|
+
// Must be a non-null object
|
|
101
|
+
if (!v || typeof v !== 'object')
|
|
102
|
+
return false;
|
|
103
|
+
// Treat as a generic dictionary to inspect fields at runtime
|
|
104
|
+
const o = v;
|
|
105
|
+
// Required members with exact types
|
|
106
|
+
const hasTitle = typeof o.title === 'string';
|
|
107
|
+
const hasStatus = typeof o.status === 'number';
|
|
108
|
+
// Optional RFC 7807 members (if present, must be strings)
|
|
109
|
+
const typeOk = o.type === undefined || typeof o.type === 'string';
|
|
110
|
+
const detailOk = o.detail === undefined || typeof o.detail === 'string';
|
|
111
|
+
const instanceOk = o.instance === undefined || typeof o.instance === 'string';
|
|
112
|
+
return hasTitle && hasStatus && typeOk && detailOk && instanceOk;
|
|
113
|
+
}
|