reZach / secure-electron-store

A secure electron-store that uses ipcMain/ipcRenderer.
MIT License
51 stars 2 forks source link

TypeScript support #8

Open stijndcl opened 2 years ago

stijndcl commented 2 years ago

Hi, are there any plans to type this library? I've been using it in my Electron apps lately but it bugs me a bit that I can't really get any type hints/type checking anywhere. In some places it's forcing me to add a // @ts-ignore which is a bit annoying if you have to do it frequently (and it's bad practice generally).

The biggest issue for me is store.preloadBindings(). When using the contextBridge in a preload script, this adds an api-property to the window which TypeScript doesn't recognize. I can extend it with my own bindings using a global.ts file:

export {}

declare global {
    // Add the ContextBridge API interface
    interface Window {
        "api": {
            send: (channel: "toMain", ...arg: any) => void;
            receive: (channel: "fromMain" | "someOtherChannelName", func: (event: any, ...arg: any) => void) => void;
        }
    }
}

however, I can't add the types for the store-bindings myself that easily as it would take me a little while to go through the code and figure out what exactly that function returns. This is an example of every single reference needing a // @ts-ignore like I mentioned earlier. Also, I feel like I shouldn't really have to add global type definitions for an external library that I'm using.

t1nky commented 2 years ago

This should cover typings

/// <reference types="node" />
import crypto from 'crypto';
import { BrowserWindow, IpcMain, IpcRenderer } from 'electron';
export declare const readConfigRequest = "ReadConfig-Request";
export declare const readConfigResponse = "ReadConfig-Response";
export declare const readUnprotectedConfigRequest = "ReadUnprotectedConfig-Request";
export declare const readUnprotectedConfigResponse = "ReadUnprotectedConfig-Response";
export declare const writeConfigRequest = "WriteConfig-Request";
export declare const writeConfigResponse = "WriteConfig-Response";
export declare const writeUnprotectedConfigRequest = "WriteUnprotectedConfig-Request";
export declare const writeUnprotectedConfigResponse = "WriteUnprotectedConfig-Response";
export declare const deleteConfigRequest = "DeleteConfig-Request";
export declare const deleteConfigResponse = "DeleteConfig-Response";
export declare const deleteUnprotectedConfigRequest = "DeleteUnprotectedConfig-Request";
export declare const deleteUnprotectedConfigResponse = "DeleteUnprotectedConfig-Response";
export declare const savePasskeyRequest = "SavePasskey-Request";
export declare const savePasskeyResponse = "SavePasskey-Response";
export declare const useConfigInMainRequest = "UseConfigInMain-Request";
export declare const useConfigInMainResponse = "UseConfigInMain-Response";
export declare const useUnprotectedConfigInMainRequest = "UseUnprotectedConfigInMain-Request";
export declare const useUnprotectedConfigInMainResponse = "UseUnprotectedConfigInMain-Response";
export interface IStoreOptions {
    debug: boolean;
    minify: boolean;
    encrypt: boolean;
    passkey: string;
    path: string;
    unprotectedPath: string;
    filename: string;
    unprotectedFilename: string;
    extension: string;
    reset: boolean
}
export default class Store {
    options: IStoreOptions;
    fileData?: any;
    initialFileData?: any;
    initialFileDataParsed: boolean;
    unprotectedFileData?: any;
    initialUnprotectedFileData?: any;
    initialUnprotectedFileDataParsed: boolean;
    iv?: crypto.BinaryLike;
    mainLog: string;
    rendererLog: string;
    ivFile: string;
    validSendChannels: string[];
    validReceiveChannels: string[];
    constructor(options: IStoreOptions);
    getIv(): true | undefined;
    preloadBindings(ipcRenderer: IpcRenderer): {
        path: string;
        unprotectedPath: string;
        setPasskey: (passkey: string) => void;
        initial: () => any;
        initialUnprotected: () => any;
        send: (channel: string, key: string, value: any) => void;
        onReceive: (channel: string, func: (...args: any[]) => void) => void;
        clearRendererBindings: () => void;
    };
    resetFiles(path: string): void;
    resetUnprotectedFiles(unprotectedPath: string): void;
    writeToFile(path: string, browserWindow: BrowserWindow, minify: boolean, encrypt: boolean, args: any): void;
    mainBindings(ipcMain: IpcMain, browserWindow: BrowserWindow, mainProcessCallback?: undefined | ((success: boolean, data: any) => void), unprotectedMainProcessCallback?: undefined | ((success: boolean, data: any) => void)): void;
    mainInitialStore(): {};
    clearMainBindings(ipcMain: IpcMain): void;
}
meodemsao commented 1 year ago

