Preserve extension version pins through lazy CLI parsing

This commit is contained in:
Forge
2026-09-22 03:10:06 +00:00
parent eab93c3114
commit 79f2d9f1ca
4 changed files with 21 additions and 3 deletions
+13
View File
@@ -38,6 +38,19 @@ describe('codegraph version affordances', () => {
});
}
it('keeps an extension exact-version pin out of the root version flag', () => {
// No registry request is needed: --version without --registry must fail,
// not print the engine version and exit zero.
let result;
try { result = { exit: 0, output: run(['extensions', 'install', 'missing.cgext', '--version', '9.0.0']) }; }
catch (error) {
const e = error as { status: number; stdout: string; stderr: string };
result = { exit: e.status, output: `${e.stdout ?? ''}${e.stderr ?? ''}` };
}
expect(result.exit).toBe(1);
expect(result.output).toContain('--version requires --registry');
});
it('lists the `version` subcommand in --help', () => {
expect(run(['--help'])).toContain('version');
});
+2 -1
View File
@@ -132,13 +132,14 @@ window.addEventListener('message', event => {
if (message.type === 'connected' || message.type === 'status') {
const before = JSON.stringify(state.snapshot);
const wasBusy = state.snapshot?.busy;
const beforeProjects = JSON.stringify(state.snapshot?.projects);
state.snapshot = message.data;
if (wasBusy && !state.snapshot.busy && state.notice) toast(state.snapshot.progress.message);
document.querySelector('#connect').classList.add('connected');
document.querySelector('#connection-label').textContent = 'CodeGraph connected';
if (message.type === 'connected') { toast('Connected. Select your project and install an extension.'); render(); void refreshSelections(); }
else if (JSON.stringify(state.snapshot) !== before && location.pathname !== '/publish') render();
if (wasBusy && !state.snapshot.busy) void refreshSelections();
if (message.type !== 'connected' && !state.snapshot.busy && (wasBusy || JSON.stringify(state.snapshot.projects) !== beforeProjects)) void refreshSelections();
}
if (message.type === 'disconnected') disconnect();
});
@@ -8,7 +8,7 @@ const { createExtensionProject, CodeGraph } = require('../../dist');
const { packExtension } = require('../../dist/plugins/package');
const { startMarketplaceServer } = require('../../dist/plugins/marketplace');
const { startExtensionBridge } = require('../../dist/plugins/bridge');
const repo = path.resolve(__dirname, '../..'), out = path.join(repo, '.qa/recovery/compatibility');
const repo = path.resolve(__dirname, '../..'), out = path.resolve(process.env.COMPAT_OUTPUT || path.join(repo, '.qa/recovery/compatibility'));
fs.mkdirSync(out, { recursive: true });
const lab = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-compatible-'));
const author = path.join(lab, 'author'), checks = [], commands = [], releases = [];
+5 -1
View File
@@ -2807,12 +2807,16 @@ program
* the version affordance in `codegraph --help`.
*/
// Command registration is lightweight; heavy implementation loads only when invoked.
// Preserve extension --version pins for the lazily registered subcommands;
// the root's engine-version flag must not consume them first.
if (process.argv[2] === 'extensions') program.enablePositionalOptions();
const extensionCommands = program.command('extensions').description('Install and manage framework extensions').allowUnknownOption().allowExcessArguments();
extensionCommands.action(async () => {
const { registerExtensionCommands } = await import('../plugins/cli');
const cli = new Command().name('codegraph');
registerExtensionCommands(cli);
await cli.parseAsync(process.argv);
try { await cli.parseAsync(process.argv); }
catch (error) { console.error(error instanceof Error ? error.message : String(error)); process.exitCode = 1; }
});
program