mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Improve how extension-api is exposed/loaded (#1055)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
aa864fc199
commit
4f98a01a8b
1
extensions/example-extension/.gitignore
vendored
1
extensions/example-extension/.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
*.js
|
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
|
|||||||
3445
extensions/example-extension/package-lock.json
generated
3445
extensions/example-extension/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,13 +9,15 @@
|
|||||||
"styles": []
|
"styles": []
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "webpack --config webpack.config.js",
|
||||||
"dev": "tsc --watch"
|
"dev": "tsc --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-open-doodles": "^1.0.5"
|
"react-open-doodles": "^1.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^4.0.3"
|
"ts-loader": "^8.0.4",
|
||||||
|
"typescript": "^4.0.3",
|
||||||
|
"webpack": "^4.44.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Button, Icon, IconProps, LensRendererExtension, React } from "@lens/ui-extensions";
|
import { Button, Icon, IconProps, LensRendererExtension } from "@lens/ui-extensions";
|
||||||
import { CoffeeDoodle } from "react-open-doodles";
|
import { CoffeeDoodle } from "react-open-doodles";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
export function ExtensionIcon(props: IconProps) {
|
export function ExtensionIcon(props: IconProps) {
|
||||||
return <Icon {...props} material="pages" tooltip={path.basename(__filename)}/>
|
return <Icon {...props} material="pages" tooltip={path.basename(__filename)}/>
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"../../types",
|
"../../types",
|
||||||
"./renderer.ts",
|
"./*.ts",
|
||||||
"./main.ts"
|
"./*.tsx"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
|||||||
64
extensions/example-extension/webpack.config.js
Normal file
64
extensions/example-extension/webpack.config.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
entry: './main.ts',
|
||||||
|
context: __dirname,
|
||||||
|
target: "electron-main",
|
||||||
|
mode: "production",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
externals: [
|
||||||
|
{
|
||||||
|
"@lens/extensions": "var global.LensExtensions",
|
||||||
|
"mobx": "var global.Mobx",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
extensions: [ '.tsx', '.ts', '.js' ],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
libraryTarget: "commonjs2",
|
||||||
|
filename: 'main.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entry: './renderer.ts',
|
||||||
|
context: __dirname,
|
||||||
|
target: "electron-renderer",
|
||||||
|
mode: "production",
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
externals: [
|
||||||
|
{
|
||||||
|
"@lens/ui-extensions": "var global.LensExtensions",
|
||||||
|
"react": "var global.React",
|
||||||
|
"mobx": "var global.Mobx"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
resolve: {
|
||||||
|
extensions: [ '.tsx', '.ts', '.js' ],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
libraryTarget: "commonjs2",
|
||||||
|
globalObject: "this",
|
||||||
|
filename: 'renderer.js',
|
||||||
|
path: path.resolve(__dirname, 'dist'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -17,13 +17,11 @@
|
|||||||
"dev:main": "yarn compile:main --watch",
|
"dev:main": "yarn compile:main --watch",
|
||||||
"dev:renderer": "yarn compile:renderer --watch",
|
"dev:renderer": "yarn compile:renderer --watch",
|
||||||
"dev:extension-rollup": "yarn compile:extension-rollup --watch",
|
"dev:extension-rollup": "yarn compile:extension-rollup --watch",
|
||||||
"dev:extension-api": "yarn compile:extension-api --watch",
|
|
||||||
"compile": "env NODE_ENV=production concurrently yarn:compile:*",
|
"compile": "env NODE_ENV=production concurrently yarn:compile:*",
|
||||||
"compile:main": "webpack --config webpack.main.ts",
|
"compile:main": "webpack --config webpack.main.ts",
|
||||||
"compile:renderer": "webpack --config webpack.renderer.ts",
|
"compile:renderer": "webpack --config webpack.renderer.ts",
|
||||||
"compile:i18n": "lingui compile",
|
"compile:i18n": "lingui compile",
|
||||||
"compile:extension-rollup": "rollup --config src/extensions/rollup.config.js",
|
"compile:extension-rollup": "rollup --config src/extensions/rollup.config.js",
|
||||||
"compile:extension-api": "webpack --config webpack.extensions.ts",
|
|
||||||
"build:linux": "yarn compile && electron-builder --linux --dir -c.productName=Lens",
|
"build:linux": "yarn compile && electron-builder --linux --dir -c.productName=Lens",
|
||||||
"build:mac": "yarn compile && electron-builder --mac --dir -c.productName=Lens",
|
"build:mac": "yarn compile && electron-builder --mac --dir -c.productName=Lens",
|
||||||
"build:win": "yarn compile && electron-builder --win --dir -c.productName=Lens",
|
"build:win": "yarn compile && electron-builder --win --dir -c.productName=Lens",
|
||||||
@ -200,7 +198,6 @@
|
|||||||
"mobx": "^5.15.5",
|
"mobx": "^5.15.5",
|
||||||
"mobx-observable-history": "^1.0.3",
|
"mobx-observable-history": "^1.0.3",
|
||||||
"mock-fs": "^4.12.0",
|
"mock-fs": "^4.12.0",
|
||||||
"module-alias": "^2.2.2",
|
|
||||||
"node-machine-id": "^1.1.12",
|
"node-machine-id": "^1.1.12",
|
||||||
"node-pty": "^0.9.0",
|
"node-pty": "^0.9.0",
|
||||||
"npm": "^6.14.8",
|
"npm": "^6.14.8",
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import packageInfo from "../../package.json"
|
import packageInfo from "../../package.json"
|
||||||
import { defineGlobal } from "./utils/defineGlobal";
|
import { defineGlobal } from "./utils/defineGlobal";
|
||||||
import { addAlias } from "module-alias";
|
|
||||||
|
|
||||||
export const isMac = process.platform === "darwin"
|
export const isMac = process.platform === "darwin"
|
||||||
export const isWindows = process.platform === "win32"
|
export const isWindows = process.platform === "win32"
|
||||||
@ -37,15 +36,6 @@ defineGlobal("__static", {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Special dynamic module aliases
|
|
||||||
if (isProduction && process.resourcesPath) {
|
|
||||||
addAlias("@lens/extensions", path.join(process.resourcesPath, "static", `build/${extensionsLibName}.js`))
|
|
||||||
addAlias("@lens/ui-extensions", path.join(process.resourcesPath, "static", `build/${extensionsRendererLibName}.js`))
|
|
||||||
} else {
|
|
||||||
addAlias("@lens/extensions", path.join(contextDir, "static", `build/${extensionsLibName}.js`))
|
|
||||||
addAlias("@lens/ui-extensions", path.join(contextDir, "static", `build/${extensionsRendererLibName}.js`))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apis
|
// Apis
|
||||||
export const apiPrefix = "/api" // local router apis
|
export const apiPrefix = "/api" // local router apis
|
||||||
export const apiKubePrefix = "/api-kube" // k8s cluster apis
|
export const apiKubePrefix = "/api-kube" // k8s cluster apis
|
||||||
|
|||||||
@ -18,16 +18,6 @@ export function extensionPackagesRoot() {
|
|||||||
return path.join((app || remote.app).getPath("userData"))
|
return path.join((app || remote.app).getPath("userData"))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function withExtensionPackagesRoot(callback: Function) {
|
|
||||||
const cwd = process.cwd()
|
|
||||||
try {
|
|
||||||
process.chdir(extensionPackagesRoot())
|
|
||||||
return callback()
|
|
||||||
} finally {
|
|
||||||
process.chdir(cwd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ExtensionLoader {
|
export class ExtensionLoader {
|
||||||
@observable extensions = observable.map<ExtensionId, InstalledExtension>([], { deep: false });
|
@observable extensions = observable.map<ExtensionId, InstalledExtension>([], { deep: false });
|
||||||
@observable instances = observable.map<ExtensionId, LensExtension>([], { deep: false })
|
@observable instances = observable.map<ExtensionId, LensExtension>([], { deep: false })
|
||||||
@ -89,21 +79,19 @@ export class ExtensionLoader {
|
|||||||
|
|
||||||
protected requireExtension(extension: InstalledExtension) {
|
protected requireExtension(extension: InstalledExtension) {
|
||||||
let extEntrypoint = ""
|
let extEntrypoint = ""
|
||||||
return withExtensionPackagesRoot(() => {
|
try {
|
||||||
try {
|
if (ipcRenderer && extension.manifest.renderer) {
|
||||||
if (ipcRenderer && extension.manifest.renderer) {
|
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.renderer))
|
||||||
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.renderer))
|
} else if (extension.manifest.main) {
|
||||||
} else if (extension.manifest.main) {
|
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.main))
|
||||||
extEntrypoint = path.resolve(path.join(path.dirname(extension.manifestPath), extension.manifest.main))
|
|
||||||
}
|
|
||||||
if (extEntrypoint !== "") {
|
|
||||||
return __non_webpack_require__(extEntrypoint)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`[EXTENSION-LOADER]: can't load extension main at ${extEntrypoint}: ${err}`, { extension });
|
|
||||||
console.trace(err)
|
|
||||||
}
|
}
|
||||||
})
|
if (extEntrypoint !== "") {
|
||||||
|
return __non_webpack_require__(extEntrypoint)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`[EXTENSION-LOADER]: can't load extension main at ${extEntrypoint}: ${err}`, { extension });
|
||||||
|
console.trace(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getById(id: ExtensionId): InstalledExtension {
|
getById(id: ExtensionId): InstalledExtension {
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
// Lens-extensions api developer's kit
|
// Lens-extensions api developer's kit
|
||||||
export type { LensExtensionRuntimeEnv } from "./lens-renderer-runtime"
|
export type { LensExtensionRuntimeEnv } from "./lens-renderer-runtime"
|
||||||
export type { PageStore } from "./page-store"
|
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
|
export * from "./lens-extension"
|
||||||
export * from "./lens-renderer-extension"
|
export * from "./lens-renderer-extension"
|
||||||
export { DynamicPageType } from "./page-store"
|
export { DynamicPageType, PageStore } from "./page-store"
|
||||||
|
|
||||||
// TODO: add more common re-usable UI components + refactor interfaces (Props -> ComponentProps)
|
// TODO: add more common re-usable UI components + refactor interfaces (Props -> ComponentProps)
|
||||||
export { default as React } from "react"
|
|
||||||
export * from "../renderer/components/icon"
|
export * from "../renderer/components/icon"
|
||||||
export * from "../renderer/components/tooltip"
|
export * from "../renderer/components/tooltip"
|
||||||
export * from "../renderer/components/button"
|
export * from "../renderer/components/button"
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import type { PageStore } from "./extension-renderer-api"
|
|||||||
import type { PageRegistration } from "./page-store"
|
import type { PageRegistration } from "./page-store"
|
||||||
import { LensExtension } from "./lens-extension"
|
import { LensExtension } from "./lens-extension"
|
||||||
|
|
||||||
export abstract class LensRendererExtension extends LensExtension {
|
export class LensRendererExtension extends LensExtension {
|
||||||
|
|
||||||
registerPages(pageStore: PageStore) {
|
registerPages(pageStore: PageStore) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,10 +17,17 @@ import { clusterStore } from "../common/cluster-store"
|
|||||||
import { userStore } from "../common/user-store";
|
import { userStore } from "../common/user-store";
|
||||||
import { workspaceStore } from "../common/workspace-store";
|
import { workspaceStore } from "../common/workspace-store";
|
||||||
import { tracker } from "../common/tracker";
|
import { tracker } from "../common/tracker";
|
||||||
|
import * as LensExtensions from "../extensions/extension-api";
|
||||||
import { extensionManager } from "../extensions/extension-manager";
|
import { extensionManager } from "../extensions/extension-manager";
|
||||||
import { extensionLoader } from "../extensions/extension-loader";
|
import { extensionLoader } from "../extensions/extension-loader";
|
||||||
import { getLensRuntime } from "../extensions/lens-runtime";
|
import { getLensRuntime } from "../extensions/lens-runtime";
|
||||||
import logger from "./logger"
|
import logger from "./logger"
|
||||||
|
import * as Mobx from "mobx"
|
||||||
|
|
||||||
|
export {
|
||||||
|
LensExtensions,
|
||||||
|
Mobx
|
||||||
|
}
|
||||||
|
|
||||||
const workingDir = path.join(app.getPath("appData"), appName);
|
const workingDir = path.join(app.getPath("appData"), appName);
|
||||||
app.setName(appName);
|
app.setName(appName);
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import "./components/app.scss"
|
import "./components/app.scss"
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import * as Mobx from "mobx"
|
||||||
|
import * as LensExtensions from "../extensions/extension-renderer-api"
|
||||||
import { render, unmountComponentAtNode } from "react-dom";
|
import { render, unmountComponentAtNode } from "react-dom";
|
||||||
import { isMac } from "../common/vars";
|
import { isMac } from "../common/vars";
|
||||||
import { userStore } from "../common/user-store";
|
import { userStore } from "../common/user-store";
|
||||||
@ -14,6 +16,12 @@ type AppComponent = React.ComponentType & {
|
|||||||
init?(): void;
|
init?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
React,
|
||||||
|
Mobx,
|
||||||
|
LensExtensions
|
||||||
|
}
|
||||||
|
|
||||||
export async function bootstrap(App: AppComponent) {
|
export async function bootstrap(App: AppComponent) {
|
||||||
const rootElem = document.getElementById("app")
|
const rootElem = document.getElementById("app")
|
||||||
rootElem.classList.toggle("is-mac", isMac);
|
rootElem.classList.toggle("is-mac", isMac);
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
import { extensionsDir, extensionsLibName, extensionsRendererLibName } from "./src/common/vars";
|
|
||||||
import path from "path";
|
|
||||||
import webpack from "webpack";
|
|
||||||
import nodeExternals from "webpack-node-externals";
|
|
||||||
import { webpackLensRenderer } from "./webpack.renderer";
|
|
||||||
import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin";
|
|
||||||
import ProgressBarPlugin from "progress-bar-webpack-plugin";
|
|
||||||
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
||||||
|
|
||||||
export default [
|
|
||||||
webpackExtensionsApi,
|
|
||||||
webpackExtensionsRendererApi
|
|
||||||
]
|
|
||||||
|
|
||||||
// todo: use common chunks/externals for "react", "react-dom", etc.
|
|
||||||
export function webpackExtensionsApi(): webpack.Configuration {
|
|
||||||
const config = webpackLensRenderer({ showVars: false })
|
|
||||||
config.name = "extensions-api"
|
|
||||||
config.entry = {
|
|
||||||
[extensionsLibName]: path.resolve(extensionsDir, "extension-api.ts")
|
|
||||||
}
|
|
||||||
config.externals = [
|
|
||||||
nodeExternals()
|
|
||||||
]
|
|
||||||
config.plugins = [
|
|
||||||
new ProgressBarPlugin(),
|
|
||||||
new ForkTsCheckerPlugin(),
|
|
||||||
]
|
|
||||||
config.output.libraryTarget = "commonjs2"
|
|
||||||
config.devtool = "nosources-source-map"
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
export function webpackExtensionsRendererApi(): webpack.Configuration {
|
|
||||||
const config = webpackLensRenderer({ showVars: false })
|
|
||||||
config.name = "extensions-renderer-api"
|
|
||||||
config.entry = {
|
|
||||||
[extensionsRendererLibName]: path.resolve(extensionsDir, "extension-renderer-api.ts")
|
|
||||||
}
|
|
||||||
config.plugins = [
|
|
||||||
new ProgressBarPlugin(),
|
|
||||||
new ForkTsCheckerPlugin(),
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
filename: "[name].css",
|
|
||||||
})
|
|
||||||
]
|
|
||||||
config.output.libraryTarget = "commonjs2"
|
|
||||||
config.devtool = "nosources-source-map"
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
@ -17,16 +17,12 @@ export default function (): webpack.Configuration {
|
|||||||
main: path.resolve(mainDir, "index.ts"),
|
main: path.resolve(mainDir, "index.ts"),
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
libraryTarget: "global",
|
||||||
path: buildDir,
|
path: buildDir,
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.json', '.js', '.ts']
|
extensions: ['.json', '.js', '.ts']
|
||||||
},
|
},
|
||||||
node: {
|
|
||||||
// webpack modifies node internals by default, keep as is for main-process
|
|
||||||
__dirname: false,
|
|
||||||
__filename: false,
|
|
||||||
},
|
|
||||||
externals: [
|
externals: [
|
||||||
nodeExternals()
|
nodeExternals()
|
||||||
],
|
],
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export function webpackLensRenderer({ showVars = true } = {}): webpack.Configura
|
|||||||
[appName]: path.resolve(rendererDir, "bootstrap.tsx"),
|
[appName]: path.resolve(rendererDir, "bootstrap.tsx"),
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
libraryTarget: "global",
|
||||||
|
library: "",
|
||||||
|
globalObject: "this",
|
||||||
publicPath: publicPath,
|
publicPath: publicPath,
|
||||||
path: buildDir,
|
path: buildDir,
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
|
|||||||
@ -8971,11 +8971,6 @@ mock-fs@^4.12.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.12.0.tgz#a5d50b12d2d75e5bec9dac3b67ffe3c41d31ade4"
|
resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.12.0.tgz#a5d50b12d2d75e5bec9dac3b67ffe3c41d31ade4"
|
||||||
integrity sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ==
|
integrity sha512-/P/HtrlvBxY4o/PzXY9cCNBrdylDNxg7gnrv2sMNxj+UJ2m8jSpl0/A6fuJeNAWr99ZvGWH8XCbE0vmnM5KupQ==
|
||||||
|
|
||||||
module-alias@^2.2.2:
|
|
||||||
version "2.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
|
|
||||||
integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
|
|
||||||
|
|
||||||
moment@^2.10.2, moment@^2.26.0:
|
moment@^2.10.2, moment@^2.26.0:
|
||||||
version "2.26.0"
|
version "2.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user