import * as Context from "effect/Context";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Schema from "effect/Schema"; import * as Electron from "electron";import { HostProcessPlatform } from "@t3tools/shared/hostProcess"; const electronSafeStorageErrorFields = { cause: Schema.Defect(),}; export class ElectronSafeStorageAvailabilityError extends Schema.TaggedErrorClass<ElectronSafeStorageAvailabilityError>()( "ElectronSafeStorageAvailabilityError", { ...electronSafeStorageErrorFields, },) { override get message(): string { return "Electron safe storage failed to check encryption availability."; }} export class ElectronSafeStorageEncryptError extends Schema.TaggedErrorClass<ElectronSafeStorageEncryptError>()( "ElectronSafeStorageEncryptError", { ...electronSafeStorageErrorFields, },) { override get message(): string { return "Electron safe storage failed to encrypt a string."; }} export class ElectronSafeStorageDecryptError extends Schema.TaggedErrorClass<ElectronSafeStorageDecryptError>()( "ElectronSafeStorageDecryptError", { ...electronSafeStorageErrorFields, },) { override get message(): string { return "Electron safe storage failed to decrypt a string."; }} export const ElectronSafeStorageError = Schema.Union([ ElectronSafeStorageAvailabilityError, ElectronSafeStorageEncryptError, ElectronSafeStorageDecryptError,]);export type ElectronSafeStorageError = typeof ElectronSafeStorageError.Type;export const isElectronSafeStorageError = Schema.is(ElectronSafeStorageError); export class ElectronSafeStorage extends Context.Service< ElectronSafeStorage, { readonly isEncryptionAvailable: Effect.Effect<boolean, ElectronSafeStorageAvailabilityError>; readonly encryptString: ( value: string, ) => Effect.Effect<Uint8Array, ElectronSafeStorageEncryptError>; readonly decryptString: ( value: Uint8Array, ) => Effect.Effect<string, ElectronSafeStorageDecryptError>; readonly selectedStorageBackend: Effect.Effect<Option.Option<string>>; }>()("@t3tools/desktop/electron/ElectronSafeStorage") {} export const make = Effect.gen(function* () { const platform = yield* HostProcessPlatform; return ElectronSafeStorage.of({ isEncryptionAvailable: Effect.try({ try: () => Electron.safeStorage.isEncryptionAvailable(), catch: (cause) => new ElectronSafeStorageAvailabilityError({ cause }), }), encryptString: (value) => Effect.try({ try: () => Electron.safeStorage.encryptString(value), catch: (cause) => new ElectronSafeStorageEncryptError({ cause }), }), decryptString: (value) => Effect.try({ try: () => Electron.safeStorage.decryptString(Buffer.from(value)), catch: (cause) => new ElectronSafeStorageDecryptError({ cause }), }), selectedStorageBackend: Effect.sync(() => { if (platform !== "linux") { return Option.none(); } try { return Option.fromNullishOr(Electron.safeStorage.getSelectedStorageBackend()); } catch { return Option.none(); } }), });}); export const layer = Layer.effect(ElectronSafeStorage, make);
import * as Context from "effect/Context";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Schema from "effect/Schema";
import * as Electron from "electron";
import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
const electronSafeStorageErrorFields = {
cause: Schema.Defect(),
};
export class ElectronSafeStorageAvailabilityError extends Schema.TaggedErrorClass<ElectronSafeStorageAvailabilityError>()(
"ElectronSafeStorageAvailabilityError",
{
...electronSafeStorageErrorFields,
},
) {
override get message(): string {
return "Electron safe storage failed to check encryption availability.";
}
}
export class ElectronSafeStorageEncryptError extends Schema.TaggedErrorClass<ElectronSafeStorageEncryptError>()(
"ElectronSafeStorageEncryptError",
{
...electronSafeStorageErrorFields,
},
) {
override get message(): string {
return "Electron safe storage failed to encrypt a string.";
}
}
export class ElectronSafeStorageDecryptError extends Schema.TaggedErrorClass<ElectronSafeStorageDecryptError>()(
"ElectronSafeStorageDecryptError",
{
...electronSafeStorageErrorFields,
},
) {
override get message(): string {
return "Electron safe storage failed to decrypt a string.";
}
}
export const ElectronSafeStorageError = Schema.Union([
ElectronSafeStorageAvailabilityError,
ElectronSafeStorageEncryptError,
ElectronSafeStorageDecryptError,
]);
export type ElectronSafeStorageError = typeof ElectronSafeStorageError.Type;
export const isElectronSafeStorageError = Schema.is(ElectronSafeStorageError);
export class ElectronSafeStorage extends Context.Service<
ElectronSafeStorage,
{
readonly isEncryptionAvailable: Effect.Effect<boolean, ElectronSafeStorageAvailabilityError>;
readonly encryptString: (
value: string,
) => Effect.Effect<Uint8Array, ElectronSafeStorageEncryptError>;
readonly decryptString: (
value: Uint8Array,
) => Effect.Effect<string, ElectronSafeStorageDecryptError>;
readonly selectedStorageBackend: Effect.Effect<Option.Option<string>>;
}
>()("@t3tools/desktop/electron/ElectronSafeStorage") {}
export const make = Effect.gen(function* () {
const platform = yield* HostProcessPlatform;
return ElectronSafeStorage.of({
isEncryptionAvailable: Effect.try({
try: () => Electron.safeStorage.isEncryptionAvailable(),
catch: (cause) => new ElectronSafeStorageAvailabilityError({ cause }),
}),
encryptString: (value) =>
Effect.try({
try: () => Electron.safeStorage.encryptString(value),
catch: (cause) => new ElectronSafeStorageEncryptError({ cause }),
}),
decryptString: (value) =>
Effect.try({
try: () => Electron.safeStorage.decryptString(Buffer.from(value)),
catch: (cause) => new ElectronSafeStorageDecryptError({ cause }),
}),
selectedStorageBackend: Effect.sync(() => {
if (platform !== "linux") {
return Option.none();
}
try {
return Option.fromNullishOr(Electron.safeStorage.getSelectedStorageBackend());
} catch {
return Option.none();
}
}),
});
});
export const layer = Layer.effect(ElectronSafeStorage, make);