154 lines
4 KiB
JavaScript
154 lines
4 KiB
JavaScript
#!/usr/bin/env node
|
|
const { spawnSync } = require("node:child_process");
|
|
const {
|
|
copyFileSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
readdirSync,
|
|
rmSync,
|
|
writeFileSync,
|
|
} = require("node:fs");
|
|
const { dirname, join, resolve } = require("node:path");
|
|
|
|
const root = resolve(__dirname, "..");
|
|
const srcResources = join(root, "src", "resources");
|
|
const distResources = join(root, "dist", "resources");
|
|
const resourcesTsconfig = join(root, "tsconfig.resources.json");
|
|
|
|
function copyNonTsFiles(srcDir, destDir) {
|
|
for (const entry of readdirSync(srcDir, { withFileTypes: true })) {
|
|
const srcPath = join(srcDir, entry.name);
|
|
const destPath = join(destDir, entry.name);
|
|
|
|
if (entry.isDirectory()) {
|
|
copyNonTsFiles(srcPath, destPath);
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
entry.name.endsWith(".ts") ||
|
|
entry.name.endsWith(".tsx") ||
|
|
entry.name.endsWith(".js") ||
|
|
entry.name.endsWith(".jsx")
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
mkdirSync(dirname(destPath), { recursive: true });
|
|
|
|
// Rewrite pi.extensions paths from .ts to .js in package.json files
|
|
// so they match the compiled output (tsc compiles index.ts → index.js
|
|
// but package.json is copied as-is).
|
|
if (entry.name === "package.json") {
|
|
try {
|
|
const pkg = JSON.parse(readFileSync(srcPath, "utf-8"));
|
|
if (Array.isArray(pkg?.pi?.extensions)) {
|
|
pkg.pi.extensions = pkg.pi.extensions.map((ext) =>
|
|
ext.replace(/\.ts$/, ".js").replace(/\.tsx$/, ".js"),
|
|
);
|
|
writeFileSync(destPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
continue;
|
|
}
|
|
} catch {
|
|
/* fall through to plain copy */
|
|
}
|
|
}
|
|
|
|
copyFileSync(srcPath, destPath);
|
|
}
|
|
}
|
|
|
|
rmSync(distResources, { recursive: true, force: true });
|
|
|
|
// Check if there are any .ts files to compile
|
|
function hasTsFilesRecursive(dir) {
|
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
const fullPath = join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
if (hasTsFilesRecursive(fullPath)) return true;
|
|
} else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts")) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
const hasTsFiles = hasTsFilesRecursive(srcResources);
|
|
|
|
if (hasTsFiles) {
|
|
const tsgoBin = join(
|
|
dirname(require.resolve("@typescript/native-preview/package.json")),
|
|
"bin",
|
|
"tsgo.js",
|
|
);
|
|
const compileWithTsgo = () =>
|
|
spawnSync(process.execPath, [tsgoBin, "--project", resourcesTsconfig], {
|
|
cwd: root,
|
|
stdio: "inherit",
|
|
});
|
|
const compileWithTsc = () => {
|
|
const tscBin = require.resolve("typescript/bin/tsc");
|
|
return spawnSync(
|
|
process.execPath,
|
|
[tscBin, "--project", resourcesTsconfig],
|
|
{
|
|
cwd: root,
|
|
stdio: "inherit",
|
|
},
|
|
);
|
|
};
|
|
|
|
let compile = compileWithTsgo();
|
|
|
|
if (compile.status !== 0) {
|
|
process.exit(compile.status ?? 1);
|
|
}
|
|
|
|
// Native tsgo has reported successful emits while leaving .ts resources copied
|
|
// without their .js runtime output. Verify a known TS-only resource before the
|
|
// launcher tries to import it, and fall back to local tsc if needed.
|
|
const requiredJs = join(
|
|
distResources,
|
|
"extensions",
|
|
"sf",
|
|
"model-registry.js",
|
|
);
|
|
try {
|
|
readFileSync(requiredJs);
|
|
} catch {
|
|
console.warn(
|
|
"[copy-resources] tsgo did not emit model-registry.js; retrying resources build with tsc",
|
|
);
|
|
compile = compileWithTsc();
|
|
if (compile.status !== 0) {
|
|
process.exit(compile.status ?? 1);
|
|
}
|
|
}
|
|
} else {
|
|
// No .ts files — just create the dist/resources directory and copy .js files
|
|
mkdirSync(distResources, { recursive: true });
|
|
}
|
|
|
|
copyNonTsFiles(srcResources, distResources);
|
|
|
|
// Also copy .js files since they're not compiled from .ts
|
|
function copyJsFiles(srcDir, destDir) {
|
|
for (const entry of readdirSync(srcDir, { withFileTypes: true })) {
|
|
const srcPath = join(srcDir, entry.name);
|
|
const destPath = join(destDir, entry.name);
|
|
|
|
if (entry.isDirectory()) {
|
|
copyJsFiles(srcPath, destPath);
|
|
continue;
|
|
}
|
|
|
|
if (entry.name.endsWith(".js")) {
|
|
mkdirSync(dirname(destPath), { recursive: true });
|
|
copyFileSync(srcPath, destPath);
|
|
}
|
|
}
|
|
}
|
|
copyJsFiles(srcResources, distResources);
|
|
writeFileSync(
|
|
join(distResources, ".sf-resource-build-stamp"),
|
|
`${new Date().toISOString()}\n`,
|
|
);
|