@adonis-agora/media 0.1.1 → 0.2.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.
- package/CHANGELOG.md +87 -0
- package/dist/configure.d.ts +2 -2
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +3 -2
- package/dist/configure.js.map +1 -1
- package/dist/providers/media_provider.d.ts +15 -0
- package/dist/providers/media_provider.d.ts.map +1 -1
- package/dist/providers/media_provider.js +224 -12
- package/dist/providers/media_provider.js.map +1 -1
- package/dist/src/attachment.d.ts +1 -0
- package/dist/src/attachment.d.ts.map +1 -1
- package/dist/src/attachment.js +57 -21
- package/dist/src/attachment.js.map +1 -1
- package/dist/src/define_config.d.ts +83 -5
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js +3 -1
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics.d.ts +32 -1
- package/dist/src/diagnostics.d.ts.map +1 -1
- package/dist/src/diagnostics.js.map +1 -1
- package/dist/src/disks/factory.d.ts +62 -0
- package/dist/src/disks/factory.d.ts.map +1 -0
- package/dist/src/disks/factory.js +57 -0
- package/dist/src/disks/factory.js.map +1 -0
- package/dist/src/disks/s3.d.ts +76 -0
- package/dist/src/disks/s3.d.ts.map +1 -0
- package/dist/src/disks/s3.js +357 -0
- package/dist/src/disks/s3.js.map +1 -0
- package/dist/src/disks/xml_fallback.d.ts +29 -0
- package/dist/src/disks/xml_fallback.d.ts.map +1 -0
- package/dist/src/disks/xml_fallback.js +68 -0
- package/dist/src/disks/xml_fallback.js.map +1 -0
- package/dist/src/errors.d.ts +34 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +60 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/extended_disk.d.ts +10 -0
- package/dist/src/extended_disk.d.ts.map +1 -0
- package/dist/src/extended_disk.js +19 -0
- package/dist/src/extended_disk.js.map +1 -0
- package/dist/src/index.d.ts +17 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +11 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/media_library.d.ts +4 -2
- package/dist/src/media_library.d.ts.map +1 -1
- package/dist/src/media_library.js +83 -32
- package/dist/src/media_library.js.map +1 -1
- package/dist/src/media_manager.d.ts +48 -0
- package/dist/src/media_manager.d.ts.map +1 -1
- package/dist/src/media_manager.js +68 -0
- package/dist/src/media_manager.js.map +1 -1
- package/dist/src/media_store.d.ts +40 -0
- package/dist/src/media_store.d.ts.map +1 -1
- package/dist/src/media_store.js +28 -1
- package/dist/src/media_store.js.map +1 -1
- package/dist/src/multipart.d.ts +10 -0
- package/dist/src/multipart.d.ts.map +1 -0
- package/dist/src/multipart.js +16 -0
- package/dist/src/multipart.js.map +1 -0
- package/dist/src/resumable_upload.d.ts +131 -0
- package/dist/src/resumable_upload.d.ts.map +1 -0
- package/dist/src/resumable_upload.js +177 -0
- package/dist/src/resumable_upload.js.map +1 -0
- package/dist/src/services/main.d.ts +14 -0
- package/dist/src/services/main.d.ts.map +1 -0
- package/dist/src/services/main.js +18 -0
- package/dist/src/services/main.js.map +1 -0
- package/dist/src/stores/factory.d.ts +12 -4
- package/dist/src/stores/factory.d.ts.map +1 -1
- package/dist/src/stores/factory.js +20 -1
- package/dist/src/stores/factory.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +2 -1
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +42 -7
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/telescope/dashboard.d.ts +19 -0
- package/dist/src/telescope/dashboard.d.ts.map +1 -0
- package/dist/src/telescope/dashboard.js +116 -0
- package/dist/src/telescope/dashboard.js.map +1 -0
- package/dist/src/telescope/data-providers.d.ts +36 -0
- package/dist/src/telescope/data-providers.d.ts.map +1 -0
- package/dist/src/telescope/data-providers.js +286 -0
- package/dist/src/telescope/data-providers.js.map +1 -0
- package/dist/src/telescope/extension.d.ts +26 -0
- package/dist/src/telescope/extension.d.ts.map +1 -0
- package/dist/src/telescope/extension.js +42 -0
- package/dist/src/telescope/extension.js.map +1 -0
- package/dist/src/telescope/index.d.ts +5 -0
- package/dist/src/telescope/index.d.ts.map +1 -0
- package/dist/src/telescope/index.js +4 -0
- package/dist/src/telescope/index.js.map +1 -0
- package/dist/src/telescope/telescope-sdk.d.ts +125 -0
- package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
- package/dist/src/telescope/telescope-sdk.js +14 -0
- package/dist/src/telescope/telescope-sdk.js.map +1 -0
- package/dist/src/testing/in_memory_disk.d.ts +10 -0
- package/dist/src/testing/in_memory_disk.d.ts.map +1 -1
- package/dist/src/testing/in_memory_disk.js +11 -0
- package/dist/src/testing/in_memory_disk.js.map +1 -1
- package/dist/src/testing/in_memory_media_store.d.ts +2 -1
- package/dist/src/testing/in_memory_media_store.d.ts.map +1 -1
- package/dist/src/testing/in_memory_media_store.js +28 -0
- package/dist/src/testing/in_memory_media_store.js.map +1 -1
- package/dist/src/testing/in_memory_upload_session_store.d.ts +18 -0
- package/dist/src/testing/in_memory_upload_session_store.d.ts.map +1 -0
- package/dist/src/testing/in_memory_upload_session_store.js +40 -0
- package/dist/src/testing/in_memory_upload_session_store.js.map +1 -0
- package/dist/src/testing/index.d.ts +1 -0
- package/dist/src/testing/index.d.ts.map +1 -1
- package/dist/src/testing/index.js +1 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/tus.d.ts +57 -0
- package/dist/src/tus.d.ts.map +1 -0
- package/dist/src/tus.js +143 -0
- package/dist/src/tus.js.map +1 -0
- package/dist/src/types.d.ts +125 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/upload_manager.d.ts +127 -0
- package/dist/src/upload_manager.d.ts.map +1 -0
- package/dist/src/upload_manager.js +152 -0
- package/dist/src/upload_manager.js.map +1 -0
- package/dist/src/upload_mode.d.ts +27 -0
- package/dist/src/upload_mode.d.ts.map +1 -0
- package/dist/src/upload_mode.js +22 -0
- package/dist/src/upload_mode.js.map +1 -0
- package/dist/src/upload_sessions/factory.d.ts +62 -0
- package/dist/src/upload_sessions/factory.d.ts.map +1 -0
- package/dist/src/upload_sessions/factory.js +60 -0
- package/dist/src/upload_sessions/factory.js.map +1 -0
- package/dist/src/upload_sessions/lucid.d.ts +35 -0
- package/dist/src/upload_sessions/lucid.d.ts.map +1 -0
- package/dist/src/upload_sessions/lucid.js +105 -0
- package/dist/src/upload_sessions/lucid.js.map +1 -0
- package/dist/stubs/config/media.stub +16 -1
- package/dist/stubs/database/migrations/create_media_upload_sessions_table.stub +45 -0
- package/package.json +37 -1
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { AbortMultipartUploadCommand, CompleteMultipartUploadCommand, CopyObjectCommand, CreateMultipartUploadCommand, DeleteObjectCommand, DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, UploadPartCommand, } from '@aws-sdk/client-s3';
|
|
2
|
+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
3
|
+
import { extractListObjectsV2FromXml, isXmlEntityDeserializationError } from './xml_fallback.js';
|
|
4
|
+
/** Default presigned-URL lifetime when a caller passes no `expiresIn` (30 minutes). */
|
|
5
|
+
const DEFAULT_SIGNED_URL_TTL_SECONDS = 1800;
|
|
6
|
+
/** Human-readable duration units accepted in {@link SignedUrlOptions.expiresIn}. */
|
|
7
|
+
const DURATION_UNITS = { s: 1, m: 60, h: 3600, d: 86_400 };
|
|
8
|
+
/**
|
|
9
|
+
* Convert Drive's `expiresIn` (a number of seconds, or a string like `'30m'`/`'1h'`/`'45s'`/`'2d'`)
|
|
10
|
+
* into the whole-seconds the S3 request presigner expects.
|
|
11
|
+
*/
|
|
12
|
+
function toExpiresInSeconds(expiresIn) {
|
|
13
|
+
if (expiresIn === undefined)
|
|
14
|
+
return DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
15
|
+
if (typeof expiresIn === 'number')
|
|
16
|
+
return Math.max(1, Math.round(expiresIn));
|
|
17
|
+
const match = /^(\d+)\s*([smhd])$/.exec(expiresIn.trim());
|
|
18
|
+
if (match) {
|
|
19
|
+
const value = Number(match[1]);
|
|
20
|
+
const unit = DURATION_UNITS[match[2]];
|
|
21
|
+
return Math.max(1, value * unit);
|
|
22
|
+
}
|
|
23
|
+
const asNumber = Number(expiresIn);
|
|
24
|
+
if (Number.isFinite(asNumber) && asNumber > 0)
|
|
25
|
+
return Math.round(asNumber);
|
|
26
|
+
return DEFAULT_SIGNED_URL_TTL_SECONDS;
|
|
27
|
+
}
|
|
28
|
+
function isNotFound(err) {
|
|
29
|
+
const e = err;
|
|
30
|
+
return e?.name === 'NoSuchKey' || e?.name === 'NotFound' || e?.$metadata?.httpStatusCode === 404;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* S3-backed {@link Disk} satisfying the same structural contract as an `@adonisjs/drive` disk, so it
|
|
34
|
+
* is a drop-in for the media-library and attachment layers. Backed by `@aws-sdk/client-s3` (an
|
|
35
|
+
* optional peer). Beyond the base {@link Disk} surface it also implements {@link MultipartUploadDisk}
|
|
36
|
+
* — native S3 multipart, powering the `proxy` and `direct` upload modes — which the upload layer
|
|
37
|
+
* detects structurally (`isMultipartCapable`) rather than through the base contract. It also
|
|
38
|
+
* implements the optional {@link ExtendedDisk} surface (copy/move, batched delete, list, size/stat,
|
|
39
|
+
* plus a {@link DiskCapabilities} descriptor), detected structurally via `isExtendedDisk`.
|
|
40
|
+
*/
|
|
41
|
+
export class S3Disk {
|
|
42
|
+
/** Coarse feature descriptor — S3 supports presign, native multipart, and prefix listing. */
|
|
43
|
+
capabilities;
|
|
44
|
+
client;
|
|
45
|
+
bucket;
|
|
46
|
+
keyPrefix;
|
|
47
|
+
publicBaseUrl;
|
|
48
|
+
region;
|
|
49
|
+
endpoint;
|
|
50
|
+
forcePathStyle;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.client = options.client;
|
|
53
|
+
this.bucket = options.bucket;
|
|
54
|
+
this.keyPrefix = (options.keyPrefix ?? '').replace(/^\/+|\/+$/g, '');
|
|
55
|
+
this.publicBaseUrl = options.publicBaseUrl;
|
|
56
|
+
this.region = options.region;
|
|
57
|
+
this.endpoint = options.endpoint;
|
|
58
|
+
this.forcePathStyle = options.forcePathStyle ?? false;
|
|
59
|
+
this.capabilities = {
|
|
60
|
+
presign: true,
|
|
61
|
+
multipart: true,
|
|
62
|
+
// A stable public URL can always be synthesised (publicBaseUrl, endpoint, or the regional host).
|
|
63
|
+
publicUrls: true,
|
|
64
|
+
list: true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Map a logical key to a fully-qualified S3 key, applying the configured prefix. */
|
|
68
|
+
key(path) {
|
|
69
|
+
const clean = path.replace(/^\/+/, '');
|
|
70
|
+
return this.keyPrefix ? `${this.keyPrefix}/${clean}` : clean;
|
|
71
|
+
}
|
|
72
|
+
async put(key, contents, options) {
|
|
73
|
+
await this.client.send(new PutObjectCommand({
|
|
74
|
+
Bucket: this.bucket,
|
|
75
|
+
Key: this.key(key),
|
|
76
|
+
Body: contents,
|
|
77
|
+
ContentType: options?.contentType,
|
|
78
|
+
ACL: options?.visibility === 'public' ? 'public-read' : undefined,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* `ContentLength` is required, not an optimization: S3 cannot size a stream, so the SDK
|
|
83
|
+
* derives `x-amz-decoded-content-length` from it and throws
|
|
84
|
+
* `Invalid value "undefined" for header "x-amz-decoded-content-length"` when it is absent.
|
|
85
|
+
* Callers that reach this path already know the size (it is what makes streaming eligible).
|
|
86
|
+
*/
|
|
87
|
+
async putStream(key, contents, options) {
|
|
88
|
+
if (options?.contentLength === undefined) {
|
|
89
|
+
throw new Error(`S3Disk.putStream requires options.contentLength for key: ${key} — S3 cannot size a stream.`);
|
|
90
|
+
}
|
|
91
|
+
await this.client.send(new PutObjectCommand({
|
|
92
|
+
Bucket: this.bucket,
|
|
93
|
+
Key: this.key(key),
|
|
94
|
+
Body: contents,
|
|
95
|
+
ContentLength: options.contentLength,
|
|
96
|
+
ContentType: options.contentType,
|
|
97
|
+
ACL: options.visibility === 'public' ? 'public-read' : undefined,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
async getBytes(key) {
|
|
101
|
+
try {
|
|
102
|
+
const res = await this.client.send(new GetObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
103
|
+
const bytes = await res.Body?.transformToByteArray();
|
|
104
|
+
if (!bytes)
|
|
105
|
+
throw new Error(`S3Disk: empty body for key: ${key}`);
|
|
106
|
+
return bytes;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (isNotFound(err))
|
|
110
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async getStream(key) {
|
|
115
|
+
try {
|
|
116
|
+
const res = await this.client.send(new GetObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
117
|
+
if (!res.Body)
|
|
118
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
119
|
+
return res.Body;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (isNotFound(err))
|
|
123
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async exists(key) {
|
|
128
|
+
try {
|
|
129
|
+
await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
if (isNotFound(err))
|
|
134
|
+
return false;
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async delete(key) {
|
|
139
|
+
await this.client.send(new DeleteObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
140
|
+
}
|
|
141
|
+
async getUrl(key) {
|
|
142
|
+
const objectKey = this.key(key);
|
|
143
|
+
if (this.publicBaseUrl) {
|
|
144
|
+
return `${this.publicBaseUrl.replace(/\/+$/, '')}/${objectKey}`;
|
|
145
|
+
}
|
|
146
|
+
if (this.endpoint) {
|
|
147
|
+
const base = this.endpoint.replace(/\/+$/, '');
|
|
148
|
+
if (this.forcePathStyle)
|
|
149
|
+
return `${base}/${this.bucket}/${objectKey}`;
|
|
150
|
+
const withHost = base.replace(/^(https?:\/\/)/, `$1${this.bucket}.`);
|
|
151
|
+
return `${withHost}/${objectKey}`;
|
|
152
|
+
}
|
|
153
|
+
const region = this.region ?? 'us-east-1';
|
|
154
|
+
return `https://${this.bucket}.s3.${region}.amazonaws.com/${objectKey}`;
|
|
155
|
+
}
|
|
156
|
+
async getSignedUrl(key, options) {
|
|
157
|
+
return getSignedUrl(this.client, new GetObjectCommand({
|
|
158
|
+
Bucket: this.bucket,
|
|
159
|
+
Key: this.key(key),
|
|
160
|
+
ResponseContentType: options?.contentType,
|
|
161
|
+
ResponseContentDisposition: options?.contentDisposition,
|
|
162
|
+
}), { expiresIn: toExpiresInSeconds(options?.expiresIn) });
|
|
163
|
+
}
|
|
164
|
+
async getMetaData(key) {
|
|
165
|
+
try {
|
|
166
|
+
const res = await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
167
|
+
return {
|
|
168
|
+
contentLength: res.ContentLength ?? 0,
|
|
169
|
+
contentType: res.ContentType,
|
|
170
|
+
etag: res.ETag,
|
|
171
|
+
lastModified: res.LastModified,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (isNotFound(err))
|
|
176
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// --- Extended object operations (ExtendedDisk) --------------------------------------------
|
|
181
|
+
async size(key) {
|
|
182
|
+
try {
|
|
183
|
+
const res = await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
184
|
+
return res.ContentLength ?? 0;
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
if (isNotFound(err))
|
|
188
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
189
|
+
throw err;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async stat(key) {
|
|
193
|
+
try {
|
|
194
|
+
const res = await this.client.send(new HeadObjectCommand({ Bucket: this.bucket, Key: this.key(key) }));
|
|
195
|
+
return {
|
|
196
|
+
size: res.ContentLength ?? 0,
|
|
197
|
+
contentType: res.ContentType,
|
|
198
|
+
lastModified: res.LastModified,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
if (isNotFound(err))
|
|
203
|
+
throw new Error(`S3Disk: file not found: ${key}`);
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async copy(from, to, options) {
|
|
208
|
+
const targetBucket = options?.toBucket ?? this.bucket;
|
|
209
|
+
await this.client.send(new CopyObjectCommand({
|
|
210
|
+
// Destination bucket (may differ from the source for cross-bucket copies).
|
|
211
|
+
Bucket: targetBucket,
|
|
212
|
+
// Source is always this disk's configured bucket + prefixed key.
|
|
213
|
+
CopySource: `${this.bucket}/${this.key(from)}`,
|
|
214
|
+
Key: this.key(to),
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
async move(from, to, options) {
|
|
218
|
+
await this.copy(from, to, options);
|
|
219
|
+
await this.delete(from);
|
|
220
|
+
}
|
|
221
|
+
async deleteMany(keys) {
|
|
222
|
+
if (keys.length === 0)
|
|
223
|
+
return;
|
|
224
|
+
// S3 caps a DeleteObjects batch at 1000 keys.
|
|
225
|
+
for (let start = 0; start < keys.length; start += 1000) {
|
|
226
|
+
const batch = keys.slice(start, start + 1000);
|
|
227
|
+
const res = await this.client.send(new DeleteObjectsCommand({
|
|
228
|
+
Bucket: this.bucket,
|
|
229
|
+
Delete: { Objects: batch.map((key) => ({ Key: this.key(key) })) },
|
|
230
|
+
}));
|
|
231
|
+
// DeleteObjects returns 200 with a per-key Errors[] on partial failure; single delete()
|
|
232
|
+
// throws on failure, so match that here instead of swallowing.
|
|
233
|
+
if (res.Errors && res.Errors.length > 0) {
|
|
234
|
+
const failed = res.Errors.map((error) => error.Key ?? '?').join(', ');
|
|
235
|
+
throw new Error(`S3Disk: deleteMany failed for keys: ${failed}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async list(prefix, options) {
|
|
240
|
+
const bucket = options?.bucket ?? this.bucket;
|
|
241
|
+
const fullPrefix = this.key(prefix);
|
|
242
|
+
try {
|
|
243
|
+
const out = await this.client.send(new ListObjectsV2Command({
|
|
244
|
+
Bucket: bucket,
|
|
245
|
+
Prefix: fullPrefix,
|
|
246
|
+
Delimiter: options?.delimiter ?? '/',
|
|
247
|
+
MaxKeys: options?.limit,
|
|
248
|
+
ContinuationToken: options?.cursor,
|
|
249
|
+
}));
|
|
250
|
+
const folders = (out.CommonPrefixes ?? [])
|
|
251
|
+
.map((commonPrefix) => commonPrefix.Prefix)
|
|
252
|
+
.filter((value) => typeof value === 'string');
|
|
253
|
+
const files = (out.Contents ?? [])
|
|
254
|
+
.filter((object) => object.Key !== undefined && object.Key !== fullPrefix)
|
|
255
|
+
.map((object) => {
|
|
256
|
+
const objectKey = object.Key;
|
|
257
|
+
return {
|
|
258
|
+
key: objectKey,
|
|
259
|
+
name: objectKey.slice(fullPrefix.length),
|
|
260
|
+
sizeBytes: object.Size ?? null,
|
|
261
|
+
lastModified: object.LastModified ?? null,
|
|
262
|
+
};
|
|
263
|
+
});
|
|
264
|
+
const result = { folders, files };
|
|
265
|
+
if (out.IsTruncated && out.NextContinuationToken !== undefined) {
|
|
266
|
+
result.cursor = out.NextContinuationToken;
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
if (!isXmlEntityDeserializationError(err))
|
|
272
|
+
throw err;
|
|
273
|
+
// fast-xml-parser rejected valid entity refs in the ListObjectsV2 XML — presign the same
|
|
274
|
+
// request and fetch the raw body, then parse it by hand into the same shape. The presigner is
|
|
275
|
+
// already bundled with this disk, so the fallback adds no new dependency (see xml_fallback.ts).
|
|
276
|
+
const signedUrl = await getSignedUrl(this.client, new ListObjectsV2Command({
|
|
277
|
+
Bucket: bucket,
|
|
278
|
+
Prefix: fullPrefix,
|
|
279
|
+
Delimiter: options?.delimiter ?? '/',
|
|
280
|
+
MaxKeys: options?.limit,
|
|
281
|
+
ContinuationToken: options?.cursor,
|
|
282
|
+
}), { expiresIn: 60 });
|
|
283
|
+
const response = await fetch(signedUrl);
|
|
284
|
+
if (!response.ok) {
|
|
285
|
+
throw new Error(`S3Disk: signed list fallback failed: HTTP ${response.status} ${response.statusText}`);
|
|
286
|
+
}
|
|
287
|
+
const xml = await response.text();
|
|
288
|
+
const parsed = extractListObjectsV2FromXml(xml);
|
|
289
|
+
const files = parsed.objects
|
|
290
|
+
.filter((object) => object.key !== fullPrefix)
|
|
291
|
+
.map((object) => ({
|
|
292
|
+
key: object.key,
|
|
293
|
+
name: object.key.slice(fullPrefix.length),
|
|
294
|
+
sizeBytes: object.size,
|
|
295
|
+
lastModified: object.lastModified ? new Date(object.lastModified) : null,
|
|
296
|
+
}));
|
|
297
|
+
const result = { folders: parsed.folders, files };
|
|
298
|
+
if (parsed.isTruncated && parsed.nextContinuationToken) {
|
|
299
|
+
result.cursor = parsed.nextContinuationToken;
|
|
300
|
+
}
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// --- Native multipart (MultipartUploadDisk) -----------------------------------------------
|
|
305
|
+
async createMultipartUpload(key, options) {
|
|
306
|
+
const out = await this.client.send(new CreateMultipartUploadCommand({
|
|
307
|
+
Bucket: this.bucket,
|
|
308
|
+
Key: this.key(key),
|
|
309
|
+
ContentType: options?.contentType,
|
|
310
|
+
ACL: options?.visibility === 'public' ? 'public-read' : undefined,
|
|
311
|
+
}));
|
|
312
|
+
if (!out.UploadId)
|
|
313
|
+
throw new Error('S3Disk: S3 did not return an UploadId');
|
|
314
|
+
return { uploadId: out.UploadId };
|
|
315
|
+
}
|
|
316
|
+
async uploadPart(key, uploadId, partNumber, body) {
|
|
317
|
+
const out = await this.client.send(new UploadPartCommand({
|
|
318
|
+
Bucket: this.bucket,
|
|
319
|
+
Key: this.key(key),
|
|
320
|
+
UploadId: uploadId,
|
|
321
|
+
PartNumber: partNumber,
|
|
322
|
+
Body: body,
|
|
323
|
+
}));
|
|
324
|
+
if (!out.ETag)
|
|
325
|
+
throw new Error('S3Disk: S3 did not return an ETag for the uploaded part');
|
|
326
|
+
return { partNumber, etag: out.ETag };
|
|
327
|
+
}
|
|
328
|
+
async presignUploadPart(key, uploadId, partNumber, expiresInSeconds) {
|
|
329
|
+
return getSignedUrl(this.client, new UploadPartCommand({
|
|
330
|
+
Bucket: this.bucket,
|
|
331
|
+
Key: this.key(key),
|
|
332
|
+
UploadId: uploadId,
|
|
333
|
+
PartNumber: partNumber,
|
|
334
|
+
}), { expiresIn: Math.max(1, Math.round(expiresInSeconds)) });
|
|
335
|
+
}
|
|
336
|
+
async completeMultipartUpload(key, uploadId, parts) {
|
|
337
|
+
await this.client.send(new CompleteMultipartUploadCommand({
|
|
338
|
+
Bucket: this.bucket,
|
|
339
|
+
Key: this.key(key),
|
|
340
|
+
UploadId: uploadId,
|
|
341
|
+
MultipartUpload: {
|
|
342
|
+
Parts: parts
|
|
343
|
+
.slice()
|
|
344
|
+
.sort((a, b) => a.partNumber - b.partNumber)
|
|
345
|
+
.map((p) => ({ PartNumber: p.partNumber, ETag: p.etag })),
|
|
346
|
+
},
|
|
347
|
+
}));
|
|
348
|
+
}
|
|
349
|
+
async abortMultipartUpload(key, uploadId) {
|
|
350
|
+
await this.client.send(new AbortMultipartUploadCommand({
|
|
351
|
+
Bucket: this.bucket,
|
|
352
|
+
Key: this.key(key),
|
|
353
|
+
UploadId: uploadId,
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.js","sourceRoot":"","sources":["../../../src/disks/s3.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AWS SDK deserializes S3's XML responses with `fast-xml-parser`. Some hosts pin
|
|
3
|
+
* `fast-xml-parser` v5 (CVE remediation), whose stricter mode rejects valid numeric character
|
|
4
|
+
* references (`
`, …) that S3 legitimately emits inside keys — surfacing as a deserialization
|
|
5
|
+
* error on `ListObjectsV2`. This module provides a fallback for {@link S3Disk.list}: re-issue the
|
|
6
|
+
* request as a signed raw GET (presigned with `@aws-sdk/s3-request-presigner`, an existing optional
|
|
7
|
+
* peer) and hand-parse the XML, bypassing `fast-xml-parser` entirely.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: this fallback does NOT depend on `fast-xml-parser` — it exists precisely to work around it —
|
|
10
|
+
* and introduces NO new peer: the signing reuses the presigner already bundled with the S3 disk, so
|
|
11
|
+
* only regex XML parsing lives here.
|
|
12
|
+
*/
|
|
13
|
+
/** Is this the `fast-xml-parser` entity-rejection error the signed-GET fallback exists for? */
|
|
14
|
+
export declare function isXmlEntityDeserializationError(error: unknown): boolean;
|
|
15
|
+
export declare function decodeXmlEntities(value: string): string;
|
|
16
|
+
export interface ListObjectsV2Entry {
|
|
17
|
+
key: string;
|
|
18
|
+
size: number | null;
|
|
19
|
+
lastModified: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface ListObjectsV2FromXml {
|
|
22
|
+
folders: string[];
|
|
23
|
+
objects: ListObjectsV2Entry[];
|
|
24
|
+
nextContinuationToken: string | null;
|
|
25
|
+
isTruncated: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Hand-parse a `ListObjectsV2` XML body into the shape {@link S3Disk.list} needs. */
|
|
28
|
+
export declare function extractListObjectsV2FromXml(xml: string): ListObjectsV2FromXml;
|
|
29
|
+
//# sourceMappingURL=xml_fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml_fallback.d.ts","sourceRoot":"","sources":["../../../src/disks/xml_fallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,+FAA+F;AAC/F,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQvE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASvD;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,sFAAsF;AACtF,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAiC7E"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AWS SDK deserializes S3's XML responses with `fast-xml-parser`. Some hosts pin
|
|
3
|
+
* `fast-xml-parser` v5 (CVE remediation), whose stricter mode rejects valid numeric character
|
|
4
|
+
* references (`
`, …) that S3 legitimately emits inside keys — surfacing as a deserialization
|
|
5
|
+
* error on `ListObjectsV2`. This module provides a fallback for {@link S3Disk.list}: re-issue the
|
|
6
|
+
* request as a signed raw GET (presigned with `@aws-sdk/s3-request-presigner`, an existing optional
|
|
7
|
+
* peer) and hand-parse the XML, bypassing `fast-xml-parser` entirely.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: this fallback does NOT depend on `fast-xml-parser` — it exists precisely to work around it —
|
|
10
|
+
* and introduces NO new peer: the signing reuses the presigner already bundled with the S3 disk, so
|
|
11
|
+
* only regex XML parsing lives here.
|
|
12
|
+
*/
|
|
13
|
+
const ENTITY_NAME_REGEX = /Invalid character.*entity name/i;
|
|
14
|
+
/** Is this the `fast-xml-parser` entity-rejection error the signed-GET fallback exists for? */
|
|
15
|
+
export function isXmlEntityDeserializationError(error) {
|
|
16
|
+
if (!(error instanceof Error))
|
|
17
|
+
return false;
|
|
18
|
+
const message = error.message ?? '';
|
|
19
|
+
return (message.includes('EntityReplacer') ||
|
|
20
|
+
message.includes('Deserialization') ||
|
|
21
|
+
ENTITY_NAME_REGEX.test(message));
|
|
22
|
+
}
|
|
23
|
+
export function decodeXmlEntities(value) {
|
|
24
|
+
return value
|
|
25
|
+
.replace(/&#x([0-9A-Fa-f]+);/g, (_match, hex) => String.fromCodePoint(Number.parseInt(hex, 16)))
|
|
26
|
+
.replace(/&#(\d+);/g, (_match, dec) => String.fromCodePoint(Number.parseInt(dec, 10)))
|
|
27
|
+
.replace(/</g, '<')
|
|
28
|
+
.replace(/>/g, '>')
|
|
29
|
+
.replace(/"/g, '"')
|
|
30
|
+
.replace(/'/g, "'")
|
|
31
|
+
.replace(/&/g, '&');
|
|
32
|
+
}
|
|
33
|
+
/** Hand-parse a `ListObjectsV2` XML body into the shape {@link S3Disk.list} needs. */
|
|
34
|
+
export function extractListObjectsV2FromXml(xml) {
|
|
35
|
+
const folders = matchAll(xml, /<CommonPrefixes>[\s\S]*?<Prefix>([\s\S]*?)<\/Prefix>[\s\S]*?<\/CommonPrefixes>/g).map((match) => decodeXmlEntities(match[1] ?? ''));
|
|
36
|
+
const objects = matchAll(xml, /<Contents>([\s\S]*?)<\/Contents>/g).map((match) => {
|
|
37
|
+
const block = match[1] ?? '';
|
|
38
|
+
const keyMatch = block.match(/<Key>([\s\S]*?)<\/Key>/);
|
|
39
|
+
const sizeMatch = block.match(/<Size>([\s\S]*?)<\/Size>/);
|
|
40
|
+
const lastModifiedMatch = block.match(/<LastModified>([\s\S]*?)<\/LastModified>/);
|
|
41
|
+
return {
|
|
42
|
+
key: keyMatch ? decodeXmlEntities(keyMatch[1] ?? '') : '',
|
|
43
|
+
size: sizeMatch ? Number(sizeMatch[1]) : null,
|
|
44
|
+
lastModified: lastModifiedMatch ? decodeXmlEntities(lastModifiedMatch[1] ?? '') : null,
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
const nextContinuationTokenMatch = xml.match(/<NextContinuationToken>([\s\S]*?)<\/NextContinuationToken>/);
|
|
48
|
+
const isTruncatedMatch = xml.match(/<IsTruncated>(true|false)<\/IsTruncated>/);
|
|
49
|
+
return {
|
|
50
|
+
folders,
|
|
51
|
+
objects,
|
|
52
|
+
nextContinuationToken: nextContinuationTokenMatch
|
|
53
|
+
? decodeXmlEntities(nextContinuationTokenMatch[1] ?? '')
|
|
54
|
+
: null,
|
|
55
|
+
isTruncated: isTruncatedMatch?.[1] === 'true',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function matchAll(input, regex) {
|
|
59
|
+
const matches = [];
|
|
60
|
+
const localRegex = new RegExp(regex.source, regex.flags);
|
|
61
|
+
let match = localRegex.exec(input);
|
|
62
|
+
while (match !== null) {
|
|
63
|
+
matches.push(match);
|
|
64
|
+
match = localRegex.exec(input);
|
|
65
|
+
}
|
|
66
|
+
return matches;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=xml_fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml_fallback.js","sourceRoot":"","sources":["../../../src/disks/xml_fallback.ts"],"names":[],"mappings":"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"}
|
package/dist/src/errors.d.ts
CHANGED
|
@@ -14,4 +14,38 @@ export declare class ImageProcessorMissingError extends Error {
|
|
|
14
14
|
readonly code = "E_MEDIA_IMAGE_PROCESSOR_MISSING";
|
|
15
15
|
constructor();
|
|
16
16
|
}
|
|
17
|
+
export declare class VariantNotFoundError extends Error {
|
|
18
|
+
readonly code = "E_MEDIA_VARIANT_NOT_FOUND";
|
|
19
|
+
constructor(variant: string);
|
|
20
|
+
}
|
|
21
|
+
export declare class UploadNotSupportedError extends Error {
|
|
22
|
+
readonly code = "E_MEDIA_UPLOAD_NOT_SUPPORTED";
|
|
23
|
+
constructor(disk: string, operation?: string);
|
|
24
|
+
}
|
|
25
|
+
export declare class UploadSessionNotFoundError extends Error {
|
|
26
|
+
readonly code = "E_MEDIA_UPLOAD_SESSION_NOT_FOUND";
|
|
27
|
+
constructor(id: string);
|
|
28
|
+
}
|
|
29
|
+
export declare class UploadOffsetConflictError extends Error {
|
|
30
|
+
readonly expected: number;
|
|
31
|
+
readonly received: number;
|
|
32
|
+
readonly code = "E_MEDIA_UPLOAD_OFFSET_CONFLICT";
|
|
33
|
+
constructor(expected: number, received: number);
|
|
34
|
+
}
|
|
35
|
+
export declare class UploadSessionExpiredError extends Error {
|
|
36
|
+
readonly code = "E_MEDIA_UPLOAD_SESSION_EXPIRED";
|
|
37
|
+
constructor(id: string);
|
|
38
|
+
}
|
|
39
|
+
export declare class ResumableUploadsNotConfiguredError extends Error {
|
|
40
|
+
readonly code = "E_MEDIA_RESUMABLE_NOT_CONFIGURED";
|
|
41
|
+
constructor();
|
|
42
|
+
}
|
|
43
|
+
export declare class StoreNotConfiguredError extends Error {
|
|
44
|
+
readonly code = "E_MEDIA_STORE_NOT_CONFIGURED";
|
|
45
|
+
constructor(name: string);
|
|
46
|
+
}
|
|
47
|
+
export declare class UploadSessionStoreNotConfiguredError extends Error {
|
|
48
|
+
readonly code = "E_MEDIA_UPLOAD_SESSION_STORE_NOT_CONFIGURED";
|
|
49
|
+
constructor(name: string);
|
|
50
|
+
}
|
|
17
51
|
//# sourceMappingURL=errors.d.ts.map
|
package/dist/src/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAIjD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,oCAAoC;gBACrC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAInD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,qCAAqC;;CAKnD"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAIjD;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,8BAA8B;gBAC/B,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,oCAAoC;gBACrC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAInD;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,qCAAqC;;CAKnD;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,+BAA+B;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,kCAAkC;gBACnC,IAAI,EAAE,MAAM,EAAE,SAAS,SAA4B;CAMhE;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,sCAAsC;gBACvC,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAGhD,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAH3B,QAAQ,CAAC,IAAI,oCAAoC;gBAEtC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM;CAK5B;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,oCAAoC;gBACrC,EAAE,EAAE,MAAM;CAIvB;AAED,qBAAa,kCAAmC,SAAQ,KAAK;IAC3D,QAAQ,CAAC,IAAI,sCAAsC;;CAOpD;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,kCAAkC;gBACnC,IAAI,EAAE,MAAM;CAMzB;AAED,qBAAa,oCAAqC,SAAQ,KAAK;IAC7D,QAAQ,CAAC,IAAI,iDAAiD;gBAClD,IAAI,EAAE,MAAM;CAMzB"}
|
package/dist/src/errors.js
CHANGED
|
@@ -26,4 +26,64 @@ export class ImageProcessorMissingError extends Error {
|
|
|
26
26
|
this.name = 'ImageProcessorMissingError';
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
export class VariantNotFoundError extends Error {
|
|
30
|
+
code = 'E_MEDIA_VARIANT_NOT_FOUND';
|
|
31
|
+
constructor(variant) {
|
|
32
|
+
super(`Attachment has no variant "${variant}"`);
|
|
33
|
+
this.name = 'VariantNotFoundError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class UploadNotSupportedError extends Error {
|
|
37
|
+
code = 'E_MEDIA_UPLOAD_NOT_SUPPORTED';
|
|
38
|
+
constructor(disk, operation = 'direct multipart upload') {
|
|
39
|
+
super(`Disk "${disk}" does not support ${operation}. Use a multipart-capable disk (e.g. \`disks.s3()\`) or the \`proxy\` upload mode.`);
|
|
40
|
+
this.name = 'UploadNotSupportedError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export class UploadSessionNotFoundError extends Error {
|
|
44
|
+
code = 'E_MEDIA_UPLOAD_SESSION_NOT_FOUND';
|
|
45
|
+
constructor(id) {
|
|
46
|
+
super(`Upload session not found: ${id}`);
|
|
47
|
+
this.name = 'UploadSessionNotFoundError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export class UploadOffsetConflictError extends Error {
|
|
51
|
+
expected;
|
|
52
|
+
received;
|
|
53
|
+
code = 'E_MEDIA_UPLOAD_OFFSET_CONFLICT';
|
|
54
|
+
constructor(expected, received) {
|
|
55
|
+
super(`Upload offset conflict: expected ${expected}, received ${received}`);
|
|
56
|
+
this.expected = expected;
|
|
57
|
+
this.received = received;
|
|
58
|
+
this.name = 'UploadOffsetConflictError';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export class UploadSessionExpiredError extends Error {
|
|
62
|
+
code = 'E_MEDIA_UPLOAD_SESSION_EXPIRED';
|
|
63
|
+
constructor(id) {
|
|
64
|
+
super(`Upload session has expired: ${id}`);
|
|
65
|
+
this.name = 'UploadSessionExpiredError';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class ResumableUploadsNotConfiguredError extends Error {
|
|
69
|
+
code = 'E_MEDIA_RESUMABLE_NOT_CONFIGURED';
|
|
70
|
+
constructor() {
|
|
71
|
+
super("Resumable (TUS) uploads are not configured. Set `uploads.resumable` in config/media.ts (e.g. `resumable: { store: 'lucid', stores: { lucid: uploadSessions.lucid() } }`) to enable the resumable upload session store.");
|
|
72
|
+
this.name = 'ResumableUploadsNotConfiguredError';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export class StoreNotConfiguredError extends Error {
|
|
76
|
+
code = 'E_MEDIA_STORE_NOT_CONFIGURED';
|
|
77
|
+
constructor(name) {
|
|
78
|
+
super(`Media config selects store "${name}" but no matching factory exists in \`stores\`. Add \`stores.${name}\` to config/media.ts (e.g. \`stores: { ${name}: stores.lucid() }\`), or omit \`store\` to use the in-memory store.`);
|
|
79
|
+
this.name = 'StoreNotConfiguredError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class UploadSessionStoreNotConfiguredError extends Error {
|
|
83
|
+
code = 'E_MEDIA_UPLOAD_SESSION_STORE_NOT_CONFIGURED';
|
|
84
|
+
constructor(name) {
|
|
85
|
+
super(`Media config selects resumable session store "${name}" but no matching factory exists in \`uploads.resumable.stores\`. Add \`uploads.resumable.stores.${name}\` to config/media.ts (e.g. \`stores: { ${name}: uploadSessions.lucid() }\`), or omit \`store\` to use the in-memory session store.`);
|
|
86
|
+
this.name = 'UploadSessionStoreNotConfiguredError';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
29
89
|
//# sourceMappingURL=errors.js.map
|
package/dist/src/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAG,0BAA0B,CAAC;IAC3C,YAAY,UAAkB,EAAE,QAAgB;QAC9C,KAAK,CAAC,cAAc,QAAQ,mCAAmC,UAAU,GAAG,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,GAAG,0BAA0B,CAAC;IAC3C,YAAY,EAAU;QACpB,KAAK,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,gCAAgC,CAAC;IACjD,YAAY,UAAkB,EAAE,UAAkB;QAChD,KAAK,CAAC,eAAe,UAAU,oCAAoC,UAAU,GAAG,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,GAAG,iCAAiC,CAAC;IAClD;QACE,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAG,0BAA0B,CAAC;IAC3C,YAAY,UAAkB,EAAE,QAAgB;QAC9C,KAAK,CAAC,cAAc,QAAQ,mCAAmC,UAAU,GAAG,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,GAAG,0BAA0B,CAAC;IAC3C,YAAY,EAAU;QACpB,KAAK,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,gCAAgC,CAAC;IACjD,YAAY,UAAkB,EAAE,UAAkB;QAChD,KAAK,CAAC,eAAe,UAAU,oCAAoC,UAAU,GAAG,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,GAAG,iCAAiC,CAAC;IAClD;QACE,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpC,IAAI,GAAG,2BAA2B,CAAC;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,8BAA8B,OAAO,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,IAAI,GAAG,8BAA8B,CAAC;IAC/C,YAAY,IAAY,EAAE,SAAS,GAAG,yBAAyB;QAC7D,KAAK,CACH,SAAS,IAAI,sBAAsB,SAAS,oFAAoF,CACjI,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAC1C,IAAI,GAAG,kCAAkC,CAAC;IACnD,YAAY,EAAU;QACpB,KAAK,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAGvC;IACA;IAHF,IAAI,GAAG,gCAAgC,CAAC;IACjD,YACW,QAAgB,EAChB,QAAgB;QAEzB,KAAK,CAAC,oCAAoC,QAAQ,cAAc,QAAQ,EAAE,CAAC,CAAC;QAHnE,aAAQ,GAAR,QAAQ,CAAQ;QAChB,aAAQ,GAAR,QAAQ,CAAQ;QAGzB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,gCAAgC,CAAC;IACjD,YAAY,EAAU;QACpB,KAAK,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,kCAAmC,SAAQ,KAAK;IAClD,IAAI,GAAG,kCAAkC,CAAC;IACnD;QACE,KAAK,CACH,wNAAwN,CACzN,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,oCAAoC,CAAC;IACnD,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,IAAI,GAAG,8BAA8B,CAAC;IAC/C,YAAY,IAAY;QACtB,KAAK,CACH,+BAA+B,IAAI,gEAAgE,IAAI,2CAA2C,IAAI,sEAAsE,CAC7N,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,oCAAqC,SAAQ,KAAK;IACpD,IAAI,GAAG,6CAA6C,CAAC;IAC9D,YAAY,IAAY;QACtB,KAAK,CACH,iDAAiD,IAAI,oGAAoG,IAAI,2CAA2C,IAAI,sFAAsF,CACnS,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sCAAsC,CAAC;IACrD,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Disk, ExtendedDisk } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Structural guard: does this disk implement the optional {@link ExtendedDisk} surface (copy/move,
|
|
4
|
+
* batched delete, list, size/stat, plus a capabilities descriptor)? The base {@link Disk} contract
|
|
5
|
+
* deliberately omits these, so callers detect the richer operations here at runtime (the bundled
|
|
6
|
+
* `disks.s3()` disk provides them; the in-memory/Drive disks do not) rather than depending on them
|
|
7
|
+
* statically. A disk qualifies when it exposes the whole surface.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isExtendedDisk(disk: Disk): disk is Disk & ExtendedDisk;
|
|
10
|
+
//# sourceMappingURL=extended_disk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended_disk.d.ts","sourceRoot":"","sources":["../../src/extended_disk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,YAAY,CAYtE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural guard: does this disk implement the optional {@link ExtendedDisk} surface (copy/move,
|
|
3
|
+
* batched delete, list, size/stat, plus a capabilities descriptor)? The base {@link Disk} contract
|
|
4
|
+
* deliberately omits these, so callers detect the richer operations here at runtime (the bundled
|
|
5
|
+
* `disks.s3()` disk provides them; the in-memory/Drive disks do not) rather than depending on them
|
|
6
|
+
* statically. A disk qualifies when it exposes the whole surface.
|
|
7
|
+
*/
|
|
8
|
+
export function isExtendedDisk(disk) {
|
|
9
|
+
const d = disk;
|
|
10
|
+
return (typeof d.copy === 'function' &&
|
|
11
|
+
typeof d.move === 'function' &&
|
|
12
|
+
typeof d.deleteMany === 'function' &&
|
|
13
|
+
typeof d.list === 'function' &&
|
|
14
|
+
typeof d.size === 'function' &&
|
|
15
|
+
typeof d.stat === 'function' &&
|
|
16
|
+
typeof d.capabilities === 'object' &&
|
|
17
|
+
d.capabilities !== null);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=extended_disk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended_disk.js","sourceRoot":"","sources":["../../src/extended_disk.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,MAAM,CAAC,GAAG,IAA6B,CAAC;IACxC,OAAO,CACL,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAC5B,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAC5B,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU;QAClC,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAC5B,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAC5B,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU;QAC5B,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ;QAClC,CAAC,CAAC,YAAY,KAAK,IAAI,CACxB,CAAC;AACJ,CAAC"}
|