@openinary/core 1.1.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 +661 -0
- package/dist/config/deps.d.ts +14 -0
- package/dist/config/deps.d.ts.map +1 -0
- package/dist/config/deps.js +2 -0
- package/dist/config/deps.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/authenticated.d.ts +4 -0
- package/dist/routes/authenticated.d.ts.map +1 -0
- package/dist/routes/authenticated.js +130 -0
- package/dist/routes/authenticated.js.map +1 -0
- package/dist/routes/download-folder.d.ts +4 -0
- package/dist/routes/download-folder.d.ts.map +1 -0
- package/dist/routes/download-folder.js +101 -0
- package/dist/routes/download-folder.js.map +1 -0
- package/dist/routes/download-zip.d.ts +15 -0
- package/dist/routes/download-zip.d.ts.map +1 -0
- package/dist/routes/download-zip.js +147 -0
- package/dist/routes/download-zip.js.map +1 -0
- package/dist/routes/download.d.ts +4 -0
- package/dist/routes/download.d.ts.map +1 -0
- package/dist/routes/download.js +83 -0
- package/dist/routes/download.js.map +1 -0
- package/dist/routes/invalidate.d.ts +4 -0
- package/dist/routes/invalidate.d.ts.map +1 -0
- package/dist/routes/invalidate.js +114 -0
- package/dist/routes/invalidate.js.map +1 -0
- package/dist/routes/queue-events.d.ts +4 -0
- package/dist/routes/queue-events.d.ts.map +1 -0
- package/dist/routes/queue-events.js +125 -0
- package/dist/routes/queue-events.js.map +1 -0
- package/dist/routes/queue.d.ts +4 -0
- package/dist/routes/queue.d.ts.map +1 -0
- package/dist/routes/queue.js +130 -0
- package/dist/routes/queue.js.map +1 -0
- package/dist/routes/storage.d.ts +4 -0
- package/dist/routes/storage.d.ts.map +1 -0
- package/dist/routes/storage.js +694 -0
- package/dist/routes/storage.js.map +1 -0
- package/dist/routes/transform-helpers.d.ts +62 -0
- package/dist/routes/transform-helpers.d.ts.map +1 -0
- package/dist/routes/transform-helpers.js +372 -0
- package/dist/routes/transform-helpers.js.map +1 -0
- package/dist/routes/transform.d.ts +4 -0
- package/dist/routes/transform.d.ts.map +1 -0
- package/dist/routes/transform.js +65 -0
- package/dist/routes/transform.js.map +1 -0
- package/dist/routes/video-status.d.ts +4 -0
- package/dist/routes/video-status.d.ts.map +1 -0
- package/dist/routes/video-status.js +208 -0
- package/dist/routes/video-status.js.map +1 -0
- package/dist/services/transform.service.d.ts +71 -0
- package/dist/services/transform.service.d.ts.map +1 -0
- package/dist/services/transform.service.js +362 -0
- package/dist/services/transform.service.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/asset-deletion.d.ts +16 -0
- package/dist/utils/asset-deletion.d.ts.map +1 -0
- package/dist/utils/asset-deletion.js +131 -0
- package/dist/utils/asset-deletion.js.map +1 -0
- package/dist/utils/cache.d.ts +44 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +248 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/get-unique-file-path.d.ts +8 -0
- package/dist/utils/get-unique-file-path.d.ts.map +1 -0
- package/dist/utils/get-unique-file-path.js +26 -0
- package/dist/utils/get-unique-file-path.js.map +1 -0
- package/dist/utils/image/aspect-ratio.d.ts +7 -0
- package/dist/utils/image/aspect-ratio.d.ts.map +1 -0
- package/dist/utils/image/aspect-ratio.js +40 -0
- package/dist/utils/image/aspect-ratio.js.map +1 -0
- package/dist/utils/image/background.d.ts +6 -0
- package/dist/utils/image/background.d.ts.map +1 -0
- package/dist/utils/image/background.js +22 -0
- package/dist/utils/image/background.js.map +1 -0
- package/dist/utils/image/compression.d.ts +44 -0
- package/dist/utils/image/compression.d.ts.map +1 -0
- package/dist/utils/image/compression.js +345 -0
- package/dist/utils/image/compression.js.map +1 -0
- package/dist/utils/image/gravity.d.ts +6 -0
- package/dist/utils/image/gravity.d.ts.map +1 -0
- package/dist/utils/image/gravity.js +24 -0
- package/dist/utils/image/gravity.js.map +1 -0
- package/dist/utils/image/index.d.ts +8 -0
- package/dist/utils/image/index.d.ts.map +1 -0
- package/dist/utils/image/index.js +77 -0
- package/dist/utils/image/index.js.map +1 -0
- package/dist/utils/image/param-registry.d.ts +63 -0
- package/dist/utils/image/param-registry.d.ts.map +1 -0
- package/dist/utils/image/param-registry.js +196 -0
- package/dist/utils/image/param-registry.js.map +1 -0
- package/dist/utils/image/quality.d.ts +8 -0
- package/dist/utils/image/quality.d.ts.map +1 -0
- package/dist/utils/image/quality.js +9 -0
- package/dist/utils/image/quality.js.map +1 -0
- package/dist/utils/image/resize.d.ts +7 -0
- package/dist/utils/image/resize.d.ts.map +1 -0
- package/dist/utils/image/resize.js +62 -0
- package/dist/utils/image/resize.js.map +1 -0
- package/dist/utils/image/rotation.d.ts +6 -0
- package/dist/utils/image/rotation.d.ts.map +1 -0
- package/dist/utils/image/rotation.js +20 -0
- package/dist/utils/image/rotation.js.map +1 -0
- package/dist/utils/image/round-corners.d.ts +12 -0
- package/dist/utils/image/round-corners.d.ts.map +1 -0
- package/dist/utils/image/round-corners.js +102 -0
- package/dist/utils/image/round-corners.js.map +1 -0
- package/dist/utils/image/types.d.ts +2 -0
- package/dist/utils/image/types.d.ts.map +1 -0
- package/dist/utils/image/types.js +2 -0
- package/dist/utils/image/types.js.map +1 -0
- package/dist/utils/logger.d.ts +21 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +82 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/parser.d.ts +8 -0
- package/dist/utils/parser.d.ts.map +1 -0
- package/dist/utils/parser.js +226 -0
- package/dist/utils/parser.js.map +1 -0
- package/dist/utils/signature.d.ts +35 -0
- package/dist/utils/signature.d.ts.map +1 -0
- package/dist/utils/signature.js +100 -0
- package/dist/utils/signature.js.map +1 -0
- package/dist/utils/storage/cache.d.ts +41 -0
- package/dist/utils/storage/cache.d.ts.map +1 -0
- package/dist/utils/storage/cache.js +90 -0
- package/dist/utils/storage/cache.js.map +1 -0
- package/dist/utils/storage/cloud-storage.d.ts +188 -0
- package/dist/utils/storage/cloud-storage.d.ts.map +1 -0
- package/dist/utils/storage/cloud-storage.js +514 -0
- package/dist/utils/storage/cloud-storage.js.map +1 -0
- package/dist/utils/storage/factory.d.ts +10 -0
- package/dist/utils/storage/factory.d.ts.map +1 -0
- package/dist/utils/storage/factory.js +17 -0
- package/dist/utils/storage/factory.js.map +1 -0
- package/dist/utils/storage/index.d.ts +7 -0
- package/dist/utils/storage/index.d.ts.map +1 -0
- package/dist/utils/storage/index.js +8 -0
- package/dist/utils/storage/index.js.map +1 -0
- package/dist/utils/storage/key-generator.d.ts +11 -0
- package/dist/utils/storage/key-generator.d.ts.map +1 -0
- package/dist/utils/storage/key-generator.js +23 -0
- package/dist/utils/storage/key-generator.js.map +1 -0
- package/dist/utils/storage/listing-cache.d.ts +14 -0
- package/dist/utils/storage/listing-cache.d.ts.map +1 -0
- package/dist/utils/storage/listing-cache.js +29 -0
- package/dist/utils/storage/listing-cache.js.map +1 -0
- package/dist/utils/storage/s3-client.d.ts +97 -0
- package/dist/utils/storage/s3-client.d.ts.map +1 -0
- package/dist/utils/storage/s3-client.js +297 -0
- package/dist/utils/storage/s3-client.js.map +1 -0
- package/dist/utils/storage/stats-tracker.d.ts +45 -0
- package/dist/utils/storage/stats-tracker.d.ts.map +1 -0
- package/dist/utils/storage/stats-tracker.js +97 -0
- package/dist/utils/storage/stats-tracker.js.map +1 -0
- package/dist/utils/storage/types.d.ts +2 -0
- package/dist/utils/storage/types.d.ts.map +1 -0
- package/dist/utils/storage/types.js +2 -0
- package/dist/utils/storage/types.js.map +1 -0
- package/dist/utils/storage-level.d.ts +66 -0
- package/dist/utils/storage-level.d.ts.map +1 -0
- package/dist/utils/storage-level.js +106 -0
- package/dist/utils/storage-level.js.map +1 -0
- package/dist/utils/storage-tree.d.ts +30 -0
- package/dist/utils/storage-tree.d.ts.map +1 -0
- package/dist/utils/storage-tree.js +81 -0
- package/dist/utils/storage-tree.js.map +1 -0
- package/dist/utils/upload-signature.d.ts +25 -0
- package/dist/utils/upload-signature.d.ts.map +1 -0
- package/dist/utils/upload-signature.js +56 -0
- package/dist/utils/upload-signature.js.map +1 -0
- package/dist/utils/video/auto-downscale.d.ts +12 -0
- package/dist/utils/video/auto-downscale.d.ts.map +1 -0
- package/dist/utils/video/auto-downscale.js +29 -0
- package/dist/utils/video/auto-downscale.js.map +1 -0
- package/dist/utils/video/command-builder.d.ts +22 -0
- package/dist/utils/video/command-builder.d.ts.map +1 -0
- package/dist/utils/video/command-builder.js +79 -0
- package/dist/utils/video/command-builder.js.map +1 -0
- package/dist/utils/video/config.d.ts +51 -0
- package/dist/utils/video/config.d.ts.map +1 -0
- package/dist/utils/video/config.js +170 -0
- package/dist/utils/video/config.js.map +1 -0
- package/dist/utils/video/format.d.ts +22 -0
- package/dist/utils/video/format.d.ts.map +1 -0
- package/dist/utils/video/format.js +64 -0
- package/dist/utils/video/format.js.map +1 -0
- package/dist/utils/video/index.d.ts +25 -0
- package/dist/utils/video/index.d.ts.map +1 -0
- package/dist/utils/video/index.js +104 -0
- package/dist/utils/video/index.js.map +1 -0
- package/dist/utils/video/param-registry.d.ts +64 -0
- package/dist/utils/video/param-registry.d.ts.map +1 -0
- package/dist/utils/video/param-registry.js +201 -0
- package/dist/utils/video/param-registry.js.map +1 -0
- package/dist/utils/video/quality.d.ts +12 -0
- package/dist/utils/video/quality.d.ts.map +1 -0
- package/dist/utils/video/quality.js +45 -0
- package/dist/utils/video/quality.js.map +1 -0
- package/dist/utils/video/queue-store.d.ts +51 -0
- package/dist/utils/video/queue-store.d.ts.map +1 -0
- package/dist/utils/video/queue-store.js +2 -0
- package/dist/utils/video/queue-store.js.map +1 -0
- package/dist/utils/video/resize.d.ts +7 -0
- package/dist/utils/video/resize.d.ts.map +1 -0
- package/dist/utils/video/resize.js +40 -0
- package/dist/utils/video/resize.js.map +1 -0
- package/dist/utils/video/sqlite-video-job-store.d.ts +29 -0
- package/dist/utils/video/sqlite-video-job-store.d.ts.map +1 -0
- package/dist/utils/video/sqlite-video-job-store.js +320 -0
- package/dist/utils/video/sqlite-video-job-store.js.map +1 -0
- package/dist/utils/video/thumbnail.d.ts +7 -0
- package/dist/utils/video/thumbnail.d.ts.map +1 -0
- package/dist/utils/video/thumbnail.js +22 -0
- package/dist/utils/video/thumbnail.js.map +1 -0
- package/dist/utils/video/trim.d.ts +7 -0
- package/dist/utils/video/trim.d.ts.map +1 -0
- package/dist/utils/video/trim.js +36 -0
- package/dist/utils/video/trim.js.map +1 -0
- package/dist/utils/video/types.d.ts +19 -0
- package/dist/utils/video/types.d.ts.map +1 -0
- package/dist/utils/video/types.js +2 -0
- package/dist/utils/video/types.js.map +1 -0
- package/dist/utils/video/video-info.d.ts +25 -0
- package/dist/utils/video/video-info.d.ts.map +1 -0
- package/dist/utils/video/video-info.js +58 -0
- package/dist/utils/video/video-info.js.map +1 -0
- package/dist/utils/video/video-worker.d.ts +52 -0
- package/dist/utils/video/video-worker.d.ts.map +1 -0
- package/dist/utils/video/video-worker.js +192 -0
- package/dist/utils/video/video-worker.js.map +1 -0
- package/dist/utils/video-job-queue.d.ts +62 -0
- package/dist/utils/video-job-queue.d.ts.map +1 -0
- package/dist/utils/video-job-queue.js +122 -0
- package/dist/utils/video-job-queue.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export declare const IMAGE_EXTENSIONS: string[];
|
|
2
|
+
export declare const VIDEO_EXTENSIONS: string[];
|
|
3
|
+
export type MediaType = "image" | "video";
|
|
4
|
+
export type FolderPreviewItem = {
|
|
5
|
+
path: string;
|
|
6
|
+
type: MediaType;
|
|
7
|
+
};
|
|
8
|
+
export type LevelFile = {
|
|
9
|
+
name: string;
|
|
10
|
+
path: string;
|
|
11
|
+
size?: number;
|
|
12
|
+
mtime?: string;
|
|
13
|
+
};
|
|
14
|
+
export type LevelFolder = {
|
|
15
|
+
name: string;
|
|
16
|
+
path: string;
|
|
17
|
+
};
|
|
18
|
+
export type FolderSummary = {
|
|
19
|
+
itemCount: number;
|
|
20
|
+
truncated: boolean;
|
|
21
|
+
previewItems: FolderPreviewItem[];
|
|
22
|
+
};
|
|
23
|
+
type ListedObject = {
|
|
24
|
+
key: string;
|
|
25
|
+
size?: number;
|
|
26
|
+
lastModified?: Date;
|
|
27
|
+
};
|
|
28
|
+
export declare const FOLDER_SUMMARY_MAX_KEYS = 100;
|
|
29
|
+
export declare const FOLDER_PREVIEW_LIMIT = 4;
|
|
30
|
+
export declare function getMediaType(name: string): MediaType | null;
|
|
31
|
+
/**
|
|
32
|
+
* Normalizes a user-provided folder path.
|
|
33
|
+
* Returns "" for the root, null when the path is invalid (empty segments,
|
|
34
|
+
* "." or "..", critical to prevent traversal in the local-FS fallback).
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeLevelPath(raw: string): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Shapes one delimiter-listed directory level into folder names and files.
|
|
39
|
+
* `storagePrefix` is the raw listing prefix (e.g. "public/cows/"), `folderPath`
|
|
40
|
+
* the relative path of the listed folder ("" for root). The folder marker
|
|
41
|
+
* object (key === storagePrefix) is excluded.
|
|
42
|
+
*/
|
|
43
|
+
export declare function shapeLevel(storagePrefix: string, folderPath: string, delimited: {
|
|
44
|
+
prefixes: string[];
|
|
45
|
+
objects: ListedObject[];
|
|
46
|
+
}): {
|
|
47
|
+
folderNames: string[];
|
|
48
|
+
files: LevelFile[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Shapes a bounded single-page listing of a folder into its summary:
|
|
52
|
+
* direct child count (capped by the page size), truncation flag and up to
|
|
53
|
+
* FOLDER_PREVIEW_LIMIT media preview items.
|
|
54
|
+
*/
|
|
55
|
+
export declare function shapeFolderSummary(storagePrefix: string, folderPath: string, page: {
|
|
56
|
+
prefixes: string[];
|
|
57
|
+
objects: ListedObject[];
|
|
58
|
+
isTruncated: boolean;
|
|
59
|
+
}, previewLimit?: number): FolderSummary;
|
|
60
|
+
/**
|
|
61
|
+
* Derives every folder path (including intermediate ones) from a flat list of
|
|
62
|
+
* relative keys. Marker keys ("a/b/") count as folders themselves.
|
|
63
|
+
*/
|
|
64
|
+
export declare function deriveFolderPaths(keys: string[]): string[];
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=storage-level.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-level.d.ts","sourceRoot":"","sources":["../../src/utils/storage-level.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,UAQ5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,UAA4B,CAAC;AAE1D,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAElE,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,iBAAiB,EAAE,CAAC;CACnC,CAAC;AAEF,KAAK,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAExE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK3D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW7D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,GACzD;IAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,CAqB/C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,EAC3E,YAAY,SAAuB,GAClC,aAAa,CAqBf;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAc1D"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export const IMAGE_EXTENSIONS = [
|
|
2
|
+
".jpg",
|
|
3
|
+
".jpeg",
|
|
4
|
+
".png",
|
|
5
|
+
".webp",
|
|
6
|
+
".gif",
|
|
7
|
+
".avif",
|
|
8
|
+
".psd",
|
|
9
|
+
];
|
|
10
|
+
export const VIDEO_EXTENSIONS = [".mp4", ".mov", ".webm"];
|
|
11
|
+
export const FOLDER_SUMMARY_MAX_KEYS = 100;
|
|
12
|
+
export const FOLDER_PREVIEW_LIMIT = 4;
|
|
13
|
+
export function getMediaType(name) {
|
|
14
|
+
const lower = name.toLowerCase();
|
|
15
|
+
if (IMAGE_EXTENSIONS.some((ext) => lower.endsWith(ext)))
|
|
16
|
+
return "image";
|
|
17
|
+
if (VIDEO_EXTENSIONS.some((ext) => lower.endsWith(ext)))
|
|
18
|
+
return "video";
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Normalizes a user-provided folder path.
|
|
23
|
+
* Returns "" for the root, null when the path is invalid (empty segments,
|
|
24
|
+
* "." or "..", critical to prevent traversal in the local-FS fallback).
|
|
25
|
+
*/
|
|
26
|
+
export function normalizeLevelPath(raw) {
|
|
27
|
+
const trimmed = raw.replace(/^\/+|\/+$/g, "");
|
|
28
|
+
if (!trimmed)
|
|
29
|
+
return "";
|
|
30
|
+
const segments = trimmed.split("/");
|
|
31
|
+
for (const segment of segments) {
|
|
32
|
+
if (!segment || segment === "." || segment === "..") {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return segments.join("/");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Shapes one delimiter-listed directory level into folder names and files.
|
|
40
|
+
* `storagePrefix` is the raw listing prefix (e.g. "public/cows/"), `folderPath`
|
|
41
|
+
* the relative path of the listed folder ("" for root). The folder marker
|
|
42
|
+
* object (key === storagePrefix) is excluded.
|
|
43
|
+
*/
|
|
44
|
+
export function shapeLevel(storagePrefix, folderPath, delimited) {
|
|
45
|
+
const folderNames = delimited.prefixes
|
|
46
|
+
.map((prefix) => prefix.slice(storagePrefix.length).replace(/\/+$/, ""))
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.sort((a, b) => a.localeCompare(b));
|
|
49
|
+
const files = delimited.objects
|
|
50
|
+
.filter((obj) => obj.key !== storagePrefix)
|
|
51
|
+
.map((obj) => {
|
|
52
|
+
const name = obj.key.slice(storagePrefix.length);
|
|
53
|
+
return {
|
|
54
|
+
name,
|
|
55
|
+
path: folderPath ? `${folderPath}/${name}` : name,
|
|
56
|
+
size: obj.size,
|
|
57
|
+
mtime: obj.lastModified?.toISOString(),
|
|
58
|
+
};
|
|
59
|
+
})
|
|
60
|
+
.filter((file) => file.name)
|
|
61
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
62
|
+
return { folderNames, files };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Shapes a bounded single-page listing of a folder into its summary:
|
|
66
|
+
* direct child count (capped by the page size), truncation flag and up to
|
|
67
|
+
* FOLDER_PREVIEW_LIMIT media preview items.
|
|
68
|
+
*/
|
|
69
|
+
export function shapeFolderSummary(storagePrefix, folderPath, page, previewLimit = FOLDER_PREVIEW_LIMIT) {
|
|
70
|
+
const children = page.objects.filter((obj) => obj.key !== storagePrefix);
|
|
71
|
+
const previewItems = [];
|
|
72
|
+
for (const obj of children) {
|
|
73
|
+
if (previewItems.length >= previewLimit)
|
|
74
|
+
break;
|
|
75
|
+
const name = obj.key.slice(storagePrefix.length);
|
|
76
|
+
const type = getMediaType(name);
|
|
77
|
+
if (type) {
|
|
78
|
+
previewItems.push({
|
|
79
|
+
path: folderPath ? `${folderPath}/${name}` : name,
|
|
80
|
+
type,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
itemCount: page.prefixes.length + children.length,
|
|
86
|
+
truncated: page.isTruncated,
|
|
87
|
+
previewItems,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Derives every folder path (including intermediate ones) from a flat list of
|
|
92
|
+
* relative keys. Marker keys ("a/b/") count as folders themselves.
|
|
93
|
+
*/
|
|
94
|
+
export function deriveFolderPaths(keys) {
|
|
95
|
+
const folders = new Set();
|
|
96
|
+
for (const key of keys) {
|
|
97
|
+
const normalized = key.replace(/^\/+/, "");
|
|
98
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
99
|
+
const dirDepth = normalized.endsWith("/") ? parts.length : parts.length - 1;
|
|
100
|
+
for (let i = 1; i <= dirDepth; i++) {
|
|
101
|
+
folders.add(parts.slice(0, i).join("/"));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return [...folders].sort((a, b) => a.localeCompare(b));
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=storage-level.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-level.js","sourceRoot":"","sources":["../../src/utils/storage-level.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type StorageNode = {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
type: "file" | "directory";
|
|
5
|
+
size?: number;
|
|
6
|
+
mtime?: string;
|
|
7
|
+
children?: StorageNode[];
|
|
8
|
+
};
|
|
9
|
+
export type TreeDataItem = {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
size?: number;
|
|
13
|
+
mtime?: string;
|
|
14
|
+
children?: TreeDataItem[];
|
|
15
|
+
draggable?: boolean;
|
|
16
|
+
droppable?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type ListedObject = {
|
|
20
|
+
key: string;
|
|
21
|
+
size?: number;
|
|
22
|
+
lastModified?: Date;
|
|
23
|
+
};
|
|
24
|
+
export declare function buildTreeFromKeys(keys: ListedObject[]): StorageNode;
|
|
25
|
+
export declare function storageTreeToTreeData(root: StorageNode): TreeDataItem[];
|
|
26
|
+
export declare function sumTreeSize(node: StorageNode): {
|
|
27
|
+
size: number;
|
|
28
|
+
fileCount: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=storage-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-tree.d.ts","sourceRoot":"","sources":["../../src/utils/storage-tree.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,WAAW,CAkEnE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,EAAE,CAcvE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAWA"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export function buildTreeFromKeys(keys) {
|
|
2
|
+
const root = {
|
|
3
|
+
name: "storage",
|
|
4
|
+
path: "",
|
|
5
|
+
type: "directory",
|
|
6
|
+
children: [],
|
|
7
|
+
};
|
|
8
|
+
// Path-indexed lookups keep tree construction linear in the number of keys
|
|
9
|
+
const dirByPath = new Map([["", root]]);
|
|
10
|
+
const filePaths = new Set();
|
|
11
|
+
const ensureDir = (dirPath) => {
|
|
12
|
+
const existing = dirByPath.get(dirPath);
|
|
13
|
+
if (existing) {
|
|
14
|
+
return existing;
|
|
15
|
+
}
|
|
16
|
+
const slashIndex = dirPath.lastIndexOf("/");
|
|
17
|
+
const parent = ensureDir(slashIndex === -1 ? "" : dirPath.slice(0, slashIndex));
|
|
18
|
+
const dirNode = {
|
|
19
|
+
name: dirPath.slice(slashIndex + 1),
|
|
20
|
+
path: dirPath,
|
|
21
|
+
type: "directory",
|
|
22
|
+
children: [],
|
|
23
|
+
};
|
|
24
|
+
parent.children = parent.children || [];
|
|
25
|
+
parent.children.push(dirNode);
|
|
26
|
+
dirByPath.set(dirPath, dirNode);
|
|
27
|
+
return dirNode;
|
|
28
|
+
};
|
|
29
|
+
for (const { key, size, lastModified } of keys) {
|
|
30
|
+
const normalizedKey = key.replace(/^\/+/, "");
|
|
31
|
+
const isFolderMarker = normalizedKey.endsWith("/");
|
|
32
|
+
const parts = normalizedKey.split("/").filter(Boolean);
|
|
33
|
+
if (parts.length === 0) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const fullPath = parts.join("/");
|
|
37
|
+
if (isFolderMarker) {
|
|
38
|
+
ensureDir(fullPath);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const parent = ensureDir(parts.slice(0, -1).join("/"));
|
|
42
|
+
if (filePaths.has(fullPath)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
filePaths.add(fullPath);
|
|
46
|
+
parent.children = parent.children || [];
|
|
47
|
+
parent.children.push({
|
|
48
|
+
name: parts[parts.length - 1],
|
|
49
|
+
path: fullPath,
|
|
50
|
+
type: "file",
|
|
51
|
+
size,
|
|
52
|
+
mtime: lastModified?.toISOString(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return root;
|
|
56
|
+
}
|
|
57
|
+
export function storageTreeToTreeData(root) {
|
|
58
|
+
if (!root.children)
|
|
59
|
+
return [];
|
|
60
|
+
const mapNode = (node) => {
|
|
61
|
+
return {
|
|
62
|
+
id: node.path || node.name,
|
|
63
|
+
name: node.name || node.path,
|
|
64
|
+
size: node.size,
|
|
65
|
+
mtime: node.mtime,
|
|
66
|
+
children: node.children?.map(mapNode),
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
return root.children.map(mapNode);
|
|
70
|
+
}
|
|
71
|
+
export function sumTreeSize(node) {
|
|
72
|
+
let size = node.size ?? 0;
|
|
73
|
+
let fileCount = node.type === "file" ? 1 : 0;
|
|
74
|
+
for (const child of node.children ?? []) {
|
|
75
|
+
const childStats = sumTreeSize(child);
|
|
76
|
+
size += childStats.size;
|
|
77
|
+
fileCount += childStats.fileCount;
|
|
78
|
+
}
|
|
79
|
+
return { size, fileCount };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=storage-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-tree.js","sourceRoot":"","sources":["../../src/utils/storage-tree.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,iBAAiB,CAAC,IAAoB;IACpD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,2EAA2E;IAC3E,MAAM,SAAS,GAAG,IAAI,GAAG,CAAsB,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,MAAM,SAAS,GAAG,CAAC,OAAe,EAAe,EAAE;QACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;QAChF,MAAM,OAAO,GAAgB;YAC3B,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;YACnC,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,EAAE;SACb,CAAC;QACF,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IAEF,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9C,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjC,IAAI,cAAc,EAAE,CAAC;YACnB,SAAS,CAAC,QAAQ,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAEvD,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExB,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YAC7B,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;YACZ,IAAI;YACJ,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE;SACnC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAiB;IACrD,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAE9B,MAAM,OAAO,GAAG,CAAC,IAAiB,EAAgB,EAAE;QAClD,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;YAC1B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;SACtC,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAiB;IAI3C,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IAC1B,IAAI,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC;QACxB,SAAS,IAAI,UAAU,CAAC,SAAS,CAAC;IACpC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signature utility for presigned client-side uploads.
|
|
3
|
+
* Mirrors utils/signature.ts (used for /authenticated delivery URLs) but the
|
|
4
|
+
* signed payload includes an expiry, since presigned uploads are meant to be
|
|
5
|
+
* handed to a browser and should stop working after a short window.
|
|
6
|
+
*/
|
|
7
|
+
export declare const UPLOAD_SIGNATURE_LENGTH = 16;
|
|
8
|
+
/**
|
|
9
|
+
* Generates a cryptographically secure signature for a presigned upload.
|
|
10
|
+
* @param folder - The destination folder the upload is scoped to (empty string for root)
|
|
11
|
+
* @param expires - Unix timestamp (seconds) after which the signature is no longer valid
|
|
12
|
+
* @param secret - The API secret key
|
|
13
|
+
* @returns The signature (first UPLOAD_SIGNATURE_LENGTH characters of HMAC-SHA256)
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateUploadSignature(folder: string, expires: number, secret: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Verifies a presigned upload signature using timing-safe comparison.
|
|
18
|
+
* @param providedSignature - The signature submitted with the upload
|
|
19
|
+
* @param folder - The destination folder submitted with the upload
|
|
20
|
+
* @param expires - The expiry timestamp submitted with the upload
|
|
21
|
+
* @param secret - The API secret key
|
|
22
|
+
* @returns True if the signature is valid, false otherwise
|
|
23
|
+
*/
|
|
24
|
+
export declare function verifyUploadSignature(providedSignature: string, folder: string, expires: number, secret: string): boolean;
|
|
25
|
+
//# sourceMappingURL=upload-signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-signature.d.ts","sourceRoot":"","sources":["../../src/utils/upload-signature.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,MAAM,CAUR;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CA2BT"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Signature utility for presigned client-side uploads.
|
|
4
|
+
* Mirrors utils/signature.ts (used for /authenticated delivery URLs) but the
|
|
5
|
+
* signed payload includes an expiry, since presigned uploads are meant to be
|
|
6
|
+
* handed to a browser and should stop working after a short window.
|
|
7
|
+
*/
|
|
8
|
+
export const UPLOAD_SIGNATURE_LENGTH = 16; // 64 bits of entropy
|
|
9
|
+
/**
|
|
10
|
+
* Generates a cryptographically secure signature for a presigned upload.
|
|
11
|
+
* @param folder - The destination folder the upload is scoped to (empty string for root)
|
|
12
|
+
* @param expires - Unix timestamp (seconds) after which the signature is no longer valid
|
|
13
|
+
* @param secret - The API secret key
|
|
14
|
+
* @returns The signature (first UPLOAD_SIGNATURE_LENGTH characters of HMAC-SHA256)
|
|
15
|
+
*/
|
|
16
|
+
export function generateUploadSignature(folder, expires, secret) {
|
|
17
|
+
if (!secret) {
|
|
18
|
+
throw new Error('API_SECRET is required for signature generation');
|
|
19
|
+
}
|
|
20
|
+
const stringToSign = `${folder}:${expires}`;
|
|
21
|
+
const hmac = crypto.createHmac('sha256', secret);
|
|
22
|
+
hmac.update(stringToSign);
|
|
23
|
+
return hmac.digest('hex').substring(0, UPLOAD_SIGNATURE_LENGTH);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Verifies a presigned upload signature using timing-safe comparison.
|
|
27
|
+
* @param providedSignature - The signature submitted with the upload
|
|
28
|
+
* @param folder - The destination folder submitted with the upload
|
|
29
|
+
* @param expires - The expiry timestamp submitted with the upload
|
|
30
|
+
* @param secret - The API secret key
|
|
31
|
+
* @returns True if the signature is valid, false otherwise
|
|
32
|
+
*/
|
|
33
|
+
export function verifyUploadSignature(providedSignature, folder, expires, secret) {
|
|
34
|
+
if (!secret || !providedSignature) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (providedSignature.length !== UPLOAD_SIGNATURE_LENGTH) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (!Number.isFinite(expires)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const expectedSignature = generateUploadSignature(folder, expires, secret);
|
|
45
|
+
const providedBuffer = Buffer.from(providedSignature, 'utf8');
|
|
46
|
+
const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
|
|
47
|
+
if (providedBuffer.length !== expectedBuffer.length) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return crypto.timingSafeEqual(providedBuffer, expectedBuffer);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=upload-signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-signature.js","sourceRoot":"","sources":["../../src/utils/upload-signature.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC,CAAC,qBAAqB;AAEhE;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAc,EACd,OAAe,EACf,MAAc;IAEd,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,YAAY,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;IAE5C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,iBAAyB,EACzB,MAAc,EACd,OAAe,EACf,MAAc;IAEd,IAAI,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,iBAAiB,CAAC,MAAM,KAAK,uBAAuB,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAE3E,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAE9D,IAAI,cAAc,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,EAAE,CAAC;YACpD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TransformFunction } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Automatically downscale videos larger than 720p to reduce processing load
|
|
4
|
+
* This prevents high-resolution videos (4K, 5K, 8K) from overwhelming the system
|
|
5
|
+
* Only applies if no explicit resize parameters are provided
|
|
6
|
+
*
|
|
7
|
+
* Uses 720p instead of 1080p for faster processing of very large videos (8K, 5K)
|
|
8
|
+
* - 8K (7680x4320) -> 720p = 98% pixel reduction (vs 94% to 1080p)
|
|
9
|
+
* - Processing time reduced by ~50% compared to 1080p output
|
|
10
|
+
*/
|
|
11
|
+
export declare const applyAutoDownscale: TransformFunction;
|
|
12
|
+
//# sourceMappingURL=auto-downscale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-downscale.d.ts","sourceRoot":"","sources":["../../../src/utils/video/auto-downscale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,iBAyBhC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automatically downscale videos larger than 720p to reduce processing load
|
|
3
|
+
* This prevents high-resolution videos (4K, 5K, 8K) from overwhelming the system
|
|
4
|
+
* Only applies if no explicit resize parameters are provided
|
|
5
|
+
*
|
|
6
|
+
* Uses 720p instead of 1080p for faster processing of very large videos (8K, 5K)
|
|
7
|
+
* - 8K (7680x4320) -> 720p = 98% pixel reduction (vs 94% to 1080p)
|
|
8
|
+
* - Processing time reduced by ~50% compared to 1080p output
|
|
9
|
+
*/
|
|
10
|
+
export const applyAutoDownscale = (command, context) => {
|
|
11
|
+
// Skip for thumbnail extraction
|
|
12
|
+
if (context.isThumbnail) {
|
|
13
|
+
return command;
|
|
14
|
+
}
|
|
15
|
+
const { resize, width, height } = context.params;
|
|
16
|
+
// Skip if user has explicitly specified dimensions
|
|
17
|
+
if (resize || width !== undefined || height !== undefined) {
|
|
18
|
+
return command;
|
|
19
|
+
}
|
|
20
|
+
// Auto-downscale to 720p max to reduce CPU/memory usage
|
|
21
|
+
// Using 720p instead of 1080p significantly speeds up processing of 8K/5K videos
|
|
22
|
+
// scale="min(1280\,iw):min(720\,ih)" means:
|
|
23
|
+
// - Width: minimum of 1280 or original width
|
|
24
|
+
// - Height: minimum of 720 or original height
|
|
25
|
+
// - Force even dimensions (required for h264 encoding)
|
|
26
|
+
const filter = "scale='min(1280,iw)':'min(720,ih)':force_original_aspect_ratio=decrease,scale=trunc(iw/2)*2:trunc(ih/2)*2";
|
|
27
|
+
return command.videoFilters(filter);
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=auto-downscale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-downscale.js","sourceRoot":"","sources":["../../../src/utils/video/auto-downscale.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CACnD,OAAO,EACP,OAAO,EACP,EAAE;IACF,gCAAgC;IAChC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAEjD,mDAAmD;IACnD,IAAI,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1D,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,wDAAwD;IACxD,iFAAiF;IACjF,4CAA4C;IAC5C,6CAA6C;IAC7C,8CAA8C;IAC9C,uDAAuD;IACvD,MAAM,MAAM,GAAG,2GAA2G,CAAC;IAE3H,OAAO,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { VideoContext, TransformFunction } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Builder class for constructing and executing ffmpeg commands
|
|
4
|
+
* Provides a fluent interface for applying multiple transformations
|
|
5
|
+
*/
|
|
6
|
+
export declare class VideoCommandBuilder {
|
|
7
|
+
private command;
|
|
8
|
+
private context;
|
|
9
|
+
constructor(context: VideoContext);
|
|
10
|
+
/**
|
|
11
|
+
* Apply one or more transformation functions to the ffmpeg command
|
|
12
|
+
* Returns this for method chaining
|
|
13
|
+
*/
|
|
14
|
+
apply(...transforms: TransformFunction[]): this;
|
|
15
|
+
/**
|
|
16
|
+
* Execute the ffmpeg command and return the output buffer
|
|
17
|
+
* Handles cleanup of temporary files
|
|
18
|
+
* Includes a 5-minute timeout to handle large videos (4K, 8K)
|
|
19
|
+
*/
|
|
20
|
+
execute(): Promise<Buffer>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=command-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-builder.d.ts","sourceRoot":"","sources":["../../../src/utils/video/command-builder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG/D;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAAe;gBAElB,OAAO,EAAE,YAAY;IAmBjC;;;OAGG;IACH,KAAK,CAAC,GAAG,UAAU,EAAE,iBAAiB,EAAE,GAAG,IAAI;IAO/C;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAqCjC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import ffmpeg from 'fluent-ffmpeg';
|
|
2
|
+
import { readFile, unlink, rmdir } from 'fs/promises';
|
|
3
|
+
import { FFMPEG_THREADS, FFMPEG_NICENESS } from './config.js';
|
|
4
|
+
/**
|
|
5
|
+
* Builder class for constructing and executing ffmpeg commands
|
|
6
|
+
* Provides a fluent interface for applying multiple transformations
|
|
7
|
+
*/
|
|
8
|
+
export class VideoCommandBuilder {
|
|
9
|
+
command;
|
|
10
|
+
context;
|
|
11
|
+
constructor(context) {
|
|
12
|
+
this.context = context;
|
|
13
|
+
// niceness lowers ffmpeg's scheduling priority so encoding never starves
|
|
14
|
+
// the HTTP event loop; threads are capped to the container's effective
|
|
15
|
+
// CPUs (leaving one for serving) instead of a hardcoded value
|
|
16
|
+
this.command = ffmpeg(context.inputPath, { niceness: FFMPEG_NICENESS })
|
|
17
|
+
.output(context.outputPath)
|
|
18
|
+
.addOption('-threads', String(FFMPEG_THREADS));
|
|
19
|
+
// -movflags and -max_muxing_queue_size are MOV/MP4 container options and are
|
|
20
|
+
// incompatible with image output formats (image2 muxer used for thumbnails).
|
|
21
|
+
// Only apply them for video output.
|
|
22
|
+
if (!context.isImageOutput) {
|
|
23
|
+
this.command = this.command
|
|
24
|
+
.addOption('-movflags', '+faststart') // Optimize for web streaming
|
|
25
|
+
.addOption('-max_muxing_queue_size', '1024'); // Prevent buffer issues
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Apply one or more transformation functions to the ffmpeg command
|
|
30
|
+
* Returns this for method chaining
|
|
31
|
+
*/
|
|
32
|
+
apply(...transforms) {
|
|
33
|
+
for (const transform of transforms) {
|
|
34
|
+
this.command = transform(this.command, this.context);
|
|
35
|
+
}
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Execute the ffmpeg command and return the output buffer
|
|
40
|
+
* Handles cleanup of temporary files
|
|
41
|
+
* Includes a 5-minute timeout to handle large videos (4K, 8K)
|
|
42
|
+
*/
|
|
43
|
+
async execute() {
|
|
44
|
+
const TIMEOUT_MS = 300000; // 5 minutes (increased for 8K videos)
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
// Set timeout to kill ffmpeg if it takes too long
|
|
47
|
+
const timeoutId = setTimeout(() => {
|
|
48
|
+
this.command.kill('SIGKILL');
|
|
49
|
+
reject(new Error('Video processing timeout: exceeded 5 minutes. Try reducing video resolution or duration.'));
|
|
50
|
+
}, TIMEOUT_MS);
|
|
51
|
+
this.command
|
|
52
|
+
.on('end', async () => {
|
|
53
|
+
clearTimeout(timeoutId);
|
|
54
|
+
try {
|
|
55
|
+
// Read the output file
|
|
56
|
+
const buffer = await readFile(this.context.outputPath);
|
|
57
|
+
// Cleanup: remove output file and temp directory
|
|
58
|
+
await unlink(this.context.outputPath);
|
|
59
|
+
try {
|
|
60
|
+
await rmdir(this.context.tmpDir);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Ignore if directory is not empty or already removed
|
|
64
|
+
}
|
|
65
|
+
resolve(buffer);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
reject(error);
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
.on('error', (error) => {
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
reject(new Error(`Video processing failed: ${error.message}`));
|
|
74
|
+
})
|
|
75
|
+
.run();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=command-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-builder.js","sourceRoot":"","sources":["../../../src/utils/video/command-builder.ts"],"names":[],"mappings":"AAAA,OAAO,MAAyB,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3D;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IACtB,OAAO,CAAgB;IACvB,OAAO,CAAe;IAE9B,YAAY,OAAqB;QAC/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,yEAAyE;QACzE,uEAAuE;QACvE,8DAA8D;QAC9D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;aACpE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;aAC1B,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;QAEjD,6EAA6E;QAC7E,6EAA6E;QAC7E,oCAAoC;QACpC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO;iBACxB,SAAS,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,6BAA6B;iBAClE,SAAS,CAAC,wBAAwB,EAAE,MAAM,CAAC,CAAC,CAAC,wBAAwB;QAC1E,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAG,UAA+B;QACtC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,sCAAsC;QAEjE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,kDAAkD;YAClD,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7B,MAAM,CAAC,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAC,CAAC;YAChH,CAAC,EAAE,UAAU,CAAC,CAAC;YAEf,IAAI,CAAC,OAAO;iBACT,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;gBACpB,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,IAAI,CAAC;oBACH,uBAAuB;oBACvB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBAEvD,iDAAiD;oBACjD,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;oBACtC,IAAI,CAAC;wBACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;oBACnC,CAAC;oBAAC,MAAM,CAAC;wBACP,sDAAsD;oBACxD,CAAC;oBAED,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC,CAAC;iBACD,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACrB,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC,CAAC;iBACD,GAAG,EAAE,CAAC;QACX,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video processing queue configuration
|
|
3
|
+
* These values can be overridden via environment variables
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Effective CPU count (host CPUs or cgroup quota, whichever is lower)
|
|
7
|
+
*/
|
|
8
|
+
export declare const EFFECTIVE_CPU_COUNT: number;
|
|
9
|
+
/**
|
|
10
|
+
* Number of threads each ffmpeg process may use.
|
|
11
|
+
* Leaves one CPU free for the HTTP serving event loop so video jobs never
|
|
12
|
+
* starve the API, or configured via VIDEO_FFMPEG_THREADS env variable.
|
|
13
|
+
*/
|
|
14
|
+
export declare const FFMPEG_THREADS: number;
|
|
15
|
+
/**
|
|
16
|
+
* Niceness applied to spawned ffmpeg processes (0-19, higher = lower priority).
|
|
17
|
+
* Keeps the Node event loop responsive even when ffmpeg saturates the CPU.
|
|
18
|
+
* Configurable via VIDEO_FFMPEG_NICENESS env variable.
|
|
19
|
+
*/
|
|
20
|
+
export declare const FFMPEG_NICENESS: number;
|
|
21
|
+
/**
|
|
22
|
+
* Maximum number of concurrent video jobs
|
|
23
|
+
* Auto-detected based on available memory and CPU (host or cgroup limit,
|
|
24
|
+
* whichever is lower), or configured via VIDEO_MAX_CONCURRENT env variable
|
|
25
|
+
*/
|
|
26
|
+
export declare const MAX_CONCURRENT_JOBS: number;
|
|
27
|
+
/**
|
|
28
|
+
* Maximum number of retry attempts for failed jobs
|
|
29
|
+
*/
|
|
30
|
+
export declare const JOB_RETRY_MAX: number;
|
|
31
|
+
/**
|
|
32
|
+
* Hours after which completed/error jobs are cleaned up
|
|
33
|
+
*/
|
|
34
|
+
export declare const JOB_CLEANUP_HOURS: number;
|
|
35
|
+
/**
|
|
36
|
+
* Worker polling interval in milliseconds
|
|
37
|
+
*/
|
|
38
|
+
export declare const WORKER_POLL_INTERVAL_MS: number;
|
|
39
|
+
/**
|
|
40
|
+
* Priority for thumbnail extraction jobs (lower = higher priority)
|
|
41
|
+
*/
|
|
42
|
+
export declare const THUMBNAIL_PRIORITY = 1;
|
|
43
|
+
/**
|
|
44
|
+
* Priority for video transformation jobs
|
|
45
|
+
*/
|
|
46
|
+
export declare const TRANSFORMATION_PRIORITY = 2;
|
|
47
|
+
/**
|
|
48
|
+
* Priority for other video jobs
|
|
49
|
+
*/
|
|
50
|
+
export declare const LOW_PRIORITY = 3;
|
|
51
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/utils/video/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqHH;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAoB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAEW,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAEtB,CAAC;AAEP;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,QAEqC,CAAC;AAOtE;;GAEG;AACH,eAAO,MAAM,aAAa,QAGzB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAG7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,QAGnC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,YAAY,IAAI,CAAC"}
|