experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix tile-preload: wrap settings get/set to return {success, data} shape

+36 -11
+36 -11
backend/electron/tile-preload.cts
··· 927 927 // shape — wrapped to log first-use per tile. 928 928 api.settings = { 929 929 /** 930 - * Get a setting value (returns raw value, no wrapper) 930 + * Get a setting value. Returns a normalised response object that 931 + * satisfies BOTH the legacy `{success, data}` shape used by most 932 + * feature callers AND the strict `{value, error}` shape emitted by 933 + * `tile:settings:get`. Fields present on the returned object: 934 + * success — true when no error occurred 935 + * data — the stored value (alias for `value`) 936 + * value — the stored value (strict-IPC field, kept for callers 937 + * that already destructure the strict shape) 938 + * error — error string when the call failed, undefined otherwise 931 939 */ 932 - get: (key: string) => { 940 + get: async (key: string) => { 933 941 if (!tokenValid) return Promise.reject(new Error('Not initialized')); 934 - return ipcRenderer.invoke('tile:settings:get', { 942 + const r = await ipcRenderer.invoke('tile:settings:get', { 935 943 token: tileToken, 936 944 key, 937 - }); 945 + }) as { value?: unknown; error?: string } | null; 946 + if (!r || r.error) { 947 + return { success: false, data: undefined, value: undefined, error: r?.error ?? 'unknown error' }; 948 + } 949 + return { success: true, data: r.value, value: r.value, error: undefined }; 938 950 }, 939 951 940 952 /** 941 - * Set a setting value 953 + * Set a setting value. Returns a normalised `{success, error}` object 954 + * so callers that inspect the result get a consistent shape. 942 955 */ 943 - set: (key: string, value: unknown) => { 956 + set: async (key: string, value: unknown) => { 944 957 if (!tokenValid) return Promise.reject(new Error('Not initialized')); 945 - return ipcRenderer.invoke('tile:settings:set', { 958 + const r = await ipcRenderer.invoke('tile:settings:set', { 946 959 token: tileToken, 947 960 key, 948 961 value, 949 - }); 962 + }) as { error?: string } | null; 963 + if (!r || r.error) { 964 + return { success: false, error: r?.error ?? 'unknown error' }; 965 + } 966 + return { success: true, error: undefined }; 950 967 }, 951 968 952 969 /** ··· 983 1000 /** 984 1001 * Phase 4: getExtKey v1-compat fallback REMOVED. Strict path only. 985 1002 * Tile manifest must declare settings.readForeign to use this. 1003 + * 1004 + * Returns a normalised `{success, data, value, error}` object so that 1005 + * callers using either the legacy `{success, data}` shape or the strict 1006 + * `{value, error}` shape both work correctly. 986 1007 */ 987 1008 getExtKey: async (extId: unknown, key: unknown) => { 988 1009 if (!extId || !key) { 989 - return { success: false, error: 'extId and key are required' }; 1010 + return { success: false, data: undefined, value: undefined, error: 'extId and key are required' }; 990 1011 } 991 1012 if (!hasSettingsForeignCapability()) { 992 1013 throw new Error('[tile-preload] api.settings.getExtKey requires settings.readForeign capability in manifest (Phase 4: v1-compat fallback removed)'); 993 1014 } 994 - return ipcRenderer.invoke('tile:settings:get-foreign', { 1015 + const r = await ipcRenderer.invoke('tile:settings:get-foreign', { 995 1016 token: tileToken, 996 1017 foreignExtId: extId, 997 1018 key, 998 - }); 1019 + }) as { value?: unknown; error?: string } | null; 1020 + if (!r || r.error) { 1021 + return { success: false, data: undefined, value: undefined, error: r?.error ?? 'unknown error' }; 1022 + } 1023 + return { success: true, data: r.value, value: r.value, error: undefined }; 999 1024 }, 1000 1025 }; 1001 1026