feat: git hook config (husky eslint prettier)

This commit is contained in:
Amadou Ada DIENE
2021-07-20 10:51:46 +02:00
parent 1a5a76f912
commit 77b15bdfc4
33 changed files with 52217 additions and 51866 deletions

View File

@@ -16,22 +16,23 @@
"settings": { "settings": {
"import/resolver": { "import/resolver": {
"node": { "node": {
"extensions": [ "extensions": [".js", ".jsx", ".ts", ".tsx"]
".js",
".jsx",
".ts",
".tsx"
]
} }
} }
}, },
"ignorePatterns": ["**/dist/**/*","**/.dist/**/*"], "ignorePatterns": ["**/dist/**/*", "**/.dist/**/*"],
"rules": { "rules": {
"@typescript-eslint/no-unused-vars": ["error", { "@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_" "argsIgnorePattern": "^_"
}], }
"@typescript-eslint/no-explicit-any": ["error", { ],
"@typescript-eslint/no-explicit-any": [
"error",
{
"ignoreRestArgs": true "ignoreRestArgs": true
}] }
]
} }
} }

1
.husky/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_;

30
.husky/_/husky.sh Normal file
View File

@@ -0,0 +1,30 @@
#!/bin/sh
if [ -z "$husky_skip_init" ]; then
debug () {
[ "$HUSKY_DEBUG" = "1" ] && echo "husky (debug) - $1"
}
readonly hook_name="$(basename "$0")"
debug "starting $hook_name..."
if [ "$HUSKY" = "0" ]; then
debug "HUSKY env variable is set to 0, skipping hook"
exit 0
fi
if [ -f ~/.huskyrc ]; then
debug "sourcing ~/.huskyrc"
. ~/.huskyrc
fi
export readonly husky_skip_init=1
sh -e "$0" "$@"
exitCode="$?"
if [ $exitCode != 0 ]; then
echo "husky - $hook_name hook exited with code $exitCode (error)"
exit $exitCode
fi
exit 0
fi

4
.husky/commit-msg Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit "$1"

5
.husky/pre-commit Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
npx pretty-quick --staged

8
.prettierrc Normal file
View File

@@ -0,0 +1,8 @@
{
"useTabs": true,
"tabSize": 2,
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true
}

983
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,10 @@
"publish": "electron-forge publish", "publish": "electron-forge publish",
"lint": "eslint --ext .ts .", "lint": "eslint --ext .ts .",
"test:electron-e2e": "npm run package && cross-env X_NODE_ENV=e2e-test node workspaces/electron-e2e/jasmine.js", "test:electron-e2e": "npm run package && cross-env X_NODE_ENV=e2e-test node workspaces/electron-e2e/jasmine.js",
"clean": "del -f .webpack out node_modules workspaces/shared-lib/.dist workspaces/angular-app/node_modules workspaces/angular-app/.dist", "clean": "shx rm -rf .webpack out node_modules workspaces/shared-lib/.dist workspaces/angular-app/node_modules workspaces/angular-app/.dist",
"version": "npx conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md" "version": "npx conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
"prepare": "husky install",
"postinstall": "husky install && shx rm -rf .git/hooks && shx ln -s ../.husky .git/hooks"
}, },
"config": { "config": {
"forge": { "forge": {
@@ -121,18 +123,22 @@
"copy-webpack-plugin": "^9.0.1", "copy-webpack-plugin": "^9.0.1",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"css-loader": "^5.0.0", "css-loader": "^5.0.0",
"del-cli": "^4.0.1",
"electron": "^13.1.7", "electron": "^13.1.7",
"eslint": "^7.6.0", "eslint": "^7.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.20.0", "eslint-plugin-import": "^2.20.0",
"eslint-plugin-prettier": "^3.4.0",
"fork-ts-checker-webpack-plugin": "^6.0.1", "fork-ts-checker-webpack-plugin": "^6.0.1",
"husky": "^7.0.1", "husky": "^7.0.1",
"jasmine": "^3.8.0", "jasmine": "^3.8.0",
"jasmine-core": "^3.8.0", "jasmine-core": "^3.8.0",
"jasmine-spec-reporter": "^7.0.0", "jasmine-spec-reporter": "^7.0.0",
"lint-staged": "^11.0.1",
"node-loader": "^2.0.0", "node-loader": "^2.0.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"npm-watch": "^0.10.0", "npm-watch": "^0.10.0",
"prettier": "^2.3.2",
"shx": "^0.3.3",
"spectron": "^15.0.0", "spectron": "^15.0.0",
"style-loader": "^2.0.0", "style-loader": "^2.0.0",
"ts-loader": "^9.2.2", "ts-loader": "^9.2.2",
@@ -145,9 +151,7 @@
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"winston": "^3.3.3" "winston": "^3.3.3"
}, },
"husky": { "lint-staged": {
"hooks": { "*.ts": "npm run lint"
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
} }
} }

View File

@@ -16,8 +16,5 @@
"*": ["node_modules/*"] "*": ["node_modules/*"]
} }
}, },
"include": [ "include": ["workspaces/electron-app/**/*", "workspaces/electron-e2e/**/*"]
"workspaces/electron-app/**/*",
"workspaces/electron-e2e/**/*"
]
} }

View File

@@ -1,4 +1,4 @@
const path = require("path"); const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = { module.exports = {
@@ -13,17 +13,17 @@ module.exports = {
}, },
resolve: { resolve: {
extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'], extensions: ['.js', '.ts', '.jsx', '.tsx', '.css', '.json'],
modules: [path.resolve(__dirname, "node_modules"), "node_modules"] modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'],
}, },
plugins: [ plugins: [
new CopyWebpackPlugin({ new CopyWebpackPlugin({
patterns: [ patterns: [
{ from: "workspaces/electron-app/main/assets" }, { from: 'workspaces/electron-app/main/assets' },
{ {
from: "workspaces/angular-app/.dist/angular-app", from: 'workspaces/angular-app/.dist/angular-app',
to: "../renderer/angular_window", to: '../renderer/angular_window',
noErrorOnMissing: true noErrorOnMissing: true,
} },
], ],
}), }),
], ],

View File

@@ -1,16 +0,0 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View File

@@ -26,13 +26,8 @@
"polyfills": "src/polyfills.ts", "polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json", "tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss", "inlineStyleLanguage": "scss",
"assets": [ "assets": ["src/favicon.ico", "src/assets"],
"src/favicon.ico", "styles": ["src/styles.scss"],
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [] "scripts": []
}, },
"configurations": { "configurations": {
@@ -94,13 +89,8 @@
"tsConfig": "tsconfig.spec.json", "tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js", "karmaConfig": "karma.conf.js",
"inlineStyleLanguage": "scss", "inlineStyleLanguage": "scss",
"assets": [ "assets": ["src/favicon.ico", "src/assets"],
"src/favicon.ico", "styles": ["src/styles.scss"],
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [] "scripts": []
} }
} }

View File

@@ -16,10 +16,7 @@
"importHelpers": true, "importHelpers": true,
"target": "es2017", "target": "es2017",
"module": "es2020", "module": "es2020",
"lib": [ "lib": ["es2018", "dom"]
"es2018",
"dom"
]
}, },
"angularCompilerOptions": { "angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false, "enableI18nLegacyMessageIdFormat": false,

View File

@@ -1,20 +1,20 @@
import { app, BrowserWindow, shell } from "electron"; import { app, BrowserWindow, shell } from 'electron';
import { Window } from "./window"; import { Window } from './window';
export class App { export class App {
private static _wrapper: Window; private static _wrapper: Window;
public static launch(): void { public static launch(): void {
app.on("window-all-closed", App.quit); app.on('window-all-closed', App.quit);
app.on("activate", App.start); app.on('activate', App.start);
app.on("ready", App.start); app.on('ready', App.start);
// Fix warning by applying electron new default value for this property // Fix warning by applying electron new default value for this property
// Further details : https://github.com/electron/electron/issues/18397 // Further details : https://github.com/electron/electron/issues/18397
app.allowRendererProcessReuse = true; app.allowRendererProcessReuse = true;
// Limit navigation and open external links in default browser // Limit navigation and open external links in default browser
app.on("web-contents-created", App.openExternalLinksInDefaultBrowser); app.on('web-contents-created', App.openExternalLinksInDefaultBrowser);
} }
public static get electronWindow(): BrowserWindow | undefined { public static get electronWindow(): BrowserWindow | undefined {
@@ -30,7 +30,7 @@ export class App {
private static quit() { private static quit() {
// On MacOS it is common for applications to stay open until the user explicitly quits // On MacOS it is common for applications to stay open until the user explicitly quits
if (process.platform !== "darwin") { if (process.platform !== 'darwin') {
app.quit(); app.quit();
} }
} }
@@ -45,16 +45,16 @@ export class App {
shell.openExternal(handler.url); shell.openExternal(handler.url);
// Blocking this event from loading in current app // Blocking this event from loading in current app
return { action: "deny" }; return { action: 'deny' };
}); });
// Limiting navigation // Limiting navigation
contents.on( contents.on(
"will-navigate", 'will-navigate',
(event: Electron.Event, navigationUrl: string) => { (event: Electron.Event, navigationUrl: string) => {
const parsedUrl = new URL(navigationUrl); const parsedUrl = new URL(navigationUrl);
// Allowing local navigation only // Allowing local navigation only
if (parsedUrl.origin !== "http://localhost:4200") { if (parsedUrl.origin !== 'http://localhost:4200') {
event.preventDefault(); event.preventDefault();
} }
} }

View File

@@ -1,8 +1,8 @@
import { app, BrowserWindow, ipcMain, nativeImage } from "electron"; import { app, BrowserWindow, ipcMain, nativeImage } from 'electron';
import * as path from "path"; import * as path from 'path';
import { AbstractService } from "../services/abstract-service"; import { AbstractService } from '../services/abstract-service';
import { MultiplesService } from "../services/multiples-service"; import { MultiplesService } from '../services/multiples-service';
import { Logger } from "../utils/logger"; import { Logger } from '../utils/logger';
declare const global: Global; declare const global: Global;
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string; declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
@@ -20,7 +20,7 @@ export class Window {
this._electronWindow = new BrowserWindow({ this._electronWindow = new BrowserWindow({
width: 1280, width: 1280,
height: 720, height: 720,
backgroundColor: "#FFFFFF", backgroundColor: '#FFFFFF',
// FIXME // FIXME
// icon: this.loadIcon(), // icon: this.loadIcon(),
webPreferences: { webPreferences: {
@@ -46,11 +46,11 @@ export class Window {
private loadIcon(): Electron.NativeImage | undefined { private loadIcon(): Electron.NativeImage | undefined {
let iconObj = undefined; let iconObj = undefined;
if (global.appConfig.isIconAvailable) { if (global.appConfig.isIconAvailable) {
const iconPath = path.join(__dirname, "icons/icon.png"); const iconPath = path.join(__dirname, 'icons/icon.png');
Logger.debug("Icon Path", iconPath); Logger.debug('Icon Path', iconPath);
iconObj = nativeImage.createFromPath(iconPath); iconObj = nativeImage.createFromPath(iconPath);
// Change dock icon on MacOS // Change dock icon on MacOS
if (iconObj && process.platform === "darwin") { if (iconObj && process.platform === 'darwin') {
app.dock.setIcon(iconObj); app.dock.setIcon(iconObj);
} }
} }
@@ -58,14 +58,14 @@ export class Window {
} }
private loadRenderer(): void { private loadRenderer(): void {
if (global.appConfig.configId === "development") { if (global.appConfig.configId === 'development') {
// Dev mode, take advantage of the live reload by loading local URL // Dev mode, take advantage of the live reload by loading local URL
this.electronWindow.loadURL(`http://localhost:4200`); this.electronWindow.loadURL(`http://localhost:4200`);
} else { } else {
// Else mode, we simply load angular bundle // Else mode, we simply load angular bundle
const indexPath = path.join( const indexPath = path.join(
__dirname, __dirname,
"../renderer/angular_window/index.html" '../renderer/angular_window/index.html'
); );
this.electronWindow.loadURL(`file://${indexPath}`); this.electronWindow.loadURL(`file://${indexPath}`);
} }
@@ -75,7 +75,7 @@ export class Window {
} }
// When the window is closed` // When the window is closed`
this._electronWindow.on("closed", () => { this._electronWindow.on('closed', () => {
// Remove IPC Main listeners // Remove IPC Main listeners
ipcMain.removeAllListeners(); ipcMain.removeAllListeners();
// Delete current reference // Delete current reference
@@ -85,7 +85,7 @@ export class Window {
private openDevTools(): void { private openDevTools(): void {
this._electronWindow.webContents.openDevTools(); this._electronWindow.webContents.openDevTools();
this._electronWindow.webContents.on("devtools-opened", () => { this._electronWindow.webContents.on('devtools-opened', () => {
this._electronWindow.focus(); this._electronWindow.focus();
setImmediate(() => { setImmediate(() => {
this._electronWindow.focus(); this._electronWindow.focus();

View File

@@ -1,8 +1,8 @@
import * as fs from "fs-extra"; import * as fs from 'fs-extra';
import * as _ from "lodash"; import * as _ from 'lodash';
import * as path from "path"; import * as path from 'path';
import { AppConfig } from "shared-lib"; import { AppConfig } from 'shared-lib';
import { App } from "./components/app"; import { App } from './components/app';
declare const global: Global; declare const global: Global;
@@ -15,11 +15,11 @@ declare global {
// Load config // Load config
const currentEnv = process.env.X_NODE_ENV || process.env.NODE_ENV; const currentEnv = process.env.X_NODE_ENV || process.env.NODE_ENV;
const appConfigs = fs.readJsonSync(path.join(__dirname, "config.json")); const appConfigs = fs.readJsonSync(path.join(__dirname, 'config.json'));
const defaultConf = appConfigs.development; const defaultConf = appConfigs.development;
const currentConf = appConfigs[currentEnv]; const currentConf = appConfigs[currentEnv];
global.appConfig = global.appConfig =
currentEnv === "development" currentEnv === 'development'
? defaultConf ? defaultConf
: _.merge(defaultConf, currentConf); : _.merge(defaultConf, currentConf);

View File

@@ -1,13 +1,13 @@
export class AbstractService<In, Out> { export class AbstractService<In, Out> {
receptionChannel(): string { receptionChannel(): string {
throw new Error("Method not implemented yet."); throw new Error('Method not implemented yet.');
} }
sendingChannel(): string { sendingChannel(): string {
throw new Error("Method not implemented yet."); throw new Error('Method not implemented yet.');
} }
process(_input: In): Out { process(_input: In): Out {
throw new Error("Method not implemented yet."); throw new Error('Method not implemented yet.');
} }
} }

View File

@@ -1,5 +1,5 @@
import { WindowApiConst } from "shared-lib"; import { WindowApiConst } from 'shared-lib';
import { AbstractService } from "./abstract-service"; import { AbstractService } from './abstract-service';
export class MultiplesService extends AbstractService<number, number[]> { export class MultiplesService extends AbstractService<number, number[]> {
receptionChannel(): string { receptionChannel(): string {

View File

@@ -1,7 +1,7 @@
import { app } from "electron"; import { app } from 'electron';
import * as os from "os"; import * as os from 'os';
import * as path from "path"; import * as path from 'path';
import * as winston from "winston"; import * as winston from 'winston';
declare const global: Global; declare const global: Global;
@@ -52,9 +52,9 @@ export class Logger {
private constructor() { private constructor() {
this._logger = winston.createLogger({ this._logger = winston.createLogger({
level: "debug", level: 'debug',
format: winston.format.json(), format: winston.format.json(),
defaultMeta: { service: "user-service" }, defaultMeta: { service: 'user-service' },
transports: [ transports: [
new winston.transports.File({ new winston.transports.File({
filename: this.getLogFilename(), filename: this.getLogFilename(),
@@ -69,10 +69,10 @@ export class Logger {
// If we're not in production then log also to the `console` with the format: // If we're not in production then log also to the `console` with the format:
// `${info.timestamp} ${info.level}: ${info.message} JSON.stringify({ ...rest }) ` // `${info.timestamp} ${info.level}: ${info.message} JSON.stringify({ ...rest }) `
if (global.appConfig.configId === "development") { if (global.appConfig.configId === 'development') {
this._logger.add( this._logger.add(
new winston.transports.Console({ new winston.transports.Console({
stderrLevels: ["error", "warn"], stderrLevels: ['error', 'warn'],
format: winston.format.combine( format: winston.format.combine(
winston.format.timestamp(), winston.format.timestamp(),
this.consoleFormat this.consoleFormat
@@ -88,13 +88,13 @@ export class Logger {
*/ */
private getLogFilename() { private getLogFilename() {
let filename = global.appConfig.mainLogFile; let filename = global.appConfig.mainLogFile;
if (global.appConfig.configId === "production") { if (global.appConfig.configId === 'production') {
const appName = app.getName(); const appName = app.getName();
if (process.platform == "linux") { if (process.platform == 'linux') {
filename = `.config/${appName}/${filename}`; filename = `.config/${appName}/${filename}`;
} else if (process.platform == "darwin") { } else if (process.platform == 'darwin') {
filename = `Library/Logs/${appName}/${filename}`; filename = `Library/Logs/${appName}/${filename}`;
} else if (process.platform == "win32") { } else if (process.platform == 'win32') {
filename = `AppData\\Roaming\\${appName}\\${filename}`; filename = `AppData\\Roaming\\${appName}\\${filename}`;
} }
} }

View File

@@ -1,7 +1,7 @@
// To secure user platform when running renderer process stuff, // To secure user platform when running renderer process stuff,
// Node.JS and Electron APIs are only available in this script // Node.JS and Electron APIs are only available in this script
import { contextBridge, ipcRenderer, IpcRendererEvent } from "electron"; import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import { WindowApi, WindowApiConst } from "shared-lib"; import { WindowApi, WindowApiConst } from 'shared-lib';
// So we expose protected methods that allow the renderer process // So we expose protected methods that allow the renderer process
// to use the ipcRenderer without exposing the entire object // to use the ipcRenderer without exposing the entire object
@@ -22,14 +22,14 @@ const windowApi: WindowApi = {
}; };
declare const window: Window; declare const window: Window;
if (process.env.X_NODE_ENV === "e2e-test") { if (process.env.X_NODE_ENV === 'e2e-test') {
// Injecting windowApi directly // Injecting windowApi directly
window.api = windowApi; window.api = windowApi;
} else { } else {
// ContextBridge API can only be used when contextIsolation is enabled // ContextBridge API can only be used when contextIsolation is enabled
// which is normally the case except in e2e test mode // which is normally the case except in e2e test mode
contextBridge.exposeInMainWorld("api", windowApi); contextBridge.exposeInMainWorld('api', windowApi);
} }
console.log(typeof window); console.log(typeof window);
console.log("The preload script has been injected successfully."); console.log('The preload script has been injected successfully.');

View File

@@ -1,22 +1,24 @@
const Jasmine = require("jasmine"); const Jasmine = require('jasmine');
const { SpecReporter } = require("jasmine-spec-reporter"); const { SpecReporter } = require('jasmine-spec-reporter');
const jasmine = new Jasmine(); const jasmine = new Jasmine();
jasmine.loadConfig({ jasmine.loadConfig({
showColors: true, showColors: true,
defaultTimeoutInterval: 15000, defaultTimeoutInterval: 15000,
spec_dir: "workspaces/electron-e2e", spec_dir: 'workspaces/electron-e2e',
spec_files: ["./**/*-spec.ts"], spec_files: ['./**/*-spec.ts'],
helpers: ["./**/*-helper.ts"], helpers: ['./**/*-helper.ts'],
random: false, random: false,
seed: undefined, seed: undefined,
stopSpecOnExpectationFailure: false, stopSpecOnExpectationFailure: false,
}); });
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
require("ts-node").register({ require('ts-node').register({
project: require("path").join(__dirname, "./tsconfig.json"), project: require('path').join(__dirname, './tsconfig.json'),
}); });
jasmine.env.clearReporters(); jasmine.env.clearReporters();
jasmine.addReporter(new SpecReporter({ spec: { displayStacktrace: 'pretty' } })); jasmine.addReporter(
new SpecReporter({ spec: { displayStacktrace: 'pretty' } })
);
jasmine.execute(); jasmine.execute();

View File

@@ -1,11 +1,11 @@
import * as path from "path"; import * as path from 'path';
import { Application } from "spectron"; import { Application } from 'spectron';
describe("A simple test to verify a visible window is opened with a title", () => { describe('A simple test to verify a visible window is opened with a title', () => {
// Init local app // Init local app
const app = new Application({ const app = new Application({
path: path.join(__dirname, "../../../node_modules/.bin/electron"), path: path.join(__dirname, '../../../node_modules/.bin/electron'),
args: [path.join(__dirname, "../../../.webpack/main/index.js")], args: [path.join(__dirname, '../../../.webpack/main/index.js')],
}); });
beforeAll(async () => { beforeAll(async () => {
@@ -22,14 +22,14 @@ describe("A simple test to verify a visible window is opened with a title", () =
} }
}); });
it("shows an initial window", async () => { it('shows an initial window', async () => {
// Checking there is one visible window // Checking there is one visible window
expect(await app.browserWindow.isVisible()).toEqual(true); expect(await app.browserWindow.isVisible()).toEqual(true);
// Please note that getWindowCount() will return 2 if `dev tools` are opened. // Please note that getWindowCount() will return 2 if `dev tools` are opened.
expect(await app.client.getWindowCount()).toEqual(1); expect(await app.client.getWindowCount()).toEqual(1);
}); });
it("should have expected title", async () => { it('should have expected title', async () => {
expect(await app.client.getTitle()).toEqual("ElectronAngularQuickStart"); expect(await app.client.getTitle()).toEqual('ElectronAngularQuickStart');
}); });
}); });

View File

@@ -1,7 +1,7 @@
import { WindowApi } from "./apis/window-api"; import { WindowApi } from './apis/window-api';
export * from "./apis/window-api"; export * from './apis/window-api';
export * from "./apis/window-api-consts"; export * from './apis/window-api-consts';
export * from "./models/config/app-config"; export * from './models/config/app-config';
declare global { declare global {
// Global augmentation of the `Window` interface // Global augmentation of the `Window` interface

View File

@@ -2,8 +2,7 @@
"name": "shared-lib", "name": "shared-lib",
"version": "2.0.0", "version": "2.0.0",
"main": ".dist/index.js", "main": ".dist/index.js",
"scripts": { "scripts": {},
},
"author": "Sourcygen", "author": "Sourcygen",
"license": "MIT" "license": "MIT"
} }