@velajs/storage 0.3.0 → 0.3.2
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 +6 -1
- package/dist/body-BMUcBeQ0.js +93 -0
- package/dist/body-BMUcBeQ0.js.map +1 -0
- package/dist/client/index.d.ts +49 -46
- package/dist/client/index.js +207 -228
- package/dist/client/index.js.map +1 -0
- package/dist/drivers/memory/index.d.ts +17 -13
- package/dist/drivers/memory/index.js +190 -197
- package/dist/drivers/memory/index.js.map +1 -0
- package/dist/drivers/r2/index.d.ts +7 -4
- package/dist/drivers/r2/index.js +162 -160
- package/dist/drivers/r2/index.js.map +1 -0
- package/dist/drivers/r2-http/index.d.ts +23 -19
- package/dist/drivers/r2-http/index.js +52 -45
- package/dist/drivers/r2-http/index.js.map +1 -0
- package/dist/drivers/s3/index.d.ts +79 -5
- package/dist/drivers/s3/index.js +2 -3
- package/dist/index.d.ts +271 -17
- package/dist/index.js +1078 -16
- package/dist/index.js.map +1 -0
- package/dist/middleware/index.d.ts +177 -15
- package/dist/middleware/index.js +553 -8
- package/dist/middleware/index.js.map +1 -0
- package/dist/protocol.types-C5PPBD12.d.ts +80 -0
- package/dist/r2.types-Bw4Ft83t.d.ts +71 -0
- package/dist/retry-DXtO6R9D.js +119 -0
- package/dist/retry-DXtO6R9D.js.map +1 -0
- package/dist/s3-DrE9NrnD.js +557 -0
- package/dist/s3-DrE9NrnD.js.map +1 -0
- package/dist/storage.error-DVCOkJhc.js +49 -0
- package/dist/storage.error-DVCOkJhc.js.map +1 -0
- package/dist/storage.types-BJN7Yp1J.d.ts +288 -0
- package/dist/storagesdk/index.d.ts +73 -69
- package/dist/storagesdk/index.js +117 -130
- package/dist/storagesdk/index.js.map +1 -0
- package/dist/stored-file-2Yl07eRc.js +105 -0
- package/dist/stored-file-2Yl07eRc.js.map +1 -0
- package/dist/testing/index.d.ts +12 -8
- package/dist/testing/index.js +36 -53
- package/dist/testing/index.js.map +1 -0
- package/package.json +62 -48
- package/dist/base64.d.ts +0 -8
- package/dist/base64.js +0 -25
- package/dist/decorators/inject-storage.decorator.d.ts +0 -17
- package/dist/decorators/inject-storage.decorator.js +0 -21
- package/dist/drivers/r2/r2.types.d.ts +0 -67
- package/dist/drivers/r2/r2.types.js +0 -5
- package/dist/drivers/s3/s3-client.d.ts +0 -33
- package/dist/drivers/s3/s3-client.js +0 -154
- package/dist/drivers/s3/s3.driver.d.ts +0 -4
- package/dist/drivers/s3/s3.driver.js +0 -404
- package/dist/drivers/s3/s3.types.d.ts +0 -28
- package/dist/drivers/s3/s3.types.js +0 -1
- package/dist/drivers/s3/xml.d.ts +0 -6
- package/dist/drivers/s3/xml.js +0 -52
- package/dist/http/authorizer.types.d.ts +0 -59
- package/dist/http/authorizer.types.js +0 -1
- package/dist/http/http-helpers.d.ts +0 -22
- package/dist/http/http-helpers.js +0 -80
- package/dist/http/protocol.types.d.ts +0 -76
- package/dist/http/protocol.types.js +0 -1
- package/dist/internal/body.d.ts +0 -18
- package/dist/internal/body.js +0 -90
- package/dist/internal/retry.d.ts +0 -41
- package/dist/internal/retry.js +0 -127
- package/dist/internal/stored-file.d.ts +0 -27
- package/dist/internal/stored-file.js +0 -114
- package/dist/middleware/cache.d.ts +0 -50
- package/dist/middleware/cache.js +0 -101
- package/dist/middleware/compose.d.ts +0 -12
- package/dist/middleware/compose.js +0 -11
- package/dist/middleware/compression.d.ts +0 -16
- package/dist/middleware/compression.js +0 -101
- package/dist/middleware/encryption.d.ts +0 -14
- package/dist/middleware/encryption.js +0 -134
- package/dist/middleware/failover.d.ts +0 -18
- package/dist/middleware/failover.js +0 -52
- package/dist/middleware/retry.d.ts +0 -14
- package/dist/middleware/retry.js +0 -47
- package/dist/middleware/versioning.d.ts +0 -36
- package/dist/middleware/versioning.js +0 -89
- package/dist/middleware/wrap.d.ts +0 -11
- package/dist/middleware/wrap.js +0 -46
- package/dist/object-key.d.ts +0 -17
- package/dist/object-key.js +0 -42
- package/dist/storage.controller.d.ts +0 -21
- package/dist/storage.controller.js +0 -380
- package/dist/storage.error.d.ts +0 -28
- package/dist/storage.error.js +0 -46
- package/dist/storage.facade.d.ts +0 -47
- package/dist/storage.facade.js +0 -443
- package/dist/storage.module.d.ts +0 -46
- package/dist/storage.module.js +0 -113
- package/dist/storage.service.d.ts +0 -42
- package/dist/storage.service.js +0 -86
- package/dist/storage.tokens.d.ts +0 -13
- package/dist/storage.tokens.js +0 -26
- package/dist/storage.types.d.ts +0 -245
- package/dist/storage.types.js +0 -1
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type Token, type Type } from '@velajs/vela';
|
|
2
|
-
import type { StorageService } from './storage.service';
|
|
3
|
-
import type { StorageAuthorizer } from './http/authorizer.types';
|
|
4
|
-
export interface ResolvedHttpOptions {
|
|
5
|
-
driverName: string;
|
|
6
|
-
authorize?: StorageAuthorizer;
|
|
7
|
-
defaultPolicy: 'deny' | 'allow';
|
|
8
|
-
download: 'redirect' | 'proxy';
|
|
9
|
-
defaultExpiresIn: number;
|
|
10
|
-
maxExpiresIn: number;
|
|
11
|
-
maxUploadSize?: number;
|
|
12
|
-
maxListLimit: number;
|
|
13
|
-
deleteConcurrency: number;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Build a vela controller exposing presigned/multipart upload + download
|
|
17
|
-
* endpoints for one bucket. Factory-decorated (like better-auth's catch-all)
|
|
18
|
-
* so `basePath` bakes in at decoration time. Consumes the {@link StorageService}
|
|
19
|
-
* facade so gating/retry/prefix apply uniformly on the HTTP path.
|
|
20
|
-
*/
|
|
21
|
-
export declare function createStorageController(basePath: string, serviceToken: Token<StorageService>, http: ResolvedHttpOptions): Type;
|
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
}
|
|
7
|
-
function _ts_metadata(k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
}
|
|
10
|
-
function _ts_param(paramIndex, decorator) {
|
|
11
|
-
return function(target, key) {
|
|
12
|
-
decorator(target, key, paramIndex);
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
import { Controller, Get, Inject, Injectable, Post, Req } from "@velajs/vela";
|
|
16
|
-
import { sanitizeKey } from "./object-key.js";
|
|
17
|
-
import { StorageError } from "./storage.error.js";
|
|
18
|
-
import { clampExpiry, dispositionHeader, mapError, parseRange, serializeStored } from "./http/http-helpers.js";
|
|
19
|
-
/**
|
|
20
|
-
* Build a vela controller exposing presigned/multipart upload + download
|
|
21
|
-
* endpoints for one bucket. Factory-decorated (like better-auth's catch-all)
|
|
22
|
-
* so `basePath` bakes in at decoration time. Consumes the {@link StorageService}
|
|
23
|
-
* facade so gating/retry/prefix apply uniformly on the HTTP path.
|
|
24
|
-
*/ export function createStorageController(basePath, serviceToken, http) {
|
|
25
|
-
let StorageController = class StorageController {
|
|
26
|
-
svc;
|
|
27
|
-
constructor(svc){
|
|
28
|
-
this.svc = svc;
|
|
29
|
-
}
|
|
30
|
-
get storage() {
|
|
31
|
-
return this.svc.storage;
|
|
32
|
-
}
|
|
33
|
-
async authorize(c, action) {
|
|
34
|
-
if (!http.authorize) {
|
|
35
|
-
if (http.defaultPolicy === 'allow') return {};
|
|
36
|
-
throw new StorageError('AccessDenied', 'storage: no authorizer configured (default deny)');
|
|
37
|
-
}
|
|
38
|
-
const res = await http.authorize(action, {
|
|
39
|
-
req: c.req.raw,
|
|
40
|
-
ctx: c,
|
|
41
|
-
driver: http.driverName
|
|
42
|
-
});
|
|
43
|
-
if (res === false) throw new StorageError('AccessDenied', 'not allowed');
|
|
44
|
-
if (res === true) return {};
|
|
45
|
-
return res;
|
|
46
|
-
}
|
|
47
|
-
fail(c, e) {
|
|
48
|
-
const err = e instanceof StorageError ? e : StorageError.wrap(e);
|
|
49
|
-
const { wire, status } = mapError(err.code);
|
|
50
|
-
return c.json({
|
|
51
|
-
error: {
|
|
52
|
-
code: wire,
|
|
53
|
-
message: err.message
|
|
54
|
-
}
|
|
55
|
-
}, status);
|
|
56
|
-
}
|
|
57
|
-
async signUpload(c) {
|
|
58
|
-
try {
|
|
59
|
-
const b = await c.req.json();
|
|
60
|
-
const ov = await this.authorize(c, {
|
|
61
|
-
type: 'sign-upload',
|
|
62
|
-
key: b.key,
|
|
63
|
-
contentType: b.contentType,
|
|
64
|
-
size: b.size
|
|
65
|
-
});
|
|
66
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
67
|
-
const upload = await this.storage.signedUploadUrl(key, {
|
|
68
|
-
expiresIn: clampExpiry(ov.expiresIn ?? b.expiresIn, http.defaultExpiresIn, http.maxExpiresIn),
|
|
69
|
-
contentType: b.contentType,
|
|
70
|
-
maxSize: ov.maxSize ?? http.maxUploadSize
|
|
71
|
-
});
|
|
72
|
-
return c.json({
|
|
73
|
-
key,
|
|
74
|
-
upload
|
|
75
|
-
});
|
|
76
|
-
} catch (e) {
|
|
77
|
-
return this.fail(c, e);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
async multipartCreate(c) {
|
|
81
|
-
try {
|
|
82
|
-
const b = await c.req.json();
|
|
83
|
-
const ov = await this.authorize(c, {
|
|
84
|
-
type: 'multipart-create',
|
|
85
|
-
key: b.key,
|
|
86
|
-
contentType: b.contentType
|
|
87
|
-
});
|
|
88
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
89
|
-
const sm = this.storage.signedMultipart;
|
|
90
|
-
if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');
|
|
91
|
-
const created = await sm.create(key, {
|
|
92
|
-
contentType: b.contentType,
|
|
93
|
-
metadata: ov.metadata ?? b.metadata,
|
|
94
|
-
partSize: b.partSize
|
|
95
|
-
});
|
|
96
|
-
return c.json({
|
|
97
|
-
key,
|
|
98
|
-
uploadId: created.uploadId,
|
|
99
|
-
partSize: created.partSize
|
|
100
|
-
});
|
|
101
|
-
} catch (e) {
|
|
102
|
-
return this.fail(c, e);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async multipartSignPart(c) {
|
|
106
|
-
try {
|
|
107
|
-
const b = await c.req.json();
|
|
108
|
-
const ov = await this.authorize(c, {
|
|
109
|
-
type: 'multipart-sign-part',
|
|
110
|
-
key: b.key,
|
|
111
|
-
uploadId: b.uploadId,
|
|
112
|
-
partNumber: b.partNumber
|
|
113
|
-
});
|
|
114
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
115
|
-
const sm = this.storage.signedMultipart;
|
|
116
|
-
if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');
|
|
117
|
-
const part = await sm.signPart(key, b.uploadId, b.partNumber, {
|
|
118
|
-
expiresIn: clampExpiry(ov.expiresIn, http.defaultExpiresIn, http.maxExpiresIn)
|
|
119
|
-
});
|
|
120
|
-
return c.json({
|
|
121
|
-
partNumber: b.partNumber,
|
|
122
|
-
method: 'PUT',
|
|
123
|
-
url: part.url,
|
|
124
|
-
headers: part.headers
|
|
125
|
-
});
|
|
126
|
-
} catch (e) {
|
|
127
|
-
return this.fail(c, e);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async multipartComplete(c) {
|
|
131
|
-
try {
|
|
132
|
-
const b = await c.req.json();
|
|
133
|
-
const ov = await this.authorize(c, {
|
|
134
|
-
type: 'multipart-complete',
|
|
135
|
-
key: b.key,
|
|
136
|
-
uploadId: b.uploadId
|
|
137
|
-
});
|
|
138
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
139
|
-
const sm = this.storage.signedMultipart;
|
|
140
|
-
if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');
|
|
141
|
-
return c.json(await sm.complete(key, b.uploadId, b.parts));
|
|
142
|
-
} catch (e) {
|
|
143
|
-
return this.fail(c, e);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
async multipartAbort(c) {
|
|
147
|
-
try {
|
|
148
|
-
const b = await c.req.json();
|
|
149
|
-
const ov = await this.authorize(c, {
|
|
150
|
-
type: 'multipart-abort',
|
|
151
|
-
key: b.key,
|
|
152
|
-
uploadId: b.uploadId
|
|
153
|
-
});
|
|
154
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
155
|
-
const sm = this.storage.signedMultipart;
|
|
156
|
-
if (!sm) throw new StorageError('Unsupported', 'presigned multipart not supported');
|
|
157
|
-
await sm.abort(key, b.uploadId);
|
|
158
|
-
return c.json({
|
|
159
|
-
ok: true
|
|
160
|
-
});
|
|
161
|
-
} catch (e) {
|
|
162
|
-
return this.fail(c, e);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
async list(c) {
|
|
166
|
-
try {
|
|
167
|
-
const prefix = c.req.query('prefix');
|
|
168
|
-
const ov = await this.authorize(c, {
|
|
169
|
-
type: 'list',
|
|
170
|
-
prefix
|
|
171
|
-
});
|
|
172
|
-
const limit = c.req.query('limit');
|
|
173
|
-
const res = await this.storage.list({
|
|
174
|
-
prefix: ov.prefix ?? prefix,
|
|
175
|
-
cursor: c.req.query('cursor'),
|
|
176
|
-
delimiter: c.req.query('delimiter'),
|
|
177
|
-
limit: limit ? Math.min(Number(limit), http.maxListLimit) : undefined
|
|
178
|
-
});
|
|
179
|
-
return c.json({
|
|
180
|
-
items: res.items.map(serializeStored),
|
|
181
|
-
prefixes: res.prefixes,
|
|
182
|
-
cursor: res.cursor
|
|
183
|
-
});
|
|
184
|
-
} catch (e) {
|
|
185
|
-
return this.fail(c, e);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
async head(c) {
|
|
189
|
-
try {
|
|
190
|
-
const key = sanitizeKey(c.req.query('key') ?? '');
|
|
191
|
-
const ov = await this.authorize(c, {
|
|
192
|
-
type: 'head',
|
|
193
|
-
key
|
|
194
|
-
});
|
|
195
|
-
const file = await this.storage.head(sanitizeKey(ov.key ?? key));
|
|
196
|
-
return c.json(serializeStored(file));
|
|
197
|
-
} catch (e) {
|
|
198
|
-
return this.fail(c, e);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
async delete(c) {
|
|
202
|
-
try {
|
|
203
|
-
const b = await c.req.json();
|
|
204
|
-
const keys = b.keys.map((k)=>sanitizeKey(k));
|
|
205
|
-
const ov = await this.authorize(c, {
|
|
206
|
-
type: 'delete',
|
|
207
|
-
keys
|
|
208
|
-
});
|
|
209
|
-
const effective = (ov.keys ?? keys).map((k)=>sanitizeKey(k));
|
|
210
|
-
return c.json(await this.storage.delete(effective, {
|
|
211
|
-
concurrency: http.deleteConcurrency
|
|
212
|
-
}));
|
|
213
|
-
} catch (e) {
|
|
214
|
-
return this.fail(c, e);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
async download(c) {
|
|
218
|
-
try {
|
|
219
|
-
const key = sanitizeKey(c.req.query('key') ?? '');
|
|
220
|
-
const disp = c.req.query('disposition');
|
|
221
|
-
const ov = await this.authorize(c, {
|
|
222
|
-
type: 'download',
|
|
223
|
-
key
|
|
224
|
-
});
|
|
225
|
-
const ekey = sanitizeKey(ov.key ?? key);
|
|
226
|
-
const name = ekey.slice(ekey.lastIndexOf('/') + 1);
|
|
227
|
-
if (http.download === 'redirect' && this.storage.capabilities.signedUrl.supported) {
|
|
228
|
-
const url = await this.storage.url(ekey, {
|
|
229
|
-
expiresIn: clampExpiry(ov.expiresIn, http.defaultExpiresIn, http.maxExpiresIn),
|
|
230
|
-
responseContentDisposition: dispositionHeader(disp, name)
|
|
231
|
-
});
|
|
232
|
-
return c.redirect(url, 302);
|
|
233
|
-
}
|
|
234
|
-
const range = parseRange(c.req.header('range'));
|
|
235
|
-
const file = await this.storage.download(ekey, range ? {
|
|
236
|
-
range
|
|
237
|
-
} : undefined);
|
|
238
|
-
const headers = new Headers({
|
|
239
|
-
'content-type': file.type,
|
|
240
|
-
'content-length': String(file.size),
|
|
241
|
-
'content-disposition': dispositionHeader(disp, file.name)
|
|
242
|
-
});
|
|
243
|
-
if (file.etag) headers.set('etag', file.etag);
|
|
244
|
-
if (range) {
|
|
245
|
-
headers.set('content-range', `bytes ${range.start}-${range.start + file.size - 1}/*`);
|
|
246
|
-
return new Response(file.stream(), {
|
|
247
|
-
status: 206,
|
|
248
|
-
headers
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
return new Response(file.stream(), {
|
|
252
|
-
status: 200,
|
|
253
|
-
headers
|
|
254
|
-
});
|
|
255
|
-
} catch (e) {
|
|
256
|
-
return this.fail(c, e);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
async signDownload(c) {
|
|
260
|
-
try {
|
|
261
|
-
const b = await c.req.json();
|
|
262
|
-
const ov = await this.authorize(c, {
|
|
263
|
-
type: 'download',
|
|
264
|
-
key: b.key
|
|
265
|
-
});
|
|
266
|
-
const key = sanitizeKey(ov.key ?? b.key);
|
|
267
|
-
const expiresIn = clampExpiry(ov.expiresIn ?? b.expiresIn, http.defaultExpiresIn, http.maxExpiresIn);
|
|
268
|
-
const url = await this.storage.url(key, {
|
|
269
|
-
expiresIn
|
|
270
|
-
});
|
|
271
|
-
return c.json({
|
|
272
|
-
url,
|
|
273
|
-
expiresAt: Date.now() + expiresIn * 1000
|
|
274
|
-
});
|
|
275
|
-
} catch (e) {
|
|
276
|
-
return this.fail(c, e);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
_ts_decorate([
|
|
281
|
-
Post('/sign-upload'),
|
|
282
|
-
_ts_param(0, Req()),
|
|
283
|
-
_ts_metadata("design:type", Function),
|
|
284
|
-
_ts_metadata("design:paramtypes", [
|
|
285
|
-
typeof Context === "undefined" ? Object : Context
|
|
286
|
-
]),
|
|
287
|
-
_ts_metadata("design:returntype", Promise)
|
|
288
|
-
], StorageController.prototype, "signUpload", null);
|
|
289
|
-
_ts_decorate([
|
|
290
|
-
Post('/multipart/create'),
|
|
291
|
-
_ts_param(0, Req()),
|
|
292
|
-
_ts_metadata("design:type", Function),
|
|
293
|
-
_ts_metadata("design:paramtypes", [
|
|
294
|
-
typeof Context === "undefined" ? Object : Context
|
|
295
|
-
]),
|
|
296
|
-
_ts_metadata("design:returntype", Promise)
|
|
297
|
-
], StorageController.prototype, "multipartCreate", null);
|
|
298
|
-
_ts_decorate([
|
|
299
|
-
Post('/multipart/sign-part'),
|
|
300
|
-
_ts_param(0, Req()),
|
|
301
|
-
_ts_metadata("design:type", Function),
|
|
302
|
-
_ts_metadata("design:paramtypes", [
|
|
303
|
-
typeof Context === "undefined" ? Object : Context
|
|
304
|
-
]),
|
|
305
|
-
_ts_metadata("design:returntype", Promise)
|
|
306
|
-
], StorageController.prototype, "multipartSignPart", null);
|
|
307
|
-
_ts_decorate([
|
|
308
|
-
Post('/multipart/complete'),
|
|
309
|
-
_ts_param(0, Req()),
|
|
310
|
-
_ts_metadata("design:type", Function),
|
|
311
|
-
_ts_metadata("design:paramtypes", [
|
|
312
|
-
typeof Context === "undefined" ? Object : Context
|
|
313
|
-
]),
|
|
314
|
-
_ts_metadata("design:returntype", Promise)
|
|
315
|
-
], StorageController.prototype, "multipartComplete", null);
|
|
316
|
-
_ts_decorate([
|
|
317
|
-
Post('/multipart/abort'),
|
|
318
|
-
_ts_param(0, Req()),
|
|
319
|
-
_ts_metadata("design:type", Function),
|
|
320
|
-
_ts_metadata("design:paramtypes", [
|
|
321
|
-
typeof Context === "undefined" ? Object : Context
|
|
322
|
-
]),
|
|
323
|
-
_ts_metadata("design:returntype", Promise)
|
|
324
|
-
], StorageController.prototype, "multipartAbort", null);
|
|
325
|
-
_ts_decorate([
|
|
326
|
-
Get('/list'),
|
|
327
|
-
_ts_param(0, Req()),
|
|
328
|
-
_ts_metadata("design:type", Function),
|
|
329
|
-
_ts_metadata("design:paramtypes", [
|
|
330
|
-
typeof Context === "undefined" ? Object : Context
|
|
331
|
-
]),
|
|
332
|
-
_ts_metadata("design:returntype", Promise)
|
|
333
|
-
], StorageController.prototype, "list", null);
|
|
334
|
-
_ts_decorate([
|
|
335
|
-
Get('/head'),
|
|
336
|
-
_ts_param(0, Req()),
|
|
337
|
-
_ts_metadata("design:type", Function),
|
|
338
|
-
_ts_metadata("design:paramtypes", [
|
|
339
|
-
typeof Context === "undefined" ? Object : Context
|
|
340
|
-
]),
|
|
341
|
-
_ts_metadata("design:returntype", Promise)
|
|
342
|
-
], StorageController.prototype, "head", null);
|
|
343
|
-
_ts_decorate([
|
|
344
|
-
Post('/delete'),
|
|
345
|
-
_ts_param(0, Req()),
|
|
346
|
-
_ts_metadata("design:type", Function),
|
|
347
|
-
_ts_metadata("design:paramtypes", [
|
|
348
|
-
typeof Context === "undefined" ? Object : Context
|
|
349
|
-
]),
|
|
350
|
-
_ts_metadata("design:returntype", Promise)
|
|
351
|
-
], StorageController.prototype, "delete", null);
|
|
352
|
-
_ts_decorate([
|
|
353
|
-
Get('/download'),
|
|
354
|
-
_ts_param(0, Req()),
|
|
355
|
-
_ts_metadata("design:type", Function),
|
|
356
|
-
_ts_metadata("design:paramtypes", [
|
|
357
|
-
typeof Context === "undefined" ? Object : Context
|
|
358
|
-
]),
|
|
359
|
-
_ts_metadata("design:returntype", Promise)
|
|
360
|
-
], StorageController.prototype, "download", null);
|
|
361
|
-
_ts_decorate([
|
|
362
|
-
Post('/sign-download'),
|
|
363
|
-
_ts_param(0, Req()),
|
|
364
|
-
_ts_metadata("design:type", Function),
|
|
365
|
-
_ts_metadata("design:paramtypes", [
|
|
366
|
-
typeof Context === "undefined" ? Object : Context
|
|
367
|
-
]),
|
|
368
|
-
_ts_metadata("design:returntype", Promise)
|
|
369
|
-
], StorageController.prototype, "signDownload", null);
|
|
370
|
-
StorageController = _ts_decorate([
|
|
371
|
-
Controller(basePath),
|
|
372
|
-
Injectable(),
|
|
373
|
-
_ts_param(0, Inject(serviceToken)),
|
|
374
|
-
_ts_metadata("design:type", Function),
|
|
375
|
-
_ts_metadata("design:paramtypes", [
|
|
376
|
-
typeof StorageService === "undefined" ? Object : StorageService
|
|
377
|
-
])
|
|
378
|
-
], StorageController);
|
|
379
|
-
return StorageController;
|
|
380
|
-
}
|
package/dist/storage.error.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The single error taxonomy for `@velajs/storage`. Every driver maps its
|
|
3
|
-
* provider/transport failures onto a {@link StorageErrorCode}; the facade's
|
|
4
|
-
* capability gates throw `Unsupported`; the retry loop keys off
|
|
5
|
-
* {@link StorageError.retryable}; and the HTTP controller maps codes to
|
|
6
|
-
* status via its own `codeToHttp()` table.
|
|
7
|
-
*/
|
|
8
|
-
export type StorageErrorCode = 'NotFound' | 'AccessDenied' | 'Unsupported' | 'ReadOnly' | 'InvalidKey' | 'InvalidRequest' | 'Conflict' | 'RateLimited' | 'Network' | 'Timeout' | 'Aborted' | 'Provider' | 'Parse';
|
|
9
|
-
export interface StorageErrorOptions {
|
|
10
|
-
cause?: unknown;
|
|
11
|
-
/** Underlying HTTP status, when the failure came from a transport response. */
|
|
12
|
-
status?: number;
|
|
13
|
-
/** Override the default retryability implied by {@link StorageErrorCode}. */
|
|
14
|
-
retryable?: boolean;
|
|
15
|
-
}
|
|
16
|
-
export declare class StorageError extends Error {
|
|
17
|
-
name: string;
|
|
18
|
-
readonly code: StorageErrorCode;
|
|
19
|
-
readonly retryable: boolean;
|
|
20
|
-
readonly status: number | undefined;
|
|
21
|
-
constructor(code: StorageErrorCode, message: string, options?: StorageErrorOptions);
|
|
22
|
-
/** Wrap an arbitrary thrown value as a `StorageError` (idempotent). */
|
|
23
|
-
static wrap(e: unknown): StorageError;
|
|
24
|
-
/** Map a transport status code to a `StorageError` (5xx/429 retryable). */
|
|
25
|
-
static fromStatus(status: number, message: string, cause?: unknown): StorageError;
|
|
26
|
-
}
|
|
27
|
-
/** True for `AbortError`-shaped values (DOMException or `{ name: 'AbortError' }`). */
|
|
28
|
-
export declare function isAbort(e: unknown): boolean;
|
package/dist/storage.error.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The single error taxonomy for `@velajs/storage`. Every driver maps its
|
|
3
|
-
* provider/transport failures onto a {@link StorageErrorCode}; the facade's
|
|
4
|
-
* capability gates throw `Unsupported`; the retry loop keys off
|
|
5
|
-
* {@link StorageError.retryable}; and the HTTP controller maps codes to
|
|
6
|
-
* status via its own `codeToHttp()` table.
|
|
7
|
-
*/ /** Codes that are safe to retry by default (transient failures). */ const RETRYABLE = new Set([
|
|
8
|
-
'Network',
|
|
9
|
-
'RateLimited',
|
|
10
|
-
'Timeout',
|
|
11
|
-
'Provider'
|
|
12
|
-
]);
|
|
13
|
-
export class StorageError extends Error {
|
|
14
|
-
name = 'StorageError';
|
|
15
|
-
code;
|
|
16
|
-
retryable;
|
|
17
|
-
status;
|
|
18
|
-
constructor(code, message, options){
|
|
19
|
-
super(message, options?.cause !== undefined ? {
|
|
20
|
-
cause: options.cause
|
|
21
|
-
} : undefined);
|
|
22
|
-
this.code = code;
|
|
23
|
-
this.status = options?.status;
|
|
24
|
-
this.retryable = options?.retryable ?? RETRYABLE.has(code);
|
|
25
|
-
}
|
|
26
|
-
/** Wrap an arbitrary thrown value as a `StorageError` (idempotent). */ static wrap(e) {
|
|
27
|
-
if (e instanceof StorageError) return e;
|
|
28
|
-
if (isAbort(e)) return new StorageError('Aborted', 'operation aborted', {
|
|
29
|
-
cause: e
|
|
30
|
-
});
|
|
31
|
-
return new StorageError('Provider', e instanceof Error ? e.message : String(e), {
|
|
32
|
-
cause: e
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
/** Map a transport status code to a `StorageError` (5xx/429 retryable). */ static fromStatus(status, message, cause) {
|
|
36
|
-
const code = status === 404 ? 'NotFound' : status === 403 || status === 401 ? 'AccessDenied' : status === 409 ? 'Conflict' : status === 429 ? 'RateLimited' : status >= 500 ? 'Provider' : 'InvalidRequest';
|
|
37
|
-
return new StorageError(code, message, {
|
|
38
|
-
status,
|
|
39
|
-
cause,
|
|
40
|
-
retryable: status === 429 || status >= 500
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/** True for `AbortError`-shaped values (DOMException or `{ name: 'AbortError' }`). */ export function isAbort(e) {
|
|
45
|
-
return typeof e === 'object' && e !== null && 'name' in e && e.name === 'AbortError';
|
|
46
|
-
}
|
package/dist/storage.facade.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { Body, CreateMultipartOptions, DeleteManyOptions, DeleteManyResult, DownloadOptions, ListOptions, ListResult, MultipartUpload, OperationOptions, SignedMultipartCapability, SignedUpload, SignUploadOptions, StorageCapabilities, StorageDriver, StorageOptions, StoredFile, UploadOptions, UploadResult, UrlOptions } from './storage.types';
|
|
2
|
-
/**
|
|
3
|
-
* The consumer-facing storage handle. Wraps a {@link StorageDriver} with
|
|
4
|
-
* capability-gating (throws before any driver call), retry/timeout/abort,
|
|
5
|
-
* prefix scoping, generic `move`/`deleteMany` fallbacks, multipart
|
|
6
|
-
* orchestration, progress synthesis, and observability hooks.
|
|
7
|
-
*
|
|
8
|
-
* Framework-free — `StorageService` builds and caches one of these per bucket.
|
|
9
|
-
*/
|
|
10
|
-
export declare class Storage {
|
|
11
|
-
#private;
|
|
12
|
-
constructor(opts: StorageOptions);
|
|
13
|
-
get raw(): unknown;
|
|
14
|
-
get driver(): StorageDriver;
|
|
15
|
-
get capabilities(): StorageCapabilities;
|
|
16
|
-
upload(key: string, body: Body, opts?: UploadOptions): Promise<UploadResult>;
|
|
17
|
-
download(key: string, opts?: DownloadOptions): Promise<StoredFile>;
|
|
18
|
-
head(key: string, opts?: OperationOptions): Promise<StoredFile>;
|
|
19
|
-
exists(key: string, opts?: OperationOptions): Promise<boolean>;
|
|
20
|
-
delete(key: string, opts?: OperationOptions): Promise<void>;
|
|
21
|
-
delete(keys: string[], opts?: DeleteManyOptions): Promise<DeleteManyResult>;
|
|
22
|
-
copy(from: string, to: string, opts?: OperationOptions): Promise<void>;
|
|
23
|
-
move(from: string, to: string, opts?: OperationOptions): Promise<void>;
|
|
24
|
-
list(opts?: ListOptions): Promise<ListResult>;
|
|
25
|
-
listAll(opts?: ListOptions): AsyncGenerator<StoredFile>;
|
|
26
|
-
url(key: string, opts?: UrlOptions): Promise<string>;
|
|
27
|
-
signedUploadUrl(key: string, opts: SignUploadOptions): Promise<SignedUpload>;
|
|
28
|
-
/** Prefix-bound view of the driver's presigned-multipart capability. */
|
|
29
|
-
get signedMultipart(): SignedMultipartCapability | undefined;
|
|
30
|
-
createMultipartUpload(key: string, opts?: CreateMultipartOptions): Promise<MultipartUpload>;
|
|
31
|
-
resumeMultipartUpload(key: string, uploadId: string): MultipartUpload;
|
|
32
|
-
/** A key-bound handle over the common single-object operations. */
|
|
33
|
-
file(key: string): FileHandle;
|
|
34
|
-
/** A read-only clone of this handle (mutations throw `ReadOnly`). */
|
|
35
|
-
readonly(): Storage;
|
|
36
|
-
}
|
|
37
|
-
export interface FileHandle {
|
|
38
|
-
readonly key: string;
|
|
39
|
-
upload(body: Body, opts?: UploadOptions): Promise<UploadResult>;
|
|
40
|
-
download(opts?: DownloadOptions): Promise<StoredFile>;
|
|
41
|
-
head(opts?: OperationOptions): Promise<StoredFile>;
|
|
42
|
-
exists(opts?: OperationOptions): Promise<boolean>;
|
|
43
|
-
delete(opts?: OperationOptions): Promise<void>;
|
|
44
|
-
url(opts?: UrlOptions): Promise<string>;
|
|
45
|
-
signedUploadUrl(opts: SignUploadOptions): Promise<SignedUpload>;
|
|
46
|
-
}
|
|
47
|
-
export declare function createStorage(opts: StorageOptions): Storage;
|