**feat: improve environment detection and storage logic in opfsStorage.ts**
### Changes: - Enhanced environment detection logic with a structured `environment` object (`isBrowser`, `isNode`, `isServerless`). - Implemented fallback options for various environments: - Added priority handling for storage types (e.g., MemoryStorage, OPFSStorage, FileSystemStorage). - Improved dynamic imports for `s3CompatibleStorage.js` and `fileSystemStorage.js`. - Unified and expanded cloud storage support by merging environment variables with provided options: - Refined logic for R2, S3, and GCS storage configurations. - Added detailed logging during storage type selection (`console.log` for selected storage). - Introduced better error handling with warnings and defaults for unsupported environments. - Removed redundant checks and reorganized storage selection logic for clarity. ### Purpose: Streamlined environment detection and adaptive storage logic to ensure seamless operation across different platforms (browser, Node.js, serverless). These changes improve maintainability, enhance debugging, and simplify storage configuration while providing robust fallback mechanisms.
This commit is contained in:
parent
2433acb1f1
commit
830322fef9
1 changed files with 136 additions and 119 deletions
|
|
@ -1660,13 +1660,27 @@ export async function createStorage(
|
||||||
forceMemoryStorage?: boolean
|
forceMemoryStorage?: boolean
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<StorageAdapter> {
|
): Promise<StorageAdapter> {
|
||||||
// Check for environment variables for cloud storage (only in Node.js environment)
|
// Detect environment
|
||||||
const isNode =
|
const environment = {
|
||||||
|
isBrowser: typeof window !== 'undefined',
|
||||||
|
isNode:
|
||||||
typeof process !== 'undefined' &&
|
typeof process !== 'undefined' &&
|
||||||
process.versions != null &&
|
process.versions != null &&
|
||||||
process.versions.node != null
|
process.versions.node != null,
|
||||||
|
isServerless:
|
||||||
|
typeof window === 'undefined' &&
|
||||||
|
(typeof process === 'undefined' ||
|
||||||
|
!process.versions ||
|
||||||
|
!process.versions.node)
|
||||||
|
}
|
||||||
|
|
||||||
// Default empty values
|
// If force memory storage is specified, use MemoryStorage regardless of environment
|
||||||
|
if (options.forceMemoryStorage) {
|
||||||
|
console.log('Using in-memory storage (forced by configuration)')
|
||||||
|
return new MemoryStorage()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default empty values for environment variables
|
||||||
const defaultEnvStorage = {
|
const defaultEnvStorage = {
|
||||||
bucketName: undefined,
|
bucketName: undefined,
|
||||||
accountId: undefined,
|
accountId: undefined,
|
||||||
|
|
@ -1676,8 +1690,20 @@ export async function createStorage(
|
||||||
endpoint: undefined
|
endpoint: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to use cloud storage if configured
|
||||||
|
if (
|
||||||
|
options.r2Storage ||
|
||||||
|
options.s3Storage ||
|
||||||
|
options.gcsStorage ||
|
||||||
|
options.customS3Storage ||
|
||||||
|
(environment.isNode &&
|
||||||
|
(process.env.R2_BUCKET_NAME ||
|
||||||
|
process.env.S3_BUCKET_NAME ||
|
||||||
|
process.env.GCS_BUCKET_NAME))
|
||||||
|
) {
|
||||||
|
try {
|
||||||
// Only try to access process.env in Node.js environment
|
// Only try to access process.env in Node.js environment
|
||||||
const envR2Storage = isNode
|
const envR2Storage = environment.isNode
|
||||||
? {
|
? {
|
||||||
bucketName: process.env.R2_BUCKET_NAME,
|
bucketName: process.env.R2_BUCKET_NAME,
|
||||||
accountId: process.env.R2_ACCOUNT_ID,
|
accountId: process.env.R2_ACCOUNT_ID,
|
||||||
|
|
@ -1686,18 +1712,19 @@ export async function createStorage(
|
||||||
}
|
}
|
||||||
: defaultEnvStorage
|
: defaultEnvStorage
|
||||||
|
|
||||||
const envS3Storage = isNode
|
const envS3Storage = environment.isNode
|
||||||
? {
|
? {
|
||||||
bucketName: process.env.S3_BUCKET_NAME,
|
bucketName: process.env.S3_BUCKET_NAME,
|
||||||
accessKeyId:
|
accessKeyId:
|
||||||
process.env.S3_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY_ID,
|
process.env.S3_ACCESS_KEY_ID || process.env.AWS_ACCESS_KEY_ID,
|
||||||
secretAccessKey:
|
secretAccessKey:
|
||||||
process.env.S3_SECRET_ACCESS_KEY || process.env.AWS_SECRET_ACCESS_KEY,
|
process.env.S3_SECRET_ACCESS_KEY ||
|
||||||
|
process.env.AWS_SECRET_ACCESS_KEY,
|
||||||
region: process.env.S3_REGION || process.env.AWS_REGION
|
region: process.env.S3_REGION || process.env.AWS_REGION
|
||||||
}
|
}
|
||||||
: defaultEnvStorage
|
: defaultEnvStorage
|
||||||
|
|
||||||
const envGCSStorage = isNode
|
const envGCSStorage = environment.isNode
|
||||||
? {
|
? {
|
||||||
bucketName: process.env.GCS_BUCKET_NAME,
|
bucketName: process.env.GCS_BUCKET_NAME,
|
||||||
accessKeyId: process.env.GCS_ACCESS_KEY_ID,
|
accessKeyId: process.env.GCS_ACCESS_KEY_ID,
|
||||||
|
|
@ -1744,14 +1771,6 @@ export async function createStorage(
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any S3-compatible storage options are provided, use S3CompatibleStorage
|
|
||||||
if (
|
|
||||||
mergedOptions.r2Storage ||
|
|
||||||
mergedOptions.s3Storage ||
|
|
||||||
mergedOptions.gcsStorage ||
|
|
||||||
mergedOptions.customS3Storage
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const s3Module = await import('./s3CompatibleStorage.js')
|
const s3Module = await import('./s3CompatibleStorage.js')
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
@ -1761,6 +1780,7 @@ export async function createStorage(
|
||||||
mergedOptions.r2Storage.accessKeyId &&
|
mergedOptions.r2Storage.accessKeyId &&
|
||||||
mergedOptions.r2Storage.secretAccessKey
|
mergedOptions.r2Storage.secretAccessKey
|
||||||
) {
|
) {
|
||||||
|
console.log('Using Cloudflare R2 storage')
|
||||||
return new s3Module.R2Storage({
|
return new s3Module.R2Storage({
|
||||||
bucketName: mergedOptions.r2Storage.bucketName,
|
bucketName: mergedOptions.r2Storage.bucketName,
|
||||||
accountId: mergedOptions.r2Storage.accountId,
|
accountId: mergedOptions.r2Storage.accountId,
|
||||||
|
|
@ -1773,6 +1793,7 @@ export async function createStorage(
|
||||||
mergedOptions.s3Storage.accessKeyId &&
|
mergedOptions.s3Storage.accessKeyId &&
|
||||||
mergedOptions.s3Storage.secretAccessKey
|
mergedOptions.s3Storage.secretAccessKey
|
||||||
) {
|
) {
|
||||||
|
console.log('Using Amazon S3 storage')
|
||||||
return new s3Module.S3CompatibleStorage({
|
return new s3Module.S3CompatibleStorage({
|
||||||
bucketName: mergedOptions.s3Storage.bucketName,
|
bucketName: mergedOptions.s3Storage.bucketName,
|
||||||
accessKeyId: mergedOptions.s3Storage.accessKeyId,
|
accessKeyId: mergedOptions.s3Storage.accessKeyId,
|
||||||
|
|
@ -1786,6 +1807,7 @@ export async function createStorage(
|
||||||
mergedOptions.gcsStorage.accessKeyId &&
|
mergedOptions.gcsStorage.accessKeyId &&
|
||||||
mergedOptions.gcsStorage.secretAccessKey
|
mergedOptions.gcsStorage.secretAccessKey
|
||||||
) {
|
) {
|
||||||
|
console.log('Using Google Cloud Storage')
|
||||||
return new s3Module.S3CompatibleStorage({
|
return new s3Module.S3CompatibleStorage({
|
||||||
bucketName: mergedOptions.gcsStorage.bucketName,
|
bucketName: mergedOptions.gcsStorage.bucketName,
|
||||||
accessKeyId: mergedOptions.gcsStorage.accessKeyId,
|
accessKeyId: mergedOptions.gcsStorage.accessKeyId,
|
||||||
|
|
@ -1799,6 +1821,7 @@ export async function createStorage(
|
||||||
mergedOptions.customS3Storage.accessKeyId &&
|
mergedOptions.customS3Storage.accessKeyId &&
|
||||||
mergedOptions.customS3Storage.secretAccessKey
|
mergedOptions.customS3Storage.secretAccessKey
|
||||||
) {
|
) {
|
||||||
|
console.log('Using custom S3-compatible storage')
|
||||||
return new s3Module.S3CompatibleStorage({
|
return new s3Module.S3CompatibleStorage({
|
||||||
bucketName: mergedOptions.customS3Storage.bucketName,
|
bucketName: mergedOptions.customS3Storage.bucketName,
|
||||||
accessKeyId: mergedOptions.customS3Storage.accessKeyId,
|
accessKeyId: mergedOptions.customS3Storage.accessKeyId,
|
||||||
|
|
@ -1810,35 +1833,19 @@ export async function createStorage(
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'Failed to load S3CompatibleStorage, falling back to default storage:',
|
'Failed to load S3CompatibleStorage, falling back to environment-specific storage:',
|
||||||
error
|
error
|
||||||
)
|
)
|
||||||
// Continue to default storage selection
|
// Continue to environment-specific storage selection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If force memory storage is specified, use MemoryStorage
|
// Environment-specific storage selection
|
||||||
if (options.forceMemoryStorage) {
|
if (environment.isBrowser) {
|
||||||
return new MemoryStorage()
|
// In browser environments
|
||||||
}
|
|
||||||
|
|
||||||
// Reuse the isNode variable from above
|
|
||||||
|
|
||||||
if (isNode) {
|
|
||||||
// In Node.js, use FileSystemStorage first, then fall back to memory
|
|
||||||
try {
|
|
||||||
const fileSystemModule = await import('./fileSystemStorage.js')
|
|
||||||
return new fileSystemModule.FileSystemStorage()
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(
|
|
||||||
'Failed to load FileSystemStorage, falling back to in-memory storage:',
|
|
||||||
error
|
|
||||||
)
|
|
||||||
return new MemoryStorage()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// In browser, try OPFS first (unless force FileSystem is specified)
|
|
||||||
if (!options.forceFileSystemStorage) {
|
if (!options.forceFileSystemStorage) {
|
||||||
|
try {
|
||||||
|
// Try OPFS first (Origin Private File System - browser-specific)
|
||||||
const opfsStorage = new OPFSStorage()
|
const opfsStorage = new OPFSStorage()
|
||||||
|
|
||||||
if (opfsStorage.isOPFSAvailable()) {
|
if (opfsStorage.isOPFSAvailable()) {
|
||||||
|
|
@ -1852,21 +1859,31 @@ export async function createStorage(
|
||||||
console.warn('Persistent storage permission denied')
|
console.warn('Persistent storage permission denied')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log('Using Origin Private File System (OPFS) storage')
|
||||||
return opfsStorage
|
return opfsStorage
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('OPFS storage initialization failed:', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OPFS is not available or force FileSystem is specified, try to use FileSystem API if available
|
// Fall back to memory storage for browser environments
|
||||||
|
console.log('Using in-memory storage for browser environment')
|
||||||
|
return new MemoryStorage()
|
||||||
|
} else if (environment.isNode) {
|
||||||
|
// In Node.js environments
|
||||||
try {
|
try {
|
||||||
// Try to load FileSystemStorage for browser environments
|
|
||||||
// Note: This will likely fail as FileSystemStorage is designed for Node.js
|
|
||||||
const fileSystemModule = await import('./fileSystemStorage.js')
|
const fileSystemModule = await import('./fileSystemStorage.js')
|
||||||
|
console.log('Using file system storage for Node.js environment')
|
||||||
return new fileSystemModule.FileSystemStorage()
|
return new fileSystemModule.FileSystemStorage()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn('Failed to load FileSystemStorage:', error)
|
||||||
'FileSystem storage is not available, falling back to in-memory storage'
|
console.log('Using in-memory storage for Node.js environment')
|
||||||
)
|
return new MemoryStorage()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In serverless or other environments
|
||||||
|
console.log('Using in-memory storage for serverless/unknown environment')
|
||||||
return new MemoryStorage()
|
return new MemoryStorage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue