All files / src/lib/helpers appSettings.ts

87.8% Statements 36/41
100% Branches 9/9
70.58% Functions 12/17
90.32% Lines 28/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 868x 8x           8x       8x   8x 8x   8x 7x 1x     8x     8x 4x         2x     2x 1x     1x         8x       6x 8x           8x 5x         8x           8x               8x       2x 2x 2x 2x          
import settings from "electron-settings";
import { promiseRetry } from "shared/lib/helpers/promise";
 
type SettingsValue = Parameters<typeof settings.set>[1];
 
// Set electron-settings filename to
// match previous releases
settings.configure({
  fileName: "Settings",
});
 
let settingsMutationQueue: Promise<void> = Promise.resolve();
 
const queueSettingsMutation = <T>(operation: () => Promise<T>): Promise<T> => {
  const result = settingsMutationQueue.then(operation, operation);
 
  settingsMutationQueue = result.then(
    () => undefined,
    () => undefined,
  );
 
  return result;
};
 
const isTransientFilesystemError = (error: unknown): boolean => {
  if (
    !(error instanceof Error) ||
    !("code" in error) ||
    typeof error.code !== "string"
  ) {
    return false;
  }
 
  if (["EBUSY", "EMFILE", "ENFILE"].includes(error.code)) {
    return true;
  }
 
  return (
    process.platform === "win32" && ["EACCES", "EPERM"].includes(error.code)
  );
};
 
export const settingsSet = async (
  key: string,
  value: SettingsValue,
): Promise<void> =>
  queueSettingsMutation(() =>
    promiseRetry(() => settings.set(key, value), {
      retries: 5,
      shouldRetry: isTransientFilesystemError,
    }),
  );
 
export const settingsGet = (key: string) =>
  promiseRetry(() => settings.get(key), {
    retries: 5,
    shouldRetry: isTransientFilesystemError,
  });
 
export const settingsGetAll = () =>
  promiseRetry(() => settings.get(), {
    retries: 5,
    shouldRetry: isTransientFilesystemError,
  });
 
export const settingsUnset = async (key: string): Promise<void> =>
  queueSettingsMutation(() =>
    promiseRetry(() => settings.unset(key), {
      retries: 5,
      shouldRetry: isTransientFilesystemError,
    }),
  );
 
export const settingsUpdate = async (
  key: string,
  update: (currentValue: unknown) => SettingsValue,
): Promise<void> =>
  queueSettingsMutation(async () => {
    const currentValue = await settingsGet(key);
    const nextValue = update(currentValue);
    await promiseRetry(() => settings.set(key, nextValue), {
      retries: 5,
      shouldRetry: isTransientFilesystemError,
    });
  });