mirror of
https://github.com/frappe/books.git
synced 2024-09-19 19:19:02 +00:00
chore: convert main.js to renderer.ts
This commit is contained in:
parent
a596f5dcad
commit
a86e9447ab
@ -9,6 +9,9 @@ const {
|
||||
const { markRaw } = require('vue');
|
||||
|
||||
module.exports = {
|
||||
isElectron: false,
|
||||
isServer: false,
|
||||
|
||||
initializeAndRegister(customModels = {}, force = false) {
|
||||
this.init(force);
|
||||
const common = require('frappe/common');
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { app } from 'electron';
|
||||
import { Main } from '../main';
|
||||
import { handleError } from '../src/errorHandling';
|
||||
|
||||
export default function registerProcessListeners(main: Main) {
|
||||
if (main.isDevelopment) {
|
||||
@ -15,4 +16,12 @@ export default function registerProcessListeners(main: Main) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (error: Error) => {
|
||||
handleError(true, error);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
handleError(true, error, {}, () => process.exit(1));
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ interface ErrorLog {
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
more?: object;
|
||||
more?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function getCanLog(): boolean {
|
||||
@ -71,7 +71,10 @@ function getToastProps(errorLogObj: ErrorLog, canLog: boolean, cb?: Function) {
|
||||
return props;
|
||||
}
|
||||
|
||||
export function getErrorLogObject(error: Error, more: object = {}): ErrorLog {
|
||||
export function getErrorLogObject(
|
||||
error: Error,
|
||||
more: Record<string, unknown>
|
||||
): ErrorLog {
|
||||
const { name, stack, message } = error;
|
||||
const errorLogObj = { name, stack, message, more };
|
||||
|
||||
@ -84,7 +87,7 @@ export function getErrorLogObject(error: Error, more: object = {}): ErrorLog {
|
||||
export function handleError(
|
||||
shouldLog: boolean,
|
||||
error: Error,
|
||||
more: object = {},
|
||||
more?: Record<string, unknown>,
|
||||
cb?: Function
|
||||
) {
|
||||
telemetry.error(error.name);
|
||||
@ -96,7 +99,7 @@ export function handleError(
|
||||
return;
|
||||
}
|
||||
|
||||
const errorLogObj = getErrorLogObject(error, more);
|
||||
const errorLogObj = getErrorLogObject(error, more ?? {});
|
||||
|
||||
// @ts-ignore
|
||||
const canLog = getCanLog();
|
||||
|
168
src/main.js
168
src/main.js
@ -1,168 +0,0 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
import frappe from 'frappe';
|
||||
import { createApp } from 'vue';
|
||||
import models from '../models';
|
||||
import App from './App';
|
||||
import FeatherIcon from './components/FeatherIcon';
|
||||
import config, { ConfigKeys } from './config';
|
||||
import { getErrorHandled, handleError } from './errorHandling';
|
||||
import { IPC_CHANNELS, IPC_MESSAGES } from './messages';
|
||||
import router from './router';
|
||||
import telemetry from './telemetry/telemetry';
|
||||
import { outsideClickDirective } from './ui';
|
||||
import { setLanguageMap, showToast, stringifyCircular } from './utils';
|
||||
(async () => {
|
||||
const language = config.get('language');
|
||||
if (language) {
|
||||
await setLanguageMap(language);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
window.config = config;
|
||||
}
|
||||
|
||||
frappe.isServer = true;
|
||||
frappe.isElectron = true;
|
||||
frappe.initializeAndRegister(models, language);
|
||||
frappe.fetch = window.fetch.bind();
|
||||
|
||||
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
||||
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
||||
|
||||
window.frappe = frappe;
|
||||
|
||||
window.onerror = (message, source, lineno, colno, error) => {
|
||||
error = error ?? new Error('triggered in window.onerror');
|
||||
handleError(true, error, { message, source, lineno, colno });
|
||||
};
|
||||
|
||||
process.on('unhandledRejection', (error) => {
|
||||
handleError(true, error);
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
handleError(true, error, () => process.exit(1));
|
||||
});
|
||||
|
||||
registerIpcRendererListeners();
|
||||
|
||||
const app = createApp({
|
||||
template: '<App/>',
|
||||
});
|
||||
app.use(router);
|
||||
app.component('App', App);
|
||||
app.component('feather-icon', FeatherIcon);
|
||||
app.directive('on-outside-click', outsideClickDirective);
|
||||
app.mixin({
|
||||
computed: {
|
||||
frappe() {
|
||||
return frappe;
|
||||
},
|
||||
platform() {
|
||||
return {
|
||||
win32: 'Windows',
|
||||
darwin: 'Mac',
|
||||
linux: 'Linux',
|
||||
}[process.platform];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
t: frappe.t,
|
||||
T: frappe.T,
|
||||
},
|
||||
});
|
||||
|
||||
app.config.errorHandler = (err, vm, info) => {
|
||||
const more = {
|
||||
info,
|
||||
};
|
||||
|
||||
if (vm) {
|
||||
const { fullPath, params } = vm.$route;
|
||||
more.fullPath = fullPath;
|
||||
more.params = stringifyCircular(params ?? {});
|
||||
more.data = stringifyCircular(vm.$data ?? {}, true, true);
|
||||
more.props = stringifyCircular(vm.$props ?? {}, true, true);
|
||||
}
|
||||
|
||||
handleError(false, err, more);
|
||||
console.error(err, vm, info);
|
||||
};
|
||||
|
||||
incrementOpenCount();
|
||||
app.mount('body');
|
||||
})();
|
||||
|
||||
function incrementOpenCount() {
|
||||
let openCount = config.get(ConfigKeys.OpenCount);
|
||||
if (typeof openCount !== 'number') {
|
||||
openCount = 1;
|
||||
} else {
|
||||
openCount += 1;
|
||||
}
|
||||
|
||||
config.set(ConfigKeys.OpenCount, openCount);
|
||||
}
|
||||
|
||||
function registerIpcRendererListeners() {
|
||||
ipcRenderer.on(IPC_CHANNELS.STORE_ON_WINDOW, (event, message) => {
|
||||
Object.assign(window.frappe.store, message);
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.CHECKING_FOR_UPDATE, (_) => {
|
||||
showToast({ message: frappe.t`Checking for updates` });
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_AVAILABLE, (_, version) => {
|
||||
const message = version
|
||||
? frappe.t`Version ${version} available`
|
||||
: frappe.t`New version available`;
|
||||
const action = () => {
|
||||
ipcRenderer.send(IPC_MESSAGES.DOWNLOAD_UPDATE);
|
||||
showToast({ message: frappe.t`Downloading update` });
|
||||
};
|
||||
|
||||
showToast({
|
||||
message,
|
||||
action,
|
||||
actionText: frappe.t`Download Update`,
|
||||
duration: 10000,
|
||||
type: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_NOT_AVAILABLE, (_) => {
|
||||
showToast({ message: frappe.t`No updates available` });
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_DOWNLOADED, (_) => {
|
||||
const action = () => {
|
||||
ipcRenderer.send(IPC_MESSAGES.INSTALL_UPDATE);
|
||||
};
|
||||
showToast({
|
||||
message: frappe.t`Update downloaded`,
|
||||
action,
|
||||
actionText: frappe.t`Install Update`,
|
||||
duration: 10000,
|
||||
type: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_ERROR, (_, error) => {
|
||||
error.name = 'Updation Error';
|
||||
handleError(true, error);
|
||||
});
|
||||
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
const { visibilityState } = document;
|
||||
if (visibilityState === 'visible' && !telemetry.started) {
|
||||
telemetry.start();
|
||||
}
|
||||
|
||||
if (visibilityState !== 'hidden') {
|
||||
return;
|
||||
}
|
||||
|
||||
telemetry.stop();
|
||||
});
|
||||
}
|
95
src/renderer.ts
Normal file
95
src/renderer.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
import frappe from 'frappe';
|
||||
import { createApp } from 'vue';
|
||||
import models from '../models';
|
||||
import App from './App.vue';
|
||||
import FeatherIcon from './components/FeatherIcon.vue';
|
||||
import config, { ConfigKeys } from './config';
|
||||
import { getErrorHandled, handleError } from './errorHandling';
|
||||
import { incrementOpenCount } from './renderer/helpers';
|
||||
import registerIpcRendererListeners from './renderer/registerIpcRendererListeners';
|
||||
import router from './router';
|
||||
import { outsideClickDirective } from './ui';
|
||||
import { setLanguageMap, stringifyCircular } from './utils';
|
||||
|
||||
(async () => {
|
||||
const language = config.get(ConfigKeys.Language);
|
||||
if (language) {
|
||||
await setLanguageMap(language);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
// @ts-ignore
|
||||
window.config = config;
|
||||
}
|
||||
|
||||
frappe.isServer = true;
|
||||
frappe.isElectron = true;
|
||||
|
||||
frappe.initializeAndRegister(models);
|
||||
|
||||
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
||||
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
||||
|
||||
// @ts-ignore
|
||||
window.frappe = frappe;
|
||||
|
||||
window.onerror = (message, source, lineno, colno, error) => {
|
||||
error = error ?? new Error('triggered in window.onerror');
|
||||
handleError(true, error, { message, source, lineno, colno });
|
||||
};
|
||||
|
||||
registerIpcRendererListeners();
|
||||
|
||||
const app = createApp({
|
||||
template: '<App/>',
|
||||
});
|
||||
|
||||
app.use(router);
|
||||
app.component('App', App);
|
||||
app.component('feather-icon', FeatherIcon);
|
||||
app.directive('on-outside-click', outsideClickDirective);
|
||||
app.mixin({
|
||||
computed: {
|
||||
frappe() {
|
||||
return frappe;
|
||||
},
|
||||
platform(): string {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
return 'Windows';
|
||||
case 'darwin':
|
||||
return 'Mac';
|
||||
case 'linux':
|
||||
return 'Linux';
|
||||
default:
|
||||
return 'Linux';
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
t: frappe.t,
|
||||
T: frappe.T,
|
||||
},
|
||||
});
|
||||
|
||||
app.config.errorHandler = (err, vm, info) => {
|
||||
const more: Record<string, unknown> = {
|
||||
info,
|
||||
};
|
||||
|
||||
if (vm) {
|
||||
const { fullPath, params } = vm.$route;
|
||||
more.fullPath = fullPath;
|
||||
more.params = stringifyCircular(params ?? {});
|
||||
more.data = stringifyCircular(vm.$data ?? {}, true, true);
|
||||
more.props = stringifyCircular(vm.$props ?? {}, true, true);
|
||||
}
|
||||
|
||||
handleError(false, err as Error, more);
|
||||
console.error(err, vm, info);
|
||||
};
|
||||
|
||||
incrementOpenCount();
|
||||
app.mount('body');
|
||||
})();
|
12
src/renderer/helpers.ts
Normal file
12
src/renderer/helpers.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import config, { ConfigKeys } from '@/config';
|
||||
|
||||
export function incrementOpenCount() {
|
||||
let openCount = config.get(ConfigKeys.OpenCount);
|
||||
if (typeof openCount !== 'number') {
|
||||
openCount = 1;
|
||||
} else {
|
||||
openCount += 1;
|
||||
}
|
||||
|
||||
config.set(ConfigKeys.OpenCount, openCount);
|
||||
}
|
64
src/renderer/registerIpcRendererListeners.ts
Normal file
64
src/renderer/registerIpcRendererListeners.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { handleError } from '@/errorHandling';
|
||||
import { IPC_CHANNELS, IPC_MESSAGES } from '@/messages';
|
||||
import telemetry from '@/telemetry/telemetry';
|
||||
import { showToast } from '@/utils';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import frappe from 'frappe';
|
||||
|
||||
export default function registerIpcRendererListeners() {
|
||||
ipcRenderer.on(IPC_CHANNELS.STORE_ON_WINDOW, (event, message) => {
|
||||
Object.assign(frappe.store, message);
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.CHECKING_FOR_UPDATE, (_) => {
|
||||
showToast({ message: frappe.t`Checking for updates` });
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_AVAILABLE, (_, version) => {
|
||||
const message = version
|
||||
? frappe.t`Version ${version} available`
|
||||
: frappe.t`New version available`;
|
||||
const action = () => {
|
||||
ipcRenderer.send(IPC_MESSAGES.DOWNLOAD_UPDATE);
|
||||
showToast({ message: frappe.t`Downloading update` });
|
||||
};
|
||||
|
||||
showToast({
|
||||
message,
|
||||
action,
|
||||
actionText: frappe.t`Download Update`,
|
||||
duration: 10000,
|
||||
type: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_NOT_AVAILABLE, (_) => {
|
||||
showToast({ message: frappe.t`No updates available` });
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_DOWNLOADED, (_) => {
|
||||
const action = () => {
|
||||
ipcRenderer.send(IPC_MESSAGES.INSTALL_UPDATE);
|
||||
};
|
||||
showToast({
|
||||
message: frappe.t`Update downloaded`,
|
||||
action,
|
||||
actionText: frappe.t`Install Update`,
|
||||
duration: 10000,
|
||||
type: 'success',
|
||||
});
|
||||
});
|
||||
|
||||
ipcRenderer.on(IPC_CHANNELS.UPDATE_ERROR, (_, error) => {
|
||||
error.name = 'Updation Error';
|
||||
handleError(true, error);
|
||||
});
|
||||
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
if (document.visibilityState !== 'hidden') {
|
||||
return;
|
||||
}
|
||||
|
||||
telemetry.stop();
|
||||
});
|
||||
}
|
@ -1,16 +1,14 @@
|
||||
import ChartOfAccounts from '@/pages/ChartOfAccounts';
|
||||
// standard views
|
||||
import Dashboard from '@/pages/Dashboard/Dashboard';
|
||||
import DataImport from '@/pages/DataImport';
|
||||
// custom views
|
||||
import GetStarted from '@/pages/GetStarted';
|
||||
import InvoiceForm from '@/pages/InvoiceForm';
|
||||
import JournalEntryForm from '@/pages/JournalEntryForm';
|
||||
import ListView from '@/pages/ListView/ListView';
|
||||
import PrintView from '@/pages/PrintView/PrintView';
|
||||
import QuickEditForm from '@/pages/QuickEditForm';
|
||||
import Report from '@/pages/Report';
|
||||
import Settings from '@/pages/Settings/Settings';
|
||||
import ChartOfAccounts from '@/pages/ChartOfAccounts.vue';
|
||||
import Dashboard from '@/pages/Dashboard/Dashboard.vue';
|
||||
import DataImport from '@/pages/DataImport.vue';
|
||||
import GetStarted from '@/pages/GetStarted.vue';
|
||||
import InvoiceForm from '@/pages/InvoiceForm.vue';
|
||||
import JournalEntryForm from '@/pages/JournalEntryForm.vue';
|
||||
import ListView from '@/pages/ListView/ListView.vue';
|
||||
import PrintView from '@/pages/PrintView/PrintView.vue';
|
||||
import QuickEditForm from '@/pages/QuickEditForm.vue';
|
||||
import Report from '@/pages/Report.vue';
|
||||
import Settings from '@/pages/Settings/Settings.vue';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import telemetry from './telemetry/telemetry';
|
||||
import { NounEnum, Verb } from './telemetry/types';
|
||||
|
6
src/shims-vue.d.ts
vendored
6
src/shims-vue.d.ts
vendored
@ -1,4 +1,6 @@
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
import type { DefineComponent } from 'vue';
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
export default component;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Avatar from '@/components/Avatar';
|
||||
import Toast from '@/components/Toast';
|
||||
import Avatar from '@/components/Avatar.vue';
|
||||
import Toast from '@/components/Toast.vue';
|
||||
import router from '@/router';
|
||||
import { ipcRenderer } from 'electron';
|
||||
import frappe, { t } from 'frappe';
|
||||
|
@ -6,6 +6,7 @@ module.exports = {
|
||||
electronBuilder: {
|
||||
nodeIntegration: true,
|
||||
mainProcessFile: 'main.ts',
|
||||
rendererProcessFile: 'src/renderer.ts',
|
||||
disableMainProcessTypescript: false,
|
||||
mainProcessTypeChecking: true,
|
||||
chainWebpackRendererProcess: (config) => {
|
||||
|
Loading…
Reference in New Issue
Block a user