@numa-tech/numa 1.18.0 → 1.20.0
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 +58 -10
- package/THIRD_PARTY_NOTICES.md +50 -0
- package/dist/oss/commands.d.ts +2 -1
- package/dist/oss/commands.js +44 -23
- package/dist/oss/commands.js.map +1 -1
- package/dist/oss/file-operations.d.ts +57 -0
- package/dist/oss/file-operations.js +269 -0
- package/dist/oss/file-operations.js.map +1 -0
- package/dist/oss/local-picker.d.ts +25 -0
- package/dist/oss/local-picker.js +251 -0
- package/dist/oss/local-picker.js.map +1 -0
- package/dist/oss/transfer-paths.d.ts +16 -0
- package/dist/oss/transfer-paths.js +131 -0
- package/dist/oss/transfer-paths.js.map +1 -0
- package/dist/oss/transfer-queue.d.ts +62 -0
- package/dist/oss/transfer-queue.js +349 -0
- package/dist/oss/transfer-queue.js.map +1 -0
- package/dist/oss/transfer-types.d.ts +54 -0
- package/dist/oss/transfer-types.js +2 -0
- package/dist/oss/transfer-types.js.map +1 -0
- package/dist/oss/transfer-worker.d.ts +3 -0
- package/dist/oss/transfer-worker.js +415 -0
- package/dist/oss/transfer-worker.js.map +1 -0
- package/dist/oss/transfers.d.ts +23 -0
- package/dist/oss/transfers.js +111 -0
- package/dist/oss/transfers.js.map +1 -1
- package/dist/oss/web-icons.d.ts +3 -0
- package/dist/oss/web-icons.js +4 -0
- package/dist/oss/web-icons.js.map +1 -0
- package/dist/oss/web-page.js +510 -65
- package/dist/oss/web-page.js.map +1 -1
- package/dist/oss/web-service.d.ts +45 -0
- package/dist/oss/web-service.js +107 -0
- package/dist/oss/web-service.js.map +1 -0
- package/dist/oss/web.d.ts +16 -0
- package/dist/oss/web.js +320 -79
- package/dist/oss/web.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { constants } from 'node:fs';
|
|
2
|
+
import { open, lstat, mkdir, link, unlink } from 'node:fs/promises';
|
|
3
|
+
import { dirname, basename, resolve, relative, isAbsolute, join, parse } from 'node:path';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import { Readable } from 'node:stream';
|
|
6
|
+
import OSS from 'ali-oss';
|
|
7
|
+
import { OssError } from './errors.js';
|
|
8
|
+
import { ossTransferOptions } from './transfers.js';
|
|
9
|
+
const PART = 8 * 1024 * 1024;
|
|
10
|
+
const fail = (message, code = 'oss_transfer_failed') => new OssError(message, code);
|
|
11
|
+
function check(ctx) { if (ctx.signal.aborted)
|
|
12
|
+
throw fail('Transfer paused.', 'oss_transfer_paused'); }
|
|
13
|
+
function same(a, b) { return a.dev === b.dev && a.ino === b.ino && a.size === b.size && a.mtimeMs === b.mtimeMs; }
|
|
14
|
+
function code(error) { return error?.code; }
|
|
15
|
+
function headers(res) { return Object.fromEntries(Object.entries(res?.headers ?? {}).map(([k, v]) => [k.toLowerCase(), String(v)])); }
|
|
16
|
+
/** Reject symlinks in every component, including ancestors of the chosen root. */
|
|
17
|
+
async function safePath(job, createParents = false) {
|
|
18
|
+
const root = resolve(job.localRoot), path = resolve(job.localPath), rel = relative(root, path);
|
|
19
|
+
if (!isAbsolute(job.localRoot) || !isAbsolute(job.localPath) || !rel || rel === '..' || rel.startsWith(`..${parse(path).root === '/' ? '/' : '\\'}`) || isAbsolute(rel))
|
|
20
|
+
throw fail('Local path is outside the selected directory.', 'oss_path_invalid');
|
|
21
|
+
let current = parse(path).root;
|
|
22
|
+
const components = relative(current, path).split(/[\\/]/u);
|
|
23
|
+
for (let i = 0; i < components.length; i++) {
|
|
24
|
+
current = join(current, components[i]);
|
|
25
|
+
let st;
|
|
26
|
+
try {
|
|
27
|
+
st = await lstat(current);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
if (code(e) !== 'ENOENT')
|
|
31
|
+
throw e;
|
|
32
|
+
if (i === components.length - 1)
|
|
33
|
+
return;
|
|
34
|
+
if (!createParents)
|
|
35
|
+
throw fail('Local parent directory is missing.', 'oss_path_invalid');
|
|
36
|
+
try {
|
|
37
|
+
await mkdir(current, { mode: 0o700 });
|
|
38
|
+
}
|
|
39
|
+
catch (mkdirError) {
|
|
40
|
+
if (code(mkdirError) !== 'EEXIST')
|
|
41
|
+
throw mkdirError;
|
|
42
|
+
}
|
|
43
|
+
st = await lstat(current);
|
|
44
|
+
}
|
|
45
|
+
if (st.isSymbolicLink())
|
|
46
|
+
throw fail('Local path contains a symbolic link.', 'oss_path_invalid');
|
|
47
|
+
if (i < components.length - 1 && !st.isDirectory())
|
|
48
|
+
throw fail('Local parent is not a directory.', 'oss_path_invalid');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function validateCheckpoint(job) {
|
|
52
|
+
const cp = job.checkpoint;
|
|
53
|
+
if (!cp)
|
|
54
|
+
return;
|
|
55
|
+
if (cp.kind !== job.direction || !Number.isSafeInteger(cp.partSize) || cp.partSize < 100 * 1024 || cp.partSize > 5 * 1024 ** 3 || !Array.isArray(cp.parts))
|
|
56
|
+
throw fail('Invalid transfer checkpoint.', 'oss_checkpoint_invalid');
|
|
57
|
+
const count = Math.ceil(job.size / cp.partSize);
|
|
58
|
+
if (count > 10000)
|
|
59
|
+
throw fail('Invalid transfer checkpoint.', 'oss_checkpoint_invalid');
|
|
60
|
+
const numbers = cp.kind === 'upload' ? cp.parts.map(p => p.number - 1) : cp.parts;
|
|
61
|
+
if (new Set(numbers).size !== numbers.length || numbers.some(n => !Number.isInteger(n) || n < 0 || n >= count)
|
|
62
|
+
|| (cp.kind === 'upload' && (typeof cp.uploadId !== 'string' || (job.size > 0 && !cp.uploadId) || cp.parts.some(p => typeof p.etag !== 'string' || !p.etag)))
|
|
63
|
+
|| (cp.kind === 'download' && (typeof cp.etag !== 'string' || !cp.etag)))
|
|
64
|
+
throw fail('Invalid transfer checkpoint.', 'oss_checkpoint_invalid');
|
|
65
|
+
}
|
|
66
|
+
async function syncDirectory(path) {
|
|
67
|
+
let directory;
|
|
68
|
+
try {
|
|
69
|
+
directory = await open(path, constants.O_RDONLY);
|
|
70
|
+
await directory.sync();
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
if (process.platform !== 'win32' || !['EPERM', 'EISDIR', 'EINVAL', 'ENOTSUP'].includes(code(e) ?? ''))
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
await directory?.close();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function exists(path) { try {
|
|
81
|
+
return await lstat(path);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
if (code(e) === 'ENOENT')
|
|
85
|
+
return undefined;
|
|
86
|
+
throw e;
|
|
87
|
+
} }
|
|
88
|
+
async function concurrent(parts, ctx, work) {
|
|
89
|
+
let next = 0;
|
|
90
|
+
let failure;
|
|
91
|
+
await Promise.all(Array.from({ length: Math.min(3, parts.length) }, async () => {
|
|
92
|
+
while (!failure && !ctx.signal.aborted) {
|
|
93
|
+
const n = parts[next++];
|
|
94
|
+
if (n === undefined)
|
|
95
|
+
return;
|
|
96
|
+
try {
|
|
97
|
+
await work(n);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
failure ??= e;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}));
|
|
104
|
+
if (failure)
|
|
105
|
+
throw failure;
|
|
106
|
+
check(ctx);
|
|
107
|
+
}
|
|
108
|
+
async function retry(ctx, operation) {
|
|
109
|
+
for (let attempt = 0;; attempt++) {
|
|
110
|
+
check(ctx);
|
|
111
|
+
try {
|
|
112
|
+
return await operation();
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
check(ctx);
|
|
116
|
+
const status = e?.status;
|
|
117
|
+
if (e instanceof OssError || attempt >= 2 || !(status === 429 || (status !== undefined && status >= 500) || ['ECONNRESET', 'ETIMEDOUT', 'EPIPE'].includes(code(e) ?? '')))
|
|
118
|
+
throw e;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function bindAbort(ctx, stream) {
|
|
123
|
+
const abort = () => stream.destroy(fail('Transfer paused.', 'oss_transfer_paused'));
|
|
124
|
+
stream.on('error', () => undefined);
|
|
125
|
+
ctx.signal.addEventListener('abort', abort, { once: true });
|
|
126
|
+
if (ctx.signal.aborted)
|
|
127
|
+
abort();
|
|
128
|
+
return () => ctx.signal.removeEventListener('abort', abort);
|
|
129
|
+
}
|
|
130
|
+
export function createTransferWorker({ clientFactory = options => new OSS(options) } = {}) {
|
|
131
|
+
async function client(job, ctx, operation, allowAborted = false) {
|
|
132
|
+
if (!allowAborted)
|
|
133
|
+
check(ctx);
|
|
134
|
+
const scoped = ossTransferOptions(await ctx.session(), job.key, operation);
|
|
135
|
+
if (!allowAborted)
|
|
136
|
+
check(ctx);
|
|
137
|
+
return clientFactory(scoped.options);
|
|
138
|
+
}
|
|
139
|
+
async function upload(job, ctx) {
|
|
140
|
+
await safePath(job);
|
|
141
|
+
const file = await open(job.localPath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
142
|
+
try {
|
|
143
|
+
const verify = async () => { await safePath(job); const st = await file.stat(); const current = await lstat(job.localPath); if (!st.isFile() || !job.source || !same(st, job.source) || !same(current, job.source) || st.size !== job.size)
|
|
144
|
+
throw fail('Upload source changed.', 'oss_source_changed'); };
|
|
145
|
+
await verify();
|
|
146
|
+
if (job.checkpoint && job.checkpoint.kind !== 'upload')
|
|
147
|
+
throw fail('Invalid transfer checkpoint.');
|
|
148
|
+
let cp = job.checkpoint;
|
|
149
|
+
if (cp?.committing) {
|
|
150
|
+
try {
|
|
151
|
+
const head = await (await client(job, ctx, 'read')).head(job.key);
|
|
152
|
+
const h = headers(head.res);
|
|
153
|
+
if ((head.meta?.['numa-transfer-id'] ?? h['x-oss-meta-numa-transfer-id']) === job.id && Number(h['content-length']) === job.size) {
|
|
154
|
+
ctx.progress(job.size);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
throw fail('Destination already exists.', 'oss_output_exists');
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
if (e.status !== 404)
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!cp) {
|
|
165
|
+
const partSize = Math.max(PART, Math.ceil(job.size / 10000));
|
|
166
|
+
if (partSize > 5 * 1024 ** 3)
|
|
167
|
+
throw fail('Upload exceeds the multipart size limit.', 'oss_input_invalid');
|
|
168
|
+
const uploadId = job.size ? (await (await client(job, ctx, 'write')).initMultipartUpload(job.key, { headers: { 'x-oss-meta-numa-transfer-id': job.id } })).uploadId : '';
|
|
169
|
+
cp = { kind: 'upload', uploadId, partSize, parts: [] };
|
|
170
|
+
job.checkpoint = cp;
|
|
171
|
+
await ctx.save();
|
|
172
|
+
}
|
|
173
|
+
const checkpoint = cp;
|
|
174
|
+
const count = Math.ceil(job.size / cp.partSize);
|
|
175
|
+
const progress = () => ctx.progress(checkpoint.parts.reduce((sum, p) => sum + Math.min(checkpoint.partSize, job.size - (p.number - 1) * checkpoint.partSize), 0));
|
|
176
|
+
progress();
|
|
177
|
+
await concurrent(Array.from({ length: count }, (_, i) => i + 1).filter(n => !checkpoint.parts.some(p => p.number === n)), ctx, async (n) => {
|
|
178
|
+
const result = await retry(ctx, async () => {
|
|
179
|
+
await verify();
|
|
180
|
+
const sdk = await client(job, ctx, 'write');
|
|
181
|
+
const start = (n - 1) * checkpoint.partSize, end = Math.min(job.size, start + checkpoint.partSize);
|
|
182
|
+
const stream = Readable.from((async function* () { let position = start; while (position < end) {
|
|
183
|
+
check(ctx);
|
|
184
|
+
const buffer = Buffer.alloc(Math.min(256 * 1024, end - position));
|
|
185
|
+
const { bytesRead } = await file.read(buffer, 0, buffer.length, position);
|
|
186
|
+
if (!bytesRead)
|
|
187
|
+
throw fail('Upload source changed.', 'oss_source_changed');
|
|
188
|
+
position += bytesRead;
|
|
189
|
+
yield buffer.subarray(0, bytesRead);
|
|
190
|
+
} })());
|
|
191
|
+
const cleanup = bindAbort(ctx, stream);
|
|
192
|
+
try {
|
|
193
|
+
return await sdk.uploadPart(job.key, checkpoint.uploadId, n, stream, start, end);
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
cleanup();
|
|
197
|
+
stream.destroy();
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
if (!result.etag)
|
|
201
|
+
throw fail('OSS returned no part ETag.');
|
|
202
|
+
checkpoint.parts.push({ number: n, etag: result.etag });
|
|
203
|
+
await ctx.save();
|
|
204
|
+
progress();
|
|
205
|
+
});
|
|
206
|
+
await verify();
|
|
207
|
+
check(ctx);
|
|
208
|
+
checkpoint.committing = true;
|
|
209
|
+
await ctx.save();
|
|
210
|
+
const sdk = await client(job, ctx, 'write');
|
|
211
|
+
if (job.size === 0)
|
|
212
|
+
await sdk.put(job.key, Buffer.alloc(0), { headers: { 'x-oss-meta-numa-transfer-id': job.id, 'x-oss-forbid-overwrite': 'true' } });
|
|
213
|
+
else
|
|
214
|
+
await sdk.completeMultipartUpload(job.key, checkpoint.uploadId, checkpoint.parts, { headers: { 'x-oss-forbid-overwrite': 'true' } });
|
|
215
|
+
ctx.progress(job.size);
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
await file.close();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function ownedTemp(job) {
|
|
222
|
+
const cp = job.checkpoint;
|
|
223
|
+
if (cp?.kind !== 'download' || dirname(cp.tempPath) !== dirname(job.localPath) || !/^\.numa-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.part$/u.test(basename(cp.tempPath)) || cp.tempDev === undefined || cp.tempIno === undefined)
|
|
224
|
+
throw fail('Invalid download temporary file.', 'oss_path_invalid');
|
|
225
|
+
await safePath(job);
|
|
226
|
+
const f = await open(cp.tempPath, constants.O_RDWR | constants.O_NOFOLLOW);
|
|
227
|
+
const st = await f.stat();
|
|
228
|
+
if (!st.isFile() || st.dev !== cp.tempDev || st.ino !== cp.tempIno || st.size !== job.size) {
|
|
229
|
+
await f.close();
|
|
230
|
+
throw fail('Download temporary file changed.', 'oss_source_changed');
|
|
231
|
+
}
|
|
232
|
+
return f;
|
|
233
|
+
}
|
|
234
|
+
async function download(job, ctx) {
|
|
235
|
+
await safePath(job, true);
|
|
236
|
+
if (job.checkpoint && job.checkpoint.kind !== 'download')
|
|
237
|
+
throw fail('Invalid transfer checkpoint.');
|
|
238
|
+
let cp = job.checkpoint;
|
|
239
|
+
const destination = await exists(job.localPath);
|
|
240
|
+
if (destination) {
|
|
241
|
+
if (cp?.committing && destination.dev === cp.tempDev && destination.ino === cp.tempIno && destination.size === job.size) {
|
|
242
|
+
await cleanupTemp(job);
|
|
243
|
+
ctx.progress(job.size);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
throw fail('Destination already exists.', 'oss_output_exists');
|
|
247
|
+
}
|
|
248
|
+
const head = await (await client(job, ctx, 'read')).head(job.key);
|
|
249
|
+
const h = headers(head.res);
|
|
250
|
+
if (!h.etag || Number(h['content-length']) !== job.size || (cp && cp.etag !== h.etag))
|
|
251
|
+
throw fail('Remote object changed.', 'oss_remote_changed');
|
|
252
|
+
let file;
|
|
253
|
+
if (!cp) {
|
|
254
|
+
const tempPath = join(dirname(job.localPath), `.numa-${randomUUID()}.part`);
|
|
255
|
+
file = await open(tempPath, constants.O_RDWR | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
256
|
+
try {
|
|
257
|
+
await file.truncate(job.size);
|
|
258
|
+
await file.sync();
|
|
259
|
+
await syncDirectory(dirname(tempPath));
|
|
260
|
+
const st = await file.stat();
|
|
261
|
+
cp = { kind: 'download', partSize: Math.max(PART, Math.ceil(job.size / 10000)), etag: h.etag, parts: [], tempPath, tempDev: st.dev, tempIno: st.ino };
|
|
262
|
+
job.checkpoint = cp;
|
|
263
|
+
await ctx.save();
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
await file.close();
|
|
267
|
+
throw e;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else
|
|
271
|
+
file = await ownedTemp(job);
|
|
272
|
+
const checkpoint = cp;
|
|
273
|
+
try {
|
|
274
|
+
const progress = () => ctx.progress(checkpoint.parts.reduce((sum, n) => sum + Math.min(checkpoint.partSize, job.size - n * checkpoint.partSize), 0));
|
|
275
|
+
progress();
|
|
276
|
+
await concurrent(Array.from({ length: Math.ceil(job.size / checkpoint.partSize) }, (_, i) => i).filter(n => !checkpoint.parts.includes(n)), ctx, async (n) => {
|
|
277
|
+
await retry(ctx, async () => {
|
|
278
|
+
const start = n * checkpoint.partSize, end = Math.min(job.size, start + checkpoint.partSize) - 1;
|
|
279
|
+
const result = await (await client(job, ctx, 'read')).getStream(job.key, { headers: { Range: `bytes=${start}-${end}`, 'If-Match': checkpoint.etag } });
|
|
280
|
+
const stream = result.stream;
|
|
281
|
+
const cleanup = bindAbort(ctx, stream);
|
|
282
|
+
try {
|
|
283
|
+
const rh = headers(result.res);
|
|
284
|
+
if (result.res.status !== 206 || rh['content-range'] !== `bytes ${start}-${end}/${job.size}` || (rh.etag && rh.etag !== checkpoint.etag))
|
|
285
|
+
throw fail('Remote object or byte range changed.', 'oss_remote_changed');
|
|
286
|
+
let position = start;
|
|
287
|
+
for await (const data of stream) {
|
|
288
|
+
check(ctx);
|
|
289
|
+
const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
290
|
+
if (position + chunk.length > end + 1)
|
|
291
|
+
throw fail('Invalid download byte count.');
|
|
292
|
+
let offset = 0;
|
|
293
|
+
while (offset < chunk.length) {
|
|
294
|
+
const { bytesWritten } = await file.write(chunk, offset, chunk.length - offset, position);
|
|
295
|
+
if (!bytesWritten)
|
|
296
|
+
throw fail('Cannot write download file.');
|
|
297
|
+
offset += bytesWritten;
|
|
298
|
+
position += bytesWritten;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (position !== end + 1)
|
|
302
|
+
throw fail('Incomplete download byte range.');
|
|
303
|
+
await file.sync();
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
cleanup();
|
|
307
|
+
stream.destroy();
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
checkpoint.parts.push(n);
|
|
311
|
+
await ctx.save();
|
|
312
|
+
progress();
|
|
313
|
+
});
|
|
314
|
+
check(ctx);
|
|
315
|
+
await safePath(job);
|
|
316
|
+
const identity = await lstat(checkpoint.tempPath);
|
|
317
|
+
if (identity.dev !== checkpoint.tempDev || identity.ino !== checkpoint.tempIno)
|
|
318
|
+
throw fail('Download temporary file changed.', 'oss_source_changed');
|
|
319
|
+
checkpoint.committing = true;
|
|
320
|
+
await ctx.save();
|
|
321
|
+
await file.sync();
|
|
322
|
+
await link(checkpoint.tempPath, job.localPath);
|
|
323
|
+
await syncDirectory(dirname(job.localPath));
|
|
324
|
+
await cleanupTemp(job);
|
|
325
|
+
ctx.progress(job.size);
|
|
326
|
+
}
|
|
327
|
+
finally {
|
|
328
|
+
await file.close();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async function cleanupTemp(job) {
|
|
332
|
+
const cp = job.checkpoint;
|
|
333
|
+
if (cp?.kind !== 'download')
|
|
334
|
+
return;
|
|
335
|
+
await safePath(job);
|
|
336
|
+
const st = await exists(cp.tempPath);
|
|
337
|
+
if (!st)
|
|
338
|
+
return;
|
|
339
|
+
const f = await ownedTemp(job);
|
|
340
|
+
await f.close();
|
|
341
|
+
await unlink(cp.tempPath);
|
|
342
|
+
}
|
|
343
|
+
return {
|
|
344
|
+
async run(job, ctx) { try {
|
|
345
|
+
check(ctx);
|
|
346
|
+
if (!Number.isSafeInteger(job.size) || job.size < 0)
|
|
347
|
+
throw fail('Invalid transfer size.', 'oss_input_invalid');
|
|
348
|
+
validateCheckpoint(job);
|
|
349
|
+
await (job.direction === 'upload' ? upload(job, ctx) : download(job, ctx));
|
|
350
|
+
}
|
|
351
|
+
catch (e) {
|
|
352
|
+
if (e instanceof OssError)
|
|
353
|
+
throw e;
|
|
354
|
+
if (code(e) === 'EEXIST' || e.status === 409)
|
|
355
|
+
throw fail('Destination already exists.', 'oss_output_exists');
|
|
356
|
+
if (e.status === 412)
|
|
357
|
+
throw fail('Remote object changed.', 'oss_remote_changed');
|
|
358
|
+
throw fail('OSS transfer failed. Retry or resume the transfer.');
|
|
359
|
+
} },
|
|
360
|
+
async cancel(job, ctx) {
|
|
361
|
+
try {
|
|
362
|
+
validateCheckpoint(job);
|
|
363
|
+
const cp = job.checkpoint;
|
|
364
|
+
if (cp?.kind === 'upload') {
|
|
365
|
+
if (cp.committing) {
|
|
366
|
+
let head;
|
|
367
|
+
try {
|
|
368
|
+
head = await (await client(job, ctx, 'read', true)).head(job.key);
|
|
369
|
+
}
|
|
370
|
+
catch (e) {
|
|
371
|
+
if (e.status !== 404)
|
|
372
|
+
throw e;
|
|
373
|
+
}
|
|
374
|
+
if (head) {
|
|
375
|
+
const h = headers(head.res);
|
|
376
|
+
if ((head.meta?.['numa-transfer-id'] ?? h['x-oss-meta-numa-transfer-id']) === job.id && Number(h['content-length']) === job.size) {
|
|
377
|
+
job.status = 'completed';
|
|
378
|
+
ctx.progress(job.size);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
if (cp.uploadId) {
|
|
384
|
+
try {
|
|
385
|
+
await (await client(job, ctx, 'write', true)).abortMultipartUpload(job.key, cp.uploadId);
|
|
386
|
+
}
|
|
387
|
+
catch (e) {
|
|
388
|
+
if (e.status !== 404)
|
|
389
|
+
throw e;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
else if (cp?.kind === 'download') {
|
|
394
|
+
if (cp.committing) {
|
|
395
|
+
await safePath(job);
|
|
396
|
+
const final = await exists(job.localPath);
|
|
397
|
+
if (final?.isFile() && final.dev === cp.tempDev && final.ino === cp.tempIno && final.size === job.size) {
|
|
398
|
+
await cleanupTemp(job);
|
|
399
|
+
job.status = 'completed';
|
|
400
|
+
ctx.progress(job.size);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
await cleanupTemp(job);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
catch (e) {
|
|
408
|
+
if (e instanceof OssError)
|
|
409
|
+
throw e;
|
|
410
|
+
throw fail('Unable to clean up the cancelled transfer.', 'oss_transfer_cleanup_failed');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
//# sourceMappingURL=transfer-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transfer-worker.js","sourceRoot":"","sources":["../../src/oss/transfer-worker.ts"],"names":[],"mappings":"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"}
|
package/dist/oss/transfers.d.ts
CHANGED
|
@@ -24,6 +24,15 @@ export interface OssObjectMetadata {
|
|
|
24
24
|
etag?: string;
|
|
25
25
|
lastModified?: string;
|
|
26
26
|
metadata: Record<string, string>;
|
|
27
|
+
storageClass?: string;
|
|
28
|
+
objectType?: string;
|
|
29
|
+
versionId?: string;
|
|
30
|
+
crc64?: string;
|
|
31
|
+
cacheControl?: string;
|
|
32
|
+
contentDisposition?: string;
|
|
33
|
+
contentEncoding?: string;
|
|
34
|
+
expires?: string;
|
|
35
|
+
serverSideEncryption?: string;
|
|
27
36
|
}
|
|
28
37
|
export declare class OssTransferClient {
|
|
29
38
|
private readonly clientFactory;
|
|
@@ -47,10 +56,19 @@ export declare class OssTransferClient {
|
|
|
47
56
|
key: string;
|
|
48
57
|
sizeBytes: number;
|
|
49
58
|
}>;
|
|
59
|
+
createDirectory(session: AccessSession, key: string): Promise<void>;
|
|
60
|
+
/** Copies on OSS, without downloading bytes through the browser or CLI. */
|
|
61
|
+
copy(session: AccessSession, source: string, target: string, getSession?: () => Promise<AccessSession>): Promise<OssObjectMetadata>;
|
|
62
|
+
removeBatch(session: AccessSession, keys: string[]): Promise<{
|
|
63
|
+
deleted: string[];
|
|
64
|
+
failed: string[];
|
|
65
|
+
}>;
|
|
50
66
|
remove(session: AccessSession, key: string): Promise<{
|
|
51
67
|
key: string;
|
|
52
68
|
}>;
|
|
53
69
|
}
|
|
70
|
+
/** Unsigned public-network address; object ACLs still govern anonymous access. */
|
|
71
|
+
export declare function ossObjectPublicUrl(session: AccessSession, key: string): string;
|
|
54
72
|
export declare function ossSessionCapabilities(session: AccessSession): {
|
|
55
73
|
root: string;
|
|
56
74
|
list: boolean;
|
|
@@ -59,3 +77,8 @@ export declare function ossSessionCapabilities(session: AccessSession): {
|
|
|
59
77
|
delete: boolean;
|
|
60
78
|
};
|
|
61
79
|
export declare function sessionMetadata(session: AccessSession): Record<string, unknown>;
|
|
80
|
+
/** Validate every refreshed session before background transfer requests. */
|
|
81
|
+
export declare function ossTransferOptions(session: AccessSession, key: string, operation: "read" | "write" | "delete" | "list"): {
|
|
82
|
+
key: string;
|
|
83
|
+
options: OSS.Options;
|
|
84
|
+
};
|
package/dist/oss/transfers.js
CHANGED
|
@@ -239,6 +239,15 @@ export class OssTransferClient {
|
|
|
239
239
|
contentLength: header("content-length") === undefined ? undefined : Number(header("content-length")),
|
|
240
240
|
etag: header("etag"),
|
|
241
241
|
lastModified: header("last-modified"),
|
|
242
|
+
storageClass: header("x-oss-storage-class"),
|
|
243
|
+
objectType: header("x-oss-object-type"),
|
|
244
|
+
versionId: header("x-oss-version-id"),
|
|
245
|
+
crc64: header("x-oss-hash-crc64ecma"),
|
|
246
|
+
cacheControl: header("cache-control"),
|
|
247
|
+
contentDisposition: header("content-disposition"),
|
|
248
|
+
contentEncoding: header("content-encoding"),
|
|
249
|
+
expires: header("expires"),
|
|
250
|
+
serverSideEncryption: header("x-oss-server-side-encryption"),
|
|
242
251
|
metadata: Object.fromEntries(Object.entries(meta).filter((entry) => typeof entry[1] === "string"))
|
|
243
252
|
};
|
|
244
253
|
}
|
|
@@ -303,6 +312,93 @@ export class OssTransferClient {
|
|
|
303
312
|
throw transferError("upload", error);
|
|
304
313
|
}
|
|
305
314
|
}
|
|
315
|
+
async createDirectory(session, key) {
|
|
316
|
+
const checked = ossTransferOptions(session, key, "write");
|
|
317
|
+
if (!key.endsWith("/") || key === ossSessionCapabilities(session).root) {
|
|
318
|
+
throw new OssError("Invalid directory", "oss_input_invalid", 400);
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
await this.clientFactory(checked.options).put(checked.key, Buffer.alloc(0), { headers: { "x-oss-forbid-overwrite": "true" } });
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
throw transferError("mkdir", error);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/** Copies on OSS, without downloading bytes through the browser or CLI. */
|
|
328
|
+
async copy(session, source, target, getSession = async () => session) {
|
|
329
|
+
ossTransferOptions(session, source, "read");
|
|
330
|
+
ossTransferOptions(session, target, "write");
|
|
331
|
+
if (source === target)
|
|
332
|
+
throw new OssError("Same source and target", "oss_input_invalid", 400);
|
|
333
|
+
const original = await this.stat(session, source);
|
|
334
|
+
if (!original.etag || !Number.isSafeInteger(original.contentLength) || original.contentLength < 0) {
|
|
335
|
+
throw new OssError("Missing source identity", "oss_source_changed", 409);
|
|
336
|
+
}
|
|
337
|
+
const client = async () => {
|
|
338
|
+
const fresh = await getSession();
|
|
339
|
+
if (fresh.bucketName !== session.bucketName || fresh.region !== session.region || fresh.grantId !== session.grantId) {
|
|
340
|
+
throw new OssError("Scope changed", "oss_web_scope_changed", 409);
|
|
341
|
+
}
|
|
342
|
+
ossTransferOptions(fresh, source, "read");
|
|
343
|
+
return this.clientFactory(ossTransferOptions(fresh, target, "write").options);
|
|
344
|
+
};
|
|
345
|
+
const conditional = { "x-oss-copy-source-if-match": original.etag };
|
|
346
|
+
const noOverwrite = { "x-oss-forbid-overwrite": "true" };
|
|
347
|
+
if (original.contentLength <= 1024 ** 3) {
|
|
348
|
+
try {
|
|
349
|
+
const result = await (await client()).copy(target, source, { headers: { ...conditional, ...noOverwrite } });
|
|
350
|
+
if (result.res.status !== 200)
|
|
351
|
+
throw new OssError("Copy not completed", "oss_transfer_failed", 502);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
throw transferError("copy", error);
|
|
355
|
+
}
|
|
356
|
+
return original;
|
|
357
|
+
}
|
|
358
|
+
const metadata = {};
|
|
359
|
+
for (const [header, value] of Object.entries({ "cache-control": original.cacheControl, "content-disposition": original.contentDisposition,
|
|
360
|
+
"content-encoding": original.contentEncoding, expires: original.expires }))
|
|
361
|
+
if (value)
|
|
362
|
+
metadata[header] = value;
|
|
363
|
+
const initialClient = await client();
|
|
364
|
+
const upload = await initialClient.initMultipartUpload(target, { mime: original.contentType, meta: original.metadata, headers: metadata });
|
|
365
|
+
try {
|
|
366
|
+
const parts = [];
|
|
367
|
+
// At most 10,000 parts, and bounded request sizes for large objects.
|
|
368
|
+
const partSize = Math.max(64 * 1024 ** 2, Math.ceil(original.contentLength / 10_000));
|
|
369
|
+
for (let start = 0; start < original.contentLength; start += partSize) {
|
|
370
|
+
const number = parts.length + 1;
|
|
371
|
+
const part = await (await client()).uploadPartCopy(target, upload.uploadId, number, `${start}-${Math.min(start + partSize, original.contentLength) - 1}`, { sourceKey: source, sourceBucketName: session.bucketName }, { headers: { ...conditional } });
|
|
372
|
+
parts.push({ number, etag: part.etag });
|
|
373
|
+
}
|
|
374
|
+
await (await client()).completeMultipartUpload(target, upload.uploadId, parts, { headers: noOverwrite });
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
// Cleanup still runs if the operation was stopped between parts.
|
|
378
|
+
await initialClient.abortMultipartUpload(target, upload.uploadId).catch(() => { });
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
return original;
|
|
382
|
+
}
|
|
383
|
+
async removeBatch(session, keys) {
|
|
384
|
+
if (!keys.length || keys.length > 100)
|
|
385
|
+
throw new OssError("Invalid delete batch", "oss_input_invalid", 400);
|
|
386
|
+
const checked = keys.map(key => ossTransferOptions(session, key, "delete").key);
|
|
387
|
+
if (checked.some((key, index) => key !== keys[index]))
|
|
388
|
+
throw new OssError("Ambiguous object key", "oss_input_invalid", 400);
|
|
389
|
+
try {
|
|
390
|
+
const result = await this.client(session).deleteMulti(checked, { quiet: false });
|
|
391
|
+
// ali-oss typings say string[], but the XML parser can return { Key, VersionId } records.
|
|
392
|
+
const values = result.deleted ?? [];
|
|
393
|
+
const deleted = [...new Set(values.map(value => typeof value === "string" ? value : value && typeof value === "object" && "Key" in value ? value.Key : undefined))];
|
|
394
|
+
if (deleted.some(value => typeof value !== "string" || !checked.includes(value)))
|
|
395
|
+
throw new Error("Invalid delete response");
|
|
396
|
+
return { deleted: deleted, failed: checked.filter(key => !deleted.includes(key)) };
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
throw transferError("delete", error);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
306
402
|
async remove(session, key) {
|
|
307
403
|
requirePermission(session, "delete");
|
|
308
404
|
const objectKey = validateKey(key, effectivePrefix(session), "object key");
|
|
@@ -315,6 +411,16 @@ export class OssTransferClient {
|
|
|
315
411
|
}
|
|
316
412
|
}
|
|
317
413
|
}
|
|
414
|
+
/** Unsigned public-network address; object ACLs still govern anonymous access. */
|
|
415
|
+
export function ossObjectPublicUrl(session, key) {
|
|
416
|
+
requirePermission(session, "read");
|
|
417
|
+
const objectKey = validateKey(key, effectivePrefix(session), "object key");
|
|
418
|
+
const options = clientOptions(session);
|
|
419
|
+
const region = String(options.region).replace(/-internal$/u, "");
|
|
420
|
+
const encoded = objectKey.split("/").map(part => encodeURIComponent(part)
|
|
421
|
+
.replace(/[!'()*]/gu, c => `%${c.charCodeAt(0).toString(16).toUpperCase()}`)).join("/");
|
|
422
|
+
return `https://${options.bucket}.${region}.aliyuncs.com/${encoded}`;
|
|
423
|
+
}
|
|
318
424
|
export function ossSessionCapabilities(session) {
|
|
319
425
|
clientOptions(session);
|
|
320
426
|
const prefix = effectivePrefix(session);
|
|
@@ -350,4 +456,9 @@ export function sessionMetadata(session) {
|
|
|
350
456
|
expires_at: session.expiration
|
|
351
457
|
};
|
|
352
458
|
}
|
|
459
|
+
/** Validate every refreshed session before background transfer requests. */
|
|
460
|
+
export function ossTransferOptions(session, key, operation) {
|
|
461
|
+
requirePermission(session, operation);
|
|
462
|
+
return { key: validateKey(key, effectivePrefix(session), "object key", operation === "list"), options: clientOptions(session) };
|
|
463
|
+
}
|
|
353
464
|
//# sourceMappingURL=transfers.js.map
|