From 881a6cd6d8fa502a613a3879cb6dc54cb1055a21 Mon Sep 17 00:00:00 2001 From: Jonathan Yeboah <10155597+JonYeb@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:14:25 +0200 Subject: [PATCH 1/5] context providers and some setup for indexedDbs --- .eslintrc.json | 3 +- .prettierignore | 6 +++ .prettierrc | 13 +++++ package-lock.json | 33 +++++++++++- package.json | 2 + src/app.tsx | 18 ++++--- src/constants.ts | 21 ++++++++ src/customHooks/Persistence.tsx | 96 +++++++++++++++++++++++++++++++++ src/login.tsx | 5 ++ yarn.lock | 12 ++++- 10 files changed, 199 insertions(+), 10 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 src/constants.ts create mode 100644 src/customHooks/Persistence.tsx create mode 100644 src/login.tsx diff --git a/.eslintrc.json b/.eslintrc.json index 2d7aa60..4c8c4f9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,7 +10,8 @@ "plugin:@typescript-eslint/recommended", "plugin:import/recommended", "plugin:import/electron", - "plugin:import/typescript" + "plugin:import/typescript", + "prettier" ], "parser": "@typescript-eslint/parser" } diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..fcac576 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +# Ignore artifacts: +build +coverage + +# Ignore all HTML files: +**/*.html \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..12137bf --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "trailingComma": "es5", + "singleQuote": true, + "parser": "typescript", + "overrides": [ + { + "files": "*.json", + "options": { + "parser": "json" + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index b52b7a3..c81acd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vrcass", - "version": "1.0.0", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vrcass", - "version": "1.0.0", + "version": "0.1.0", "license": "MIT", "dependencies": { "electron-squirrel-startup": "^1.0.1", @@ -31,9 +31,11 @@ "css-loader": "^6.0.0", "electron": "32.1.2", "eslint": "^8.0.1", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.25.0", "fork-ts-checker-webpack-plugin": "^7.2.13", "node-loader": "^2.0.0", + "prettier": "^3.3.3", "style-loader": "^3.0.0", "ts-loader": "^9.2.2", "ts-node": "^10.0.0", @@ -4740,6 +4742,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -9110,6 +9124,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", diff --git a/package.json b/package.json index d6eb67a..c2a0fd0 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,11 @@ "css-loader": "^6.0.0", "electron": "32.1.2", "eslint": "^8.0.1", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.25.0", "fork-ts-checker-webpack-plugin": "^7.2.13", "node-loader": "^2.0.0", + "prettier": "^3.3.3", "style-loader": "^3.0.0", "ts-loader": "^9.2.2", "ts-node": "^10.0.0", diff --git a/src/app.tsx b/src/app.tsx index bd785c5..1e204fc 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,20 +1,26 @@ -import React from "react"; +import React from 'react'; +import { Persistence, usePersistence } from './customHooks/Persistence'; import { createRoot } from 'react-dom/client'; - function App() { + const { ready } = usePersistence(); return (
-

💖 Hello World!

-

Welcome to your Electron application.

