File size: 4,282 Bytes
6a2bc3b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | #!/usr/bin/env node
import { createRequire } from 'node:module';
import { mkdir } from 'node:fs/promises';
import { join, resolve } from 'node:path';
import { runLocalCli } from './local-cli.mjs';
import {
defaultVsixOutputDir,
extensionRoot,
isMainModule,
normalizeVsixTargets,
vsixFileName,
} from './vsix-targets.mjs';
import { verifyVsix } from './vsix-verify.mjs';
const require = createRequire(import.meta.url);
function parseArguments(argv) {
const targets = [];
let outputDir = defaultVsixOutputDir;
let dryRun = false;
let help = false;
for (let index = 0; index < argv.length; index += 1) {
const argument = argv[index];
if (argument === '--') {
continue;
} else if (argument === '--help' || argument === '-h') {
help = true;
} else if (argument === '--dry-run') {
dryRun = true;
} else if (argument === '--out-dir') {
outputDir = requireOptionValue(argv, ++index, '--out-dir');
} else if (argument === '--target') {
targets.push(requireOptionValue(argv, ++index, '--target'));
} else if (argument.startsWith('-')) {
throw new Error(`Unknown option: ${argument}`);
} else {
targets.push(argument);
}
}
return {
targets: normalizeVsixTargets(targets),
outputDir: resolve(outputDir),
dryRun,
help,
};
}
function requireOptionValue(argv, index, option) {
const value = argv[index];
if (value !== undefined && !value.startsWith('-')) return value;
throw new Error(`${option} requires a value.`);
}
function usage() {
return [
'Usage: node scripts/vsix-package.mjs [targets...] [--out-dir <directory>]',
' node scripts/vsix-package.mjs --target win32-x64 --dry-run',
'',
'With no targets, all six supported VSIX targets are built and audited.',
'This command never publishes an extension.',
].join('\n');
}
async function main() {
const options = parseArguments(process.argv.slice(2));
if (options.help) {
console.log(usage());
return;
}
await mkdir(options.outputDir, { recursive: true });
console.log(`VSIX targets: ${options.targets.join(', ')}`);
console.log(`Output directory: ${options.outputDir}`);
if (!options.dryRun) {
console.log('Building the extension once before packaging all targets...');
buildExtension();
}
const packVsix = options.dryRun ? undefined : loadVscePack();
for (const target of options.targets) {
const outputPath = join(options.outputDir, vsixFileName(target));
if (options.dryRun) {
console.log(`Would package ${target} -> ${outputPath}`);
continue;
}
console.log(`\nPackaging ${target} with the workspace @vscode/vsce...`);
await packVsix({
cwd: extensionRoot,
dependencies: false,
packagePath: outputPath,
target,
});
const result = await verifyVsix(outputPath, target, { sourceRoot: extensionRoot });
console.log(
`Verified ${target}: ${result.files} files, ${result.bytes} unpacked bytes; package/static checks passed.`,
);
}
if (!options.dryRun) {
console.log(
'\nVSIX packaging complete. These are package-only results until each target runs in its matching extension host.',
);
}
}
function buildExtension() {
runLocalCli('tsdown', 'tsdown', ['--config', 'tsdown.config.ts'], { cwd: extensionRoot });
runLocalCli('vite', 'vite', ['build', '--config', 'webview-ui/vite.config.ts'], {
cwd: extensionRoot,
});
}
function loadVscePack() {
try {
// VSCE's public API always runs vscode:prepublish. We build once above and pin VSCE,
// so use its package phase directly instead of rebuilding for every target.
const module = require('@vscode/vsce/out/package.js');
if (typeof module.pack !== 'function') {
throw new TypeError('the installed package does not expose pack()');
}
return module.pack;
} catch (error) {
throw new Error(
'The workspace @vscode/vsce package API is unavailable. Run pnpm install; runtime CLI downloads are disabled.',
{ cause: error },
);
}
}
if (isMainModule(import.meta.url)) {
main().catch((error) => {
console.error(`VSIX packaging failed: ${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
});
}
|