154 lines
3.9 KiB
TypeScript
154 lines
3.9 KiB
TypeScript
import { BuildFailure, BuildOptions, BuildResult, build } from 'esbuild'
|
|
import { UserScriptMetaFull } from './types'
|
|
import readMeta from './readmeta'
|
|
import { format, resolveConfig } from 'prettier'
|
|
import { AllPaths, CLIArgs } from './main'
|
|
import { writeFile, stat, unlink } from 'fs/promises'
|
|
|
|
export interface runBuildResult {
|
|
meta: UserScriptMetaFull
|
|
error: string | null
|
|
}
|
|
|
|
export default async function runBuild(name: string) {
|
|
//read meta file
|
|
let { meta, metaString } = readMeta(name)
|
|
let paths = AllPaths.script(name)
|
|
|
|
let result = await runEsbuild({
|
|
entryPoints: [paths.main],
|
|
outfile: paths.dist,
|
|
|
|
target: 'esnext',
|
|
platform: 'node',
|
|
format: 'esm',
|
|
|
|
bundle: true,
|
|
minify: CLIArgs.minify,
|
|
|
|
define: {
|
|
UserScriptName: `'${meta.name}'`,
|
|
UserScriptNamespace: `'${meta.namespace}'`,
|
|
UserScriptVersion: `'${meta.version}'`,
|
|
|
|
UserScriptDownloadURL: `'${meta.downloadURL}'`,
|
|
UserScriptSupportURL: `'${meta.supportURL}'`,
|
|
UserScriptHomepageURL: `'${meta.homepageURL}'`,
|
|
},
|
|
})
|
|
|
|
let error = await postBuild(name, result, metaString)
|
|
|
|
return {
|
|
meta,
|
|
error,
|
|
}
|
|
}
|
|
|
|
interface RunEsbuildResult {
|
|
content: string | null
|
|
error: string | null
|
|
errorRaw?: BuildFailure
|
|
}
|
|
|
|
async function runEsbuild(opts: BuildOptions): Promise<RunEsbuildResult> {
|
|
opts.write = false
|
|
|
|
try {
|
|
let res = await build(opts)
|
|
return getResult(null, res)
|
|
} catch (err) {
|
|
return getResult(err as BuildFailure, null)
|
|
}
|
|
}
|
|
|
|
function getResult(error: BuildFailure | null, result: BuildResult | null) {
|
|
if (error) {
|
|
return {
|
|
content: null,
|
|
error: (error as BuildFailure).message,
|
|
errorRaw: error,
|
|
}
|
|
} else if (result) {
|
|
let content = ''
|
|
if (result.outputFiles && result.outputFiles.length > 0) {
|
|
content = result.outputFiles[0].text
|
|
if (!CLIArgs.srccomment) content = clearFilenameComments(content)
|
|
}
|
|
if (content === '') {
|
|
return {
|
|
content: null,
|
|
error: 'No output',
|
|
}
|
|
}
|
|
return {
|
|
content,
|
|
error: null,
|
|
}
|
|
} else {
|
|
return {
|
|
content: null,
|
|
error: 'No result',
|
|
}
|
|
}
|
|
}
|
|
|
|
function clearFilenameComments(content: string): string {
|
|
let regexp = new RegExp(`//\\s*${AllPaths.base.in}/.*(?:\\n|$)`, 'g')
|
|
return content.replace(regexp, '')
|
|
}
|
|
|
|
async function postBuild(
|
|
name: string,
|
|
result: RunEsbuildResult,
|
|
metaString: string
|
|
) {
|
|
let error: string | null = null
|
|
let paths = AllPaths.script(name)
|
|
|
|
let PrettierConfig = (await resolveConfig(paths.dir)) ?? {}
|
|
|
|
if (result.error) {
|
|
console.error(name, result.errorRaw || result.error)
|
|
error = result.error
|
|
} else if (result.content) {
|
|
let content = metaString + result.content
|
|
if (CLIArgs.prettier) {
|
|
content = await format(content, {
|
|
...PrettierConfig,
|
|
parser: 'babel',
|
|
})
|
|
}
|
|
await writeFile(paths.dist, content)
|
|
} else {
|
|
console.error(name, 'No output')
|
|
}
|
|
|
|
await doErrorFile(name, error)
|
|
|
|
return error
|
|
}
|
|
|
|
async function doErrorFile(name: string, error: string | null) {
|
|
let paths = AllPaths.script(name)
|
|
|
|
let content = `${new Date().toISOString()}\n\n${error}`
|
|
|
|
if (error !== null) {
|
|
await writeFile(paths.error, content)
|
|
if (await existsFile(paths.dist)) {
|
|
await unlink(paths.dist)
|
|
}
|
|
} else if (await existsFile(paths.error)) {
|
|
await unlink(paths.error)
|
|
}
|
|
}
|
|
|
|
function existsFile(path: string): Promise<boolean> {
|
|
return new Promise(resolve => {
|
|
stat(path)
|
|
.then(() => resolve(true))
|
|
.catch(() => resolve(false))
|
|
})
|
|
}
|