mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 03:20:46 +02:00
V2 Make FileId type opaque and use consistently throughout project (#4307)
# Description of Changes The `FileId` type in V2 currently is just defined to be a string. This makes it really easy to accidentally pass strings into things accepting file IDs (such as file names). This PR makes the `FileId` type [an opaque type](https://www.geeksforgeeks.org/typescript/opaque-types-in-typescript/), so it is compatible with things accepting strings (arguably not ideal for this...) but strings are not compatible with it without explicit conversion. The PR also includes changes to use `FileId` consistently throughout the project (everywhere I could find uses of `fileId: string`), so that we have the maximum benefit from the type safety. > [!note] > I've marked quite a few things as `FIX ME` where we're passing names in as IDs. If that is intended behaviour, I'm happy to remove the fix me and insert a cast instead, but they probably need comments explaining why we're using a file name as an ID.
This commit is contained in:
@@ -4,10 +4,11 @@
|
||||
* Now uses centralized IndexedDB manager
|
||||
*/
|
||||
|
||||
import { FileId } from '../types/file';
|
||||
import { indexedDBManager, DATABASE_CONFIGS } from './indexedDBManager';
|
||||
|
||||
export interface StoredFile {
|
||||
id: string;
|
||||
id: FileId;
|
||||
name: string;
|
||||
type: string;
|
||||
size: number;
|
||||
@@ -38,7 +39,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Store a file in IndexedDB with external UUID
|
||||
*/
|
||||
async storeFile(file: File, fileId: string, thumbnail?: string): Promise<StoredFile> {
|
||||
async storeFile(file: File, fileId: FileId, thumbnail?: string): Promise<StoredFile> {
|
||||
const db = await this.getDatabase();
|
||||
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
@@ -88,7 +89,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Retrieve a file from IndexedDB
|
||||
*/
|
||||
async getFile(id: string): Promise<StoredFile | null> {
|
||||
async getFile(id: FileId): Promise<StoredFile | null> {
|
||||
const db = await this.getDatabase();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -166,7 +167,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Delete a file from IndexedDB
|
||||
*/
|
||||
async deleteFile(id: string): Promise<void> {
|
||||
async deleteFile(id: FileId): Promise<void> {
|
||||
const db = await this.getDatabase();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -182,12 +183,12 @@ class FileStorageService {
|
||||
/**
|
||||
* Update the lastModified timestamp of a file (for most recently used sorting)
|
||||
*/
|
||||
async touchFile(id: string): Promise<boolean> {
|
||||
async touchFile(id: FileId): Promise<boolean> {
|
||||
const db = await this.getDatabase();
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction([this.storeName], 'readwrite');
|
||||
const store = transaction.objectStore(this.storeName);
|
||||
|
||||
|
||||
const getRequest = store.get(id);
|
||||
getRequest.onsuccess = () => {
|
||||
const file = getRequest.result;
|
||||
@@ -438,9 +439,9 @@ class FileStorageService {
|
||||
* Convert StoredFile to the format expected by FileContext.addStoredFiles()
|
||||
* This is the recommended way to load stored files into FileContext
|
||||
*/
|
||||
createFileWithMetadata(storedFile: StoredFile): { file: File; originalId: string; metadata: { thumbnail?: string } } {
|
||||
createFileWithMetadata(storedFile: StoredFile): { file: File; originalId: FileId; metadata: { thumbnail?: string } } {
|
||||
const file = this.createFileFromStored(storedFile);
|
||||
|
||||
|
||||
return {
|
||||
file,
|
||||
originalId: storedFile.id,
|
||||
@@ -461,7 +462,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Get file data as ArrayBuffer for streaming/chunked processing
|
||||
*/
|
||||
async getFileData(id: string): Promise<ArrayBuffer | null> {
|
||||
async getFileData(id: FileId): Promise<ArrayBuffer | null> {
|
||||
try {
|
||||
const storedFile = await this.getFile(id);
|
||||
return storedFile ? storedFile.data : null;
|
||||
@@ -474,7 +475,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Create a temporary blob URL that gets revoked automatically
|
||||
*/
|
||||
async createTemporaryBlobUrl(id: string): Promise<string | null> {
|
||||
async createTemporaryBlobUrl(id: FileId): Promise<string | null> {
|
||||
const data = await this.getFileData(id);
|
||||
if (!data) return null;
|
||||
|
||||
@@ -492,7 +493,7 @@ class FileStorageService {
|
||||
/**
|
||||
* Update thumbnail for an existing file
|
||||
*/
|
||||
async updateThumbnail(id: string, thumbnail: string): Promise<boolean> {
|
||||
async updateThumbnail(id: FileId, thumbnail: string): Promise<boolean> {
|
||||
const db = await this.getDatabase();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
Reference in New Issue
Block a user