Skip to content

Commit fb4bd37

Browse files
committed
fix: improve parseFlags and dispatchSubcommand error handling
1 parent 5d484ad commit fb4bd37

2 files changed

Lines changed: 37 additions & 5 deletions

File tree

src/cli.test.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,11 @@ afterEach(async () => {
4646
});
4747

4848
describe('dispatchSubcommand', () => {
49-
it('returns false for unknown subcommand', async () => {
49+
it('throws for unknown subcommand', async () => {
5050
const { dispatchSubcommand } = await import('./cli.js');
51-
expect(await dispatchSubcommand(['node', 'cli.js', 'unknown'])).toBe(false);
51+
await expect(dispatchSubcommand(['node', 'cli.js', 'unknown'])).rejects.toThrow(
52+
'Unknown subcommand: "unknown"',
53+
);
5254
});
5355

5456
it('returns true and runs add-app-extension for matching subcommand', async () => {
@@ -109,6 +111,13 @@ describe('parseFlags', () => {
109111
expect(parseFlags(['node', 'cli.js', '--app-extensions', 'none'])).toMatchObject({ appExtensions: [] });
110112
});
111113

114+
it('throws when --app-extensions combines none with extension types', async () => {
115+
const { parseFlags } = await import('./cli.js');
116+
expect(() => parseFlags(['node', 'cli.js', '--app-extensions', 'none,custom-panel'])).toThrow(
117+
'"none" cannot be combined with other extension types.',
118+
);
119+
});
120+
112121
it('parses --app-extensions custom-panel', async () => {
113122
const { parseFlags } = await import('./cli.js');
114123
expect(parseFlags(['node', 'cli.js', '--app-extensions', 'custom-panel'])).toMatchObject({
@@ -140,7 +149,16 @@ describe('parseFlags', () => {
140149
it('parses all three flags together', async () => {
141150
const { parseFlags } = await import('./cli.js');
142151
expect(
143-
parseFlags(['node', 'cli.js', '--project-name', 'my-app', '--database', 'sqlite', '--app-extensions', 'none']),
152+
parseFlags([
153+
'node',
154+
'cli.js',
155+
'--project-name',
156+
'my-app',
157+
'--database',
158+
'sqlite',
159+
'--app-extensions',
160+
'none',
161+
]),
144162
).toEqual({ nameOrPath: 'my-app', database: 'sqlite', appExtensions: [] });
145163
});
146164
});

src/cli.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ export function parseFlags(argv: string[]): ParsedFlags {
8383
if (value === 'none') {
8484
result.appExtensions = [];
8585
} else {
86+
if (value.includes(',') && value.split(',').includes('none')) {
87+
throw new Error('"none" cannot be combined with other extension types.');
88+
}
8689
const types = value.split(',');
8790
for (const type of types) {
8891
if (!isAppExtensionType(type)) {
@@ -104,12 +107,23 @@ export async function dispatchSubcommand(argv: string[]): Promise<boolean> {
104107
if (subcommand === 'add-app-extension') {
105108
const appExtIdx = argv.indexOf('--app-extensions');
106109
const appExtValue = appExtIdx !== -1 ? argv[appExtIdx + 1] : undefined;
107-
const appExtensions: AppExtensionType[] | undefined =
108-
appExtValue !== undefined && isAppExtensionType(appExtValue) ? [appExtValue] : undefined;
110+
let appExtensions: AppExtensionType[] | undefined;
111+
if (appExtValue !== undefined) {
112+
if (!isAppExtensionType(appExtValue)) {
113+
throw new Error(
114+
`Invalid app extension type "${appExtValue}". Choose from: custom-panel, custom-modal.`,
115+
);
116+
}
117+
appExtensions = [appExtValue];
118+
}
109119
await addAppExtension(outputDir, appExtensions);
110120
return true;
111121
}
112122

123+
if (subcommand && !subcommand.startsWith('--')) {
124+
throw new Error(`Unknown subcommand: "${subcommand}". Available: add-app-extension`);
125+
}
126+
113127
return false;
114128
}
115129

0 commit comments

Comments
 (0)