diff --git a/.babelrc b/.babelrc index 84d79198de..693bff5b29 100644 --- a/.babelrc +++ b/.babelrc @@ -1,20 +1,10 @@ { "presets": [ - [ - "@babel/preset-env", { - "debug": true, - "modules": false, - "targets": { - "esmodules": false - } - } - ], + "@babel/preset-env", "@babel/preset-react", "@lingui/babel-preset-react" ], "plugins": [ - "@babel/plugin-transform-runtime", - "@babel/plugin-syntax-dynamic-import", - "babel-plugin-macros" + "macros" ] } diff --git a/package.json b/package.json index 81c443a1be..75fb432faf 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,9 @@ "dev:main": "DEBUG=true webpack --watch --cache --config webpack.main.ts", "dev:renderer": "DEBUG=true webpack --watch --cache --config webpack.renderer.ts", "compile": "NODE_ENV=production concurrently 'yarn download-bins' 'yarn i18n:compile' 'yarn compile:dll' && concurrently yarn:compile:*", - "compile:main": "NODE_ENV=production webpack -p --progress --config webpack.main.ts", - "compile:renderer": "NODE_ENV=production webpack -p --progress --config webpack.renderer.ts", - "compile:dll": "webpack --config webpack.dll.ts", + "compile:main": "NODE_ENV=production webpack --progress --config webpack.main.ts $@", + "compile:renderer": "NODE_ENV=production webpack --progress --config webpack.renderer.ts $@", + "compile:dll": "webpack --config webpack.dll.ts $@", "build:linux": "yarn compile && electron-builder --linux --dir -c.productName=LensDev", "build:mac": "yarn compile && electron-builder --mac --dir -c.productName=LensDev", "build:win": "yarn compile && electron-builder --win --dir -c.productName=LensDev", @@ -196,8 +196,6 @@ }, "devDependencies": { "@babel/core": "^7.10.2", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-runtime": "^7.10.1", "@babel/preset-env": "^7.10.2", "@babel/preset-react": "^7.10.1", "@babel/preset-typescript": "^7.10.1", @@ -249,8 +247,11 @@ "dompurify": "^2.0.11", "electron-builder": "^22.7.0", "electron-notarize": "^0.3.0", + "electron-reloader": "^1.0.1", + "electron-serve": "^1.0.0", "file-loader": "^6.0.0", "flex.box": "^3.4.4", + "fork-ts-checker-webpack-plugin": "^5.0.0", "hashicon": "^0.3.0", "hoist-non-react-statics": "^3.3.2", "html-webpack-plugin": "^4.3.0", diff --git a/src/common/vars.ts b/src/common/vars.ts index 60697cc17b..97094b3aa4 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -1,10 +1,12 @@ // App's common configuration for any process (main, renderer, build pipeline, etc.) import path from "path"; +// Flags export const isMac = process.platform === "darwin" export const isWindows = process.platform === "win32" +export const isDebugging = process.env.DEBUG === "true"; export const isProduction = process.env.NODE_ENV === "production" -export const isDevelopment = !isProduction; +export const isDevelopment = isDebugging || !isProduction; export const buildVersion = process.env.BUILD_VERSION; // Paths @@ -24,7 +26,10 @@ export const apiPrefix = { BASE: '/api', TERMINAL: '/api-terminal', // terminal api KUBE_BASE: '/api-kube', // kubernetes cluster api - KUBE_USERS: '/api-users', // users & groups api KUBE_HELM: '/api-helm', // helm charts api KUBE_RESOURCE_APPLIER: "/api-resource", }; + +// Links +export const issuesTrackerUrl = "https://github.com/lensapp/lens/issues" +export const slackUrl = "https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI" diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index 6e986816f7..29786b4914 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -11,7 +11,7 @@ import path from "path" import { promises } from "fs" import { ensureDir } from "fs-extra" import filenamify from "filenamify" -import { v4 as uuid } from "uuid" +import uuid from "uuid" export type FeatureInstallRequest = { name: string; @@ -92,7 +92,7 @@ export class ClusterManager { configs.forEach(c => { k8s.validateConfig(c) const cluster = new Cluster({ - id: uuid(), + id: uuid.v4(), port: this.port, kubeConfig: k8s.dumpConfigYaml(c), preferences: clusterData.preferences, @@ -115,15 +115,15 @@ export class ClusterManager { logger.debug(`IPC: addCluster`) const cluster = await this.addNewCluster(clusterData) return { - addedCluster: this.clusterResponse(cluster), - allClusters: Array.from(this.getClusters()).map((cluster: Cluster) => this.clusterResponse(cluster)) + addedCluster: cluster.toClusterInfo(), + allClusters: Array.from(this.getClusters()).map((cluster: Cluster) => cluster.toClusterInfo()) } }); this.promiseIpc.on("getClusters", async (workspaceId: string) => { logger.debug(`IPC: getClusters, workspace ${workspaceId}`) const workspaceClusters = Array.from(this.getClusters()).filter((cluster) => cluster.workspace === workspaceId) - return workspaceClusters.map((cluster: Cluster) => this.clusterResponse(cluster)) + return workspaceClusters.map((cluster: Cluster) => cluster.toClusterInfo()) }); this.promiseIpc.on("getCluster", async (id: string) => { @@ -131,7 +131,7 @@ export class ClusterManager { const cluster = this.getCluster(id) if (cluster) { await cluster.refreshCluster() - return this.clusterResponse(cluster) + return cluster.toClusterInfo() } else { return null } @@ -179,7 +179,7 @@ export class ClusterManager { if(!cluster.preferences) cluster.preferences = {}; cluster.preferences.icon = clusterIcon clusterStore.storeCluster(cluster); - return {success: true, cluster: this.clusterResponse(cluster), message: ""} + return {success: true, cluster: cluster.toClusterInfo(), message: ""} } catch(error) { return {success: false, message: error} } @@ -191,7 +191,7 @@ export class ClusterManager { if (cluster && cluster.preferences) { cluster.preferences.icon = null; clusterStore.storeCluster(cluster) - return {success: true, cluster: this.clusterResponse(cluster), message: ""} + return {success: true, cluster: cluster.toClusterInfo(), message: ""} } else { return {success: false, message: "Cluster not found"} } @@ -200,7 +200,7 @@ export class ClusterManager { this.promiseIpc.on("refreshCluster", async (clusterId: string) => { const cluster = this.clusters.get(clusterId) await cluster.refreshCluster() - return this.clusterResponse(cluster) + return cluster.toClusterInfo() }); this.promiseIpc.on("stopCluster", (clusterId: string) => { @@ -215,7 +215,7 @@ export class ClusterManager { this.promiseIpc.on("removeCluster", (ctx: string) => { logger.debug(`IPC: removeCluster: ${ctx}`) - return this.removeCluster(ctx).map((cluster: Cluster) => this.clusterResponse(cluster)) + return this.removeCluster(ctx).map((cluster: Cluster) => cluster.toClusterInfo()) }); this.promiseIpc.on("clusterStored", (clusterId: string) => { @@ -272,11 +272,6 @@ export class ClusterManager { return cluster; } - // TODO: remove this - protected clusterResponse(cluster: Cluster) { - return cluster.toClusterInfo() - } - protected async uploadClusterIcon(cluster: Cluster, fileName: string, src: string): Promise { await ensureDir(ClusterManager.clusterIconDir) fileName = filenamify(cluster.contextName + "-" + fileName) diff --git a/src/main/cluster.ts b/src/main/cluster.ts index 4e938c5f83..56268c92e3 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -179,16 +179,14 @@ export class Cluster implements ClusterInfo { } } - protected async k8sRequest(path: string, opts?: request.RequestPromiseOptions) { - const options = Object.assign({ - json: true, timeout: 10000 - }, (opts || {})) - if (!options.headers) { - options.headers = {} - } - options.headers.host = `${this.id}.localhost:${this.port}` - - return request(`http://127.0.0.1:${this.port}/api-kube${path}`, options) + protected async k8sRequest(path: string, opts: request.RequestPromiseOptions = {}) { + const url = `http://127.0.0.1:${this.port}/api-kube${path}`; // fixme: remove hardcoded api prefix + opts.json = true; + opts.timeout = 10000; + opts.headers = Object.assign({}, opts.headers, { + host: `${this.id}.localhost:${this.port}`, + }); + return request(url, opts); } protected async getConnectionStatus() { @@ -300,9 +298,7 @@ export class Cluster implements ClusterInfo { if (k8s.podHasIssues(pod)) { uniqEventSources.add(w.involvedObject.uid); } - continue; // TODO: refactor - } catch (error) { - continue; + } catch (err) { } } else { diff --git a/src/main/index_backup.ts b/src/main/index_backup.ts index 1646be9d61..0ccd1a447e 100644 --- a/src/main/index_backup.ts +++ b/src/main/index_backup.ts @@ -132,3 +132,8 @@ app.on("will-quit", async (event) => { if (clusterManager) clusterManager.stop() app.exit(0); }) + +// auto-restart app in dev-mode +if (isDevelopment) { + require('electron-reloader')(module); +} diff --git a/src/main/logger.ts b/src/main/logger.ts index 0618852b4b..eab9478bf0 100644 --- a/src/main/logger.ts +++ b/src/main/logger.ts @@ -1,10 +1,11 @@ -import * as winston from "winston" +import winston from "winston" +import { isDebugging } from "../common/vars"; const options = { colorize: true, handleExceptions: false, json: false, - level: process.env.DEBUG === "true" ? "debug" : "info", + level: isDebugging ? "debug" : "info", } const logger = winston.createLogger({ diff --git a/src/main/menu.ts b/src/main/menu.ts index 36c58c0ceb..f38486c849 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -1,5 +1,5 @@ import { app, BrowserWindow, dialog, Menu, MenuItem, MenuItemConstructorOptions, shell, webContents } from "electron" -import { isDevelopment, isMac, isWindows } from "../common/vars"; +import { isDevelopment, isMac, issuesTrackerUrl, isWindows, slackUrl } from "../common/vars"; // todo: refactor + split menu sections to separated files, e.g. menus/file.menu.ts @@ -183,13 +183,13 @@ export default function initMenu(opts: MenuOptions, promiseIpc: any) { { label: 'Community Slack', click: async () => { - shell.openExternal('https://join.slack.com/t/k8slens/shared_invite/enQtOTc5NjAyNjYyOTk4LWU1NDQ0ZGFkOWJkNTRhYTc2YjVmZDdkM2FkNGM5MjhiYTRhMDU2NDQ1MzIyMDA4ZGZlNmExOTc0N2JmY2M3ZGI'); + shell.openExternal(slackUrl); }, }, { label: 'Report an Issue', click: async () => { - shell.openExternal('https://github.com/lensapp/lens/issues'); + shell.openExternal(issuesTrackerUrl); }, }, { diff --git a/src/renderer/api/endpoints/helm-charts.api.ts b/src/renderer/api/endpoints/helm-charts.api.ts index 223df8441f..1f2d8ce0fd 100644 --- a/src/renderer/api/endpoints/helm-charts.api.ts +++ b/src/renderer/api/endpoints/helm-charts.api.ts @@ -1,5 +1,5 @@ import { compile } from "path-to-regexp"; -import { apiKubeHelm } from "../index"; +import { apiHelm } from "../index"; import { stringify } from "querystring"; import { autobind } from "../../utils"; @@ -21,7 +21,7 @@ const endpoint = compile(`/v2/charts/:repo?/:name?`) as (params?: { export const helmChartsApi = { list() { - return apiKubeHelm + return apiHelm .get(endpoint()) .then(data => { return Object @@ -33,7 +33,7 @@ export const helmChartsApi = { get(repo: string, name: string, readmeVersion?: string) { const path = endpoint({ repo, name }); - return apiKubeHelm + return apiHelm .get(path + "?" + stringify({ version: readmeVersion })) .then(data => { const versions = data.versions.map(HelmChart.create); @@ -46,7 +46,7 @@ export const helmChartsApi = { }, getValues(repo: string, name: string, version: string) { - return apiKubeHelm + return apiHelm .get(`/v2/charts/${repo}/${name}/values?` + stringify({ version })); } }; diff --git a/src/renderer/api/endpoints/helm-releases.api.ts b/src/renderer/api/endpoints/helm-releases.api.ts index 8a86e0138c..91ed843edb 100644 --- a/src/renderer/api/endpoints/helm-releases.api.ts +++ b/src/renderer/api/endpoints/helm-releases.api.ts @@ -2,7 +2,7 @@ import jsYaml from "js-yaml"; import { compile } from "path-to-regexp"; import { autobind, formatDuration } from "../../utils"; import capitalize from "lodash/capitalize"; -import { apiKubeHelm } from "../index"; +import { apiHelm } from "../index"; import { helmChartStore } from "../../components/+apps-helm-charts/helm-chart.store"; import { ItemObject } from "../../item.store"; import { KubeObject } from "../kube-object"; @@ -69,14 +69,14 @@ const endpoint = compile(`/v2/releases/:namespace?/:name?`) as ( export const helmReleasesApi = { list(namespace?: string) { - return apiKubeHelm + return apiHelm .get(endpoint({ namespace })) .then(releases => releases.map(HelmRelease.create)); }, get(name: string, namespace: string) { const path = endpoint({ name, namespace }); - return apiKubeHelm.get(path).then(details => { + return apiHelm.get(path).then(details => { const items: KubeObject[] = JSON.parse(details.resources).items; const resources = items.map(item => KubeObject.create(item)); return { @@ -90,34 +90,34 @@ export const helmReleasesApi = { const { repo, ...data } = payload; data.chart = `${repo}/${data.chart}`; data.values = jsYaml.safeLoad(data.values); - return apiKubeHelm.post(endpoint(), { data }); + return apiHelm.post(endpoint(), { data }); }, update(name: string, namespace: string, payload: IReleaseUpdatePayload): Promise { const { repo, ...data } = payload; data.chart = `${repo}/${data.chart}`; data.values = jsYaml.safeLoad(data.values); - return apiKubeHelm.put(endpoint({ name, namespace }), { data }); + return apiHelm.put(endpoint({ name, namespace }), { data }); }, async delete(name: string, namespace: string) { const path = endpoint({ name, namespace }); - return apiKubeHelm.del(path); + return apiHelm.del(path); }, getValues(name: string, namespace: string) { const path = endpoint({ name, namespace }) + "/values"; - return apiKubeHelm.get(path); + return apiHelm.get(path); }, getHistory(name: string, namespace: string): Promise { const path = endpoint({ name, namespace }) + "/history"; - return apiKubeHelm.get(path); + return apiHelm.get(path); }, rollback(name: string, namespace: string, revision: number) { const path = endpoint({ name, namespace }) + "/rollback"; - return apiKubeHelm.put(path, { + return apiHelm.put(path, { data: { revision: revision } diff --git a/src/renderer/api/endpoints/resource-applier.api.ts b/src/renderer/api/endpoints/resource-applier.api.ts index ffa2852b5e..6697b4a56d 100644 --- a/src/renderer/api/endpoints/resource-applier.api.ts +++ b/src/renderer/api/endpoints/resource-applier.api.ts @@ -1,7 +1,7 @@ import jsYaml from "js-yaml" import { KubeObject } from "../kube-object"; import { KubeJsonApiData } from "../kube-json-api"; -import { apiKubeResourceApplier } from "../index"; +import { apiResourceApplier } from "../index"; import { apiManager } from "../api-manager"; export const resourceApplierApi = { @@ -13,7 +13,7 @@ export const resourceApplierApi = { if (typeof resource === "string") { resource = jsYaml.safeLoad(resource); } - return apiKubeResourceApplier + return apiResourceApplier .post("/stack", { data: resource }) .then(data => { const items = data.map(obj => { diff --git a/src/renderer/api/index.ts b/src/renderer/api/index.ts index 436cc4ebf6..aacf0c09a8 100644 --- a/src/renderer/api/index.ts +++ b/src/renderer/api/index.ts @@ -13,15 +13,11 @@ export const apiKube = new KubeJsonApi({ debug: isDevelopment, apiPrefix: apiPrefix.KUBE_BASE, }); -export const apiKubeUsers = new KubeJsonApi({ - debug: isDevelopment, - apiPrefix: apiPrefix.KUBE_USERS, -}); -export const apiKubeHelm = new KubeJsonApi({ +export const apiHelm = new KubeJsonApi({ debug: isDevelopment, apiPrefix: apiPrefix.KUBE_HELM, }); -export const apiKubeResourceApplier = new KubeJsonApi({ +export const apiResourceApplier = new KubeJsonApi({ debug: isDevelopment, apiPrefix: apiPrefix.KUBE_RESOURCE_APPLIER, }); @@ -38,6 +34,5 @@ function onApiError(error: JsonApiErrorParsed, res: Response) { apiBase.onError.addListener(onApiError); apiKube.onError.addListener(onApiError); -apiKubeUsers.onError.addListener(onApiError); -apiKubeHelm.onError.addListener(onApiError); -apiKubeResourceApplier.onError.addListener(onApiError); +apiHelm.onError.addListener(onApiError); +apiResourceApplier.onError.addListener(onApiError); diff --git a/src/renderer/api/kube-watch-api.ts b/src/renderer/api/kube-watch-api.ts index aefb0870b0..338bc991b3 100644 --- a/src/renderer/api/kube-watch-api.ts +++ b/src/renderer/api/kube-watch-api.ts @@ -8,6 +8,7 @@ import { KubeObjectStore } from "../kube-object.store"; import { KubeApi } from "./kube-api"; import { configStore } from "../config.store"; import { apiManager } from "./api-manager"; +import { apiPrefix, isDevelopment } from "../../common/vars"; export interface IKubeWatchEvent { type: "ADDED" | "MODIFIED" | "DELETED"; @@ -28,9 +29,8 @@ export interface IKubeWatchRouteQuery { export class KubeWatchApi { protected evtSource: EventSource; protected onData = new EventEmitter<[IKubeWatchEvent]>(); - protected apiUrl = configStore.apiPrefix.BASE + "/watch"; + protected apiUrl = apiPrefix.BASE + "/watch"; protected subscribers = observable.map(); - protected reconnectInterval = interval(60 * 5, this.reconnect); // background reconnect every 5min protected reconnectTimeoutMs = 5000; protected maxReconnectsOnError = 10; protected reconnectAttempts = this.maxReconnectsOnError; @@ -138,7 +138,7 @@ export class KubeWatchApi { } protected writeLog(...data: any[]) { - if (configStore.isDevelopment) { + if (isDevelopment) { console.log('%cKUBE-WATCH-API:', `font-weight: bold`, ...data); } } diff --git a/src/renderer/api/terminal-api.ts b/src/renderer/api/terminal-api.ts index aec97f34af..30a990e8fc 100644 --- a/src/renderer/api/terminal-api.ts +++ b/src/renderer/api/terminal-api.ts @@ -3,6 +3,7 @@ import { autobind, base64, EventEmitter, interval } from "../utils"; import { WebSocketApi } from "./websocket-api"; import { configStore } from "../config.store"; import isEqual from "lodash/isEqual" +import { apiPrefix, isDevelopment } from "../../common/vars"; export enum TerminalChannels { STDIN = 0, @@ -40,26 +41,28 @@ export class TerminalApi extends WebSocketApi { constructor(protected options: ITerminalApiOptions) { super({ - logging: configStore.isDevelopment, + logging: isDevelopment, flushOnOpen: false, pingIntervalSeconds: 30, }); } async getUrl(token: string) { - const { hostname, protocol } = location; + var { hostname, protocol, port } = location; + const prefix = apiPrefix.TERMINAL; const { id, node } = this.options; - const apiPrefix = configStore.apiPrefix.TERMINAL; const wss = `ws${protocol === "https:" ? "s" : ""}://`; const queryParams = { token, id }; + if (port) { + port = `:${port}` + } if (node) { Object.assign(queryParams, { node: node, type: "node" }); } - - return `${wss}${hostname}${configStore.serverPort}${apiPrefix}/api?${stringify(queryParams)}`; + return `${wss}${hostname}${port}${prefix}/api?${stringify(queryParams)}`; } async connect() { diff --git a/src/renderer/components/error-boundary/error-boundary.tsx b/src/renderer/components/error-boundary/error-boundary.tsx index c30d858e30..5e43f53f26 100644 --- a/src/renderer/components/error-boundary/error-boundary.tsx +++ b/src/renderer/components/error-boundary/error-boundary.tsx @@ -5,9 +5,9 @@ import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { t, Trans } from "@lingui/macro"; import { Button } from "../button"; -import { configStore } from "../../config.store"; import { navigation } from "../../navigation"; import { _i18n } from "../../i18n"; +import { issuesTrackerUrl, slackUrl, buildVersion } from "../../../common/vars"; interface Props { } @@ -38,14 +38,14 @@ export class ErrorBoundary extends React.Component { render() { const { error, errorInfo } = this.state; if (error) { - const slackLink = Slack - const githubLink = Github + const slackLink = Slack + const githubLink = Github const pageUrl = location.href; return (
App crash at {pageUrl} - {configStore.buildVersion &&

Build version: {configStore.buildVersion}

} + {buildVersion &&

Build version: {buildVersion}

}

diff --git a/src/renderer/config.store.ts b/src/renderer/config.store.ts index f27127a6d3..4ea90d1514 100755 --- a/src/renderer/config.store.ts +++ b/src/renderer/config.store.ts @@ -1,15 +1,10 @@ import { observable, when } from "mobx"; import type { IConfigRoutePayload } from "../main/routes/config"; -import { apiPrefix, buildVersion, isDevelopment } from "../common/vars"; import { autobind, interval } from "./utils"; import { configApi } from "./api/endpoints"; @autobind() export class ConfigStore { - readonly isDevelopment = isDevelopment; - readonly buildVersion = buildVersion; - readonly apiPrefix = apiPrefix; - protected updater = interval(60, this.load); @observable config: Partial = {}; @@ -32,11 +27,6 @@ export class ConfigStore { return this.config.token; } - get serverPort() { - const port = location.port; - return port ? `:${port}` : ""; - } - get allowedNamespaces() { return this.config.allowedNamespaces || []; } diff --git a/tsconfig.json b/tsconfig.json index e6e7c53f01..783d32fda4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "target": "ES2017", "module": "ESNext", "lib": ["ESNext", "DOM", "DOM.Iterable"], + "importsNotUsedAsValues": "preserve", "moduleResolution": "Node", "sourceMap": true, "strict": false, @@ -27,6 +28,10 @@ ] } }, + "include": [ + "src/**/*", + "types/*" + ], "ts-node": { "compilerOptions": { "module": "CommonJS" diff --git a/webpack.main.ts b/webpack.main.ts index a9b92093c9..4b72e05a00 100755 --- a/webpack.main.ts +++ b/webpack.main.ts @@ -1,9 +1,11 @@ import path from "path"; import webpack from "webpack"; +import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" import { isDevelopment, isProduction, mainDir, outDir } from "./src/common/vars"; export default function (): webpack.Configuration { return { + context: __dirname, target: "electron-main", mode: isProduction ? "production" : "development", cache: isDevelopment, @@ -30,9 +32,17 @@ export default function (): webpack.Configuration { }, { test: /\.ts?$/, - use: "ts-loader", + use: { + loader: "ts-loader", + options: { + transpileOnly: true, + } + }, }, ] }, + plugins: [ + new ForkTsCheckerPlugin(), + ] } } diff --git a/webpack.renderer.ts b/webpack.renderer.ts index 6ce396882c..d9490d8533 100755 --- a/webpack.renderer.ts +++ b/webpack.renderer.ts @@ -2,8 +2,10 @@ import path from "path"; import webpack from "webpack"; import HtmlWebpackPlugin from "html-webpack-plugin"; import MiniCssExtractPlugin from "mini-css-extract-plugin"; -import TerserWebpackPlugin from "terser-webpack-plugin"; -import { htmlTemplate, isDevelopment, isProduction, outDir, rendererDir, sassCommonVars, tsConfigFile } from "./src/common/vars"; +import TerserPlugin from "terser-webpack-plugin"; +import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" +import { VueLoaderPlugin } from "vue-loader" +import { htmlTemplate, isDevelopment, isProduction, outDir, rendererDir, sassCommonVars } from "./src/common/vars"; import { libraryTarget, manifestPath } from "./webpack.dll"; export default [ @@ -13,6 +15,7 @@ export default [ export function webpackConfigReact(): webpack.Configuration { return { + context: __dirname, target: "electron-renderer", mode: isProduction ? "production" : "development", devtool: isProduction ? "source-map" : "cheap-module-eval-source-map", @@ -37,7 +40,7 @@ export function webpackConfigReact(): webpack.Configuration { optimization: { minimize: false, minimizer: [ - new TerserWebpackPlugin({ + new TerserPlugin({ cache: true, parallel: true, sourceMap: true, @@ -65,7 +68,7 @@ export function webpackConfigReact(): webpack.Configuration { { loader: "ts-loader", options: { - configFile: tsConfigFile, + transpileOnly: false, // fixme: enable types resolution with ts-fork-checker compilerOptions: { // localization support // https://lingui.js.org/guides/typescript.html @@ -112,12 +115,16 @@ export function webpackConfigReact(): webpack.Configuration { }, plugins: [ + // fixme: enable with transpileOnly=true + // new ForkTsCheckerPlugin(), + // todo: check if this actually works in mode=production files new webpack.DllReferencePlugin({ context: process.cwd(), manifest: manifestPath, sourceType: libraryTarget, }), + new HtmlWebpackPlugin({ template: htmlTemplate, inject: true, @@ -157,16 +164,15 @@ export function webpackConfigVue(): webpack.Configuration { } }, { - test: /\.jsx?$/, - loader: "babel-loader", - }, - { - test: /\.tsx?$/, - loader: "ts-loader", - options: { - transpileOnly: false, - appendTsSuffixTo: [/\.vue$/], - } + test: /\.[tj]sx?$/, + exclude: /node_modules/, + use: { + loader: "ts-loader", + options: { + transpileOnly: true, + appendTsSuffixTo: [/\.vue$/], + } + }, }, { test: /\.s?css$/, @@ -179,9 +185,9 @@ export function webpackConfigVue(): webpack.Configuration { ); // plugins - const VueLoaderPlugin = require("vue-loader/lib/plugin"); config.plugins = [ new VueLoaderPlugin(), + new ForkTsCheckerPlugin(), ]; return config; diff --git a/yarn.lock b/yarn.lock index 47fb038b6d..3ee9644147 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== @@ -3428,7 +3428,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3521,7 +3521,7 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.0: +chokidar@^3.3.1, chokidar@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== @@ -4214,6 +4214,13 @@ date-fns@^2.0.1, date-fns@^2.14.0: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.14.0.tgz#359a87a265bb34ef2e38f93ecf63ac453f9bc7ba" integrity sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw== +date-time@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-3.1.0.tgz#0d1e934d170579f481ed8df1e2b8ff70ee845e1e" + integrity sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg== + dependencies: + time-zone "^1.0.0" + de-indent@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" @@ -4621,6 +4628,11 @@ electron-download@^4.1.0, electron-download@^4.1.1: semver "^5.4.1" sumchecker "^2.0.2" +electron-is-dev@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e" + integrity sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw== + electron-notarize@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-0.3.0.tgz#b93c606306eac558b250c78ff95273ddb9fedf0a" @@ -4653,6 +4665,22 @@ electron-publish@22.7.0: lazy-val "^1.0.4" mime "^2.4.5" +electron-reloader@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/electron-reloader/-/electron-reloader-1.0.1.tgz#15b193219b6583aedd2c95fa143d9bfc244bfdec" + integrity sha512-jVLK4SMvLRI8bWMTLtcyoRcmntTWcDrLUFt5QefgdcgQwN8uKi05SMJ8dW+9yD+PM1ESuyE//poBHVmucV4vUg== + dependencies: + chalk "^3.0.0" + chokidar "^3.3.1" + date-time "^3.1.0" + electron-is-dev "^1.1.0" + find-up "^4.1.0" + +electron-serve@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/electron-serve/-/electron-serve-1.0.0.tgz#babf2f5022102fa300a841d91e4c2e7048ac4b1f" + integrity sha512-Rsm4tjj1eK7NUWKgGw6NjHkjfB+bIXZh0ztybUYzqmwCm1wzb7zv95LERbwricDZfCsKHB0V57NgVvHdi2OOAQ== + electron-store@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-5.2.0.tgz#a15718fc1fa21acfd07af55f9b94f9fa6a536665" @@ -5292,6 +5320,22 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +fork-ts-checker-webpack-plugin@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.0.0.tgz#43a8efda935aba382ca88ae169ab11b70041c06a" + integrity sha512-XdMGiyz12rl8HFEj1D9NsC0yxevLZqWncMbuhelV1a1h7ciX7ftauTHIBzO0gKGjqoqZG0NqnrnN7xavIHvzDQ== + dependencies: + "@babel/code-frame" "^7.8.3" + chalk "^2.4.1" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "1.0.0" + semver "^5.6.0" + tapable "^1.0.0" + form-data@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -5374,6 +5418,11 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" +fs-monkey@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.1.tgz#4a82f36944365e619f4454d9fff106553067b781" + integrity sha512-fcSa+wyTqZa46iWweI7/ZiUfegOZl0SG8+dltIwFXo7+zYU9J9kpS3NB6pZcSlJdhvIwp81Adx2XhZorncxiaA== + fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -7585,6 +7634,13 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" +memfs@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.0.tgz#f9438e622b5acd1daa8a4ae160c496fdd1325b26" + integrity sha512-f/xxz2TpdKv6uDn6GtHee8ivFyxwxmPuXatBb1FBwxYNuVpbM3k/Y1Z+vC0mH/dIXXrukYfe3qe5J32Dfjg93A== + dependencies: + fs-monkey "1.0.1" + "memoize-one@>=3.1.1 <6", memoize-one@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" @@ -9838,7 +9894,7 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" -schema-utils@^1.0.0: +schema-utils@1.0.0, schema-utils@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== @@ -10724,6 +10780,11 @@ through@2, through@^2.3.6: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + integrity sha1-mcW/VZWJZq9tBtg73zgA3IL67F0= + timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"