///
import { spawn } from "child_process";
import { readFileSync, writeFileSync } from "fs";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const projectRoot = join(__dirname, "..");
const adapterPath = join(projectRoot, "src/utils/platformAdapter.ts");
type AdapterMode = "tauri" | "web";
function stripLineComments(content: string) {
return content
.split(/\r?\n/)
.filter((line) => !line.trimStart().startsWith("//"))
.join("\n");
}
function detectAdapterMode(content: string): AdapterMode {
const activeContent = stripLineComments(content);
const usesTauriAdapter =
/import\s*\{\s*createTauriAdapter\s*\}\s*from\s*["']\.\/tauriAdapter["']/.test(
activeContent
) && /platformAdapter\s*=\s*createTauriAdapter\s*\(/.test(activeContent);
const usesWebAdapter =
/import\s*\{\s*createWebAdapter\s*\}\s*from\s*["']\.\/webAdapter["']/.test(
activeContent
) && /platformAdapter\s*=\s*createWebAdapter\s*\(/.test(activeContent);
if (usesTauriAdapter && !usesWebAdapter) {
return "tauri";
}
if (usesWebAdapter && !usesTauriAdapter) {
return "web";
}
throw new Error(
`Unable to detect active platform adapter in ${adapterPath}. ` +
`Expected either createTauriAdapter() or createWebAdapter() to be active.`
);
}
function setLineComment(line: string, commented: boolean) {
const indent = line.match(/^\s*/)?.[0] ?? "";
const content = line.slice(indent.length);
const uncommented = content.replace(/^\/\/\s?/, "");
return commented ? `${indent}// ${uncommented}` : `${indent}${uncommented}`;
}
function switchToWebAdapter(content: string) {
let hasTauriImport = false;
let hasTauriInit = false;
let hasWebImport = false;
let hasWebInit = false;
const nextContent = content
.split(/\r?\n/)
.map((line) => {
const normalized = line.trim().replace(/^\/\/\s?/, "");
if (
normalized === 'import { createTauriAdapter } from "./tauriAdapter";'
) {
hasTauriImport = true;
return setLineComment(line, true);
}
if (normalized === "let platformAdapter = createTauriAdapter();") {
hasTauriInit = true;
return setLineComment(line, true);
}
if (normalized === 'import { createWebAdapter } from "./webAdapter";') {
hasWebImport = true;
return setLineComment(line, false);
}
if (normalized === "let platformAdapter = createWebAdapter();") {
hasWebInit = true;
return setLineComment(line, false);
}
return line;
})
.join("\n");
if (!hasTauriImport || !hasTauriInit || !hasWebImport || !hasWebInit) {
throw new Error(
`Unable to switch ${adapterPath} to Web mode. ` +
`Expected both Tauri and Web adapter import/init lines to exist.`
);
}
detectAdapterMode(nextContent);
return nextContent;
}
function run(command: string, args: string[]) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd: projectRoot,
env: {
...process.env,
BUILD_TARGET: "web",
},
shell: process.platform === "win32",
stdio: "inherit",
});
child.on("error", reject);
child.on("exit", (code) => {
if (code === 0) {
resolve();
return;
}
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
});
});
}
async function main() {
const originalContent = readFileSync(adapterPath, "utf-8");
const originalMode = detectAdapterMode(originalContent);
const shouldRestore = originalMode !== "web";
if (shouldRestore) {
console.log("[build:web] Switching platform adapter to Web for packaging.");
writeFileSync(adapterPath, switchToWebAdapter(originalContent), "utf-8");
} else {
console.log("[build:web] Platform adapter is already Web; leaving it as-is.");
}
try {
await run("pnpm", ["exec", "tsc"]);
await run("pnpm", ["exec", "tsup", "--format", "esm"]);
} finally {
if (shouldRestore) {
writeFileSync(adapterPath, originalContent, "utf-8");
console.log("[build:web] Restored original platform adapter.");
} else {
console.log("[build:web] Kept platform adapter in original Web mode.");
}
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});