129 lines
4.4 KiB
TypeScript
129 lines
4.4 KiB
TypeScript
import * as plugins from './plugins.js';
|
|
import type { ITsdenoConfig, ICompileTarget } from './tsdeno.interfaces.js';
|
|
|
|
const shell = new plugins.smartshell.Smartshell({
|
|
executor: 'bash',
|
|
});
|
|
|
|
const smartfs = new plugins.SmartFs(new plugins.SmartFsProviderNode());
|
|
|
|
export class TsDeno {
|
|
public cwd: string;
|
|
|
|
constructor(cwdArg?: string) {
|
|
this.cwd = cwdArg || process.cwd();
|
|
}
|
|
|
|
/**
|
|
* Wraps `deno compile` with package.json isolation.
|
|
* Temporarily removes package.json so Deno doesn't resolve devDependencies
|
|
* into the compiled binary, then restores it afterwards.
|
|
*/
|
|
public async compile(args: string[]): Promise<void> {
|
|
const packageJsonPath = plugins.path.join(this.cwd, 'package.json');
|
|
const backupPath = plugins.path.join(this.cwd, 'package.json.bak');
|
|
|
|
const hasPackageJson = await smartfs.file(packageJsonPath).exists();
|
|
|
|
// Ensure --node-modules-dir=none is present
|
|
if (!args.some((arg) => arg.startsWith('--node-modules-dir'))) {
|
|
args = ['--node-modules-dir=none', ...args];
|
|
}
|
|
|
|
// Temporarily hide package.json from Deno
|
|
if (hasPackageJson) {
|
|
console.log('tsdeno: temporarily hiding package.json to exclude devDependencies from bundle');
|
|
await smartfs.file(packageJsonPath).move(backupPath);
|
|
}
|
|
|
|
try {
|
|
const shellCommand = `cd ${this.cwd} && deno compile ${args.join(' ')}`;
|
|
console.log(`tsdeno: running deno compile ${args.join(' ')}`);
|
|
const result = await shell.execPassthrough(shellCommand);
|
|
|
|
if (result.exitCode !== 0) {
|
|
console.error(`tsdeno: deno compile exited with code ${result.exitCode}`);
|
|
process.exit(result.exitCode);
|
|
}
|
|
} finally {
|
|
// Always restore package.json
|
|
if (hasPackageJson) {
|
|
await smartfs.file(backupPath).move(packageJsonPath);
|
|
console.log('tsdeno: restored package.json');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads compile targets from npmextra.json and compiles each one.
|
|
* The package.json hide/restore wraps the entire loop.
|
|
*/
|
|
public async compileFromConfig(): Promise<void> {
|
|
const npmextraInstance = new plugins.npmextra.Npmextra(this.cwd);
|
|
const config = npmextraInstance.dataFor<ITsdenoConfig>('@git.zone/tsdeno', {
|
|
compileTargets: [],
|
|
});
|
|
|
|
if (config.compileTargets.length === 0) {
|
|
console.error('tsdeno: no compileTargets found in npmextra.json under "@git.zone/tsdeno"');
|
|
console.error('tsdeno: either pass args directly or add config to npmextra.json');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`tsdeno: found ${config.compileTargets.length} compile target(s) in npmextra.json`);
|
|
|
|
const packageJsonPath = plugins.path.join(this.cwd, 'package.json');
|
|
const backupPath = plugins.path.join(this.cwd, 'package.json.bak');
|
|
const hasPackageJson = await smartfs.file(packageJsonPath).exists();
|
|
|
|
// Hide package.json once for all targets
|
|
if (hasPackageJson) {
|
|
console.log('tsdeno: temporarily hiding package.json to exclude devDependencies from bundle');
|
|
await smartfs.file(packageJsonPath).move(backupPath);
|
|
}
|
|
|
|
try {
|
|
for (const target of config.compileTargets) {
|
|
console.log(`\ntsdeno: compiling target "${target.name}"...`);
|
|
const args = this.buildArgsFromTarget(target);
|
|
const shellCommand = `cd ${this.cwd} && deno compile ${args.join(' ')}`;
|
|
console.log(`tsdeno: running deno compile ${args.join(' ')}`);
|
|
const result = await shell.execPassthrough(shellCommand);
|
|
|
|
if (result.exitCode !== 0) {
|
|
console.error(`tsdeno: deno compile exited with code ${result.exitCode} for target "${target.name}"`);
|
|
process.exit(result.exitCode);
|
|
}
|
|
}
|
|
} finally {
|
|
if (hasPackageJson) {
|
|
await smartfs.file(backupPath).move(packageJsonPath);
|
|
console.log('\ntsdeno: restored package.json');
|
|
}
|
|
}
|
|
|
|
console.log(`\ntsdeno: all ${config.compileTargets.length} target(s) compiled successfully`);
|
|
}
|
|
|
|
private buildArgsFromTarget(target: ICompileTarget): string[] {
|
|
const args: string[] = ['--node-modules-dir=none'];
|
|
|
|
if (target.noCheck) {
|
|
args.push('--no-check');
|
|
}
|
|
|
|
if (target.permissions) {
|
|
args.push(...target.permissions);
|
|
}
|
|
|
|
const outputPath = plugins.path.join(target.outDir, target.name);
|
|
args.push('--output', outputPath);
|
|
|
|
args.push('--target', target.target);
|
|
|
|
args.push(target.entryPoint);
|
|
|
|
return args;
|
|
}
|
|
}
|