From 122bdcf3220929f60c19a615fdc688abd25ca896 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 11 Nov 2021 20:55:05 +0100 Subject: [PATCH] core-create: large refactor * drop `yarn` support as it doesn't support peer dependency installation * drop `ora` and add proper messaging * change git branch to `main` * add initial git commit * merge `ProjectPackage` back into `sync` --- core/create/package.json | 8 +- core/create/src/ProjectPackage.ts | 148 ---------------------- core/create/src/config.ts | 14 +-- core/create/src/helpers.ts | 140 +++++---------------- core/create/src/index.ts | 200 +++++++++++++----------------- core/create/src/spinner.ts | 3 - core/create/src/sync.ts | 99 +++++++++++++-- package-lock.json | 23 +++- 8 files changed, 231 insertions(+), 404 deletions(-) delete mode 100644 core/create/src/ProjectPackage.ts delete mode 100644 core/create/src/spinner.ts diff --git a/core/create/package.json b/core/create/package.json index fa7b8fc2..c636296b 100755 --- a/core/create/package.json +++ b/core/create/package.json @@ -29,19 +29,21 @@ "kleur": "^4.1.4", "lodash.merge": "^4.6.2", "npm-package-arg": "^8.1.5", - "ora": "^6.0.1", "sade": "^1.7.4", "sort-package-json": "^1.52.0" }, "devDependencies": { "@types/cross-spawn": "^6.0.2", + "@types/dedent": "^0.7.0", "@types/lodash.merge": "^4.6.6", "@types/npm-package-arg": "^6.1.1", - "@types/sade": "^1.7.3" + "@types/sade": "^1.7.3", + "dedent": "^0.7.0" }, "engines": { "node": ">=14", - "npm": ">=7" + "npm": ">=7", + "yarn": "unsupported" }, "publishConfig": { "access": "public" diff --git a/core/create/src/ProjectPackage.ts b/core/create/src/ProjectPackage.ts deleted file mode 100644 index dcf55336..00000000 --- a/core/create/src/ProjectPackage.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { basename, extname } from 'path'; - -// @ts-ignore TypeScript is being weird -import merge from 'lodash.merge'; -import { sortPackageJson } from 'sort-package-json'; -import { readPackageJson, writePackageJson } from '@pota/shared/fs'; -import { PotaConfig } from '@pota/shared/config'; -import type { PackageJsonShape } from '@pota/shared/config'; - -import { POTA_CLI, POTA_CLI_BIN } from './config.js'; - -function filterObject>(o: T, fields: ReadonlyArray) { - type Result = Record; - - let r: Result | undefined = undefined; - - for (const field of Object.keys(o) as ReadonlyArray) { - if (fields.includes(field)) { - r ??= {} as Result; - r[field] = o[field]; - } - } - - return r; -} - -export default class ProjectPackage { - private static ignoredFields: ReadonlyArray = [ - 'name', - 'version', - 'peerDependencies', - 'dependencies', - 'devDependencies', - 'files', - 'publishConfig', - 'repository', - 'bugs', - 'author', - ]; - - private pkg: PackageJsonShape | null = null; - - constructor(private path: string) {} - - /* - * Loads the package from disk via the provided `path` - */ - async load() { - this.pkg = await readPackageJson(this.path); - - return this; - } - - /* - * Adds the passed file basename as a `@pota/cli command to the `scripts` - */ - applyFileAsScript(file: string) { - if (!this.pkg) throw new Error('`setProjectPackage` must be called before `addFileAsScript`'); - - const command = basename(file, extname(file)); - - this.pkg.scripts ??= {}; - this.pkg.scripts[command] = `${POTA_CLI_BIN} ${command}`; - } - - /* - * Merges the fields of the package from `path` into the project package. - */ - async merge(path: string, config: PotaConfig) { - if (!this.pkg) { - throw new Error('`setProjectPackage` must be called before `applySkeletonPackage`'); - } - - const skeletonPkg = await readPackageJson(path); - - const { name: skeleton, version, peerDependencies = {} } = skeletonPkg; - - for (const field of ProjectPackage.ignoredFields) { - delete skeletonPkg[field]; - } - - if ('scripts' in skeletonPkg && 'scripts' in config) { - skeletonPkg.scripts = filterObject(skeletonPkg.scripts!, config.scripts!); - } - - merge(this.pkg, skeletonPkg); - - // place the skeleton package in `devDependencies` - this.pkg.devDependencies ??= {}; - // TODO: this semver chevron ain't great, chief - this.pkg.devDependencies[skeleton!] = `^${version!}`; - - for (const [dep, version] of Object.entries(peerDependencies)) { - // place the `@pota/cli` (if it exists) package in `devDependencies` - if (dep === POTA_CLI) this.pkg.devDependencies[POTA_CLI] = peerDependencies[POTA_CLI]; - // this `else if` condition makes sure that the dependency isn't defined in `devDependencies` - // which might me the case for extended skeletons defined in `peerDependencies` - else if (!(dep in this.pkg.devDependencies)) { - this.pkg.dependencies ??= {}; - this.pkg.dependencies[dep] = version; - } - } - } - - /* - * Sorts package fields using `sort-package-json` - */ - sort() { - if (!this.pkg) throw new Error('`setProjectPackage` must be called before `sort`'); - - this.pkg = sortPackageJson(this.pkg); - - return this; - } - - /* - * Sets the `pota` field. - */ - setDefaultSkeleton(skeleton: string) { - if (!this.pkg) { - throw new Error('`setProjectPackage` must be called before `setDefaultSkeleton`'); - } - - this.pkg.pota = skeleton; - - return this; - } - - /* - * Sets the `name` field. - */ - setName(name: string) { - if (!this.pkg) throw new Error('`setProjectPackage` must be called before `setName`'); - - this.pkg.name = name; - - return this; - } - - /* - * Writes the package back to the `path` - */ - async write() { - if (!this.pkg) throw new Error('`setProjectPackage` must be called before `write`'); - - await writePackageJson(this.pkg, this.path); - } -} diff --git a/core/create/src/config.ts b/core/create/src/config.ts index 2f5bad4b..f1c21bc3 100755 --- a/core/create/src/config.ts +++ b/core/create/src/config.ts @@ -11,15 +11,11 @@ type ObjectEntries = ( const typedObjectEntries: ObjectEntries = Object.entries; -const SCOPE = '@pota'; - -const getPorterDependency = (name: T) => `${SCOPE}/${name}` as const; - const SKELETON_SHORTHANDS = { - [getPorterDependency('webpack-skeleton')]: ['webpack'] as const, - [getPorterDependency('react-skeleton')]: ['react'] as const, - [getPorterDependency('react-base-skeleton')]: ['react-base'] as const, - [getPorterDependency('vue-skeleton')]: ['vue'] as const, + ['@pota/webpack-skeleton']: ['webpack'] as const, + ['@pota/react-skeleton']: ['react'] as const, + ['@pota/react-base-skeleton']: ['react-base'] as const, + ['@pota/vue-skeleton']: ['vue'] as const, }; const INVERTED_SKELETON_SHORTHANDS = Object.fromEntries( @@ -33,7 +29,5 @@ export const isSkeletonShorthand = (shorthand: string) => shorthand in INVERTED_ export const getSkeletonFromShorthand = (shorthand: string) => INVERTED_SKELETON_SHORTHANDS[shorthand]; -export type PackageManager = 'yarn' | 'npm'; - export const POTA_CLI = '@pota/cli' as const; export const POTA_CLI_BIN = 'pota' as const; diff --git a/core/create/src/helpers.ts b/core/create/src/helpers.ts index f50891f2..29fe28ca 100755 --- a/core/create/src/helpers.ts +++ b/core/create/src/helpers.ts @@ -1,157 +1,83 @@ import { exec, SpawnOptions } from 'child_process'; +import { rm, mkdir } from 'fs/promises'; -import npa from 'npm-package-arg'; -import readline from 'readline'; +import type { Result as NpaResult } from 'npm-package-arg'; import crossSpawn from 'cross-spawn'; -import { readPackageJson } from '@pota/shared/fs'; import kleur from 'kleur'; - -import { SPINNER } from './spinner.js'; +import { readPackageJson, isDirectoryAvailable } from '@pota/shared/fs'; const { green, cyan } = kleur; -export const newline = () => console.log(); - -export const log = (text: string) => console.log(text); - -export function clear() { - if (process.stdout.isTTY) { - console.log('\n'.repeat(process.stdout.rows)); - readline.cursorTo(process.stdout, 0, 0); - readline.clearScreenDown(process.stdout); - } -} +export const log = (text: string = '') => console.log(text); -const createSpawn = (options: SpawnOptions) => - async function spawn(command: string, ...args: string[]): Promise { - await new Promise((resolve, reject) => +function createSpawn(options: SpawnOptions) { + return (command: string, ...args: string[]): Promise => + new Promise((resolve, reject) => crossSpawn(command, args, options) .on('close', (code) => code !== 0 ? reject({ command: `${command} ${args.join(' ')}` }) : resolve(), ) .on('error', reject), ); - }; +} export const spawn = createSpawn({ stdio: 'inherit' }); -export const spawnSilent = createSpawn({ stdio: 'ignore' }); -export const command = (command: string, quiet: boolean = true) => - new Promise((resolve, reject) => +export function command(command: string, quiet: boolean = true) { + return new Promise((resolve, reject) => exec(command, (error, stdout, stderr) => { - if (error) { - return reject(error); - } + if (error) return reject(error); resolve(quiet ? undefined : stdout || stderr); }), ); - -export function isValidSkeleton(skeleton: string) { - try { - return Boolean(npa(skeleton)); - } catch (error) { - return false; - } -} - -export function isFileSkeleton(skeleton: string) { - return npa(skeleton).type === 'file'; -} - -type PackageManager = 'yarn' | 'npm'; - -function getPackageManager(): PackageManager { - const userAgent = process.env.npm_config_user_agent; - - if (userAgent?.startsWith('npm')) { - return 'npm'; - } - - if (userAgent?.startsWith('yarn')) { - return 'yarn'; - } - - return 'npm'; } -interface InstallOptions { - cwd?: string; - dev?: boolean; - npm?: boolean; - yarn?: boolean; -} - -export function createInstaller(options: InstallOptions = {}) { - const { cwd, dev, yarn, npm } = options; - let pre: Array = []; - let post: Array = []; - - const pm = !yarn && !npm ? getPackageManager() : yarn ? 'yarn' : 'npm'; - - switch (pm) { - case 'npm': { - pre = ['install']; - if (cwd) post.push('--prefix', cwd); - if (dev) post.push('--save-dev'); - // reduce terminal noise - post.push('--no-audit', '--no-fund'); - break; - } - case 'yarn': { - pre = ['add']; - if (cwd) post.push('--cwd', cwd); - if (dev) post.push('--dev'); - break; - } - } - - return async (...packages: ReadonlyArray) => { - // we must use `install` instead of `add` with `yarn` - // when installing `package.json` deps - switch (pm) { - case 'yarn': - if (packages.length === 0) pre[0] = 'install'; - break; +export function createBailer(dir?: string) { + return async () => { + if (dir) { + try { + log(); + console.error('Deleting created directory.'); + await rm(dir, { recursive: true }); + } catch {} } - SPINNER.stopAndPersist(); - - try { - await spawn(pm, ...pre, ...packages, ...post); - } finally { - SPINNER.start(); - } + process.exit(1); }; } -export async function getSkeletonName(rawSkeletonName: string, packageJsonPath: string) { - const parsedName = npa(rawSkeletonName); +export async function createDir(path: string) { + if (await isDirectoryAvailable(path)) await mkdir(path, { recursive: true }); + else throw new Error(`${green(path)} already exists, please specify a different directory`); +} +export async function getSkeletonName(skeletonPkgDetails: NpaResult, packageJsonPath: string) { const { dependencies = {}, devDependencies = {} } = await readPackageJson(packageJsonPath); const dependency = [dependencies, devDependencies] .flatMap((d) => Object.entries(d)) .find(([name, version]) => { - switch (parsedName.type) { + switch (skeletonPkgDetails.type) { case 'git': { - const { gitCommittish, hosted } = parsedName; + const { gitCommittish, hosted } = skeletonPkgDetails; const { user, type, project } = hosted!; // github:mediamonks/pota#feature return ( version === `${type}:${user}/${project}#${gitCommittish}` || - version === parsedName.rawSpec + version === skeletonPkgDetails.rawSpec ); } case 'file': - return version === parsedName.saveSpec; + return version === skeletonPkgDetails.saveSpec; default: - return name === rawSkeletonName; + return name === skeletonPkgDetails.raw; } }); - if (!dependency) - throw new Error(`Could not find ${cyan(rawSkeletonName)} in ${green(packageJsonPath)}`); + if (!dependency) { + throw new Error(`Could not find ${cyan(skeletonPkgDetails.raw)} in ${green(packageJsonPath)}`); + } return dependency[0]; // the name of the dependency } diff --git a/core/create/src/index.ts b/core/create/src/index.ts index 53d0e5e1..c7f8f59c 100755 --- a/core/create/src/index.ts +++ b/core/create/src/index.ts @@ -1,166 +1,134 @@ -import { rm, mkdir } from 'fs/promises'; import { relative, basename } from 'path'; +import npa from 'npm-package-arg'; import sade from 'sade'; import kleur from 'kleur'; -import * as fs from '@pota/shared/fs'; +// @ts-ignore TypeScript is being weird +import dedent from 'dedent'; +import { resolveUser } from '@pota/shared/fs'; -import { isSkeletonShorthand, getSkeletonFromShorthand, POTA_CLI } from './config.js'; +import { isSkeletonShorthand, getSkeletonFromShorthand } from './config.js'; import * as helpers from './helpers.js'; import sync from './sync.js'; -import { SPINNER } from './spinner.js'; -const { clear, log } = helpers; -const { red, green, cyan } = kleur; +const { log } = helpers; +const { green, cyan, bold } = kleur; type SadeSkeleton = string; type SadeDirectory = string; interface SadeOptions { 'fail-cleanup': boolean; - 'use-npm': boolean; - 'use-yarn': boolean; } sade('@pota/create ', true) .describe('Create Pota project') .option('--fail-cleanup', 'Cleanup after failing initialization', true) - .option('--use-yarn', 'Force Pota to use yarn', false) - .option('--use-npm', 'Force Pota to use npm', false) .example('npx @pota/create webpack ./project-directory') .action(async (skeleton: SadeSkeleton, dir: SadeDirectory, options: SadeOptions) => { - SPINNER.start(`Creating new Pota App in ${green(dir)}`); - - /** - * Validation - */ - if (!(await fs.isDirectoryAvailable(dir))) { - console.error(`${green(dir)} already exists, please specify a different directory`); - - process.exit(1); - } - - if (!helpers.isValidSkeleton(skeleton)) { - console.error(`${green(skeleton)} is not a valid skeleton package`); - - process.exit(1); - } - - /** - * Post-validation, initialization of utilities - */ - let isFileSkeleton = false; - const pkgName = basename(dir); - const cwd = fs.resolveUser(dir); - - if (helpers.isFileSkeleton(skeleton)) { - isFileSkeleton = true; - skeleton = relative(cwd, skeleton); - } else if (isSkeletonShorthand(skeleton)) skeleton = getSkeletonFromShorthand(skeleton); - - const installOptions = { cwd, npm: options['use-npm'], yarn: options['use-yarn'] }; - const install = helpers.createInstaller(installOptions); - const installDev = helpers.createInstaller({ ...installOptions, dev: true }); - - async function bail() { - if (options['fail-cleanup']) { - try { - console.log(); - console.error('Deleting created directory.'); - await rm(cwd, { recursive: true }); - } catch {} - } + const cwd = resolveUser(dir); - process.exit(1); - } - - /** - * Project creation - */ - - clear(); - - try { - await mkdir(cwd, { recursive: true }); - } catch (error) { - SPINNER.fail(); - console.error(error); - - await bail(); - } + log(`Creating a new Pota App ${cyan(pkgName)} in ${green(cwd)}.`); - SPINNER.succeed(); - // change directory into current working directory (the project directory) - process.chdir(cwd); + // resolve shorthand to full package name + if (isSkeletonShorthand(skeleton)) skeleton = getSkeletonFromShorthand(skeleton); - SPINNER.start('Initializing git'); + // parse the skeleton package + let skeletonPkgDetails: npa.Result; try { - await helpers.command(`git init`); + skeletonPkgDetails = npa(skeleton); } catch (error) { - SPINNER.fail(); - console.error(error); + console.error(`${green(skeleton)} is not a valid skeleton package`); - await bail(); + process.exit(1); } - SPINNER.succeed(); + // if the skeleton package is a file path, then resolve it to a relative path + if (skeletonPkgDetails.type === 'file') skeleton = relative(cwd, skeleton); - const visualName = isFileSkeleton ? basename(skeleton) : skeleton; - - SPINNER.start(`Installing ${cyan(visualName)}, this might take a while...`); + const bail = helpers.createBailer(options['fail-cleanup'] ? cwd : undefined); try { - await installDev(skeleton); + // create project directory + await helpers.createDir(cwd); + + // change directory into current working directory (the project directory) + process.chdir(cwd); + + const visualName = skeletonPkgDetails.type === 'file' ? basename(skeleton) : skeleton; + + log(`Installing ${cyan(visualName)}, this might take a while...`); + log(); + + await helpers.spawn( + 'npm', + 'install', + skeleton, + `--prefix ${cwd}`, + '--include=dev', + '--no-audit', + '--no-fund', + ); + + log(); + console.log(`Setting up project structure...`); + + await sync(cwd, await helpers.getSkeletonName(skeletonPkgDetails, cwd), pkgName); + + console.log(`Installing remaining peer dependencies...`); + + await helpers.spawn( + 'npm', + 'install', + `--prefix ${cwd}`, + '--no-audit', + '--no-fund', + '--prefer-offline', + ); + + // create branch under the name `main` and create initial commit + try { + await helpers.command('git init -b main'); + await helpers.command('git add .'); + await helpers.command('git commit -m "Initial commit from @pota/create"'); + } catch (error) { + // if `-b main` isn't supported fallback to renaming the branch + if ((error as { code: number }).code === 129) { + await helpers.command('git init'); + await helpers.command('git add .'); + await helpers.command('git commit -m "Initial commit from @pota/create"'); + await helpers.command('git branch master -m main'); + } else throw error; + } } catch (error) { - SPINNER.fail(); console.error(error); await bail(); } - try { - skeleton = await helpers.getSkeletonName(skeleton, cwd); - } catch (error) { - SPINNER.fail(`An Error occured reading the project ${green('package.json')}`); - console.error(error); + log(); + log(dedent` + Initialized a git repository. - await bail(); - } + 🚀🚀🚀 ${green('SUCCESS')} 🚀🚀🚀 + Created ${cyan(pkgName)} at ${green(cwd)} - SPINNER.succeed(); + Inside that directory, you can run several commands: - SPINNER.start(`Syncing...`); + ${cyan(`npm run dev`)} + Starts the development server. - try { - await sync(cwd, skeleton, pkgName); - } catch (error) { - SPINNER.fail(); - console.error(error); - - await bail(); - } - - SPINNER.succeed(); - - let failed = false; + ${cyan(`npm run build`)} + Builds the app for production. - SPINNER.start(`Syncing peer dependencies...`); + We suggest that you begin by typing: - try { - await install(); - SPINNER.succeed(); - } catch (error) { - SPINNER.fail(); - console.error(error); - - failed = true; - } + ${cyan('cd')} my-app + ${cyan(`npm run dev`)} - SPINNER.stop(); - if (failed) log(red(`🥊 Done, but with errors 😥`)); - else log(`🥊 Done`); + `); process.exit(0); }) diff --git a/core/create/src/spinner.ts b/core/create/src/spinner.ts deleted file mode 100644 index 6548759f..00000000 --- a/core/create/src/spinner.ts +++ /dev/null @@ -1,3 +0,0 @@ -import ora from 'ora'; - -export const SPINNER = ora(); diff --git a/core/create/src/sync.ts b/core/create/src/sync.ts index 06134d55..6546a271 100644 --- a/core/create/src/sync.ts +++ b/core/create/src/sync.ts @@ -1,11 +1,85 @@ -import { join, dirname } from 'path'; +import { join, dirname, basename, extname } from 'path'; +import { copyFile, mkdir } from 'fs/promises'; -import { PACKAGE_JSON_FILE, POTA_COMMANDS_DIR, POTA_DIR } from '@pota/shared/config'; +// @ts-ignore TypeScript is being weird +import merge from 'lodash.merge'; +import { sortPackageJson } from 'sort-package-json'; +import type { PackageJsonShape } from '@pota/shared/config'; +import { PotaConfig, PACKAGE_JSON_FILE, POTA_COMMANDS_DIR, POTA_DIR } from '@pota/shared/config'; import { getNestedSkeletons } from '@pota/shared/skeleton'; +import { exists, readPackageJson, writePackageJson } from '@pota/shared/fs'; -import ProjectPackage from './ProjectPackage.js'; -import { copyFile, mkdir } from 'fs/promises'; -import { exists } from '@pota/shared/fs'; +import { POTA_CLI, POTA_CLI_BIN } from './config.js'; + +function addFileAsScript(pkg: PackageJsonShape, file: string) { + const command = basename(file, extname(file)); + + pkg.scripts ??= {}; + pkg.scripts[command] = `${POTA_CLI_BIN} ${command}`; +} + +const IGNORED_PACKAGE_FIELDS: ReadonlyArray = [ + 'name', + 'version', + 'peerDependencies', + 'dependencies', + 'devDependencies', + 'files', + 'publishConfig', + 'repository', + 'bugs', + 'author', +]; + +function filterObject>(o: T, fields: ReadonlyArray) { + type Result = Record; + + let r: Result | undefined = undefined; + + for (const field of Object.keys(o) as ReadonlyArray) { + if (fields.includes(field)) { + r ??= {} as Result; + r[field] = o[field]; + } + } + + return r; +} + +/* + * Merges the fields of the package from `path` into the project package. + */ +async function mergeSkeleton(pkg: PackageJsonShape, path: string, config: PotaConfig) { + const skeletonPkg = await readPackageJson(path); + + const { name: skeleton, version, peerDependencies = {} } = skeletonPkg; + + for (const field of IGNORED_PACKAGE_FIELDS) { + delete skeletonPkg[field]; + } + + if ('scripts' in skeletonPkg && 'scripts' in config) { + skeletonPkg.scripts = filterObject(skeletonPkg.scripts!, config.scripts!); + } + + merge(pkg, skeletonPkg); + + // place the skeleton package in `devDependencies` + pkg.devDependencies ??= {}; + // TODO: this semver chevron ain't great, chief + pkg.devDependencies[skeleton!] = `^${version!}`; + + for (const [dep, version] of Object.entries(peerDependencies)) { + // place the `@pota/cli` (if it exists) package in `devDependencies` + if (dep === POTA_CLI) pkg.devDependencies[POTA_CLI] = peerDependencies[POTA_CLI]; + // this `else if` condition makes sure that the dependency isn't defined in `devDependencies` + // which might me the case for extended skeletons defined in `peerDependencies` + else if (!(dep in pkg.devDependencies)) { + pkg.dependencies ??= {}; + pkg.dependencies[dep] = version; + } + } +} async function copy(src: string, dst: string) { // create destination directories if they don't exist @@ -18,9 +92,9 @@ async function copy(src: string, dst: string) { export default async function sync(targetPath: string, skeleton: string, pkgName: string) { const nestedSkeletons = await getNestedSkeletons(targetPath, skeleton); - const projectPkg = (await new ProjectPackage(targetPath).load()) - .setName(pkgName) - .setDefaultSkeleton(skeleton); + const pkg = await readPackageJson(targetPath); + pkg.name = pkgName; + pkg.pota = skeleton; const commandsDir = join(POTA_DIR, POTA_COMMANDS_DIR); @@ -30,10 +104,9 @@ export default async function sync(targetPath: string, skeleton: string, pkgName for (const { path, config, files } of nestedSkeletons) { if (config.omit) omits.push(...config.omit); for (const file of files) { - if (file === PACKAGE_JSON_FILE) { - await projectPkg.merge(path, config); - } else if (file.startsWith(POTA_DIR)) { - if (file.startsWith(commandsDir)) projectPkg.applyFileAsScript(file); + if (file === PACKAGE_JSON_FILE) await mergeSkeleton(pkg, path, config); + else if (file.startsWith(POTA_DIR)) { + if (file.startsWith(commandsDir)) addFileAsScript(pkg, file); } else { const renamed = config.rename?.[file] ?? file; fileMap.set(renamed, { src: join(path, file), dst: join(targetPath, renamed) }); @@ -45,5 +118,5 @@ export default async function sync(targetPath: string, skeleton: string, pkgName if (!omits.includes(file)) await copy(src, dst); } - await projectPkg.sort().write(); + await writePackageJson(sortPackageJson(pkg), targetPath); } diff --git a/package-lock.json b/package-lock.json index 13e9fb1c..b83f289c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,6 @@ "kleur": "^4.1.4", "lodash.merge": "^4.6.2", "npm-package-arg": "^8.1.5", - "ora": "^6.0.1", "sade": "^1.7.4", "sort-package-json": "^1.52.0" }, @@ -59,13 +58,16 @@ }, "devDependencies": { "@types/cross-spawn": "^6.0.2", + "@types/dedent": "^0.7.0", "@types/lodash.merge": "^4.6.6", "@types/npm-package-arg": "^6.1.1", - "@types/sade": "^1.7.3" + "@types/sade": "^1.7.3", + "dedent": "^0.7.0" }, "engines": { "node": ">=14", - "npm": ">=7" + "npm": ">=7", + "yarn": "unsupported" } }, "core/create/node_modules/kleur": { @@ -2254,6 +2256,12 @@ "@types/node": "*" } }, + "node_modules/@types/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@types/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A==", + "dev": true + }, "node_modules/@types/eslint": { "version": "7.28.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.2.tgz", @@ -13802,14 +13810,15 @@ "requires": { "@pota/shared": "^1.4.0", "@types/cross-spawn": "^6.0.2", + "@types/dedent": "^0.7.0", "@types/lodash.merge": "^4.6.6", "@types/npm-package-arg": "^6.1.1", "@types/sade": "^1.7.3", "cross-spawn": "^7.0.3", + "dedent": "^0.7.0", "kleur": "^4.1.4", "lodash.merge": "^4.6.2", "npm-package-arg": "^8.1.5", - "ora": "^6.0.1", "sade": "^1.7.4", "sort-package-json": "^1.52.0" }, @@ -14288,6 +14297,12 @@ "@types/node": "*" } }, + "@types/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@types/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A==", + "dev": true + }, "@types/eslint": { "version": "7.28.2", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.2.tgz",