@typecad/typecad
Version:
🤖programmatically 💥create 🛰️hardware
168 lines (148 loc) • 5.42 kB
JavaScript
import { watch } from 'fs';
import { exec } from 'child_process';
import chalk from 'chalk';
import { fileURLToPath } from 'url';
import { dirname, basename } from 'path';
import * as ts from 'typescript';
import { promisify } from 'util';
import { readFile, writeFile } from 'fs/promises';
import JavaScriptObfuscator from 'javascript-obfuscator';
const execAsync = promisify(exec);
const filesToWatch = [
'index.ts',
'component.ts',
'pcb.ts',
'pcb_registry.ts',
'pcb_kicad_window.ts',
'pcb_track_builder.ts',
'pcb_interfaces.ts',
'schematic.ts',
'buses.ts',
'config.ts',
'erc.ts',
'kicad.ts',
'pin.ts',
'reference_counter.ts',
'component_registry.ts'
];
// Debounce timers for each file
const debounceTimers = new Map();
const DEBOUNCE_DELAY = 500;
console.log(chalk.blue('🔍 Watching files for changes...'));
console.log(chalk.gray('Watching:'));
filesToWatch.forEach(file => console.log(chalk.gray(` - ${file}`)));
async function compileFile(file) {
// console.log('Debug: ts object:', typeof ts !== 'undefined' ? 'defined' : 'undefined');
// if (ts) {
// console.log('Debug: ts.version:', ts.version);
// console.log('Debug: ts.default:', typeof ts.default !== 'undefined' ? 'defined' : 'undefined');
// if (ts.default) {
// console.log('Debug: ts.default.ScriptTarget:', ts.default.ScriptTarget);
// console.log('Debug: ts.default.ModuleKind:', ts.default.ModuleKind);
// console.log('Debug: ts.default.ModuleResolutionKind:', ts.default.ModuleResolutionKind);
// console.log('Debug: ts.default.ScriptTarget.ES2021:', ts.default.ScriptTarget?.ES2021);
// console.log('Debug: ts.default.ModuleKind.ES2020:', ts.default.ModuleKind?.ES2020);
// console.log('Debug: ts.default.ModuleResolutionKind.NodeJs:', ts.default.ModuleResolutionKind?.NodeJs);
// } else {
// // Log original paths if ts.default is not present
// console.log('Debug: ts.ScriptTarget (direct):', ts.ScriptTarget);
// console.log('Debug: ts.ModuleKind (direct):', ts.ModuleKind);
// console.log('Debug: ts.ModuleResolutionKind (direct):', ts.ModuleResolutionKind);
// }
// }
const tsApi = ts.default;
const program = tsApi.createProgram([file], {
target: tsApi.ScriptTarget.ES2021,
module: tsApi.ModuleKind.ES2020,
moduleResolution: tsApi.ModuleResolutionKind.NodeJs, // Changed from Node to NodeJs
esModuleInterop: true,
outDir: 'dist',
declaration: true
});
const emitResult = program.emit();
const diagnostics = tsApi.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
if (diagnostics.length > 0) {
throw new Error(tsApi.formatDiagnosticsWithColorAndContext(diagnostics, {
getCurrentDirectory: () => process.cwd(),
getCanonicalFileName: fileName => fileName,
getNewLine: () => tsApi.sys.newLine
}));
}
}
async function obfuscateFile(file) {
const fileName = basename(file, '.ts');
const inputPath = `dist/${fileName}.js`;
const outputPath = `dist/${fileName}.js`;
const code = await readFile(inputPath, 'utf8');
const obfuscatedCode = JavaScriptObfuscator.obfuscate(code, {
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.5,
deadCodeInjection: false,
debugProtection: false,
disableConsoleOutput: false,
identifierNamesGenerator: "hexadecimal",
numbersToExpressions: true,
renameGlobals: false,
selfDefending: false,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 10,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.5,
stringArrayEncoding: ["base64"],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: "function",
stringArrayThreshold: 0.5,
transformObjectKeys: true,
unicodeEscapeSequence: false
});
await writeFile(outputPath, obfuscatedCode.getObfuscatedCode());
}
async function rebuild(file) {
console.log(chalk.yellow(`\n🔄 Changes detected in ${file}`));
console.log(chalk.gray('Building and obfuscating...'));
const startTime = Date.now();
try {
await compileFile(file);
await obfuscateFile(file);
const endTime = Date.now();
const duration = endTime - startTime;
console.log(chalk.green(`✅ Build completed in ${duration}ms`));
console.log(chalk.gray('Watching for changes...'));
} catch (error) {
console.error(chalk.red('❌ Build failed:'));
console.error(error.message);
}
}
function debouncedRebuild(file) {
if (debounceTimers.has(file)) {
clearTimeout(debounceTimers.get(file));
}
const timer = setTimeout(() => {
rebuild(file);
debounceTimers.delete(file);
}, DEBOUNCE_DELAY);
debounceTimers.set(file, timer);
}
// Initial build
console.log(chalk.blue('🏗️ Running initial build...'));
Promise.all(filesToWatch.map(compileFile))
.then(() => console.log(chalk.green('✅ Initial build completed')))
.catch(error => {
console.error(chalk.red('❌ Initial build failed:'));
console.error(error.message);
});
filesToWatch.forEach(file => {
watch(file, (eventType) => {
if (eventType === 'change') {
debouncedRebuild(file);
}
});
});