import crypto from 'crypto'; import { BrowserWindow, IpcMain, IpcRenderer } from 'electron'; export declare const readConfigRequest = "ReadConfig-Request"; export declare const readConfigResponse = "ReadConfig-Response"; export declare const readUnprotectedConfigRequest = "ReadUnprotectedConfig-Request"; export declare const readUnprotectedConfigResponse = "ReadUnprotectedConfig-Response"; export declare const writeConfigRequest = "WriteConfig-Request"; export declare const writeConfigResponse = "WriteConfig-Response"; export declare const writeUnprotectedConfigRequest = "WriteUnprotectedConfig-Request"; export declare const writeUnprotectedConfigResponse = "WriteUnprotectedConfig-Response"; export declare const deleteConfigRequest = "DeleteConfig-Request"; export declare const deleteConfigResponse = "DeleteConfig-Response"; export declare const deleteUnprotectedConfigRequest = "DeleteUnprotectedConfig-Request"; export declare const deleteUnprotectedConfigResponse = "DeleteUnprotectedConfig-Response"; export declare const savePasskeyRequest = "SavePasskey-Request"; export declare const savePasskeyResponse = "SavePasskey-Response"; export declare const useConfigInMainRequest = "UseConfigInMain-Request"; export declare const useConfigInMainResponse = "UseConfigInMain-Response"; export declare const useUnprotectedConfigInMainRequest = "UseUnprotectedConfigInMain-Request"; export declare const useUnprotectedConfigInMainResponse = "UseUnprotectedConfigInMain-Response"; export interface IStoreOptions { debug: boolean; minify: boolean; encrypt: boolean; passkey: string; path: string; unprotectedPath: string; filename: string; unprotectedFilename: string; extension: string; reset: boolean } export default class Store { options: IStoreOptions; fileData?: any; initialFileData?: any; initialFileDataParsed: boolean; unprotectedFileData?: any; initialUnprotectedFileData?: any; initialUnprotectedFileDataParsed: boolean; iv?: crypto.BinaryLike; mainLog: string; rendererLog: string; ivFile: string; validSendChannels: string[]; validReceiveChannels: string[]; constructor(options: IStoreOptions); getIv(): true | undefined; preloadBindings(ipcRenderer: IpcRenderer): { path: string; unprotectedPath: string; setPasskey: (passkey: string) => void; initial: () => any; initialUnprotected: () => any; send: (channel: string, key: string, value: any) => void; onReceive: (channel: string, func: (...args: any[]) => void) => void; clearRendererBindings: () => void; }; resetFiles(path: string): void; resetUnprotectedFiles(unprotectedPath: string): void; writeToFile(path: string, browserWindow: BrowserWindow, minify: boolean, encrypt: boolean, args: any): void; mainBindings(ipcMain: IpcMain, browserWindow: BrowserWindow, mainProcessCallback?: undefined | ((success: boolean, data: any) => void), unprotectedMainProcessCallback?: undefined | ((success: boolean, data: any) => void)): void; mainInitialStore(): {}; clearMainBindings(ipcMain: IpcMain): void; }

where i can add this types to use this. I try add to src/types/storage.d.ts and also add "typeRoots": ["./node_modules/@types", "./src/types"] to tsconfig.json but seem not work