@zjlab-fe/data-hub-ui 0.9.0 → 0.10.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.
Files changed (57) hide show
  1. package/.github/instructions/i.instructions.md +249 -0
  2. package/dist/types/components/FileUploader/FileUploadModal.d.ts +3 -0
  3. package/dist/types/components/FileUploader/FileUploader.d.ts +3 -0
  4. package/dist/types/components/FileUploader/UploadStoreProvider/UploadStoreProvider.d.ts +3 -0
  5. package/dist/types/components/feature-card/demo/moha.d.ts +1 -0
  6. package/dist/types/components/feature-card/index.d.ts +7 -1
  7. package/dist/types/components/file-uploader/components/circle-progress.d.ts +6 -0
  8. package/dist/types/components/file-uploader/components/hooks/use-drop-zone.d.ts +18 -0
  9. package/dist/types/components/file-uploader/components/hooks/use-file-validation.d.ts +13 -0
  10. package/dist/types/components/file-uploader/components/icons.d.ts +5 -0
  11. package/dist/types/components/file-uploader/components/uploader-drop-zone.d.ts +50 -0
  12. package/dist/types/components/file-uploader/components/uploader-file-item.d.ts +44 -0
  13. package/dist/types/components/file-uploader/components/uploader-file-list.d.ts +29 -0
  14. package/dist/types/components/file-uploader/components/uploader.d.ts +64 -0
  15. package/dist/types/components/file-uploader/components/uploading-status.d.ts +9 -0
  16. package/dist/types/components/file-uploader/components/utils/directory-reader.d.ts +8 -0
  17. package/dist/types/components/file-uploader/constants.d.ts +27 -0
  18. package/dist/types/components/file-uploader/context/file-state-store.d.ts +64 -0
  19. package/dist/types/components/file-uploader/context/handler-registry.d.ts +96 -0
  20. package/dist/types/components/file-uploader/context/upload-context.d.ts +14 -0
  21. package/dist/types/components/file-uploader/context/upload-provider.d.ts +47 -0
  22. package/dist/types/components/file-uploader/context/upload-reducer.d.ts +6 -0
  23. package/dist/types/components/file-uploader/context/use-upload-engine.d.ts +22 -0
  24. package/dist/types/components/file-uploader/demo/index.d.ts +2 -0
  25. package/dist/types/components/file-uploader/engine/queue-callbacks.d.ts +21 -0
  26. package/dist/types/components/file-uploader/engine/queue-manager.d.ts +63 -0
  27. package/dist/types/components/file-uploader/engine/queue-types.d.ts +37 -0
  28. package/dist/types/components/file-uploader/engine/queue-uploader.d.ts +8 -0
  29. package/dist/types/components/file-uploader/hooks/use-upload-batch.d.ts +36 -0
  30. package/dist/types/components/file-uploader/hooks/use-upload-control.d.ts +37 -0
  31. package/dist/types/components/file-uploader/hooks/use-upload-files.d.ts +40 -0
  32. package/dist/types/components/file-uploader/hooks/use-upload-operations.d.ts +43 -0
  33. package/dist/types/components/file-uploader/hooks/use-upload.d.ts +85 -0
  34. package/dist/types/components/file-uploader/index.d.ts +13 -0
  35. package/dist/types/components/file-uploader/persistence/file-blob-store.d.ts +71 -0
  36. package/dist/types/components/file-uploader/persistence/file-handle-store.d.ts +116 -0
  37. package/dist/types/components/file-uploader/persistence/index.d.ts +42 -0
  38. package/dist/types/components/file-uploader/persistence/metadata-store.d.ts +63 -0
  39. package/dist/types/components/file-uploader/persistence/persistence-context.d.ts +20 -0
  40. package/dist/types/components/file-uploader/persistence/persistence-manager.d.ts +103 -0
  41. package/dist/types/components/file-uploader/persistence/persistence-provider.d.ts +49 -0
  42. package/dist/types/components/file-uploader/persistence/types.d.ts +268 -0
  43. package/dist/types/components/file-uploader/persistence/use-persistence.d.ts +78 -0
  44. package/dist/types/components/file-uploader/types.d.ts +135 -0
  45. package/dist/types/components/file-uploader/utils/chunk-handlers.d.ts +40 -0
  46. package/dist/types/components/file-uploader/utils/ensure-handlers.d.ts +7 -0
  47. package/dist/types/components/file-uploader/utils/error-handler.d.ts +59 -0
  48. package/dist/types/components/file-uploader/utils/upload-controllers.d.ts +72 -0
  49. package/dist/types/components/file-uploader/utils/upload-handler.d.ts +17 -0
  50. package/dist/types/components/file-uploader/utils/validate-handlers.d.ts +6 -0
  51. package/dist/types/components/section-heading/index.d.ts +1 -1
  52. package/dist/types/components/tip-tap/extensions/index.d.ts +1 -1
  53. package/dist/types/index.d.ts +2 -1
  54. package/es/index.js +1 -1
  55. package/lib/index.js +1 -1
  56. package/package.json +1 -1
  57. package/tailwind.config.js +4 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * File Handle Store - IndexedDB storage for FileSystemFileHandle
