2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 19:09:01 +00:00

chore: enable typescript eslint rules

- refactor code to satisfy rules (batch 1)
- use ensuredir in build to prevent ENOENT
This commit is contained in:
18alantom 2023-06-21 16:08:39 +05:30
parent 8a1392e533
commit 4415c04a88
41 changed files with 240 additions and 183 deletions

View File

@ -1,23 +1,32 @@
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
node: true, node: true,
browser: true,
es2020: true,
}, },
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-console': 'warn',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': 'warn',
'arrow-body-style': 'off', 'arrow-body-style': 'off',
'prefer-arrow-callback': 'off', 'prefer-arrow-callback': 'warn',
'vue/no-mutating-props': 'off', 'vue/no-mutating-props': 'off',
'vue/multi-word-component-names': 'off', 'vue/multi-word-component-names': 'off',
'vue/no-useless-template-attributes': 'off', 'vue/no-useless-template-attributes': 'off',
'vue/one-component-per-file': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
}, },
parserOptions: {
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
}, parserOptions: { project: true, tsconfigRootDir: __dirname },
plugins: ['@typescript-eslint'],
extends: ['plugin:vue/vue3-essential', '@vue/typescript'], extends: [
'plugin:vue/vue3-strongly-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
ignorePatterns: ['.eslintrc.js'],
}; };

View File

@ -24,9 +24,9 @@ await packageApp();
function updatePaths() { function updatePaths() {
fs.removeSync(buildDirPath); fs.removeSync(buildDirPath);
fs.mkdirSync(buildDirPath); fs.ensureDirSync(buildDirPath);
fs.removeSync(packageDirPath); fs.removeSync(packageDirPath);
fs.mkdirSync(packageDirPath); fs.ensureDirSync(packageDirPath);
fs.ensureDirSync(path.join(buildDirPath, 'node_modules')); fs.ensureDirSync(path.join(buildDirPath, 'node_modules'));
} }

View File

