fix: git worker uncatched error, and untranslated error message

Uncached: Observable.error from worker to main can't be catch, don't know why. Even add try catch around them, will still get uncatched error from electron-unhaldled. Maybe thread.js observable error halder have bug

untranslated error message: Error passing from worker thread to main, will loose its type. Because threads plugin will seriailize it and deserialize back
This commit is contained in:
linonetwo 2023-05-19 17:03:34 +08:00
parent 275e18cc77
commit 5ee2f583aa
7 changed files with 121 additions and 63 deletions

View file

@ -33,7 +33,6 @@ module.exports = {
}, },
}, },
rules: { rules: {
'no-use-before-define': ['error', { functions: false }],
'unicorn/prevent-abbreviations': [ 'unicorn/prevent-abbreviations': [
'error', 'error',
{ {
@ -94,9 +93,10 @@ module.exports = {
'unicorn/consistent-function-scoping': [0], 'unicorn/consistent-function-scoping': [0],
'no-void': [0], 'no-void': [0],
'unicorn/prefer-ternary': 'off', 'unicorn/prefer-ternary': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
semi: [0], semi: [0],
'@typescript-eslint/no-use-before-define': [1],
'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': ['warn', { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' }], 'unused-imports/no-unused-vars': ['warn', { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' }],
'dprint-integration/dprint': [ 'dprint-integration/dprint': [

View file

@ -42,7 +42,7 @@
"electron-window-state": "5.0.3", "electron-window-state": "5.0.3",
"errio": "1.2.2", "errio": "1.2.2",
"fs-extra": "11.1.1", "fs-extra": "11.1.1",
"git-sync-js": "^1.0.4", "git-sync-js": "^1.0.5",
"i18next": "22.5.0", "i18next": "22.5.0",
"i18next-electron-fs-backend": "3.0.0", "i18next-electron-fs-backend": "3.0.0",
"i18next-fs-backend": "2.1.2", "i18next-fs-backend": "2.1.2",

26
pnpm-lock.yaml generated
View file

@ -47,8 +47,8 @@ dependencies:
specifier: 11.1.1 specifier: 11.1.1
version: 11.1.1 version: 11.1.1
git-sync-js: git-sync-js:
specifier: ^1.0.4 specifier: ^1.0.5
version: 1.0.4 version: 1.0.5
i18next: i18next:
specifier: 22.5.0 specifier: 22.5.0
version: 22.5.0 version: 22.5.0
@ -3962,7 +3962,7 @@ packages:
dev: true dev: true
/checksum@0.1.1: /checksum@0.1.1:
resolution: {integrity: sha1-3GUn1MkL6FYNvR7Uzs8yl9Uo6ek=} resolution: {integrity: sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g==}
hasBin: true hasBin: true
dependencies: dependencies:
optimist: 0.3.7 optimist: 0.3.7
@ -4565,7 +4565,7 @@ packages:
optional: true optional: true
/decompress-response@3.3.0: /decompress-response@3.3.0:
resolution: {integrity: sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=} resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==}
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
mimic-response: 1.0.1 mimic-response: 1.0.1
@ -4706,7 +4706,7 @@ packages:
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
/diff3@0.0.3: /diff3@0.0.3:
resolution: {integrity: sha1-1OXDpM305f4SEatC5pP8tDIVgPw=} resolution: {integrity: sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==}
dev: false dev: false
/diff@4.0.2: /diff@4.0.2:
@ -6431,8 +6431,8 @@ packages:
omggif: 1.0.10 omggif: 1.0.10
dev: false dev: false
/git-sync-js@1.0.4: /git-sync-js@1.0.5:
resolution: {integrity: sha512-twAkhJH0HXfpIMLAYLy9msM6p+Cy93yy5fqmXPqYVjWfPF9eUYlhw9BUPsEiQy5fIEpIIHSO9DrF40a6KCKnEw==} resolution: {integrity: sha512-Y+YZCPvbj4rIUh2+KN26UGC/2Gi53DvruW82M5fZRUK4hG4y3tsamyB4zbSNmalaG952J87MeW+YhxUUkHqffA==}
dependencies: dependencies:
dugite: 1.110.0 dugite: 1.110.0
fs-extra: 10.1.0 fs-extra: 10.1.0
@ -7410,7 +7410,7 @@ packages:
dev: true dev: true
/json-buffer@3.0.0: /json-buffer@3.0.0:
resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==}
dev: false dev: false
/json-buffer@3.0.1: /json-buffer@3.0.1:
@ -8597,7 +8597,7 @@ packages:
dev: true dev: true
/optimist@0.3.7: /optimist@0.3.7:
resolution: {integrity: sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=} resolution: {integrity: sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==}
dependencies: dependencies:
wordwrap: 0.0.3 wordwrap: 0.0.3
dev: false dev: false
@ -9035,7 +9035,7 @@ packages:
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
/prepend-http@2.0.0: /prepend-http@2.0.0:
resolution: {integrity: sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=} resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==}
engines: {node: '>=4'} engines: {node: '>=4'}
dev: false dev: false
@ -9516,7 +9516,7 @@ packages:
dev: true dev: true
/responselike@1.0.2: /responselike@1.0.2:
resolution: {integrity: sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=} resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==}
dependencies: dependencies:
lowercase-keys: 1.0.1 lowercase-keys: 1.0.1
dev: false dev: false
@ -10876,7 +10876,7 @@ packages:
punycode: 2.3.0 punycode: 2.3.0
/url-parse-lax@3.0.0: /url-parse-lax@3.0.0:
resolution: {integrity: sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=} resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
dependencies: dependencies:
prepend-http: 2.0.0 prepend-http: 2.0.0
@ -11293,7 +11293,7 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
/wordwrap@0.0.3: /wordwrap@0.0.3:
resolution: {integrity: sha1-o9XabNXAvAAI03I0u68b7WMFkQc=} resolution: {integrity: sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
dev: false dev: false

View file

@ -2,13 +2,33 @@
import 'source-map-support/register'; import 'source-map-support/register';
import { WikiChannel } from '@/constants/channels'; import { WikiChannel } from '@/constants/channels';
import type { IWorkspace } from '@services/workspaces/interface'; import type { IWorkspace } from '@services/workspaces/interface';
import { clone, commitAndSync, getModifiedFileList, getRemoteUrl, GitStep, ILoggerContext, initGit, SyncParameterMissingError } from 'git-sync-js'; import {
AssumeSyncError,
CantSyncGitNotInitializedError,
CantSyncInSpecialGitStateAutoFixFailed,
clone,
commitAndSync,
getModifiedFileList,
getRemoteUrl,
GitPullPushError,
GitStep,
ILoggerContext,
initGit,
SyncParameterMissingError,
SyncScriptIsInDeadLoopError,
} from 'git-sync-js';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { expose } from 'threads/worker'; import { expose } from 'threads/worker';
import { defaultGitInfo } from './defaultGitInfo'; import { defaultGitInfo } from './defaultGitInfo';
import type { ICommitAndSyncConfigs, IGitLogMessage, IGitUserInfos } from './interface'; import type { ICommitAndSyncConfigs, IGitLogMessage, IGitUserInfos } from './interface';
function initWikiGit(wikiFolderPath: string, syncImmediately?: boolean, remoteUrl?: string, userInfo?: IGitUserInfos): Observable<IGitLogMessage> { function initWikiGit(
wikiFolderPath: string,
errorI18NDict: Record<string, string>,
syncImmediately?: boolean,
remoteUrl?: string,
userInfo?: IGitUserInfos,
): Observable<IGitLogMessage> {
return new Observable<IGitLogMessage>((observer) => { return new Observable<IGitLogMessage>((observer) => {
let task: Promise<void>; let task: Promise<void>;
if (syncImmediately === true) { if (syncImmediately === true) {
@ -60,7 +80,14 @@ function initWikiGit(wikiFolderPath: string, syncImmediately?: boolean, remoteUr
observer.complete(); observer.complete();
}, },
(error) => { (error) => {
observer.error(error); if (error instanceof Error) {
observer.next({ message: `${error.message} ${error.stack ?? ''}`, level: 'warn', meta: { callerFunction: 'initWikiGit' } });
translateAndLogErrorMessage(error, errorI18NDict);
observer.next({ level: 'error', error });
} else {
observer.next({ message: String(error), level: 'warn', meta: { callerFunction: 'initWikiGit' } });
}
observer.complete();
}, },
); );
}); });
@ -71,7 +98,7 @@ function initWikiGit(wikiFolderPath: string, syncImmediately?: boolean, remoteUr
* @param {string} remoteUrl * @param {string} remoteUrl
* @param {{ login: string, email: string, accessToken: string }} userInfo * @param {{ login: string, email: string, accessToken: string }} userInfo
*/ */
function commitAndSyncWiki(workspace: IWorkspace, configs: ICommitAndSyncConfigs): Observable<IGitLogMessage> { function commitAndSyncWiki(workspace: IWorkspace, configs: ICommitAndSyncConfigs, errorI18NDict: Record<string, string>): Observable<IGitLogMessage> {
return new Observable<IGitLogMessage>((observer) => { return new Observable<IGitLogMessage>((observer) => {
void commitAndSync({ void commitAndSync({
dir: workspace.wikiFolderLocation, dir: workspace.wikiFolderLocation,
@ -94,13 +121,20 @@ function commitAndSyncWiki(workspace: IWorkspace, configs: ICommitAndSyncConfigs
observer.complete(); observer.complete();
}, },
(error) => { (error) => {
observer.error(error); if (error instanceof Error) {
observer.next({ message: `${error.message} ${error.stack ?? ''}`, level: 'warn', meta: { callerFunction: 'commitAndSync' } });
translateAndLogErrorMessage(error, errorI18NDict);
observer.next({ level: 'error', error });
} else {
observer.next({ message: String(error), level: 'warn', meta: { callerFunction: 'commitAndSync' } });
}
observer.complete();
}, },
); );
}); });
} }
function cloneWiki(repoFolderPath: string, remoteUrl: string, userInfo: IGitUserInfos): Observable<IGitLogMessage> { function cloneWiki(repoFolderPath: string, remoteUrl: string, userInfo: IGitUserInfos, errorI18NDict: Record<string, string>): Observable<IGitLogMessage> {
return new Observable<IGitLogMessage>((observer) => { return new Observable<IGitLogMessage>((observer) => {
void clone({ void clone({
dir: repoFolderPath, dir: repoFolderPath,
@ -123,12 +157,35 @@ function cloneWiki(repoFolderPath: string, remoteUrl: string, userInfo: IGitUser
observer.complete(); observer.complete();
}, },
(error) => { (error) => {
observer.error(error); if (error instanceof Error) {
observer.next({ message: `${error.message} ${error.stack ?? ''}`, level: 'warn', meta: { callerFunction: 'clone' } });
translateAndLogErrorMessage(error, errorI18NDict);
observer.next({ level: 'error', error });
} else {
observer.next({ message: String(error), level: 'warn', meta: { callerFunction: 'clone' } });
}
observer.complete();
}, },
); );
}); });
} }
function translateAndLogErrorMessage(error: Error, errorI18NDict: Record<string, string>): void {
if (error instanceof AssumeSyncError) {
error.message = errorI18NDict.AssumeSyncError;
} else if (error instanceof SyncParameterMissingError) {
error.message = errorI18NDict.SyncParameterMissingError + error.parameterName;
} else if (error instanceof GitPullPushError) {
error.message = errorI18NDict.GitPullPushError;
} else if (error instanceof CantSyncGitNotInitializedError) {
error.message = errorI18NDict.CantSyncGitNotInitializedError;
} else if (error instanceof SyncScriptIsInDeadLoopError) {
error.message = errorI18NDict.SyncScriptIsInDeadLoopError;
} else if (error instanceof CantSyncInSpecialGitStateAutoFixFailed) {
error.message = errorI18NDict.CantSyncInSpecialGitStateAutoFixFailed;
}
}
const gitWorker = { initWikiGit, commitAndSyncWiki, cloneWiki, getModifiedFileList, getRemoteUrl }; const gitWorker = { initWikiGit, commitAndSyncWiki, cloneWiki, getModifiedFileList, getRemoteUrl };
export type GitWorker = typeof gitWorker; export type GitWorker = typeof gitWorker;
expose(gitWorker); expose(gitWorker);

View file

@ -1,16 +1,5 @@
import { dialog, ipcMain, net, shell } from 'electron'; import { dialog, ipcMain, net, shell } from 'electron';
import { import { getRemoteName, getRemoteUrl, GitStep, ModifiedFileList } from 'git-sync-js';
AssumeSyncError,
CantSyncGitNotInitializedError,
CantSyncInSpecialGitStateAutoFixFailed,
getRemoteName,
getRemoteUrl,
GitPullPushError,
GitStep,
ModifiedFileList,
SyncParameterMissingError,
SyncScriptIsInDeadLoopError,
} from 'git-sync-js';
import { inject, injectable } from 'inversify'; import { inject, injectable } from 'inversify';
import { compact } from 'lodash'; import { compact } from 'lodash';
import { ModuleThread, spawn, Worker } from 'threads'; import { ModuleThread, spawn, Worker } from 'threads';
@ -74,6 +63,7 @@ export class Git implements IGitService {
} }
public async getWorkspacesRemote(wikiFolderPath?: string): Promise<string | undefined> { public async getWorkspacesRemote(wikiFolderPath?: string): Promise<string | undefined> {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (!wikiFolderPath) return; if (!wikiFolderPath) return;
const branch = (await this.authService.get('git-branch' as ServiceBranchTypes)) ?? 'main'; const branch = (await this.authService.get('git-branch' as ServiceBranchTypes)) ?? 'main';
const defaultRemoteName = (await getRemoteName(wikiFolderPath, branch)) ?? 'origin'; const defaultRemoteName = (await getRemoteName(wikiFolderPath, branch)) ?? 'origin';
@ -201,22 +191,15 @@ export class Git implements IGitService {
} }
} }
private translateAndLogErrorMessage(error: Error): void { private getErrorMessageI18NDict() {
logger.error(error?.message ?? error); return {
if (error instanceof AssumeSyncError) { AssumeSyncError: i18n.t('Log.SynchronizationFailed'),
error.message = i18n.t('Log.SynchronizationFailed'); SyncParameterMissingError: i18n.t('Log.GitTokenMissing'), // + error.parameterName,
} else if (error instanceof SyncParameterMissingError) { GitPullPushError: i18n.t('Log.SyncFailedSystemError'),
error.message = i18n.t('Log.GitTokenMissing') + error.parameterName; CantSyncGitNotInitializedError: i18n.t('Log.CantSyncGitNotInitialized'),
} else if (error instanceof GitPullPushError) { SyncScriptIsInDeadLoopError: i18n.t('Log.CantSynchronizeAndSyncScriptIsInDeadLoop'),
error.message = i18n.t('Log.SyncFailedSystemError'); CantSyncInSpecialGitStateAutoFixFailed: i18n.t('Log.CantSyncInSpecialGitStateAutoFixFailed'),
} else if (error instanceof CantSyncGitNotInitializedError) { };
error.message = i18n.t('Log.CantSyncGitNotInitialized');
} else if (error instanceof SyncScriptIsInDeadLoopError) {
error.message = i18n.t('Log.CantSynchronizeAndSyncScriptIsInDeadLoop');
} else if (error instanceof CantSyncInSpecialGitStateAutoFixFailed) {
error.message = i18n.t('Log.CantSyncInSpecialGitStateAutoFixFailed');
}
logger.error('↑Translated→: ' + error?.message ?? error);
} }
private popGitErrorNotificationToUser(step: GitStep, message: string): void { private popGitErrorNotificationToUser(step: GitStep, message: string): void {
@ -234,8 +217,15 @@ export class Git implements IGitService {
} }
} }
private readonly getWorkerMessageObserver = (resolve: () => void, reject: (error: Error) => void): Observer<IGitLogMessage> => ({ /**
* Handle common error dialog and message dialog
*/
private readonly getWorkerMessageObserver = (wikiFolderPath: string, resolve: () => void, reject: (error: Error) => void): Observer<IGitLogMessage> => ({
next: (messageObject) => { next: (messageObject) => {
if (messageObject.level === 'error') {
this.createFailedDialog((messageObject.error).message, wikiFolderPath);
return;
}
const { message, meta, level } = messageObject; const { message, meta, level } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta) { if (typeof meta === 'object' && meta !== null && 'step' in meta) {
this.popGitErrorNotificationToUser((meta as { step: GitStep }).step, message); this.popGitErrorNotificationToUser((meta as { step: GitStep }).step, message);
@ -243,7 +233,7 @@ export class Git implements IGitService {
logger.log(level, this.translateMessage(message), meta); logger.log(level, this.translateMessage(message), meta);
}, },
error: (error) => { error: (error) => {
this.translateAndLogErrorMessage(error as Error); // this normally won't happen. And will become unhandled error. Because Observable error can't be catch, don't know why.
reject(error as Error); reject(error as Error);
}, },
complete: () => { complete: () => {
@ -267,9 +257,10 @@ export class Git implements IGitService {
try { try {
const result = await this.nativeService.openInGitGuiApp(wikiFolderPath); const result = await this.nativeService.openInGitGuiApp(wikiFolderPath);
if (!result) { if (!result) {
throw new Error('open download site'); throw new Error('open github desktop download site');
} }
} catch { } catch (error) {
logger.error((error as Error).message);
await shell.openExternal(githubDesktopUrl); await shell.openExternal(githubDesktopUrl);
} }
} }
@ -283,8 +274,8 @@ export class Git implements IGitService {
const syncImmediately = !!isSyncedWiki && !!isMainWiki; const syncImmediately = !!isSyncedWiki && !!isMainWiki;
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
this.gitWorker this.gitWorker
?.initWikiGit(wikiFolderPath, syncImmediately && net.isOnline(), remoteUrl, userInfo) ?.initWikiGit(wikiFolderPath, this.getErrorMessageI18NDict(), syncImmediately && net.isOnline(), remoteUrl, userInfo)
.subscribe(this.getWorkerMessageObserver(resolve, reject)); .subscribe(this.getWorkerMessageObserver(wikiFolderPath, resolve, reject));
}); });
} }
@ -294,11 +285,14 @@ export class Git implements IGitService {
} }
try { try {
return await new Promise<boolean>((resolve, reject) => { return await new Promise<boolean>((resolve, reject) => {
const observable = this.gitWorker?.commitAndSyncWiki(workspace, config); const observable = this.gitWorker?.commitAndSyncWiki(workspace, config, this.getErrorMessageI18NDict());
observable?.subscribe(this.getWorkerMessageObserver(() => {}, reject)); observable?.subscribe(this.getWorkerMessageObserver(workspace.wikiFolderLocation, () => {}, reject));
let hasChanges = false; let hasChanges = false;
observable?.subscribe({ observable?.subscribe({
next: (messageObject) => { next: (messageObject) => {
if (messageObject.level === 'error') {
return;
}
const { meta } = messageObject; const { meta } = messageObject;
if (typeof meta === 'object' && meta !== null && 'step' in meta && stepWithChanges.includes((meta as { step: GitStep }).step)) { if (typeof meta === 'object' && meta !== null && 'step' in meta && stepWithChanges.includes((meta as { step: GitStep }).step)) {
hasChanges = true; hasChanges = true;
@ -321,7 +315,7 @@ export class Git implements IGitService {
return; return;
} }
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
this.gitWorker?.cloneWiki(repoFolderPath, remoteUrl, userInfo).subscribe(this.getWorkerMessageObserver(resolve, reject)); this.gitWorker?.cloneWiki(repoFolderPath, remoteUrl, userInfo, this.getErrorMessageI18NDict()).subscribe(this.getWorkerMessageObserver(repoFolderPath, resolve, reject));
}); });
} }
} }

View file

@ -16,11 +16,16 @@ export interface IGitUserInfosWithoutToken {
gitUserName: string; gitUserName: string;
} }
export interface IGitLogMessage { export type IGitLogMessage = INormalGitLogMessage | IErrorGitLogMessage;
export interface INormalGitLogMessage {
level: 'debug' | 'warn' | 'info'; level: 'debug' | 'warn' | 'info';
message: string; message: string;
meta: unknown; meta: unknown;
} }
export interface IErrorGitLogMessage {
error: Error;
level: 'error';
}
export interface ICommitAndSyncConfigs { export interface ICommitAndSyncConfigs {
commitOnly?: boolean; commitOnly?: boolean;

View file

@ -15,9 +15,10 @@
}, },
"skipLibCheck": true, "skipLibCheck": true,
/* Basic Options */ /* Basic Options */
"target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, /* Wait until https://github.com/inversify/InversifyJS/pull/1499 fixed */
"target": "es2021" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"lib": ["esnext", "dom"] /* Specify library files to be included in the compilation. */, "lib": ["ESNext", "dom"] /* Specify library files to be included in the compilation. */,
"allowJs": true /* Allow javascript files to be compiled. */, "allowJs": true /* Allow javascript files to be compiled. */,
// "checkJs": true, /* Report errors in .js files. */ // "checkJs": true, /* Report errors in .js files. */
"jsx": "react-jsx" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */, "jsx": "react-jsx" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
@ -68,6 +69,7 @@
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */ /* Experimental Options */
/* Wait until https://github.com/inversify/InversifyJS/pull/1499 fixed */
"experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
"emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */