@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,269 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { OssError } from './errors.js';
|
|
4
|
+
import { ossSessionCapabilities, ossTransferOptions } from './transfers.js';
|
|
5
|
+
const entrySchema = z.object({ key: z.string().min(1).max(1024), directory: z.boolean() }).strict();
|
|
6
|
+
const inputSchema = z.discriminatedUnion('kind', [
|
|
7
|
+
z.object({ kind: z.literal('delete'), entries: z.array(entrySchema).min(1).max(1000) }).strict(),
|
|
8
|
+
z.object({ kind: z.enum(['copy', 'move', 'rename']), entries: z.array(entrySchema).length(1), destination: z.string().max(1024) }).strict(),
|
|
9
|
+
z.object({ kind: z.literal('mkdir'), destination: z.string().min(1).max(1024) }).strict()
|
|
10
|
+
]);
|
|
11
|
+
class Stopped extends Error {
|
|
12
|
+
}
|
|
13
|
+
const active = (job) => job.status === 'running' || job.status === 'stopping';
|
|
14
|
+
const identity = (s) => JSON.stringify([s.grantId, s.accountUid, s.roleArn, s.bucketName, s.region, s.scopeType, s.objectPrefix, s.sourceIdentity]);
|
|
15
|
+
const compareKeys = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b));
|
|
16
|
+
function invalid() { throw new OssError('Invalid file operation', 'oss_input_invalid', 400); }
|
|
17
|
+
function conflict() { throw new OssError('Destination exists', 'oss_transfer_destination_exists', 409); }
|
|
18
|
+
function key(session, value, operation) {
|
|
19
|
+
// Do not silently normalize object names into different objects.
|
|
20
|
+
if (value !== value.trim() || value.includes('//'))
|
|
21
|
+
invalid();
|
|
22
|
+
const result = ossTransferOptions(session, value, operation).key;
|
|
23
|
+
if (result === ossSessionCapabilities(session).root)
|
|
24
|
+
invalid();
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function entries(input) {
|
|
28
|
+
const sorted = [...input.entries].sort((a, b) => compareKeys(a.key, b.key));
|
|
29
|
+
const result = [];
|
|
30
|
+
for (const entry of sorted) {
|
|
31
|
+
if (entry.directory !== entry.key.endsWith('/'))
|
|
32
|
+
invalid();
|
|
33
|
+
if (!result.some(parent => parent.key === entry.key || parent.directory && entry.key.startsWith(parent.key)))
|
|
34
|
+
result.push(entry);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
function targetFor(session, input) {
|
|
39
|
+
if (input.kind === 'mkdir') {
|
|
40
|
+
if (!input.destination.endsWith('/'))
|
|
41
|
+
invalid();
|
|
42
|
+
return key(session, input.destination, 'write');
|
|
43
|
+
}
|
|
44
|
+
const source = input.entries[0];
|
|
45
|
+
const name = source.key.replace(/\/$/u, '').split('/').at(-1);
|
|
46
|
+
let target;
|
|
47
|
+
if (input.kind === 'rename') {
|
|
48
|
+
if (!input.destination || input.destination.includes('/') || input.destination !== input.destination.trim())
|
|
49
|
+
invalid();
|
|
50
|
+
const parent = source.key.replace(/\/$/u, '').slice(0, -name.length);
|
|
51
|
+
target = parent + input.destination + (source.directory ? '/' : '');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const directory = input.destination;
|
|
55
|
+
if (directory && !directory.endsWith('/'))
|
|
56
|
+
invalid();
|
|
57
|
+
const root = ossSessionCapabilities(session).root;
|
|
58
|
+
if (directory !== root)
|
|
59
|
+
key(session, directory, 'write');
|
|
60
|
+
target = directory + name + (source.directory ? '/' : '');
|
|
61
|
+
}
|
|
62
|
+
key(session, target, 'write');
|
|
63
|
+
if (target === source.key || source.directory && (target.startsWith(source.key) || source.key.startsWith(target)))
|
|
64
|
+
invalid();
|
|
65
|
+
return target;
|
|
66
|
+
}
|
|
67
|
+
/** In-memory remote operations: bounded paging/history; never recursively pre-count or persist STS. */
|
|
68
|
+
export class OssFileOperations {
|
|
69
|
+
transfer;
|
|
70
|
+
session;
|
|
71
|
+
jobs = [];
|
|
72
|
+
pending = Promise.resolve();
|
|
73
|
+
starting = false;
|
|
74
|
+
closing = false;
|
|
75
|
+
constructor(transfer, session) {
|
|
76
|
+
this.transfer = transfer;
|
|
77
|
+
this.session = session;
|
|
78
|
+
}
|
|
79
|
+
list() { return this.jobs.map(job => ({ ...job })); }
|
|
80
|
+
async start(grantId, value) {
|
|
81
|
+
if (this.closing || this.starting || this.jobs.some(active))
|
|
82
|
+
throw new OssError('Operation already running', 'oss_operation_busy', 409);
|
|
83
|
+
const parsed = inputSchema.safeParse(value);
|
|
84
|
+
if (!parsed.success)
|
|
85
|
+
invalid();
|
|
86
|
+
const input = parsed.data;
|
|
87
|
+
this.starting = true;
|
|
88
|
+
try {
|
|
89
|
+
const initial = await this.session(grantId);
|
|
90
|
+
if (this.closing)
|
|
91
|
+
throw new Stopped();
|
|
92
|
+
const selected = input.kind === 'mkdir' ? [] : entries(input);
|
|
93
|
+
for (const entry of selected) {
|
|
94
|
+
key(initial, entry.key, input.kind === 'delete' ? 'delete' : 'read');
|
|
95
|
+
if (input.kind === 'move' || input.kind === 'rename')
|
|
96
|
+
key(initial, entry.key, 'delete');
|
|
97
|
+
if (entry.directory)
|
|
98
|
+
ossTransferOptions(initial, entry.key, 'list');
|
|
99
|
+
}
|
|
100
|
+
const target = input.kind === 'delete' ? undefined : targetFor(initial, input);
|
|
101
|
+
const job = { id: randomUUID(), grantId, kind: input.kind, status: 'running', selected: input.kind === 'mkdir' ? 1 : input.entries.length,
|
|
102
|
+
scanned: 0, done: 0, copied: 0, failed: 0, startedAt: new Date().toISOString() };
|
|
103
|
+
this.jobs = [job, ...this.jobs].slice(0, 20);
|
|
104
|
+
const check = () => { if (job.status === 'stopping' || this.closing)
|
|
105
|
+
throw new Stopped(); };
|
|
106
|
+
const fresh = async () => {
|
|
107
|
+
check();
|
|
108
|
+
const session = await this.session(grantId);
|
|
109
|
+
if (identity(session) !== identity(initial))
|
|
110
|
+
throw new OssError('Scope changed', 'oss_web_scope_changed', 409);
|
|
111
|
+
check();
|
|
112
|
+
return session;
|
|
113
|
+
};
|
|
114
|
+
this.pending = this.run(job, input, selected, target, fresh, check).then(() => {
|
|
115
|
+
job.status = job.status === 'stopping' ? 'stopped' : 'completed';
|
|
116
|
+
}, error => {
|
|
117
|
+
if (error instanceof Stopped || job.status === 'stopping') {
|
|
118
|
+
job.status = 'stopped';
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
job.status = 'failed';
|
|
122
|
+
job.failed = Math.max(1, job.failed);
|
|
123
|
+
job.error = error instanceof OssError && error.code === 'oss_transfer_destination_exists'
|
|
124
|
+
? '目标已存在,操作已停止;已有结果保留,请检查后再操作。'
|
|
125
|
+
: error instanceof OssError && error.code === 'oss_source_changed'
|
|
126
|
+
? '源文件已变化,已保留源文件并停止操作。'
|
|
127
|
+
: '操作失败并已停止,已完成的操作不会回滚。网络异常时部分结果可能未确认,请刷新列表核对后再操作。';
|
|
128
|
+
});
|
|
129
|
+
return { ...job };
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
this.starting = false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
stop(id) {
|
|
136
|
+
const job = this.jobs.find(job => job.id === id);
|
|
137
|
+
if (!job)
|
|
138
|
+
throw new OssError('Unknown operation', 'oss_input_invalid', 404);
|
|
139
|
+
if (active(job))
|
|
140
|
+
job.status = 'stopping';
|
|
141
|
+
}
|
|
142
|
+
async wait() { await this.pending; }
|
|
143
|
+
async close() { this.closing = true; for (const job of this.jobs)
|
|
144
|
+
if (active(job))
|
|
145
|
+
job.status = 'stopping'; await this.pending; }
|
|
146
|
+
async absent(session, target) {
|
|
147
|
+
if (target.endsWith('/')) {
|
|
148
|
+
const page = await this.transfer.list(session, target, 1);
|
|
149
|
+
if (page.objects.length || page.directories.length)
|
|
150
|
+
conflict();
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
try {
|
|
154
|
+
await this.transfer.stat(session, target);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404)
|
|
158
|
+
return;
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
conflict();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async run(job, input, selected, target, fresh, check) {
|
|
165
|
+
if (target !== undefined)
|
|
166
|
+
await this.absent(await fresh(), target);
|
|
167
|
+
if (input.kind === 'mkdir') {
|
|
168
|
+
check();
|
|
169
|
+
job.scanned = 1;
|
|
170
|
+
await this.transfer.createDirectory(await fresh(), target);
|
|
171
|
+
job.done = 1;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const perform = async (source, entry) => {
|
|
175
|
+
check();
|
|
176
|
+
job.currentKey = source;
|
|
177
|
+
if (input.kind === 'delete')
|
|
178
|
+
await this.transfer.remove(await fresh(), source);
|
|
179
|
+
else {
|
|
180
|
+
const destination = target + (entry.directory ? source.slice(entry.key.length) : '');
|
|
181
|
+
// Check each target as well as the directory root; external writers can race this operation.
|
|
182
|
+
try {
|
|
183
|
+
await this.transfer.stat(await fresh(), destination);
|
|
184
|
+
conflict();
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (!(error && typeof error === 'object' && 'status' in error && error.status === 404))
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
const original = await this.transfer.copy(await fresh(), source, destination, fresh);
|
|
191
|
+
job.copied++;
|
|
192
|
+
if (input.kind !== 'copy') {
|
|
193
|
+
const current = await this.transfer.stat(await fresh(), source);
|
|
194
|
+
if (!original.etag || original.etag !== current.etag || original.contentLength !== current.contentLength || original.lastModified !== current.lastModified) {
|
|
195
|
+
throw new OssError('Source changed', 'oss_source_changed', 409);
|
|
196
|
+
}
|
|
197
|
+
await this.transfer.remove(await fresh(), source);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
job.done++;
|
|
201
|
+
};
|
|
202
|
+
for (const entry of selected) {
|
|
203
|
+
check();
|
|
204
|
+
if (!entry.directory) {
|
|
205
|
+
job.scanned++;
|
|
206
|
+
await perform(entry.key, entry);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
let marker;
|
|
210
|
+
for (;;) {
|
|
211
|
+
const pageSession = await fresh();
|
|
212
|
+
const page = await this.transfer.list(pageSession, entry.key, 200, { marker });
|
|
213
|
+
// Validate before mutating a page, including monotonic pagination and exact subtree boundaries.
|
|
214
|
+
if (page.objects.length > 200 || page.objects.some(object => !object.key.startsWith(entry.key) || marker && compareKeys(object.key, marker) <= 0)
|
|
215
|
+
|| new Set(page.objects.map(object => object.key)).size !== page.objects.length
|
|
216
|
+
|| page.truncated && (!page.nextMarker || marker && compareKeys(page.nextMarker, marker) <= 0 || !page.nextMarker.startsWith(entry.key)
|
|
217
|
+
|| page.objects.some(object => compareKeys(object.key, page.nextMarker) > 0)))
|
|
218
|
+
invalid();
|
|
219
|
+
for (const object of page.objects)
|
|
220
|
+
key(pageSession, object.key, input.kind === 'delete' ? 'delete' : 'read');
|
|
221
|
+
job.scanned += page.objects.length;
|
|
222
|
+
if (input.kind === 'delete') {
|
|
223
|
+
// Two requests per full page instead of one request per object. Stop between batches.
|
|
224
|
+
for (let offset = 0; offset < page.objects.length; offset += 100) {
|
|
225
|
+
check();
|
|
226
|
+
const keys = page.objects.slice(offset, offset + 100).map(object => object.key);
|
|
227
|
+
job.currentKey = keys[0];
|
|
228
|
+
const session = await fresh();
|
|
229
|
+
let result;
|
|
230
|
+
try {
|
|
231
|
+
result = await this.transfer.removeBatch(session, keys);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
job.failed += keys.length;
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
job.done += result.deleted.length;
|
|
238
|
+
job.failed += result.failed.length;
|
|
239
|
+
if (result.failed.length)
|
|
240
|
+
throw new OssError('Partial delete failure', 'oss_transfer_failed', 502);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
let cursor = 0, failure;
|
|
245
|
+
await Promise.all(Array.from({ length: 3 }, async () => {
|
|
246
|
+
while (cursor < page.objects.length && !failure) {
|
|
247
|
+
const object = page.objects[cursor++];
|
|
248
|
+
try {
|
|
249
|
+
await perform(object.key, entry);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (!(error instanceof Stopped))
|
|
253
|
+
job.failed++;
|
|
254
|
+
failure ??= error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}));
|
|
258
|
+
if (failure)
|
|
259
|
+
throw failure;
|
|
260
|
+
}
|
|
261
|
+
check();
|
|
262
|
+
if (!page.truncated)
|
|
263
|
+
break;
|
|
264
|
+
marker = page.nextMarker;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=file-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-operations.js","sourceRoot":"","sources":["../../src/oss/file-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface LocalPicker {
|
|
2
|
+
pickFiles(): Promise<string[] | undefined>;
|
|
3
|
+
pickFolder(purpose: "upload" | "download"): Promise<string | undefined>;
|
|
4
|
+
close?(): void;
|
|
5
|
+
}
|
|
6
|
+
export interface LocalPickerRunOptions {
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
shell: false;
|
|
9
|
+
timeout: number;
|
|
10
|
+
maxBuffer: number;
|
|
11
|
+
stdio: readonly ["ignore", "pipe", "ignore"];
|
|
12
|
+
env: NodeJS.ProcessEnv;
|
|
13
|
+
}
|
|
14
|
+
export interface LocalPickerRunResult {
|
|
15
|
+
stdout: string;
|
|
16
|
+
exitCode: number | null;
|
|
17
|
+
error?: unknown;
|
|
18
|
+
}
|
|
19
|
+
export type LocalPickerRunner = (file: string, args: readonly string[], options: LocalPickerRunOptions) => Promise<LocalPickerRunResult>;
|
|
20
|
+
export interface LocalPickerOptions {
|
|
21
|
+
platform?: NodeJS.Platform;
|
|
22
|
+
env?: NodeJS.ProcessEnv;
|
|
23
|
+
run?: LocalPickerRunner;
|
|
24
|
+
}
|
|
25
|
+
export declare function createLocalPicker(options?: LocalPickerOptions): LocalPicker;
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { posix, win32 } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { OssError } from "./errors.js";
|
|
6
|
+
const PICKER_TIMEOUT_MS = 120_000;
|
|
7
|
+
const PICKER_MAX_BUFFER = 1024 * 1024;
|
|
8
|
+
function unavailable() {
|
|
9
|
+
return new OssError("无法打开系统文件选择器。请在桌面会话中重试;Linux 需安装 zenity 或 kdialog。", "oss_picker_unavailable");
|
|
10
|
+
}
|
|
11
|
+
function failed() {
|
|
12
|
+
return new OssError("系统文件选择器失败,请在桌面终端重试。", "oss_picker_failed");
|
|
13
|
+
}
|
|
14
|
+
function invalidResponse() {
|
|
15
|
+
return new OssError("系统文件选择器返回了无效路径,请重试。", "oss_picker_invalid_response");
|
|
16
|
+
}
|
|
17
|
+
const runNative = (file, args, options) => new Promise(resolve => {
|
|
18
|
+
let stdout = "";
|
|
19
|
+
let settled = false;
|
|
20
|
+
let tooLarge = false;
|
|
21
|
+
const child = spawn(file, args, {
|
|
22
|
+
signal: options.signal,
|
|
23
|
+
env: options.env,
|
|
24
|
+
shell: options.shell,
|
|
25
|
+
windowsHide: true,
|
|
26
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
27
|
+
});
|
|
28
|
+
const finish = (result) => {
|
|
29
|
+
if (settled)
|
|
30
|
+
return;
|
|
31
|
+
settled = true;
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
resolve(result);
|
|
34
|
+
};
|
|
35
|
+
const timer = setTimeout(() => {
|
|
36
|
+
child.kill();
|
|
37
|
+
finish({ stdout: "", exitCode: null, error: new Error("picker timeout") });
|
|
38
|
+
}, options.timeout);
|
|
39
|
+
timer.unref();
|
|
40
|
+
child.stdout?.setEncoding("utf8");
|
|
41
|
+
child.stdout?.on("data", (chunk) => {
|
|
42
|
+
if (tooLarge)
|
|
43
|
+
return;
|
|
44
|
+
stdout += chunk;
|
|
45
|
+
if (Buffer.byteLength(stdout, "utf8") > options.maxBuffer) {
|
|
46
|
+
tooLarge = true;
|
|
47
|
+
stdout = "";
|
|
48
|
+
child.kill();
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
child.once("error", error => finish({ stdout: "", exitCode: null, error }));
|
|
52
|
+
child.once("close", exitCode => finish({
|
|
53
|
+
stdout,
|
|
54
|
+
exitCode,
|
|
55
|
+
...(tooLarge ? { error: new Error("picker output limit exceeded") } : {})
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
const macFilesScript = String.raw `
|
|
59
|
+
ObjC.import('stdlib');
|
|
60
|
+
const app = Application.currentApplication();
|
|
61
|
+
app.includeStandardAdditions = true;
|
|
62
|
+
(() => {
|
|
63
|
+
try {
|
|
64
|
+
const selected = app.chooseFile({withPrompt: 'Select files to upload', multipleSelectionsAllowed: true});
|
|
65
|
+
return JSON.stringify(selected.map(item => Path(item).toString()));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error.number === -128) return 'null';
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
})()`;
|
|
71
|
+
function macFolderScript(purpose) {
|
|
72
|
+
const prompt = purpose === "upload" ? "Select folder to upload" : "Select download destination";
|
|
73
|
+
return String.raw `
|
|
74
|
+
ObjC.import('stdlib');
|
|
75
|
+
const app = Application.currentApplication();
|
|
76
|
+
app.includeStandardAdditions = true;
|
|
77
|
+
(() => {
|
|
78
|
+
try {
|
|
79
|
+
const selected = app.chooseFolder({withPrompt: '${prompt}'});
|
|
80
|
+
return JSON.stringify(Path(selected).toString());
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error.number === -128) return 'null';
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
})()`;
|
|
86
|
+
}
|
|
87
|
+
const windowsFilesScript = String.raw `
|
|
88
|
+
$ErrorActionPreference = 'Stop'
|
|
89
|
+
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
|
|
90
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
91
|
+
$dialog = New-Object System.Windows.Forms.OpenFileDialog
|
|
92
|
+
$dialog.Multiselect = $true
|
|
93
|
+
$dialog.Title = 'Select files to upload'
|
|
94
|
+
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
|
95
|
+
ConvertTo-Json -Compress -InputObject @($dialog.FileNames)
|
|
96
|
+
} else { 'null' }
|
|
97
|
+
`;
|
|
98
|
+
function windowsFolderScript(purpose) {
|
|
99
|
+
const description = purpose === "upload" ? "Select folder to upload" : "Select download destination";
|
|
100
|
+
return String.raw `
|
|
101
|
+
$ErrorActionPreference = 'Stop'
|
|
102
|
+
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding($false)
|
|
103
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
104
|
+
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
|
105
|
+
$dialog.Description = '${description}'
|
|
106
|
+
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
|
|
107
|
+
ConvertTo-Json -Compress -InputObject $dialog.SelectedPath
|
|
108
|
+
} else { 'null' }
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
function isMissingTool(error) {
|
|
112
|
+
return !!error && typeof error === "object" && "code" in error && error.code === "ENOENT";
|
|
113
|
+
}
|
|
114
|
+
function parseJson(stdout) {
|
|
115
|
+
if (Buffer.byteLength(stdout, "utf8") > PICKER_MAX_BUFFER)
|
|
116
|
+
throw invalidResponse();
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(stdout.trim());
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
throw invalidResponse();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function validatePaths(value, platform, multiple) {
|
|
125
|
+
if (value === null)
|
|
126
|
+
return undefined;
|
|
127
|
+
const values = multiple ? value : [value];
|
|
128
|
+
if (!Array.isArray(values) || values.length === 0 || values.length > 10_000)
|
|
129
|
+
throw invalidResponse();
|
|
130
|
+
const isAbsolute = platform === "win32" ? win32.isAbsolute : posix.isAbsolute;
|
|
131
|
+
if (!values.every(item => typeof item === "string" && item.length > 0 && isAbsolute(item))) {
|
|
132
|
+
throw invalidResponse();
|
|
133
|
+
}
|
|
134
|
+
return values;
|
|
135
|
+
}
|
|
136
|
+
export function createLocalPicker(options = {}) {
|
|
137
|
+
const platform = options.platform ?? process.platform;
|
|
138
|
+
const env = options.env ?? process.env;
|
|
139
|
+
const run = options.run ?? runNative;
|
|
140
|
+
const controller = new AbortController();
|
|
141
|
+
let active = false;
|
|
142
|
+
const runOptions = {
|
|
143
|
+
signal: controller.signal,
|
|
144
|
+
shell: false,
|
|
145
|
+
timeout: PICKER_TIMEOUT_MS,
|
|
146
|
+
maxBuffer: PICKER_MAX_BUFFER,
|
|
147
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
148
|
+
env
|
|
149
|
+
};
|
|
150
|
+
const exclusive = async (operation) => {
|
|
151
|
+
if (controller.signal.aborted)
|
|
152
|
+
throw failed();
|
|
153
|
+
if (active)
|
|
154
|
+
throw new OssError("已有系统文件选择器正在打开。", "oss_picker_busy");
|
|
155
|
+
active = true;
|
|
156
|
+
try {
|
|
157
|
+
return await operation();
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
active = false;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const invokeJson = async (file, args, multiple) => {
|
|
164
|
+
let result;
|
|
165
|
+
try {
|
|
166
|
+
result = await run(file, args, runOptions);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
throw failed();
|
|
170
|
+
}
|
|
171
|
+
if (result.error || result.exitCode !== 0)
|
|
172
|
+
throw failed();
|
|
173
|
+
return validatePaths(parseJson(result.stdout), platform, multiple);
|
|
174
|
+
};
|
|
175
|
+
const invokeLinux = async (zenityArgs, kdialogArgs, multiple, zenitySeparator) => {
|
|
176
|
+
let result;
|
|
177
|
+
let usedKdialog = false;
|
|
178
|
+
try {
|
|
179
|
+
result = await run("zenity", zenityArgs, runOptions);
|
|
180
|
+
if (isMissingTool(result.error)) {
|
|
181
|
+
usedKdialog = true;
|
|
182
|
+
result = await run("kdialog", kdialogArgs, runOptions);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (!isMissingTool(error))
|
|
187
|
+
throw failed();
|
|
188
|
+
try {
|
|
189
|
+
usedKdialog = true;
|
|
190
|
+
result = await run("kdialog", kdialogArgs, runOptions);
|
|
191
|
+
}
|
|
192
|
+
catch (fallbackError) {
|
|
193
|
+
if (isMissingTool(fallbackError))
|
|
194
|
+
throw unavailable();
|
|
195
|
+
throw failed();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (isMissingTool(result.error))
|
|
199
|
+
throw unavailable();
|
|
200
|
+
if (result.exitCode === 1 && !result.error)
|
|
201
|
+
return undefined;
|
|
202
|
+
if (result.error || result.exitCode !== 0)
|
|
203
|
+
throw failed();
|
|
204
|
+
if (Buffer.byteLength(result.stdout, "utf8") > PICKER_MAX_BUFFER)
|
|
205
|
+
throw invalidResponse();
|
|
206
|
+
// Native tools append LF. A preceding CR can belong to the filename.
|
|
207
|
+
const output = result.stdout.endsWith("\n") ? result.stdout.slice(0, -1) : result.stdout;
|
|
208
|
+
let values;
|
|
209
|
+
try {
|
|
210
|
+
values = multiple
|
|
211
|
+
? usedKdialog
|
|
212
|
+
? output.split("\n").filter(Boolean).map(value => fileURLToPath(value.replaceAll(" ", "%20")))
|
|
213
|
+
: output.split(zenitySeparator).filter(Boolean)
|
|
214
|
+
: [output];
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
throw invalidResponse();
|
|
218
|
+
}
|
|
219
|
+
return validatePaths(multiple ? values : values[0], platform, multiple);
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
close: () => controller.abort(),
|
|
223
|
+
pickFiles: () => exclusive(async () => {
|
|
224
|
+
if (platform === "darwin")
|
|
225
|
+
return invokeJson("/usr/bin/osascript", ["-l", "JavaScript", "-e", macFilesScript], true);
|
|
226
|
+
if (platform === "win32")
|
|
227
|
+
return invokeJson("powershell.exe", ["-NoProfile", "-NonInteractive", "-STA", "-Command", windowsFilesScript], true);
|
|
228
|
+
if (platform === "linux") {
|
|
229
|
+
if (!env.DISPLAY && !env.WAYLAND_DISPLAY)
|
|
230
|
+
throw unavailable();
|
|
231
|
+
const separator = `numa-${randomBytes(16).toString("hex")}`;
|
|
232
|
+
return invokeLinux(["--file-selection", "--multiple", `--separator=${separator}`, "--title=Select files to upload"], ["--getopenurl", env.HOME ?? "/", "*", "--multiple", "--separate-output", "--title", "Select files to upload"], true, separator);
|
|
233
|
+
}
|
|
234
|
+
throw unavailable();
|
|
235
|
+
}),
|
|
236
|
+
pickFolder: purpose => exclusive(async () => {
|
|
237
|
+
if (platform === "darwin")
|
|
238
|
+
return (await invokeJson("/usr/bin/osascript", ["-l", "JavaScript", "-e", macFolderScript(purpose)], false))?.[0];
|
|
239
|
+
if (platform === "win32")
|
|
240
|
+
return (await invokeJson("powershell.exe", ["-NoProfile", "-NonInteractive", "-STA", "-Command", windowsFolderScript(purpose)], false))?.[0];
|
|
241
|
+
if (platform === "linux") {
|
|
242
|
+
if (!env.DISPLAY && !env.WAYLAND_DISPLAY)
|
|
243
|
+
throw unavailable();
|
|
244
|
+
const title = purpose === "upload" ? "Select folder to upload" : "Select download destination";
|
|
245
|
+
return (await invokeLinux(["--file-selection", "--directory", `--title=${title}`], ["--getexistingdirectory", env.HOME ?? "/", "--title", title], false))?.[0];
|
|
246
|
+
}
|
|
247
|
+
throw unavailable();
|
|
248
|
+
})
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=local-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-picker.js","sourceRoot":"","sources":["../../src/oss/local-picker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AccessSession } from './schemas.js';
|
|
2
|
+
import type { LocalFileIdentity } from './transfer-types.js';
|
|
3
|
+
import { OssTransferClient } from './transfers.js';
|
|
4
|
+
export interface PlannedFile {
|
|
5
|
+
key: string;
|
|
6
|
+
localPath: string;
|
|
7
|
+
localRoot: string;
|
|
8
|
+
size: number;
|
|
9
|
+
source?: LocalFileIdentity;
|
|
10
|
+
}
|
|
11
|
+
export declare function transferBinding(session: AccessSession): string;
|
|
12
|
+
export declare function planUploadJobs(session: AccessSession, selected: string[], prefix: string, folder: boolean): Promise<PlannedFile[]>;
|
|
13
|
+
export declare function planDownloadJobs(session: AccessSession, entries: {
|
|
14
|
+
key: string;
|
|
15
|
+
directory: boolean;
|
|
16
|
+
}[], selectedRoot: string, transfer: OssTransferClient): Promise<PlannedFile[]>;
|