From b0f30918ba8f28574ff6d6aa0460863e933b54db Mon Sep 17 00:00:00 2001 From: kuntal1461 Date: Wed, 19 Aug 2026 18:26:43 +0530 Subject: [PATCH] fix: actor set-value KEY with no value doesn't delete the record Fixes #1193. `value || process.stdin` coerced both the omitted-arg case (undefined) and the explicit-empty-string case ("") to the already-drained process.stdin stream, so the deletion check never fired. Replace with `value ?? cachedStdinInput` to use the pre-buffered stdin and preserve the empty-string sentinel for deletion. --- src/commands/actor/set-value.ts | 3 ++- test/e2e/commands/actor/set-value.test.ts | 32 +++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/commands/actor/set-value.ts b/src/commands/actor/set-value.ts index 5d6d1330b..2a68aee12 100644 --- a/src/commands/actor/set-value.ts +++ b/src/commands/actor/set-value.ts @@ -1,3 +1,4 @@ +import { cachedStdinInput } from '../../entrypoints/_shared.js'; import { APIFY_STORAGE_TYPES, getApifyStorageClient, getDefaultStorageId } from '../../lib/actor.js'; import { ApifyCommand } from '../../lib/command-framework/apify-command.js'; import { Args } from '../../lib/command-framework/args.js'; @@ -56,7 +57,7 @@ export class ActorSetValueCommand extends ApifyCommand { cwd: actor.dir, }); expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0); + + const recordPath = path.join(actor.dir, 'storage', 'key_value_stores', 'default', 'MY_KEY.json'); + await expect(readFile(recordPath, 'utf-8')).resolves.toBe('{"hello":"world"}'); + }); + + it('deletes a value when no value or stdin is provided', async () => { + const recordPath = path.join(actor.dir, 'storage', 'key_value_stores', 'default', 'DELETE_ME.json'); + const setResult = await runCli('apify', ['actor', 'set-value', 'DELETE_ME', '{"exists":true}'], { + cwd: actor.dir, + }); + expect(setResult.exitCode, `stderr: ${setResult.stderr}`).toBe(0); + await expect(readFile(recordPath, 'utf-8')).resolves.toBe('{"exists":true}'); + + const deleteResult = await runCli('apify', ['actor', 'set-value', 'DELETE_ME'], { + cwd: actor.dir, + }); + expect(deleteResult.exitCode, `stderr: ${deleteResult.stderr}`).toBe(0); + await expect(access(recordPath)).rejects.toThrow(); + }); + + it('sets a value from stdin', async () => { + const result = await runCli('apify', ['actor', 'set-value', 'FROM_STDIN', '--content-type', 'text/plain'], { + cwd: actor.dir, + stdin: 'VALUE', + }); + expect(result.exitCode, `stderr: ${result.stderr}`).toBe(0); + + const recordPath = path.join(actor.dir, 'storage', 'key_value_stores', 'default', 'FROM_STDIN.txt'); + await expect(readFile(recordPath, 'utf-8')).resolves.toBe('VALUE'); }); });