@wasmedia/wexiftool 0.1.1 → 0.2.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/dist/cli.cjs +4 -6
- package/dist/cli.es.js +144 -58
- package/dist/{index-BUUKaFua.js → index-C7MUqxoE.js} +2 -2
- package/dist/{index-Czh_jOH1.cjs → index-CwcAkqsP.cjs} +1 -1
- package/dist/{node-WHSUCdKF.js → node-Cu1famID.js} +2 -2
- package/dist/{node-6KJNNt7l.cjs → node-RbU1bgHg.cjs} +1 -1
- package/dist/wexiftool-CRI8zlju.js +948 -0
- package/dist/wexiftool-e6N3ift5.cjs +7 -0
- package/dist/wexiftool.cjs +1 -1
- package/dist/wexiftool.d.ts +18 -2
- package/dist/wexiftool.es.js +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.es.js +2 -2
- package/package.json +1 -1
- package/wasm/perl.wasm +1 -1
- package/dist/wexiftool-CUKoJisL.js +0 -761
- package/dist/wexiftool-Dt9AnMsh.cjs +0 -4
|
@@ -0,0 +1,948 @@
|
|
|
1
|
+
var J = Object.defineProperty;
|
|
2
|
+
var q = (r, t, e) => t in r ? J(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
|
|
3
|
+
var P = (r, t, e) => q(r, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
class $ extends Error {
|
|
5
|
+
constructor(t, e) {
|
|
6
|
+
super(t, e), this.name = new.target.name;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
class At extends $ {
|
|
10
|
+
}
|
|
11
|
+
class kt extends $ {
|
|
12
|
+
constructor(e, n) {
|
|
13
|
+
super(`${e} is locked by another sync access handle (another tab or worker may be using it)`, { cause: n });
|
|
14
|
+
P(this, "path");
|
|
15
|
+
this.path = e;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
class z extends $ {
|
|
19
|
+
}
|
|
20
|
+
class xt extends $ {
|
|
21
|
+
}
|
|
22
|
+
class Pt extends $ {
|
|
23
|
+
}
|
|
24
|
+
class St extends $ {
|
|
25
|
+
constructor(e, n) {
|
|
26
|
+
super(`commit() failed after ${e.length} file(s): ${(n == null ? void 0 : n.message) ?? String(n)}`, { cause: n });
|
|
27
|
+
P(this, "committed");
|
|
28
|
+
this.committed = e;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function G(r, t, e, n = ",") {
|
|
32
|
+
const o = O(t), s = r === "json" ? V(o, e) : K(o, e, n);
|
|
33
|
+
return s === o ? t : L(s);
|
|
34
|
+
}
|
|
35
|
+
function V(r, t) {
|
|
36
|
+
return r.replace(/("SourceFile"\s*:\s*)("(?:[^"\\]|\\.)*")/g, (e, n, o) => {
|
|
37
|
+
let s;
|
|
38
|
+
try {
|
|
39
|
+
s = JSON.parse(j(o));
|
|
40
|
+
} catch {
|
|
41
|
+
return e;
|
|
42
|
+
}
|
|
43
|
+
const i = t(s);
|
|
44
|
+
return i === void 0 ? e : n + O(new TextEncoder().encode(JSON.stringify(i)));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function K(r, t, e) {
|
|
48
|
+
var c;
|
|
49
|
+
const n = X(r, e);
|
|
50
|
+
if (n.length === 0) return r;
|
|
51
|
+
const o = n[0].map((l) => I(r.slice(l.start, l.end)).replace(/^\xef\xbb\xbf/, ""));
|
|
52
|
+
let s = o.indexOf("SourceFile");
|
|
53
|
+
if (s < 0 && ((c = o[0]) == null ? void 0 : c.toLowerCase()) === "sourcefile" && (s = 0), s < 0) return r;
|
|
54
|
+
let i = "", a = 0;
|
|
55
|
+
for (const l of n.slice(1)) {
|
|
56
|
+
const u = l[s];
|
|
57
|
+
if (!u) continue;
|
|
58
|
+
const h = t(j(I(r.slice(u.start, u.end))));
|
|
59
|
+
h !== void 0 && (i += r.slice(a, u.start) + '"' + O(new TextEncoder().encode(h)).replaceAll('"', '""') + '"', a = u.end);
|
|
60
|
+
}
|
|
61
|
+
return i + r.slice(a);
|
|
62
|
+
}
|
|
63
|
+
function X(r, t) {
|
|
64
|
+
const e = [];
|
|
65
|
+
let n = [], o = 0;
|
|
66
|
+
for (; o < r.length; ) {
|
|
67
|
+
const s = o;
|
|
68
|
+
let i = o;
|
|
69
|
+
for (; r[i] === " "; ) i++;
|
|
70
|
+
if (r[i] === '"') {
|
|
71
|
+
for (i++; i < r.length; )
|
|
72
|
+
if (r[i] === '"')
|
|
73
|
+
if (r[i + 1] === '"') i += 2;
|
|
74
|
+
else break;
|
|
75
|
+
else
|
|
76
|
+
i++;
|
|
77
|
+
for (i++; i < r.length && !r.startsWith(t, i) && r[i] !== `
|
|
78
|
+
` && r[i] !== "\r"; ) i++;
|
|
79
|
+
} else
|
|
80
|
+
for (; i < r.length && !r.startsWith(t, i) && r[i] !== `
|
|
81
|
+
` && r[i] !== "\r"; ) i++;
|
|
82
|
+
if (n.push({ start: s, end: i }), r.startsWith(t, i)) {
|
|
83
|
+
o = i + t.length;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
e.push(n), n = [], r[i] === "\r" && r[i + 1] === `
|
|
87
|
+
` ? o = i + 2 : o = i + 1;
|
|
88
|
+
}
|
|
89
|
+
return n.length > 0 && e.push(n), e;
|
|
90
|
+
}
|
|
91
|
+
function I(r) {
|
|
92
|
+
const t = r.replace(/^ +/, "");
|
|
93
|
+
return t.startsWith('"') ? t.slice(1).replace(/"\s*$/, "").replaceAll('""', '"') : t.replace(/[ \n\r]+$/, "");
|
|
94
|
+
}
|
|
95
|
+
function O(r) {
|
|
96
|
+
let t = "";
|
|
97
|
+
for (let e = 0; e < r.length; e += 32768)
|
|
98
|
+
t += String.fromCharCode(...r.subarray(e, e + 32768));
|
|
99
|
+
return t;
|
|
100
|
+
}
|
|
101
|
+
function L(r) {
|
|
102
|
+
const t = new Uint8Array(r.length);
|
|
103
|
+
for (let e = 0; e < r.length; e++) t[e] = r.charCodeAt(e);
|
|
104
|
+
return t;
|
|
105
|
+
}
|
|
106
|
+
function j(r) {
|
|
107
|
+
return new TextDecoder().decode(L(r));
|
|
108
|
+
}
|
|
109
|
+
const g = "/wexiftool", Q = "/opt/perlwasm/bin/exiftool";
|
|
110
|
+
function Y(r) {
|
|
111
|
+
r.ENV && (r.ENV.LC_ALL = "C");
|
|
112
|
+
}
|
|
113
|
+
class Z {
|
|
114
|
+
constructor(t, e) {
|
|
115
|
+
this.wasmUrl = t, this.onWasmProgress = e, this.module = null, this.modulePromise = null, this.tail = Promise.resolve(), this.createModule = null, this.stdoutSink = null, this.stderrSink = null;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Lazily initialize the WASM module on first use.
|
|
119
|
+
*/
|
|
120
|
+
async init() {
|
|
121
|
+
if (!this.module) {
|
|
122
|
+
if (this.modulePromise) {
|
|
123
|
+
await this.modulePromise;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.modulePromise = this.loadModule(), this.module = await this.modulePromise;
|
|
127
|
+
try {
|
|
128
|
+
this.module.FS.mkdir(g);
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async loadModule() {
|
|
134
|
+
const t = {
|
|
135
|
+
noInitialRun: !0,
|
|
136
|
+
print: (s) => {
|
|
137
|
+
var i;
|
|
138
|
+
(i = this.stdoutSink) == null || i.call(this, s);
|
|
139
|
+
},
|
|
140
|
+
printErr: (s) => {
|
|
141
|
+
var i;
|
|
142
|
+
(i = this.stderrSink) == null || i.call(this, s);
|
|
143
|
+
},
|
|
144
|
+
preRun: [Y]
|
|
145
|
+
}, e = this.wasmUrl ?? this.defaultWasmUrl(), n = await this.importModuleFactory(e);
|
|
146
|
+
this.createModule = n;
|
|
147
|
+
const o = e.substring(0, e.lastIndexOf("/") + 1);
|
|
148
|
+
if (this.onWasmProgress && typeof fetch < "u" && !S()) {
|
|
149
|
+
const s = await this.fetchWithProgress(o + "perl.wasm");
|
|
150
|
+
return await n({
|
|
151
|
+
...t,
|
|
152
|
+
locateFile: (i) => o + i,
|
|
153
|
+
wasmBinary: s
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return await n({
|
|
157
|
+
...t,
|
|
158
|
+
locateFile: (s) => o + s
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async fetchWithProgress(t) {
|
|
162
|
+
const e = await fetch(t);
|
|
163
|
+
if (!e.ok)
|
|
164
|
+
throw new Error(`Failed to fetch ${t}: ${e.status} ${e.statusText}`);
|
|
165
|
+
const n = e.headers.get("content-length"), o = n ? parseInt(n, 10) : null, s = e.body.getReader(), i = [];
|
|
166
|
+
let a = 0;
|
|
167
|
+
for (; ; ) {
|
|
168
|
+
const { done: u, value: h } = await s.read();
|
|
169
|
+
if (u) break;
|
|
170
|
+
i.push(h), a += h.byteLength, this.onWasmProgress(a, o);
|
|
171
|
+
}
|
|
172
|
+
const c = new Uint8Array(a);
|
|
173
|
+
let l = 0;
|
|
174
|
+
for (const u of i)
|
|
175
|
+
c.set(u, l), l += u.byteLength;
|
|
176
|
+
return c;
|
|
177
|
+
}
|
|
178
|
+
async importModuleFactory(t) {
|
|
179
|
+
if (S()) {
|
|
180
|
+
const s = await import(
|
|
181
|
+
/* @vite-ignore */
|
|
182
|
+
t
|
|
183
|
+
);
|
|
184
|
+
return s.default ?? s;
|
|
185
|
+
}
|
|
186
|
+
const e = await fetch(t);
|
|
187
|
+
if (!e.ok)
|
|
188
|
+
throw new Error(`Failed to fetch ${t}: ${e.status} ${e.statusText}`);
|
|
189
|
+
const n = await e.text();
|
|
190
|
+
return new Function(
|
|
191
|
+
"exports",
|
|
192
|
+
"module",
|
|
193
|
+
"define",
|
|
194
|
+
`${n}
|
|
195
|
+
return createPerlModule;`
|
|
196
|
+
)(void 0, void 0, void 0);
|
|
197
|
+
}
|
|
198
|
+
defaultWasmUrl() {
|
|
199
|
+
return new URL(
|
|
200
|
+
/* @vite-ignore */
|
|
201
|
+
"../wasm/perl.js",
|
|
202
|
+
import.meta.url
|
|
203
|
+
).href;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Run exiftool over in-memory files. Only one run happens at a time (Perl is
|
|
207
|
+
* single-threaded). `result.files` holds the files the run changed.
|
|
208
|
+
*/
|
|
209
|
+
async exec(t, e) {
|
|
210
|
+
const n = [...e].map(([i, a]) => ({ name: i, source: a })), { committed: o, ...s } = await this.run(t, n);
|
|
211
|
+
return s;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Run exiftool over any mix of in-memory files and file references.
|
|
215
|
+
*
|
|
216
|
+
* If every input is bytes, they are staged in MEMFS. Otherwise each input
|
|
217
|
+
* gets its own wopfs mount, so referenced files are read in place rather
|
|
218
|
+
* than copied in. Both use the same layout, `/wexiftool/<i>/<name>`, and
|
|
219
|
+
* both make inputs read-only, so exiftool sees identical files and produces
|
|
220
|
+
* identical output either way.
|
|
221
|
+
*/
|
|
222
|
+
async run(t, e, n = {}) {
|
|
223
|
+
return await this.init(), e = await tt(t, e), this.enqueue(
|
|
224
|
+
() => {
|
|
225
|
+
var o;
|
|
226
|
+
return e.some((s) => !(s.source instanceof Uint8Array)) || (o = n.outputs) != null && o.length ? this.runMounted(t, e, n) : this.runStaged(t, e);
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
runStaged(t, e) {
|
|
231
|
+
const n = this.module.FS, o = e.map((i, a) => `${g}/${a}/${E(i)}`), s = /* @__PURE__ */ new Map();
|
|
232
|
+
try {
|
|
233
|
+
e.forEach((a, c) => {
|
|
234
|
+
n.mkdir(`${g}/${c}`), n.writeFile(o[c], a.source), n.chmod(o[c], 292), s.set(o[c], U(n, o[c]));
|
|
235
|
+
});
|
|
236
|
+
const i = this.callExiftool(t, e, o, /* @__PURE__ */ new Map());
|
|
237
|
+
return e.forEach((a, c) => {
|
|
238
|
+
if (U(n, o[c]) !== s.get(o[c]))
|
|
239
|
+
try {
|
|
240
|
+
i.files.set(a.name, n.readFile(o[c]));
|
|
241
|
+
} catch {
|
|
242
|
+
}
|
|
243
|
+
}), { ...i, committed: /* @__PURE__ */ new Map() };
|
|
244
|
+
} finally {
|
|
245
|
+
e.forEach((i, a) => C(n, `${g}/${a}`));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async runMounted(t, e, n) {
|
|
249
|
+
var c;
|
|
250
|
+
if (S() && !globalThis.crypto) {
|
|
251
|
+
const { webcrypto: l } = await import(
|
|
252
|
+
/* @vite-ignore */
|
|
253
|
+
"node:crypto"
|
|
254
|
+
);
|
|
255
|
+
Object.defineProperty(globalThis, "crypto", { value: l, configurable: !0, writable: !0 });
|
|
256
|
+
}
|
|
257
|
+
const { mountFiles: o } = await import("./index-C7MUqxoE.js").then((l) => l.a), s = this.module, i = e.map((l, u) => `${g}/${u}/${E(l)}`), a = [];
|
|
258
|
+
try {
|
|
259
|
+
for (const [m, d] of e.entries()) {
|
|
260
|
+
const y = ((c = d.commitTo) == null ? void 0 : c.dir) ?? (n.readOnly ? void 0 : n.privateDir);
|
|
261
|
+
if (y === void 0 && !n.readOnly)
|
|
262
|
+
throw new Error(`Input "${d.name}" is mounted, so the run needs a privateDir, a commitTo or readOnly`);
|
|
263
|
+
a.push(
|
|
264
|
+
await o(s, `${g}/${m}`, {
|
|
265
|
+
inputs: { [E(d)]: d.source },
|
|
266
|
+
outputDir: y,
|
|
267
|
+
// Read-only: no outputDir, so wopfs creates no scratch directory or
|
|
268
|
+
// pool, and anything exiftool tried to create would fail with
|
|
269
|
+
// EROFS. Otherwise exiftool creates one temp file per file it
|
|
270
|
+
// writes, and spill covers anything unexpected.
|
|
271
|
+
scratch: y === void 0 ? 0 : n.scratch ?? 1,
|
|
272
|
+
onExhausted: "spill",
|
|
273
|
+
backend: n.backend
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
const l = n.outputs ?? [], u = /* @__PURE__ */ new Map();
|
|
278
|
+
for (const [m, d] of l.entries()) {
|
|
279
|
+
const y = `${g}/o${m}`;
|
|
280
|
+
a.push(
|
|
281
|
+
await o(s, y, {
|
|
282
|
+
inputs: Object.fromEntries(d.existing.map((w) => [w, `${d.dir}/${w}`])),
|
|
283
|
+
outputDir: d.dir,
|
|
284
|
+
// A directory gets a file per input (-o DIR/).
|
|
285
|
+
scratch: n.scratch ?? (d.file === void 0 ? Math.max(1, e.length) : 1),
|
|
286
|
+
onExhausted: "spill",
|
|
287
|
+
backend: n.backend
|
|
288
|
+
})
|
|
289
|
+
), u.set(d.name, d.file === void 0 ? `${y}/` : `${y}/${d.file}`);
|
|
290
|
+
}
|
|
291
|
+
const h = this.callExiftool(t, e, i, u), f = /* @__PURE__ */ new Map();
|
|
292
|
+
for (const [m, d] of e.entries()) {
|
|
293
|
+
const y = await a[m].commit(), w = y.find((p) => p.path === E(d));
|
|
294
|
+
if (d.commitTo)
|
|
295
|
+
w && f.set(d.name, w);
|
|
296
|
+
else
|
|
297
|
+
for (const p of y)
|
|
298
|
+
p === w && h.files.set(d.name, await it(p)), await st(p, n.privateDir);
|
|
299
|
+
}
|
|
300
|
+
for (const [m, d] of l.entries())
|
|
301
|
+
for (const y of await a[e.length + m].commit())
|
|
302
|
+
f.set(d.file === void 0 ? ot(d.name, y.path) : d.name, y);
|
|
303
|
+
return { ...h, committed: f };
|
|
304
|
+
} finally {
|
|
305
|
+
for (const l of a) await l.release();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Map names in `args` to their paths, run exiftool, and map paths in its
|
|
310
|
+
* output back to names. Synchronous: everything callMain touches must
|
|
311
|
+
* already be in place.
|
|
312
|
+
*/
|
|
313
|
+
callExiftool(t, e, n, o) {
|
|
314
|
+
const s = this.module, i = new Map(e.map((f, m) => [f.name, n[m]])), a = [Q], c = /* @__PURE__ */ new Set();
|
|
315
|
+
for (const f of t) {
|
|
316
|
+
if (f.toLowerCase() === "-overwrite_original_in_place") {
|
|
317
|
+
a.push("-overwrite_original");
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const m = i.get(f) ?? o.get(f);
|
|
321
|
+
if (m !== void 0) {
|
|
322
|
+
c.add(f), a.push(m);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
const d = nt.exec(f), y = d ? i.get(d[2]) : void 0;
|
|
326
|
+
if (d && y !== void 0) {
|
|
327
|
+
c.add(d[2]), a.push(d[1] + y);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
a.push(f);
|
|
331
|
+
}
|
|
332
|
+
for (const f of e)
|
|
333
|
+
c.has(f.name) || a.push(i.get(f.name));
|
|
334
|
+
let l = "", u = "";
|
|
335
|
+
this.stdoutSink = (f) => {
|
|
336
|
+
l += f + `
|
|
337
|
+
`;
|
|
338
|
+
}, this.stderrSink = (f) => {
|
|
339
|
+
u += f + `
|
|
340
|
+
`;
|
|
341
|
+
};
|
|
342
|
+
let h;
|
|
343
|
+
try {
|
|
344
|
+
h = s.callMain(a);
|
|
345
|
+
} catch (f) {
|
|
346
|
+
if (f.status !== void 0)
|
|
347
|
+
h = f.status;
|
|
348
|
+
else
|
|
349
|
+
throw f;
|
|
350
|
+
} finally {
|
|
351
|
+
this.stdoutSink = null, this.stderrSink = null;
|
|
352
|
+
}
|
|
353
|
+
for (const [f, m] of [...i, ...o])
|
|
354
|
+
l = l.replaceAll(m, f), u = u.replaceAll(m, f);
|
|
355
|
+
return e.forEach((f, m) => {
|
|
356
|
+
const d = new RegExp(`${g}/${m}(?![0-9])`, "g"), y = f.name.lastIndexOf("/"), w = y > 0 ? f.name.slice(0, y) : y === 0 ? "/" : ".";
|
|
357
|
+
l = l.replace(d, () => w), u = u.replace(d, () => w);
|
|
358
|
+
}), { stdout: l.trimEnd(), stderr: u.trimEnd(), exitCode: h, files: /* @__PURE__ */ new Map() };
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Serialize runs. A run spans awaits (mounting, committing), so this is a
|
|
362
|
+
* promise chain rather than a flag: the next run starts only when the
|
|
363
|
+
* previous one has fully settled.
|
|
364
|
+
*/
|
|
365
|
+
enqueue(t) {
|
|
366
|
+
const e = this.tail.then(t, t);
|
|
367
|
+
return this.tail = e.catch(() => {
|
|
368
|
+
}), e;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Release WASM module resources.
|
|
372
|
+
*/
|
|
373
|
+
destroy() {
|
|
374
|
+
this.module = null, this.modulePromise = null, this.createModule = null, this.tail = Promise.resolve();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
async function tt(r, t) {
|
|
378
|
+
var a;
|
|
379
|
+
const e = r.findIndex((c) => c.toLowerCase() === "-csvdelim"), n = e >= 0 ? (a = r[e + 1]) == null ? void 0 : a.replaceAll("\\t", " ") : void 0, o = (c, l) => `${g}/${l}/${E(c)}`, s = (c) => {
|
|
380
|
+
const l = c.toLowerCase(), u = t.findIndex(
|
|
381
|
+
(h) => h.name === c || h.name.toLowerCase() === l || typeof h.source == "string" && (h.source === c || h.source.toLowerCase() === l)
|
|
382
|
+
);
|
|
383
|
+
return u < 0 ? void 0 : o(t[u], u);
|
|
384
|
+
}, i = [...t];
|
|
385
|
+
for (const c of r) {
|
|
386
|
+
const l = rt.exec(c), u = l ? t.findIndex((m) => m.name === l[2]) : -1;
|
|
387
|
+
if (!l || u < 0) continue;
|
|
388
|
+
const h = l[1].toLowerCase() === "csv" ? "csv" : "json", f = G(h, await et(t[u].source), s, n);
|
|
389
|
+
i[u] = { name: t[u].name, source: f };
|
|
390
|
+
}
|
|
391
|
+
return i;
|
|
392
|
+
}
|
|
393
|
+
async function et(r) {
|
|
394
|
+
if (r instanceof Uint8Array) return r;
|
|
395
|
+
if (typeof r == "string") {
|
|
396
|
+
const { readFile: t } = await import(
|
|
397
|
+
/* @vite-ignore */
|
|
398
|
+
"node:fs/promises"
|
|
399
|
+
);
|
|
400
|
+
return new Uint8Array(await t(r));
|
|
401
|
+
}
|
|
402
|
+
return new Uint8Array(await (await r.getFile()).arrayBuffer());
|
|
403
|
+
}
|
|
404
|
+
const rt = /^-(csv|j|json)\+?=(.+)$/i, nt = /^(-(?:csv|j|json)\+?=|-geotag=)(.+)$/i;
|
|
405
|
+
function ot(r, t) {
|
|
406
|
+
return r.endsWith("/") ? r + t : `${r}/${t}`;
|
|
407
|
+
}
|
|
408
|
+
function S() {
|
|
409
|
+
var r;
|
|
410
|
+
return typeof process < "u" && !!((r = process.versions) != null && r.node);
|
|
411
|
+
}
|
|
412
|
+
function E(r) {
|
|
413
|
+
var e;
|
|
414
|
+
const t = (((e = r.commitTo) == null ? void 0 : e.as) ?? r.name).split("/").pop();
|
|
415
|
+
return t && t !== "." && t !== ".." ? t : "input.bin";
|
|
416
|
+
}
|
|
417
|
+
function U(r, t) {
|
|
418
|
+
try {
|
|
419
|
+
const e = r.stat(t);
|
|
420
|
+
return `${e.ino}:${e.size}:${+e.mtime}`;
|
|
421
|
+
} catch {
|
|
422
|
+
return "missing";
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function C(r, t) {
|
|
426
|
+
let e;
|
|
427
|
+
try {
|
|
428
|
+
e = r.readdir(t);
|
|
429
|
+
} catch {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
for (const n of e) {
|
|
433
|
+
if (n === "." || n === "..") continue;
|
|
434
|
+
const o = `${t}/${n}`;
|
|
435
|
+
try {
|
|
436
|
+
r.unlink(o);
|
|
437
|
+
} catch {
|
|
438
|
+
C(r, o);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
r.rmdir(t);
|
|
443
|
+
} catch {
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
async function it(r) {
|
|
447
|
+
if (r.handle) return new Uint8Array(await (await r.handle.getFile()).arrayBuffer());
|
|
448
|
+
if (r.hostPath) {
|
|
449
|
+
const { readFile: t } = await import(
|
|
450
|
+
/* @vite-ignore */
|
|
451
|
+
"node:fs/promises"
|
|
452
|
+
);
|
|
453
|
+
return new Uint8Array(await t(r.hostPath));
|
|
454
|
+
}
|
|
455
|
+
return r.bytes ?? new Uint8Array();
|
|
456
|
+
}
|
|
457
|
+
async function st(r, t) {
|
|
458
|
+
if (r.hostPath) {
|
|
459
|
+
const { rm: e } = await import(
|
|
460
|
+
/* @vite-ignore */
|
|
461
|
+
"node:fs/promises"
|
|
462
|
+
);
|
|
463
|
+
await e(r.hostPath, { force: !0 });
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (typeof t != "string") {
|
|
467
|
+
const e = r.path.split("/"), n = e.pop();
|
|
468
|
+
let o = t;
|
|
469
|
+
for (const s of e) o = await o.getDirectoryHandle(s);
|
|
470
|
+
await o.removeEntry(n).catch(() => {
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function b(r) {
|
|
475
|
+
return typeof r == "object" && r !== null && r.kind === "file" && typeof r.getFile == "function";
|
|
476
|
+
}
|
|
477
|
+
async function x(r) {
|
|
478
|
+
if (r instanceof Uint8Array)
|
|
479
|
+
return { name: "input.bin", data: r };
|
|
480
|
+
if (r instanceof ArrayBuffer)
|
|
481
|
+
return { name: "input.bin", data: new Uint8Array(r) };
|
|
482
|
+
if (b(r)) {
|
|
483
|
+
const t = await r.getFile();
|
|
484
|
+
return { name: r.name || "input.bin", data: new Uint8Array(await t.arrayBuffer()) };
|
|
485
|
+
}
|
|
486
|
+
if (typeof File < "u" && r instanceof File) {
|
|
487
|
+
const t = await r.arrayBuffer();
|
|
488
|
+
return { name: r.name || "input.bin", data: new Uint8Array(t) };
|
|
489
|
+
}
|
|
490
|
+
if (typeof Blob < "u" && r instanceof Blob) {
|
|
491
|
+
const t = await r.arrayBuffer();
|
|
492
|
+
return { name: "input.bin", data: new Uint8Array(t) };
|
|
493
|
+
}
|
|
494
|
+
throw new Error("Unsupported input type");
|
|
495
|
+
}
|
|
496
|
+
async function at(r, t) {
|
|
497
|
+
const e = ct(t);
|
|
498
|
+
if (typeof r.createSyncAccessHandle == "function") {
|
|
499
|
+
let n;
|
|
500
|
+
try {
|
|
501
|
+
n = await r.createSyncAccessHandle();
|
|
502
|
+
} catch (o) {
|
|
503
|
+
if (typeof r.createWritable != "function") throw o;
|
|
504
|
+
return D(r, e);
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
n.truncate(0);
|
|
508
|
+
let o = 0;
|
|
509
|
+
for (; o < e.byteLength; ) {
|
|
510
|
+
const s = o === 0 ? e : e.slice(o), i = n.write(s, { at: o });
|
|
511
|
+
if (i <= 0)
|
|
512
|
+
throw new Error(`Short write to ${r.name} at byte ${o} of ${e.byteLength}`);
|
|
513
|
+
o += i;
|
|
514
|
+
}
|
|
515
|
+
n.flush();
|
|
516
|
+
} finally {
|
|
517
|
+
n.close();
|
|
518
|
+
}
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (typeof r.createWritable == "function")
|
|
522
|
+
return D(r, e);
|
|
523
|
+
throw new Error(
|
|
524
|
+
`Cannot write to file handle "${r.name}": it has neither createSyncAccessHandle() (dedicated workers only) nor createWritable().`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
async function D(r, t) {
|
|
528
|
+
const e = await r.createWritable();
|
|
529
|
+
try {
|
|
530
|
+
await e.write(t), await e.close();
|
|
531
|
+
} catch (n) {
|
|
532
|
+
throw await e.abort(n).catch(() => {
|
|
533
|
+
}), n;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function ct(r) {
|
|
537
|
+
const { buffer: t, byteOffset: e, byteLength: n } = r;
|
|
538
|
+
return t instanceof ArrayBuffer && e === 0 && n === t.byteLength ? t : r.slice().buffer;
|
|
539
|
+
}
|
|
540
|
+
const lt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
541
|
+
__proto__: null,
|
|
542
|
+
isFileHandle: b,
|
|
543
|
+
resolveInput: x,
|
|
544
|
+
writeToHandle: at
|
|
545
|
+
}, Symbol.toStringTag, { value: "Module" })), B = ".wexiftool";
|
|
546
|
+
function M() {
|
|
547
|
+
var s, i;
|
|
548
|
+
const r = globalThis, t = !!((i = (s = r.process) == null ? void 0 : s.versions) != null && i.node) && typeof r.window > "u", e = r.DedicatedWorkerGlobalScope, n = r.FileSystemFileHandle, o = !t && typeof e == "function" && globalThis instanceof e && !!(n && "createSyncAccessHandle" in n.prototype);
|
|
549
|
+
return { node: t, opfs: o };
|
|
550
|
+
}
|
|
551
|
+
async function W(r, t, e, n) {
|
|
552
|
+
if (typeof t == "string") {
|
|
553
|
+
if (!e.node) throw new Error(`"${t}": file paths are only supported under Node`);
|
|
554
|
+
const { resolve: s, dirname: i, basename: a } = await import(
|
|
555
|
+
/* @vite-ignore */
|
|
556
|
+
"node:path"
|
|
557
|
+
), c = s(t);
|
|
558
|
+
if (n === void 0) return { input: { name: r, source: c } };
|
|
559
|
+
if (typeof n != "string") return { input: { name: r, source: c }, writeAfter: n };
|
|
560
|
+
const l = s(n);
|
|
561
|
+
return a(l) !== a(c) ? { input: { name: r, source: c }, writeAfter: l } : { input: { name: r, source: c, commitTo: { dir: i(l), as: a(l) } } };
|
|
562
|
+
}
|
|
563
|
+
if (b(t) && e.opfs && await _(t)) {
|
|
564
|
+
const s = t;
|
|
565
|
+
if (n === void 0) return { input: { name: r, source: s } };
|
|
566
|
+
const i = b(n) && n.name === t.name ? await wt(n) : null;
|
|
567
|
+
return i ? { input: { name: r, source: s, commitTo: { dir: i, as: n.name } } } : { input: { name: r, source: s }, writeAfter: n };
|
|
568
|
+
}
|
|
569
|
+
const { data: o } = await x(t);
|
|
570
|
+
return { input: { name: r, source: o }, writeAfter: n };
|
|
571
|
+
}
|
|
572
|
+
const F = /* @__PURE__ */ new WeakMap();
|
|
573
|
+
async function ut(r, t) {
|
|
574
|
+
try {
|
|
575
|
+
const e = await dt(t);
|
|
576
|
+
e && await e.isSameEntry(r) && F.set(r, t);
|
|
577
|
+
} catch {
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async function ft(r) {
|
|
581
|
+
return (await navigator.storage.getDirectory()).resolve(r);
|
|
582
|
+
}
|
|
583
|
+
async function dt(r) {
|
|
584
|
+
if (r.length === 0) return null;
|
|
585
|
+
let t = await navigator.storage.getDirectory();
|
|
586
|
+
for (const e of r.slice(0, -1)) t = await t.getDirectoryHandle(e);
|
|
587
|
+
return t.getFileHandle(r[r.length - 1]);
|
|
588
|
+
}
|
|
589
|
+
const ht = 5e3;
|
|
590
|
+
async function _(r) {
|
|
591
|
+
const t = F.get(r);
|
|
592
|
+
if (t) return t;
|
|
593
|
+
const n = [[await navigator.storage.getDirectory(), []]];
|
|
594
|
+
let o = 0;
|
|
595
|
+
for (; n.length > 0; ) {
|
|
596
|
+
const [s, i] = n.shift();
|
|
597
|
+
for await (const [a, c] of s.entries()) {
|
|
598
|
+
if (++o > ht) return null;
|
|
599
|
+
if (c.kind === "file") {
|
|
600
|
+
if (a === r.name && await c.isSameEntry(r)) {
|
|
601
|
+
const l = [...i, a];
|
|
602
|
+
return F.set(r, l), l;
|
|
603
|
+
}
|
|
604
|
+
} else i.length === 0 && a === B || n.push([c, [...i, a]]);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
async function wt(r) {
|
|
610
|
+
const t = await _(r);
|
|
611
|
+
if (!t) return null;
|
|
612
|
+
let e = await navigator.storage.getDirectory();
|
|
613
|
+
for (const n of t.slice(0, -1)) e = await e.getDirectoryHandle(n);
|
|
614
|
+
return e;
|
|
615
|
+
}
|
|
616
|
+
async function H(r, t) {
|
|
617
|
+
if (r.node) {
|
|
618
|
+
const { mkdtemp: i, rm: a } = await import(
|
|
619
|
+
/* @vite-ignore */
|
|
620
|
+
"node:fs/promises"
|
|
621
|
+
), { tmpdir: c } = await import(
|
|
622
|
+
/* @vite-ignore */
|
|
623
|
+
"node:os"
|
|
624
|
+
), { join: l } = await import(
|
|
625
|
+
/* @vite-ignore */
|
|
626
|
+
"node:path"
|
|
627
|
+
), u = await i(l(c(), "wexiftool-"));
|
|
628
|
+
try {
|
|
629
|
+
return await t(u);
|
|
630
|
+
} finally {
|
|
631
|
+
await a(u, { recursive: !0, force: !0 });
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const e = globalThis.crypto.randomUUID().slice(0, 8), o = await (await navigator.storage.getDirectory()).getDirectoryHandle(B, { create: !0 }), s = await o.getDirectoryHandle(e, { create: !0 });
|
|
635
|
+
try {
|
|
636
|
+
return await t(s);
|
|
637
|
+
} finally {
|
|
638
|
+
await o.removeEntry(e, { recursive: !0 }).catch(() => {
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
async function T(r, t) {
|
|
643
|
+
if (typeof r == "string") {
|
|
644
|
+
const { writeFile: n } = await import(
|
|
645
|
+
/* @vite-ignore */
|
|
646
|
+
"node:fs/promises"
|
|
647
|
+
);
|
|
648
|
+
await n(r, t);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const { writeToHandle: e } = await Promise.resolve().then(() => lt);
|
|
652
|
+
await e(r, t);
|
|
653
|
+
}
|
|
654
|
+
const mt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
655
|
+
__proto__: null,
|
|
656
|
+
detectEnvironment: M,
|
|
657
|
+
planInput: W,
|
|
658
|
+
registerHint: ut,
|
|
659
|
+
resolveOnCallerSide: ft,
|
|
660
|
+
withPrivateDir: H,
|
|
661
|
+
writeRef: T
|
|
662
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
663
|
+
function yt(r) {
|
|
664
|
+
const t = r, e = [];
|
|
665
|
+
return "input" in t && e.push(t.input), t.inputs && e.push(...t.inputs), t.files && e.push(...t.files.values()), t.options && "output" in t.options && e.push(t.options.output), e.filter(b);
|
|
666
|
+
}
|
|
667
|
+
class R {
|
|
668
|
+
constructor(t, e) {
|
|
669
|
+
this.port = t, this.onWasmProgress = e, this.nextId = 1, this.pending = /* @__PURE__ */ new Map(), this.destroyed = !1, t.addEventListener("message", (n) => this.receive(n.data)), t.addEventListener("error", (n) => this.failAll(gt(n, "Worker error"))), t.addEventListener(
|
|
670
|
+
"messageerror",
|
|
671
|
+
() => this.failAll("Worker sent a message that could not be deserialized")
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Load the WASM module inside `worker` and resolve once it's ready.
|
|
676
|
+
*/
|
|
677
|
+
static async create(t, e) {
|
|
678
|
+
const n = new R(t, e == null ? void 0 : e.onWasmProgress);
|
|
679
|
+
return await n.call({
|
|
680
|
+
op: "init",
|
|
681
|
+
options: { wasmUrl: e == null ? void 0 : e.wasmUrl, progress: !!(e != null && e.onWasmProgress) }
|
|
682
|
+
}), n;
|
|
683
|
+
}
|
|
684
|
+
read(t) {
|
|
685
|
+
return this.call({ op: "read", input: t });
|
|
686
|
+
}
|
|
687
|
+
readMany(t) {
|
|
688
|
+
return this.call({ op: "readMany", inputs: t });
|
|
689
|
+
}
|
|
690
|
+
readRaw(t, e) {
|
|
691
|
+
return this.call({ op: "readRaw", input: t, args: e });
|
|
692
|
+
}
|
|
693
|
+
write(t, e, n) {
|
|
694
|
+
return this.call({ op: "write", input: t, tags: e, options: n });
|
|
695
|
+
}
|
|
696
|
+
exec(t, e, n) {
|
|
697
|
+
return this.call({ op: "exec", args: t, files: e, options: n });
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Free the module. Terminates the worker when given a real `Worker`, which
|
|
701
|
+
* releases its memory outright; otherwise asks it to drop the module.
|
|
702
|
+
*/
|
|
703
|
+
async destroy() {
|
|
704
|
+
if (this.destroyed = !0, typeof this.port.terminate == "function") {
|
|
705
|
+
this.port.terminate(), this.failAll("WExifToolWorker was destroyed");
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
await this.call({ op: "destroy" });
|
|
709
|
+
}
|
|
710
|
+
async call(t) {
|
|
711
|
+
const e = this.nextId++, n = await pt(t);
|
|
712
|
+
if (this.destroyed && t.op !== "destroy") throw new Error("WExifToolWorker was destroyed");
|
|
713
|
+
return new Promise((o, s) => {
|
|
714
|
+
this.pending.set(e, { resolve: o, reject: s });
|
|
715
|
+
try {
|
|
716
|
+
this.port.postMessage({ ...t, id: e, hints: n });
|
|
717
|
+
} catch (i) {
|
|
718
|
+
this.pending.delete(e), s(i instanceof Error ? i : new Error(String(i)));
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
receive(t) {
|
|
723
|
+
var n;
|
|
724
|
+
if (t.kind === "progress") {
|
|
725
|
+
(n = this.onWasmProgress) == null || n.call(this, t.loaded, t.total);
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
const e = this.pending.get(t.id);
|
|
729
|
+
e && (this.pending.delete(t.id), t.ok ? e.resolve(t.value) : e.reject(new Error(t.error)));
|
|
730
|
+
}
|
|
731
|
+
failAll(t) {
|
|
732
|
+
const e = new Error(t);
|
|
733
|
+
for (const n of this.pending.values()) n.reject(e);
|
|
734
|
+
this.pending.clear();
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
async function pt(r) {
|
|
738
|
+
var o, s;
|
|
739
|
+
const t = globalThis;
|
|
740
|
+
if (typeof t.window > "u" || typeof ((s = (o = t.navigator) == null ? void 0 : o.storage) == null ? void 0 : s.getDirectory) != "function") return;
|
|
741
|
+
const e = yt(r);
|
|
742
|
+
if (e.length === 0) return;
|
|
743
|
+
const { resolveOnCallerSide: n } = await Promise.resolve().then(() => mt);
|
|
744
|
+
return Promise.all(e.map((i) => n(i).catch(() => null)));
|
|
745
|
+
}
|
|
746
|
+
function gt(r, t) {
|
|
747
|
+
const e = r == null ? void 0 : r.message;
|
|
748
|
+
return typeof e == "string" && e ? `${t}: ${e}` : t;
|
|
749
|
+
}
|
|
750
|
+
class N {
|
|
751
|
+
constructor(t) {
|
|
752
|
+
this.glue = t;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Create and initialize a WExifTool instance.
|
|
756
|
+
* The WASM module is lazy-loaded on first use.
|
|
757
|
+
*/
|
|
758
|
+
static async create(t) {
|
|
759
|
+
const e = new Z(t == null ? void 0 : t.wasmUrl, t == null ? void 0 : t.onWasmProgress);
|
|
760
|
+
return await e.init(), new N(e);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Read all metadata from a file.
|
|
764
|
+
* Returns a record of tag names to values.
|
|
765
|
+
*
|
|
766
|
+
* A host path (Node) or an OPFS file handle (in a dedicated worker) is read
|
|
767
|
+
* in place, without copying the file into memory.
|
|
768
|
+
*/
|
|
769
|
+
async read(t) {
|
|
770
|
+
const e = k(t), n = await this.runFiles(["-json", "-G", e], [[e, t]], { readOnly: !0 });
|
|
771
|
+
if (n.exitCode !== 0 && n.stderr)
|
|
772
|
+
throw new Error(`ExifTool error: ${n.stderr}`);
|
|
773
|
+
try {
|
|
774
|
+
const o = JSON.parse(n.stdout);
|
|
775
|
+
return Array.isArray(o) ? o[0] : o;
|
|
776
|
+
} catch {
|
|
777
|
+
throw new Error(`Failed to parse ExifTool output: ${n.stdout}`);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Read metadata from several files in one exiftool run, which saves
|
|
782
|
+
* starting Perl once per file. Results are in input order.
|
|
783
|
+
*
|
|
784
|
+
* A file exiftool can't read gets an entry with an `Error` tag rather than
|
|
785
|
+
* failing the batch, as with native `exiftool -json`.
|
|
786
|
+
*/
|
|
787
|
+
async readMany(t) {
|
|
788
|
+
if (t.length === 0) return [];
|
|
789
|
+
const e = bt(t.map(k)), n = await this.runFiles(
|
|
790
|
+
["-json", "-G", ...e],
|
|
791
|
+
t.map((s, i) => [e[i], s]),
|
|
792
|
+
{ readOnly: !0 }
|
|
793
|
+
);
|
|
794
|
+
let o;
|
|
795
|
+
try {
|
|
796
|
+
o = JSON.parse(n.stdout);
|
|
797
|
+
} catch {
|
|
798
|
+
throw new Error(`ExifTool error: ${n.stderr || `unparseable output: ${n.stdout}`}`);
|
|
799
|
+
}
|
|
800
|
+
if (!Array.isArray(o) || o.length !== t.length)
|
|
801
|
+
throw new Error(`ExifTool error: ${n.stderr || `expected ${t.length} results`}`);
|
|
802
|
+
return o;
|
|
803
|
+
}
|
|
804
|
+
async write(t, e, n) {
|
|
805
|
+
const o = k(t), s = Object.entries(e).map(([l, u]) => `-${l}=${u}`), i = typeof t == "string" || b(t), a = i ? (n == null ? void 0 : n.output) ?? t : void 0, c = await this.runFiles(
|
|
806
|
+
["-overwrite_original", ...s, o],
|
|
807
|
+
[[o, t]],
|
|
808
|
+
{ targets: a === void 0 ? void 0 : /* @__PURE__ */ new Map([[o, a]]) }
|
|
809
|
+
);
|
|
810
|
+
if (c.exitCode !== 0 && c.stderr)
|
|
811
|
+
throw new Error(`ExifTool error: ${c.stderr}`);
|
|
812
|
+
return i ? (!c.written.includes(o) && a !== t && await T(a, (await x(t)).data), a) : c.files.get(o) ?? (await x(t)).data;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Run exiftool with arbitrary flags and return raw stdout.
|
|
816
|
+
*/
|
|
817
|
+
async readRaw(t, e) {
|
|
818
|
+
const n = k(t), o = await this.runFiles([...e, n], [[n, t]], { scratch: 0 });
|
|
819
|
+
if (o.exitCode !== 0 && o.stderr)
|
|
820
|
+
throw new Error(`ExifTool error: ${o.stderr}`);
|
|
821
|
+
return o.stdout;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Low-level: run exiftool with arbitrary args and a map of files.
|
|
825
|
+
* This is the most flexible API — CLI and other methods build on it.
|
|
826
|
+
*
|
|
827
|
+
* Values may be bytes, file handles or (under Node) host paths. Files the
|
|
828
|
+
* run changed come back as bytes in `result.files`.
|
|
829
|
+
*
|
|
830
|
+
* With `writeBack: true`, a changed file that came from a handle or host
|
|
831
|
+
* path is written back to it instead, and its name is listed in
|
|
832
|
+
* `result.written` rather than returned as bytes. Byte inputs always come
|
|
833
|
+
* back in `result.files`.
|
|
834
|
+
*/
|
|
835
|
+
async exec(t, e, n) {
|
|
836
|
+
var c;
|
|
837
|
+
const o = [...e ?? []], s = n == null ? void 0 : n.writeBack, i = s ? new Map(
|
|
838
|
+
o.filter(
|
|
839
|
+
([l, u]) => (typeof u == "string" || b(u)) && (s === !0 || s.includes(l))
|
|
840
|
+
)
|
|
841
|
+
) : void 0, a = (c = n == null ? void 0 : n.outputs) != null && c.length ? await $t(n.outputs, o) : void 0;
|
|
842
|
+
return this.runFiles(t, o, { targets: i, outputs: a });
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Plan every input (mount or copy), run, and write back results the
|
|
846
|
+
* mounts couldn't commit in place.
|
|
847
|
+
*/
|
|
848
|
+
async runFiles(t, e, n) {
|
|
849
|
+
const o = M();
|
|
850
|
+
try {
|
|
851
|
+
return await this.runPlanned(t, e, n, o);
|
|
852
|
+
} catch (s) {
|
|
853
|
+
if (o.opfs && s instanceof z)
|
|
854
|
+
return this.runPlanned(t, e, n, { ...o, opfs: !1 });
|
|
855
|
+
throw s;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
async runPlanned(t, e, { targets: n, scratch: o, readOnly: s, outputs: i }, a) {
|
|
859
|
+
var y;
|
|
860
|
+
const c = [], l = [];
|
|
861
|
+
for (const [w, p] of e) {
|
|
862
|
+
let v = await W(w, p, a, n == null ? void 0 : n.get(w));
|
|
863
|
+
const A = v.input.source;
|
|
864
|
+
typeof A == "object" && !(A instanceof Uint8Array) && (await vt(A, l) ? v = await W(w, p, { ...a, opfs: !1 }, n == null ? void 0 : n.get(w)) : l.push(A)), c.push(v);
|
|
865
|
+
}
|
|
866
|
+
const u = c.map((w) => w.input);
|
|
867
|
+
let h;
|
|
868
|
+
if (!i && u.every((w) => w.source instanceof Uint8Array))
|
|
869
|
+
h = await this.glue.exec(t, new Map(u.map((w) => [w.name, w.source])));
|
|
870
|
+
else {
|
|
871
|
+
const w = a.node ? "node" : "opfs";
|
|
872
|
+
h = !s && u.some((p) => !p.commitTo) ? await H(
|
|
873
|
+
a,
|
|
874
|
+
(p) => this.glue.run(t, u, { privateDir: p, backend: w, scratch: o, outputs: i })
|
|
875
|
+
) : await this.glue.run(t, u, { backend: w, scratch: o, readOnly: s, outputs: i });
|
|
876
|
+
}
|
|
877
|
+
const f = [...((y = h.committed) == null ? void 0 : y.keys()) ?? []];
|
|
878
|
+
for (const { input: w, writeAfter: p } of c) {
|
|
879
|
+
const v = h.files.get(w.name);
|
|
880
|
+
p && v && (await T(p, v), h.files.delete(w.name), f.push(w.name));
|
|
881
|
+
}
|
|
882
|
+
const { committed: m, ...d } = h;
|
|
883
|
+
return { ...d, written: f };
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Free WASM module resources.
|
|
887
|
+
*/
|
|
888
|
+
destroy() {
|
|
889
|
+
this.glue.destroy();
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
function k(r) {
|
|
893
|
+
return typeof r == "string" ? r : (b(r) || typeof File < "u" && r instanceof File) && r.name || "input.bin";
|
|
894
|
+
}
|
|
895
|
+
function bt(r) {
|
|
896
|
+
const t = new Set(r), e = /* @__PURE__ */ new Map();
|
|
897
|
+
return r.map((n) => {
|
|
898
|
+
const o = (e.get(n) ?? 0) + 1;
|
|
899
|
+
if (e.set(n, o), o === 1) return n;
|
|
900
|
+
const s = n.lastIndexOf("/"), i = n.lastIndexOf("."), a = i > s + 1 ? i : n.length;
|
|
901
|
+
let c = o, l = `${n.slice(0, a)} (${c})${n.slice(a)}`;
|
|
902
|
+
for (; t.has(l); ) l = `${n.slice(0, a)} (${++c})${n.slice(a)}`;
|
|
903
|
+
return t.add(l), l;
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
async function vt(r, t) {
|
|
907
|
+
for (const e of t)
|
|
908
|
+
if (e === r || await e.isSameEntry(r)) return !0;
|
|
909
|
+
return !1;
|
|
910
|
+
}
|
|
911
|
+
async function $t(r, t) {
|
|
912
|
+
var u;
|
|
913
|
+
if (!M().node) throw new Error("exec() outputs are only supported under Node");
|
|
914
|
+
const { mkdir: e, stat: n } = await import(
|
|
915
|
+
/* @vite-ignore */
|
|
916
|
+
"node:fs/promises"
|
|
917
|
+
), { resolve: o, dirname: s, basename: i, join: a } = await import(
|
|
918
|
+
/* @vite-ignore */
|
|
919
|
+
"node:path"
|
|
920
|
+
), c = (h) => n(h).then((f) => f, () => null), l = [];
|
|
921
|
+
for (const h of r) {
|
|
922
|
+
const f = o(h), m = await c(f);
|
|
923
|
+
if (h.endsWith("/") || m != null && m.isDirectory()) {
|
|
924
|
+
const d = [];
|
|
925
|
+
for (const [y] of t) {
|
|
926
|
+
const w = i(y);
|
|
927
|
+
(u = await c(a(f, w))) != null && u.isFile() && d.push(w);
|
|
928
|
+
}
|
|
929
|
+
await e(f, { recursive: !0 }), l.push({ name: h, dir: f, existing: d });
|
|
930
|
+
} else
|
|
931
|
+
await e(s(f), { recursive: !0 }), l.push({ name: h, dir: s(f), file: i(f), existing: m ? [i(f)] : [] });
|
|
932
|
+
}
|
|
933
|
+
return l;
|
|
934
|
+
}
|
|
935
|
+
export {
|
|
936
|
+
N as W,
|
|
937
|
+
At as a,
|
|
938
|
+
Pt as b,
|
|
939
|
+
xt as c,
|
|
940
|
+
St as d,
|
|
941
|
+
z as e,
|
|
942
|
+
kt as f,
|
|
943
|
+
$ as g,
|
|
944
|
+
yt as h,
|
|
945
|
+
b as i,
|
|
946
|
+
R as j,
|
|
947
|
+
mt as m
|
|
948
|
+
};
|