From d4801e9311f9f9b3148eeac2c9573646b11cc5f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Sol=C3=A1r?= Date: Fri, 13 Mar 2026 00:43:27 +0100 Subject: [PATCH] fix(): prevent modifying local input.json file --- src/commands/run.ts | 15 +++++---------- test/local/commands/crawlee/run.test.ts | 11 +++++++---- test/local/commands/run.test.ts | 8 ++++++-- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/commands/run.ts b/src/commands/run.ts index cc1dbaf26..94fb5ced8 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -410,7 +410,9 @@ export class RunCommand extends ApifyCommand { } /** - * Ensures the input that the actor will be ran with locally matches the input schema (and prefills default values if missing) + * Validates the input against the input schema and writes to disk only when necessary. + * When the user already has an INPUT.json and no override is provided, it validates in-memory + * without modifying the file (returns null so the finally block is a no-op). * @param inputOverride Optional input received through command flags */ private async validateAndStoreInput(inputOverride?: { input: Record; source: string }) { @@ -536,15 +538,8 @@ export class RunCommand extends ApifyCommand { ); } - // Step 4: store the input - await mkdir(dirname(inputFilePath), { recursive: true }); - await writeFile(inputFilePath, JSON.stringify(fullInput, null, 2)); - - return { - existingInput, - inputFilePath, - writtenAt: Date.now(), - }; + // Don't write to the file — leave the user's INPUT.json untouched + return null; } return null; diff --git a/test/local/commands/crawlee/run.test.ts b/test/local/commands/crawlee/run.test.ts index 6d06d891b..69174d587 100644 --- a/test/local/commands/crawlee/run.test.ts +++ b/test/local/commands/crawlee/run.test.ts @@ -68,22 +68,25 @@ describe('apify run', () => { expect(lastErrorMessage()).toMatch(/Field awesome is required/i); }); - it('prefills input with defaults', async () => { + it('validates input without modifying file', async () => { await writeFile(inputPath, originalInput); await testRunCommand(RunCommand, {}); const output = JSON.parse(await readFile(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you' }); + + const inputAfterRun = await readFile(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalInput); }); - it('should restore the original input file after run', async () => { + it('does not modify input file during run', async () => { await writeFile(inputPath, originalInputWithExtraField); await testRunCommand(RunCommand, {}); - const input = JSON.parse(await readFile(inputPath, 'utf8')); - expect(input).toStrictEqual({ awesome: true, extra: 'field' }); + const inputAfterRun = await readFile(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalInputWithExtraField); const output = JSON.parse(await readFile(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you', extra: 'field' }); diff --git a/test/local/commands/run.test.ts b/test/local/commands/run.test.ts index dbbf6fc9b..547b0451e 100644 --- a/test/local/commands/run.test.ts +++ b/test/local/commands/run.test.ts @@ -333,14 +333,18 @@ writeFileSync(String.raw\`${joinPath('result.txt')}\`, 'hello world'); expect(lastErrorMessage()).toMatch(/Field help must be string/i); }); - it('automatically inserts missing defaulted fields', async () => { - writeFileSync(inputPath, '{"awesome": true}', { flag: 'w' }); + it('does not inject defaults into existing input file', async () => { + const originalContent = '{"awesome": true}'; + writeFileSync(inputPath, originalContent, { flag: 'w' }); copyFileSync(defaultsInputSchemaPath, inputSchemaPath); await testRunCommand(RunCommand, {}); const output = JSON.parse(readFileSync(outputPath, 'utf8')); expect(output).toStrictEqual({ awesome: true, help: 'this_maze_is_not_meant_for_you' }); + + const inputAfterRun = readFileSync(inputPath, 'utf8'); + expect(inputAfterRun).toBe(originalContent); }); it('does not insert missing prefilled fields', async () => {