@numa-tech/numa 1.18.0 → 1.19.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.
@@ -0,0 +1,131 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { lstat, readdir, realpath } from 'node:fs/promises';
3
+ import { basename, dirname, isAbsolute, join, relative, sep } from 'node:path';
4
+ import { OssError } from './errors.js';
5
+ import { ossSessionCapabilities, ossTransferOptions } from './transfers.js';
6
+ const MAX_FILES = 10_000;
7
+ function invalid(message = '文件路径无效,或目录包含符号链接。') { throw new OssError(message, 'oss_transfer_path_invalid', 400); }
8
+ function count(files) { if (files.length > MAX_FILES)
9
+ throw new OssError('单次最多选择 10000 个文件。', 'oss_transfer_limit', 400); }
10
+ function validSize(size) { if (!Number.isSafeInteger(size) || size < 0)
11
+ invalid(); return size; }
12
+ function segments(path) {
13
+ const parts = path.split('/');
14
+ if (parts.some(p => !p || p === '.' || p === '..' || /[\\\u0000-\u001f\u007f]/u.test(p)))
15
+ invalid();
16
+ return parts;
17
+ }
18
+ export function transferBinding(session) {
19
+ return createHash('sha256').update(JSON.stringify([session.grantId, session.accountUid, session.bucketName,
20
+ session.region, session.scopeType, ossSessionCapabilities(session).root, session.roleArn, session.sourceIdentity])).digest('hex');
21
+ }
22
+ export async function planUploadJobs(session, selected, prefix, folder) {
23
+ const files = [], keys = new Set();
24
+ if (!selected.length || selected.length > MAX_FILES || (folder && selected.length !== 1))
25
+ invalid();
26
+ const target = prefix ? prefix.replace(/\/$/u, '') + '/' : '';
27
+ async function visit(path, key, root) {
28
+ const info = await lstat(path);
29
+ if (info.isSymbolicLink())
30
+ invalid();
31
+ if (info.isDirectory()) {
32
+ for (const entry of await readdir(path)) {
33
+ segments(entry);
34
+ await visit(join(path, entry), key + '/' + entry, root);
35
+ }
36
+ }
37
+ else if (info.isFile()) {
38
+ const checked = ossTransferOptions(session, key, 'write').key;
39
+ // Never silently trim a local filename while translating it to an OSS key.
40
+ if (checked !== key || keys.has(key))
41
+ invalid();
42
+ keys.add(key);
43
+ files.push({ key, localPath: path, localRoot: root, size: validSize(info.size),
44
+ source: { dev: info.dev, ino: info.ino, size: info.size, mtimeMs: info.mtimeMs } });
45
+ count(files);
46
+ }
47
+ else
48
+ invalid();
49
+ }
50
+ for (const path of selected) {
51
+ if (!isAbsolute(path))
52
+ invalid();
53
+ const info = await lstat(path);
54
+ if (info.isSymbolicLink() || (folder ? !info.isDirectory() : !info.isFile()))
55
+ invalid();
56
+ const name = basename(path);
57
+ segments(name);
58
+ const parent = await realpath(dirname(path)), canonical = join(parent, name);
59
+ await visit(canonical, target + name, folder ? canonical : parent);
60
+ }
61
+ if (!files.length)
62
+ throw new OssError('所选目录中没有文件。', 'oss_transfer_empty', 400);
63
+ return files;
64
+ }
65
+ export async function planDownloadJobs(session, entries, selectedRoot, transfer) {
66
+ if (!isAbsolute(selectedRoot) || !entries.length || entries.length > MAX_FILES)
67
+ invalid();
68
+ if ((await lstat(selectedRoot)).isSymbolicLink())
69
+ invalid();
70
+ const root = await realpath(selectedRoot);
71
+ if (!(await lstat(root)).isDirectory())
72
+ invalid();
73
+ const files = [], outputs = new Set();
74
+ async function add(key, path, size) {
75
+ if (ossTransferOptions(session, key, 'read').key !== key)
76
+ invalid();
77
+ const parts = segments(path);
78
+ // Use portable filenames so the same queue cannot create Windows device/ADS paths.
79
+ if (parts.some(p => /[<>:"|?*]/u.test(p) || /[. ]$/u.test(p) || /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(p)))
80
+ invalid();
81
+ const folded = parts.join('/').normalize('NFC').toLowerCase();
82
+ if ([...outputs].some(p => p === folded || p.startsWith(folded + '/') || folded.startsWith(p + '/')))
83
+ invalid('所选文件的本地路径重复。');
84
+ outputs.add(folded);
85
+ const localPath = join(root, ...parts);
86
+ if (relative(root, localPath).startsWith('..' + sep))
87
+ invalid();
88
+ let current = root;
89
+ for (let i = 0; i < parts.length; i++) {
90
+ current = join(current, parts[i]);
91
+ const info = await lstat(current).catch(error => { if (error.code === 'ENOENT')
92
+ return undefined; throw error; });
93
+ if (info && (i === parts.length - 1 || info.isSymbolicLink() || !info.isDirectory())) {
94
+ throw new OssError('目标文件已存在或路径不安全,未覆盖。', 'oss_transfer_destination_exists', 409);
95
+ }
96
+ }
97
+ files.push({ key, localRoot: root, localPath, size: validSize(size) });
98
+ count(files);
99
+ }
100
+ for (const entry of entries) {
101
+ const key = entry.key;
102
+ if (!entry.directory) {
103
+ const metadata = await transfer.stat(session, key);
104
+ await add(key, key.split('/').pop(), metadata.contentLength);
105
+ continue;
106
+ }
107
+ if (!key.endsWith('/'))
108
+ invalid();
109
+ const name = segments(key.slice(0, -1)).at(-1);
110
+ let marker;
111
+ const seen = new Set();
112
+ do {
113
+ const listing = await transfer.list(session, key, 1000, { marker });
114
+ for (const object of listing.objects) {
115
+ if (!object.key.startsWith(key))
116
+ invalid();
117
+ if (!object.key.endsWith('/'))
118
+ await add(object.key, name + '/' + object.key.slice(key.length), object.sizeBytes);
119
+ }
120
+ marker = listing.truncated ? listing.nextMarker : undefined;
121
+ if (listing.truncated && (!marker || seen.has(marker)))
122
+ invalid();
123
+ if (marker)
124
+ seen.add(marker);
125
+ } while (marker);
126
+ }
127
+ if (!files.length)
128
+ throw new OssError('所选目录中没有可下载的文件。', 'oss_transfer_empty', 400);
129
+ return files;
130
+ }
131
+ //# sourceMappingURL=transfer-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer-paths.js","sourceRoot":"","sources":["../../src/oss/transfer-paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import type { AccessSession } from './schemas.js';
2
+ import { type PlannedFile } from './transfer-paths.js';
3
+ import type { TransferJob, TransferWorker } from './transfer-types.js';
4
+ export interface TransferQueueOptions {
5
+ directory: string;
6
+ session(grantId: number): Promise<AccessSession>;
7
+ worker?: TransferWorker;
8
+ maxConcurrent?: number;
9
+ }
10
+ type Action = 'pause' | 'resume' | 'cancel';
11
+ export declare function createTransferQueue(options: TransferQueueOptions): Promise<TransferQueue>;
12
+ export declare class TransferQueue {
13
+ private options;
14
+ private jobs;
15
+ private readonly active;
16
+ private readonly actions;
17
+ private saving;
18
+ private closing;
19
+ private closed?;
20
+ private lock?;
21
+ private worker;
22
+ private maximum;
23
+ private storageError;
24
+ constructor(options: TransferQueueOptions);
25
+ initialize(): Promise<void>;
26
+ list(): {
27
+ id: string;
28
+ direction: 'upload' | 'download';
29
+ grantId: number;
30
+ key: string;
31
+ localPath: string;
32
+ size: number;
33
+ transferred: number;
34
+ status: import("./transfer-types.js").TransferStatus;
35
+ createdAt: string;
36
+ updatedAt: string;
37
+ error?: string;
38
+ bytesPerSecond: number;
39
+ }[];
40
+ add(direction: TransferJob['direction'], session: AccessSession, files: PlannedFile[]): Promise<{
41
+ id: string;
42
+ direction: 'upload' | 'download';
43
+ grantId: number;
44
+ key: string;
45
+ localPath: string;
46
+ size: number;
47
+ transferred: number;
48
+ status: import("./transfer-types.js").TransferStatus;
49
+ createdAt: string;
50
+ updatedAt: string;
51
+ error?: string;
52
+ bytesPerSecond: number;
53
+ }[]>;
54
+ private context;
55
+ private schedule;
56
+ action(id: string, action: Action): Promise<void>;
57
+ private performAction;
58
+ private save;
59
+ close(): Promise<void>;
60
+ private unlock;
61
+ }
62
+ export {};
@@ -0,0 +1,349 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { constants } from 'node:fs';
3
+ import { lstat, mkdir, open, readFile, rename, rm, chmod } from 'node:fs/promises';
4
+ import { isAbsolute, join, relative, sep } from 'node:path';
5
+ import { z } from 'zod';
6
+ import { OssError } from './errors.js';
7
+ import { transferBinding } from './transfer-paths.js';
8
+ import { createTransferWorker } from './transfer-worker.js';
9
+ const integer = z.number().int().nonnegative().safe();
10
+ const checkpoint = z.discriminatedUnion('kind', [
11
+ z.object({ kind: z.literal('upload'), uploadId: z.string().max(2048), partSize: integer.positive(), parts: z.array(z.object({ number: integer.positive(), etag: z.string().max(2048) }).strict()).max(10000), committing: z.boolean().optional() }).strict(),
12
+ z.object({ kind: z.literal('download'), partSize: integer.positive(), etag: z.string().max(2048), parts: z.array(integer).max(10000), tempPath: z.string().max(8192), tempDev: integer.optional(), tempIno: integer.optional(), committing: z.boolean().optional() }).strict()
13
+ ]);
14
+ const jobSchema = z.object({ id: z.string().uuid(), direction: z.enum(['upload', 'download']), grantId: integer.positive(), key: z.string().min(1).max(1024),
15
+ localPath: z.string().max(8192), localRoot: z.string().max(8192), size: integer, transferred: integer, binding: z.string().regex(/^[a-f0-9]{64}$/u),
16
+ source: z.object({ dev: integer, ino: integer, size: integer, mtimeMs: z.number().finite() }).strict().optional(), checkpoint: checkpoint.optional(),
17
+ status: z.enum(['queued', 'running', 'pausing', 'paused', 'cancelling', 'cancelled', 'completed', 'failed']), createdAt: z.string().datetime(), updatedAt: z.string().datetime(), error: z.string().max(2048).optional()
18
+ }).strict();
19
+ const stateSchema = z.object({ version: z.literal(1), jobs: z.array(jobSchema).max(10000) }).strict();
20
+ function safeError(error) {
21
+ const code = error instanceof OssError ? error.code : '';
22
+ const messages = {
23
+ oss_output_exists: '目标文件已存在,未覆盖。', oss_source_changed: '本地文件已变化,请重新选择文件。',
24
+ oss_remote_changed: '远程文件已变化,请取消后重新下载。', oss_path_invalid: '本地路径无效或包含符号链接。',
25
+ oss_checkpoint_invalid: '断点记录无效,请取消后重新创建任务。', oss_transfer_cleanup_failed: '清理未完成,请检查连接后再次取消。',
26
+ oss_transfer_binding_changed: '授权范围或身份已变化,请重新选择授权并创建任务。',
27
+ oss_web_session_expired: 'STS 已到期,请续期后继续任务。', oss_web_refresh_failed: '授权续期失败,请检查登录后继续任务。',
28
+ oss_web_scope_changed: '授权范围已变化,请重新启动 CLI。', oss_operation_forbidden: '当前授权不允许此操作。',
29
+ oss_grant_forbidden: '当前授权不可用,请检查授权后继续任务。', oss_scope_violation: '对象路径超出当前授权范围。'
30
+ };
31
+ return messages[code] ?? '传输失败,请检查网络、权限和本地磁盘后重试。';
32
+ }
33
+ export async function createTransferQueue(options) {
34
+ const queue = new TransferQueue(options);
35
+ await queue.initialize();
36
+ return queue;
37
+ }
38
+ export class TransferQueue {
39
+ options;
40
+ jobs = [];
41
+ active = new Map();
42
+ actions = new Map();
43
+ saving = Promise.resolve();
44
+ closing = false;
45
+ closed;
46
+ lock;
47
+ worker;
48
+ maximum;
49
+ storageError = false;
50
+ constructor(options) {
51
+ this.options = options;
52
+ this.worker = options.worker ?? createTransferWorker();
53
+ this.maximum = options.maxConcurrent ?? 3;
54
+ if (!Number.isInteger(this.maximum) || this.maximum < 1 || this.maximum > 10)
55
+ throw new OssError('Invalid concurrency', 'oss_input_invalid', 400);
56
+ }
57
+ async initialize() {
58
+ const directory = this.options.directory;
59
+ await mkdir(directory, { recursive: true, mode: 0o700 });
60
+ const info = await lstat(directory);
61
+ if (!info.isDirectory() || info.isSymbolicLink())
62
+ throw new OssError('任务目录无效。', 'oss_transfer_storage_invalid');
63
+ await chmod(directory, 0o700);
64
+ const path = join(directory, 'queue.lock');
65
+ try {
66
+ this.lock = await open(path, 'wx', 0o600);
67
+ }
68
+ catch (error) {
69
+ if (error.code !== 'EEXIST')
70
+ throw error;
71
+ // Serialize stale-PID recovery: comparing an inode before unlink is not
72
+ // sufficient when two new servers start at the same time.
73
+ const recoveryPath = join(directory, 'queue.recovery.lock');
74
+ const recovery = await open(recoveryPath, 'wx', 0o600).catch(() => { throw new OssError('任务队列正在恢复,或上次恢复被中断;请检查本机任务目录。', 'oss_transfer_queue_busy', 409); });
75
+ try {
76
+ const existing = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
77
+ let identity;
78
+ try {
79
+ identity = await existing.stat();
80
+ if (!identity.isFile() || identity.size > 100)
81
+ throw new Error('invalid lock');
82
+ const pid = Number((await existing.readFile('utf8')).trim());
83
+ if (!Number.isSafeInteger(pid) || pid <= 0)
84
+ throw new OssError('任务目录锁无效,请检查本机任务目录。', 'oss_transfer_storage_invalid');
85
+ let alive = true;
86
+ try {
87
+ process.kill(pid, 0);
88
+ }
89
+ catch (e) {
90
+ if (e.code === 'ESRCH')
91
+ alive = false;
92
+ }
93
+ if (alive)
94
+ throw new OssError('另一个 OSS 网页服务正在使用此账号的任务队列。', 'oss_transfer_queue_busy', 409);
95
+ }
96
+ finally {
97
+ await existing.close();
98
+ }
99
+ const current = await lstat(path);
100
+ if (current.dev !== identity.dev || current.ino !== identity.ino)
101
+ throw new OssError('任务队列已被占用。', 'oss_transfer_queue_busy', 409);
102
+ await rm(path);
103
+ this.lock = await open(path, 'wx', 0o600);
104
+ }
105
+ finally {
106
+ await recovery.close();
107
+ await rm(recoveryPath, { force: true });
108
+ }
109
+ }
110
+ try {
111
+ await this.lock.writeFile(String(process.pid));
112
+ await this.lock.sync();
113
+ const statePath = join(directory, 'tasks.json');
114
+ const info = await lstat(statePath).catch(e => { if (e.code === 'ENOENT')
115
+ return undefined; throw e; });
116
+ if (info) {
117
+ if (!info.isFile() || info.isSymbolicLink() || info.size > 16 * 1024 * 1024)
118
+ throw new Error('invalid state file');
119
+ const state = stateSchema.parse(JSON.parse(await readFile(statePath, 'utf8')));
120
+ const seen = new Set();
121
+ for (const job of state.jobs) {
122
+ const rel = relative(job.localRoot, job.localPath);
123
+ if (!isAbsolute(job.localPath) || !isAbsolute(job.localRoot) || !rel || rel === '..' || rel.startsWith('..' + sep) || isAbsolute(rel) || seen.has(job.id))
124
+ throw new Error('invalid job path');
125
+ seen.add(job.id);
126
+ if (['queued', 'running', 'pausing', 'cancelling'].includes(job.status))
127
+ job.status = 'paused';
128
+ }
129
+ this.jobs = state.jobs;
130
+ }
131
+ await this.save();
132
+ }
133
+ catch (error) {
134
+ await this.unlock();
135
+ if (error instanceof OssError)
136
+ throw error;
137
+ throw new OssError('本机任务记录无法读取或写入;请检查任务目录。', 'oss_transfer_storage_invalid');
138
+ }
139
+ }
140
+ list() {
141
+ return this.jobs.map(job => {
142
+ const { checkpoint: _checkpoint, binding: _binding, source: _source, localRoot: _root, ...view } = job;
143
+ const active = this.active.get(job.id);
144
+ const bytesPerSecond = active && job.status === 'running' ? Math.max(0, (job.transferred - active.initial) / Math.max(1, (Date.now() - active.started) / 1000)) : 0;
145
+ return { ...view, bytesPerSecond };
146
+ });
147
+ }
148
+ async add(direction, session, files) {
149
+ if (this.closing || this.storageError)
150
+ throw new OssError('任务队列不可用。', 'oss_transfer_storage_invalid');
151
+ const pending = this.jobs.filter(j => !['completed', 'cancelled'].includes(j.status));
152
+ if (!files.length || pending.length + files.length > 10000)
153
+ throw new OssError('未完成任务数量已达上限。', 'oss_transfer_limit', 400);
154
+ const binding = transferBinding(session), date = new Date().toISOString();
155
+ const additions = files.map(file => jobSchema.parse({ ...file, id: randomUUID(), direction, grantId: session.grantId, binding, transferred: 0, status: 'queued', createdAt: date, updatedAt: date }));
156
+ for (const job of additions) {
157
+ if (pending.some(other => other.direction === direction && (direction === 'download' ? other.localPath === job.localPath : other.binding === job.binding && other.key === job.key)))
158
+ throw new OssError('同一路径已有未完成任务。', 'oss_transfer_duplicate', 409);
159
+ pending.push(job);
160
+ }
161
+ let excess = this.jobs.length + additions.length - 10000;
162
+ this.jobs = this.jobs.filter(job => { if (excess > 0 && ['completed', 'cancelled'].includes(job.status)) {
163
+ excess--;
164
+ return false;
165
+ } return true; });
166
+ this.jobs.push(...additions);
167
+ await this.save();
168
+ this.schedule();
169
+ const ids = new Set(additions.map(j => j.id));
170
+ return this.list().filter(j => ids.has(j.id));
171
+ }
172
+ context(job, controller) {
173
+ return { signal: controller.signal, session: async () => {
174
+ const session = await this.options.session(job.grantId);
175
+ if (transferBinding(session) !== job.binding)
176
+ throw new OssError('Binding changed', 'oss_transfer_binding_changed');
177
+ return session;
178
+ }, save: () => this.save(), progress: bytes => { if (Number.isFinite(bytes)) {
179
+ job.transferred = Math.max(0, Math.min(job.size, bytes));
180
+ job.updatedAt = new Date().toISOString();
181
+ } } };
182
+ }
183
+ schedule() {
184
+ if (this.closing || this.storageError)
185
+ return;
186
+ for (const job of this.jobs) {
187
+ if (this.active.size >= this.maximum)
188
+ break;
189
+ if (job.status !== 'queued')
190
+ continue;
191
+ const controller = new AbortController();
192
+ job.status = 'running';
193
+ delete job.error;
194
+ const active = { controller, done: Promise.resolve(), started: Date.now(), initial: job.transferred };
195
+ this.active.set(job.id, active);
196
+ active.done = (async () => {
197
+ try {
198
+ await this.save();
199
+ await this.worker.run(job, this.context(job, controller));
200
+ // A committed object/file cannot be undone by a late pause or cancellation.
201
+ job.status = 'completed';
202
+ job.transferred = job.size;
203
+ delete job.checkpoint;
204
+ }
205
+ catch (error) {
206
+ if (controller.signal.aborted)
207
+ job.status = 'paused';
208
+ else {
209
+ job.status = 'failed';
210
+ job.error = safeError(error);
211
+ }
212
+ }
213
+ finally {
214
+ job.updatedAt = new Date().toISOString();
215
+ try {
216
+ await this.save();
217
+ }
218
+ catch {
219
+ this.storageError = true;
220
+ }
221
+ this.active.delete(job.id);
222
+ this.schedule();
223
+ }
224
+ })();
225
+ }
226
+ }
227
+ action(id, action) {
228
+ const previous = this.actions.get(id) ?? Promise.resolve();
229
+ const next = previous.catch(() => { }).then(() => this.performAction(id, action));
230
+ this.actions.set(id, next);
231
+ void next.finally(() => { if (this.actions.get(id) === next)
232
+ this.actions.delete(id); }).catch(() => { });
233
+ return next;
234
+ }
235
+ async performAction(id, action) {
236
+ if (this.closing)
237
+ throw new OssError('任务服务正在关闭。', 'oss_transfer_storage_invalid');
238
+ const job = this.jobs.find(j => j.id === id);
239
+ if (!job)
240
+ throw new OssError('任务不存在。', 'oss_input_invalid', 404);
241
+ if (['completed', 'cancelled'].includes(job.status))
242
+ return;
243
+ if (action === 'resume') {
244
+ if (!['paused', 'failed'].includes(job.status))
245
+ return;
246
+ if (this.storageError)
247
+ throw new OssError('任务记录写入失败。', 'oss_transfer_storage_invalid');
248
+ job.status = 'queued';
249
+ delete job.error;
250
+ await this.save();
251
+ this.schedule();
252
+ return;
253
+ }
254
+ const active = this.active.get(id);
255
+ job.status = action === 'pause' ? 'pausing' : 'cancelling';
256
+ active?.controller.abort();
257
+ if (active)
258
+ await active.done;
259
+ if (job.status === 'completed')
260
+ return;
261
+ if (action === 'cancel') {
262
+ try {
263
+ await this.worker.cancel(job, this.context(job, new AbortController()));
264
+ if (job.status !== 'completed')
265
+ job.status = 'cancelled';
266
+ delete job.checkpoint;
267
+ delete job.error;
268
+ }
269
+ catch (error) {
270
+ job.status = 'failed';
271
+ job.error = safeError(error);
272
+ }
273
+ }
274
+ else
275
+ job.status = 'paused';
276
+ job.updatedAt = new Date().toISOString();
277
+ await this.save();
278
+ }
279
+ save() {
280
+ const write = this.saving.catch(() => { }).then(async () => {
281
+ const data = JSON.stringify({ version: 1, jobs: this.jobs });
282
+ if (Buffer.byteLength(data) > 16 * 1024 * 1024)
283
+ throw new Error('state too large');
284
+ const temporary = join(this.options.directory, `.tasks-${randomUUID()}.tmp`);
285
+ const file = await open(temporary, 'wx', 0o600);
286
+ try {
287
+ await file.writeFile(data);
288
+ await file.sync();
289
+ await file.close();
290
+ await rename(temporary, join(this.options.directory, 'tasks.json'));
291
+ // Persist the rename as well as the JSON bytes before acknowledging a checkpoint.
292
+ let parent;
293
+ try {
294
+ parent = await open(this.options.directory, constants.O_RDONLY);
295
+ await parent.sync();
296
+ }
297
+ catch (error) {
298
+ if (process.platform !== 'win32' || !['EPERM', 'EISDIR', 'EINVAL', 'ENOTSUP'].includes(error.code ?? ''))
299
+ throw error;
300
+ }
301
+ finally {
302
+ await parent?.close();
303
+ }
304
+ }
305
+ finally {
306
+ await file.close().catch(() => { });
307
+ await rm(temporary, { force: true }).catch(() => { });
308
+ }
309
+ });
310
+ this.saving = write;
311
+ return write;
312
+ }
313
+ close() {
314
+ if (this.closed)
315
+ return this.closed;
316
+ this.closing = true;
317
+ this.closed = (async () => {
318
+ try {
319
+ for (const job of this.jobs)
320
+ if (job.status === 'queued')
321
+ job.status = 'paused';
322
+ for (const active of this.active.values())
323
+ active.controller.abort();
324
+ await Promise.allSettled([...this.active.values()].map(a => a.done));
325
+ await Promise.allSettled([...this.actions.values()]);
326
+ await this.save();
327
+ }
328
+ finally {
329
+ await this.unlock();
330
+ }
331
+ })();
332
+ return this.closed;
333
+ }
334
+ async unlock() {
335
+ if (!this.lock)
336
+ return;
337
+ const lock = this.lock;
338
+ this.lock = undefined;
339
+ try {
340
+ const owned = await lock.stat(), current = await lstat(join(this.options.directory, 'queue.lock'));
341
+ if (owned.ino === current.ino && owned.dev === current.dev)
342
+ await rm(join(this.options.directory, 'queue.lock'));
343
+ }
344
+ finally {
345
+ await lock.close();
346
+ }
347
+ }
348
+ }
349
+ //# sourceMappingURL=transfer-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer-queue.js","sourceRoot":"","sources":["../../src/oss/transfer-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { AccessSession } from './schemas.js';
2
+ export type TransferStatus = 'queued' | 'running' | 'pausing' | 'paused' | 'cancelling' | 'cancelled' | 'completed' | 'failed';
3
+ export interface LocalFileIdentity {
4
+ dev: number;
5
+ ino: number;
6
+ size: number;
7
+ mtimeMs: number;
8
+ }
9
+ export type TransferCheckpoint = {
10
+ kind: 'upload';
11
+ uploadId: string;
12
+ partSize: number;
13
+ parts: {
14
+ number: number;
15
+ etag: string;
16
+ }[];
17
+ committing?: boolean;
18
+ } | {
19
+ kind: 'download';
20
+ partSize: number;
21
+ etag: string;
22
+ parts: number[];
23
+ tempPath: string;
24
+ tempDev?: number;
25
+ tempIno?: number;
26
+ committing?: boolean;
27
+ };
28
+ export interface TransferJob {
29
+ id: string;
30
+ direction: 'upload' | 'download';
31
+ grantId: number;
32
+ key: string;
33
+ localPath: string;
34
+ localRoot: string;
35
+ size: number;
36
+ transferred: number;
37
+ binding: string;
38
+ source?: LocalFileIdentity;
39
+ checkpoint?: TransferCheckpoint;
40
+ status: TransferStatus;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ error?: string;
44
+ }
45
+ export interface TransferContext {
46
+ session(): Promise<AccessSession>;
47
+ signal: AbortSignal;
48
+ save(): Promise<void>;
49
+ progress(bytes: number): void;
50
+ }
51
+ export interface TransferWorker {
52
+ run(job: TransferJob, context: TransferContext): Promise<void>;
53
+ cancel(job: TransferJob, context: TransferContext): Promise<void>;
54
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=transfer-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transfer-types.js","sourceRoot":"","sources":["../../src/oss/transfer-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import { type OssTransferDependencies } from './transfers.js';
2
+ import type { TransferWorker } from './transfer-types.js';
3
+ export declare function createTransferWorker({ clientFactory }?: OssTransferDependencies): TransferWorker;