diff --git a/.eslintrc.js b/.eslintrc.js index a8876a1510..da18d19a95 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { extends: [ - require.resolve('@backstage/cli/config/eslint.js'), + require.resolve('@backstage/cli/config/eslint'), '@spotify/eslint-config-oss', ], }; diff --git a/packages/app/.eslintrc.js b/packages/app/.eslintrc.js index b321cd0fb8..930c98ee1b 100644 --- a/packages/app/.eslintrc.js +++ b/packages/app/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], overrides: [ { files: ['**/*.ts?(x)'], diff --git a/packages/cli/.eslintrc.js b/packages/cli/.eslintrc.js index f3f858836d..4ae4e8d91b 100644 --- a/packages/cli/.eslintrc.js +++ b/packages/cli/.eslintrc.js @@ -1,4 +1,5 @@ module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], ignorePatterns: ['templates/**'], rules: { 'no-console': 0, diff --git a/packages/cli/config/eslint.js b/packages/cli/config/eslint.js index 983a423a57..230a95c324 100644 --- a/packages/cli/config/eslint.js +++ b/packages/cli/config/eslint.js @@ -65,7 +65,7 @@ module.exports = { }, }, { - files: ['**/*.test.*', '**/src/setupTests.*'], + files: ['*.test.*', 'src/setupTests.*', 'dev/**'], rules: { // Tests are allowed to import dev dependencies 'import/no-extraneous-dependencies': [ diff --git a/packages/cli/src/commands/plugin/rollup.config.ts b/packages/cli/src/commands/plugin/rollup.config.ts index f2c46d1976..e267bb9582 100644 --- a/packages/cli/src/commands/plugin/rollup.config.ts +++ b/packages/cli/src/commands/plugin/rollup.config.ts @@ -46,6 +46,17 @@ export default { json(), typescript({ include: `${paths.resolveTarget('src')}/**/*.{js,jsx,ts,tsx}`, + tsconfigOverride: { + // The dev folder is for the local plugin serve, ignore it in the build + // If we don't do this we get a folder structure similar to dist/{src,dev}/... + exclude: ['dev'], + compilerOptions: { + // Use absolute path to src dir as root for declarations, relying on the default + // seems to produce declaration maps that are relative to dist/ instead of src/ + // Using a relative path like ../src doesn't work either becaus it will be used as is in subdirs. + sourceRoot: paths.resolveTarget('src'), + }, + }, clean: true, }), ], diff --git a/packages/cli/src/commands/plugin/serve/config.ts b/packages/cli/src/commands/plugin/serve/config.ts index c3f850d00a..7381165b5d 100644 --- a/packages/cli/src/commands/plugin/serve/config.ts +++ b/packages/cli/src/commands/plugin/serve/config.ts @@ -31,18 +31,19 @@ export function createConfig(paths: Paths): webpack.Configuration { profile: false, bail: false, devtool: 'cheap-module-eval-source-map', - context: paths.appPath, + context: paths.targetPath, entry: [ `${require.resolve('webpack-dev-server/client')}?/`, require.resolve('webpack/hot/dev-server'), - paths.appDevEntry, + paths.targetDevEntry, ], resolve: { - extensions: ['.ts', '.tsx', '.js', '.jsx'], + extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'], + modules: ['node_modules', paths.targetSrc], plugins: [ new ModuleScopePlugin( - [paths.appSrc, paths.appDev], - [paths.appPackageJson], + [paths.targetSrc, paths.targetDev], + [paths.targetPackageJson], ), ], }, @@ -51,7 +52,7 @@ export function createConfig(paths: Paths): webpack.Configuration { { test: /\.(tsx?|jsx?|mjs)$/, enforce: 'pre', - include: [paths.appSrc, paths.appDev], + include: [paths.targetSrc, paths.targetDev], use: { loader: 'eslint-loader', options: { @@ -61,7 +62,7 @@ export function createConfig(paths: Paths): webpack.Configuration { }, { test: /\.(tsx?|jsx?|mjs)$/, - include: [paths.appSrc, paths.appDev], + include: [paths.targetSrc, paths.targetDev], exclude: /node_modules/, loader: 'ts-loader', options: { @@ -72,7 +73,7 @@ export function createConfig(paths: Paths): webpack.Configuration { { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.frag/, /\.xml/], loader: 'url-loader', - include: paths.appAssets, + include: paths.targetAssets, options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]', @@ -98,15 +99,15 @@ export function createConfig(paths: Paths): webpack.Configuration { }, plugins: [ new HtmlWebpackPlugin({ - template: paths.appHtml, + template: paths.targetHtml, }), new ForkTsCheckerWebpackPlugin({ - tsconfig: paths.appTsConfig, + tsconfig: paths.targetTsConfig, eslint: true, eslintOptions: { parserOptions: { - project: paths.appTsConfig, - tsconfigRootDir: paths.appPath, + project: paths.targetTsConfig, + tsconfigRootDir: paths.targetPath, }, }, reportFiles: ['**', '!**/__tests__/**', '!**/?(*.)(spec|test).*'], diff --git a/packages/cli/src/commands/plugin/serve/index.ts b/packages/cli/src/commands/plugin/serve/index.ts index de6f871b0e..00c7728b63 100644 --- a/packages/cli/src/commands/plugin/serve/index.ts +++ b/packages/cli/src/commands/plugin/serve/index.ts @@ -15,7 +15,13 @@ */ import { startDevServer } from './server'; +import { watchDeps } from 'lib/watchDeps'; export default async () => { + await watchDeps({ build: true }); + await startDevServer(); + + // Wait for interrupt signal + await new Promise(() => {}); }; diff --git a/packages/cli/src/commands/plugin/serve/paths.ts b/packages/cli/src/commands/plugin/serve/paths.ts index 732efc46f1..b44a7bff74 100644 --- a/packages/cli/src/commands/plugin/serve/paths.ts +++ b/packages/cli/src/commands/plugin/serve/paths.ts @@ -14,39 +14,35 @@ * limitations under the License. */ -import { resolve as resolvePath } from 'path'; -import { existsSync, realpathSync } from 'fs'; +import { existsSync } from 'fs'; +import { paths } from 'lib/paths'; export function getPaths() { - const appDir = realpathSync(process.cwd()); - - const resolveApp = (path: string) => resolvePath(appDir, path); - const resolveOwn = (path: string) => resolvePath(__dirname, '..', path); - const resolveAppModule = (path: string) => { + const resolveTargetModule = (path: string) => { for (const ext of ['mjs', 'js', 'ts', 'tsx', 'jsx']) { - const filePath = resolveApp(`${path}.${ext}`); + const filePath = paths.resolveTarget(`${path}.${ext}`); if (existsSync(filePath)) { return filePath; } } - return resolveApp(`${path}.js`); + return paths.resolveTarget(`${path}.js`); }; - let appHtml = resolveApp('dev/index.html'); - if (!existsSync(appHtml)) { - appHtml = resolveOwn('../../templates/serve_index.html'); + let targetHtml = paths.resolveTarget('dev/index.html'); + if (!existsSync(targetHtml)) { + targetHtml = paths.resolveOwn('templates/serve_index.html'); } return { - appHtml, - appPath: resolveApp('.'), - appAssets: resolveApp('assets'), - appSrc: resolveApp('src'), - appDev: resolveApp('dev'), - appDevEntry: resolveAppModule('dev/index'), - appTsConfig: resolveApp('tsconfig.json'), - appNodeModules: resolveApp('node_modules'), - appPackageJson: resolveApp('package.json'), + targetHtml, + targetPath: paths.resolveTarget('.'), + targetAssets: paths.resolveTarget('assets'), + targetSrc: paths.resolveTarget('src'), + targetDev: paths.resolveTarget('dev'), + targetDevEntry: resolveTargetModule('dev/index'), + targetTsConfig: paths.resolveTarget('tsconfig.json'), + targetNodeModules: paths.resolveTarget('node_modules'), + targetPackageJson: paths.resolveTarget('package.json'), }; } diff --git a/packages/cli/src/commands/plugin/serve/server.ts b/packages/cli/src/commands/plugin/serve/server.ts index 850ab00941..066f741406 100644 --- a/packages/cli/src/commands/plugin/serve/server.ts +++ b/packages/cli/src/commands/plugin/serve/server.ts @@ -39,6 +39,7 @@ export async function startDevServer() { const server = new WebpackDevServer(compiler, { hot: true, publicPath: '/', + historyApiFallback: true, quiet: true, https: protocol === 'https', host, diff --git a/packages/cli/templates/default-app/.eslintrc.js b/packages/cli/templates/default-app/.eslintrc.js index dd47f29781..13573efa9c 100644 --- a/packages/cli/templates/default-app/.eslintrc.js +++ b/packages/cli/templates/default-app/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], }; diff --git a/packages/cli/templates/default-app/packages/app/.eslintrc.js b/packages/cli/templates/default-app/packages/app/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/packages/cli/templates/default-app/packages/app/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/packages/cli/templates/default-app/plugins/welcome/.eslintrc.js b/packages/cli/templates/default-app/plugins/welcome/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/packages/cli/templates/default-app/plugins/welcome/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/packages/cli/templates/default-plugin/.eslintrc.js b/packages/cli/templates/default-plugin/.eslintrc.js index dd47f29781..13573efa9c 100644 --- a/packages/cli/templates/default-plugin/.eslintrc.js +++ b/packages/cli/templates/default-plugin/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], }; diff --git a/packages/core/.eslintrc.js b/packages/core/.eslintrc.js index 02b430e588..d592a653c8 100644 --- a/packages/core/.eslintrc.js +++ b/packages/core/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], rules: { // TODO: add prop types to JS and remove 'react/prop-types': 0, diff --git a/packages/test-utils-core/.eslintrc.js b/packages/test-utils-core/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/packages/test-utils-core/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/packages/test-utils/.eslintrc.js b/packages/test-utils/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/packages/test-utils/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/home-page/.eslintrc.js b/plugins/home-page/.eslintrc.js index dd47f29781..13573efa9c 100644 --- a/plugins/home-page/.eslintrc.js +++ b/plugins/home-page/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], }; diff --git a/plugins/home-page/dev/index.tsx b/plugins/home-page/dev/index.tsx new file mode 100644 index 0000000000..c68b8f7a51 --- /dev/null +++ b/plugins/home-page/dev/index.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { FC } from 'react'; +import ReactDOM from 'react-dom'; +import { BrowserRouter } from 'react-router-dom'; +import HomeIcon from '@material-ui/icons/Home'; +import { ThemeProvider, CssBaseline } from '@material-ui/core'; +import { + createApp, + SidebarPage, + Sidebar, + SidebarItem, + SidebarSpacer, +} from '@backstage/core'; +import { lightTheme } from '@backstage/theme'; +import { plugin } from '../src/plugin'; + +const app = createApp(); +app.registerPlugin(plugin); +const AppComponent = app.build(); + +const App: FC<{}> = () => { + return ( + + + + + + + + + + + + + + ); +}; + +ReactDOM.render(, document.getElementById('root')); diff --git a/plugins/home-page/package.json b/plugins/home-page/package.json index 4cc553b994..28c5dfeeb6 100644 --- a/plugins/home-page/package.json +++ b/plugins/home-page/package.json @@ -7,6 +7,7 @@ "private": true, "scripts": { "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", "lint": "backstage-cli lint", "test": "backstage-cli test", "clean": "backstage-cli clean" @@ -18,7 +19,8 @@ "@testing-library/user-event": "^7.1.2", "@types/jest": "^24.0.0", "@types/node": "^12.0.0", - "@types/testing-library__jest-dom": "5.0.2" + "@types/testing-library__jest-dom": "5.0.2", + "react-router-dom": "^5.1.2" }, "dependencies": { "@backstage/core": "^0.1.1-alpha.4", diff --git a/plugins/home-page/tsconfig.json b/plugins/home-page/tsconfig.json index 7b73db2f0f..55fa1e2384 100644 --- a/plugins/home-page/tsconfig.json +++ b/plugins/home-page/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "../../tsconfig.json", - "include": ["src"], + "include": ["src", "dev"], "compilerOptions": { "baseUrl": "src" } diff --git a/plugins/lighthouse/.eslintrc.js b/plugins/lighthouse/.eslintrc.js index dd47f29781..13573efa9c 100644 --- a/plugins/lighthouse/.eslintrc.js +++ b/plugins/lighthouse/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], }; diff --git a/plugins/welcome/.eslintrc.js b/plugins/welcome/.eslintrc.js index dd47f29781..13573efa9c 100644 --- a/plugins/welcome/.eslintrc.js +++ b/plugins/welcome/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint.js')], + extends: [require.resolve('@backstage/cli/config/eslint')], };