mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-10-20 18:56:30 +00:00
Remove the unreleased Electron desktop package
packages/apps-electron was never released, and electron 28, electron-builder and their tooling (got, tar, app-builder-lib, builder-util-runtime) were most of the dependency advisories left in this repo. Drop the package, its scripts, the build:electron CI step, its i18n namespace and the deps only it used (concurrently included). The shipped web bundle changes by one string: "apps-electron" leaves the i18n namespace list. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fd7e4522e2
commit
d4cc96df1f
34 files changed
+25
-1882
No files matched your search
@@ -10,7 +10,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: jacogr/action-merge@d2d64b4545acd93b0a9575177d3d215ae3f92029
|
- uses: jacogr/action-merge@d2d64b4545acd93b0a9575177d3d215ae3f92029
|
||||||
with:
|
with:
|
||||||
checks: pr (build:code),pr (build:i18n),pr (build:electron),pr (lint),pr (test)
|
checks: pr (build:code),pr (build:i18n),pr (lint),pr (test)
|
||||||
labels: -auto
|
labels: -auto
|
||||||
strategy: squash
|
strategy: squash
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
@@ -6,7 +6,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
step: ['lint', 'test', 'build:code', 'build:i18n', 'build:electron']
|
step: ['lint', 'test', 'build:code', 'build:i18n']
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|||||||
+1
-21
@@ -24,20 +24,13 @@
|
|||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"main": "packages/apps-electron/build/electron.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "yarn clean && BUILD_ANALYZE=1 yarn run build:code && yarn source-map-explorer packages/apps/build/app.*.js",
|
"analyze": "yarn clean && BUILD_ANALYZE=1 yarn run build:code && yarn source-map-explorer packages/apps/build/app.*.js",
|
||||||
"build": "yarn run build:i18n && yarn run build:code",
|
"build": "yarn run build:i18n && yarn run build:code",
|
||||||
"build:before": "yarn build:images && yarn build:typesBundle",
|
"build:before": "yarn build:images && yarn build:typesBundle",
|
||||||
"build:code": "NODE_ENV=production yarn pezkuwi-dev-build-ts",
|
"build:code": "NODE_ENV=production yarn pezkuwi-dev-build-ts",
|
||||||
"build:devElectronMain": "cd packages/apps-electron && yarn pezkuwi-exec-webpack --config webpack.main.cjs",
|
|
||||||
"build:devElectronRenderer": "cd packages/apps-electron && yarn pezkuwi-exec-webpack --config webpack.renderer.cjs",
|
|
||||||
"build:electron": "yarn clean:electronBuild && yarn build:electronMain && yarn build:electronRenderer",
|
|
||||||
"build:electronMain": "cd packages/apps-electron && NODE_ENV=production yarn pezkuwi-exec-webpack --config webpack.main.cjs",
|
|
||||||
"build:electronRenderer": "cd packages/apps-electron && NODE_ENV=production yarn pezkuwi-exec-webpack --config webpack.renderer.cjs",
|
|
||||||
"build:i18n": "i18next-scanner --config i18next-scanner.config.cjs && node ./scripts/i18nSort.cjs",
|
"build:i18n": "i18next-scanner --config i18next-scanner.config.cjs && node ./scripts/i18nSort.cjs",
|
||||||
"build:images": "node scripts/imgConvert.mjs",
|
"build:images": "node scripts/imgConvert.mjs",
|
||||||
"build:release:electron": "yarn build && yarn build:electron && yarn postinstall:electron",
|
|
||||||
"build:release:ghpages": "yarn pezkuwi-ci-ghact-docs",
|
"build:release:ghpages": "yarn pezkuwi-ci-ghact-docs",
|
||||||
"build:release:ipfs": "node scripts/ipfsUpload.mjs",
|
"build:release:ipfs": "node scripts/ipfsUpload.mjs",
|
||||||
"build:release:www": "yarn pezkuwi-ci-ghact-build && yarn build:release:ghpages && yarn build:release:ipfs",
|
"build:release:www": "yarn pezkuwi-ci-ghact-build && yarn build:release:ghpages && yarn build:release:ipfs",
|
||||||
@@ -47,21 +40,12 @@
|
|||||||
"ci:chainEndpoints": "pezkuwi-dev-run-test --env node --logfile .github/chain-endpoints.md packages/apps-config/src/ci/chainEndpoints",
|
"ci:chainEndpoints": "pezkuwi-dev-run-test --env node --logfile .github/chain-endpoints.md packages/apps-config/src/ci/chainEndpoints",
|
||||||
"ci:chainTypes": "echo ok",
|
"ci:chainTypes": "echo ok",
|
||||||
"clean": "pezkuwi-dev-clean-build",
|
"clean": "pezkuwi-dev-clean-build",
|
||||||
"clean:electronBuild": "cd packages/apps-electron && pezkuwi-dev-clean-build",
|
|
||||||
"clean:electronRelease": "cd packages/apps-electron && rm -rf release",
|
|
||||||
"clean:i18n": "rm -rf packages/apps/public/locales/en && mkdir -p packages/apps/public/locales/en",
|
"clean:i18n": "rm -rf packages/apps/public/locales/en && mkdir -p packages/apps/public/locales/en",
|
||||||
"docs": "echo \"skipping docs\"",
|
"docs": "echo \"skipping docs\"",
|
||||||
"lint": "pezkuwi-dev-run-lint",
|
"lint": "pezkuwi-dev-run-lint",
|
||||||
"packElectron": "yarn build:release:electron && yarn clean:electronRelease && electron-builder build -mwl",
|
|
||||||
"packElectron:linux": "yarn build:release:electron && electron-builder build --linux --project packages/apps-electron",
|
|
||||||
"packElectron:mac": "yarn build:release:electron && electron-builder build --mac --project packages/apps-electron",
|
|
||||||
"packElectron:test": "yarn build:release:electron && electron-builder --dir --project packages/apps-electron",
|
|
||||||
"packElectron:win": "yarn build:release:electron && electron-builder build --win --project packages/apps-electron",
|
|
||||||
"postinstall": "pezkuwi-dev-yarn-only",
|
"postinstall": "pezkuwi-dev-yarn-only",
|
||||||
"postinstall:electron": "electron-builder install-app-deps",
|
|
||||||
"start": "yarn clean && cd packages/apps && yarn pezkuwi-exec-webpack serve --config webpack.serve.cjs --port 3000",
|
"start": "yarn clean && cd packages/apps && yarn pezkuwi-exec-webpack serve --config webpack.serve.cjs --port 3000",
|
||||||
"start:electron": "yarn clean:electronBuild && concurrently 'yarn build:devElectronMain && cd packages/apps-electron && electron ./build/electron.js' 'yarn build:devElectronRenderer'",
|
"test": "pezkuwi-dev-run-test --env browser ^typesBundle ^chainEndpoints ^chainTypes ^page- ^react-",
|
||||||
"test": "pezkuwi-dev-run-test --env browser ^typesBundle ^chainEndpoints ^chainTypes ^page- ^react- ^apps-electron",
|
|
||||||
"test:all": "pezkuwi-dev-run-test --env browser ^chainEndpoints ^chainTypes",
|
"test:all": "pezkuwi-dev-run-test --env browser ^chainEndpoints ^chainTypes",
|
||||||
"test:one": "pezkuwi-dev-run-test --env browser",
|
"test:one": "pezkuwi-dev-run-test --env browser",
|
||||||
"test:skipped": "echo 'tests skipped'"
|
"test:skipped": "echo 'tests skipped'"
|
||||||
@@ -79,12 +63,8 @@
|
|||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/store": "^2.0.5",
|
"@types/store": "^2.0.5",
|
||||||
"concurrently": "^8.2.2",
|
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"dnslink-cloudflare": "^3.0.0",
|
"dnslink-cloudflare": "^3.0.0",
|
||||||
"electron": "28.0.0",
|
|
||||||
"electron-builder": "24.10.0",
|
|
||||||
"electron-builder-notarize": "^1.5.1",
|
|
||||||
"extensionless": "^1.9.6",
|
"extensionless": "^1.9.6",
|
||||||
"i18next-scanner": "^4.4.0",
|
"i18next-scanner": "^4.4.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
build
|
|
||||||
node_modules
|
|
||||||
release
|
|
||||||
Whitespace-only changes.
Whitespace-only changes.
@@ -1,17 +0,0 @@
|
|||||||
# @pezkuwi/apps-electron
|
|
||||||
|
|
||||||
Desktop Pezkuwi apps client for Windows, Mac and Linux.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
[Download here](https://github.com/pezkuwichain/pezkuwi-apps/releases/latest) latest versions for Windows, Mac and Linux.
|
|
||||||
|
|
||||||
## Development and testing
|
|
||||||
|
|
||||||
Contributions are welcome!
|
|
||||||
|
|
||||||
Follow steps described [here](https://github.com/pezkuwichain/pezkuwi-apps#development) to setup the project.
|
|
||||||
|
|
||||||
* Run `yarn start:electron` to start the app in development mode. You will possibly see the `Not Found / 404` message. It's ok, just wait for the build to finish and refresh pressing `Ctrl+R`.
|
|
||||||
* Run `yarn test` to run tests
|
|
||||||
* Run `yarn packElectron:(mac|linux|windows)` with the OS you want to build for to create the app executable. Find the packages in `packages/apps-electron/release`.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.device.camera</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB |
@@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
productName: Polkadot-JS Apps
|
|
||||||
artifactName: Polkadot-JS-Apps-${version}.${ext}
|
|
||||||
files:
|
|
||||||
- "./build"
|
|
||||||
- "./assets"
|
|
||||||
- "./appleEntitlements"
|
|
||||||
appId: com.polkadotjs.polkadotjs-apps
|
|
||||||
linux:
|
|
||||||
executableName: polkadot-apps
|
|
||||||
mac:
|
|
||||||
artifactName: Polkadot-JS-Apps-mac-${version}.${ext}
|
|
||||||
category: public.app-category.finance
|
|
||||||
entitlements: "./packages/apps-electron/appleEntitlements/entitlements.mac.plist"
|
|
||||||
extendInfo:
|
|
||||||
NSCameraUsageDescription: "This app requires camera access to capture account data on imports"
|
|
||||||
hardenedRuntime: true
|
|
||||||
directories:
|
|
||||||
buildResources: "./assets"
|
|
||||||
output: "./release"
|
|
||||||
afterSign: electron-builder-notarize
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"author": "Dijital Kurdistan Tech Institute <info@pezkuwichain.io>",
|
|
||||||
"bugs": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-apps/issues",
|
|
||||||
"description": "An Apps portal into the Pezkuwi network",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"homepage": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-apps/tree/master/packages/apps-electron#readme",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"name": "@pezkuwi/apps-electron",
|
|
||||||
"private": true,
|
|
||||||
"repository": {
|
|
||||||
"directory": "packages/apps-electron",
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-apps.git"
|
|
||||||
},
|
|
||||||
"sideEffects": false,
|
|
||||||
"version": "1.0.2-1-x",
|
|
||||||
"main": "build/electron.js",
|
|
||||||
"dependencies": {
|
|
||||||
"electron-log": "^5.0.1",
|
|
||||||
"electron-updater": "^6.1.7"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@pezkuwi/dev": "^0.85.2",
|
|
||||||
"@types/tmp": "^0.2.6",
|
|
||||||
"copy-webpack-plugin": "^11.0.0",
|
|
||||||
"electron": "28.0.0",
|
|
||||||
"electron-builder": "24.10.0",
|
|
||||||
"electron-builder-notarize": "^1.5.1",
|
|
||||||
"html-webpack-plugin": "^5.5.4",
|
|
||||||
"tmp": "^0.2.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"webpack": "*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson } from '@pezkuwi/ui-keyring/types';
|
|
||||||
|
|
||||||
export interface AccountStoreApi {
|
|
||||||
all: () => Promise<{ key: string, value: KeyringJson }[]>
|
|
||||||
get: (key: string) => Promise<KeyringJson>
|
|
||||||
remove: (key: string) => Promise<void>
|
|
||||||
set: (key: string, value: KeyringJson) => Promise<void>
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { AccountStoreApi } from './account-store-api.js';
|
|
||||||
|
|
||||||
export interface ElectronMainApi {
|
|
||||||
accountStore: AccountStoreApi
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { ElectronMainApi } from './electron-main-api.js';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
ElectronMain: ElectronMainApi
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const electronMainApi = window.ElectronMain;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { AppUpdater } from 'electron-updater';
|
|
||||||
|
|
||||||
export async function setupAutoUpdater (): Promise<void> {
|
|
||||||
const { autoUpdater } = await import('electron-updater');
|
|
||||||
|
|
||||||
await setLogger(autoUpdater);
|
|
||||||
autoUpdater.checkForUpdatesAndNotify().catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setLogger (autoUpdater: AppUpdater): Promise<void> {
|
|
||||||
const log = await import('electron-log');
|
|
||||||
|
|
||||||
log.transports.file.level = 'debug';
|
|
||||||
autoUpdater.logger = log;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { HeadersReceivedResponse } from 'electron';
|
|
||||||
|
|
||||||
import { session } from 'electron';
|
|
||||||
|
|
||||||
export function setupContentSecurityPolicy (_: string): void {
|
|
||||||
session.defaultSession.webRequest.onHeadersReceived((details, respond: (response: HeadersReceivedResponse) => void) => {
|
|
||||||
respond({
|
|
||||||
responseHeaders: {
|
|
||||||
...details.responseHeaders,
|
|
||||||
'Content-Security-Policy': [
|
|
||||||
"default-src 'self';" +
|
|
||||||
" style-src-elem 'self' https://fonts.googleapis.com/css 'unsafe-inline';" +
|
|
||||||
" font-src data: 'self' https://fonts.gstatic.com;" +
|
|
||||||
" style-src 'unsafe-inline';" +
|
|
||||||
" connect-src 'self' wss: ws:;" +
|
|
||||||
" img-src 'self' data:;" +
|
|
||||||
// react-qr-reader uses an embedded blob
|
|
||||||
" worker-src 'self' blob: filesystem:;" +
|
|
||||||
// unsafe-eval is needed for the WASM content - same as the extension
|
|
||||||
// script hashes here are for the window.top script (not technically needed)
|
|
||||||
" script-src 'self' 'unsafe-eval' 'sha256-02/ejyoV/iwRdJ4NAsxjzF6WVUtLMPM6Nv96EbAm6u8=' 'sha256-wW/WsLudCDaPo/ibpeK0KslHqYpCzcAKNFxFBXwCHJg='"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import { app } from 'electron';
|
|
||||||
|
|
||||||
import { registerAccountStoreHandlers } from '../main/account-store.js';
|
|
||||||
import { setupAutoUpdater } from './autoUpdater.js';
|
|
||||||
import { setupContentSecurityPolicy } from './contentSecurityPolicy.js';
|
|
||||||
import { createWindow } from './window.js';
|
|
||||||
|
|
||||||
const ENV = process.env.NODE_ENV || 'production';
|
|
||||||
|
|
||||||
app.on('web-contents-created', (_, webContents): void => {
|
|
||||||
webContents.setWindowOpenHandler(() => ({ action: 'allow' }));
|
|
||||||
});
|
|
||||||
|
|
||||||
app
|
|
||||||
.whenReady()
|
|
||||||
.then(async (): Promise<void> => {
|
|
||||||
registerAccountStoreHandlers();
|
|
||||||
setupContentSecurityPolicy(ENV);
|
|
||||||
|
|
||||||
await createWindow(ENV);
|
|
||||||
await setupAutoUpdater();
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import { BrowserWindow, screen, shell } from 'electron';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
export function createWindow (environment: string): Promise<unknown> {
|
|
||||||
const { height, width } = screen.getPrimaryDisplay().workAreaSize;
|
|
||||||
|
|
||||||
const win = new BrowserWindow({
|
|
||||||
height,
|
|
||||||
icon: path.join(__dirname, 'icon.png'),
|
|
||||||
webPreferences: {
|
|
||||||
contextIsolation: true,
|
|
||||||
nodeIntegration: false,
|
|
||||||
preload: path.join(__dirname, 'preload.js')
|
|
||||||
},
|
|
||||||
width
|
|
||||||
});
|
|
||||||
|
|
||||||
if (environment === 'development') {
|
|
||||||
win.webContents.openDevTools();
|
|
||||||
|
|
||||||
return win.loadURL('http://127.0.0.1:3000/');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle attempts to open a new window via window.open()
|
|
||||||
win.webContents.setWindowOpenHandler(({ url }) => {
|
|
||||||
// Open all http/https URLs externally
|
|
||||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
||||||
shell.openExternal(url).catch(console.log);
|
|
||||||
|
|
||||||
return { action: 'deny' };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { action: 'allow' };
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle in-app navigation attempts, such as clicking on <a href="...">
|
|
||||||
win.webContents.on('will-navigate', (event, url) => {
|
|
||||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
||||||
event.preventDefault();
|
|
||||||
shell.openExternal(url).catch(console.log);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const mainFilePath = path.resolve(__dirname, 'index.html');
|
|
||||||
|
|
||||||
return win.loadFile(mainFilePath);
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// setup these right at front
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import '@pezkuwi/apps/initSettings';
|
|
||||||
import 'semantic-ui-css/semantic.min.css';
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import '@pezkuwi/react-components/i18n';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { createRoot } from 'react-dom/client';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import Root from '@pezkuwi/apps/Root';
|
|
||||||
|
|
||||||
import { electronMainApi } from './api/global-exported-api.js';
|
|
||||||
import { RemoteElectronStore } from './renderer/remote-electron-store.js';
|
|
||||||
|
|
||||||
const rootId = 'root';
|
|
||||||
const rootElement = document.getElementById(rootId);
|
|
||||||
|
|
||||||
if (!rootElement) {
|
|
||||||
throw new Error(`Unable to find element with id '${rootId}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = new RemoteElectronStore(electronMainApi.accountStore);
|
|
||||||
|
|
||||||
createRoot(rootElement).render(
|
|
||||||
<Root
|
|
||||||
isElectron
|
|
||||||
store={store}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson } from '@pezkuwi/ui-keyring/types';
|
|
||||||
import type { IpcMainHandler } from './ipc-main-handler.js';
|
|
||||||
|
|
||||||
import * as tmp from 'tmp';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import { FileStore } from '@pezkuwi/ui-keyring/stores';
|
|
||||||
|
|
||||||
import { accountStoreIpcHandler } from './account-store.js';
|
|
||||||
|
|
||||||
const exampleAccount = (address: string): KeyringJson => ({
|
|
||||||
address,
|
|
||||||
meta: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Account store', () => {
|
|
||||||
let accountStore: IpcMainHandler;
|
|
||||||
let tmpDir: tmp.DirResult;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
tmpDir = tmp.dirSync({ unsafeCleanup: true });
|
|
||||||
accountStore = accountStoreIpcHandler(new FileStore(tmpDir.name));
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
tmpDir.removeCallback();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('all returns empty array at first', () => {
|
|
||||||
expect(accountStore['account-store-all']()).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('after adding accounts, they become visible', async () => {
|
|
||||||
await accountStore['account-store-set']('1', exampleAccount('a'));
|
|
||||||
await accountStore['account-store-set']('2', exampleAccount('b'));
|
|
||||||
|
|
||||||
expect(accountStore['account-store-all']()).toEqual([{
|
|
||||||
key: '1', value: exampleAccount('a')
|
|
||||||
}, {
|
|
||||||
key: '2', value: exampleAccount('b')
|
|
||||||
}]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('get returns account if exists', async () => {
|
|
||||||
await accountStore['account-store-set']('1', exampleAccount('a'));
|
|
||||||
expect(await accountStore['account-store-get']('1')).toEqual(exampleAccount('a'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('get returns null if account does not exist', async () => {
|
|
||||||
// jest.spyOn(console, 'error').mockImplementationOnce(() => { /**/ });
|
|
||||||
|
|
||||||
expect(await accountStore['account-store-get']('1')).toEqual(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('account disappears from list after it is removed', async () => {
|
|
||||||
// jest.spyOn(console, 'error').mockImplementationOnce(() => { /**/ });
|
|
||||||
|
|
||||||
await accountStore['account-store-set']('1', exampleAccount('a'));
|
|
||||||
await accountStore['account-store-remove']('1');
|
|
||||||
|
|
||||||
expect(await accountStore['account-store-get']('1')).toEqual(null);
|
|
||||||
expect(accountStore['account-store-all']()).toEqual([]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson } from '@pezkuwi/ui-keyring/types';
|
|
||||||
import type { IpcMainHandler } from './ipc-main-handler.js';
|
|
||||||
|
|
||||||
import electron from 'electron';
|
|
||||||
import path from 'path';
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import { FileStore } from '@pezkuwi/ui-keyring/stores';
|
|
||||||
|
|
||||||
import { registerIpcHandler } from './register-ipc-handler.js';
|
|
||||||
|
|
||||||
const ACCOUNTS_SUBFOLDER = 'pezkuwi-accounts';
|
|
||||||
|
|
||||||
function safeWriteKey (key: string) {
|
|
||||||
return key.replace(/:/g, '-');
|
|
||||||
}
|
|
||||||
|
|
||||||
function safeReadKey (key: string) {
|
|
||||||
return key.replace(/-/g, ':');
|
|
||||||
}
|
|
||||||
|
|
||||||
export const accountStoreIpcHandler = (fileStore: FileStore): IpcMainHandler => ({
|
|
||||||
'account-store-all': () => {
|
|
||||||
let result: { key: string, value: KeyringJson }[] = [];
|
|
||||||
|
|
||||||
const collect = (key: string, value: KeyringJson) => {
|
|
||||||
result = [...result, { key: safeReadKey(key), value }];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileStore.all(collect);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
'account-store-get': async (key: string) => new Promise((resolve) => {
|
|
||||||
try {
|
|
||||||
fileStore.get(safeWriteKey(key), resolve);
|
|
||||||
} catch {
|
|
||||||
resolve(null);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
'account-store-remove': async (key: string) => new Promise((resolve) =>
|
|
||||||
fileStore.remove(safeWriteKey(key), () => resolve(undefined))
|
|
||||||
),
|
|
||||||
'account-store-set': async (key: string, value: KeyringJson) => new Promise((resolve) =>
|
|
||||||
fileStore.set(safeWriteKey(key), value, () => resolve(undefined))
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
export const registerAccountStoreHandlers = (): void => {
|
|
||||||
const defaultStorePath = path.join(electron.app.getPath('userData'), ACCOUNTS_SUBFOLDER);
|
|
||||||
const fileStore = new FileStore(defaultStorePath);
|
|
||||||
|
|
||||||
registerIpcHandler(accountStoreIpcHandler(fileStore));
|
|
||||||
};
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
export type IpcMainHandler = Record<string, (...args: any[]) => unknown>;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
import type { IpcMainHandler } from './ipc-main-handler.js';
|
|
||||||
|
|
||||||
import electron from 'electron';
|
|
||||||
|
|
||||||
export const registerIpcHandler = (ipcHandler: IpcMainHandler): void => {
|
|
||||||
for (const [channel, listener] of Object.entries(ipcHandler)) {
|
|
||||||
electron.ipcMain.handle(channel, (_, ...args: unknown[]) => {
|
|
||||||
return listener(...args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson } from '@pezkuwi/ui-keyring/types';
|
|
||||||
|
|
||||||
import { contextBridge, ipcRenderer } from 'electron';
|
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('ElectronMain', {
|
|
||||||
accountStore: {
|
|
||||||
all: () => ipcRenderer.invoke('account-store-all'),
|
|
||||||
get: (key: string) => ipcRenderer.invoke('account-store-get', key),
|
|
||||||
remove: (key: string) => ipcRenderer.invoke('account-store-remove', key),
|
|
||||||
set: (key: string, value: KeyringJson) => ipcRenderer.invoke('account-store-set', key, value)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson } from '@pezkuwi/ui-keyring/types';
|
|
||||||
|
|
||||||
import { RemoteElectronStore } from './remote-electron-store.js';
|
|
||||||
|
|
||||||
describe('Remote Electron Store', () => {
|
|
||||||
const accountStore = {
|
|
||||||
all: jest.fn(),
|
|
||||||
get: jest.fn(),
|
|
||||||
remove: jest.fn(),
|
|
||||||
set: jest.fn()
|
|
||||||
};
|
|
||||||
const remoteStore = new RemoteElectronStore(accountStore);
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
accountStore.all.mockClear();
|
|
||||||
accountStore.get.mockClear();
|
|
||||||
accountStore.remove.mockClear();
|
|
||||||
accountStore.set.mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('all', () => {
|
|
||||||
it('calls callback for each returned account', async () => {
|
|
||||||
accountStore.all.mockResolvedValue([{
|
|
||||||
key: 1,
|
|
||||||
value: 'a'
|
|
||||||
}, {
|
|
||||||
key: 2,
|
|
||||||
value: 'b'
|
|
||||||
}]);
|
|
||||||
const cb = jest.fn();
|
|
||||||
|
|
||||||
remoteStore.all(cb);
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(cb).toHaveBeenNthCalledWith(1, 1, 'a');
|
|
||||||
expect(cb).toHaveBeenNthCalledWith(2, 2, 'b');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get', () => {
|
|
||||||
it('calls callback with returned account', async () => {
|
|
||||||
accountStore.get.mockResolvedValue('a');
|
|
||||||
const cb = jest.fn();
|
|
||||||
|
|
||||||
remoteStore.get('1', cb);
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(accountStore.get).toHaveBeenCalledWith('1');
|
|
||||||
expect(cb).toHaveBeenCalledWith('a');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls callback with null if no accounts found', async () => {
|
|
||||||
accountStore.get.mockResolvedValue(null);
|
|
||||||
const cb = jest.fn();
|
|
||||||
|
|
||||||
remoteStore.get('1', cb);
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(cb).toHaveBeenCalledWith(null);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('remove', () => {
|
|
||||||
it('calls callback after success', async () => {
|
|
||||||
accountStore.remove.mockResolvedValue(null);
|
|
||||||
const cb = jest.fn();
|
|
||||||
|
|
||||||
remoteStore.remove('1', cb);
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(accountStore.remove).toHaveBeenCalledWith('1');
|
|
||||||
expect(cb).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('set', () => {
|
|
||||||
it('calls callback after success', async () => {
|
|
||||||
accountStore.set.mockResolvedValue(null);
|
|
||||||
const cb = jest.fn();
|
|
||||||
|
|
||||||
remoteStore.set('1', 'a' as unknown as KeyringJson, cb);
|
|
||||||
await Promise.resolve();
|
|
||||||
|
|
||||||
expect(accountStore.set).toHaveBeenCalledWith('1', 'a');
|
|
||||||
expect(cb).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore Warned on by nodenext resolution (while package does build in bundler mode)
|
|
||||||
import type { KeyringJson, KeyringStore } from '@pezkuwi/ui-keyring/types';
|
|
||||||
import type { AccountStoreApi } from '../api/account-store-api.js';
|
|
||||||
|
|
||||||
export class RemoteElectronStore implements KeyringStore {
|
|
||||||
readonly #accountStore: AccountStoreApi;
|
|
||||||
|
|
||||||
constructor (accountStore: AccountStoreApi) {
|
|
||||||
this.#accountStore = accountStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
all (cb: (key: string, value: KeyringJson) => void): void {
|
|
||||||
this.#accountStore.all()
|
|
||||||
.then((result: { key: string, value: KeyringJson }[]) => result?.forEach(({ key, value }) => cb(key, value)))
|
|
||||||
.catch((e: Error) => {
|
|
||||||
throw new Error(`error getting all accounts: ${e.message}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get (key: string, cb: (value: KeyringJson) => void): void {
|
|
||||||
this.#accountStore.get(key)
|
|
||||||
.then(cb).catch((e: Error) => {
|
|
||||||
throw new Error(`error storing account: ${e.message}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
remove (key: string, cb: (() => void) | undefined): void {
|
|
||||||
this.#accountStore.remove(key).then(cb).catch((e: Error) => {
|
|
||||||
throw new Error(`error removing account: ${e.message}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
set (key: string, value: KeyringJson, cb: (() => void) | undefined): void {
|
|
||||||
this.#accountStore.set(key, value).then(cb).catch((e: Error) => {
|
|
||||||
throw new Error(`error saving account: ${e.message}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": "..",
|
|
||||||
"outDir": "./build",
|
|
||||||
"rootDir": "./src",
|
|
||||||
/* Since this is a forced-by-electron-CJS-module, we have to switch this off */
|
|
||||||
"verbatimModuleSyntax": false
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"webpack.*.cjs"
|
|
||||||
],
|
|
||||||
"references": [
|
|
||||||
{ "path": "../apps/tsconfig.build.json" },
|
|
||||||
{ "path": "../react-components/tsconfig.build.json" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps-electron authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function createWebpack () {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
entry: {
|
|
||||||
electron: './src/electron',
|
|
||||||
preload: './src/preload.ts'
|
|
||||||
},
|
|
||||||
mode: 'production',
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
include: /node_modules/,
|
|
||||||
test: /\.mjs$/,
|
|
||||||
type: 'javascript/auto'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
exclude: /(node_modules)/,
|
|
||||||
test: /\.(ts|tsx)$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: require.resolve('ts-loader'),
|
|
||||||
options: {
|
|
||||||
configFile: 'tsconfig.webpack.json',
|
|
||||||
transpileOnly: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
__dirname: false,
|
|
||||||
__filename: false
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: '[name].js',
|
|
||||||
path: path.join(__dirname, '/build')
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new CopyWebpackPlugin({ patterns: [{ from: 'assets' }] })
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@pezkuwi/hw-ledger-transports': require.resolve('@pezkuwi/hw-ledger-transports/node')
|
|
||||||
},
|
|
||||||
extensionAlias: {
|
|
||||||
'.js': ['.ts', '.tsx', '.js']
|
|
||||||
},
|
|
||||||
extensions: ['.js', '.jsx', '.json', '.mjs', '.ts', '.tsx']
|
|
||||||
},
|
|
||||||
target: 'electron-main'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = createWebpack();
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright 2017-2026 @pezkuwi/apps authors & contributors
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/* eslint-disable camelcase */
|
|
||||||
|
|
||||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
||||||
const path = require('path');
|
|
||||||
const { merge } = require('webpack-merge');
|
|
||||||
|
|
||||||
const baseConfig = require('../apps/webpack.base.cjs');
|
|
||||||
|
|
||||||
const context = __dirname;
|
|
||||||
|
|
||||||
module.exports = merge(
|
|
||||||
baseConfig(context, 'development'),
|
|
||||||
{
|
|
||||||
plugins: [
|
|
||||||
// It must be placed before HtmlWebpackPlugin
|
|
||||||
new CopyWebpackPlugin({
|
|
||||||
patterns: [{
|
|
||||||
from: '../apps/public',
|
|
||||||
globOptions: {
|
|
||||||
dot: true,
|
|
||||||
ignore: ['**/index.html']
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}),
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
PAGE_TITLE: 'Pezkuwi/Bizinikiwi Portal',
|
|
||||||
minify: false,
|
|
||||||
template: path.join(context, '../apps/public/index.html')
|
|
||||||
})
|
|
||||||
],
|
|
||||||
target: 'web'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@@ -50,7 +50,6 @@ i18next
|
|||||||
ns: [
|
ns: [
|
||||||
'apps',
|
'apps',
|
||||||
'apps-config',
|
'apps-config',
|
||||||
'apps-electron',
|
|
||||||
'apps-routing',
|
'apps-routing',
|
||||||
'app-accounts',
|
'app-accounts',
|
||||||
'app-claims',
|
'app-claims',
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
{ "path": "./packages/apps/tsconfig.build.json" },
|
{ "path": "./packages/apps/tsconfig.build.json" },
|
||||||
{ "path": "./packages/apps-config/tsconfig.build.json" },
|
{ "path": "./packages/apps-config/tsconfig.build.json" },
|
||||||
{ "path": "./packages/apps-config/tsconfig.spec.json" },
|
{ "path": "./packages/apps-config/tsconfig.spec.json" },
|
||||||
{ "path": "./packages/apps-electron/tsconfig.build.json" },
|
|
||||||
{ "path": "./packages/apps-routing/tsconfig.build.json" },
|
{ "path": "./packages/apps-routing/tsconfig.build.json" },
|
||||||
{ "path": "./packages/page-accounts/tsconfig.build.json" },
|
{ "path": "./packages/page-accounts/tsconfig.build.json" },
|
||||||
{ "path": "./packages/page-accounts/tsconfig.spec.json" },
|
{ "path": "./packages/page-accounts/tsconfig.spec.json" },
|
||||||
|
|||||||
+1
-3
@@ -4,9 +4,7 @@
|
|||||||
"baseUrl": "./packages",
|
"baseUrl": "./packages",
|
||||||
"composite": false,
|
"composite": false,
|
||||||
/*
|
/*
|
||||||
* We have a couple of issues that forces us to disable this -
|
* Disabled since some of our packaged dependencies are problematic
|
||||||
* 1. apps-electron is still CJS
|
|
||||||
* 2. some of our packaged dependencies are problematic
|
|
||||||
*
|
*
|
||||||
* (also disabled in tsconfig.build.json)
|
* (also disabled in tsconfig.build.json)
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in new issue
Block a user