@cedarjs/uploads 7.0.1-next.314 → 7.0.1-next.466
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 +11 -0
- package/dist/authenticator.d.ts +2 -2
- package/dist/authenticator.d.ts.map +1 -1
- package/dist/cleanupStaleUploads.d.ts +4 -3
- package/dist/cleanupStaleUploads.d.ts.map +1 -1
- package/dist/cleanupStaleUploads.js +8 -2
- package/dist/contentTypes.d.ts +74 -0
- package/dist/contentTypes.d.ts.map +1 -0
- package/dist/contentTypes.js +78 -0
- package/dist/deleteFile.d.ts +19 -4
- package/dist/deleteFile.d.ts.map +1 -1
- package/dist/deleteFile.js +49 -8
- package/dist/detectContentType.d.ts +168 -0
- package/dist/detectContentType.d.ts.map +1 -0
- package/dist/detectContentType.js +443 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -1
- package/dist/fastify/plugin.d.ts +30 -2
- package/dist/fastify/plugin.d.ts.map +1 -1
- package/dist/fastify/plugin.js +38 -10
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -0
- package/dist/keys.d.ts +3 -1
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +2 -1
- package/dist/profiles.d.ts +8 -2
- package/dist/profiles.d.ts.map +1 -1
- package/dist/profiles.js +5 -4
- package/dist/providers/s3.d.ts.map +1 -1
- package/dist/providers/s3.js +16 -0
- package/dist/services.d.ts +24 -6
- package/dist/services.d.ts.map +1 -1
- package/dist/services.js +45 -10
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/variants.d.ts +207 -0
- package/dist/variants.d.ts.map +1 -0
- package/dist/variants.js +498 -0
- package/dist/verifyStoredContentType.d.ts +19 -0
- package/dist/verifyStoredContentType.d.ts.map +1 -0
- package/dist/verifyStoredContentType.js +41 -0
- package/dist/web/createUppy.d.ts +19 -2
- package/dist/web/createUppy.d.ts.map +1 -1
- package/dist/web/createUppy.js +37 -15
- package/dist/web/hooks/useFsUpload.d.ts.map +1 -1
- package/dist/web/hooks/useFsUpload.js +21 -9
- package/dist/web/hooks/useS3Upload.d.ts.map +1 -1
- package/dist/web/hooks/useS3Upload.js +12 -5
- package/dist/web/hooks/useUploadToken.d.ts +27 -1
- package/dist/web/hooks/useUploadToken.d.ts.map +1 -1
- package/dist/web/hooks/useUploadToken.js +72 -3
- package/dist/web/hooks/useUppyUpload.d.ts.map +1 -1
- package/dist/web/hooks/useUppyUpload.js +2 -8
- package/dist/webhooks/s3.d.ts +17 -8
- package/dist/webhooks/s3.d.ts.map +1 -1
- package/dist/webhooks/s3.js +22 -3
- package/package.json +18 -18
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import {
|
|
2
|
+
canonicalContentType,
|
|
3
|
+
isContentTypeListed,
|
|
4
|
+
isExplicitOnlyContentType
|
|
5
|
+
} from "./contentTypes.js";
|
|
6
|
+
import { isMimeTypeAllowed } from "./profiles.js";
|
|
7
|
+
const DETECT_CONTENT_TYPE_BYTES = 4096;
|
|
8
|
+
const DETECT_CONTENT_TYPE_TAIL_BYTES = 64 * 1024;
|
|
9
|
+
const MAX_ZIP_DIRECTORY_BYTES = 4 * 1024 * 1024;
|
|
10
|
+
const DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
11
|
+
const XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
12
|
+
const PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
13
|
+
const DOCM = "application/vnd.ms-word.document.macroenabled.12";
|
|
14
|
+
const XLSM = "application/vnd.ms-excel.sheet.macroenabled.12";
|
|
15
|
+
const PPTM = "application/vnd.ms-powerpoint.presentation.macroenabled.12";
|
|
16
|
+
const ODT = "application/vnd.oasis.opendocument.text";
|
|
17
|
+
const ODS = "application/vnd.oasis.opendocument.spreadsheet";
|
|
18
|
+
const ODP = "application/vnd.oasis.opendocument.presentation";
|
|
19
|
+
const DETECTABLE_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
20
|
+
"image/jpeg",
|
|
21
|
+
"image/png",
|
|
22
|
+
"image/gif",
|
|
23
|
+
"image/webp",
|
|
24
|
+
"image/bmp",
|
|
25
|
+
"image/tiff",
|
|
26
|
+
"image/avif",
|
|
27
|
+
"image/heic",
|
|
28
|
+
"image/heic-sequence",
|
|
29
|
+
"image/heif",
|
|
30
|
+
"image/heif-sequence",
|
|
31
|
+
"application/pdf",
|
|
32
|
+
"video/mp4",
|
|
33
|
+
"audio/mp4",
|
|
34
|
+
"video/quicktime",
|
|
35
|
+
"video/webm",
|
|
36
|
+
"video/matroska",
|
|
37
|
+
DOCX,
|
|
38
|
+
XLSX,
|
|
39
|
+
PPTX,
|
|
40
|
+
DOCM,
|
|
41
|
+
XLSM,
|
|
42
|
+
PPTM,
|
|
43
|
+
ODT,
|
|
44
|
+
ODS,
|
|
45
|
+
ODP
|
|
46
|
+
]);
|
|
47
|
+
const PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
48
|
+
const EBML_SIGNATURE = [26, 69, 223, 163];
|
|
49
|
+
const BMP_INFO_HEADER_SIZES = /* @__PURE__ */ new Set([12, 40, 52, 56, 64, 108, 124]);
|
|
50
|
+
const AVIF_BRANDS = /* @__PURE__ */ new Set(["avif", "avis"]);
|
|
51
|
+
const HEIC_BRANDS = /* @__PURE__ */ new Set(["heic", "heix", "heim", "heis"]);
|
|
52
|
+
const HEIC_SEQUENCE_BRANDS = /* @__PURE__ */ new Set(["hevc", "hevx", "hevm", "hevs"]);
|
|
53
|
+
const MP4_BRANDS = /* @__PURE__ */ new Set([
|
|
54
|
+
"isom",
|
|
55
|
+
"iso2",
|
|
56
|
+
"iso3",
|
|
57
|
+
"iso4",
|
|
58
|
+
"iso5",
|
|
59
|
+
"iso6",
|
|
60
|
+
"iso7",
|
|
61
|
+
"iso8",
|
|
62
|
+
"iso9",
|
|
63
|
+
"mp41",
|
|
64
|
+
"mp42",
|
|
65
|
+
"mp71",
|
|
66
|
+
"avc1",
|
|
67
|
+
"dash",
|
|
68
|
+
"M4V "
|
|
69
|
+
]);
|
|
70
|
+
const MP4_AUDIO_BRANDS = /* @__PURE__ */ new Set(["M4A ", "M4B "]);
|
|
71
|
+
const QUICKTIME_BRAND = "qt ";
|
|
72
|
+
const MAX_FTYP_BOX_SIZE = 1024;
|
|
73
|
+
const EBML_DOC_TYPE_ID = 17026;
|
|
74
|
+
const MAX_DOC_TYPE_LENGTH = 32;
|
|
75
|
+
function hasBytesAt(bytes, offset, expected) {
|
|
76
|
+
if (bytes.length < offset + expected.length) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
return expected.every((b, i) => bytes[offset + i] === b);
|
|
80
|
+
}
|
|
81
|
+
function ascii(bytes, start, end) {
|
|
82
|
+
if (end > bytes.length) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
let text = "";
|
|
86
|
+
for (let i = start; i < end; i++) {
|
|
87
|
+
text += String.fromCharCode(bytes[i]);
|
|
88
|
+
}
|
|
89
|
+
return text;
|
|
90
|
+
}
|
|
91
|
+
function readUint32BE(bytes, offset) {
|
|
92
|
+
if (bytes.length < offset + 4) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return bytes[offset] * 16777216 + bytes[offset + 1] * 65536 + bytes[offset + 2] * 256 + bytes[offset + 3];
|
|
96
|
+
}
|
|
97
|
+
function readUint32LE(bytes, offset) {
|
|
98
|
+
if (bytes.length < offset + 4) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return bytes[offset] + bytes[offset + 1] * 256 + bytes[offset + 2] * 65536 + bytes[offset + 3] * 16777216;
|
|
102
|
+
}
|
|
103
|
+
function detectIsoBmff(bytes) {
|
|
104
|
+
if (ascii(bytes, 4, 8) !== "ftyp") {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const boxSize = readUint32BE(bytes, 0);
|
|
108
|
+
if (boxSize === null || boxSize < 16 || boxSize % 4 !== 0 || boxSize > MAX_FTYP_BOX_SIZE) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const major = ascii(bytes, 8, 12);
|
|
112
|
+
if (major === null) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const fromMajor = classifyMajorBrand(major);
|
|
116
|
+
if (fromMajor) {
|
|
117
|
+
return fromMajor;
|
|
118
|
+
}
|
|
119
|
+
if (bytes.length < boxSize) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const compatible = [];
|
|
123
|
+
for (let offset = 16; offset + 4 <= boxSize; offset += 4) {
|
|
124
|
+
const brand = ascii(bytes, offset, offset + 4);
|
|
125
|
+
if (brand !== null) {
|
|
126
|
+
compatible.push(brand);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return classifyCompatibleBrands(major, compatible);
|
|
130
|
+
}
|
|
131
|
+
function classifyMajorBrand(major) {
|
|
132
|
+
if (AVIF_BRANDS.has(major)) {
|
|
133
|
+
return "image/avif";
|
|
134
|
+
}
|
|
135
|
+
if (HEIC_BRANDS.has(major)) {
|
|
136
|
+
return "image/heic";
|
|
137
|
+
}
|
|
138
|
+
if (HEIC_SEQUENCE_BRANDS.has(major)) {
|
|
139
|
+
return "image/heic-sequence";
|
|
140
|
+
}
|
|
141
|
+
if (major === QUICKTIME_BRAND) {
|
|
142
|
+
return "video/quicktime";
|
|
143
|
+
}
|
|
144
|
+
if (MP4_AUDIO_BRANDS.has(major)) {
|
|
145
|
+
return "audio/mp4";
|
|
146
|
+
}
|
|
147
|
+
if (MP4_BRANDS.has(major)) {
|
|
148
|
+
return "video/mp4";
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function classifyCompatibleBrands(major, compatible) {
|
|
153
|
+
const has = (brands) => compatible.some((brand) => brands.has(brand));
|
|
154
|
+
if (has(AVIF_BRANDS)) {
|
|
155
|
+
return "image/avif";
|
|
156
|
+
}
|
|
157
|
+
if (has(HEIC_BRANDS)) {
|
|
158
|
+
return "image/heic";
|
|
159
|
+
}
|
|
160
|
+
if (has(HEIC_SEQUENCE_BRANDS)) {
|
|
161
|
+
return "image/heic-sequence";
|
|
162
|
+
}
|
|
163
|
+
if (major === "mif1" || major === "mif2" || compatible.includes("mif1")) {
|
|
164
|
+
return "image/heif";
|
|
165
|
+
}
|
|
166
|
+
if (major === "msf1" || compatible.includes("msf1")) {
|
|
167
|
+
return "image/heif-sequence";
|
|
168
|
+
}
|
|
169
|
+
if (compatible.includes(QUICKTIME_BRAND)) {
|
|
170
|
+
return "video/quicktime";
|
|
171
|
+
}
|
|
172
|
+
if (has(MP4_AUDIO_BRANDS)) {
|
|
173
|
+
return "audio/mp4";
|
|
174
|
+
}
|
|
175
|
+
if (has(MP4_BRANDS)) {
|
|
176
|
+
return "video/mp4";
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
function readVint(bytes, offset, keepMarker) {
|
|
181
|
+
if (offset >= bytes.length) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const first = bytes[offset];
|
|
185
|
+
if (first === 0) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
let length = 1;
|
|
189
|
+
while (!(first & 128 >> length - 1)) {
|
|
190
|
+
length++;
|
|
191
|
+
}
|
|
192
|
+
if (offset + length > bytes.length) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const marker = 128 >> length - 1;
|
|
196
|
+
let value = keepMarker ? first : first & marker - 1;
|
|
197
|
+
let allOnes = (first & marker - 1) === marker - 1;
|
|
198
|
+
for (let i = 1; i < length; i++) {
|
|
199
|
+
const byte = bytes[offset + i];
|
|
200
|
+
value = value * 256 + byte;
|
|
201
|
+
allOnes = allOnes && byte === 255;
|
|
202
|
+
}
|
|
203
|
+
return { value, length, unknown: !keepMarker && allOnes };
|
|
204
|
+
}
|
|
205
|
+
function detectEbml(bytes) {
|
|
206
|
+
if (!hasBytesAt(bytes, 0, EBML_SIGNATURE)) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
const headerSize = readVint(bytes, EBML_SIGNATURE.length, false);
|
|
210
|
+
if (!headerSize || headerSize.unknown) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const headerStart = EBML_SIGNATURE.length + headerSize.length;
|
|
214
|
+
const headerEnd = headerStart + headerSize.value;
|
|
215
|
+
let offset = headerStart;
|
|
216
|
+
while (offset < Math.min(headerEnd, bytes.length)) {
|
|
217
|
+
const id = readVint(bytes, offset, true);
|
|
218
|
+
if (!id || id.length > 4 || offset + id.length > headerEnd) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
const size = readVint(bytes, offset + id.length, false);
|
|
222
|
+
if (!size || size.unknown) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
const dataStart = offset + id.length + size.length;
|
|
226
|
+
if (dataStart + size.value > headerEnd) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
if (id.value === EBML_DOC_TYPE_ID) {
|
|
230
|
+
let docTypeEnd = dataStart + size.value;
|
|
231
|
+
if (size.value > MAX_DOC_TYPE_LENGTH || docTypeEnd > bytes.length) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
while (docTypeEnd > dataStart && bytes[docTypeEnd - 1] === 0) {
|
|
235
|
+
docTypeEnd--;
|
|
236
|
+
}
|
|
237
|
+
switch (ascii(bytes, dataStart, docTypeEnd)) {
|
|
238
|
+
case "webm":
|
|
239
|
+
return "video/webm";
|
|
240
|
+
case "matroska":
|
|
241
|
+
return "video/matroska";
|
|
242
|
+
default:
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
offset = dataStart + size.value;
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
function detectBmp(bytes) {
|
|
251
|
+
if (ascii(bytes, 0, 2) !== "BM") {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const reserved = readUint32LE(bytes, 6);
|
|
255
|
+
const infoHeaderSize = readUint32LE(bytes, 14);
|
|
256
|
+
if (reserved === 0 && infoHeaderSize !== null && BMP_INFO_HEADER_SIZES.has(infoHeaderSize)) {
|
|
257
|
+
return "image/bmp";
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const ZIP_LOCAL_HEADER = [80, 75, 3, 4];
|
|
262
|
+
const ZIP_CENTRAL_HEADER = [80, 75, 1, 2];
|
|
263
|
+
const ZIP_END_OF_DIRECTORY = [80, 75, 5, 6];
|
|
264
|
+
const ZIP_LOCAL_HEADER_SIZE = 30;
|
|
265
|
+
const ZIP_CENTRAL_HEADER_SIZE = 46;
|
|
266
|
+
const ZIP_END_OF_DIRECTORY_SIZE = 22;
|
|
267
|
+
const ZIP_MAX_COMMENT_LENGTH = 65535;
|
|
268
|
+
const OPEN_DOCUMENT_TYPES = /* @__PURE__ */ new Set([ODT, ODS, ODP]);
|
|
269
|
+
function readUint16LE(bytes, offset) {
|
|
270
|
+
if (bytes.length < offset + 2) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
return bytes[offset] + bytes[offset + 1] * 256;
|
|
274
|
+
}
|
|
275
|
+
function detectOpenDocument(bytes) {
|
|
276
|
+
const flags = readUint16LE(bytes, 6);
|
|
277
|
+
const method = readUint16LE(bytes, 8);
|
|
278
|
+
const compressedSize = readUint32LE(bytes, 18);
|
|
279
|
+
const size = readUint32LE(bytes, 22);
|
|
280
|
+
const nameLength = readUint16LE(bytes, 26);
|
|
281
|
+
const extraLength = readUint16LE(bytes, 28);
|
|
282
|
+
if (flags === null || method === null || compressedSize === null || size === null || nameLength === null || extraLength === null) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
if (method !== 0 || flags & 8 || compressedSize !== size || size > 64) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
const nameEnd = ZIP_LOCAL_HEADER_SIZE + nameLength;
|
|
289
|
+
if (ascii(bytes, ZIP_LOCAL_HEADER_SIZE, nameEnd) !== "mimetype") {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
const contentStart = nameEnd + extraLength;
|
|
293
|
+
const content = ascii(bytes, contentStart, contentStart + size);
|
|
294
|
+
return content !== null && OPEN_DOCUMENT_TYPES.has(content) ? content : null;
|
|
295
|
+
}
|
|
296
|
+
const MAX_ZIP_END_RECORD_CANDIDATES = 16;
|
|
297
|
+
function* zipEndRecords(end) {
|
|
298
|
+
const last = end.length - ZIP_END_OF_DIRECTORY_SIZE;
|
|
299
|
+
const first = Math.max(0, last - ZIP_MAX_COMMENT_LENGTH);
|
|
300
|
+
let candidates = 0;
|
|
301
|
+
for (let offset = last; offset >= first; offset--) {
|
|
302
|
+
if (!hasBytesAt(end, offset, ZIP_END_OF_DIRECTORY) || readUint16LE(end, offset + 20) !== last - offset) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (++candidates > MAX_ZIP_END_RECORD_CANDIDATES) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const disk = readUint16LE(end, offset + 4);
|
|
309
|
+
const directoryDisk = readUint16LE(end, offset + 6);
|
|
310
|
+
const entries = readUint16LE(end, offset + 10);
|
|
311
|
+
const directorySize = readUint32LE(end, offset + 12);
|
|
312
|
+
const directoryOffset = readUint32LE(end, offset + 16);
|
|
313
|
+
if (disk !== 0 || directoryDisk !== 0 || entries === null || entries === 65535 || directorySize === null || directorySize === 4294967295 || directorySize > MAX_ZIP_DIRECTORY_BYTES || directoryOffset === null || directoryOffset === 4294967295) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
yield { recordOffset: offset, entries, directorySize, directoryOffset };
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function findZipCentralDirectory(tail) {
|
|
320
|
+
for (const record of zipEndRecords(tail)) {
|
|
321
|
+
if (record.entries > 0 && record.directorySize > 0) {
|
|
322
|
+
return { offset: record.directoryOffset, size: record.directorySize };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
function readZipEntryNames(end, { recordOffset, entries, directorySize }) {
|
|
328
|
+
let offset = recordOffset - directorySize;
|
|
329
|
+
if (offset < 0) {
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
const names = [];
|
|
333
|
+
for (let i = 0; i < entries; i++) {
|
|
334
|
+
if (!hasBytesAt(end, offset, ZIP_CENTRAL_HEADER)) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const nameLength = readUint16LE(end, offset + 28);
|
|
338
|
+
const extraLength = readUint16LE(end, offset + 30);
|
|
339
|
+
const commentLength = readUint16LE(end, offset + 32);
|
|
340
|
+
if (nameLength === null || extraLength === null || commentLength === null) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
const nameStart = offset + ZIP_CENTRAL_HEADER_SIZE;
|
|
344
|
+
const name = ascii(end, nameStart, nameStart + nameLength);
|
|
345
|
+
offset = nameStart + nameLength + extraLength + commentLength;
|
|
346
|
+
if (name === null || offset > recordOffset) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
names.push(name);
|
|
350
|
+
}
|
|
351
|
+
return offset === recordOffset ? names : null;
|
|
352
|
+
}
|
|
353
|
+
function classifyOfficeOpenXml(entryNames) {
|
|
354
|
+
const names = entryNames.map((name) => name.toLowerCase());
|
|
355
|
+
if (!names.includes("[content_types].xml")) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const families = [
|
|
359
|
+
{ prefix: "word/", plain: DOCX, macro: DOCM },
|
|
360
|
+
{ prefix: "xl/", plain: XLSX, macro: XLSM },
|
|
361
|
+
{ prefix: "ppt/", plain: PPTX, macro: PPTM }
|
|
362
|
+
].filter(({ prefix }) => names.some((name) => name.startsWith(prefix)));
|
|
363
|
+
if (families.length !== 1) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
const hasMacros = names.some(
|
|
367
|
+
(name) => name.endsWith("vbaproject.bin") || name.endsWith("vbadata.xml") || name.startsWith("xl/macrosheets/")
|
|
368
|
+
);
|
|
369
|
+
return hasMacros ? families[0].macro : families[0].plain;
|
|
370
|
+
}
|
|
371
|
+
function detectZip(bytes, tail) {
|
|
372
|
+
if (!hasBytesAt(bytes, 0, ZIP_LOCAL_HEADER)) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
const openDocument = detectOpenDocument(bytes);
|
|
376
|
+
if (openDocument) {
|
|
377
|
+
return openDocument;
|
|
378
|
+
}
|
|
379
|
+
const end = tail ?? bytes;
|
|
380
|
+
for (const record of zipEndRecords(end)) {
|
|
381
|
+
const names = readZipEntryNames(end, record);
|
|
382
|
+
const type = names && classifyOfficeOpenXml(names);
|
|
383
|
+
if (type) {
|
|
384
|
+
return type;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
function detectContentType(bytes, options = {}) {
|
|
390
|
+
if (hasBytesAt(bytes, 0, [255, 216, 255])) {
|
|
391
|
+
return "image/jpeg";
|
|
392
|
+
}
|
|
393
|
+
if (hasBytesAt(bytes, 0, PNG_SIGNATURE)) {
|
|
394
|
+
return "image/png";
|
|
395
|
+
}
|
|
396
|
+
const head6 = ascii(bytes, 0, 6);
|
|
397
|
+
if (head6 === "GIF87a" || head6 === "GIF89a") {
|
|
398
|
+
return "image/gif";
|
|
399
|
+
}
|
|
400
|
+
if (ascii(bytes, 0, 4) === "RIFF" && ascii(bytes, 8, 12) === "WEBP") {
|
|
401
|
+
return "image/webp";
|
|
402
|
+
}
|
|
403
|
+
if (ascii(bytes, 0, 5) === "%PDF-") {
|
|
404
|
+
return "application/pdf";
|
|
405
|
+
}
|
|
406
|
+
const head4 = ascii(bytes, 0, 4);
|
|
407
|
+
if (head4 === "II*\0" || head4 === "MM\0*") {
|
|
408
|
+
return "image/tiff";
|
|
409
|
+
}
|
|
410
|
+
return detectIsoBmff(bytes) ?? detectEbml(bytes) ?? detectBmp(bytes) ?? detectZip(bytes, options.tail);
|
|
411
|
+
}
|
|
412
|
+
function isClaimedContentTypeAllowed(accept, claimedType) {
|
|
413
|
+
const claimed = canonicalContentType(claimedType);
|
|
414
|
+
if (!claimed || claimed.includes("*")) {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
return isExplicitOnlyContentType(claimed) ? isContentTypeListed(accept, claimed) : isMimeTypeAllowed(accept, claimed);
|
|
418
|
+
}
|
|
419
|
+
function acceptedContentType(bytes, accept, claimedType, options = {}) {
|
|
420
|
+
const detected = detectContentType(bytes, options);
|
|
421
|
+
if (detected) {
|
|
422
|
+
const allowed = isExplicitOnlyContentType(detected) ? isContentTypeListed(accept, detected) : isMimeTypeAllowed(accept, detected);
|
|
423
|
+
return allowed ? detected : null;
|
|
424
|
+
}
|
|
425
|
+
if (!claimedType) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
const claimed = canonicalContentType(claimedType);
|
|
429
|
+
if (DETECTABLE_CONTENT_TYPES.has(claimed)) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
return isClaimedContentTypeAllowed(accept, claimed) ? claimed : null;
|
|
433
|
+
}
|
|
434
|
+
export {
|
|
435
|
+
DETECTABLE_CONTENT_TYPES,
|
|
436
|
+
DETECT_CONTENT_TYPE_BYTES,
|
|
437
|
+
DETECT_CONTENT_TYPE_TAIL_BYTES,
|
|
438
|
+
MAX_ZIP_DIRECTORY_BYTES,
|
|
439
|
+
acceptedContentType,
|
|
440
|
+
detectContentType,
|
|
441
|
+
findZipCentralDirectory,
|
|
442
|
+
isClaimedContentTypeAllowed
|
|
443
|
+
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type UploadErrorCode = 'CONFIGURATION' | 'UNKNOWN_TARGET' | 'UNKNOWN_PROFILE' | 'UNAUTHENTICATED' | 'INVALID_TOKEN' | 'TOKEN_USER_MISMATCH' | 'TOKEN_ORGANIZATION_MISMATCH' | 'MIME_TYPE_NOT_ALLOWED' | 'FILE_TOO_LARGE' | 'TOO_MANY_FILES' | 'PRESIGN_NOT_SUPPORTED' | 'NOT_SUPPORTED' | 'NOT_FOUND' | 'FORBIDDEN' | 'NOT_PENDING' | 'NOT_IN_STORAGE' | 'SIZE_MISMATCH' | 'INVALID_KEY';
|
|
1
|
+
export type UploadErrorCode = 'CONFIGURATION' | 'UNKNOWN_TARGET' | 'UNKNOWN_PROFILE' | 'UNAUTHENTICATED' | 'INVALID_TOKEN' | 'TOKEN_USER_MISMATCH' | 'TOKEN_ORGANIZATION_MISMATCH' | 'MIME_TYPE_NOT_ALLOWED' | 'FILE_TOO_LARGE' | 'TOO_MANY_FILES' | 'PRESIGN_NOT_SUPPORTED' | 'NOT_SUPPORTED' | 'NOT_FOUND' | 'FORBIDDEN' | 'NOT_PENDING' | 'NOT_IN_STORAGE' | 'SIZE_MISMATCH' | 'INVALID_KEY' | 'HAS_VARIANTS';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown by every part of the uploads package when a request cannot be
|
|
4
4
|
* honored. `code` is stable for programmatic handling and `statusCode` is the
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,eAAe,GACf,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,GACf,qBAAqB,GACrB,6BAA6B,GAC7B,uBAAuB,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,uBAAuB,GACvB,eAAe,GACf,WAAW,GACX,WAAW,GACX,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,eAAe,GACf,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,GACf,qBAAqB,GACrB,6BAA6B,GAC7B,uBAAuB,GACvB,gBAAgB,GAChB,gBAAgB,GAChB,uBAAuB,GACvB,eAAe,GACf,WAAW,GACX,WAAW,GACX,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,cAAc,CAAA;AAwBlB;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,EAAE,eAAe,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;gBAEN,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAMpE"}
|
package/dist/errors.js
CHANGED
package/dist/fastify/plugin.d.ts
CHANGED
|
@@ -3,8 +3,12 @@ import type { UploadAuthenticator } from '../authenticator.js';
|
|
|
3
3
|
import type { StorageTargets, UploadDatabase } from '../types.js';
|
|
4
4
|
import type { FetchCertificate } from '../webhooks/sns.js';
|
|
5
5
|
export interface UploadPluginOptions {
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Secret upload tokens and serve URLs are signed with. Usually
|
|
8
|
+
* `process.env.UPLOAD_TOKEN_SECRET`; the plugin throws a configuration
|
|
9
|
+
* error when it's missing.
|
|
10
|
+
*/
|
|
11
|
+
tokenSecret: string | undefined;
|
|
8
12
|
/** The app's storage targets. */
|
|
9
13
|
targets: StorageTargets;
|
|
10
14
|
db: UploadDatabase;
|
|
@@ -35,6 +39,30 @@ export interface UploadPluginOptions {
|
|
|
35
39
|
};
|
|
36
40
|
/** `Cache-Control` for served files. Defaults to `private, max-age=3600`. */
|
|
37
41
|
serveCacheControl?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Active-content MIME types the serve route may send inline when the
|
|
44
|
+
* signed URL asks for `inline`, e.g. `['application/pdf']` to preview PDFs
|
|
45
|
+
* in the browser. Every other active type is always served as an
|
|
46
|
+
* attachment. Only list types you're comfortable rendering from the app's
|
|
47
|
+
* origin, keeping in mind that the stored MIME type is client-asserted.
|
|
48
|
+
*/
|
|
49
|
+
inlineTypes?: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Checks each file's type by what its bytes are, using
|
|
52
|
+
* `acceptedContentType()`, instead of trusting the type the client
|
|
53
|
+
* claimed. On `POST {prefix}/fs`, a file the detector recognises is
|
|
54
|
+
* accepted when its detected type is in the profile's `allowedMimeTypes`;
|
|
55
|
+
* one it doesn't recognise is accepted on its claimed type, through a
|
|
56
|
+
* wildcard too, except that a claimed type the detector would have
|
|
57
|
+
* recognised is refused, and a type that can carry script (SVG, HTML,
|
|
58
|
+
* JavaScript, XML) must be listed exactly. Files are stored under the
|
|
59
|
+
* canonical spelling of the accepted type (`image/jpeg` for a claimed
|
|
60
|
+
* `image/jpg`). The S3 webhook checks objects' bytes against their
|
|
61
|
+
* declared type the same way `confirmUpload` does.
|
|
62
|
+
*
|
|
63
|
+
* Defaults to `true`. `false` checks the claimed type only.
|
|
64
|
+
*/
|
|
65
|
+
verifyContentType?: boolean;
|
|
38
66
|
}
|
|
39
67
|
/**
|
|
40
68
|
* Registers the upload routes on a Fastify server. Register it on the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/fastify/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAA;AAE5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/fastify/plugin.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAA;AAE5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAiB9D,OAAO,KAAK,EAEV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AA4B1D,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,iCAAiC;IACjC,OAAO,EAAE,cAAc,CAAA;IACvB,EAAE,EAAE,cAAc,CAAA;IAClB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC;;;OAGG;IACH,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,CAAA;QAChB,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;QACnC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;KACrB,CAAA;IACD,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AA+DD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA2Rf"}
|
package/dist/fastify/plugin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fastifyMultipart from "@fastify/multipart";
|
|
2
2
|
import { deleteFile } from "../deleteFile.js";
|
|
3
|
+
import { acceptedContentType, detectContentType } from "../detectContentType.js";
|
|
3
4
|
import { UploadError } from "../errors.js";
|
|
4
5
|
import { generateStorageKey, trimTrailingSlashes } from "../keys.js";
|
|
5
6
|
import {
|
|
@@ -40,8 +41,24 @@ function headerValue(req, name) {
|
|
|
40
41
|
const value = req.headers[name];
|
|
41
42
|
return Array.isArray(value) ? value[0] : value;
|
|
42
43
|
}
|
|
43
|
-
function
|
|
44
|
-
return
|
|
44
|
+
function normalizeMimeType(mimeType) {
|
|
45
|
+
return mimeType.split(";")[0].trim().toLowerCase();
|
|
46
|
+
}
|
|
47
|
+
function verifiedContentType(payload, data, claimedType) {
|
|
48
|
+
const mimeType = acceptedContentType(
|
|
49
|
+
data,
|
|
50
|
+
payload.allowedMimeTypes,
|
|
51
|
+
claimedType
|
|
52
|
+
);
|
|
53
|
+
if (mimeType) {
|
|
54
|
+
return mimeType;
|
|
55
|
+
}
|
|
56
|
+
const detected = detectContentType(data);
|
|
57
|
+
const what = detected ? `'${detected}'` : `of a type that couldn't be recognised (claimed '${claimedType}')`;
|
|
58
|
+
throw new UploadError(
|
|
59
|
+
"MIME_TYPE_NOT_ALLOWED",
|
|
60
|
+
`File is ${what}, which is not allowed for upload profile '${payload.profile}'.`
|
|
61
|
+
);
|
|
45
62
|
}
|
|
46
63
|
function contentDispositionHeader(disposition, filename) {
|
|
47
64
|
const ascii = filename.replace(/[^\x20-\x7e]/g, "_").replace(/["\\]/g, "_");
|
|
@@ -57,8 +74,11 @@ async function cedarUploadsPlugin(fastify, options) {
|
|
|
57
74
|
bodyLimit = FIVE_HUNDRED_MB,
|
|
58
75
|
authenticate,
|
|
59
76
|
s3Webhook,
|
|
60
|
-
serveCacheControl = "private, max-age=3600"
|
|
77
|
+
serveCacheControl = "private, max-age=3600",
|
|
78
|
+
inlineTypes = [],
|
|
79
|
+
verifyContentType = true
|
|
61
80
|
} = options;
|
|
81
|
+
const allowedInlineTypes = new Set(inlineTypes.map(normalizeMimeType));
|
|
62
82
|
if (!tokenSecret) {
|
|
63
83
|
throw new UploadError(
|
|
64
84
|
"CONFIGURATION",
|
|
@@ -118,7 +138,12 @@ async function cedarUploadsPlugin(fastify, options) {
|
|
|
118
138
|
if (part.type !== "file") {
|
|
119
139
|
continue;
|
|
120
140
|
}
|
|
121
|
-
|
|
141
|
+
if (!verifyContentType) {
|
|
142
|
+
assertTokenAllowsFile(payload, {
|
|
143
|
+
contentType: part.mimetype,
|
|
144
|
+
size: 0n
|
|
145
|
+
});
|
|
146
|
+
}
|
|
122
147
|
let data;
|
|
123
148
|
try {
|
|
124
149
|
data = await part.toBuffer();
|
|
@@ -132,18 +157,19 @@ async function cedarUploadsPlugin(fastify, options) {
|
|
|
132
157
|
throw e;
|
|
133
158
|
}
|
|
134
159
|
const size = BigInt(data.byteLength);
|
|
135
|
-
|
|
136
|
-
|
|
160
|
+
const mimeType = verifyContentType ? verifiedContentType(payload, data, part.mimetype) : part.mimetype;
|
|
161
|
+
assertTokenAllowsFile(payload, { contentType: mimeType, size });
|
|
162
|
+
const storageKey = generateStorageKey(mimeType);
|
|
137
163
|
const upload = await createPendingUpload({
|
|
138
164
|
db,
|
|
139
165
|
payload,
|
|
140
166
|
filename: part.filename,
|
|
141
|
-
mimeType
|
|
167
|
+
mimeType,
|
|
142
168
|
size,
|
|
143
169
|
storageKey
|
|
144
170
|
});
|
|
145
171
|
stored.push({ target: payload.target, upload });
|
|
146
|
-
await target.write(storageKey, data, { contentType:
|
|
172
|
+
await target.write(storageKey, data, { contentType: mimeType });
|
|
147
173
|
const { count } = await db.upload.updateMany({
|
|
148
174
|
where: { id: upload.id, status: "pending" },
|
|
149
175
|
data: { status: "completed" }
|
|
@@ -202,7 +228,8 @@ async function cedarUploadsPlugin(fastify, options) {
|
|
|
202
228
|
} catch (e) {
|
|
203
229
|
throw new UploadError("NOT_FOUND", "File not found.", e);
|
|
204
230
|
}
|
|
205
|
-
const
|
|
231
|
+
const mimeType = normalizeMimeType(upload.mimeType);
|
|
232
|
+
const disposition = ACTIVE_CONTENT_TYPES.has(mimeType) && !allowedInlineTypes.has(mimeType) ? "attachment" : requested;
|
|
206
233
|
return reply.code(200).header("Content-Type", upload.mimeType).header("Content-Length", upload.size.toString()).header(
|
|
207
234
|
"Content-Disposition",
|
|
208
235
|
contentDispositionHeader(disposition, upload.filename)
|
|
@@ -226,7 +253,8 @@ async function cedarUploadsPlugin(fastify, options) {
|
|
|
226
253
|
targets,
|
|
227
254
|
topicArn: s3Webhook.topicArn,
|
|
228
255
|
fetchCertificate: s3Webhook.fetchCertificate,
|
|
229
|
-
fetch: s3Webhook.fetch
|
|
256
|
+
fetch: s3Webhook.fetch,
|
|
257
|
+
verifyContentType
|
|
230
258
|
});
|
|
231
259
|
return reply.code(200).send(result);
|
|
232
260
|
} catch (e) {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export type { UploadErrorCode } from './errors.js';
|
|
|
4
4
|
export { defineStorageTargets, resolveTarget } from './targets.js';
|
|
5
5
|
export { DB_MAX_FILE_SIZE, DEFAULT_UPLOAD_TOKEN_EXPIRES_IN, defineUploadProfiles, isMimeTypeAllowed, resolveProfile, } from './profiles.js';
|
|
6
6
|
export type { ResolvedUploadProfile, UploadProfile, UploadProfiles, } from './profiles.js';
|
|
7
|
+
export { acceptedContentType, DETECT_CONTENT_TYPE_BYTES, DETECT_CONTENT_TYPE_TAIL_BYTES, DETECTABLE_CONTENT_TYPES, detectContentType, findZipCentralDirectory, isClaimedContentTypeAllowed, MAX_ZIP_DIRECTORY_BYTES, } from './detectContentType.js';
|
|
8
|
+
export type { DetectContentTypeOptions } from './detectContentType.js';
|
|
9
|
+
export { canonicalContentType, CONTENT_TYPE_ALIASES, isExplicitOnlyContentType, isScriptableContentType, MACRO_CONTENT_TYPES, SCRIPTABLE_CONTENT_TYPES, } from './contentTypes.js';
|
|
7
10
|
export { createFsProvider } from './providers/fs.js';
|
|
8
11
|
export type { FsProviderOptions } from './providers/fs.js';
|
|
9
12
|
export { createDbProvider } from './providers/db.js';
|
|
@@ -12,6 +15,8 @@ export { storeFile } from './storeFile.js';
|
|
|
12
15
|
export type { StoreFileOptions } from './storeFile.js';
|
|
13
16
|
export { deleteFile } from './deleteFile.js';
|
|
14
17
|
export type { DeleteFileOptions } from './deleteFile.js';
|
|
18
|
+
export { defineUploadVariants, deleteVariants } from './variants.js';
|
|
19
|
+
export type { DefineUploadVariantsOptions, RegenerateVariantsResult, UploadVariantContext, UploadVariantDefinition, UploadVariantFile, UploadVariantGenerator, UploadVariants, UploadVariantSource, } from './variants.js';
|
|
15
20
|
export { cleanupStaleUploads } from './cleanupStaleUploads.js';
|
|
16
21
|
export type { CleanupStaleUploadsOptions, CleanupStaleUploadsResult, } from './cleanupStaleUploads.js';
|
|
17
22
|
export { createUploadToken, UPLOAD_TOKEN_HEADER, UPLOAD_TOKEN_PURPOSE, verifyUploadToken, } from './uploadToken.js';
|
|
@@ -28,7 +33,7 @@ export type { CreateUploadAuthenticatorOptions, UploadAuthenticator, UploadReque
|
|
|
28
33
|
export { cedarUploadsPlugin } from './fastify/plugin.js';
|
|
29
34
|
export type { UploadPluginOptions } from './fastify/plugin.js';
|
|
30
35
|
export { handleS3Webhook, processS3EventRecord } from './webhooks/s3.js';
|
|
31
|
-
export type { S3Event, S3EventOutcome, S3EventRecord, S3WebhookOptions, S3WebhookResult, } from './webhooks/s3.js';
|
|
36
|
+
export type { ProcessS3EventRecordOptions, S3Event, S3EventOutcome, S3EventRecord, S3WebhookOptions, S3WebhookResult, } from './webhooks/s3.js';
|
|
32
37
|
export { verifySnsMessage } from './webhooks/sns.js';
|
|
33
38
|
export type { SnsMessage } from './webhooks/sns.js';
|
|
34
39
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,EACL,gBAAgB,EAChB,+BAA+B,EAC/B,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,GACf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,YAAY,EACV,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,uBAAuB,EACvB,uBAAuB,EACvB,WAAW,EACX,mBAAmB,GACpB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,iCAAiC,EACjC,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,wBAAwB,EACxB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,kCAAkC,EAClC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,YAAY,EACV,gCAAgC,EAChC,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACxE,YAAY,EACV,OAAO,EACP,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|