UNPKG

@supabase-cache-helpers/storage-core

Version:

A collection of cache utilities for working with the Supabase Storage API. It is not meant to be used standalone.

1 lines 11.3 kB
{"version":3,"sources":["../src/index.ts","../src/directory-fetcher.ts","../src/url-fetcher.ts","../src/directory-urls-fetcher.ts","../src/lib/get-minimal-paths.ts","../src/mutate-paths.ts","../src/remove-files.ts","../src/remove-directory.ts","../src/upload.ts"],"sourcesContent":["export * from './lib/types';\n\nexport * from './directory-fetcher';\nexport * from './directory-urls-fetcher';\nexport * from './mutate-paths';\nexport * from './remove-directory';\nexport * from './remove-files';\nexport * from './upload';\nexport * from './url-fetcher';\n","import type { FileObject } from '@supabase/storage-js';\nimport type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nexport const fetchDirectory = async (\n fileApi: StorageFileApi,\n path: string,\n): Promise<FileObject[]> => {\n const { data, error } = await fileApi.list(path);\n if (error) throw error;\n if (!Array.isArray(data)) return [];\n return data;\n};\n","import type { TransformOptions } from '@supabase/storage-js';\nimport type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nimport type { StoragePrivacy } from './lib/types';\n\ntype URLFetcher = (\n fileApi: StorageFileApi,\n path: string,\n) => Promise<string | undefined>;\n\nexport type URLFetcherConfig = {\n expiresIn?: number;\n ensureExistence?: boolean;\n download?: string | boolean | undefined;\n transform?: TransformOptions | undefined;\n};\n\nexport const createUrlFetcher = (\n mode: StoragePrivacy,\n config?: URLFetcherConfig,\n): URLFetcher => {\n return async (\n fileApi: StorageFileApi,\n path: string,\n ): Promise<string | undefined> => {\n let params: Record<string, string> = {};\n\n if (config?.ensureExistence) {\n const { data: exists } = await fileApi.exists(path);\n if (!exists) return;\n // the `info` endpoint is cached - we need to bust it\n const { data: fileInfo } = await fileApi.info(\n `${path}?bust=${Date.now()}`,\n );\n if (!fileInfo) return;\n const value = fileInfo.lastModified || fileInfo.updatedAt;\n if (!value) return;\n params = {\n updated_at: value,\n };\n }\n\n let url: string | undefined;\n if (mode === 'private') {\n const { data, error } = await fileApi.createSignedUrl(\n path,\n config?.expiresIn ?? 1800,\n config,\n );\n if (error) throw error;\n url = data.signedUrl;\n } else if (mode === 'public') {\n const { data } = fileApi.getPublicUrl(path, config);\n url = data.publicUrl;\n } else {\n throw new Error(`Invalid mode: ${mode}`);\n }\n const fileURL = new URL(url);\n Object.entries(params).forEach(([key, value]) => {\n fileURL.searchParams.append(key, value);\n });\n return fileURL.toString();\n };\n};\n","import type { FileObject } from '@supabase/storage-js';\nimport type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nimport { fetchDirectory } from './directory-fetcher';\nimport type { StoragePrivacy } from './lib/types';\nimport { type URLFetcherConfig, createUrlFetcher } from './url-fetcher';\n\ntype DirectoryURLsFetcher = (\n fileApi: StorageFileApi,\n path: string,\n) => Promise<(FileObject & { url: string })[]>;\n\nexport const createDirectoryUrlsFetcher = (\n mode: StoragePrivacy,\n config?: Pick<URLFetcherConfig, 'expiresIn'>,\n): DirectoryURLsFetcher => {\n const fetchUrl = createUrlFetcher(mode, config);\n return async (fileApi: StorageFileApi, path) => {\n const files = await fetchDirectory(fileApi, path);\n const filesWithUrls = [];\n for (const f of files) {\n const url = await fetchUrl(fileApi, `${path}/${f.name}`);\n if (url) filesWithUrls.push({ ...f, url });\n }\n return filesWithUrls;\n };\n};\n","export const getMinimalPaths = (paths: string[]) =>\n paths.reduce<string[]>((paths, path) => {\n const matchingPaths = paths.filter((p) => p.startsWith(path));\n return [...paths.filter((p) => !matchingPaths.includes(p)), path];\n }, []);\n","import { getMinimalPaths } from './lib/get-minimal-paths';\nimport type { DecodedStorageKey } from './lib/types';\n\nexport type Cache<KeyType> = {\n /**\n * The keys currently present in the cache\n */\n cacheKeys: KeyType[];\n /**\n * Decode a key. Should return null if not a Storage key.\n */\n decode: (k: KeyType) => DecodedStorageKey | null;\n /**\n * The mutation function from the cache library\n */\n mutate: (key: KeyType) => Promise<void>;\n};\n\nexport const mutatePaths = async <KeyType>(\n bucketId: string,\n paths: string[],\n { cacheKeys, decode, mutate }: Cache<KeyType>,\n) => {\n const minimalPaths = getMinimalPaths(paths);\n if (minimalPaths.length === 0) return;\n await Promise.all(\n cacheKeys.map(async (key) => {\n const decodedKey = decode(key);\n if (!decodedKey) return false;\n if (decodedKey.bucketId !== bucketId) return false;\n if (\n minimalPaths.find(\n (p) => p.startsWith(decodedKey.path) || decodedKey.path.startsWith(p),\n )\n ) {\n mutate(key);\n }\n }),\n );\n};\n","import type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nexport const createRemoveFilesFetcher =\n (fileApi: StorageFileApi) => async (paths: string[]) => {\n const { data, error } = await fileApi.remove(paths);\n if (error) throw error;\n return data;\n };\n","import type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nimport { fetchDirectory } from './directory-fetcher';\nimport { createRemoveFilesFetcher } from './remove-files';\n\nexport const createRemoveDirectoryFetcher = (fileApi: StorageFileApi) => {\n const removeFiles = createRemoveFilesFetcher(fileApi);\n return async (path: string) => {\n const files = await fetchDirectory(fileApi, path);\n return await removeFiles(files.map((f) => [path, f.name].join('/')));\n };\n};\n","import type { FileOptions } from '@supabase/storage-js';\nimport type StorageFileApi from '@supabase/storage-js/dist/module/packages/StorageFileApi';\n\nexport type BuildFileNameFn = ({\n path,\n fileName,\n}: {\n path?: string;\n fileName: string;\n}) => string;\n\nconst defaultBuildFileName: BuildFileNameFn = ({ path, fileName }) =>\n [path, fileName].filter(Boolean).join('/');\n\nexport type UploadFetcherConfig = Partial<\n Pick<FileOptions, 'cacheControl' | 'upsert'>\n> & {\n buildFileName?: BuildFileNameFn;\n};\n\nexport type UploadFileResponse = Awaited<ReturnType<StorageFileApi['upload']>>;\n\nexport type UploadFileInput = {\n data: Parameters<StorageFileApi['upload']>[1];\n type?: string;\n name: string;\n metadata?: NonNullable<Parameters<StorageFileApi['upload']>[2]>['metadata'];\n};\n\nexport type FileInput = File | UploadFileInput;\n\nconst isUploadFileInput = (i: FileInput): i is UploadFileInput =>\n Boolean((i as UploadFileInput).data);\n\nexport const createUploadFetcher = (\n fileApi: StorageFileApi,\n config?: UploadFetcherConfig,\n) => {\n const buildFileName = config?.buildFileName ?? defaultBuildFileName;\n return async (\n files: FileList | FileInput[],\n path?: string,\n ): Promise<UploadFileResponse[]> => {\n // convert FileList into File[]\n const inputFiles: FileInput[] = [];\n for (let i = 0; i < files.length; i++) {\n inputFiles.push(files[i]);\n }\n const uploading = inputFiles.map(async (f) => {\n const res = await fileApi.upload(\n buildFileName({\n path,\n fileName: f.name,\n }).replace(\n // remove double \"/\"\n /\\/+/g,\n '/',\n ),\n isUploadFileInput(f) ? f.data : f,\n {\n contentType: f.type,\n metadata: isUploadFileInput(f) ? f.metadata : undefined,\n ...config,\n },\n );\n return res;\n });\n return await Promise.all(uploading);\n };\n};\n"],"mappings":"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","names":["paths"]}