From 9e5d12970704646d96dfc4f5fb707a190e959ddb Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 1 Sep 2026 16:07:29 +0700 Subject: [PATCH] fix: drop the NUL byte from shortcutKey and add it to the default export src/index.tsx held a literal U+0000 where shortcutKey builds its separator, so every key came out as "id{...}" instead of "id {...}". That has two consequences: * The byte reaches consumers. shortcutKey is documented public API and the same string is baked into lib/module/index.js, so anything that logs the key, stores it, or uses it as a React key carries a control character it never asked for. * Git classified src/index.tsx as binary, so every diff of the package entry point rendered as "Binary files differ" and blame, grep and code search all failed on it. That clears once this lands, because the new blob is plain text. shortcutKey is also added to the default export. README.md states that every function is reachable both as a named export and on the default export, and this was the one that was not, so `import AppShortcuts from '@giabaojs/react-native-app-shortcuts'` followed by `AppShortcuts.shortcutKey(item)` threw a TypeError. Both are covered: one test asserts the key holds no control characters, the other derives the expected default export from the module's own named function exports so a later addition cannot silently drift again. --- src/__tests__/shortcuts.test.ts | 27 ++++++++++++++++++++++++++- src/index.tsx | Bin 6711 -> 6726 bytes 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/__tests__/shortcuts.test.ts b/src/__tests__/shortcuts.test.ts index 8d334ff..68539aa 100644 --- a/src/__tests__/shortcuts.test.ts +++ b/src/__tests__/shortcuts.test.ts @@ -1,4 +1,4 @@ -import { +import AppShortcuts, { clearShortcuts, getInitialShortcut, getShortcuts, @@ -6,6 +6,7 @@ import { shortcutKey, type ShortcutItem, } from '../index'; +import * as namedExports from '../index'; import NativeAppShortcuts from '../NativeAppShortcuts'; jest.mock('../NativeAppShortcuts', () => ({ @@ -153,4 +154,28 @@ describe('shortcutKey', () => { shortcutKey({ id: 'b', title: 'T' }) ); }); + + // The key is public API and ends up in logs, Map keys and React keys, so a + // stray control character in the separator is a defect callers cannot see. + it('contains no control characters', () => { + const key = shortcutKey({ id: 'a', title: 'T', data: { x: '1' } }); + + expect([...key].filter((char) => char.charCodeAt(0) < 0x20)).toEqual([]); + expect(key).toBe('a {"x":"1"}'); + }); +}); + +describe('default export', () => { + // The README promises every function is reachable both ways, so this is + // derived from the module rather than a hand-kept list that can drift. + it('carries every function the module exports by name', () => { + const functionExports = Object.entries(namedExports) + .filter( + ([name, value]) => name !== 'default' && typeof value === 'function' + ) + .map(([name]) => name); + + expect(functionExports).toContain('shortcutKey'); + expect(Object.keys(AppShortcuts).sort()).toEqual(functionExports.sort()); + }); }); diff --git a/src/index.tsx b/src/index.tsx index 143876fd3285cb827ab805474dfb206870c2d9ea..4be5fabd95b003267932d892493551b13ed9e7a7 100644 GIT binary patch delta 33 ocmdmPa?E6dA1kB6W`EYFB0>rZ#TofUCCQ~F-l>&3T(#C*0L4fO`2YX_ delta 18 ZcmX?RvfX5ZA1fonW`EYFBFwecTmU|H1+M@A