1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix failing to run built version

- Finally make logger fully injectable
- Simplify startMainApplication to only have runMany(Sync) invocations
  to fix time of use bugs related to logger

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-11-15 14:18:10 -05:00
parent cd8a6f8dcc
commit 22ea834a88
19 changed files with 303 additions and 154 deletions

View File

@ -365,6 +365,7 @@
"@typescript-eslint/parser": "^5.42.1",
"adr": "^1.4.3",
"ansi_up": "^5.1.0",
"chalk": "^4.1.2",
"chart.js": "^2.9.4",
"circular-dependency-plugin": "^5.2.2",
"cli-progress": "^3.11.2",

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import appPathsInjectable from "./app-paths.injectable";
const directoryForLogsInjectable = getInjectable({
id: "directory-for-logs",
instantiate: (di) => di.inject(appPathsInjectable).logs,
});
export default directoryForLogsInjectable;

View File

@ -3,12 +3,19 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { createLogger, format } from "winston";
import type { Logger } from "./logger";
import logger from "./logger";
import { loggerTransportInjectionToken } from "./logger/transports";
const loggerInjectable = getInjectable({
id: "logger",
instantiate: (): Logger => logger,
instantiate: (di): Logger => createLogger({
format: format.combine(
format.splat(),
format.simple(),
),
transports: di.injectMany(loggerTransportInjectionToken),
}),
});
export default loggerInjectable;

View File

