Merge branch 'master' of github.com:spotify/backstage into shmidt-i/proxy-plugin
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"@backstage/plugin-graphiql": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-lighthouse": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-register-component": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-rollbar": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-scaffolder": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-sentry": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-tech-radar": "^0.1.1-alpha.13",
|
||||
|
||||
@@ -57,6 +57,8 @@ import {
|
||||
} from '@backstage/plugin-graphiql';
|
||||
import { scaffolderApiRef, ScaffolderApi } from '@backstage/plugin-scaffolder';
|
||||
|
||||
import { rollbarApiRef, RollbarClient } from '@backstage/plugin-rollbar';
|
||||
|
||||
export const apis = (config: ConfigApi) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Creating APIs for ${config.getString('app.title')}`);
|
||||
@@ -170,5 +172,13 @@ export const apis = (config: ConfigApi) => {
|
||||
]),
|
||||
);
|
||||
|
||||
builder.add(
|
||||
rollbarApiRef,
|
||||
new RollbarClient({
|
||||
apiOrigin: backendUrl,
|
||||
basePath: '/rollbar',
|
||||
}),
|
||||
);
|
||||
|
||||
return builder.build();
|
||||
};
|
||||
|
||||
@@ -26,3 +26,4 @@ export { plugin as GitopsProfiles } from '@backstage/plugin-gitops-profiles';
|
||||
export { plugin as TechDocs } from '@backstage/plugin-techdocs';
|
||||
export { plugin as GraphiQL } from '@backstage/plugin-graphiql';
|
||||
export { plugin as GithubActions } from '@backstage/plugin-github-actions';
|
||||
export { plugin as Rollbar } from '@backstage/plugin-rollbar';
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@backstage/plugin-auth-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-catalog-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-identity-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-sentry-backend": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-techdocs-backend": "^0.1.1-alpha.13",
|
||||
|
||||
@@ -33,6 +33,7 @@ import knex from 'knex';
|
||||
import auth from './plugins/auth';
|
||||
import catalog from './plugins/catalog';
|
||||
import identity from './plugins/identity';
|
||||
import rollbar from './plugins/rollbar';
|
||||
import scaffolder from './plugins/scaffolder';
|
||||
import sentry from './plugins/sentry';
|
||||
import proxy from './plugins/proxy';
|
||||
@@ -71,6 +72,12 @@ async function main() {
|
||||
const service = createServiceBuilder(module)
|
||||
.loadConfig(configReader)
|
||||
.addRouter('/catalog', await catalog(catalogEnv))
|
||||
.addRouter(
|
||||
'/rollbar',
|
||||
await rollbar(
|
||||
getRootLogger().child({ type: 'plugin', plugin: 'rollbar' }),
|
||||
),
|
||||
)
|
||||
.addRouter('/scaffolder', await scaffolder(scaffolderEnv))
|
||||
.addRouter(
|
||||
'/sentry',
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 { createRouter } from '@backstage/plugin-rollbar-backend';
|
||||
import { Logger } from 'winston';
|
||||
|
||||
export default async function createPlugin(logger: Logger) {
|
||||
return await createRouter({ logger });
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 { Command } from 'commander';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { buildBundle } from '../../lib/bundler';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
await buildBundle({
|
||||
entry: 'dev/index',
|
||||
statsJsonEnabled: cmd.stats,
|
||||
config: ConfigReader.fromConfigs(appConfigs),
|
||||
appConfigs,
|
||||
});
|
||||
};
|
||||
@@ -103,6 +103,12 @@ const main = (argv: string[]) => {
|
||||
.option('--check', 'Enable type checking and linting')
|
||||
.action(lazyAction(() => import('./commands/plugin/serve'), 'default'));
|
||||
|
||||
program
|
||||
.command('plugin:export')
|
||||
.description('Exports the dev/ folder of a plugin')
|
||||
.option('--stats', 'Write bundle stats to output directory')
|
||||
.action(lazyAction(() => import('./commands/plugin/export'), 'default'));
|
||||
|
||||
program
|
||||
.command('plugin:diff')
|
||||
.option('--check', 'Fail if changes are required')
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
module.exports = {
|
||||
extends: [require.resolve('@backstage/cli/config/eslint')],
|
||||
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
|
||||
rules: {
|
||||
'no-console': 0,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,3 +3,49 @@
|
||||
Check out the [TechDocs README](https://github.com/spotify/backstage/blob/master/plugins/techdocs/README.md) to learn more.
|
||||
|
||||
**WIP: This cli is a work in progress. It is not ready for use yet. Follow our progress on [the Backstage Discord](https://discord.gg/MUpMjP2) under #docs-like-code or on [our GitHub Milestone](https://github.com/spotify/backstage/milestone/15).**
|
||||
|
||||
## Getting Started
|
||||
|
||||
You'll need Docker installed and running to use this. You will also need to build the container located at `plugins/techdocs/mkdocs/container` under the tag `mkdocs:local-dev`, as you can see in the commands from below:
|
||||
|
||||
```bash
|
||||
docker build plugins/techdocs/mkdocs/container -t mkdocs:local-dev
|
||||
```
|
||||
|
||||
From that point, you can invoke the CLI from any project with a docs folder. Try out our example!
|
||||
|
||||
```bash
|
||||
cd plugins/techdocs/mkdocs/mock-docs
|
||||
npx @techdocs/cli serve
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
You'll need Docker installed and running to use this. You will also need to build the container located at `plugins/techdocs/mkdocs/container` under the tag `mkdocs:local-dev`, as you can see in the commands from below:
|
||||
|
||||
```bash
|
||||
docker build plugins/techdocs/mkdocs/container -t mkdocs:local-dev
|
||||
```
|
||||
|
||||
Once that is built, you'll need to manually create an `alias` for running the CLI locally:
|
||||
|
||||
```bash
|
||||
cd packages/techdocs-cli
|
||||
echo "$(pwd)/bin/techdocs"
|
||||
|
||||
# Copy the value from above and add it in [HERE] below
|
||||
# For more convenience, add it to your ~/.zshrc or ~/.bash_profile
|
||||
# otherwise you'll lose it when you open a new Terminal
|
||||
alias techdocs="[HERE]"
|
||||
```
|
||||
|
||||
From that point, you can invoke `techdocs` from any project with a docs folder. Try out our example!
|
||||
|
||||
```bash
|
||||
cd plugins/techdocs/mkdocs/mock-docs
|
||||
techdocs serve
|
||||
```
|
||||
|
||||
You should have a `localhost:3000` serving TechDocs in Backstage, as well as `localhost:8000` serving Mkdocs (which won't open up and be exposed to the user).
|
||||
|
||||
Happy hacking!
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
ROOT_DIR=$(git rev-parse --show-toplevel)
|
||||
TECHDOCS_PREVIEW_SOURCE=$ROOT_DIR/plugins/techdocs/dist
|
||||
TECHDOCS_PREVIEW_DEST=$ROOT_DIR/packages/techdocs-cli/dist/techdocs-preview-bundle
|
||||
|
||||
# Build the CLI
|
||||
backstage-cli build --outputs cjs
|
||||
|
||||
# Create export of the TechDocs plugin
|
||||
yarn workspace @backstage/plugin-techdocs export
|
||||
|
||||
# Copy over export to techdocs-cli dist/ folder
|
||||
cp -r $TECHDOCS_PREVIEW_SOURCE $TECHDOCS_PREVIEW_DEST
|
||||
|
||||
# Clean output
|
||||
yarn workspace @backstage/plugin-techdocs clean
|
||||
|
||||
# Write to console
|
||||
echo "[techdocs-cli]: Built the dist/ folder"
|
||||
echo "[techdocs-cli]: Imported @backstage/plugin-techdocs dist/ folder into techdocs-preview-bundle/"
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "@backstage/techdocs-cli",
|
||||
"name": "@techdocs/cli",
|
||||
"description": "CLI for running TechDocs locally.",
|
||||
"version": "0.1.1-alpha.13",
|
||||
"private": true,
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -18,7 +18,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"main": "dist/index.cjs.js",
|
||||
"scripts": {
|
||||
"build": "backstage-cli build --outputs cjs",
|
||||
"build": "./bin/build",
|
||||
"lint": "backstage-cli lint",
|
||||
"test": "backstage-cli test --passWithNoTests",
|
||||
"clean": "backstage-cli clean",
|
||||
@@ -28,7 +28,11 @@
|
||||
"techdocs": "bin/techdocs-cli"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.13"
|
||||
"@spotify/eslint-config": "^7.0.0",
|
||||
"@spotify/prettier-config": "^7.0.0",
|
||||
"@types/serve-handler": "^6.1.0",
|
||||
"eslint": "^7.1.0",
|
||||
"eslint-plugin-import": "^2.22.0"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
@@ -36,7 +40,15 @@
|
||||
],
|
||||
"nodemonConfig": {
|
||||
"watch": "./src",
|
||||
"exec": "bin/techdocs-cli",
|
||||
"exec": "bin/build && bin/techdocs-cli",
|
||||
"ext": "ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.13",
|
||||
"@backstage/plugin-techdocs": "^0.1.1-alpha.13",
|
||||
"chalk": "^4.1.0",
|
||||
"commander": "^5.1.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"serve-handler": "^6.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,5 +13,77 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import program from 'commander';
|
||||
import { version } from './lib/version';
|
||||
// import chalk from 'chalk';
|
||||
import { spawn } from 'child_process';
|
||||
import path from 'path';
|
||||
// import HTTPServer from './lib/httpServer';
|
||||
|
||||
export const techDocsCli = () => {};
|
||||
const run = (workingDirectory: string, name: string, args: string[] = []) => {
|
||||
const child = spawn(name, args, {
|
||||
cwd: workingDirectory,
|
||||
stdio: ['inherit', 'inherit', 'inherit'],
|
||||
shell: true,
|
||||
env: {
|
||||
...process.env,
|
||||
FORCE_COLOR: 'true',
|
||||
},
|
||||
});
|
||||
|
||||
child.once('error', error => {
|
||||
console.error(error);
|
||||
});
|
||||
child.once('exit', code => {
|
||||
console.log('exited!', code);
|
||||
});
|
||||
};
|
||||
|
||||
const main = (argv: string[]) => {
|
||||
program.name('techdocs-cli').version(version);
|
||||
|
||||
program
|
||||
.command('serve')
|
||||
.description('Serve a documentation project locally')
|
||||
.action(() => {
|
||||
// const techdocsPreviewBundlePath = path.join(
|
||||
// __dirname,
|
||||
// '..',
|
||||
// 'dist',
|
||||
// 'techdocs-preview-bundle',
|
||||
// );
|
||||
|
||||
// new HTTPServer(techdocsPreviewBundlePath, 3000).serve();
|
||||
|
||||
run(process.env.PWD!, 'docker', [
|
||||
'run',
|
||||
'-it',
|
||||
'-w',
|
||||
'/content',
|
||||
'-v',
|
||||
'$(pwd):/content',
|
||||
'-p',
|
||||
'8000:8000',
|
||||
'mkdocs:local-dev',
|
||||
'serve',
|
||||
'-a',
|
||||
'0.0.0.0:8000',
|
||||
]);
|
||||
|
||||
const pluginPath = path.join(
|
||||
require.resolve('@backstage/plugin-techdocs'),
|
||||
'..',
|
||||
'..',
|
||||
);
|
||||
|
||||
run(
|
||||
pluginPath,
|
||||
path.join(require.resolve('@backstage/cli'), '../../bin/backstage-cli'),
|
||||
['plugin:serve'],
|
||||
);
|
||||
});
|
||||
|
||||
program.parse(argv);
|
||||
};
|
||||
|
||||
main(process.argv);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 serveHandler from 'serve-handler';
|
||||
import http from 'http';
|
||||
|
||||
export default class HTTPServer {
|
||||
constructor(public dir: string, public port: number) {}
|
||||
|
||||
serve() {
|
||||
const server = http.createServer((request, response) => {
|
||||
return serveHandler(request, response, {
|
||||
public: this.dir,
|
||||
trailingSlash: true,
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(this.port, () => {
|
||||
console.log('Running at http://localhost:3000');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 fs from 'fs-extra';
|
||||
import { dirname, resolve as resolvePath } from 'path';
|
||||
|
||||
export type ResolveFunc = (...paths: string[]) => string;
|
||||
|
||||
// Common paths and resolve functions used by the cli.
|
||||
// Currently assumes it is being executed within a monorepo.
|
||||
export type Paths = {
|
||||
// Root dir of the cli itself, containing package.json
|
||||
ownDir: string;
|
||||
|
||||
// Monorepo root dir of the cli itself. Only accessible when running inside Backstage repo.
|
||||
ownRoot: string;
|
||||
|
||||
// The location of the app that the cli is being executed in
|
||||
targetDir: string;
|
||||
|
||||
// The monorepo root package of the app that the cli is being executed in.
|
||||
targetRoot: string;
|
||||
|
||||
// Resolve a path relative to own repo
|
||||
resolveOwn: ResolveFunc;
|
||||
|
||||
// Resolve a path relative to own monorepo root. Only accessible when running inside Backstage repo.
|
||||
resolveOwnRoot: ResolveFunc;
|
||||
|
||||
// Resolve a path relative to the app
|
||||
resolveTarget: ResolveFunc;
|
||||
|
||||
// Resolve a path relative to the app repo root
|
||||
resolveTargetRoot: ResolveFunc;
|
||||
};
|
||||
|
||||
// Looks for a package.json that has name: "root" to identify the root of the monorepo
|
||||
export function findRootPath(topPath: string): string {
|
||||
let path = topPath;
|
||||
|
||||
// Some sanity check to avoid infinite loop
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const packagePath = resolvePath(path, 'package.json');
|
||||
const exists = fs.pathExistsSync(packagePath);
|
||||
if (exists) {
|
||||
try {
|
||||
const data = fs.readJsonSync(packagePath);
|
||||
if (data.name === 'root' || data.name.includes('backstage-e2e')) {
|
||||
return path;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to parse package.json file while searching for root, ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const newPath = dirname(path);
|
||||
if (newPath === path) {
|
||||
throw new Error(
|
||||
`No package.json with name "root" found as a parent of ${topPath}`,
|
||||
);
|
||||
}
|
||||
path = newPath;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Iteration limit reached when searching for root package.json at ${topPath}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Finds the root of the cli package itself
|
||||
export function findOwnDir() {
|
||||
// Known relative locations of package in dist/dev
|
||||
const pathDist = '..';
|
||||
const pathDev = '../..';
|
||||
|
||||
// Check the closest dir first
|
||||
const pkgInDist = resolvePath(__dirname, pathDist, 'package.json');
|
||||
const isDist = fs.pathExistsSync(pkgInDist);
|
||||
|
||||
const path = isDist ? pathDist : pathDev;
|
||||
return resolvePath(__dirname, path);
|
||||
}
|
||||
|
||||
// Finds the root of the monorepo that the cli exists in. Only accessible when running inside Backstage repo.
|
||||
export function findOwnRootPath(ownDir: string) {
|
||||
const isLocal = fs.pathExistsSync(resolvePath(ownDir, 'src'));
|
||||
if (!isLocal) {
|
||||
throw new Error(
|
||||
'Tried to access monorepo package root dir outside of Backstage repository',
|
||||
);
|
||||
}
|
||||
|
||||
return resolvePath(ownDir, '../..');
|
||||
}
|
||||
|
||||
export function findPaths(): Paths {
|
||||
const ownDir = findOwnDir();
|
||||
const targetDir = fs.realpathSync(process.cwd());
|
||||
|
||||
// Lazy load this as it will throw an error if we're not inside the Backstage repo.
|
||||
let ownRoot = '';
|
||||
const getOwnRoot = () => {
|
||||
if (!ownRoot) {
|
||||
ownRoot = findOwnRootPath(ownDir);
|
||||
}
|
||||
return ownRoot;
|
||||
};
|
||||
|
||||
// We're not always running in a monorepo, so we lazy init this to only crash commands
|
||||
// that require a monorepo when we're not in one.
|
||||
let targetRoot = '';
|
||||
const getTargetRoot = () => {
|
||||
if (!targetRoot) {
|
||||
targetRoot = findRootPath(targetDir);
|
||||
}
|
||||
return targetRoot;
|
||||
};
|
||||
|
||||
return {
|
||||
ownDir,
|
||||
get ownRoot() {
|
||||
return getOwnRoot();
|
||||
},
|
||||
targetDir,
|
||||
get targetRoot() {
|
||||
return getTargetRoot();
|
||||
},
|
||||
resolveOwn: (...paths) => resolvePath(ownDir, ...paths),
|
||||
resolveOwnRoot: (...paths) => resolvePath(getOwnRoot(), ...paths),
|
||||
resolveTarget: (...paths) => resolvePath(targetDir, ...paths),
|
||||
resolveTargetRoot: (...paths) => resolvePath(getTargetRoot(), ...paths),
|
||||
};
|
||||
}
|
||||
|
||||
export const paths = findPaths();
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 fs from 'fs-extra';
|
||||
import { paths } from './paths';
|
||||
|
||||
export function findVersion() {
|
||||
const pkgContent = fs.readFileSync(paths.resolveOwn('package.json'), 'utf8');
|
||||
return JSON.parse(pkgContent).version;
|
||||
}
|
||||
|
||||
export const version = findVersion();
|
||||
export const isDev = fs.pathExistsSync(paths.resolveOwn('src'));
|
||||
Reference in New Issue
Block a user