diff --git a/packages/cli/README.md b/packages/cli/README.md index 16c464c40a..02f1aba90d 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -19,7 +19,7 @@ To run the cli in watch mode, use `yarn start `. For example `yarn start l To try out the command locally, you can execute the following from the parent directory of this repo: ```bash -./backstage/packages/cli/bin/janus-cli --help +./packages/cli/bin/janus-cli --help ``` ## Documentation diff --git a/packages/cli/package.json b/packages/cli/package.json index 1e5f908cd8..79d2103404 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -48,6 +48,7 @@ "bfj": "^8.0.0", "chalk": "^4.0.0", "chokidar": "^3.3.1", + "codeowners": "^5.1.1", "commander": "^9.1.0", "css-loader": "^6.5.1", "esbuild": "^0.21.0", @@ -58,9 +59,11 @@ "express": "^4.18.2", "fork-ts-checker-webpack-plugin": "^7.0.0-alpha.8", "fs-extra": "^10.1.0", + "gitconfiglocal": "2.1.0", "handlebars": "^4.7.7", "html-webpack-plugin": "^5.3.1", "inquirer": "^8.2.0", + "is-native-module": "^1.1.3", "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.4.2", "node-libs-browser": "^2.2.1", @@ -83,8 +86,7 @@ "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", "yml-loader": "^2.1.0", - "yn": "^4.0.0", - "is-native-module": "^1.1.3" + "yn": "^4.0.0" }, "devDependencies": { "@backstage/backend-common": "0.21.7", @@ -99,6 +101,8 @@ "@backstage/plugin-scaffolder-node": "0.4.3", "@backstage/test-utils": "1.5.4", "@backstage/theme": "0.5.3", + "@ianvs/prettier-plugin-sort-imports": "^4.2.1", + "@spotify/prettier-config": "^15.0.0", "@types/express": "4.17.21", "@types/fs-extra": "9.0.13", "@types/inquirer": "8.2.10", diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index fa1cba1f4e..ab3688c956 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -143,6 +143,32 @@ export function registerScriptCommand(program: Command) { .command('schema') .description('Print configuration schema for a package') .action(lazy(() => import('./schema').then(m => m.default))); + + command + .command('metadata') + .description('Add metadata to a package.json file') + .option( + '--dir ', + 'Folder in which to make changes to package.json, if not the current directory', + './', + ) + .option('--author ', 'Set author', 'Red Hat') + .option('--license ', 'Set license', 'Apache-2.0') + .option('--homepage ', 'Set homepage', 'https://red.ht/rhdh') + .option( + '--bugs ', + 'Set issue tracker URL', + 'https://github.com/janus-idp/backstage-plugins/issues', + ) + .option( + '--keywords ', + 'Add or replace keywords; there can be only one `support:` or `lifecycle:` value,\n ' + + 'but unlimited other keywords can be added. To remove values, manually edit package.json\n\n ' + + 'Valid values for support: alpha, beta, tech-preview, or production.\n ' + + 'Valid values for lifecycle: active, maintenance, deprecated, inactive, retired.\n ', + 'backstage,plugin,support:production,lifecycle:active', + ) + .action(lazy(() => import('./metadata').then(m => m.command))); } export function registerCommands(program: Command) { diff --git a/packages/cli/src/commands/metadata/command.ts b/packages/cli/src/commands/metadata/command.ts new file mode 100644 index 0000000000..0936642a65 --- /dev/null +++ b/packages/cli/src/commands/metadata/command.ts @@ -0,0 +1,223 @@ +/* + * Copyright 2024 The Backstage Authors + * + * 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. + */ + +// test with ./packages/cli/bin/janus-cli package metadata --help + +// @ts-ignore +import Codeowners from 'codeowners'; +import { OptionValues } from 'commander'; +import gitconfig from 'gitconfiglocal'; + +import * as fs from 'fs'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import process from 'node:process'; +import { promisify } from 'node:util'; + +const pGitconfig = promisify(gitconfig); + +export async function command(opts: OptionValues): Promise { + const config = await pGitconfig(process.cwd()); + updatePackageMetadata(opts, config?.remote?.origin?.url); +} + +interface Repository { + type: string; + url: string; + directory: string; +} + +interface PackageJson { + name: string; + version: string; + main: string; + types: string; + license: string; + author: string; + configschema: string; + + homepage: URL; + bugs: URL; + + sideEffects: boolean; + + publishConfig: {}; + backstage: { + role: string; + 'supported-versions': string; + }; + scripts: {}; + dependencies: {}; + peerDependencies: {}; + devDependencies: {}; + scalprum: {}; + repository: Repository; + + files: string[]; + maintainers: string[]; + keywords: string[]; +} + +const path = { + /** + * @method resolveRelativeFromAbsolute resolves a relative path from an absolute path + * @param {string} DotDotPath relative path + * @returns {string} resolved absolutePath + */ + resolveRelativeFromAbsolute(DotDotPath: string): string[] { + const pathsArray = DotDotPath.replaceAll(/[/|\\]/g, '/').split('/'); + const map = pathsArray.reduce( + (acc, e) => acc.set(e, (acc.get(e) || 0) + 1), + new Map(), + ); + // console.log(` @ ${DotDotPath} => ${pathsArray} (${map.get("..")} backs)`) + const rootDir = pathsArray.slice(0, -(map.get('..') * 2)).join('/'); + // console.log(` @ root dir: ${rootdir}`) + const relativeDir = process.cwd().replaceAll(`${rootDir}/`, ''); + return [rootDir, relativeDir]; + }, +}; + +function findCodeowners(element: string) { + if (fs.existsSync(`${element}/.github/CODEOWNERS`)) { + return element; // found the root dir + } + return findCodeowners(`${element}/..`); +} + +function separateKeywords(array: string[]): { + keywords: string[]; + lifecycle?: string; + support?: string; +} { + return array.reduce( + (prev, keyword) => { + // separate lifecycle keyword + if (keyword.startsWith('lifecycle:')) { + return { ...prev, lifecycle: keyword }; + } + + // separate support keyword + if (keyword.startsWith('support:')) { + return { ...prev, support: keyword }; + } + + // keep the remaining keywords together + prev.keywords.push(keyword); + return prev; + }, + { keywords: [] } as { + keywords: string[]; + lifecycle?: string; + support?: string; + }, + ); +} + +export function updatePackageMetadata( + opts: OptionValues, + gitconfigRemoteOriginUrl: string, +) { + // load the package.json from the specified (or current) folder + const workingDir = `${process.cwd()}/${opts.dir}`; + console.log(`Updating ${workingDir} / package.json`); + + // compute the root dir and relative path to the current dir + const [rootDir, relativePath] = opts.dir + ? [process.cwd(), opts.dir] + : path.resolveRelativeFromAbsolute(findCodeowners(`${process.cwd()}`)); + // console.log(` @ rootdir = ${rootdir}, relative_path = ${relative_path}`) + + const packageJSONPath = join(workingDir, 'package.json'); + const packageJSON = JSON.parse( + readFileSync(packageJSONPath, 'utf8'), + ) as PackageJson; + + /* now let's change some values */ + + // 1. add backstage version matching the current value of backstage.json in this repo + if (fs.existsSync(join(rootDir, '/backstage.json'))) { + packageJSON.backstage['supported-versions'] = JSON.parse( + readFileSync(join(rootDir, '/backstage.json'), 'utf8'), + ).version; + } + + // 2. set up repository values and the current path as repo.directory + const repo = {} as Repository; + repo.type = 'git'; + repo.url = gitconfigRemoteOriginUrl + .toString() + .replaceAll('git@github.com:', 'https://github.com/') + .replaceAll('.git', '') + .trim(); + repo.directory = relativePath; + packageJSON.repository = repo; + + // 3. load owners from CODEOWNERS file, using this package.json's repository.directory field to compute maintainer groups + let owners: string[] = []; + if (packageJSON.repository.directory) { + const repos = new Codeowners(); + owners = repos.getOwner(relativePath); + } else { + console.log( + ` ! Could not load .github/CODEOWNERS file, so cannot update maintainers in package.json`, + ); + } + packageJSON.maintainers = owners; + + // 4. set some hardcoded values based on commandline flags + packageJSON.author = opts.author; + packageJSON.license = opts.license; + packageJSON.homepage = new URL(opts.homepage); + packageJSON.bugs = new URL(opts.bugs); + + // initialize empty string array if not already present + if (!packageJSON.keywords) { + packageJSON.keywords = []; + } + + // if already have keywords, replace lifecycle and support with new values (if defined) + // we can only have ONE lifecycle and one support keyword, so remove replace any existing values + const { + keywords: oldKeywords, + lifecycle: oldLifecycle, + support: oldSupport, + } = separateKeywords(packageJSON.keywords); + + const { + keywords: optsKeywords, + lifecycle: optsLifecycle, + support: optsSupport, + } = separateKeywords(opts.keywords.split(',')); + + const newKeywords = oldKeywords.concat(optsKeywords); + + // if there is a lifecycle keyword, push to the beginning of the array + if (oldLifecycle || optsLifecycle) { + newKeywords.unshift(optsLifecycle ?? oldLifecycle ?? ''); + } + + // if there is a support keyword, push to the beginning of the array + if (oldSupport || optsSupport) { + newKeywords.unshift(optsSupport ?? oldSupport ?? ''); + } + + // dedupe new keywords + packageJSON.keywords = Array.from(new Set(newKeywords)); + + // write changes to file + writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, 2), 'utf8'); +} diff --git a/packages/cli/src/commands/metadata/index.ts b/packages/cli/src/commands/metadata/index.ts new file mode 100644 index 0000000000..5e437411e6 --- /dev/null +++ b/packages/cli/src/commands/metadata/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * 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. + */ + +export { command } from './command'; diff --git a/packages/cli/src/types.d.ts b/packages/cli/src/types.d.ts index 1222b2b4b8..c0b4ba3123 100644 --- a/packages/cli/src/types.d.ts +++ b/packages/cli/src/types.d.ts @@ -22,6 +22,9 @@ declare namespace NodeJS { declare module 'fs' { export interface StatSyncFn {} } + +declare module 'gitconfiglocal'; + declare module 'rollup-plugin-image-files' { export default function image(options?: any): any; } diff --git a/yarn.lock b/yarn.lock index 4dd47aa28d..b072824718 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6308,7 +6308,7 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== -"@ianvs/prettier-plugin-sort-imports@4.2.1": +"@ianvs/prettier-plugin-sort-imports@4.2.1", "@ianvs/prettier-plugin-sort-imports@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.1.tgz#b5665a130ab882741df6d5ccd423f002ae065ad8" integrity sha512-NKN1LVFWUDGDGr3vt+6Ey3qPeN/163uR1pOPAlkWpgvAqgxQ6kSdUf1F0it8aHUtKRUzEGcK38Wxd07O61d7+Q== @@ -7795,7 +7795,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.6", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -10724,9 +10724,9 @@ resolved "https://registry.yarnpkg.com/@spotify/eslint-config-typescript/-/eslint-config-typescript-15.0.0.tgz#b1857a76951df6e2cc4a1e92d98e7fd4f5a4baec" integrity sha512-70nKh2v6So0MddkEfKj4xgAcqs1VmR0AS2yb62XYetZ1Ep3AmhYDl/5CYtU5pbAQS4zCap8rd/EYdmVEHXiS6g== -"@spotify/prettier-config@15.0.0": +"@spotify/prettier-config@15.0.0", "@spotify/prettier-config@^15.0.0": version "15.0.0" - resolved "https://registry.yarnpkg.com/@spotify/prettier-config/-/prettier-config-15.0.0.tgz#3dcc94ffa9c3fad68a1e8430ccba57edc0131399" + resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-15.0.0.tgz#3dcc94ffa9c3fad68a1e8430ccba57edc0131399" integrity sha512-ex7bdst1STr97y/MUTgVxadxpEZy48XVQDwZrESYO07EONSRstQYBaQWGVo80jmJ9NXC+r4ZjUqjT2Gw524Nqg== "@sqltools/formatter@^1.2.5": @@ -17613,6 +17613,21 @@ codeowners-utils@^1.0.2: ignore "^5.1.4" locate-path "^5.0.0" +codeowners@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/codeowners/-/codeowners-5.1.1.tgz#2df18cec20f5ea029103d5315d641cc9d2be6f80" + integrity sha512-NKsnAQQBhdsfkm7xZb073MTlzfz9kmE9iyjIcsfU9kZMPq2E7e+O42HD+yFTIu3f1CwvnBsSFdSLjv5k6CRIZg== + dependencies: + "@nodelib/fs.walk" "^1.2.6" + commander "^6.2.1" + find-up "^2.1.0" + ignore "^3.3.10" + is-directory "^0.3.1" + lodash.intersection "^4.4.0" + lodash.maxby "^4.6.0" + lodash.padend "^4.6.1" + "true-case-path" "^1.0.3" + collect-v8-coverage@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" @@ -21245,9 +21260,9 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -21924,6 +21939,13 @@ git-url-parse@^14.0.0: dependencies: git-up "^7.0.0" +gitconfiglocal@2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz#07c28685c55cc5338b27b5acbcfe34aeb92e43d1" + integrity sha512-qoerOEliJn3z+Zyn1HW2F6eoYJqKwS6MgC9cztTLUB/xLWX8gD/6T60pKn4+t/d6tP7JlybI7Z3z+I572CR/Vg== + dependencies: + ini "^1.3.2" + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -21978,7 +22000,7 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.2.3, glob@^7.0.0, glob@^7.0.3, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3: +glob@7.2.3, glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -22903,6 +22925,11 @@ ignore-walk@^6.0.0: dependencies: minimatch "^9.0.0" +ignore@^3.3.10: + version "3.3.10" + resolved "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + ignore@^5.1.4, ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -23011,7 +23038,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -23376,6 +23403,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-accessor-descriptor "^1.0.1" is-data-descriptor "^1.0.1" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -25803,6 +25835,11 @@ lodash.includes@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== +lodash.intersection@^4.4.0: + version "4.4.0" + resolved "https://registry.npmjs.org/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705" + integrity sha512-N+L0cCfnqMv6mxXtSPeKt+IavbOBBSiAEkKyLasZ8BVcP9YXQgxLO12oPR8OyURwKV8l5vJKiE1M8aS70heuMg== + lodash.isarguments@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -25843,6 +25880,11 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== +lodash.maxby@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/lodash.maxby/-/lodash.maxby-4.6.0.tgz#082240068f3c7a227aa00a8380e4f38cf0786e3d" + integrity sha512-QfTqQTwzmKxLy7VZlbx2M/ipWv8DCQ2F5BI/MRxLharOQ5V78yMSuB+JE+EuUM22txYfj09R2Q7hUlEYj7KdNg== + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -25858,6 +25900,11 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== +lodash.padend@^4.6.1: + version "4.6.1" + resolved "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz#53ccba047d06e158d311f45da625f4e49e6f166e" + integrity sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw== + lodash.topath@^4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.topath/-/lodash.topath-4.5.2.tgz#3616351f3bba61994a0931989660bd03254fd009" @@ -34160,6 +34207,13 @@ trough@^2.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== +"true-case-path@^1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" + integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== + dependencies: + glob "^7.1.2" + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"