@velajs/storage 0.3.0 → 0.3.1
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.
|
@@ -58,7 +58,10 @@ function toError(status, code, message, key) {
|
|
|
58
58
|
const retryable = mapped === 'Provider' || mapped === 'RateLimited' || mapped === 'Timeout' || mapped === 'Network';
|
|
59
59
|
return new StorageError(mapped, message ?? code ?? `S3 error${key ? ` (${key})` : ''}`, {
|
|
60
60
|
status: status >= 400 ? status : undefined,
|
|
61
|
-
retryable
|
|
61
|
+
retryable,
|
|
62
|
+
// `message`/`code` are the provider's own <Message>/<Code> — never client-safe,
|
|
63
|
+
// even on a 4xx status (e.g. AccessDenied/NoSuchKey text can carry internal detail).
|
|
64
|
+
internal: true
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
67
|
async function s3Error(res, key) {
|
|
@@ -47,10 +47,16 @@ import { clampExpiry, dispositionHeader, mapError, parseRange, serializeStored }
|
|
|
47
47
|
fail(c, e) {
|
|
48
48
|
const err = e instanceof StorageError ? e : StorageError.wrap(e);
|
|
49
49
|
const { wire, status } = mapError(err.code);
|
|
50
|
+
// Never echo a provider/transport/wrapped message to the client: those are
|
|
51
|
+
// flagged `internal` (driver <Message>/<Code>, StorageError.wrap, fromStatus)
|
|
52
|
+
// and can carry host/bucket/credential detail — including on a 4xx status.
|
|
53
|
+
// Redact internal errors at any status, plus all upstream (5xx) responses;
|
|
54
|
+
// 4xx codes with an author-vouched message echo it.
|
|
55
|
+
const message = err.internal || status >= 500 ? 'storage backend error' : err.message;
|
|
50
56
|
return c.json({
|
|
51
57
|
error: {
|
|
52
58
|
code: wire,
|
|
53
|
-
message
|
|
59
|
+
message
|
|
54
60
|
}
|
|
55
61
|
}, status);
|
|
56
62
|
}
|
package/dist/storage.error.d.ts
CHANGED
|
@@ -12,12 +12,22 @@ export interface StorageErrorOptions {
|
|
|
12
12
|
status?: number;
|
|
13
13
|
/** Override the default retryability implied by {@link StorageErrorCode}. */
|
|
14
14
|
retryable?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* True when `message` came from a provider/transport/wrapped source rather
|
|
17
|
+
* than being authored as client-safe text. The HTTP controller redacts such
|
|
18
|
+
* messages so raw provider detail never reaches a client. Default false —
|
|
19
|
+
* a bare `new StorageError(code, msg)` is the author's vouch that `msg` is
|
|
20
|
+
* client-safe; driver/wrap code MUST set this when echoing provider text.
|
|
21
|
+
*/
|
|
22
|
+
internal?: boolean;
|
|
15
23
|
}
|
|
16
24
|
export declare class StorageError extends Error {
|
|
17
25
|
name: string;
|
|
18
26
|
readonly code: StorageErrorCode;
|
|
19
27
|
readonly retryable: boolean;
|
|
20
28
|
readonly status: number | undefined;
|
|
29
|
+
/** Whether `message` is non-client-safe (provider/transport/wrapped origin). */
|
|
30
|
+
readonly internal: boolean;
|
|
21
31
|
constructor(code: StorageErrorCode, message: string, options?: StorageErrorOptions);
|
|
22
32
|
/** Wrap an arbitrary thrown value as a `StorageError` (idempotent). */
|
|
23
33
|
static wrap(e: unknown): StorageError;
|
package/dist/storage.error.js
CHANGED
|
@@ -15,6 +15,7 @@ export class StorageError extends Error {
|
|
|
15
15
|
code;
|
|
16
16
|
retryable;
|
|
17
17
|
status;
|
|
18
|
+
/** Whether `message` is non-client-safe (provider/transport/wrapped origin). */ internal;
|
|
18
19
|
constructor(code, message, options){
|
|
19
20
|
super(message, options?.cause !== undefined ? {
|
|
20
21
|
cause: options.cause
|
|
@@ -22,14 +23,17 @@ export class StorageError extends Error {
|
|
|
22
23
|
this.code = code;
|
|
23
24
|
this.status = options?.status;
|
|
24
25
|
this.retryable = options?.retryable ?? RETRYABLE.has(code);
|
|
26
|
+
this.internal = options?.internal ?? false;
|
|
25
27
|
}
|
|
26
28
|
/** Wrap an arbitrary thrown value as a `StorageError` (idempotent). */ static wrap(e) {
|
|
27
29
|
if (e instanceof StorageError) return e;
|
|
28
30
|
if (isAbort(e)) return new StorageError('Aborted', 'operation aborted', {
|
|
29
31
|
cause: e
|
|
30
32
|
});
|
|
33
|
+
// The wrapped message is arbitrary provider/host text — never client-safe.
|
|
31
34
|
return new StorageError('Provider', e instanceof Error ? e.message : String(e), {
|
|
32
|
-
cause: e
|
|
35
|
+
cause: e,
|
|
36
|
+
internal: true
|
|
33
37
|
});
|
|
34
38
|
}
|
|
35
39
|
/** Map a transport status code to a `StorageError` (5xx/429 retryable). */ static fromStatus(status, message, cause) {
|
|
@@ -37,7 +41,9 @@ export class StorageError extends Error {
|
|
|
37
41
|
return new StorageError(code, message, {
|
|
38
42
|
status,
|
|
39
43
|
cause,
|
|
40
|
-
retryable: status === 429 || status >= 500
|
|
44
|
+
retryable: status === 429 || status >= 500,
|
|
45
|
+
// Message came off a transport response — treat as non-client-safe.
|
|
46
|
+
internal: true
|
|
41
47
|
});
|
|
42
48
|
}
|
|
43
49
|
}
|