Files
2026-07-13 12:38:34 +08:00

108 lines
3.8 KiB
TypeScript

#!/usr/bin/env bun
import { $ } from 'bun';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const packageRoot = path.resolve(scriptDir, '..');
const repoRoot = path.resolve(packageRoot, '../../..');
const swiftPackagePath = path.join(packageRoot, 'native/composio-native-ui');
const outputRoot = path.join(packageRoot, 'local-tools-binaries/composio-native-ui');
const targets = [
{
platform: 'darwin-arm64',
swiftArch: 'arm64',
buildPath: '.build/arm64-apple-macosx/release/composio-native-ui',
},
] as const;
type Target = (typeof targets)[number];
const exists = async (filePath: string): Promise<boolean> =>
fs
.access(filePath)
.then(() => true)
.catch(() => false);
const ensurePlatform = () => {
if (process.platform !== 'darwin') {
throw new Error(
'Building the Composio native UI sidecar requires macOS and the Swift toolchain.'
);
}
};
const buildTarget = async (target: Target) => {
console.log(`Building composio-native-ui for ${target.platform} (${target.swiftArch})...`);
await $`swift build -c release --product composio-native-ui --arch ${target.swiftArch}`.cwd(
swiftPackagePath
);
const builtBinary = path.join(swiftPackagePath, target.buildPath);
if (!(await exists(builtBinary))) {
throw new Error(`Swift build completed but ${target.buildPath} was not produced.`);
}
const targetDir = path.join(outputRoot, target.platform);
const outputBinary = path.join(targetDir, 'composio-native-ui');
await fs.mkdir(targetDir, { recursive: true });
await fs.copyFile(builtBinary, outputBinary);
await fs.chmod(outputBinary, 0o755);
console.log(`Wrote ${path.relative(repoRoot, outputBinary)}`);
};
const writeNotice = async () => {
const notice = `# Composio native UI sidecar
The \`composio-native-ui\` binaries are built from the in-repository Swift package at \`ts/packages/cli-local-tools/native/composio-native-ui\`.
- Purpose: native macOS UI surface that the Bun-compiled Composio CLI can spawn for auth flows, tool pickers, and other desktop affordances.
- Build command: \`pnpm --filter @composio/cli-local-tools build:composio-native-ui -- --target <darwin-arm64>\`
- Underlying Swift build commands:
- \`swift build -c release --product composio-native-ui --arch arm64\`
The scaffold currently opens a small AppKit panel near the bottom-right corner of the active screen. Generated executables are intentionally not committed; release jobs rebuild them before packaging CLI artifacts.
`;
await fs.writeFile(path.join(outputRoot, 'NOTICE.md'), notice, 'utf8');
};
const parseTargets = (): ReadonlyArray<Target> => {
const rawArgs = process.argv.slice(2).filter(arg => arg !== '--');
const targetIndex = rawArgs.indexOf('--target');
const args =
targetIndex >= 0 && rawArgs[targetIndex + 1]
? [rawArgs[targetIndex + 1]!]
: rawArgs.filter(arg => !arg.startsWith('--'));
if (args.length === 0 || args.includes('all')) return targets;
const selected = targets.filter(target => args.includes(target.platform));
const unknown = args.filter(arg => !targets.some(target => target.platform === arg));
if (unknown.length > 0) {
throw new Error(
`Unknown target(s): ${unknown.join(', ')}. Expected one of: all, ${targets
.map(target => target.platform)
.join(', ')}`
);
}
return selected;
};
const main = async () => {
ensurePlatform();
await fs.mkdir(outputRoot, { recursive: true });
const selectedTargets = parseTargets();
for (const target of selectedTargets) {
await buildTarget(target);
}
await writeNotice();
};
main().catch(error => {
console.error(error instanceof Error ? error.message : error);
process.exit(1);
});