Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions packages/app/src/cli/services/extensions/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,7 @@ export async function bundleThemeExtension(
options.stdout.write(`Bundling theme extension ${extension.localIdentifier}...`)
const files = await themeExtensionFiles(extension)

await Promise.all(
files.map(function (filepath) {
const relativePathName = relativePath(extension.directory, filepath)
const outputFile = joinPath(extension.outputPath, relativePathName)
if (filepath === outputFile) return
return copyFile(filepath, outputFile)
}),
)
await copyFiles(files, extension.directory, extension.outputPath)
}

export async function copyFilesForExtension(
Expand All @@ -93,14 +86,8 @@ export async function copyFilesForExtension(
ignore: ignored,
})

await Promise.all(
files.map(function (filepath) {
const relativePathName = relativePath(extension.directory, filepath)
const outputFile = joinPath(extension.outputPath, relativePathName)
if (filepath === outputFile) return
return copyFile(filepath, outputFile)
}),
)
await copyFiles(files, extension.directory, extension.outputPath)

options.stdout.write(`${extension.localIdentifier} successfully built`)
}

Expand All @@ -121,6 +108,41 @@ function onResult(result: Awaited<ReturnType<typeof esBuild>> | null, options: B
}
}

async function copyFiles(files: string[], directory: string, outputPath: string): Promise<void> {
const results = await Promise.allSettled(
files.map(async function (filepath) {
const relativePathName = relativePath(directory, filepath)
const outputFile = joinPath(outputPath, relativePathName)
if (filepath === outputFile) return {status: 'skipped', filepath}

try {
await copyFile(filepath, outputFile)
return {status: 'success', filepath}
// eslint-disable-next-line no-catch-all/no-catch-all
} catch (error) {
// Log warning but don't fail the entire process
// We intentionally catch all errors here to continue copying other files
outputDebug(`Failed to copy file ${filepath}: ${error}`)
return {status: 'failed', filepath, error}
}
}),
)

// Report any failures as warnings
const failures = results.filter((result) => {
return result.status === 'rejected' || (result.status === 'fulfilled' && result.value?.status === 'failed')
})

if (failures.length > 0) {
const failedFiles = failures.map((failure) => {
if (failure.status === 'rejected') return 'unknown file'
const value = (failure as PromiseFulfilledResult<{status: string; filepath: string}>).value
return value.filepath
})
outputDebug(`Warning: ${failures.length} file(s) could not be copied: ${failedFiles.join(', ')}`)
}
}

export function getESBuildOptions(options: BundleOptions, processEnv = process.env): Parameters<typeof esContext>[0] {
const validEnvs = pickBy(processEnv, (value, key) => EsbuildEnvVarRegex.test(key) && value)

Expand Down
Loading