@ -58,7 +58,10 @@ export class AuthHandler {
return { ...this.#config }; return { ...this.#config };
} }
init() {} init() {
return null;
}
async login(email: string, password: string) { async login(email: string, password: string) {
if (email === 'Administrator') { if (email === 'Administrator') {
this.#session.user = 'Administrator'; this.#session.user = 'Administrator';
@ -107,8 +110,6 @@ export class AuthHandler {
// TODO: Implement this with auth flow // TODO: Implement this with auth flow
} }
async purgeCache() {}
#getServerURL() { #getServerURL() {
return this.#config.serverURL || ''; return this.#config.serverURL || '';
} }

View File

@ -28,7 +28,7 @@ export class DocHandler {
this.observer = new Observable(); this.observer = new Observable();
} }
async purgeCache() { purgeCache() {
this.init(); this.init();
} }
@ -82,10 +82,10 @@ export class DocHandler {
getNewDoc( getNewDoc(
schemaName: string, schemaName: string,
data: DocValueMap | RawValueMap = {}, data: DocValueMap | RawValueMap = {},
cacheDoc: boolean = true, cacheDoc = true,
schema?: Schema, schema?: Schema,
Model?: typeof Doc, Model?: typeof Doc,
isRawValueMap: boolean = true isRawValueMap = true
): Doc { ): Doc {
if (!this.models[schemaName] && Model) { if (!this.models[schemaName] && Model) {
this.models[schemaName] = Model; this.models[schemaName] = Model;
@ -153,7 +153,7 @@ export class DocHandler {
// propagate change to `docs` // propagate change to `docs`
doc.on('change', (params: unknown) => { doc.on('change', (params: unknown) => {
this.docs!.trigger('change', params); this.docs.trigger('change', params);
}); });
doc.on('afterSync', () => { doc.on('afterSync', () => {

View File

@ -1,8 +1,8 @@
import { Doc } from 'fyo/model/doc'; import type { Doc } from 'fyo/model/doc';
import { Money } from 'pesa'; import type { Money } from 'pesa';
import { RawValue } from 'schemas/types'; import type { RawValue } from 'schemas/types';
import { AuthDemuxBase } from 'utils/auth/types'; import type { AuthDemuxBase } from 'utils/auth/types';
import { DatabaseDemuxBase } from 'utils/db/types'; import type { DatabaseDemuxBase } from 'utils/db/types';
export type Attachment = { name: string; type: string; data: string }; export type Attachment = { name: string; type: string; data: string };
export type DocValue = export type DocValue =
@ -31,12 +31,12 @@ export type DatabaseDemuxConstructor = new (
export type AuthDemuxConstructor = new (isElectron?: boolean) => AuthDemuxBase; export type AuthDemuxConstructor = new (isElectron?: boolean) => AuthDemuxBase;
export enum ConfigKeys { export type ConfigMap = {
Files = 'files', files: ConfigFile[];
LastSelectedFilePath = 'lastSelectedFilePath', lastSelectedFilePath: null | string;
Language = 'language', language: string
DeviceId = 'deviceId', deviceId: string
} };
export interface ConfigFile { export interface ConfigFile {
id: string; id: string;

View File

@ -1,11 +1,12 @@
import type Store from 'electron-store'; import type Store from 'electron-store';
import { ConfigMap } from 'fyo/core/types';
export class Config { export class Config {
config: Map<string, unknown> | Store; config: Map<string, unknown> | Store;
constructor(isElectron: boolean) { constructor(isElectron: boolean) {
this.config = new Map(); this.config = new Map();
if (isElectron) { if (isElectron) {
const Config: typeof Store = require('electron-store'); const Config = require('electron-store') as typeof Store;
this.config = new Config(); this.config = new Config();
} }
} }
@ -23,15 +24,19 @@ export class Config {
} }
} }
get(key: string, defaultValue?: unknown): unknown { get<K extends keyof ConfigMap>(
return this.config.get(key) ?? defaultValue; key: K,
defaultValue?: ConfigMap[K]
): ConfigMap[K] | undefined {
const value = this.config.get(key) as ConfigMap[K] | undefined;
return value ?? defaultValue;
} }
set(key: string, value: unknown) { set<K extends keyof ConfigMap>(key: K, value: ConfigMap[K]) {
this.config.set(key, value); this.config.set(key, value);
} }
delete(key: string) { delete(key: keyof ConfigMap) {
this.config.delete(key); this.config.delete(key);
} }

View File

@ -35,7 +35,7 @@ export class Fyo {
doc: DocHandler; doc: DocHandler;
db: DatabaseHandler; db: DatabaseHandler;
_initialized: boolean = false; _initialized = false;
errorLog: ErrorLog[] = []; errorLog: ErrorLog[] = [];
temp?: Record<string, unknown>; temp?: Record<string, unknown>;
@ -94,7 +94,7 @@ export class Fyo {
return format(value, field, doc ?? null, this); return format(value, field, doc ?? null, this);
} }
async setIsElectron() { setIsElectron() {
try { try {
this.isElectron = Boolean(require('electron')); this.isElectron = Boolean(require('electron'));
} catch { } catch {
@ -105,7 +105,7 @@ export class Fyo {
async initializeAndRegister( async initializeAndRegister(
models: ModelMap = {}, models: ModelMap = {},
regionalModels: ModelMap = {}, regionalModels: ModelMap = {},
force: boolean = false force = false
) { ) {
if (this._initialized && !force) return; if (this._initialized && !force) return;
@ -121,8 +121,8 @@ export class Fyo {
// temp params while calling routes // temp params while calling routes
this.temp = {}; this.temp = {};
await this.doc.init(); this.doc.init();
await this.auth.init(); this.auth.init();
await this.db.init(); await this.db.init();
} }
@ -189,14 +189,14 @@ export class Fyo {
let value: DocValue | Doc[]; let value: DocValue | Doc[];
try { try {
doc = await this.doc.getDoc(schemaName, name); doc = await this.doc.getDoc(schemaName, name);
value = doc.get(fieldname!); value = doc.get(fieldname);
} catch (err) { } catch (err) {
value = undefined; value = undefined;
} }
if (value === undefined && schemaName === name) { if (value === undefined && schemaName === name) {
const sv = await this.db.getSingleValues({ const sv = await this.db.getSingleValues({
fieldname: fieldname!, fieldname: fieldname,
parent: schemaName, parent: schemaName,
}); });
@ -221,8 +221,7 @@ export class Fyo {
this.errorLog = []; this.errorLog = [];
this.temp = {}; this.temp = {};
await this.db.purgeCache(); await this.db.purgeCache();
await this.auth.purgeCache(); this.doc.purgeCache();
await this.doc.purgeCache();
} }
store = { store = {

View File

@ -1,5 +1,4 @@
import { Fyo } from 'fyo'; import { Fyo } from 'fyo';
import { ConfigKeys } from 'fyo/core/types';
import { Noun, Telemetry, Verb } from './types'; import { Noun, Telemetry, Verb } from './types';
/** /**
@ -28,8 +27,8 @@ import { Noun, Telemetry, Verb } from './types';
*/ */
export class TelemetryManager { export class TelemetryManager {
#url: string = ''; #url = '';
#token: string = ''; #token = '';
#started = false; #started = false;
fyo: Fyo; fyo: Fyo;
@ -108,16 +107,12 @@ export class TelemetryManager {
noun: Noun, noun: Noun,
more?: Record<string, unknown> more?: Record<string, unknown>
): Telemetry { ): Telemetry {
const countryCode = this.fyo.singles.SystemSettings?.countryCode as const countryCode = this.fyo.singles.SystemSettings?.countryCode;
| string
| undefined;
return { return {
country: countryCode ?? '', country: countryCode ?? '',
language: this.fyo.store.language, language: this.fyo.store.language,
deviceId: deviceId:
this.fyo.store.deviceId || this.fyo.store.deviceId || (this.fyo.config.get('deviceId') ?? '-'),
(this.fyo.config.get(ConfigKeys.DeviceId) as string),
instanceId: this.fyo.store.instanceId, instanceId: this.fyo.store.instanceId,
version: this.fyo.store.appVersion, version: this.fyo.store.appVersion,
openCount: this.fyo.store.openCount, openCount: this.fyo.store.openCount,

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line
require('source-map-support').install({ require('source-map-support').install({
handleUncaughtException: false, handleUncaughtException: false,
environment: 'node', environment: 'node',
@ -22,10 +23,10 @@ import registerIpcMainMessageListeners from './main/registerIpcMainMessageListen
import registerProcessListeners from './main/registerProcessListeners'; import registerProcessListeners from './main/registerProcessListeners';
export class Main { export class Main {
title: string = 'Frappe Books'; title = 'Frappe Books';
icon: string; icon: string;
winURL: string = ''; winURL = '';
checkedForUpdate = false; checkedForUpdate = false;
mainWindow: BrowserWindow | null = null; mainWindow: BrowserWindow | null = null;
@ -130,9 +131,9 @@ export class Main {
this.registerAppProtocol(); this.registerAppProtocol();
} }
this.mainWindow!.loadURL(this.winURL); this.mainWindow.loadURL(this.winURL);
if (this.isDevelopment && !this.isTest) { if (this.isDevelopment && !this.isTest) {
this.mainWindow!.webContents.openDevTools(); this.mainWindow.webContents.openDevTools();
} }
this.setMainWindowListeners(); this.setMainWindowListeners();

View File

@ -4,6 +4,7 @@ import fetch from 'node-fetch';
import path from 'path'; import path from 'path';
import { Creds } from 'utils/types'; import { Creds } from 'utils/types';
import { rendererLog } from './helpers'; import { rendererLog } from './helpers';
import type { Main } from 'main';
export function getUrlAndTokenString(): Creds { export function getUrlAndTokenString(): Creds {
const inProduction = app.isPackaged; const inProduction = app.isPackaged;
@ -42,7 +43,7 @@ export function getUrlAndTokenString(): Creds {
}; };
} }
export async function sendError(body: string) { export async function sendError(body: string, main: Main) {
const { errorLogUrl, tokenString } = getUrlAndTokenString(); const { errorLogUrl, tokenString } = getUrlAndTokenString();
const headers = { const headers = {
Authorization: tokenString, Authorization: tokenString,
@ -51,6 +52,6 @@ export async function sendError(body: string) {
}; };
await fetch(errorLogUrl, { method: 'POST', headers, body }).catch((err) => { await fetch(errorLogUrl, { method: 'POST', headers, body }).catch((err) => {
rendererLog(err); rendererLog(main, err);
}); });
} }

View File

@ -16,8 +16,7 @@ import fs from 'fs/promises';
import path from 'path'; import path from 'path';
import { parseCSV } from 'utils/csvParser'; import { parseCSV } from 'utils/csvParser';
import { LanguageMap } from 'utils/types'; import { LanguageMap } from 'utils/types';
import fetch from 'node-fetch';
const fetch = require('node-fetch').default;
const VALENTINES_DAY = 1644796800000; const VALENTINES_DAY = 1644796800000;
@ -100,7 +99,7 @@ async function fetchContentsFromApi(code: string) {
return null; return null;
} }
const resJson = await res.json(); const resJson = (await res.json()) as { content: string };
return Buffer.from(resJson.content, 'base64').toString(); return Buffer.from(resJson.content, 'base64').toString();
} }
@ -138,7 +137,9 @@ async function getLastUpdated(code: string): Promise<Date> {
return new Date(VALENTINES_DAY); return new Date(VALENTINES_DAY);
} }
const resJson = await res.json(); const resJson = (await res.json()) as {
commit: { author: { date: string } };
}[];
try { try {
return new Date(resJson[0].commit.author.date); return new Date(resJson[0].commit.author.date);
} catch { } catch {
@ -187,7 +188,7 @@ async function storeFile(code: string, contents: string) {
async function errorHandledFetch(url: string) { async function errorHandledFetch(url: string) {
try { try {
return (await fetch(url)) as Response; return await fetch(url);
} catch { } catch {
return null; return null;
} }

View File

@ -1,6 +1,6 @@
import { constants } from 'fs'; import { constants } from 'fs';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { ConfigFile, ConfigKeys } from 'fyo/core/types'; import { ConfigFile } from 'fyo/core/types';
import { Main } from 'main'; import { Main } from 'main';
import config from 'utils/config'; import config from 'utils/config';
import { BackendResponse } from 'utils/ipc/types'; import { BackendResponse } from 'utils/ipc/types';
@ -8,7 +8,7 @@ import { IPC_CHANNELS } from 'utils/messages';
import type { ConfigFilesWithModified } from 'utils/types'; import type { ConfigFilesWithModified } from 'utils/types';
export async function setAndGetCleanedConfigFiles() { export async function setAndGetCleanedConfigFiles() {
const files = config.get(ConfigKeys.Files, []) as ConfigFile[]; const files = config.get('files', []);
const cleanedFileMap: Map<string, ConfigFile> = new Map(); const cleanedFileMap: Map<string, ConfigFile> = new Map();
for (const file of files) { for (const file of files) {
@ -30,7 +30,7 @@ export async function setAndGetCleanedConfigFiles() {
} }
const cleanedFiles = Array.from(cleanedFileMap.values()); const cleanedFiles = Array.from(cleanedFileMap.values());
config.set(ConfigKeys.Files, cleanedFiles); config.set('files', cleanedFiles);
return cleanedFiles; return cleanedFiles;
} }
@ -50,7 +50,9 @@ export async function getConfigFilesWithModified(files: ConfigFile[]) {
return filesWithModified; return filesWithModified;
} }
export async function getErrorHandledReponse(func: () => Promise<unknown>) { export async function getErrorHandledReponse(
func: () => Promise<unknown> | unknown
) {
const response: BackendResponse = {}; const response: BackendResponse = {};
try { try {

View File

@ -1,4 +1,11 @@
import { app, dialog, ipcMain } from 'electron'; import {
MessageBoxOptions,
OpenDialogOptions,
SaveDialogOptions,
app,
dialog,
ipcMain,
} from 'electron';
import { autoUpdater } from 'electron-updater'; import { autoUpdater } from 'electron-updater';
import fs from 'fs/promises'; import fs from 'fs/promises';
import path from 'path'; import path from 'path';
@ -20,39 +27,60 @@ import {
import { saveHtmlAsPdf } from './saveHtmlAsPdf'; import { saveHtmlAsPdf } from './saveHtmlAsPdf';
export default function registerIpcMainActionListeners(main: Main) { export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle(IPC_ACTIONS.GET_OPEN_FILEPATH, async (event, options) => { ipcMain.handle(
IPC_ACTIONS.GET_OPEN_FILEPATH,
async (_, options: OpenDialogOptions) => {
return await dialog.showOpenDialog(main.mainWindow!, options); return await dialog.showOpenDialog(main.mainWindow!, options);
}); }
);
ipcMain.handle(IPC_ACTIONS.GET_SAVE_FILEPATH, async (event, options) => { ipcMain.handle(
IPC_ACTIONS.GET_SAVE_FILEPATH,
async (_, options: SaveDialogOptions) => {
return await dialog.showSaveDialog(main.mainWindow!, options); return await dialog.showSaveDialog(main.mainWindow!, options);
}); }
);
ipcMain.handle(IPC_ACTIONS.GET_DIALOG_RESPONSE, async (event, options) => { ipcMain.handle(
IPC_ACTIONS.GET_DIALOG_RESPONSE,
async (_, options: MessageBoxOptions) => {
if (main.isDevelopment || main.isLinux) { if (main.isDevelopment || main.isLinux) {
Object.assign(options, { icon: main.icon }); Object.assign(options, { icon: main.icon });
} }
return await dialog.showMessageBox(main.mainWindow!, options); return await dialog.showMessageBox(main.mainWindow!, options);
}); }
);
ipcMain.handle(IPC_ACTIONS.SHOW_ERROR, async (event, { title, content }) => { ipcMain.handle(
return await dialog.showErrorBox(title, content); IPC_ACTIONS.SHOW_ERROR,
}); (_, { title, content }: { title: string; content: string }) => {
return dialog.showErrorBox(title, content);
}
);
ipcMain.handle( ipcMain.handle(
IPC_ACTIONS.SAVE_HTML_AS_PDF, IPC_ACTIONS.SAVE_HTML_AS_PDF,
async (event, html, savePath, width: number, height: number) => { async (
_,
html: string,
savePath: string,
width: number,
height: number
) => {
return await saveHtmlAsPdf(html, savePath, app, width, height); return await saveHtmlAsPdf(html, savePath, app, width, height);
} }
); );
ipcMain.handle(IPC_ACTIONS.SAVE_DATA, async (event, data, savePath) => { ipcMain.handle(
IPC_ACTIONS.SAVE_DATA,
async (_, data: string, savePath: string) => {
return await fs.writeFile(savePath, data, { encoding: 'utf-8' }); return await fs.writeFile(savePath, data, { encoding: 'utf-8' });
}); }
);
ipcMain.handle(IPC_ACTIONS.SEND_ERROR, (event, bodyJson) => { ipcMain.handle(IPC_ACTIONS.SEND_ERROR, (_, bodyJson: string) => {
sendError(bodyJson); sendError(bodyJson, main);
}); });
ipcMain.handle(IPC_ACTIONS.CHECK_FOR_UPDATES, async () => { ipcMain.handle(IPC_ACTIONS.CHECK_FOR_UPDATES, async () => {
@ -72,7 +100,7 @@ export default function registerIpcMainActionListeners(main: Main) {
main.checkedForUpdate = true; main.checkedForUpdate = true;
}); });
ipcMain.handle(IPC_ACTIONS.GET_LANGUAGE_MAP, async (event, code) => { ipcMain.handle(IPC_ACTIONS.GET_LANGUAGE_MAP, async (_, code: string) => {
const obj = { languageMap: {}, success: true, message: '' }; const obj = { languageMap: {}, success: true, message: '' };
try { try {
obj.languageMap = await getLanguageMap(code); obj.languageMap = await getLanguageMap(code);
@ -117,20 +145,20 @@ export default function registerIpcMainActionListeners(main: Main) {
} }
); );
ipcMain.handle(IPC_ACTIONS.GET_CREDS, async (event) => { ipcMain.handle(IPC_ACTIONS.GET_CREDS, () => {
return getUrlAndTokenString(); return getUrlAndTokenString();
}); });
ipcMain.handle(IPC_ACTIONS.DELETE_FILE, async (_, filePath) => { ipcMain.handle(IPC_ACTIONS.DELETE_FILE, async (_, filePath: string) => {
return getErrorHandledReponse(async () => await fs.unlink(filePath)); return getErrorHandledReponse(async () => await fs.unlink(filePath));
}); });
ipcMain.handle(IPC_ACTIONS.GET_DB_LIST, async (_) => { ipcMain.handle(IPC_ACTIONS.GET_DB_LIST, async () => {
const files = await setAndGetCleanedConfigFiles(); const files = await setAndGetCleanedConfigFiles();
return await getConfigFilesWithModified(files); return await getConfigFilesWithModified(files);
}); });
ipcMain.handle(IPC_ACTIONS.GET_ENV, async (_) => { ipcMain.handle(IPC_ACTIONS.GET_ENV, () => {
return { return {
isDevelopment: main.isDevelopment, isDevelopment: main.isDevelopment,
platform: process.platform, platform: process.platform,
@ -149,7 +177,7 @@ export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle( ipcMain.handle(
IPC_ACTIONS.DB_CREATE, IPC_ACTIONS.DB_CREATE,
async (_, dbPath: string, countryCode: string) => { async (_, dbPath: string, countryCode: string) => {
return await getErrorHandledReponse(async function dbFunc() { return await getErrorHandledReponse(async () => {
return await databaseManager.createNewDatabase(dbPath, countryCode); return await databaseManager.createNewDatabase(dbPath, countryCode);
}); });
} }
@ -158,7 +186,7 @@ export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle( ipcMain.handle(
IPC_ACTIONS.DB_CONNECT, IPC_ACTIONS.DB_CONNECT,
async (_, dbPath: string, countryCode?: string) => { async (_, dbPath: string, countryCode?: string) => {
return await getErrorHandledReponse(async function dbFunc() { return await getErrorHandledReponse(async () => {
return await databaseManager.connectToDatabase(dbPath, countryCode); return await databaseManager.connectToDatabase(dbPath, countryCode);
}); });
} }
@ -167,7 +195,7 @@ export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle( ipcMain.handle(
IPC_ACTIONS.DB_CALL, IPC_ACTIONS.DB_CALL,
async (_, method: DatabaseMethod, ...args: unknown[]) => { async (_, method: DatabaseMethod, ...args: unknown[]) => {
return await getErrorHandledReponse(async function dbFunc() { return await getErrorHandledReponse(async () => {
return await databaseManager.call(method, ...args); return await databaseManager.call(method, ...args);
}); });
} }
@ -176,15 +204,15 @@ export default function registerIpcMainActionListeners(main: Main) {
ipcMain.handle( ipcMain.handle(
IPC_ACTIONS.DB_BESPOKE, IPC_ACTIONS.DB_BESPOKE,
async (_, method: string, ...args: unknown[]) => { async (_, method: string, ...args: unknown[]) => {
return await getErrorHandledReponse(async function dbFunc() { return await getErrorHandledReponse(async () => {
return await databaseManager.callBespoke(method, ...args); return await databaseManager.callBespoke(method, ...args);
}); });
} }
); );
ipcMain.handle(IPC_ACTIONS.DB_SCHEMA, async (_) => { ipcMain.handle(IPC_ACTIONS.DB_SCHEMA, async () => {
return await getErrorHandledReponse(async function dbFunc() { return await getErrorHandledReponse(() => {
return await databaseManager.getSchemaMap(); return databaseManager.getSchemaMap();
}); });
}); });
} }

View File

@ -20,11 +20,11 @@ export default function registerIpcMainMessageListeners(main: Main) {
main.mainWindow!.reload(); main.mainWindow!.reload();
}); });
ipcMain.on(IPC_MESSAGES.OPEN_EXTERNAL, (_, link) => { ipcMain.on(IPC_MESSAGES.OPEN_EXTERNAL, (_, link: string) => {
shell.openExternal(link); shell.openExternal(link);
}); });
ipcMain.on(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, (_, filePath) => { ipcMain.on(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, (_, filePath: string) => {
return shell.showItemInFolder(filePath); return shell.showItemInFolder(filePath);
}); });
} }

View File

@ -36,7 +36,6 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ConfigKeys } from 'fyo/core/types';
import { RTL_LANGUAGES } from 'fyo/utils/consts'; import { RTL_LANGUAGES } from 'fyo/utils/consts';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { systemLanguageRef } from 'src/utils/refs'; import { systemLanguageRef } from 'src/utils/refs';
@ -126,10 +125,7 @@ export default defineComponent({
}, },
methods: { methods: {
async setInitialScreen(): Promise<void> { async setInitialScreen(): Promise<void> {
const lastSelectedFilePath = fyo.config.get( const lastSelectedFilePath = fyo.config.get('lastSelectedFilePath', null);
ConfigKeys.LastSelectedFilePath,
null
);
if ( if (
typeof lastSelectedFilePath !== 'string' || typeof lastSelectedFilePath !== 'string' ||
@ -159,7 +155,7 @@ export default defineComponent({
updateConfigFiles(fyo); updateConfigFiles(fyo);
}, },
async fileSelected(filePath: string, isNew?: boolean): Promise<void> { async fileSelected(filePath: string, isNew?: boolean): Promise<void> {
fyo.config.set(ConfigKeys.LastSelectedFilePath, filePath); fyo.config.set('lastSelectedFilePath', filePath);
if (isNew) { if (isNew) {
this.activeScreen = Screen.SetupWizard; this.activeScreen = Screen.SetupWizard;
return; return;
@ -173,7 +169,7 @@ export default defineComponent({
} }
}, },
async setupComplete(setupWizardOptions: SetupWizardOptions): Promise<void> { async setupComplete(setupWizardOptions: SetupWizardOptions): Promise<void> {
const filePath = fyo.config.get(ConfigKeys.LastSelectedFilePath); const filePath = fyo.config.get('lastSelectedFilePath');
if (typeof filePath !== 'string') { if (typeof filePath !== 'string') {
return; return;
} }

View File

@ -1,5 +1,4 @@
import { t } from 'fyo'; import { t } from 'fyo';
import { ConfigKeys } from 'fyo/core/types';
import { Doc } from 'fyo/model/doc'; import { Doc } from 'fyo/model/doc';
import { BaseError } from 'fyo/utils/errors'; import { BaseError } from 'fyo/utils/errors';
import { ErrorLog } from 'fyo/utils/types'; import { ErrorLog } from 'fyo/utils/types';
@ -10,6 +9,7 @@ import { fyo } from './initFyo';
import router from './router'; import router from './router';
import { getErrorMessage, stringifyCircular } from './utils'; import { getErrorMessage, stringifyCircular } from './utils';
import { DialogOptions, ToastOptions } from './utils/types'; import { DialogOptions, ToastOptions } from './utils/types';
import { UnknownFunction } from 'utils/types';
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron');
function shouldNotStore(error: Error) { function shouldNotStore(error: Error) {
@ -23,7 +23,7 @@ export async function sendError(errorLogObj: ErrorLog) {
} }
errorLogObj.more ??= {}; errorLogObj.more ??= {};
errorLogObj.more!.path ??= router.currentRoute.value.fullPath; errorLogObj.more.path ??= router.currentRoute.value.fullPath;
const body = { const body = {
error_name: errorLogObj.name, error_name: errorLogObj.name,
@ -77,7 +77,7 @@ export async function handleError(
logToConsole: boolean, logToConsole: boolean,
error: Error, error: Error,
more: Record<string, unknown> = {}, more: Record<string, unknown> = {},
notifyUser: boolean = true notifyUser = true
) { ) {
if (logToConsole) { if (logToConsole) {
console.error(error); console.error(error);
@ -127,7 +127,13 @@ export async function handleErrorWithDialog(
}, },
isPrimary: true, isPrimary: true,
}, },
{ label: t`Cancel`, action() {}, isEscape: true }, {
label: t`Cancel`,
action() {
return null;
},
isEscape: true,
},
]; ];
} }
@ -152,7 +158,7 @@ export async function showErrorDialog(title?: string, content?: string) {
// Wrapper Functions // Wrapper Functions
export function getErrorHandled(func: Function) { export function getErrorHandled(func: UnknownFunction) {
return async function errorHandled(...args: unknown[]) { return async function errorHandled(...args: unknown[]) {
try { try {
return await func(...args); return await func(...args);
@ -167,7 +173,7 @@ export function getErrorHandled(func: Function) {
}; };
} }
export function getErrorHandledSync(func: Function) { export function getErrorHandledSync(func: UnknownFunction) {
return function errorHandledSync(...args: unknown[]) { return function errorHandledSync(...args: unknown[]) {
try { try {
return func(...args); return func(...args);
@ -208,7 +214,7 @@ function getIssueUrlQuery(errorLogObj?: ErrorLog): string {
body.push(`**Platform**: \`${fyo.store.platform}\``); body.push(`**Platform**: \`${fyo.store.platform}\``);
body.push(`**Path**: \`${router.currentRoute.value.fullPath}\``); body.push(`**Path**: \`${router.currentRoute.value.fullPath}\``);
body.push(`**Language**: \`${fyo.config.get(ConfigKeys.Language)}\``); body.push(`**Language**: \`${fyo.config.get('language') ?? '-'}\``);
if (fyo.singles.SystemSettings?.countryCode) { if (fyo.singles.SystemSettings?.countryCode) {
body.push(`**Country**: \`${fyo.singles.SystemSettings.countryCode}\``); body.push(`**Country**: \`${fyo.singles.SystemSettings.countryCode}\``);
} }

View File

@ -117,7 +117,7 @@ export class Importer {
this.templateFieldsMap = new Map(); this.templateFieldsMap = new Map();
this.templateFieldsPicked = new Map(); this.templateFieldsPicked = new Map();
templateFields.forEach((f, i) => { templateFields.forEach((f) => {
this.templateFieldsMap.set(f.fieldKey, f); this.templateFieldsMap.set(f.fieldKey, f);
this.templateFieldsPicked.set(f.fieldKey, true); this.templateFieldsPicked.set(f.fieldKey, true);
}); });

View File

@ -214,7 +214,6 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { setupDummyInstance } from 'dummy'; import { setupDummyInstance } from 'dummy';
const { ipcRenderer } = require('electron');
import { t } from 'fyo'; import { t } from 'fyo';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import Button from 'src/components/Button.vue'; import Button from 'src/components/Button.vue';
@ -224,11 +223,12 @@ import Loading from 'src/components/Loading.vue';
import Modal from 'src/components/Modal.vue'; import Modal from 'src/components/Modal.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { showDialog } from 'src/utils/interactive'; import { showDialog } from 'src/utils/interactive';
import { deleteDb, getSavePath } from 'src/utils/ipcCalls'; import { deleteDb, getSavePath, getSelectedFilePath } from 'src/utils/ipcCalls';
import { updateConfigFiles } from 'src/utils/misc'; import { updateConfigFiles } from 'src/utils/misc';
import { IPC_ACTIONS } from 'utils/messages'; import { IPC_ACTIONS } from 'utils/messages';
import type { ConfigFilesWithModified } from 'utils/types'; import type { ConfigFilesWithModified } from 'utils/types';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
const { ipcRenderer } = require('electron');
export default defineComponent({ export default defineComponent({
name: 'DatabaseSelector', name: 'DatabaseSelector',
@ -353,13 +353,7 @@ export default defineComponent({
return; return;
} }
const filePath = ( const filePath = (await getSelectedFilePath())?.filePaths?.[0];
await ipcRenderer.invoke(IPC_ACTIONS.GET_OPEN_FILEPATH, {
title: this.t`Select file`,
properties: ['openFile'],
filters: [{ name: 'SQLite DB File', extensions: ['db'] }],
})
)?.filePaths?.[0];
this.emitFileSelected(filePath); this.emitFileSelected(filePath);
}, },
async selectFile(file: ConfigFilesWithModified) { async selectFile(file: ConfigFilesWithModified) {

View File

@ -1,5 +1,4 @@
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron');
import { ConfigKeys } from 'fyo/core/types';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { CUSTOM_EVENTS, IPC_ACTIONS } from 'utils/messages'; import { CUSTOM_EVENTS, IPC_ACTIONS } from 'utils/messages';
import { UnexpectedLogObject } from 'utils/types'; import { UnexpectedLogObject } from 'utils/types';
@ -16,7 +15,7 @@ import { stringifyCircular } from './utils';
import { setLanguageMap } from './utils/language'; import { setLanguageMap } from './utils/language';
(async () => { (async () => {
const language = fyo.config.get(ConfigKeys.Language) as string; const language = fyo.config.get('language') as string;
if (language) { if (language) {
await setLanguageMap(language); await setLanguageMap(language);
} }
@ -74,7 +73,13 @@ function setErrorHandlers(app: VueApp) {
}; };
window.onunhandledrejection = (event: PromiseRejectionEvent) => { window.onunhandledrejection = (event: PromiseRejectionEvent) => {
const error = event.reason; let error: Error;
if (event.reason instanceof Error) {
error = event.reason;
} else {
error = new Error(String(event.reason));
}
handleError(true, error).catch((err) => console.error(err)); handleError(true, error).catch((err) => console.error(err));
}; };

View File

@ -36,7 +36,7 @@ export default function registerIpcRendererListeners() {
} }
}); });
document.addEventListener('visibilitychange', function () { document.addEventListener('visibilitychange', () => {
const { visibilityState } = document; const { visibilityState } = document;
if (visibilityState === 'visible' && !fyo.telemetry.started) { if (visibilityState === 'visible' && !fyo.telemetry.started) {
fyo.telemetry.start(); fyo.telemetry.start();

View File

@ -12,6 +12,7 @@ import Settings from 'src/pages/Settings/Settings.vue';
import TemplateBuilder from 'src/pages/TemplateBuilder/TemplateBuilder.vue'; import TemplateBuilder from 'src/pages/TemplateBuilder/TemplateBuilder.vue';
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import { historyState } from './utils/refs'; import { historyState } from './utils/refs';
import type { HistoryState } from 'vue-router';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
{ {
@ -122,8 +123,9 @@ const routes: RouteRecordRaw[] = [
const router = createRouter({ routes, history: createWebHistory() }); const router = createRouter({ routes, history: createWebHistory() });
router.afterEach(() => { router.afterEach(() => {
historyState.forward = !!history.state?.forward; const state = history.state as HistoryState;
historyState.back = !!history.state?.back; historyState.forward = !!state.forward;
historyState.back = !!state.back;
}); });
export default router; export default router;

View File

@ -262,7 +262,7 @@ async function checkAndCreateDoc(
return; return;
} }
const doc = await fyo.doc.getNewDoc(schemaName, docObject); const doc = fyo.doc.getNewDoc(schemaName, docObject);
return doc.sync(); return doc.sync();
} }

4
src/shims-tsx.d.ts vendored
View File

@ -3,9 +3,9 @@ import Vue, { VNode } from 'vue'
declare global { declare global {
namespace JSX { namespace JSX {
// tslint:disable no-empty-interface // tslint:disable no-empty-interface
interface Element extends VNode {} type Element = VNode
// tslint:disable no-empty-interface // tslint:disable no-empty-interface
interface ElementClass extends Vue {} type ElementClass = Vue
interface IntrinsicElements { interface IntrinsicElements {
[elem: string]: any [elem: string]: any
} }

View File

@ -37,7 +37,7 @@ function evaluateFieldMeta(
field: Field, field: Field,
doc?: Doc, doc?: Doc,
meta?: 'required' | 'hidden' | 'readOnly', meta?: 'required' | 'hidden' | 'readOnly',
defaultValue: boolean = false defaultValue = false
) { ) {
if (meta === undefined) { if (meta === undefined) {
return defaultValue; return defaultValue;

View File

@ -118,7 +118,7 @@ export async function getCsvExportData(
const tableFieldRowMap = parentNameMap[parentName]; const tableFieldRowMap = parentNameMap[parentName];
if (!tableFieldRowMap || !Object.keys(tableFieldRowMap ?? {}).length) { if (!tableFieldRowMap || !Object.keys(tableFieldRowMap ?? {}).length) {
rows.push([baseRowData, headers.child.map((_) => '')].flat()); rows.push([baseRowData, headers.child.map(() => '')].flat());
continue; continue;
} }

View File

@ -14,8 +14,8 @@ import { fyo } from 'src/initFyo';
export function stringifyCircular( export function stringifyCircular(
obj: unknown, obj: unknown,
ignoreCircular: boolean = false, ignoreCircular = false,
convertDocument: boolean = false convertDocument = false
) { ) {
const cacheKey: string[] = []; const cacheKey: string[] = [];
const cacheValue: unknown[] = []; const cacheValue: unknown[] = [];

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo'; import { Fyo } from 'fyo';
import { ConfigFile, ConfigKeys } from 'fyo/core/types'; import { ConfigFile } from 'fyo/core/types';
import { getRegionalModels, models } from 'models/index'; import { getRegionalModels, models } from 'models/index';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { TargetField } from 'schemas/types'; import { TargetField } from 'schemas/types';
@ -68,7 +68,7 @@ async function checkSingleLinks(fyo: Fyo) {
.flat() .flat()
.filter((field) => field.fieldtype === 'Link' && field.target) .filter((field) => field.fieldtype === 'Link' && field.target)
.map((field) => ({ .map((field) => ({
fieldKey: `${field.schemaName}.${field.fieldname}`, fieldKey: `${field.schemaName!}.${field.fieldname}`,
target: (field as TargetField).target, target: (field as TargetField).target,
})); }));
const linkFieldsMap = getMapFromList(linkFields, 'fieldKey'); const linkFieldsMap = getMapFromList(linkFields, 'fieldKey');
@ -126,10 +126,10 @@ async function setVersion(fyo: Fyo) {
} }
function setDeviceId(fyo: Fyo) { function setDeviceId(fyo: Fyo) {
let deviceId = fyo.config.get(ConfigKeys.DeviceId) as string | undefined; let deviceId = fyo.config.get('deviceId');
if (deviceId === undefined) { if (deviceId === undefined) {
deviceId = getRandomString(); deviceId = getRandomString();
fyo.config.set(ConfigKeys.DeviceId, deviceId); fyo.config.set('deviceId', deviceId);
} }
fyo.store.deviceId = deviceId; fyo.store.deviceId = deviceId;
@ -176,7 +176,7 @@ async function setOpenCount(fyo: Fyo) {
} }
function getOpenCountFromFiles(fyo: Fyo) { function getOpenCountFromFiles(fyo: Fyo) {
const configFile = fyo.config.get(ConfigKeys.Files, []) as ConfigFile[]; const configFile = fyo.config.get('files', []) as ConfigFile[];
for (const file of configFile) { for (const file of configFile) {
if (file.id === fyo.singles.SystemSettings?.instanceId) { if (file.id === fyo.singles.SystemSettings?.instanceId) {
return file.openCount ?? 0; return file.openCount ?? 0;

View File

@ -13,7 +13,7 @@ type DialogReturn<DO extends DialogOptions> = DO['buttons'] extends {
export async function showDialog<DO extends DialogOptions>(options: DO) { export async function showDialog<DO extends DialogOptions>(options: DO) {
const preWrappedButtons: DialogButton[] = options.buttons ?? [ const preWrappedButtons: DialogButton[] = options.buttons ?? [
{ label: t`Okay`, action: () => {}, isEscape: true }, { label: t`Okay`, action: () => null, isEscape: true },
]; ];
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {

View File

@ -9,11 +9,20 @@ import { IPC_ACTIONS, IPC_MESSAGES } from 'utils/messages';
import { SelectFileOptions, SelectFileReturn, TemplateFile } from 'utils/types'; import { SelectFileOptions, SelectFileReturn, TemplateFile } from 'utils/types';
import { showDialog, showToast } from './interactive'; import { showDialog, showToast } from './interactive';
import { setLanguageMap } from './language'; import { setLanguageMap } from './language';
import type { OpenDialogReturnValue } from 'electron';
export function reloadWindow() { export function reloadWindow() {
return ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW); return ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
} }
export async function getSelectedFilePath(): Promise<OpenDialogReturnValue> {
return await ipcRenderer.invoke(IPC_ACTIONS.GET_OPEN_FILEPATH, {
title: this.t`Select file`,
properties: ['openFile'],
filters: [{ name: 'SQLite DB File', extensions: ['db'] }],
});
}
export async function getTemplates(): Promise<TemplateFile[]> { export async function getTemplates(): Promise<TemplateFile[]> {
return await ipcRenderer.invoke(IPC_ACTIONS.GET_TEMPLATES); return await ipcRenderer.invoke(IPC_ACTIONS.GET_TEMPLATES);
} }

View File

@ -25,7 +25,7 @@ export const languageCodeMap: Record<string, string> = {
export async function setLanguageMap( export async function setLanguageMap(
initLanguage?: string, initLanguage?: string,
dontReload: boolean = false dontReload = false
) { ) {
const oldLanguage = fyo.config.get('language') as string; const oldLanguage = fyo.config.get('language') as string;
initLanguage ??= oldLanguage; initLanguage ??= oldLanguage;

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo'; import { Fyo } from 'fyo';
import { ConfigFile, ConfigKeys } from 'fyo/core/types'; import { ConfigFile } from 'fyo/core/types';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { SetupWizard } from 'models/baseModels/SetupWizard/SetupWizard'; import { SetupWizard } from 'models/baseModels/SetupWizard/SetupWizard';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
@ -64,7 +64,7 @@ export function getSetupWizardDoc() {
} }
export function updateConfigFiles(fyo: Fyo): ConfigFile { export function updateConfigFiles(fyo: Fyo): ConfigFile {
const configFiles = fyo.config.get(ConfigKeys.Files, []) as ConfigFile[]; const configFiles = fyo.config.get('files', []) as ConfigFile[];
const companyName = fyo.singles.AccountingSettings!.companyName as string; const companyName = fyo.singles.AccountingSettings!.companyName as string;
const id = fyo.singles.SystemSettings!.instanceId as string; const id = fyo.singles.SystemSettings!.instanceId as string;
@ -83,7 +83,7 @@ export function updateConfigFiles(fyo: Fyo): ConfigFile {
newFile = configFiles[fileIndex]; newFile = configFiles[fileIndex];
} }
fyo.config.set(ConfigKeys.Files, configFiles); fyo.config.set('files', configFiles);
return newFile; return newFile;
} }

View File

@ -93,11 +93,12 @@ export function getPrintTemplatePropHints(schemaName: string, fyo: Fyo) {
} }
function showHSN(doc: Doc): boolean { function showHSN(doc: Doc): boolean {
if (!Array.isArray(doc.items)) { const items = doc.items;
if (!Array.isArray(items)) {
return false; return false;
} }
return doc.items.map((i) => i.hsnCode).every(Boolean); return items.map((i: Doc) => i.hsnCode).every(Boolean);
} }
function formattedTotalDiscount(doc: Doc): string { function formattedTotalDiscount(doc: Doc): string {
@ -246,15 +247,14 @@ function constructPrintDocument(innerHTML: string) {
} }
function getAllCSSAsStyleElem() { function getAllCSSAsStyleElem() {
const cssTexts = []; const cssTexts: string[] = [];
for (const sheet of document.styleSheets) { for (const sheet of document.styleSheets) {
for (const rule of sheet.cssRules) { for (const rule of sheet.cssRules) {
cssTexts.push(rule.cssText); cssTexts.push(rule.cssText);
} }
// @ts-ignore if (sheet.ownerRule) {
for (const rule of sheet.ownerRule ?? []) { cssTexts.push(sheet.ownerRule.cssText);
cssTexts.push(rule.cssText);
} }
} }

View File

@ -1,9 +1,10 @@
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import type { HistoryState } from 'vue-router';
export const showSidebar = ref(true); export const showSidebar = ref(true);
export const docsPathRef = ref<string>(''); export const docsPathRef = ref<string>('');
export const systemLanguageRef = ref<string>(''); export const systemLanguageRef = ref<string>('');
export const historyState = reactive({ export const historyState = reactive({
forward: !!history.state?.forward, forward: !!(history.state as HistoryState)?.forward,
back: !!history.state?.back, back: !!(history.state as HistoryState)?.back,
}); });

View File

@ -346,8 +346,8 @@ export class Search {
* - Marked indices are rebuilt when the modal is opened. * - Marked indices are rebuilt when the modal is opened.
*/ */
_obsSet: boolean = false; _obsSet = false;
numSearches: number = 0; numSearches = 0;
searchables: Record<string, Searchable>; searchables: Record<string, Searchable>;
keywords: Record<string, Keyword[]>; keywords: Record<string, Keyword[]>;
priorityMap: Record<string, number> = { priorityMap: Record<string, number> = {
@ -707,7 +707,7 @@ export class Search {
_getDocSearchItemFromKeyword(keyword: Keyword): DocSearchItem { _getDocSearchItemFromKeyword(keyword: Keyword): DocSearchItem {
const schemaName = keyword.meta.schemaName as string; const schemaName = keyword.meta.schemaName as string;
const schemaLabel = this.fyo.schemaMap[schemaName]?.label!; const schemaLabel = this.fyo.schemaMap[schemaName]?.label ?? schemaName;
const route = this._getRouteFromKeyword(keyword); const route = this._getRouteFromKeyword(keyword);
return { return {
label: keyword.values[0], label: keyword.values[0],

View File

@ -12,7 +12,7 @@ interface ModMap {
type Mod = keyof ModMap; type Mod = keyof ModMap;
type Context = unknown; type Context = unknown;
type ShortcutFunction = () => void; type ShortcutFunction = () => unknown;
type ShortcutConfig = { type ShortcutConfig = {
callback: ShortcutFunction; callback: ShortcutFunction;
propagate: boolean; propagate: boolean;
@ -117,8 +117,8 @@ export class Shortcuts {
context: Context, context: Context,
shortcut: string[], shortcut: string[],
callback: ShortcutFunction, callback: ShortcutFunction,
propagate: boolean = false, propagate = false,
removeIfSet: boolean = true removeIfSet = true
): void { ): void {
const key = this.getKey(shortcut); const key = this.getKey(shortcut);
if (!key) { if (!key) {

View File

@ -3,8 +3,8 @@ import { routeFilters } from 'src/utils/filters';
import { fyo } from '../initFyo'; import { fyo } from '../initFyo';
import { SidebarConfig, SidebarItem, SidebarRoot } from './types'; import { SidebarConfig, SidebarItem, SidebarRoot } from './types';
export async function getSidebarConfig(): Promise<SidebarConfig> { export function getSidebarConfig(): SidebarConfig {
const sideBar = await getCompleteSidebar(); const sideBar = getCompleteSidebar();
return getFilteredSidebar(sideBar); return getFilteredSidebar(sideBar);
} }
@ -54,7 +54,7 @@ function getRegionalSidebar(): SidebarRoot[] {
]; ];
} }
async function getInventorySidebar(): Promise<SidebarRoot[]> { function getInventorySidebar(): SidebarRoot[] {
const hasInventory = !!fyo.singles.AccountingSettings?.enableInventory; const hasInventory = !!fyo.singles.AccountingSettings?.enableInventory;
if (!hasInventory) { if (!hasInventory) {
return []; return [];
@ -101,7 +101,7 @@ async function getInventorySidebar(): Promise<SidebarRoot[]> {
]; ];
} }
async function getReportSidebar() { function getReportSidebar() {
return { return {
label: t`Reports`, label: t`Reports`,
name: 'reports', name: 'reports',
@ -132,7 +132,7 @@ async function getReportSidebar() {
}; };
} }
async function getCompleteSidebar(): Promise<SidebarConfig> { function getCompleteSidebar(): SidebarConfig {
return [ return [
{ {
label: t`Get Started`, label: t`Get Started`,
@ -141,7 +141,7 @@ async function getCompleteSidebar(): Promise<SidebarConfig> {
icon: 'general', icon: 'general',
iconSize: '24', iconSize: '24',
iconHeight: 5, iconHeight: 5,
hidden: () => fyo.singles.SystemSettings!.hideGetStarted as boolean, hidden: () => !!fyo.singles.SystemSettings?.hideGetStarted,
}, },
{ {
label: t`Dashboard`, label: t`Dashboard`,
@ -254,9 +254,9 @@ async function getCompleteSidebar(): Promise<SidebarConfig> {
}, },
] as SidebarItem[], ] as SidebarItem[],
}, },
await getReportSidebar(), getReportSidebar(),
await getInventorySidebar(), getInventorySidebar(),
await getRegionalSidebar(), getRegionalSidebar(),
{ {
label: t`Setup`, label: t`Setup`,
name: 'setup', name: 'setup',

View File

@ -90,7 +90,7 @@ export type ActionGroup = {
export type DropdownItem = { export type DropdownItem = {
label: string; label: string;
value?: string; value?: string;
action?: Function; action?: () => unknown;
group?: string; group?: string;
component?: { template: string }; component?: { template: string };
isGroup?: boolean; isGroup?: boolean;

View File

@ -386,7 +386,7 @@ export function toggleSidebar(value?: boolean) {
export function focusOrSelectFormControl( export function focusOrSelectFormControl(
doc: Doc, doc: Doc,
ref: any, ref: any,
clear: boolean = true clear= true
) { ) {
if (!doc?.fyo) { if (!doc?.fyo) {
return; return;
@ -507,7 +507,7 @@ export async function commonDocCancel(doc: Doc): Promise<boolean> {
export async function commonDocSync( export async function commonDocSync(
doc: Doc, doc: Doc,
useDialog: boolean = false useDialog = false
): Promise<boolean> { ): Promise<boolean> {
let success: boolean; let success: boolean;
if (useDialog) { if (useDialog) {

View File

@ -100,7 +100,7 @@ export function useDocShortcuts(
shortcuts: Shortcuts, shortcuts: Shortcuts,
docRef: DocRef, docRef: DocRef,
name: string, name: string,
isMultiple: boolean = true isMultiple = true
) { ) {
let context = name; let context = name;
if (isMultiple) { if (isMultiple) {

View File

@ -1,4 +1,5 @@
import Store from 'electron-store'; import Store from 'electron-store';
import type { ConfigMap } from 'fyo/core/types';
const config = new Store(); const config = new Store<ConfigMap>();
export default config; export default config;

View File

@ -1,8 +1,9 @@
import type { ConfigFile } from "fyo/core/types"; import type { ConfigFile } from 'fyo/core/types';
export type UnknownMap = Record<string, unknown>; export type UnknownMap = Record<string, unknown>;
export type Translation = { translation: string; context?: string }; export type Translation = { translation: string; context?: string };
export type LanguageMap = Record<string, Translation>; export type LanguageMap = Record<string, Translation>;
export type UnknownFunction = (...args: unknown[]) => unknown;
export type CountryInfoMap = Record<string, CountryInfo | undefined>; export type CountryInfoMap = Record<string, CountryInfo | undefined>;
export interface CountryInfo { export interface CountryInfo {