+ + {ready && ( + <> +

💖 Hello World!

+

Welcome to your Electron application.

+ + )} +
); } - const root = createRoot(document.getElementById('root')); root.render( -); \ No newline at end of file +); diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..2b5ebae --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,21 @@ +export const CLIENT_API_KEY = 'JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26'; + +export const API_BASE_URL = 'https:/vrchat.com/api/1'; + +export const HEADERS = { + headers: { + 'User-Agent': 'VRC-ASS/0.1.0 onetime.jon.yeb@outlook.de', + }, +}; +/* +* { + "requiresTwoFactorAuth": [ + "emailOtp" + ] +} +* +* { + "verified": true +} +* in set cookie twoFactorAuth +* */ diff --git a/src/customHooks/Persistence.tsx b/src/customHooks/Persistence.tsx new file mode 100644 index 0000000..9ecfab9 --- /dev/null +++ b/src/customHooks/Persistence.tsx @@ -0,0 +1,96 @@ +import React, { createContext, FC, useContext, useMemo, useState } from 'react'; + +type PersistenceContext = { + ready: boolean; + db: IDBDatabase; + setItem: (item: Record) => void; +}; + +const PersistenceContext = createContext({ + db: undefined, + ready: false, + setItem(item: Record): void { + console.log(item); + }, +}); + +export const Persistence: FC = ({ children }) => { + const [isPersistence, setIsPersistence] = useState(false); + const [ready, setReady] = useState(false); + const [db, setDb] = useState(); + + const value = useMemo(() => { + function setPersistence() { + if (navigator.storage && navigator.storage.persist) { + navigator.storage.persisted().then((isPersistent) => { + if (!isPersistent) { + navigator.storage.persist().then((persistent) => { + setIsPersistence(persistent); + if (persistent) { + console.log( + 'Storage will not be cleared except by explicit user action' + ); + } else { + console.log( + 'Storage may be cleared by the UA under storage pressure.' + ); + } + }); + } + }); + } + } + setPersistence(); + + const request = indexedDB.open('VRCASS'); + request.onerror = () => { + console.error("Why didn't you allow my web app to use IndexedDB?!"); + }; + request.onupgradeneeded = () => { + const db = request.result; + setDb(db); + + // Create another object store called "names" with the autoIncrement flag set as true. + db.createObjectStore('auth', { + keyPath: 'username', + }); + + db.createObjectStore('avatars', { + autoIncrement: true, + }); + const objStore = db.createObjectStore('names', { autoIncrement: true }); + const customerData = [ + { + ssn: '444-44-4444', + name: 'Bill', + age: 35, + email: 'bill@company.com', + }, + { ssn: '555-55-5555', name: 'Donna', age: 32, email: 'donna@home.org' }, + ]; + + customerData.forEach((customer) => { + objStore.add(customer); + }); + setReady(true); + }; + + function setItem(item: Record) { + console.log(item); + if (!isPersistence) { + console.warn('no persistence'); + return; + } + } + + return { setItem, db, ready }; + }, []); + + return ( + + {children} + + ); +}; + +export const usePersistence = () => useContext(PersistenceContext); diff --git a/src/login.tsx b/src/login.tsx new file mode 100644 index 0000000..277e3ac --- /dev/null +++ b/src/login.tsx @@ -0,0 +1,5 @@ +function Login() { + return
; +} + +export default Login; diff --git a/yarn.lock b/yarn.lock index 31fc996..bf51e93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2454,6 +2454,11 @@ escape-string-regexp@^4.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + eslint-import-resolver-node@^0.3.9: version "0.3.9" resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz" @@ -2515,7 +2520,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@^8.0.1: +eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@^8.0.1, eslint@>=7.0.0: version "8.57.1" resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== @@ -4838,6 +4843,11 @@ prelude-ls@^1.2.1: resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prettier@^3.3.3: + version "3.3.3" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" From 9dbd17fdeec3a7de710ddd2cee45aeafbe5d5ed0 Mon Sep 17 00:00:00 2001 From: Jonathan Yeboah <10155597+JonYeb@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:26:52 +0200 Subject: [PATCH 2/5] added ipc and a simple world fetch --- src/_mainProcess/api/index.ts | 1 + src/_mainProcess/api/request.ts | 37 +++++++++++++++++++++++ src/_mainProcess/requests/getWorldById.ts | 11 +++++++ src/app.tsx | 13 +++----- src/constants.ts | 13 +++++--- src/customHooks/Persistence.tsx | 6 ++++ src/index.ts | 17 ++++++++--- src/preload.ts | 16 ++++++++-- src/renderer.ts | 24 +-------------- src/testFetchWorld.tsx | 12 ++++++++ src/types.ts | 1 + 11 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 src/_mainProcess/api/index.ts create mode 100644 src/_mainProcess/api/request.ts create mode 100644 src/_mainProcess/requests/getWorldById.ts create mode 100644 src/testFetchWorld.tsx create mode 100644 src/types.ts diff --git a/src/_mainProcess/api/index.ts b/src/_mainProcess/api/index.ts new file mode 100644 index 0000000..7f43cae --- /dev/null +++ b/src/_mainProcess/api/index.ts @@ -0,0 +1 @@ +export { makeRequest } from './request'; diff --git a/src/_mainProcess/api/request.ts b/src/_mainProcess/api/request.ts new file mode 100644 index 0000000..0d25c7b --- /dev/null +++ b/src/_mainProcess/api/request.ts @@ -0,0 +1,37 @@ +import { DEFAULT_HEADER } from '../../constants'; + +export const makeRequest = async ( + url: string, + method?: 'GET' | 'POST', + data?: T +) => { + const headers: Headers = new Headers({ + ...DEFAULT_HEADER, + // ...requestHeader, + }); + + const requestData: RequestInit = { + method: method ?? 'GET', + // mode: 'cors', + cache: 'no-cache', + credentials: 'same-origin', + redirect: 'follow', + referrerPolicy: 'no-referrer', + headers: headers, + }; + + if (data) { + requestData.body = JSON.stringify(data); + } + + return fetch(url, requestData) + .then((response) => { + console.log(response); + return response.json(); + }) + .then((responseData) => { + console.log(responseData); + return responseData as ResponseType; + }) + .catch((error) => console.warn(error)); +}; diff --git a/src/_mainProcess/requests/getWorldById.ts b/src/_mainProcess/requests/getWorldById.ts new file mode 100644 index 0000000..a2f5278 --- /dev/null +++ b/src/_mainProcess/requests/getWorldById.ts @@ -0,0 +1,11 @@ +import { makeRequest } from '../api'; +import { API_BASE_URL } from '../../constants'; + +export const getWorldById = async (worldId: string) => { + const url = `${API_BASE_URL}/worlds/${worldId}`; + try { + return await makeRequest(url, 'GET'); + } catch (error) { + return false; + } +}; diff --git a/src/app.tsx b/src/app.tsx index 1e204fc..6bac319 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,18 +1,15 @@ import React from 'react'; -import { Persistence, usePersistence } from './customHooks/Persistence'; +import { Persistence } from './customHooks/Persistence'; import { createRoot } from 'react-dom/client'; +import TestFetchWorld from './testFetchWorld'; function App() { - const { ready } = usePersistence(); return (
- {ready && ( - <> -

💖 Hello World!

-

Welcome to your Electron application.

- - )} +

💖 Hello World!

+

Welcome to your Electron application.

+
); diff --git a/src/constants.ts b/src/constants.ts index 2b5ebae..f1fd019 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,11 +1,14 @@ +import { RequestHeader } from './types'; + export const CLIENT_API_KEY = 'JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26'; -export const API_BASE_URL = 'https:/vrchat.com/api/1'; +export const BASE_URL = 'https:/vrchat.com'; +export const API_BASE_URL = `${BASE_URL}/api/1`; -export const HEADERS = { - headers: { - 'User-Agent': 'VRC-ASS/0.1.0 onetime.jon.yeb@outlook.de', - }, +export const DEFAULT_HEADER: RequestHeader = { + 'User-Agent': 'VRC-ASS/0.1.0 onetime.jon.yeb@outlook.de', + // 'connect-src': `${BASE_URL}*`, + // 'Access-Control-Allow-Origin': BASE_URL, }; /* * { diff --git a/src/customHooks/Persistence.tsx b/src/customHooks/Persistence.tsx index 9ecfab9..e57c4bc 100644 --- a/src/customHooks/Persistence.tsx +++ b/src/customHooks/Persistence.tsx @@ -21,6 +21,7 @@ export const Persistence: FC = ({ children }) => { const value = useMemo(() => { function setPersistence() { + console.log('setting it'); if (navigator.storage && navigator.storage.persist) { navigator.storage.persisted().then((isPersistent) => { if (!isPersistent) { @@ -46,7 +47,12 @@ export const Persistence: FC = ({ children }) => { request.onerror = () => { console.error("Why didn't you allow my web app to use IndexedDB?!"); }; + request.onsuccess = () => { + console.log('success'); + setReady(true); + }; request.onupgradeneeded = () => { + console.log('upgrade'); const db = request.result; setDb(db); diff --git a/src/index.ts b/src/index.ts index cc73fcb..fcd6355 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ -import { app, BrowserWindow } from 'electron'; +import { app, BrowserWindow, ipcMain } from 'electron'; +import { getWorldById } from './_mainProcess/requests/getWorldById'; // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on // whether you're running in development or production). @@ -13,8 +14,8 @@ if (require('electron-squirrel-startup')) { const createWindow = (): void => { // Create the browser window. const mainWindow = new BrowserWindow({ - height: 600, - width: 800, + height: 1024, + width: 960, webPreferences: { preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, }, @@ -30,7 +31,15 @@ const createWindow = (): void => { // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. -app.on('ready', createWindow); +app.on('ready', () => { + createWindow(); + ipcMain.handle('getWorldById', async (event, worldId: string) => { + const t = await getWorldById(worldId); + console.log(`${t}`); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return t!; + }); +}); // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits diff --git a/src/preload.ts b/src/preload.ts index 5e9d369..5b7a1b1 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -1,2 +1,14 @@ -// See the Electron documentation for details on how to use preload scripts: -// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts +declare global { + interface Window { + //eslint-disable-next-line @typescript-eslint/no-explicit-any + electronAPI: any; + } +} + +import { contextBridge, ipcRenderer } from 'electron'; + +contextBridge.exposeInMainWorld('electronAPI', { + getWorldById: async (worldId: string) => { + return await ipcRenderer.invoke('getWorldById', worldId); + }, +}); diff --git a/src/renderer.ts b/src/renderer.ts index d47e79a..f8b6831 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -4,29 +4,7 @@ * Electron, visit: * * https://electronjs.org/docs/latest/tutorial/process-model - * - * By default, Node.js integration in this file is disabled. When enabling Node.js integration - * in a renderer process, please be aware of potential security implications. You can read - * more about security risks here: - * - * https://electronjs.org/docs/tutorial/security - * - * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration` - * flag: - * - * ``` - * // Create the browser window. - * mainWindow = new BrowserWindow({ - * width: 800, - * height: 600, - * webPreferences: { - * nodeIntegration: true - * } - * }); - * ``` */ import './index.css'; -import './app' - -console.log('👋 This message is being logged by "renderer.js", included via webpack'); +import './app'; diff --git a/src/testFetchWorld.tsx b/src/testFetchWorld.tsx new file mode 100644 index 0000000..b645abd --- /dev/null +++ b/src/testFetchWorld.tsx @@ -0,0 +1,12 @@ +const TestFetchWorld = () => { + const btn = () => { + window.electronAPI + .getWorldById('wrld_5d8ce471-aae3-4f2b-8d15-3567c3a7075a') + .then((result: never) => { + console.log(result); + }); + }; + return ; +}; + +export default TestFetchWorld; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..1232a45 --- /dev/null +++ b/src/types.ts @@ -0,0 +1 @@ +export type RequestHeader = { [key: string]: string }; From ed562501590162bfec1e8c362ce315f624d73b1c Mon Sep 17 00:00:00 2001 From: Jonathan Yeboah <10155597+JonYeb@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:44:55 +0200 Subject: [PATCH 3/5] trying to set/get from indexedDB --- README.md | 1 + forge.config.ts | 10 +- package-lock.json | 185 +++++++++++++++++- package.json | 1 + src/_mainProcess/helpers/persistence.ts | 58 ++++++ src/app.tsx | 5 +- .../atoms/FetchWorldButton.tsx} | 4 +- src/components/atoms/SetAndRetriveAuth.tsx | 43 ++++ src/customHooks/Persistence.tsx | 49 ++++- yarn.lock | 96 ++++++++- 10 files changed, 436 insertions(+), 16 deletions(-) create mode 100644 src/_mainProcess/helpers/persistence.ts rename src/{testFetchWorld.tsx => components/atoms/FetchWorldButton.tsx} (78%) create mode 100644 src/components/atoms/SetAndRetriveAuth.tsx diff --git a/README.md b/README.md index 9a0a5a2..259cda9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +![audit](https://github.com/JonYeb/VRCASS/actions/workflows/codeql.yml/badge.svg) # VRC Avatar Saver and Switcher ## About diff --git a/forge.config.ts b/forge.config.ts index 1dcc889..1d28cca 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -16,11 +16,19 @@ const config: ForgeConfig = { asar: true, }, rebuildConfig: {}, - makers: [new MakerSquirrel({}), new MakerZIP({}, ['darwin']), new MakerRpm({}), new MakerDeb({})], + makers: [ + new MakerSquirrel({}), + new MakerZIP({}, ['darwin']), + new MakerRpm({}), + new MakerDeb({}), + ], plugins: [ new AutoUnpackNativesPlugin({}), new WebpackPlugin({ mainConfig, + //@todo remove maybe + devContentSecurityPolicy: + "default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;", renderer: { config: rendererConfig, entryPoints: [ diff --git a/package-lock.json b/package-lock.json index c81acd0..80b755b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "electron-squirrel-startup": "^1.0.1", + "electron-store": "^10.0.0", "react": "^18.3.1", "react-dom": "^18.3.1" }, @@ -2483,6 +2484,15 @@ "node": ">= 4.0.0" } }, + "node_modules/atomically": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-2.0.3.tgz", + "integrity": "sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==", + "dependencies": { + "stubborn-fs": "^1.2.5", + "when-exit": "^2.1.1" + } + }, "node_modules/author-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", @@ -3310,6 +3320,75 @@ "dev": true, "license": "MIT" }, + "node_modules/conf": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/conf/-/conf-13.0.1.tgz", + "integrity": "sha512-l9Uwc9eOnz39oADzGO2cSBDi7siv8lwO+31ocQ2nOJijnDiW3pxqm9VV10DPYUO28wW83DjABoUqY1nfHRR2hQ==", + "dependencies": { + "ajv": "^8.16.0", + "ajv-formats": "^3.0.1", + "atomically": "^2.0.3", + "debounce-fn": "^6.0.0", + "dot-prop": "^9.0.0", + "env-paths": "^3.0.0", + "json-schema-typed": "^8.0.1", + "semver": "^7.6.2", + "uint8array-extras": "^1.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/conf/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/conf/node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -3593,6 +3672,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/debounce-fn": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-6.0.0.tgz", + "integrity": "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -3984,6 +4077,31 @@ "tslib": "^2.0.3" } }, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", + "dependencies": { + "type-fest": "^4.18.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4247,6 +4365,32 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/electron-store": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-10.0.0.tgz", + "integrity": "sha512-BU/QZh+5twHBprRdLu3YZX/rIarmZzhTNpJvAvqG1/yN0mNCrsMh0kl7bM4xaUKDNRiHz1r7wP/7Prjh7cleIw==", + "dependencies": { + "conf": "^13.0.0", + "type-fest": "^4.20.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-store/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.27", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz", @@ -5279,7 +5423,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -5317,7 +5460,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true, "license": "MIT" }, "node_modules/fastq": { @@ -7184,6 +7326,11 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-typed": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.1.tgz", + "integrity": "sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==" + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -7868,6 +8015,17 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -9578,7 +9736,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9906,7 +10063,6 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10619,6 +10775,11 @@ "node": ">=0.10.0" } }, + "node_modules/stubborn-fs": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", + "integrity": "sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==" + }, "node_modules/style-loader": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", @@ -11160,6 +11321,17 @@ "node": ">=4.2.0" } }, + "node_modules/uint8array-extras": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz", + "integrity": "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -11693,6 +11865,11 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/when-exit": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.3.tgz", + "integrity": "sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw==" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index c2a0fd0..1c64267 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "license": "MIT", "dependencies": { "electron-squirrel-startup": "^1.0.1", + "electron-store": "^10.0.0", "react": "^18.3.1", "react-dom": "^18.3.1" } diff --git a/src/_mainProcess/helpers/persistence.ts b/src/_mainProcess/helpers/persistence.ts new file mode 100644 index 0000000..99c6766 --- /dev/null +++ b/src/_mainProcess/helpers/persistence.ts @@ -0,0 +1,58 @@ +export class Persistence { + readonly name: string; + private db: IDBDatabase; + private isPersistent: boolean; + private isDbCreated: boolean; + + constructor(name = 'VRCASS') { + this.name = name; + + if (navigator.storage && navigator.storage.persist) { + navigator.storage.persisted().then((isPersistent) => { + if (!isPersistent) { + navigator.storage.persist().then((persistent) => { + this.isPersistent = persistent; + }); + } + }); + } + + const request = indexedDB.open(this.name); + request.onerror = () => { + this.isDbCreated = false; + }; + + request.onupgradeneeded = () => { + console.log('upgrade'); + this.db = request.result; + + this.db.createObjectStore('auth', { + keyPath: 'username', + }); + + this.db.createObjectStore('avatars', { + autoIncrement: true, + }); + + this.isDbCreated = true; + }; + } + + setValue(item: Record, objectStore: string, key?: string) { + const objStore = this.db + .transaction([objectStore], 'readwrite') + .objectStore(objectStore); + objStore.put(item, key); + } + + getValues(query: string, objectStore: string) { + const request = this.db + .transaction(objectStore) + .objectStore(objectStore) + .get(query); + + request.onsuccess = () => { + return request.result; + }; + } +} diff --git a/src/app.tsx b/src/app.tsx index 6bac319..c8a341c 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { Persistence } from './customHooks/Persistence'; import { createRoot } from 'react-dom/client'; -import TestFetchWorld from './testFetchWorld'; +import FetchWorldButton from './components/atoms/FetchWorldButton'; +import SetAndRetrieveAuth from './components/atoms/SetAndRetriveAuth'; function App() { return ( @@ -9,7 +10,7 @@ function App() {

💖 Hello World!

Welcome to your Electron application.

- +
); diff --git a/src/testFetchWorld.tsx b/src/components/atoms/FetchWorldButton.tsx similarity index 78% rename from src/testFetchWorld.tsx rename to src/components/atoms/FetchWorldButton.tsx index b645abd..ffd5a9f 100644 --- a/src/testFetchWorld.tsx +++ b/src/components/atoms/FetchWorldButton.tsx @@ -1,4 +1,4 @@ -const TestFetchWorld = () => { +const FetchWorldButton = () => { const btn = () => { window.electronAPI .getWorldById('wrld_5d8ce471-aae3-4f2b-8d15-3567c3a7075a') @@ -9,4 +9,4 @@ const TestFetchWorld = () => { return ; }; -export default TestFetchWorld; +export default FetchWorldButton; diff --git a/src/components/atoms/SetAndRetriveAuth.tsx b/src/components/atoms/SetAndRetriveAuth.tsx new file mode 100644 index 0000000..0ca472a --- /dev/null +++ b/src/components/atoms/SetAndRetriveAuth.tsx @@ -0,0 +1,43 @@ +import { usePersistence } from '../../customHooks/Persistence'; +import { useEffect, useRef } from 'react'; + +const SetAndRetrieveAuth = () => { + const usernameInput = useRef(null); + const authcookieInput = useRef(null); + const twofactorInput = useRef(null); + //eslint-disable-next-line + let { ready, getValues, setValue } = usePersistence(); + const getValuesForName = () => { + console.log(getValues(usernameInput.current.value, 'auth')); + }; + const setValuesForName = () => { + setValue( + { + username: usernameInput.current.value, + authcookie: authcookieInput.current.value, + twofactor: twofactorInput.current.value, + }, + 'auth' + ); + }; + + return ( +
+ + + + + +
+ ); +}; + +export default SetAndRetrieveAuth; diff --git a/src/customHooks/Persistence.tsx b/src/customHooks/Persistence.tsx index e57c4bc..81e6a68 100644 --- a/src/customHooks/Persistence.tsx +++ b/src/customHooks/Persistence.tsx @@ -1,17 +1,32 @@ -import React, { createContext, FC, useContext, useMemo, useState } from 'react'; +import React, { + createContext, + FC, + useContext, + useEffect, + useMemo, + useState, +} from 'react'; type PersistenceContext = { ready: boolean; db: IDBDatabase; - setItem: (item: Record) => void; + setValue: ( + item: Record, + objectStore: string, + key?: string + ) => void; + getValues: (query: string, objectStore: string) => Record; }; const PersistenceContext = createContext({ db: undefined, ready: false, - setItem(item: Record): void { + setValue(item: Record, objectStore: string): void { console.log(item); }, + getValues(query: string, objectStore: string) { + return { foo: 'bar' }; + }, }); export const Persistence: FC = ({ children }) => { @@ -37,8 +52,12 @@ export const Persistence: FC = ({ children }) => { ); } }); + } else { + console.log('already set?'); } }); + } else { + console.log('cant get it'); } } setPersistence(); @@ -81,15 +100,35 @@ export const Persistence: FC = ({ children }) => { setReady(true); }; - function setItem(item: Record) { + function setValue( + item: Record, + objectStore: string, + key?: string + ) { console.log(item); if (!isPersistence) { console.warn('no persistence'); return; } + const objStore = db + .transaction([objectStore], 'readwrite') + .objectStore(objectStore); + objStore.put(item, key); + } + + async function getValues(query: string, objectStore: string) { + console.log(query, objectStore); + const request = db + .transaction(objectStore) + .objectStore(objectStore) + .get(query); + + request.onsuccess = () => { + return request.result; + }; } - return { setItem, db, ready }; + return { setValue, db, ready, getValues }; }, []); return ( diff --git a/yarn.lock b/yarn.lock index bf51e93..cb71e18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1163,6 +1163,13 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" @@ -1185,7 +1192,7 @@ ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0: +ajv@^8.0.0, ajv@^8.16.0: version "8.17.1" resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -1375,6 +1382,14 @@ at-least-node@^1.0.0: resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +atomically@^2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/atomically/-/atomically-2.0.3.tgz" + integrity sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw== + dependencies: + stubborn-fs "^1.2.5" + when-exit "^2.1.1" + author-regex@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz" @@ -1807,6 +1822,21 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +conf@^13.0.0: + version "13.0.1" + resolved "https://registry.npmjs.org/conf/-/conf-13.0.1.tgz" + integrity sha512-l9Uwc9eOnz39oADzGO2cSBDi7siv8lwO+31ocQ2nOJijnDiW3pxqm9VV10DPYUO28wW83DjABoUqY1nfHRR2hQ== + dependencies: + ajv "^8.16.0" + ajv-formats "^3.0.1" + atomically "^2.0.3" + debounce-fn "^6.0.0" + dot-prop "^9.0.0" + env-paths "^3.0.0" + json-schema-typed "^8.0.1" + semver "^7.6.2" + uint8array-extras "^1.1.0" + connect-history-api-fallback@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz" @@ -1968,6 +1998,13 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" +debounce-fn@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/debounce-fn/-/debounce-fn-6.0.0.tgz" + integrity sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ== + dependencies: + mimic-function "^5.0.0" + debug@^2.2.0: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" @@ -2171,6 +2208,13 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" +dot-prop@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" + integrity sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ== + dependencies: + type-fest "^4.18.2" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" @@ -2232,6 +2276,14 @@ electron-squirrel-startup@^1.0.1: dependencies: debug "^2.2.0" +electron-store@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/electron-store/-/electron-store-10.0.0.tgz" + integrity sha512-BU/QZh+5twHBprRdLu3YZX/rIarmZzhTNpJvAvqG1/yN0mNCrsMh0kl7bM4xaUKDNRiHz1r7wP/7Prjh7cleIw== + dependencies: + conf "^13.0.0" + type-fest "^4.20.0" + electron-to-chromium@^1.5.4: version "1.5.27" resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz" @@ -2316,6 +2368,11 @@ env-paths@^2.2.0: resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +env-paths@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz" + integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A== + err-code@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz" @@ -3829,6 +3886,11 @@ json-schema-traverse@^1.0.0: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema-typed@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.1.tgz" + integrity sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" @@ -4138,6 +4200,11 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" @@ -5270,7 +5337,7 @@ semver@^6.3.1: resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4: +semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4, semver@^7.6.2: version "7.6.3" resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -5672,6 +5739,11 @@ strip-outer@^1.0.1: dependencies: escape-string-regexp "^1.0.2" +stubborn-fs@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz" + integrity sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g== + style-loader@^3.0.0: version "3.3.4" resolved "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz" @@ -5891,6 +5963,16 @@ type-fest@^1.0.2: resolved "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz" integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== +type-fest@^4.18.2: + version "4.26.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz" + integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg== + +type-fest@^4.20.0: + version "4.26.1" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz" + integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" @@ -5948,6 +6030,11 @@ typescript@*, typescript@>=2.7, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0- resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz" integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +uint8array-extras@^1.1.0: + version "1.4.0" + resolved "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.4.0.tgz" + integrity sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" @@ -6192,6 +6279,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +when-exit@^2.1.1: + version "2.1.3" + resolved "https://registry.npmjs.org/when-exit/-/when-exit-2.1.3.tgz" + integrity sha512-uVieSTccFIr/SFQdFWN/fFaQYmV37OKtuaGphMAzi4DmmUlrvRBJW5WSLkHyjNQY/ePJMz3LoiX9R3yy1Su6Hw== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" From 0d62f24ea90baf4cb6ff985d931ddee96fb1ace1 Mon Sep 17 00:00:00 2001 From: Jonathan Yeboah <10155597+JonYeb@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:32:40 +0200 Subject: [PATCH 4/5] set up persistence with electron-store --- .env.sample | 2 + package-lock.json | 12 ++ package.json | 1 + src/_mainProcess/helpers/persistence.ts | 76 +++++------ src/app.tsx | 10 +- src/components/atoms/SetAndRetriveAuth.tsx | 16 ++- src/customHooks/Persistence.tsx | 141 --------------------- src/index.ts | 20 +++ src/preload.ts | 18 ++- src/types.ts | 2 + yarn.lock | 5 + 11 files changed, 100 insertions(+), 203 deletions(-) create mode 100644 .env.sample delete mode 100644 src/customHooks/Persistence.tsx diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..b813cb6 --- /dev/null +++ b/.env.sample @@ -0,0 +1,2 @@ +ENCRYPTION_KEY=SOME_STRING +NAME=CONFIG_NAME \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 80b755b..e71666b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "dotenv": "^16.4.5", "electron-squirrel-startup": "^1.0.1", "electron-store": "^10.0.0", "react": "^18.3.1", @@ -4102,6 +4103,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/package.json b/package.json index 1c64267..69cea68 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ }, "license": "MIT", "dependencies": { + "dotenv": "^16.4.5", "electron-squirrel-startup": "^1.0.1", "electron-store": "^10.0.0", "react": "^18.3.1", diff --git a/src/_mainProcess/helpers/persistence.ts b/src/_mainProcess/helpers/persistence.ts index 99c6766..6f0032f 100644 --- a/src/_mainProcess/helpers/persistence.ts +++ b/src/_mainProcess/helpers/persistence.ts @@ -1,58 +1,40 @@ +import { RecordEntries } from '../../types'; +import Store from 'electron-store'; + export class Persistence { readonly name: string; - private db: IDBDatabase; - private isPersistent: boolean; - private isDbCreated: boolean; + private store: Store; - constructor(name = 'VRCASS') { + constructor(name = 'VRCASS', encryptionKey?: string) { this.name = name; + this.store = new Store({ name: name, encryptionKey: encryptionKey }); + } - if (navigator.storage && navigator.storage.persist) { - navigator.storage.persisted().then((isPersistent) => { - if (!isPersistent) { - navigator.storage.persist().then((persistent) => { - this.isPersistent = persistent; - }); - } + setValue(item: RecordEntries, objectStore: string, key: string): void { + let newItems: Array = []; + const oldItems = this.getValues(objectStore); + if (oldItems && oldItems.length > 0) { + const index = oldItems.findIndex((element) => { + element.key = key; }); + if (index >= 0) { + oldItems[index] = item; + } else { + oldItems.push(item); + } + newItems = oldItems; + } else { + newItems.push(item); } - - const request = indexedDB.open(this.name); - request.onerror = () => { - this.isDbCreated = false; - }; - - request.onupgradeneeded = () => { - console.log('upgrade'); - this.db = request.result; - - this.db.createObjectStore('auth', { - keyPath: 'username', - }); - - this.db.createObjectStore('avatars', { - autoIncrement: true, - }); - - this.isDbCreated = true; - }; + // to get proper types package.json needs type: module and tsconfig needs module node and moduleResolution nodenext but then the rest wont compile anymore I HATE MODERN JS + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.store.set(objectStore, newItems); } - setValue(item: Record, objectStore: string, key?: string) { - const objStore = this.db - .transaction([objectStore], 'readwrite') - .objectStore(objectStore); - objStore.put(item, key); - } - - getValues(query: string, objectStore: string) { - const request = this.db - .transaction(objectStore) - .objectStore(objectStore) - .get(query); - - request.onsuccess = () => { - return request.result; - }; + getValues(objectStore: string): Array { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return this.store.get(objectStore) as Array; } } diff --git a/src/app.tsx b/src/app.tsx index c8a341c..f06e7eb 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,17 +1,13 @@ import React from 'react'; -import { Persistence } from './customHooks/Persistence'; import { createRoot } from 'react-dom/client'; -import FetchWorldButton from './components/atoms/FetchWorldButton'; import SetAndRetrieveAuth from './components/atoms/SetAndRetriveAuth'; function App() { return (
- -

💖 Hello World!

-

Welcome to your Electron application.

- -
+

💖 Hello World!

+

Welcome to your Electron application.

+
); } diff --git a/src/components/atoms/SetAndRetriveAuth.tsx b/src/components/atoms/SetAndRetriveAuth.tsx index 0ca472a..53378e7 100644 --- a/src/components/atoms/SetAndRetriveAuth.tsx +++ b/src/components/atoms/SetAndRetriveAuth.tsx @@ -1,23 +1,25 @@ -import { usePersistence } from '../../customHooks/Persistence'; -import { useEffect, useRef } from 'react'; +import { useRef } from 'react'; const SetAndRetrieveAuth = () => { const usernameInput = useRef(null); const authcookieInput = useRef(null); const twofactorInput = useRef(null); //eslint-disable-next-line - let { ready, getValues, setValue } = usePersistence(); - const getValuesForName = () => { - console.log(getValues(usernameInput.current.value, 'auth')); + const getValuesForName = async () => { + console.log(window.electronAPI.getValues('auth')); + window.electronAPI.getValues('auth').then((value) => { + console.log(value); + }); }; const setValuesForName = () => { - setValue( + window.electronAPI.setValues( { username: usernameInput.current.value, authcookie: authcookieInput.current.value, twofactor: twofactorInput.current.value, }, - 'auth' + 'auth', + usernameInput.current.value ); }; diff --git a/src/customHooks/Persistence.tsx b/src/customHooks/Persistence.tsx deleted file mode 100644 index 81e6a68..0000000 --- a/src/customHooks/Persistence.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import React, { - createContext, - FC, - useContext, - useEffect, - useMemo, - useState, -} from 'react'; - -type PersistenceContext = { - ready: boolean; - db: IDBDatabase; - setValue: ( - item: Record, - objectStore: string, - key?: string - ) => void; - getValues: (query: string, objectStore: string) => Record; -}; - -const PersistenceContext = createContext({ - db: undefined, - ready: false, - setValue(item: Record, objectStore: string): void { - console.log(item); - }, - getValues(query: string, objectStore: string) { - return { foo: 'bar' }; - }, -}); - -export const Persistence: FC = ({ children }) => { - const [isPersistence, setIsPersistence] = useState(false); - const [ready, setReady] = useState(false); - const [db, setDb] = useState(); - - const value = useMemo(() => { - function setPersistence() { - console.log('setting it'); - if (navigator.storage && navigator.storage.persist) { - navigator.storage.persisted().then((isPersistent) => { - if (!isPersistent) { - navigator.storage.persist().then((persistent) => { - setIsPersistence(persistent); - if (persistent) { - console.log( - 'Storage will not be cleared except by explicit user action' - ); - } else { - console.log( - 'Storage may be cleared by the UA under storage pressure.' - ); - } - }); - } else { - console.log('already set?'); - } - }); - } else { - console.log('cant get it'); - } - } - setPersistence(); - - const request = indexedDB.open('VRCASS'); - request.onerror = () => { - console.error("Why didn't you allow my web app to use IndexedDB?!"); - }; - request.onsuccess = () => { - console.log('success'); - setReady(true); - }; - request.onupgradeneeded = () => { - console.log('upgrade'); - const db = request.result; - setDb(db); - - // Create another object store called "names" with the autoIncrement flag set as true. - db.createObjectStore('auth', { - keyPath: 'username', - }); - - db.createObjectStore('avatars', { - autoIncrement: true, - }); - const objStore = db.createObjectStore('names', { autoIncrement: true }); - const customerData = [ - { - ssn: '444-44-4444', - name: 'Bill', - age: 35, - email: 'bill@company.com', - }, - { ssn: '555-55-5555', name: 'Donna', age: 32, email: 'donna@home.org' }, - ]; - - customerData.forEach((customer) => { - objStore.add(customer); - }); - setReady(true); - }; - - function setValue( - item: Record, - objectStore: string, - key?: string - ) { - console.log(item); - if (!isPersistence) { - console.warn('no persistence'); - return; - } - const objStore = db - .transaction([objectStore], 'readwrite') - .objectStore(objectStore); - objStore.put(item, key); - } - - async function getValues(query: string, objectStore: string) { - console.log(query, objectStore); - const request = db - .transaction(objectStore) - .objectStore(objectStore) - .get(query); - - request.onsuccess = () => { - return request.result; - }; - } - - return { setValue, db, ready, getValues }; - }, []); - - return ( - - {children} - - ); -}; - -export const usePersistence = () => useContext(PersistenceContext); diff --git a/src/index.ts b/src/index.ts index fcd6355..f8009bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,9 @@ import { app, BrowserWindow, ipcMain } from 'electron'; import { getWorldById } from './_mainProcess/requests/getWorldById'; +import { Persistence } from './_mainProcess/helpers/persistence'; +import { RecordEntries } from './types'; +import 'dotenv/config'; +import * as process from 'node:process'; // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on // whether you're running in development or production). @@ -33,12 +37,28 @@ const createWindow = (): void => { // Some APIs can only be used after this event occurs. app.on('ready', () => { createWindow(); + console.log(app.getPath('userData')); ipcMain.handle('getWorldById', async (event, worldId: string) => { const t = await getWorldById(worldId); console.log(`${t}`); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return t!; }); + const persistence: Persistence = new Persistence( + process.env.NAME, + process.env.ENCRYPTION_KEY + ); + + ipcMain.handle('getValues', (event, objectStore: string) => { + return persistence.getValues(objectStore); + }); + + ipcMain.on( + 'setValues', + (event, item: RecordEntries, objectStore: string, key: string) => { + persistence.setValue(item, objectStore, key); + } + ); }); // Quit when all windows are closed, except on macOS. There, it's common diff --git a/src/preload.ts b/src/preload.ts index 5b7a1b1..e24e882 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -1,7 +1,17 @@ +import { RecordEntries, WorldRecord } from './types'; + declare global { interface Window { //eslint-disable-next-line @typescript-eslint/no-explicit-any - electronAPI: any; + electronAPI: { + getWorldById: (worldId: string) => Promise; + getValues: (objectStore: string) => Promise; + setValues: ( + item: RecordEntries, + objectStore: string, + key: string + ) => void; + }; } } @@ -11,4 +21,10 @@ contextBridge.exposeInMainWorld('electronAPI', { getWorldById: async (worldId: string) => { return await ipcRenderer.invoke('getWorldById', worldId); }, + getValues: (objectStore: string) => { + return ipcRenderer.invoke('getValues', objectStore); + }, + setValues: (item: RecordEntries, objectStore: string, key: string) => { + ipcRenderer.send('setValues', item, objectStore, key); + }, }); diff --git a/src/types.ts b/src/types.ts index 1232a45..1b554bf 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1 +1,3 @@ export type RequestHeader = { [key: string]: string }; +export type RecordEntries = Record; +export type WorldRecord = Record; diff --git a/yarn.lock b/yarn.lock index cb71e18..98bb1c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2215,6 +2215,11 @@ dot-prop@^9.0.0: dependencies: type-fest "^4.18.2" +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" From d1bd301871a62928b57dfc8c3b6ca68ff7cd074a Mon Sep 17 00:00:00 2001 From: Jonathan Yeboah <10155597+JonYeb@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:40:55 +0200 Subject: [PATCH 5/5] put more stuff in env file --- .env.sample | 4 +++- src/constants.ts | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.env.sample b/.env.sample index b813cb6..e58bdec 100644 --- a/.env.sample +++ b/.env.sample @@ -1,2 +1,4 @@ ENCRYPTION_KEY=SOME_STRING -NAME=CONFIG_NAME \ No newline at end of file +NAME=CONFIG_NAME +CLIENT_API_KEY=API_KEY +USER_AGENT='' \ No newline at end of file diff --git a/src/constants.ts b/src/constants.ts index f1fd019..08df1a1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,12 +1,15 @@ +import 'dotenv/config'; +import * as process from 'node:process'; + import { RequestHeader } from './types'; -export const CLIENT_API_KEY = 'JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26'; +export const CLIENT_API_KEY = process.env.CLIENT_API_KEY; export const BASE_URL = 'https:/vrchat.com'; export const API_BASE_URL = `${BASE_URL}/api/1`; export const DEFAULT_HEADER: RequestHeader = { - 'User-Agent': 'VRC-ASS/0.1.0 onetime.jon.yeb@outlook.de', + 'User-Agent': process.env.USER_AGENT, // 'connect-src': `${BASE_URL}*`, // 'Access-Control-Allow-Origin': BASE_URL, };