👷 Typescript: Improving typing of asyncStorage (global-store.json) (#4369)

* typing globalprefs

* adding release notes

* unneeded partial

* removing prop that crept in
This commit is contained in:
Michael Clark
2025-02-19 18:40:12 +00:00
committed by GitHub
parent fc78d5b546
commit 04b5bdc62f
7 changed files with 70 additions and 18 deletions

View File

@@ -1,20 +1,34 @@
import { GlobalPrefs, GlobalPrefsJson } from '../../../types/prefs';
export function init(opts?: { persist?: boolean }): void;
export type Init = typeof init;
export function getItem(key: string): Promise<string>;
type InferType<K extends keyof GlobalPrefsJson> = GlobalPrefs[K];
export function getItem<K extends keyof GlobalPrefsJson>(
key: K,
): Promise<GlobalPrefsJson[K]>;
export type GetItem = typeof getItem;
export function setItem(key: string, value: unknown): void;
export function setItem<K extends keyof GlobalPrefsJson>(
key: K,
value: GlobalPrefsJson[K],
): void;
export type SetItem = typeof setItem;
export function removeItem(key: string): void;
export function removeItem(key: keyof GlobalPrefsJson): void;
export type RemoveItem = typeof removeItem;
export function multiGet(keys: string[]): Promise<[string, string][]>;
export async function multiGet<K extends readonly (keyof GlobalPrefsJson)[]>(
keys: K,
): Promise<{ [P in keyof K]: [K[P], GlobalPrefsJson[K[P]]] }>;
export type MultiGet = typeof multiGet;
export function multiSet(keyValues: [string, unknown][]): void;
export function multiSet<K extends keyof GlobalPrefsJson>(
keyValues: Array<[K, GlobalPrefsJson[K]]>,
): void;
export type MultiSet = typeof multiSet;
export function multiRemove(keys: string[]): void;
export function multiRemove(keys: (keyof GlobalPrefsJson)[]): void;
export type MultiRemove = typeof multiRemove;

View File

@@ -2,12 +2,13 @@
import * as fs from 'fs';
import { join } from 'path';
import { GlobalPrefsJson } from '../../../types/prefs';
import * as lootFs from '../fs';
import * as T from '.';
const getStorePath = () => join(lootFs.getDataDir(), 'global-store.json');
let store;
let store: GlobalPrefsJson;
let persisted = true;
export const init: T.Init = function ({ persist = true } = {}) {
@@ -55,15 +56,17 @@ export const removeItem: T.RemoveItem = function (key) {
return _saveStore();
};
export const multiGet: T.MultiGet = function (keys) {
export async function multiGet<K extends readonly (keyof GlobalPrefsJson)[]>(
keys: K,
) {
return new Promise(function (resolve) {
return resolve(
keys.map(function (key) {
return [key, store[key]];
}),
}) as { [P in keyof K]: [K[P], GlobalPrefsJson[K[P]]] },
);
});
};
}
export const multiSet: T.MultiSet = function (keyValues) {
keyValues.forEach(function ([key, value]) {

View File

@@ -1,7 +1,9 @@
// @ts-strict-ignore
import { GlobalPrefsJson } from '../../../types/prefs';
import * as T from '.';
const store = {};
const store: GlobalPrefsJson = {};
export const init: T.Init = function () {};
@@ -19,15 +21,17 @@ export const removeItem: T.RemoveItem = function (key) {
delete store[key];
};
export const multiGet: T.MultiGet = function (keys) {
export async function multiGet<K extends readonly (keyof GlobalPrefsJson)[]>(
keys: K,
) {
return new Promise(function (resolve) {
return resolve(
keys.map(function (key) {
return [key, store[key]];
}),
}) as { [P in keyof K]: [K[P], GlobalPrefsJson[K[P]]] },
);
});
};
}
export const multiSet: T.MultiSet = function (keyValues) {
keyValues.forEach(function ([key, value]) {

View File

@@ -1,4 +1,5 @@
// @ts-strict-ignore
import { GlobalPrefsJson } from '../../../types/prefs';
import { getDatabase } from '../indexeddb';
import * as T from '.';
@@ -53,7 +54,9 @@ export const removeItem: T.RemoveItem = async function (key) {
});
};
export const multiGet: T.MultiGet = async function (keys) {
export async function multiGet<K extends readonly (keyof GlobalPrefsJson)[]>(
keys: K,
) {
const db = await getDatabase();
const transaction = db.transaction(['asyncStorage'], 'readonly');
@@ -71,7 +74,7 @@ export const multiGet: T.MultiGet = async function (keys) {
commit(transaction);
return promise;
};
}
export const multiSet: T.MultiSet = async function (keyValues) {
const db = await getDatabase();

View File

@@ -1105,7 +1105,7 @@ handlers['accounts-bank-sync'] = async function ({ ids = [] }) {
const [[, userId], [, userKey]] = await asyncStorage.multiGet([
'user-id',
'user-key',
]);
] as const);
const accounts = await db.runQuery<
db.DbAccount & { bankId: db.DbBank['bank_id'] }
@@ -1403,7 +1403,7 @@ handlers['load-global-prefs'] = async function () {
'theme',
'preferred-dark-theme',
'server-self-signed-cert',
]);
] as const);
return {
floatingSidebar: floatingSidebar === 'true' ? true : false,
maxMonths: stringToInteger(maxMonths || ''),

View File

@@ -77,6 +77,8 @@ export type LocalPrefs = Partial<{
export type Theme = 'light' | 'dark' | 'auto' | 'midnight' | 'development';
export type DarkTheme = 'dark' | 'midnight';
// GlobalPrefs are the parsed global-store.json values
export type GlobalPrefs = Partial<{
floatingSidebar: boolean;
maxMonths: number;
@@ -88,4 +90,24 @@ export type GlobalPrefs = Partial<{
serverSelfSignedCert: string; // Electron only
}>;
// GlobalPrefsJson represents what's saved in the global-store.json file
export type GlobalPrefsJson = Partial<{
'user-id'?: string;
'user-key'?: string;
'encrypt-keys'?: string;
lastBudget?: string;
readOnly?: string;
'server-url'?: string;
'did-bootstrap'?: boolean;
'user-token'?: string;
'floating-sidebar'?: string; // "true" or "false"
'max-months'?: string; // e.g. "2" or "3"
'document-dir'?: GlobalPrefs['documentDir'];
'encrypt-key'?: string;
language?: GlobalPrefs['language'];
theme?: GlobalPrefs['theme'];
'preferred-dark-theme'?: GlobalPrefs['preferredDarkTheme'];
'server-self-signed-cert'?: GlobalPrefs['serverSelfSignedCert'];
}>;
export type AuthMethods = 'password' | 'openid';

View File

@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [MikesGlitch]
---
Adding typescript type for the global-store.json setting file