@lenne.tech/nuxt-extensions 1.0.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/README.md +339 -0
- package/dist/module.d.mts +10 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +126 -0
- package/dist/runtime/components/transition/LtTransitionFade.d.vue.ts +39 -0
- package/dist/runtime/components/transition/LtTransitionFade.vue +21 -0
- package/dist/runtime/components/transition/LtTransitionFade.vue.d.ts +39 -0
- package/dist/runtime/components/transition/LtTransitionFadeScale.d.vue.ts +42 -0
- package/dist/runtime/components/transition/LtTransitionFadeScale.vue +21 -0
- package/dist/runtime/components/transition/LtTransitionFadeScale.vue.d.ts +42 -0
- package/dist/runtime/components/transition/LtTransitionSlide.d.vue.ts +13 -0
- package/dist/runtime/components/transition/LtTransitionSlide.vue +16 -0
- package/dist/runtime/components/transition/LtTransitionSlide.vue.d.ts +13 -0
- package/dist/runtime/components/transition/LtTransitionSlideBottom.d.vue.ts +13 -0
- package/dist/runtime/components/transition/LtTransitionSlideBottom.vue +16 -0
- package/dist/runtime/components/transition/LtTransitionSlideBottom.vue.d.ts +13 -0
- package/dist/runtime/components/transition/LtTransitionSlideRevert.d.vue.ts +13 -0
- package/dist/runtime/components/transition/LtTransitionSlideRevert.vue +16 -0
- package/dist/runtime/components/transition/LtTransitionSlideRevert.vue.d.ts +13 -0
- package/dist/runtime/composables/auth/use-lt-auth.d.ts +32 -0
- package/dist/runtime/composables/auth/use-lt-auth.js +411 -0
- package/dist/runtime/composables/index.d.ts +5 -0
- package/dist/runtime/composables/index.js +5 -0
- package/dist/runtime/composables/use-lt-auth-client.d.ts +29 -0
- package/dist/runtime/composables/use-lt-auth-client.js +27 -0
- package/dist/runtime/composables/use-lt-file.d.ts +27 -0
- package/dist/runtime/composables/use-lt-file.js +60 -0
- package/dist/runtime/composables/use-lt-share.d.ts +32 -0
- package/dist/runtime/composables/use-lt-share.js +52 -0
- package/dist/runtime/composables/use-lt-tus-upload.d.ts +32 -0
- package/dist/runtime/composables/use-lt-tus-upload.js +236 -0
- package/dist/runtime/lib/auth-client.d.ts +831 -0
- package/dist/runtime/lib/auth-client.js +144 -0
- package/dist/runtime/lib/auth-state.d.ts +58 -0
- package/dist/runtime/lib/auth-state.js +131 -0
- package/dist/runtime/lib/index.d.ts +2 -0
- package/dist/runtime/lib/index.js +12 -0
- package/dist/runtime/locales/de.json +19 -0
- package/dist/runtime/locales/en.json +19 -0
- package/dist/runtime/plugins/auth-interceptor.client.d.ts +14 -0
- package/dist/runtime/plugins/auth-interceptor.client.js +88 -0
- package/dist/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/types/auth.d.ts +127 -0
- package/dist/runtime/types/auth.js +0 -0
- package/dist/runtime/types/index.d.ts +3 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/runtime/types/module.d.ts +88 -0
- package/dist/runtime/types/module.js +0 -0
- package/dist/runtime/types/upload.d.ts +133 -0
- package/dist/runtime/types/upload.js +0 -0
- package/dist/runtime/utils/crypto.d.ts +40 -0
- package/dist/runtime/utils/crypto.js +17 -0
- package/dist/runtime/utils/index.d.ts +2 -0
- package/dist/runtime/utils/index.js +2 -0
- package/dist/runtime/utils/tw.d.ts +20 -0
- package/dist/runtime/utils/tw.js +1 -0
- package/dist/types.d.mts +9 -0
- package/package.json +99 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useNuxtApp } from "#imports";
|
|
2
|
+
import { createLtAuthClient } from "../lib/auth-client.js";
|
|
3
|
+
let authClientInstance = null;
|
|
4
|
+
export function useLtAuthClient() {
|
|
5
|
+
if (!authClientInstance) {
|
|
6
|
+
try {
|
|
7
|
+
const nuxtApp = useNuxtApp();
|
|
8
|
+
const config = nuxtApp.$config?.public?.ltExtensions?.auth || {};
|
|
9
|
+
authClientInstance = createLtAuthClient({
|
|
10
|
+
baseURL: config.baseURL,
|
|
11
|
+
basePath: config.basePath,
|
|
12
|
+
twoFactorRedirectPath: config.twoFactorRedirectPath,
|
|
13
|
+
enableAdmin: config.enableAdmin,
|
|
14
|
+
enableTwoFactor: config.enableTwoFactor,
|
|
15
|
+
enablePasskey: config.enablePasskey
|
|
16
|
+
});
|
|
17
|
+
} catch {
|
|
18
|
+
authClientInstance = createLtAuthClient();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return authClientInstance;
|
|
22
|
+
}
|
|
23
|
+
export const ltAuthClient = {
|
|
24
|
+
get instance() {
|
|
25
|
+
return useLtAuthClient();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Utilities Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides helper functions for working with files:
|
|
5
|
+
* - File info fetching from server
|
|
6
|
+
* - URL generation for file access
|
|
7
|
+
* - File size and duration formatting
|
|
8
|
+
*/
|
|
9
|
+
import type { UseLtFileReturn } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* File utilities composable
|
|
12
|
+
*
|
|
13
|
+
* @returns File utility functions
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const { formatFileSize, getFileUrl, getDownloadUrl } = useLtFile();
|
|
18
|
+
*
|
|
19
|
+
* // Format file size
|
|
20
|
+
* console.log(formatFileSize(1024)); // "1 KB"
|
|
21
|
+
*
|
|
22
|
+
* // Get file URLs
|
|
23
|
+
* const viewUrl = getFileUrl('abc123');
|
|
24
|
+
* const downloadUrl = getDownloadUrl('abc123', 'document.pdf');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function useLtFile(): UseLtFileReturn;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useRuntimeConfig } from "#imports";
|
|
2
|
+
export function useLtFile() {
|
|
3
|
+
const config = useRuntimeConfig();
|
|
4
|
+
function getFileApiBase() {
|
|
5
|
+
return config.public.ltExtensions?.tus?.defaultEndpoint?.replace("/upload", "") || "/files";
|
|
6
|
+
}
|
|
7
|
+
function isValidMongoID(id) {
|
|
8
|
+
return /^[a-f\d]{24}$/i.test(id);
|
|
9
|
+
}
|
|
10
|
+
async function getFileInfo(id) {
|
|
11
|
+
if (!id) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (!isValidMongoID(id)) {
|
|
15
|
+
return id;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const apiBase = getFileApiBase();
|
|
19
|
+
const response = await $fetch(`${apiBase}/info/${id}`, {
|
|
20
|
+
credentials: "include",
|
|
21
|
+
method: "GET"
|
|
22
|
+
});
|
|
23
|
+
return response;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error("Error fetching file info:", error);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function getFileUrl(id) {
|
|
30
|
+
const apiBase = getFileApiBase();
|
|
31
|
+
return `${apiBase}/${id}`;
|
|
32
|
+
}
|
|
33
|
+
function getDownloadUrl(id, filename) {
|
|
34
|
+
const apiBase = getFileApiBase();
|
|
35
|
+
const base = `${apiBase}/download/${id}`;
|
|
36
|
+
return filename ? `${base}?filename=${encodeURIComponent(filename)}` : base;
|
|
37
|
+
}
|
|
38
|
+
function formatFileSize(bytes) {
|
|
39
|
+
if (bytes === 0) return "0 B";
|
|
40
|
+
const k = 1024;
|
|
41
|
+
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
42
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
43
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
44
|
+
}
|
|
45
|
+
function formatDuration(seconds) {
|
|
46
|
+
if (seconds < 60) return `${seconds}s`;
|
|
47
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
48
|
+
const hours = Math.floor(seconds / 3600);
|
|
49
|
+
const minutes = Math.floor(seconds % 3600 / 60);
|
|
50
|
+
return `${hours}h ${minutes}m`;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
formatDuration,
|
|
54
|
+
formatFileSize,
|
|
55
|
+
getDownloadUrl,
|
|
56
|
+
getFileInfo,
|
|
57
|
+
getFileUrl,
|
|
58
|
+
isValidMongoID
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web Share API Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides a unified sharing API with:
|
|
5
|
+
* - Native Web Share API on supported devices
|
|
6
|
+
* - Clipboard fallback with toast notification
|
|
7
|
+
* - i18n support with German fallback
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Return type for useLtShare composable
|
|
11
|
+
*/
|
|
12
|
+
export interface UseLtShareReturn {
|
|
13
|
+
/** Share content using native API or clipboard fallback */
|
|
14
|
+
share: (title?: string, text?: string, url?: string) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Web Share composable with clipboard fallback
|
|
18
|
+
*
|
|
19
|
+
* @returns Share function
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const { share } = useLtShare();
|
|
24
|
+
*
|
|
25
|
+
* // Share current page
|
|
26
|
+
* await share('Check this out!', 'Amazing content', window.location.href);
|
|
27
|
+
*
|
|
28
|
+
* // Share with defaults (uses current URL)
|
|
29
|
+
* await share();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function useLtShare(): UseLtShareReturn;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useNuxtApp, useRoute } from "#imports";
|
|
2
|
+
export function useLtShare() {
|
|
3
|
+
const route = useRoute();
|
|
4
|
+
const nuxtApp = useNuxtApp();
|
|
5
|
+
function t(key, germanFallback) {
|
|
6
|
+
const i18n = nuxtApp.$i18n;
|
|
7
|
+
if (!i18n?.t) {
|
|
8
|
+
return germanFallback;
|
|
9
|
+
}
|
|
10
|
+
return i18n.t(key);
|
|
11
|
+
}
|
|
12
|
+
async function share(title, text, url) {
|
|
13
|
+
if (!import.meta.client) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (window?.navigator?.share) {
|
|
17
|
+
try {
|
|
18
|
+
await window.navigator.share({
|
|
19
|
+
text: text ?? window.location.origin,
|
|
20
|
+
title,
|
|
21
|
+
url: url ?? route.fullPath
|
|
22
|
+
});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("Error sharing:", error);
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
try {
|
|
28
|
+
await navigator.clipboard.writeText(url ?? window.location.origin);
|
|
29
|
+
const useToast = nuxtApp.$useToast || globalThis.useToast;
|
|
30
|
+
if (typeof useToast === "function") {
|
|
31
|
+
try {
|
|
32
|
+
const toast = useToast();
|
|
33
|
+
toast.add({
|
|
34
|
+
color: "success",
|
|
35
|
+
description: t("lt.share.copiedDescription", "Der Link wurde in die Zwischenablage kopiert."),
|
|
36
|
+
title: t("lt.share.copied", "Link kopiert")
|
|
37
|
+
});
|
|
38
|
+
} catch {
|
|
39
|
+
console.debug("Link copied to clipboard");
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
console.debug("Link copied to clipboard");
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error("Error copying to clipboard:", error);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
share
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUS Protocol Upload Composable
|
|
3
|
+
*
|
|
4
|
+
* Provides resumable file uploads using the TUS protocol.
|
|
5
|
+
* Supports pause/resume, parallel uploads, and progress tracking.
|
|
6
|
+
*
|
|
7
|
+
* @see https://tus.io/
|
|
8
|
+
*/
|
|
9
|
+
import type { LtUploadOptions, UseLtTusUploadReturn } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* TUS Upload composable with pause/resume support
|
|
12
|
+
*
|
|
13
|
+
* @param defaultOptions - Default options for all uploads
|
|
14
|
+
* @returns Upload management functions and state
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const { addFiles, uploads, totalProgress, isUploading } = useLtTusUpload({
|
|
19
|
+
* endpoint: '/api/files/upload',
|
|
20
|
+
* onSuccess: (item) => console.log('Uploaded:', item.url),
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // Add files from input
|
|
24
|
+
* function handleFileSelect(event: Event) {
|
|
25
|
+
* const input = event.target as HTMLInputElement;
|
|
26
|
+
* if (input.files) {
|
|
27
|
+
* addFiles(Array.from(input.files));
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function useLtTusUpload(defaultOptions?: LtUploadOptions): UseLtTusUploadReturn;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { computed, ref, useRuntimeConfig } from "#imports";
|
|
2
|
+
let tusModule = null;
|
|
3
|
+
async function getTusModule() {
|
|
4
|
+
if (!tusModule) {
|
|
5
|
+
try {
|
|
6
|
+
tusModule = await import("tus-js-client");
|
|
7
|
+
} catch {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"[useLtTusUpload] tus-js-client is not installed. Please install it: npm install tus-js-client"
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return tusModule;
|
|
14
|
+
}
|
|
15
|
+
export function useLtTusUpload(defaultOptions = {}) {
|
|
16
|
+
const config = useRuntimeConfig();
|
|
17
|
+
const tusConfig = config.public.ltExtensions?.tus;
|
|
18
|
+
const uploadItems = ref(/* @__PURE__ */ new Map());
|
|
19
|
+
const tusUploads = ref(/* @__PURE__ */ new Map());
|
|
20
|
+
const defaultConfig = {
|
|
21
|
+
autoStart: true,
|
|
22
|
+
chunkSize: tusConfig?.defaultChunkSize || 5 * 1024 * 1024,
|
|
23
|
+
// 5MB chunks
|
|
24
|
+
endpoint: tusConfig?.defaultEndpoint || "/files/upload",
|
|
25
|
+
parallelUploads: 3,
|
|
26
|
+
retryDelays: [0, 1e3, 3e3, 5e3, 1e4],
|
|
27
|
+
...defaultOptions
|
|
28
|
+
};
|
|
29
|
+
const uploads = computed(() => Array.from(uploadItems.value.values()));
|
|
30
|
+
const isUploading = computed(() => uploads.value.some((u) => u.status === "uploading"));
|
|
31
|
+
const totalProgress = computed(() => {
|
|
32
|
+
const items = uploads.value;
|
|
33
|
+
if (items.length === 0) {
|
|
34
|
+
return { bytesTotal: 0, bytesUploaded: 0, percentage: 0, remainingTime: 0, speed: 0 };
|
|
35
|
+
}
|
|
36
|
+
const bytesUploaded = items.reduce((acc, i) => acc + i.progress.bytesUploaded, 0);
|
|
37
|
+
const bytesTotal = items.reduce((acc, i) => acc + i.progress.bytesTotal, 0);
|
|
38
|
+
const speed = items.reduce((acc, i) => acc + i.progress.speed, 0);
|
|
39
|
+
return {
|
|
40
|
+
bytesTotal,
|
|
41
|
+
bytesUploaded,
|
|
42
|
+
percentage: bytesTotal > 0 ? Math.round(bytesUploaded / bytesTotal * 100) : 0,
|
|
43
|
+
remainingTime: speed > 0 ? Math.ceil((bytesTotal - bytesUploaded) / speed) : 0,
|
|
44
|
+
speed
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
function generateId() {
|
|
48
|
+
return `upload_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
49
|
+
}
|
|
50
|
+
function createSpeedTracker() {
|
|
51
|
+
let lastBytes = 0;
|
|
52
|
+
let lastTime = Date.now();
|
|
53
|
+
let smoothedSpeed = 0;
|
|
54
|
+
return (bytesUploaded) => {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
const timeDiff = (now - lastTime) / 1e3;
|
|
57
|
+
const bytesDiff = bytesUploaded - lastBytes;
|
|
58
|
+
if (timeDiff > 0) {
|
|
59
|
+
const currentSpeed = bytesDiff / timeDiff;
|
|
60
|
+
smoothedSpeed = smoothedSpeed === 0 ? currentSpeed : smoothedSpeed * 0.7 + currentSpeed * 0.3;
|
|
61
|
+
}
|
|
62
|
+
lastBytes = bytesUploaded;
|
|
63
|
+
lastTime = now;
|
|
64
|
+
return Math.round(smoothedSpeed);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function updateItem(id, updates) {
|
|
68
|
+
const item = uploadItems.value.get(id);
|
|
69
|
+
if (item) {
|
|
70
|
+
const newMap = new Map(uploadItems.value);
|
|
71
|
+
newMap.set(id, { ...item, ...updates });
|
|
72
|
+
uploadItems.value = newMap;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function createTusUpload(item, options) {
|
|
76
|
+
const tus = await getTusModule();
|
|
77
|
+
const speedTracker = createSpeedTracker();
|
|
78
|
+
return new tus.Upload(item.file, {
|
|
79
|
+
chunkSize: options.chunkSize || defaultConfig.chunkSize,
|
|
80
|
+
endpoint: options.endpoint || defaultConfig.endpoint,
|
|
81
|
+
headers: options.headers,
|
|
82
|
+
metadata: {
|
|
83
|
+
filename: item.file.name,
|
|
84
|
+
filetype: item.file.type,
|
|
85
|
+
...options.metadata,
|
|
86
|
+
...item.metadata
|
|
87
|
+
},
|
|
88
|
+
onBeforeRequest: (req) => {
|
|
89
|
+
const xhr = req.getUnderlyingObject();
|
|
90
|
+
xhr.withCredentials = true;
|
|
91
|
+
},
|
|
92
|
+
onError: (error) => {
|
|
93
|
+
updateItem(item.id, {
|
|
94
|
+
error: error.message,
|
|
95
|
+
status: "error"
|
|
96
|
+
});
|
|
97
|
+
options.onError?.(uploadItems.value.get(item.id), error);
|
|
98
|
+
},
|
|
99
|
+
onProgress: (bytesUploaded, bytesTotal) => {
|
|
100
|
+
const speed = speedTracker(bytesUploaded);
|
|
101
|
+
const percentage = Math.round(bytesUploaded / bytesTotal * 100);
|
|
102
|
+
const remainingTime = speed > 0 ? Math.ceil((bytesTotal - bytesUploaded) / speed) : 0;
|
|
103
|
+
updateItem(item.id, {
|
|
104
|
+
progress: { bytesTotal, bytesUploaded, percentage, remainingTime, speed }
|
|
105
|
+
});
|
|
106
|
+
options.onProgress?.(uploadItems.value.get(item.id));
|
|
107
|
+
},
|
|
108
|
+
onShouldRetry: (err) => {
|
|
109
|
+
const status = err.originalResponse?.getStatus?.();
|
|
110
|
+
if (status && status >= 400 && status < 500 && status !== 429) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
},
|
|
115
|
+
onSuccess: () => {
|
|
116
|
+
const tusUpload = tusUploads.value.get(item.id);
|
|
117
|
+
const currentItem = uploadItems.value.get(item.id);
|
|
118
|
+
updateItem(item.id, {
|
|
119
|
+
completedAt: /* @__PURE__ */ new Date(),
|
|
120
|
+
progress: { ...currentItem.progress, percentage: 100 },
|
|
121
|
+
status: "completed",
|
|
122
|
+
url: tusUpload?.url ?? void 0
|
|
123
|
+
});
|
|
124
|
+
options.onSuccess?.(uploadItems.value.get(item.id));
|
|
125
|
+
},
|
|
126
|
+
retryDelays: options.retryDelays || defaultConfig.retryDelays
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async function addFiles(files) {
|
|
130
|
+
const fileArray = Array.isArray(files) ? files : [files];
|
|
131
|
+
const ids = [];
|
|
132
|
+
for (const file of fileArray) {
|
|
133
|
+
const id = generateId();
|
|
134
|
+
const item = {
|
|
135
|
+
file,
|
|
136
|
+
id,
|
|
137
|
+
metadata: defaultConfig.metadata,
|
|
138
|
+
progress: { bytesTotal: file.size, bytesUploaded: 0, percentage: 0, remainingTime: 0, speed: 0 },
|
|
139
|
+
status: "idle"
|
|
140
|
+
};
|
|
141
|
+
const newMap = new Map(uploadItems.value);
|
|
142
|
+
newMap.set(id, item);
|
|
143
|
+
uploadItems.value = newMap;
|
|
144
|
+
const tusUpload = await createTusUpload(item, defaultConfig);
|
|
145
|
+
tusUploads.value.set(id, tusUpload);
|
|
146
|
+
ids.push(id);
|
|
147
|
+
}
|
|
148
|
+
if (defaultConfig.autoStart) {
|
|
149
|
+
startAll();
|
|
150
|
+
}
|
|
151
|
+
return ids;
|
|
152
|
+
}
|
|
153
|
+
function startUpload(id) {
|
|
154
|
+
const item = uploadItems.value.get(id);
|
|
155
|
+
const tusUpload = tusUploads.value.get(id);
|
|
156
|
+
if (item && tusUpload && item.status !== "uploading") {
|
|
157
|
+
updateItem(id, { startedAt: /* @__PURE__ */ new Date(), status: "uploading" });
|
|
158
|
+
tusUpload.findPreviousUploads().then((previousUploads) => {
|
|
159
|
+
const previousUpload = previousUploads[0];
|
|
160
|
+
if (previousUpload) {
|
|
161
|
+
tusUpload.resumeFromPreviousUpload(previousUpload);
|
|
162
|
+
}
|
|
163
|
+
tusUpload.start();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function startAll() {
|
|
168
|
+
const pending = uploads.value.filter((u) => u.status === "idle" || u.status === "paused");
|
|
169
|
+
const currentlyUploading = uploads.value.filter((u) => u.status === "uploading").length;
|
|
170
|
+
const limit = (defaultConfig.parallelUploads || 3) - currentlyUploading;
|
|
171
|
+
pending.slice(0, Math.max(0, limit)).forEach((item) => startUpload(item.id));
|
|
172
|
+
}
|
|
173
|
+
function pauseUpload(id) {
|
|
174
|
+
const tusUpload = tusUploads.value.get(id);
|
|
175
|
+
if (tusUpload) {
|
|
176
|
+
tusUpload.abort();
|
|
177
|
+
updateItem(id, { status: "paused" });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function pauseAll() {
|
|
181
|
+
uploads.value.filter((u) => u.status === "uploading").forEach((item) => pauseUpload(item.id));
|
|
182
|
+
}
|
|
183
|
+
function resumeUpload(id) {
|
|
184
|
+
startUpload(id);
|
|
185
|
+
}
|
|
186
|
+
function resumeAll() {
|
|
187
|
+
uploads.value.filter((u) => u.status === "paused").forEach((item) => resumeUpload(item.id));
|
|
188
|
+
}
|
|
189
|
+
function cancelUpload(id) {
|
|
190
|
+
const tusUpload = tusUploads.value.get(id);
|
|
191
|
+
if (tusUpload) {
|
|
192
|
+
tusUpload.abort();
|
|
193
|
+
}
|
|
194
|
+
tusUploads.value.delete(id);
|
|
195
|
+
const newMap = new Map(uploadItems.value);
|
|
196
|
+
newMap.delete(id);
|
|
197
|
+
uploadItems.value = newMap;
|
|
198
|
+
}
|
|
199
|
+
function cancelAll() {
|
|
200
|
+
uploads.value.forEach((item) => cancelUpload(item.id));
|
|
201
|
+
}
|
|
202
|
+
function removeUpload(id) {
|
|
203
|
+
cancelUpload(id);
|
|
204
|
+
}
|
|
205
|
+
function clearCompleted() {
|
|
206
|
+
uploads.value.filter((u) => u.status === "completed").forEach((item) => removeUpload(item.id));
|
|
207
|
+
}
|
|
208
|
+
function retryUpload(id) {
|
|
209
|
+
const item = uploadItems.value.get(id);
|
|
210
|
+
if (item && item.status === "error") {
|
|
211
|
+
updateItem(id, { error: void 0, status: "idle" });
|
|
212
|
+
startUpload(id);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function getUpload(id) {
|
|
216
|
+
return uploadItems.value.get(id);
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
addFiles,
|
|
220
|
+
cancelAll,
|
|
221
|
+
cancelUpload,
|
|
222
|
+
clearCompleted,
|
|
223
|
+
getUpload,
|
|
224
|
+
isUploading,
|
|
225
|
+
pauseAll,
|
|
226
|
+
pauseUpload,
|
|
227
|
+
removeUpload,
|
|
228
|
+
resumeAll,
|
|
229
|
+
resumeUpload,
|
|
230
|
+
retryUpload,
|
|
231
|
+
startAll,
|
|
232
|
+
startUpload,
|
|
233
|
+
totalProgress,
|
|
234
|
+
uploads
|
|
235
|
+
};
|
|
236
|
+
}
|