Skip to content

Commit ff67ee3

Browse files
committed
fix(cli): refuse an empty entry in a joined file-reference list
1 parent 2ecf96b commit ff67ee3

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

‎packages/sim-cli/src/runtime/file-references.test.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ describe('files batch-delete reads the references a caller writes', () => {
4040
expect(await sentFileIds(['wf_a,wf_b'])).toEqual([['wf_a', 'wf_b']])
4141
})
4242

43+
it('refuses a JSON array or comma-joined run with an empty entry, before any request', async () => {
44+
for (const value of ['["wf_a",""]', 'wf_a,,wf_b', 'wf_a,']) {
45+
const result = await run(['files', 'batch-delete', '--ids', value, '--yes'])
46+
expect(result.exitCode).toBe(1)
47+
expect(result.stderr).toContain('--file-ids values cannot be empty')
48+
expect(result.bodies).toEqual([])
49+
}
50+
})
51+
4352
it('keeps a comma inside a path, so one file is never read as two', async () => {
4453
expect(await sentFileIds(['--paths', 'files/qc/a,b.png', 'files/c.png'])).toEqual([
4554
['files/qc/a,b.png', 'files/c.png'],

‎packages/sim-cli/src/runtime/request.ts‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,18 @@ export async function readArgumentSource(
285285
* ids, or the value itself. See {@link FlagSpec.fileReferences} for why neither reading can
286286
* misread a single id or path.
287287
*/
288-
function fileReferenceEntries(value: string): string[] {
288+
function fileReferenceEntries(value: string, flagName: string): string[] {
289289
const entries = value.startsWith('[')
290290
? jsonStringArray(value)
291291
: value.includes(',') && !value.includes('/')
292292
? value.split(',')
293293
: undefined
294-
return entries ? entries.map((entry) => entry.trim()).filter(Boolean) : [value]
294+
if (!entries) return [value]
295+
const trimmed = entries.map((entry) => entry.trim())
296+
if (trimmed.some((entry) => !entry)) {
297+
throw new SimApiError(`--${flagName} values cannot be empty: ${value}`, 0)
298+
}
299+
return trimmed
295300
}
296301

297302
function jsonStringArray(value: string): string[] | undefined {
@@ -473,9 +478,11 @@ export async function coerce(
473478
*/
474479
if (flag.list) {
475480
const listed = await readListValues(raw, flagName, flag.manifest === true)
476-
const values = (flag.fileReferences ? listed.flatMap(fileReferenceEntries) : listed).map(
477-
(value) => (flag.folderPath ? encodeFolderPath(value) : value)
478-
)
481+
const values = (
482+
flag.fileReferences
483+
? listed.flatMap((value) => fileReferenceEntries(value, flagName))
484+
: listed
485+
).map((value) => (flag.folderPath ? encodeFolderPath(value) : value))
479486
// Encoding first is also what keeps the comma-joined form unambiguous: a
480487
// folder name containing a comma leaves here as `%2C`, so the route's split
481488
// cannot cut one path in half.

0 commit comments

Comments
 (0)