3
+ *
4
+ * This store handles FileSystemFileHandle persistence for the 'file-system-access' mode.
5
+ * FileSystemFileHandle can be stored in IndexedDB via structured clone.
6
+ *
7
+ * Note: After page reload, permission must be re-requested with a user gesture.
8
+ */
9
+ /**
10
+ * Stored handle entry structure
11
+ */
12
+ interface StoredHandleEntry {
13
+ /** File ID (key) */
14
+ id: string;
15
+ /** The FileSystemFileHandle - can be cloned to IndexedDB */
16
+ handle: FileSystemFileHandle;
17
+ /** Original file name at save time */
18
+ fileName: string;
19
+ /** Storage timestamp */
20
+ createdAt: number;
21
+ }
22
+ /**
23
+ * Permission check result
24
+ */
25
+ export interface PermissionResult {
26
+ /** Whether permission is granted */
27
+ granted: boolean;
28
+ /** Permission state */
29
+ state: PermissionState;
30
+ /** Whether permission can be requested (user gesture available) */
31
+ canRequest: boolean;
32
+ }
33
+ /**
34
+ * File Handle Store class for FileSystemFileHandle persistence
35
+ */
36
+ export declare class FileHandleStore {
37
+ private prefix;
38
+ private db;
39
+ constructor(prefix?: string);
40
+ /**
41
+ * Check if File System Access API is supported
42
+ */
43
+ static isSupported(): boolean;
44
+ /**
45
+ * Initialize the store (open database connection)
46
+ */
47
+ initialize(): Promise<void>;
48
+ /**
49
+ * Ensure database is initialized
50
+ */
51
+ private ensureDb;
52
+ /**
53
+ * Save a file handle
54
+ * @param fileId - Unique file identifier
55
+ * @param handle - FileSystemFileHandle to store
56
+ * @param fileName - Original file name
57
+ */
58
+ saveHandle(fileId: string, handle: FileSystemFileHandle, fileName?: string): Promise<void>;
59
+ /**
60
+ * Get a file handle by ID
61
+ */
62
+ getHandle(fileId: string): Promise<FileSystemFileHandle | null>;
63
+ /**
64
+ * Get handle entry with metadata
65
+ */
66
+ getHandleEntry(fileId: string): Promise<StoredHandleEntry | null>;
67
+ /**
68
+ * Check permission status for a handle
69
+ * @param handle - FileSystemFileHandle to check
70
+ * @param requestIfNeeded - Whether to request permission (requires user gesture)
71
+ */
72
+ checkPermission(handle: FileSystemFileHandle, requestIfNeeded?: boolean): Promise<PermissionResult>;
73
+ /**
74
+ * Get file from handle (with permission check)
75
+ * @param handle - FileSystemFileHandle
76
+ * @param requestPermission - Whether to request permission if needed
77
+ */
78
+ getFileFromHandle(handle: FileSystemFileHandle, requestPermission?: boolean): Promise<File | null>;
79
+ /**
80
+ * Check if a handle exists
81
+ */
82
+ hasHandle(fileId: string): Promise<boolean>;
83
+ /**
84
+ * Delete a handle
85
+ */
86
+ deleteHandle(fileId: string): Promise<void>;
87
+ /**
88
+ * Delete multiple handles
89
+ */
90
+ deleteMany(fileIds: string[]): Promise<void>;
91
+ /**
92
+ * Clear all handles
93
+ */
94
+ clearAll(): Promise<void>;
95
+ /**
96
+ * Get all stored file IDs
97
+ */
98
+ getAllIds(): Promise<string[]>;
99
+ /**
100
+ * Get all entries
101
+ */
102
+ getAllEntries(): Promise<StoredHandleEntry[]>;
103
+ /**
104
+ * Close the database connection
105
+ */
106
+ close(): void;
107
+ /**
108
+ * Delete the entire database (for mode switching)
109
+ */
110
+ deleteDatabase(): Promise<void>;
111
+ }
112
+ /**
113
+ * Default singleton instance
114
+ */
115
+ export declare const fileHandleStore: FileHandleStore;
116
+ export {};
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Persistence Module - File persistence for upload state
3
+ *
4
+ * Provides three persistence modes:
5
+ * - `repick`: No persistence; user reselects files after reload (default)
6
+ * - `indexeddb`: Store file blobs in IndexedDB for auto-resume
7
+ * - `file-system-access`: Store FileSystemFileHandle for efficient resume (Chromium + HTTPS)
8
+ *
9
+ * Storage architecture:
10
+ * - Metadata is ALWAYS stored in IndexedDB (separate database)
11
+ * - File blobs stored in IndexedDB when mode='indexeddb'
12
+ * - File handles stored in IndexedDB when mode='file-system-access'
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // Wrap with PersistenceProvider inside UploadProvider
17
+ * <UploadProvider config={{ concurrentFiles: 3 }}>
18
+ * <PersistenceProvider
19
+ * config={{ mode: 'indexeddb' }}
20
+ * restoreHandler={(runtime, meta) => ({
21
+ * onGetUploadUrls: (name, count) => api.getUrls(runtime.folderId, name, count),
22
+ * onPartComplete: (name, uploadId, part) => api.completePart(name, uploadId, part),
23
+ * onFileComplete: (name, uploadId) => api.completeFile(name, uploadId),
24
+ * })}
25
+ * >
26
+ * <App />
27
+ * </PersistenceProvider>
28
+ * </UploadProvider>
29
+ *
30
+ * // In your component, use the hook
31
+ * const { pendingFiles, restoreFiles, repickFile } = usePersistence();
32
+ * ```
33
+ */
34
+ export type { PersistenceMode, PersistenceStorageConfig, PersistenceConfig, // Deprecated, use PersistenceStorageConfig
35
+ RestoreHandlerFn, StoredFileMeta, StoredChunkMeta, FileRecoveryResult, StorageQuotaInfo, PersistenceManagerInterface, FileSystemPermissionDescriptor, FileSystemHandleWithPermission, FilePickerOptions, WindowWithFileSystem, PendingFile, RestoreFilesResult, RepickFileResult, PersistenceContextValue, } from './types';
36
+ export { MetadataStore, metadataStore } from './metadata-store';
37
+ export { FileBlobStore, fileBlobStore } from './file-blob-store';
38
+ export { FileHandleStore, fileHandleStore, type PermissionResult } from './file-handle-store';
39
+ export { PersistenceManager, createPersistenceManager } from './persistence-manager';
40
+ export { PersistenceContext, usePersistence, usePersistenceOptional } from './persistence-context';
41
+ export { PersistenceProvider, type PersistenceProviderProps } from './persistence-provider';
42
+ export { uploadFileToStoredMeta, storedMetaToUploadFile } from './use-persistence';
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Metadata Store - IndexedDB storage for file metadata
3
+ *
4
+ * This store handles ONLY file metadata, separate from actual file blob storage.
5
+ * Metadata is stored in IndexedDB regardless of persistence mode.
6
+ */
7
+ import type { StoredFileMeta } from './types';
8
+ /**
9
+ * Metadata Store class for file metadata persistence
10
+ */
11
+ export declare class MetadataStore {
12
+ private prefix;
13
+ private db;
14
+ constructor(prefix?: string);
15
+ /**
16
+ * Initialize the store (open database connection)
17
+ */
18
+ initialize(): Promise<void>;
19
+ /**
20
+ * Ensure database is initialized
21
+ */
22
+ private ensureDb;
23
+ /**
24
+ * Save file metadata
25
+ */
26
+ saveMeta(meta: StoredFileMeta): Promise<void>;
27
+ /**
28
+ * Get file metadata by ID
29
+ */
30
+ getMeta(fileId: string): Promise<StoredFileMeta | null>;
31
+ /**
32
+ * Get all file metadata
33
+ */
34
+ getAllMeta(): Promise<StoredFileMeta[]>;
35
+ /**
36
+ * Delete file metadata by ID
37
+ */
38
+ deleteMeta(fileId: string): Promise<void>;
39
+ /**
40
+ * Delete multiple file metadata by IDs
41
+ */
42
+ deleteMany(fileIds: string[]): Promise<void>;
43
+ /**
44
+ * Clear all metadata
45
+ */
46
+ clearAll(): Promise<void>;
47
+ /**
48
+ * Query metadata by status
49
+ */
50
+ getByStatus(status: string): Promise<StoredFileMeta[]>;
51
+ /**
52
+ * Close the database connection
53
+ */
54
+ close(): void;
55
+ /**
56
+ * Delete the entire database (for mode switching)
57
+ */
58
+ deleteDatabase(): Promise<void>;
59
+ }
60
+ /**
61
+ * Default singleton instance
62
+ */
63
+ export declare const metadataStore: MetadataStore;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Persistence Context
3
+ *
4
+ * Context for the pluggable PersistenceProvider component.
5
+ */
6
+ import type { PersistenceContextValue } from './types';
7
+ /**
8
+ * Persistence context - null before provider mounts
9
+ */
10
+ export declare const PersistenceContext: import("react").Context<PersistenceContextValue | null>;
11
+ /**
12
+ * Hook to consume persistence context
13
+ * Must be used within PersistenceProvider
14
+ */
15
+ export declare function usePersistence(): PersistenceContextValue;
16
+ /**
17
+ * Hook to optionally consume persistence context
18
+ * Returns null if not within PersistenceProvider (no error thrown)
19
+ */
20
+ export declare function usePersistenceOptional(): PersistenceContextValue | null;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Persistence Manager - Orchestrates file persistence across modes
3
+ *
4
+ * Manages mode selection, storage switching, and coordinated data recovery.
5
+ * Handles the complexity of switching between persistence modes and ensures
6
+ * data integrity during transitions.
7
+ *
8
+ * Storage separation:
9
+ * - Metadata: Always in IndexedDB (metadata-store)
10
+ * - File blobs: IndexedDB when mode='indexeddb' (file-blob-store)
11
+ * - File handles: IndexedDB when mode='file-system-access' (file-handle-store)
12
+ */
13
+ import type { PersistenceMode, PersistenceStorageConfig, StoredFileMeta, FileRecoveryResult, StorageQuotaInfo, PersistenceManagerInterface } from './types';
14
+ import { MetadataStore } from './metadata-store';
15
+ import { FileBlobStore } from './file-blob-store';
16
+ import { FileHandleStore } from './file-handle-store';
17
+ /**
18
+ * Persistence Manager class
19
+ */
20
+ export declare class PersistenceManager implements PersistenceManagerInterface {
21
+ private config;
22
+ private metadataStore;
23
+ private blobStore;
24
+ private handleStore;
25
+ private initialized;
26
+ private _mode;
27
+ constructor(config?: Partial<PersistenceStorageConfig>);
28
+ /**
29
+ * Current persistence mode
30
+ */
31
+ get mode(): PersistenceMode;
32
+ /**
33
+ * Initialize the persistence manager
34
+ * Handles mode switching if stored mode differs from config mode
35
+ */
36
+ initialize(): Promise<void>;
37
+ /**
38
+ * Hard reset - clear all persisted data (used during mode switch)
39
+ */
40
+ hardReset(): Promise<void>;
41
+ /**
42
+ * Save file metadata to IndexedDB
43
+ */
44
+ saveFileMeta(meta: StoredFileMeta): Promise<void>;
45
+ /**
46
+ * Save file blob to IndexedDB (indexeddb mode only)
47
+ */
48
+ saveFileBlob(fileId: string, file: File): Promise<void>;
49
+ /**
50
+ * Save file handle to IndexedDB (file-system-access mode only)
51
+ */
52
+ saveFileHandle(fileId: string, handle: FileSystemFileHandle): Promise<void>;
53
+ /**
54
+ * Load all stored file metadata
55
+ */
56
+ loadAllFileMeta(): Promise<StoredFileMeta[]>;
57
+ /**
58
+ * Recover a single file with its data/handle
59
+ */
60
+ recoverFile(meta: StoredFileMeta): Promise<FileRecoveryResult>;
61
+ /**
62
+ * Request permission for a file handle (requires user gesture)
63
+ * @param fileId - File ID to request permission for
64
+ * @returns The file if permission granted, null otherwise
65
+ */
66
+ requestFilePermission(fileId: string): Promise<File | null>;
67
+ /**
68
+ * Remove file data from all storage
69
+ */
70
+ removeFile(fileId: string): Promise<void>;
71
+ /**
72
+ * Remove multiple files from storage
73
+ */
74
+ removeFiles(fileIds: string[]): Promise<void>;
75
+ /**
76
+ * Clear all persisted data
77
+ */
78
+ clearAll(): Promise<void>;
79
+ /**
80
+ * Get storage quota information
81
+ */
82
+ getStorageQuota(): Promise<StorageQuotaInfo>;
83
+ /**
84
+ * Check if File System Access API is supported
85
+ */
86
+ isFileSystemAccessSupported(): boolean;
87
+ /**
88
+ * Get the raw stores for advanced usage
89
+ */
90
+ getStores(): {
91
+ metadata: MetadataStore;
92
+ blob: FileBlobStore;
93
+ handle: FileHandleStore;
94
+ };
95
+ /**
96
+ * Close all database connections
97
+ */
98
+ close(): void;
99
+ }
100
+ /**
101
+ * Create a persistence manager instance with the given config
102
+ */
103
+ export declare function createPersistenceManager(config?: Partial<PersistenceStorageConfig>): PersistenceManager;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Persistence Provider - Pluggable component for file persistence
3
+ *
4
+ * Wraps inside UploadProvider to add persistence capabilities.
5
+ * Handles auto-save, restore, and exposes pending files for dev to manage.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <UploadProvider config={{ concurrentFiles: 3 }}>
10
+ * <PersistenceProvider
11
+ * config={{ mode: 'indexeddb' }}
12
+ * restoreHandler={(runtime, meta) => ({
13
+ * onGetUploadUrls: (name, count) => api.getUrls(runtime.folderId, name, count),
14
+ * onPartComplete: (name, uploadId, part) => api.completePart(name, uploadId, part),
15
+ * onFileComplete: (name, uploadId) => api.completeFile(name, uploadId),
16
+ * })}
17
+ * >
18
+ * <App />
19
+ * </PersistenceProvider>
20
+ * </UploadProvider>
21
+ *
22
+ * // In App:
23
+ * const { pendingFiles, restoreFiles, repickFile } = usePersistence();
24
+ * ```
25
+ */
26
+ import { type ReactNode } from 'react';
27
+ import type { PersistenceStorageConfig, RestoreHandlerFn } from './types';
28
+ export interface PersistenceProviderProps {
29
+ /** Storage configuration (mode, prefix, quota) */
30
+ config: PersistenceStorageConfig;
31
+ /** Auto-restore files on provider mount (default: true) */
32
+ autoRestore?: boolean;
33
+ /** Auto-save file state changes (default: true) */
34
+ autoSave?: boolean;
35
+ /** Cleanup completed uploads from storage (default: true) */
36
+ cleanupOnComplete?: boolean;
37
+ /**
38
+ * Handler to rebuild upload handlers for restored files.
39
+ * Called for each file that can be auto-restored.
40
+ * Return null if handlers cannot be rebuilt (file will be added to pendingFiles).
41
+ */
42
+ restoreHandler?: RestoreHandlerFn;
43
+ /** Child components */
44
+ children: ReactNode;
45
+ }
46
+ export declare function PersistenceProvider({ config, autoRestore, autoSave, cleanupOnComplete, restoreHandler, children, }: PersistenceProviderProps): import("react/jsx-runtime").JSX.Element;
47
+ export declare namespace PersistenceProvider {
48
+ var displayName: string;
49
+ }
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Persistence Types for File Uploader
3
+ *
4
+ * Defines types for three persistence modes:
5
+ * - `repick`: No persistence; user reselects files after reload
6
+ * - `indexeddb`: Store file blobs in IndexedDB for auto-resume
7
+ * - `file-system-access`: Store FileSystemFileHandle in IndexedDB (Chromium + HTTPS only)
8
+ */
9
+ import type { UploadStatusType, ChunkStatusType } from '../constants';
10
+ import type { UploadHandlers } from '../types';
11
+ /**
12
+ * Persistence modes for file storage
13
+ */
14
+ export type PersistenceMode = 'repick' | 'indexeddb' | 'file-system-access';
15
+ /**
16
+ * Storage configuration for persistence (how to persist)
17
+ */
18
+ export interface PersistenceStorageConfig {
19
+ /** Selected persistence mode */
20
+ mode: PersistenceMode;
21
+ /** Storage key prefix for namespacing (default: 'file-uploader') */
22
+ storageKeyPrefix?: string;
23
+ /** Maximum storage quota in bytes before cleanup warning (default: 500MB) */
24
+ maxStorageQuota?: number;
25
+ }
26
+ /**
27
+ * @deprecated Use PersistenceStorageConfig instead. This is kept for backward compatibility.
28
+ */
29
+ export interface PersistenceConfig extends PersistenceStorageConfig {
30
+ /** @deprecated Move to PersistenceProviderProps.autoRestore */
31
+ autoRestore?: boolean;
32
+ /** @deprecated Move to PersistenceProviderProps.autoSave */
33
+ autoSave?: boolean;
34
+ /** @deprecated Move to PersistenceProviderProps.cleanupOnComplete */
35
+ cleanupOnComplete?: boolean;
36
+ }
37
+ /**
38
+ * Handler restore function type
39
+ * Called for each file being restored to rebuild its upload handlers
40
+ *
41
+ * @param runtime - The runtime context stored with the file (dev's custom data)
42
+ * @param meta - The stored file metadata
43
+ * @returns Upload handlers for the file, or null if cannot restore
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * restoreHandler: (runtime, meta) => {
48
+ * const { folderId } = runtime as { folderId: string };
49
+ * return {
50
+ * onGetUploadUrls: (name, count) => api.getUrls(folderId, name, count),
51
+ * onPartComplete: (name, uploadId, part) => api.completePart(name, uploadId, part),
52
+ * onFileComplete: (name, uploadId) => api.completeFile(name, uploadId),
53
+ * };
54
+ * }
55
+ * ```
56
+ */
57
+ export type RestoreHandlerFn = (runtime: unknown, meta: StoredFileMeta) => UploadHandlers | null;
58
+ /**
59
+ * Stored chunk metadata (without actual data)
60
+ */
61
+ export interface StoredChunkMeta {
62
+ partNum?: number;
63
+ status: ChunkStatusType;
64
+ progress: number;
65
+ uploadUrl?: string;
66
+ error?: string;
67
+ }
68
+ /**
69
+ * Stored file metadata - saved in IndexedDB for all modes
70
+ * This is separate from the actual file blob storage
71
+ */
72
+ export interface StoredFileMeta {
73
+ /** Unique file ID */
74
+ id: string;
75
+ /** Original file name */
76
+ fileName: string;
77
+ /** File size in bytes */
78
+ fileSize: number;
79
+ /** Relative path of the file */
80
+ relativePath: string;
81
+ /** File last modified timestamp */
82
+ lastModified: number;
83
+ /** Current upload status */
84
+ status: UploadStatusType;
85
+ /** Upload progress (0-100) */
86
+ progress: number;
87
+ /** Server-assigned upload ID */
88
+ uploadId: string;
89
+ /** Chunk states */
90
+ chunks: StoredChunkMeta[];
91
+ /** Chunk size used for this upload */
92
+ chunkSize: number;
93
+ /** Arbitrary runtime context for handler rebuild */
94
+ runtime?: unknown;
95
+ /** Error message if failed */
96
+ error?: string;
97
+ /** Structured error code */
98
+ errorCode?: string;
99
+ /** Number of retry attempts */
100
+ retryCount?: number;
101
+ /** File creation timestamp */
102
+ createdAt: number;
103
+ /** Last updated timestamp */
104
+ updatedAt: number;
105
+ /** MIME type of the file */
106
+ mimeType?: string;
107
+ /** Hash of file content for integrity check (optional) */
108
+ contentHash?: string;
109
+ }
110
+ /**
111
+ * Result of file recovery operation
112
+ */
113
+ export interface FileRecoveryResult {
114
+ /** Successfully recovered file metadata */
115
+ meta: StoredFileMeta;
116
+ /** Recovered File object (if available) */
117
+ file: File | null;
118
+ /** FileSystemFileHandle (for file-system-access mode) */
119
+ handle?: FileSystemFileHandle;
120
+ /** Whether user action is needed (e.g., permission grant, repick) */
121
+ needsUserAction: boolean;
122
+ /** Reason for needing user action */
123
+ userActionReason?: 'permission_required' | 'repick_required' | 'file_modified';
124
+ }
125
+ /**
126
+ * Storage quota information
127
+ */
128
+ export interface StorageQuotaInfo {
129
+ /** Used storage in bytes */
130
+ used: number;
131
+ /** Available storage quota in bytes */
132
+ quota: number;
133
+ /** Percentage of quota used (0-100) */
134
+ usagePercent: number;
135
+ }
136
+ /**
137
+ * Persistence manager interface
138
+ */
139
+ export interface PersistenceManagerInterface {
140
+ /** Current persistence mode */
141
+ readonly mode: PersistenceMode;
142
+ /** Initialize the persistence manager */
143
+ initialize(): Promise<void>;
144
+ /** Save file metadata */
145
+ saveFileMeta(meta: StoredFileMeta): Promise<void>;
146
+ /** Save file blob (indexeddb mode only) */
147
+ saveFileBlob(fileId: string, blob: Blob): Promise<void>;
148
+ /** Save file handle (file-system-access mode only) */
149
+ saveFileHandle(fileId: string, handle: FileSystemFileHandle): Promise<void>;
150
+ /** Load all stored file metadata */
151
+ loadAllFileMeta(): Promise<StoredFileMeta[]>;
152
+ /** Recover a single file with its data/handle */
153
+ recoverFile(meta: StoredFileMeta): Promise<FileRecoveryResult>;
154
+ /** Remove file data from storage */
155
+ removeFile(fileId: string): Promise<void>;
156
+ /** Clear all persisted data */
157
+ clearAll(): Promise<void>;
158
+ /** Get storage quota information */
159
+ getStorageQuota(): Promise<StorageQuotaInfo>;
160
+ /** Check if file-system-access mode is supported */
161
+ isFileSystemAccessSupported(): boolean;
162
+ }
163
+ /**
164
+ * Pending file that needs user action to restore
165
+ */
166
+ export interface PendingFile {
167
+ /** Unique file ID */
168
+ id: string;
169
+ /** Original file name - dev can show this to guide user */
170
+ fileName: string;
171
+ /** File size in bytes */
172
+ fileSize: number;
173
+ /** File last modified timestamp */
174
+ lastModified: number;
175
+ /** Upload progress before interruption (0-100) */
176
+ progress: number;
177
+ /** Reason why file needs action */
178
+ reason: 'permission_required' | 'repick_required' | 'file_modified' | 'handlers_unavailable';
179
+ /** Full metadata for internal use */
180
+ meta: StoredFileMeta;
181
+ /** FileSystemFileHandle if available (file-system-access mode) */
182
+ handle?: FileSystemFileHandle;
183
+ }
184
+ /**
185
+ * Result of restoreFiles operation (for file-system-access mode)
186
+ */
187
+ export interface RestoreFilesResult {
188
+ /** Successfully restored file IDs */
189
+ restored: string[];
190
+ /** Files that failed to restore */
191
+ failed: Array<{
192
+ id: string;
193
+ reason: 'permission_denied' | 'file_modified' | 'file_not_found' | 'unknown_error';
194
+ fileName: string;
195
+ }>;
196
+ }
197
+ /**
198
+ * Result of repickFile operation
199
+ */
200
+ export type RepickFileResult = {
201
+ success: true;
202
+ } | {
203
+ success: false;
204
+ reason: 'name_mismatch';
205
+ expected: string;
206
+ actual: string;
207
+ } | {
208
+ success: false;
209
+ reason: 'size_mismatch';
210
+ expected: number;
211
+ actual: number;
212
+ } | {
213
+ success: false;
214
+ reason: 'modified_mismatch';
215
+ expected: number;
216
+ actual: number;
217
+ } | {
218
+ success: false;
219
+ reason: 'file_not_pending';
220
+ };
221
+ /**
222
+ * Persistence context value exposed via usePersistence hook
223
+ */
224
+ export interface PersistenceContextValue {
225
+ /** Whether persistence is initialized */
226
+ isInitialized: boolean;
227
+ /** Current persistence mode */
228
+ mode: PersistenceMode;
229
+ /** Files pending user action to restore */
230
+ pendingFiles: PendingFile[];
231
+ /**
232
+ * Restore files by requesting permission (file-system-access mode)
233
+ * Call this after user confirms they want to restore
234
+ */
235
+ restoreFiles: (fileIds?: string[]) => Promise<RestoreFilesResult>;
236
+ /**
237
+ * Repick a file (repick mode)
238
+ * Dev passes the file user selected, we validate and restore
239
+ */
240
+ repickFile: (fileId: string, file: File) => Promise<RepickFileResult>;
241
+ /** Dismiss a pending file without restoring */
242
+ dismissFile: (fileId: string) => Promise<void>;
243
+ /** Dismiss all pending files */
244
+ dismissAll: () => Promise<void>;
245
+ /** Storage quota info */
246
+ storageQuota: StorageQuotaInfo | null;
247
+ }
248
+ /**
249
+ * File-system-access API types (for TypeScript)
250
+ */
251
+ export interface FileSystemPermissionDescriptor {
252
+ mode?: 'read' | 'readwrite';
253
+ }
254
+ export interface FileSystemHandleWithPermission extends FileSystemFileHandle {
255
+ queryPermission(descriptor?: FileSystemPermissionDescriptor): Promise<PermissionState>;
256
+ requestPermission(descriptor?: FileSystemPermissionDescriptor): Promise<PermissionState>;
257
+ }
258
+ export interface FilePickerOptions {
259
+ types?: Array<{
260
+ description?: string;
261
+ accept: Record<string, string[]>;
262
+ }>;
263
+ excludeAcceptAllOption?: boolean;
264
+ multiple?: boolean;
265
+ }
266
+ export interface WindowWithFileSystem extends Window {
267
+ showOpenFilePicker(options?: FilePickerOptions): Promise<FileSystemFileHandle[]>;
268
+ }