@ -3,12 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { app, ipcMain } from "electron";
import winston, { format } from "winston";
import type Transport from "winston-transport";
import { isDebugging, isTestEnv } from "./vars";
import BrowserConsole from "winston-transport-browserconsole";
import { ConsoleFormat } from "./logger-formaters/console-format";
import { asLegacyGlobalForExtensionApi } from "../extensions/as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
import loggerInjectable from "./logger.injectable";
export interface Logger {
info: (message: string, ...args: any) => void;
@ -18,64 +14,7 @@ export interface Logger {
silly: (message: string, ...args: any) => void;
}
const logLevel = process.env.LOG_LEVEL
? process.env.LOG_LEVEL
: isDebugging
? "debug"
: isTestEnv
? "error"
: "info";
const transports: Transport[] = [];
if (ipcMain) {
transports.push(
new winston.transports.Console({
handleExceptions: false,
level: logLevel,
format: format.combine(
format.colorize({ level: true, message: false }),
format.padLevels(),
format.ms(),
new ConsoleFormat({
showMeta: true,
inspectOptions: {
depth: 4,
colors: true,
maxArrayLength: 10,
breakLength: 120,
compact: Infinity,
},
}),
),
}),
);
if (!isTestEnv) {
transports.push(
new winston.transports.File({
handleExceptions: false,
level: "debug",
filename: "lens.log",
/**
* SAFTEY: the `ipcMain` check above should mean that this is only
* called in the main process
*/
dirname: app.getPath("logs"),
maxsize: 1024 * 1024,
maxFiles: 16,
tailable: true,
}),
);
}
} else {
transports.push(new BrowserConsole());
}
export default winston.createLogger({
format: format.combine(
format.splat(),
format.simple(),
),
transports,
}) as Logger;
/**
* @deprecated use `di.inject(loggerInjectable)` instead
*/
export default asLegacyGlobalForExtensionApi(loggerInjectable);

View File

@ -0,0 +1,11 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type TransportStream from "winston-transport";
export const loggerTransportInjectionToken = getInjectionToken<TransportStream>({
id: "logger-transport",
});

View File

@ -12,8 +12,8 @@ import { pathNames } from "../../common/app-paths/app-path-names";
import { fromPairs, map } from "lodash/fp";
import { pipeline } from "@ogre-tools/fp";
import joinPathsInjectable from "../../common/path/join-paths.injectable";
import { beforeElectronIsReadyInjectionToken } from "../start-main-application/runnable-tokens/before-electron-is-ready-injection-token";
import appNameInjectable from "../../common/vars/app-name.injectable";
import { appPathsRunnablePhaseInjectionToken } from "../start-main-application/runnable-tokens/phases";
const setupAppPathsInjectable = getInjectable({
id: "setup-app-paths",
@ -51,7 +51,7 @@ const setupAppPathsInjectable = getInjectable({
};
},
injectionToken: beforeElectronIsReadyInjectionToken,
injectionToken: appPathsRunnablePhaseInjectionToken,
});
export default setupAppPathsInjectable;

View File

@ -11,15 +11,10 @@ import * as LensExtensionsCommonApi from "../extensions/common-api";
import * as LensExtensionsMainApi from "../extensions/main-api";
import { getDi } from "./getDi";
import startMainApplicationInjectable from "./start-main-application/start-main-application.injectable";
import shouldStartHiddenInjectable from "./electron-app/features/should-start-hidden.injectable";
const di = getDi();
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
const startApplication = di.inject(startMainApplicationInjectable);
void startApplication(!shouldStartHidden);
void di.inject(startMainApplicationInjectable);
/**
* Exports for virtual package "@k8slens/extensions" for main-process.

View File

@ -4,7 +4,7 @@
*/
import { LEVEL, MESSAGE, SPLAT } from "triple-beam";
import colors from "colors/safe";
import chalk from "chalk";
import type { InspectOptions } from "util";
import { inspect } from "util";
@ -77,7 +77,7 @@ export class ConsoleFormat {
private message(info: TransformableInfo, chr: string, color: string): string {
const message = info.message.replace(
ConsoleFormat.reSpacesOrEmpty,
`$1${color}${colors.dim(chr)}${colors.reset(" ")}`,
`$1${color}${chalk.dim(chr)}${chalk.reset(" ")}`,
);
return `${info.level}:${message}`;
@ -89,7 +89,7 @@ export class ConsoleFormat {
private ms(info: TransformableInfo): string {
if (info.ms) {
return colors.italic(colors.dim(` ${info.ms}`));
return chalk.italic(chalk.dim(` ${info.ms}`));
}
return "";
@ -152,13 +152,13 @@ export class ConsoleFormat {
const pad = this.pad(info.message);
messages.forEach((line, index, arr) => {
const lineNumber = colors.dim(`[${(index + 1).toString().padStart(arr.length.toString().length, " ")}]`);
const lineNumber = chalk.dim(`[${(index + 1).toString().padStart(arr.length.toString().length, " ")}]`);
let chr = ConsoleFormat.chars.line;
if (index === arr.length - 1) {
chr = ConsoleFormat.chars.endLine;
}
info[MESSAGE] += `\n${colors.dim(info.level)}:${pad}${color}${colors.dim(chr)}${colors.reset(" ")}`;
info[MESSAGE] += `\n${chalk.dim(info.level)}:${pad}${color}${chalk.dim(chr)}${chalk.reset(" ")}`;
info[MESSAGE] += `${lineNumber} ${line}`;
});
}

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { format, transports } from "winston";
import { ConsoleFormat } from "./console-format";
import { loggerTransportInjectionToken } from "../../common/logger/transports";
import logLevelInjectable from "./level.injectable";
const consoleLoggerTransportInjectable = getInjectable({
id: "console-logger-transport",
instantiate: (di) => new transports.Console({
handleExceptions: false,
level: di.inject(logLevelInjectable),
format: format.combine(
format.colorize({ level: true, message: false }),
format.padLevels(),
format.ms(),
new ConsoleFormat({
showMeta: true,
inspectOptions: {
depth: 4,
colors: true,
maxArrayLength: 10,
breakLength: 120,
compact: Infinity,
},
}),
),
}),
injectionToken: loggerTransportInjectionToken,
});
export default consoleLoggerTransportInjectable;

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { transports } from "winston";
import directoryForLogsInjectable from "../../common/app-paths/directory-for-logs.injectable";
import { loggerTransportInjectionToken } from "../../common/logger/transports";
const fileLoggerTranportInjectable = getInjectable({
id: "file-logger-tranport",
instantiate: (di) => new transports.File({
handleExceptions: false,
level: "debug",
filename: "lens.log",
/**
* SAFTEY: the `ipcMain` check above should mean that this is only
* called in the main process
*/
dirname: di.inject(directoryForLogsInjectable),
maxsize: 1024 * 1024,
maxFiles: 16,
tailable: true,
}),
injectionToken: loggerTransportInjectionToken,
});
export default fileLoggerTranportInjectable;

View File

@ -0,0 +1,9 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../../common/test-utils/get-global-override";
import logLevelInjectable from "./level.injectable";
export default getGlobalOverride(logLevelInjectable, () => "error");

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import isDebuggingInjectable from "../../common/vars/is-debugging.injectable";
export type LogLevel = "silly" | "debug" | "info" | "warn" | "error";
const logLevelInjectable = getInjectable({
id: "log-level",
instantiate: (di): LogLevel => {
const isDebugging = di.inject(isDebuggingInjectable);
const baseLevel = process.env.LOG_LEVEL?.toLowerCase();
switch (baseLevel) {
case "silly":
case "debug":
case "info":
case "warn":
case "error":
return baseLevel;
default:
return isDebugging ? "debug" : "info";
}
},
causesSideEffects: true,
});
export default logLevelInjectable;

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { Runnable } from "../../../common/runnable/run-many-for";
import type { RunnableSync } from "../../../common/runnable/run-many-sync-for";
/**
* These tokens are here so that the importing of their respective dependencies
* can be delayed until all of them are ready
*/
/**
* This runnable token should only have the app paths init so that it can be run by itself
*/
export const appPathsRunnablePhaseInjectionToken = getInjectionToken<RunnableSync>({
id: "app-paths-runnable-phase",
});
export const showLoadingRunnablePhaseInjectionToken = getInjectionToken<Runnable>({
id: "show-loading-runnable-phase",
});
export const showInitialWindowRunnablePhaseInjectionToken = getInjectionToken<Runnable>({
id: "show-initial-window-runnable-phase",
});

View File

@ -0,0 +1,51 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import shouldStartHiddenInjectable from "../../electron-app/features/should-start-hidden.injectable";
import openDeepLinkInjectable from "../../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable";
import commandLineArgumentsInjectable from "../../utils/command-line-arguments.injectable";
import createFirstApplicationWindowInjectable from "../lens-window/application-window/create-first-application-window.injectable";
import splashWindowInjectable from "../lens-window/splash-window/splash-window.injectable";
import { showInitialWindowRunnablePhaseInjectionToken } from "../runnable-tokens/phases";
const getDeepLinkUrl = (commandLineArguments: string[]) => (
commandLineArguments
.map(arg => arg.toLowerCase())
.find(arg => arg.startsWith("lens://"))
);
const showInitialWindowInjectable = getInjectable({
id: "show-initial-window",
instantiate: (di) => {
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
const shouldStartWindow = !shouldStartHidden;
const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable);
const splashWindow = di.inject(splashWindowInjectable);
const openDeepLink = di.inject(openDeepLinkInjectable);
const commandLineArguments = di.inject(commandLineArgumentsInjectable);
return {
id: "show-initial-window",
run: async () => {
if (shouldStartWindow) {
const deepLinkUrl = getDeepLinkUrl(commandLineArguments);
if (deepLinkUrl) {
await openDeepLink(deepLinkUrl);
} else {
const applicationWindow = createFirstApplicationWindow();
await applicationWindow.start();
}
splashWindow.close();
}
},
};
},
injectionToken: showInitialWindowRunnablePhaseInjectionToken,
});
export default showInitialWindowInjectable;

View File

@ -0,0 +1,29 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import shouldStartHiddenInjectable from "../../electron-app/features/should-start-hidden.injectable";
import splashWindowInjectable from "../lens-window/splash-window/splash-window.injectable";
import { showLoadingRunnablePhaseInjectionToken } from "../runnable-tokens/phases";
const showLoadingInjectable = getInjectable({
id: "show-loading",
instantiate: (di) => {
const shouldStartHidden = di.inject(shouldStartHiddenInjectable);
const shouldShowLoadingWindow = !shouldStartHidden;
const splashWindow = di.inject(splashWindowInjectable);
return {
id: "show-loading",
run: async () => {
if (shouldShowLoadingWindow) {
await splashWindow.start();
}
},
};
},
injectionToken: showLoadingRunnablePhaseInjectionToken,
});
export default showLoadingInjectable;

View File

@ -10,13 +10,8 @@ import { beforeElectronIsReadyInjectionToken } from "./runnable-tokens/before-el
import { beforeApplicationIsLoadingInjectionToken } from "./runnable-tokens/before-application-is-loading-injection-token";
import { onLoadOfApplicationInjectionToken } from "./runnable-tokens/on-load-of-application-injection-token";
import { afterApplicationIsLoadedInjectionToken } from "./runnable-tokens/after-application-is-loaded-injection-token";
import splashWindowInjectable from "./lens-window/splash-window/splash-window.injectable";
import openDeepLinkInjectable from "../protocol-handler/lens-protocol-router-main/open-deep-link-for-url/open-deep-link.injectable";
import { pipeline } from "@ogre-tools/fp";
import { find, map, startsWith, toLower } from "lodash/fp";
import commandLineArgumentsInjectable from "../utils/command-line-arguments.injectable";
import waitForElectronToBeReadyInjectable from "../electron-app/features/wait-for-electron-to-be-ready.injectable";
import createFirstApplicationWindowInjectable from "./lens-window/application-window/create-first-application-window.injectable";
import { appPathsRunnablePhaseInjectionToken, showInitialWindowRunnablePhaseInjectionToken, showLoadingRunnablePhaseInjectionToken } from "./runnable-tokens/phases";
const startMainApplicationInjectable = getInjectable({
id: "start-main-application",
@ -25,53 +20,29 @@ const startMainApplicationInjectable = getInjectable({
const runMany = runManyFor(di);
const runManySync = runManySyncFor(di);
const waitForElectronToBeReady = di.inject(waitForElectronToBeReadyInjectable);
const createFirstApplicationWindow = di.inject(createFirstApplicationWindowInjectable);
const splashWindow = di.inject(splashWindowInjectable);
const openDeepLink = di.inject(openDeepLinkInjectable);
const commandLineArguments = di.inject(commandLineArgumentsInjectable);
const appPathsRunnablePhase = runManySync(appPathsRunnablePhaseInjectionToken);
const beforeElectronIsReady = runManySync(beforeElectronIsReadyInjectionToken);
const beforeApplicationIsLoading = runMany(beforeApplicationIsLoadingInjectionToken);
const showLoadingRunnablePhase = runMany(showLoadingRunnablePhaseInjectionToken);
const onLoadOfApplication = runMany(onLoadOfApplicationInjectionToken);
const showInitialWindowRunnablePhase = runMany(showInitialWindowRunnablePhaseInjectionToken);
const afterApplicationIsLoaded = runMany(afterApplicationIsLoadedInjectionToken);
return (shouldStartWindow: boolean) => {
// Stuff happening before application is ready needs to be synchronous because of
// https://github.com/electron/electron/issues/21370
beforeElectronIsReady();
// Stuff happening before application is ready needs to be synchronous because of
// https://github.com/electron/electron/issues/21370
appPathsRunnablePhase();
beforeElectronIsReady();
return (async () => {
await waitForElectronToBeReady();
await beforeApplicationIsLoading();
if (shouldStartWindow) {
await splashWindow.start();
}
await onLoadOfApplication();
if (shouldStartWindow) {
const deepLinkUrl = getDeepLinkUrl(commandLineArguments);
if (deepLinkUrl) {
await openDeepLink(deepLinkUrl);
} else {
const applicationWindow = createFirstApplicationWindow();
await applicationWindow.start();
}
splashWindow.close();
}
await afterApplicationIsLoaded();
})();
};
return (async () => {
await waitForElectronToBeReady();
await beforeApplicationIsLoading();
await showLoadingRunnablePhase();
await onLoadOfApplication();
await showInitialWindowRunnablePhase();
await afterApplicationIsLoaded();
})();
},
});
const getDeepLinkUrl = (commandLineArguments: string[]) =>
pipeline(commandLineArguments, map(toLower), find(startsWith("lens://")));
export default startMainApplicationInjectable;

View File

@ -68,6 +68,7 @@ import applicationMenuItemCompositeInjectable from "../../../features/applicatio
import { getCompositePaths } from "../../../common/utils/composite/get-composite-paths/get-composite-paths";
import { discoverFor } from "./discovery-of-html-elements";
import { findComposite } from "../../../common/utils/composite/find-composite/find-composite";
import shouldStartHiddenInjectable from "../../../main/electron-app/features/should-start-hidden.injectable";
type Callback = (di: DiContainer) => void | Promise<void>;
@ -313,11 +314,9 @@ export const getApplicationBuilder = () => {
.map(toWindowWithHelpersFor(windowHelpers)),
get: (id) => {
const applicationWindows = builder.applicationWindow.getAll();
const applicationWindow = applicationWindows.find(
(window) => window.id === id,
);
const applicationWindow = builder.applicationWindow
.getAll()
.find((window) => window.id === id);
if (!applicationWindow) {
throw new Error(`Tried to get application window with ID "${id}" but it was not found.`);
@ -327,9 +326,7 @@ export const getApplicationBuilder = () => {
},
create: (id) => {
const createApplicationWindow = mainDi.inject(
createApplicationWindowInjectable,
);
const createApplicationWindow = mainDi.inject(createApplicationWindowInjectable);
createApplicationWindow(id);
@ -656,11 +653,8 @@ export const getApplicationBuilder = () => {
await callback(mainDi);
}
const startMainApplication = mainDi.inject(
startMainApplicationInjectable,
);
await startMainApplication(false);
mainDi.override(shouldStartHiddenInjectable, () => true);
await mainDi.inject(startMainApplicationInjectable);
applicationHasStarted = true;
},
@ -672,21 +666,15 @@ export const getApplicationBuilder = () => {
await callback(mainDi);
}
const startMainApplication = mainDi.inject(
startMainApplicationInjectable,
);
await startMainApplication(true);
mainDi.override(shouldStartHiddenInjectable, () => false);
await mainDi.inject(startMainApplicationInjectable);
applicationHasStarted = true;
const applicationWindow = builder.applicationWindow.get(
"first-application-window",
);
assert(applicationWindow);
return applicationWindow.rendered;
return builder
.applicationWindow
.get("first-application-window")
.rendered;
},
select: {

View File

@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import BrowserConsole from "winston-transport-browserconsole";
import { loggerTransportInjectionToken } from "../../common/logger/transports";
const browserLoggerTransportInjectable = getInjectable({
id: "browser-logger-transport",
instantiate: () => new BrowserConsole(),
injectionToken: loggerTransportInjectionToken,
});
export default browserLoggerTransportInjectable;

View File

@ -6,7 +6,6 @@
import Webpack from "webpack";
import WebpackDevServer from "webpack-dev-server";
import { webpackLensRenderer } from "./renderer";
import logger from "../src/common/logger";
import { buildDir, webpackDevServerPort } from "./vars";
/**
@ -42,6 +41,6 @@ const server = new WebpackDevServer({
},
}, compiler);
logger.info(`[WEBPACK-DEV-SERVER]: created with options`, server.options);
console.info(`[WEBPACK-DEV-SERVER]: created with options`, server.options);
server.start();