@useupup/core 3.3.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/LICENSE +21 -0
- package/NOTICE +8 -0
- package/README.md +75 -0
- package/dist/browser-SXR426OQ.cjs +10 -0
- package/dist/browser-WD6T5ABJ.js +1 -0
- package/dist/chunk-2H5ICKFT.cjs +122 -0
- package/dist/chunk-6HF3I2JS.cjs +39 -0
- package/dist/chunk-6S5DQDQH.js +212 -0
- package/dist/chunk-BMQC27OE.cjs +92 -0
- package/dist/chunk-BSGQGINR.cjs +219 -0
- package/dist/chunk-CPKZ2CXD.cjs +179 -0
- package/dist/chunk-DTKDIMKT.cjs +573 -0
- package/dist/chunk-DYE5XJ6Z.cjs +2134 -0
- package/dist/chunk-E3ZCNOXG.cjs +74 -0
- package/dist/chunk-FEQY2WYY.cjs +2377 -0
- package/dist/chunk-FMURBCZ7.js +120 -0
- package/dist/chunk-FYQQRULL.js +37 -0
- package/dist/chunk-GE4LIVXP.js +133 -0
- package/dist/chunk-HFR5HZJZ.js +56 -0
- package/dist/chunk-I7ULPCA2.js +72 -0
- package/dist/chunk-MHYXDLZR.js +569 -0
- package/dist/chunk-N2SLHVAW.cjs +61 -0
- package/dist/chunk-OOPDEOTM.js +169 -0
- package/dist/chunk-PMBR3OUW.js +2359 -0
- package/dist/chunk-QK7HZIVY.cjs +144 -0
- package/dist/chunk-T2AQHY7V.cjs +59 -0
- package/dist/chunk-TRCP5FUR.js +90 -0
- package/dist/chunk-U7KL5M2H.cjs +374 -0
- package/dist/chunk-UXNPM54W.js +2108 -0
- package/dist/chunk-VV6QCQLL.js +365 -0
- package/dist/chunk-ZMS2HXLB.js +56 -0
- package/dist/context-shapes-123dd3b6.d.cts +207 -0
- package/dist/context-shapes-27b24c8f.d.ts +207 -0
- package/dist/contracts-pipeline-cf177270.d.cts +78 -0
- package/dist/contracts-pipeline-cf177270.d.ts +78 -0
- package/dist/contracts-strategies-378a16b7.d.cts +168 -0
- package/dist/contracts-strategies-378a16b7.d.ts +168 -0
- package/dist/contracts.cjs +181 -0
- package/dist/contracts.d.cts +11 -0
- package/dist/contracts.d.ts +11 -0
- package/dist/contracts.js +4 -0
- package/dist/core-141335ac.d.ts +651 -0
- package/dist/core-bea2ceca.d.cts +651 -0
- package/dist/create-worker-provider-AA5SRII6.js +58 -0
- package/dist/create-worker-provider-KJNUSSTW.cjs +60 -0
- package/dist/eligibility-ONLNJ6FB.cjs +10 -0
- package/dist/eligibility-ULFC3E4G.js +8 -0
- package/dist/error-code-map-9c44a425.d.ts +62 -0
- package/dist/error-code-map-dd5becfa.d.cts +62 -0
- package/dist/i18n/index.cjs +90 -0
- package/dist/i18n/index.d.cts +3 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +1 -0
- package/dist/index.cjs +1770 -0
- package/dist/index.d.cts +280 -0
- package/dist/index.d.ts +280 -0
- package/dist/index.js +1589 -0
- package/dist/internal.cjs +2407 -0
- package/dist/internal.d.cts +595 -0
- package/dist/internal.d.ts +595 -0
- package/dist/internal.js +2275 -0
- package/dist/pipeline/index.cjs +10 -0
- package/dist/pipeline/index.d.cts +11 -0
- package/dist/pipeline/index.d.ts +11 -0
- package/dist/pipeline/index.js +1 -0
- package/dist/pipeline-worker.cjs +199 -0
- package/dist/pipeline-worker.d.cts +2 -0
- package/dist/pipeline-worker.d.ts +2 -0
- package/dist/pipeline-worker.js +197 -0
- package/dist/resolve-locale-81feef21.d.ts +20 -0
- package/dist/resolve-locale-9cb63600.d.cts +20 -0
- package/dist/resolve-theme-01758105.d.ts +53 -0
- package/dist/resolve-theme-66cf8d98.d.cts +53 -0
- package/dist/server-mode-drive-controller-b5f8ee12.d.cts +180 -0
- package/dist/server-mode-drive-controller-b5f8ee12.d.ts +180 -0
- package/dist/steps/compress.cjs +66 -0
- package/dist/steps/compress.d.cts +10 -0
- package/dist/steps/compress.d.ts +10 -0
- package/dist/steps/compress.js +64 -0
- package/dist/steps/exif.cjs +44 -0
- package/dist/steps/exif.d.cts +5 -0
- package/dist/steps/exif.d.ts +5 -0
- package/dist/steps/exif.js +42 -0
- package/dist/steps/hash.cjs +44 -0
- package/dist/steps/hash.d.cts +5 -0
- package/dist/steps/hash.d.ts +5 -0
- package/dist/steps/hash.js +42 -0
- package/dist/steps/heic.cjs +59 -0
- package/dist/steps/heic.d.cts +5 -0
- package/dist/steps/heic.d.ts +5 -0
- package/dist/steps/heic.js +57 -0
- package/dist/steps/thumbnail.cjs +54 -0
- package/dist/steps/thumbnail.d.cts +10 -0
- package/dist/steps/thumbnail.d.ts +10 -0
- package/dist/steps/thumbnail.js +52 -0
- package/dist/strategies/index.cjs +82 -0
- package/dist/strategies/index.d.cts +187 -0
- package/dist/strategies/index.d.ts +187 -0
- package/dist/strategies/index.js +60 -0
- package/dist/strategies/tus-upload.cjs +14 -0
- package/dist/strategies/tus-upload.d.cts +15 -0
- package/dist/strategies/tus-upload.d.ts +15 -0
- package/dist/strategies/tus-upload.js +5 -0
- package/dist/theme/index.cjs +38 -0
- package/dist/theme/index.d.cts +3 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.js +1 -0
- package/dist/theme-store-2e56a674.d.cts +39 -0
- package/dist/theme-store-f13e0315.d.ts +39 -0
- package/dist/token-endpoint-5fdb4a35.d.ts +20 -0
- package/dist/token-endpoint-a7d15ab6.d.cts +20 -0
- package/dist/ui-translations-c5d00392.d.cts +455 -0
- package/dist/ui-translations-c5d00392.d.ts +455 -0
- package/dist/uploader-props-72242002.d.ts +340 -0
- package/dist/uploader-props-7f956e60.d.cts +340 -0
- package/dist/vars-d3421f6c.d.cts +240 -0
- package/dist/vars-d3421f6c.d.ts +240 -0
- package/package.json +182 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkQK7HZIVY_cjs = require('./chunk-QK7HZIVY.cjs');
|
|
4
|
+
|
|
5
|
+
// src/steps/image-utils.ts
|
|
6
|
+
function hasDocument() {
|
|
7
|
+
return typeof document !== "undefined" && "createElement" in document;
|
|
8
|
+
}
|
|
9
|
+
function clampQuality(value, fallback) {
|
|
10
|
+
if (typeof value !== "number" || Number.isNaN(value)) return fallback;
|
|
11
|
+
return Math.min(1, Math.max(0.05, value));
|
|
12
|
+
}
|
|
13
|
+
function scaleDimensions(width, height, maxWidthOrHeight) {
|
|
14
|
+
if (!maxWidthOrHeight || maxWidthOrHeight <= 0) return { width, height };
|
|
15
|
+
const largest = Math.max(width, height);
|
|
16
|
+
if (largest <= maxWidthOrHeight) return { width, height };
|
|
17
|
+
const scale = maxWidthOrHeight / largest;
|
|
18
|
+
return {
|
|
19
|
+
width: Math.max(1, Math.round(width * scale)),
|
|
20
|
+
height: Math.max(1, Math.round(height * scale))
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function outputTypeFor(file, requestedType) {
|
|
24
|
+
if (requestedType) return requestedType;
|
|
25
|
+
if (file.type === "image/png" || file.type === "image/webp")
|
|
26
|
+
return file.type;
|
|
27
|
+
return "image/jpeg";
|
|
28
|
+
}
|
|
29
|
+
function createCanvas(width, height) {
|
|
30
|
+
if (typeof OffscreenCanvas !== "undefined") {
|
|
31
|
+
return new OffscreenCanvas(width, height);
|
|
32
|
+
}
|
|
33
|
+
if (!hasDocument()) return null;
|
|
34
|
+
const canvas = document.createElement("canvas");
|
|
35
|
+
canvas.width = width;
|
|
36
|
+
canvas.height = height;
|
|
37
|
+
return canvas;
|
|
38
|
+
}
|
|
39
|
+
async function canvasToBlob(canvas, type, quality) {
|
|
40
|
+
if ("convertToBlob" in canvas && typeof canvas.convertToBlob === "function") {
|
|
41
|
+
return canvas.convertToBlob({ type, quality });
|
|
42
|
+
}
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
canvas.toBlob(
|
|
45
|
+
(blob) => {
|
|
46
|
+
resolve(blob);
|
|
47
|
+
},
|
|
48
|
+
type,
|
|
49
|
+
quality
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function decodeImage(file) {
|
|
54
|
+
if (typeof createImageBitmap === "function") {
|
|
55
|
+
try {
|
|
56
|
+
const bitmap = await createImageBitmap(file);
|
|
57
|
+
return {
|
|
58
|
+
source: bitmap,
|
|
59
|
+
width: bitmap.width,
|
|
60
|
+
height: bitmap.height,
|
|
61
|
+
close: () => {
|
|
62
|
+
bitmap.close();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!hasDocument()) return null;
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
const img = new Image();
|
|
71
|
+
const url = URL.createObjectURL(file);
|
|
72
|
+
const cleanup = () => {
|
|
73
|
+
URL.revokeObjectURL(url);
|
|
74
|
+
};
|
|
75
|
+
img.onload = () => {
|
|
76
|
+
cleanup();
|
|
77
|
+
resolve({
|
|
78
|
+
source: img,
|
|
79
|
+
width: img.naturalWidth || img.width,
|
|
80
|
+
height: img.naturalHeight || img.height
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
img.onerror = () => {
|
|
84
|
+
cleanup();
|
|
85
|
+
resolve(null);
|
|
86
|
+
};
|
|
87
|
+
img.src = url;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function encodeImageFile(file, options = {}) {
|
|
91
|
+
const decoded = await decodeImage(file).catch(() => null);
|
|
92
|
+
if (!decoded) return null;
|
|
93
|
+
try {
|
|
94
|
+
const dimensions = scaleDimensions(
|
|
95
|
+
decoded.width,
|
|
96
|
+
decoded.height,
|
|
97
|
+
options.maxWidthOrHeight
|
|
98
|
+
);
|
|
99
|
+
const canvas = createCanvas(dimensions.width, dimensions.height);
|
|
100
|
+
const ctx = canvas?.getContext("2d");
|
|
101
|
+
if (!canvas || !ctx) return null;
|
|
102
|
+
ctx.drawImage(decoded.source, 0, 0, dimensions.width, dimensions.height);
|
|
103
|
+
const type = outputTypeFor(file, options.type);
|
|
104
|
+
const quality = clampQuality(options.quality, 0.82);
|
|
105
|
+
const blob = await canvasToBlob(canvas, type, quality);
|
|
106
|
+
if (!blob) return null;
|
|
107
|
+
const nextFile = new File([blob], file.name, {
|
|
108
|
+
type: blob.type || type || file.type,
|
|
109
|
+
lastModified: file.lastModified
|
|
110
|
+
});
|
|
111
|
+
return cloneUploadFile(file, nextFile, {
|
|
112
|
+
width: dimensions.width,
|
|
113
|
+
height: dimensions.height,
|
|
114
|
+
...options.metadata
|
|
115
|
+
});
|
|
116
|
+
} finally {
|
|
117
|
+
decoded.close?.();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function blobToDataUrl(blob) {
|
|
121
|
+
if (typeof FileReader !== "undefined") {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const reader = new FileReader();
|
|
124
|
+
reader.onload = () => {
|
|
125
|
+
const result = reader.result;
|
|
126
|
+
resolve(typeof result === "string" ? result : "");
|
|
127
|
+
};
|
|
128
|
+
reader.onerror = () => {
|
|
129
|
+
reject(reader.error ?? new Error("Failed to read blob"));
|
|
130
|
+
};
|
|
131
|
+
reader.readAsDataURL(blob);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
135
|
+
let binary = "";
|
|
136
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
137
|
+
const encode = typeof btoa === "function" ? btoa : globalThis.Buffer ? (input) => globalThis.Buffer.from(input, "binary").toString("base64") : null;
|
|
138
|
+
if (!encode)
|
|
139
|
+
throw new chunkQK7HZIVY_cjs.UpupError(
|
|
140
|
+
"No base64 encoder available",
|
|
141
|
+
"BAD_REQUEST" /* BAD_REQUEST */
|
|
142
|
+
);
|
|
143
|
+
return `data:${blob.type || "application/octet-stream"};base64,${encode(binary)}`;
|
|
144
|
+
}
|
|
145
|
+
async function createThumbnail(file, options = {}) {
|
|
146
|
+
const decoded = await decodeImage(file).catch(() => null);
|
|
147
|
+
if (!decoded) return null;
|
|
148
|
+
try {
|
|
149
|
+
const maxWidth = options.width ?? 320;
|
|
150
|
+
const maxHeight = options.height ?? maxWidth;
|
|
151
|
+
const scale = Math.min(
|
|
152
|
+
1,
|
|
153
|
+
maxWidth / decoded.width,
|
|
154
|
+
maxHeight / decoded.height
|
|
155
|
+
);
|
|
156
|
+
const width = Math.max(1, Math.round(decoded.width * scale));
|
|
157
|
+
const height = Math.max(1, Math.round(decoded.height * scale));
|
|
158
|
+
const canvas = createCanvas(width, height);
|
|
159
|
+
const ctx = canvas?.getContext("2d");
|
|
160
|
+
if (!canvas || !ctx) return null;
|
|
161
|
+
ctx.drawImage(decoded.source, 0, 0, width, height);
|
|
162
|
+
const type = options.type ?? "image/jpeg";
|
|
163
|
+
const quality = clampQuality(options.quality, 0.75);
|
|
164
|
+
const blob = await canvasToBlob(canvas, type, quality);
|
|
165
|
+
if (!blob) return null;
|
|
166
|
+
const ext = type === "image/png" ? "png" : type === "image/webp" ? "webp" : "jpg";
|
|
167
|
+
const thumbnailFile = new File(
|
|
168
|
+
[blob],
|
|
169
|
+
`${file.name}.thumbnail.${ext}`,
|
|
170
|
+
{
|
|
171
|
+
type: blob.type || type,
|
|
172
|
+
lastModified: file.lastModified
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
return {
|
|
176
|
+
file: thumbnailFile,
|
|
177
|
+
dataUrl: await blobToDataUrl(blob),
|
|
178
|
+
width,
|
|
179
|
+
height
|
|
180
|
+
};
|
|
181
|
+
} finally {
|
|
182
|
+
decoded.close?.();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function cloneUploadFile(original, replacement, metadata = {}) {
|
|
186
|
+
return Object.assign(replacement, {
|
|
187
|
+
id: original.id,
|
|
188
|
+
source: original.source,
|
|
189
|
+
status: original.status,
|
|
190
|
+
metadata: {
|
|
191
|
+
...original.metadata,
|
|
192
|
+
...metadata
|
|
193
|
+
},
|
|
194
|
+
url: original.url,
|
|
195
|
+
relativePath: original.relativePath,
|
|
196
|
+
key: original.key,
|
|
197
|
+
etag: original.etag,
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- v3 removal tracked
|
|
199
|
+
fileHash: original.fileHash,
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- v3 removal tracked
|
|
201
|
+
checksumSHA256: original.checksumSHA256,
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated -- v3 removal tracked
|
|
203
|
+
thumbnail: original.thumbnail
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
function uploadFileFromImageResult(original, result) {
|
|
207
|
+
const file = new File([result.bytes], result.name ?? original.name, {
|
|
208
|
+
type: result.type || original.type,
|
|
209
|
+
lastModified: original.lastModified
|
|
210
|
+
});
|
|
211
|
+
return cloneUploadFile(original, file, result.metadata ?? {});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
exports.canvasToBlob = canvasToBlob;
|
|
215
|
+
exports.cloneUploadFile = cloneUploadFile;
|
|
216
|
+
exports.createCanvas = createCanvas;
|
|
217
|
+
exports.createThumbnail = createThumbnail;
|
|
218
|
+
exports.encodeImageFile = encodeImageFile;
|
|
219
|
+
exports.uploadFileFromImageResult = uploadFileFromImageResult;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkQK7HZIVY_cjs = require('./chunk-QK7HZIVY.cjs');
|
|
4
|
+
|
|
5
|
+
// src/strategies/token-endpoint.ts
|
|
6
|
+
async function readErrorBody(response) {
|
|
7
|
+
try {
|
|
8
|
+
return await response.text();
|
|
9
|
+
} catch {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
var TokenEndpointCredentials = class {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.url = options.url;
|
|
16
|
+
this.headers = options.headers ?? {};
|
|
17
|
+
}
|
|
18
|
+
async getPresignedUrl(file) {
|
|
19
|
+
const response = await fetch(this.url, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
...this.headers
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
name: file.name,
|
|
27
|
+
size: file.size,
|
|
28
|
+
type: file.type,
|
|
29
|
+
metadata: file.metadata ?? {}
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
const body = await readErrorBody(response);
|
|
34
|
+
const error = chunkQK7HZIVY_cjs.uploadErrorFromResponse({
|
|
35
|
+
status: response.status,
|
|
36
|
+
statusText: response.statusText,
|
|
37
|
+
...body !== void 0 ? { body } : {},
|
|
38
|
+
kind: "network"
|
|
39
|
+
});
|
|
40
|
+
if (!chunkQK7HZIVY_cjs.parseErrorBody(body).message.trim()) {
|
|
41
|
+
error.message = `Presign request failed: ${response.status} ${response.statusText}`;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
return response.json();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// src/strategies/direct-upload.ts
|
|
50
|
+
var DirectUpload = class {
|
|
51
|
+
async upload(file, credentials, options) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const xhr = new XMLHttpRequest();
|
|
54
|
+
xhr.upload.addEventListener("progress", (e) => {
|
|
55
|
+
if (e.lengthComputable) {
|
|
56
|
+
options.onProgress(e.loaded, e.total);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
xhr.addEventListener("load", () => {
|
|
60
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
61
|
+
resolve({
|
|
62
|
+
key: credentials.key,
|
|
63
|
+
publicUrl: credentials.publicUrl,
|
|
64
|
+
downloadUrl: credentials.downloadUrl
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
reject(
|
|
68
|
+
chunkQK7HZIVY_cjs.uploadErrorFromResponse({
|
|
69
|
+
status: xhr.status,
|
|
70
|
+
statusText: xhr.statusText,
|
|
71
|
+
body: xhr.responseText,
|
|
72
|
+
kind: "storage",
|
|
73
|
+
operation: "upload"
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
xhr.addEventListener("error", () => {
|
|
79
|
+
reject(new chunkQK7HZIVY_cjs.UpupNetworkError("Network error during upload"));
|
|
80
|
+
});
|
|
81
|
+
xhr.addEventListener("abort", () => {
|
|
82
|
+
reject(new chunkQK7HZIVY_cjs.UpupNetworkError("Upload aborted"));
|
|
83
|
+
});
|
|
84
|
+
options.signal.addEventListener("abort", () => {
|
|
85
|
+
xhr.abort();
|
|
86
|
+
});
|
|
87
|
+
xhr.open("PUT", credentials.uploadUrl);
|
|
88
|
+
for (const [key, value] of Object.entries(
|
|
89
|
+
credentials.uploadHeaders ?? {}
|
|
90
|
+
)) {
|
|
91
|
+
xhr.setRequestHeader(key, value);
|
|
92
|
+
}
|
|
93
|
+
xhr.send(file);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/utils/multipart-session-store.ts
|
|
99
|
+
var STORAGE_PREFIX = "upup_mp_";
|
|
100
|
+
var SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
101
|
+
function fileFingerprint(file) {
|
|
102
|
+
return `${file.name}:${file.size}:${file.lastModified}:${file.type}`;
|
|
103
|
+
}
|
|
104
|
+
function storageKey(fingerprint) {
|
|
105
|
+
return `${STORAGE_PREFIX}${fingerprint}`;
|
|
106
|
+
}
|
|
107
|
+
function saveSession(fingerprint, session) {
|
|
108
|
+
try {
|
|
109
|
+
localStorage.setItem(storageKey(fingerprint), JSON.stringify(session));
|
|
110
|
+
} catch {
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function loadSession(fingerprint) {
|
|
114
|
+
try {
|
|
115
|
+
const raw = localStorage.getItem(storageKey(fingerprint));
|
|
116
|
+
if (!raw) return null;
|
|
117
|
+
const session = JSON.parse(raw);
|
|
118
|
+
if (Date.now() - session.updatedAt > SESSION_TTL_MS) {
|
|
119
|
+
removeSession(fingerprint);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return session;
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function updateSessionProgress(fingerprint, uploadedBytes) {
|
|
128
|
+
try {
|
|
129
|
+
const raw = localStorage.getItem(storageKey(fingerprint));
|
|
130
|
+
if (!raw) return;
|
|
131
|
+
const session = JSON.parse(raw);
|
|
132
|
+
session.uploadedBytes = uploadedBytes;
|
|
133
|
+
session.updatedAt = Date.now();
|
|
134
|
+
localStorage.setItem(storageKey(fingerprint), JSON.stringify(session));
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function updateSessionToken(fingerprint, token) {
|
|
139
|
+
try {
|
|
140
|
+
const raw = localStorage.getItem(storageKey(fingerprint));
|
|
141
|
+
if (!raw) return;
|
|
142
|
+
const session = JSON.parse(raw);
|
|
143
|
+
session.token = token;
|
|
144
|
+
session.updatedAt = Date.now();
|
|
145
|
+
localStorage.setItem(storageKey(fingerprint), JSON.stringify(session));
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function removeSession(fingerprint) {
|
|
150
|
+
try {
|
|
151
|
+
localStorage.removeItem(storageKey(fingerprint));
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function clearAllSessions() {
|
|
156
|
+
try {
|
|
157
|
+
const keysToRemove = [];
|
|
158
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
159
|
+
const key = localStorage.key(i);
|
|
160
|
+
if (key?.startsWith(STORAGE_PREFIX)) {
|
|
161
|
+
keysToRemove.push(key);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
keysToRemove.forEach((k) => {
|
|
165
|
+
localStorage.removeItem(k);
|
|
166
|
+
});
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
exports.DirectUpload = DirectUpload;
|
|
172
|
+
exports.TokenEndpointCredentials = TokenEndpointCredentials;
|
|
173
|
+
exports.clearAllSessions = clearAllSessions;
|
|
174
|
+
exports.fileFingerprint = fileFingerprint;
|
|
175
|
+
exports.loadSession = loadSession;
|
|
176
|
+
exports.removeSession = removeSession;
|
|
177
|
+
exports.saveSession = saveSession;
|
|
178
|
+
exports.updateSessionProgress = updateSessionProgress;
|
|
179
|
+
exports.updateSessionToken = updateSessionToken;
|