diff --git a/.gitignore b/.gitignore index 239ecff..bf4fb70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules +build yarn.lock diff --git a/package.json b/package.json index 1138e87..1d8ffff 100644 --- a/package.json +++ b/package.json @@ -13,16 +13,19 @@ "type": "module", "exports": { "types": "./index.d.ts", - "default": "./source/index.js" + "default": "./build/index.js" }, + "sideEffects": false, "engines": { "node": ">=16.10" }, "scripts": { - "test": "xo && ava && tsd" + "prepare": "npm run build", + "build": "rollup --config", + "test": "xo && tsd && npm run build && ava" }, "files": [ - "source", + "build", "index.d.ts" ], "keywords": [ @@ -44,34 +47,56 @@ "cmd", "console" ], - "dependencies": { + "_actualDependencies": [ + "@types/minimist", + "camelcase-keys", + "decamelize", + "decamelize-keys", + "hard-rejection", + "minimist-options", + "normalize-package-data", + "read-pkg-up", + "redent", + "trim-newlines", + "type-fest", + "yargs-parser" + ], + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.3", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.1.0", "@types/minimist": "^1.2.2", + "ava": "^5.3.1", "camelcase-keys": "^8.0.2", + "common-tags": "^2.0.0-alpha.1", "decamelize": "^6.0.0", "decamelize-keys": "^2.0.1", + "delete_comments": "^0.0.2", + "execa": "^7.2.0", + "globby": "^13.2.2", "hard-rejection": "^2.1.0", + "indent-string": "^5.0.0", "minimist-options": "4.1.0", "normalize-package-data": "^5.0.0", + "read-pkg": "^8.0.0", "read-pkg-up": "^10.0.0", "redent": "^4.0.0", + "rollup": "^3.27.0", + "rollup-plugin-license": "^3.0.1", "trim-newlines": "^5.0.0", + "tsd": "^0.28.1", "type-fest": "^4.2.0", + "xo": "^0.56.0", "yargs-parser": "^21.1.1" }, - "devDependencies": { - "ava": "^5.3.1", - "common-tags": "^1.8.2", - "execa": "^7.2.0", - "indent-string": "^5.0.0", - "read-pkg": "^8.0.0", - "tsd": "^0.28.1", - "xo": "^0.56.0" - }, "xo": { "rules": { "unicorn/no-process-exit": "off", "unicorn/error-message": "off" - } + }, + "ignores": [ + "build" + ] }, "ava": { "files": [ diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..55f7ab0 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,57 @@ +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import json from '@rollup/plugin-json'; +import license from 'rollup-plugin-license'; +import {globby} from 'globby'; +import {createTag, replaceResultTransformer} from 'common-tags'; +import {delete_comments as deleteComments} from 'delete_comments'; +import {defineConfig} from 'rollup'; + +/** Matches empty lines: https://stackoverflow.com/q/16369642/10292952 */ +const emptyLineRegex = /^\s*[\r\n]/gm; + +const stripComments = createTag( + {onEndResult: deleteComments}, + replaceResultTransformer(emptyLineRegex, ''), +); + +const outputDirectory = 'build'; + +export default defineConfig({ + input: await globby('source/**/*.js'), + output: { + dir: outputDirectory, + interop: 'esModule', + generatedCode: { + preset: 'es2015', + }, + chunkFileNames: '[name].js', + manualChunks(id) { + if (id.includes('node_modules')) { + return 'dependencies'; + } + }, + hoistTransitiveImports: false, + plugins: [{ + name: 'strip-dependency-comments', + renderChunk(code, chunk) { + return chunk.name === 'dependencies' ? stripComments(code) : null; + }, + }], + }, + treeshake: { + moduleSideEffects: 'no-external', + }, + plugins: [ + nodeResolve(), + commonjs({ + include: 'node_modules/**', + }), + json(), + license({ + thirdParty: { + output: `${outputDirectory}/licenses.md`, + }, + }), + ], +}); diff --git a/test/_utils.js b/test/_utils.js index 2b7f498..f09a405 100644 --- a/test/_utils.js +++ b/test/_utils.js @@ -1,6 +1,7 @@ import path from 'node:path'; import {fileURLToPath} from 'node:url'; import {execa} from 'execa'; +import {createTag, stripIndentTransformer, trimResultTransformer} from 'common-tags'; export const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -15,3 +16,9 @@ export const spawnFixture = async (fixture = 'fixture.js', args = []) => { return execa(getFixture(fixture), args); }; + +// Use old behavior prior to zspecza/common-tags#165 +export const stripIndent = createTag( + stripIndentTransformer(), + trimResultTransformer(), +); diff --git a/test/build.js b/test/build.js new file mode 100644 index 0000000..5607ef7 --- /dev/null +++ b/test/build.js @@ -0,0 +1,46 @@ +import test from 'ava'; +import {readPackage} from 'read-pkg'; +import meow from '../build/index.js'; +import {spawnFixture} from './_utils.js'; + +test('main', t => { + const cli = meow(` + Usage + foo + `, { + importMeta: import.meta, + argv: 'foo --foo-bar --u cat -- unicorn cake'.split(' '), + flags: { + unicorn: { + shortFlag: 'u', + }, + meow: { + default: 'dog', + }, + '--': true, + }, + }); + + t.like(cli, { + input: ['foo'], + flags: { + fooBar: true, + meow: 'dog', + unicorn: 'cat', + '--': [ + 'unicorn', + 'cake', + ], + }, + pkg: { + name: 'meow', + }, + help: '\n CLI app helper\n\n Usage\n foo \n', + }); +}); + +test('spawn cli and show version', async t => { + const pkg = await readPackage(); + const {stdout} = await spawnFixture(['--version']); + t.is(stdout, pkg.version); +}); diff --git a/test/choices.js b/test/choices.js index e786d8b..7fcf78b 100644 --- a/test/choices.js +++ b/test/choices.js @@ -1,6 +1,6 @@ import test from 'ava'; -import {stripIndent} from 'common-tags'; import meow from '../source/index.js'; +import {stripIndent} from './_utils.js'; const importMeta = import.meta; diff --git a/test/errors.js b/test/errors.js index f20f175..dd28aac 100644 --- a/test/errors.js +++ b/test/errors.js @@ -1,6 +1,6 @@ import test from 'ava'; -import {stripIndent} from 'common-tags'; import meow from '../source/index.js'; +import {stripIndent} from './_utils.js'; const importMeta = import.meta; diff --git a/test/fixtures/build.js b/test/fixtures/build.js new file mode 100755 index 0000000..83f7222 --- /dev/null +++ b/test/fixtures/build.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node +import process from 'node:process'; +import meow from '../../build/index.js'; + +const cli = meow(` + Usage + foo +`, { + importMeta: import.meta, + description: 'Custom description', + autoVersion: !process.argv.includes('--no-auto-version'), + autoHelp: !process.argv.includes('--no-auto-help'), + flags: { + unicorn: { + shortFlag: 'u', + }, + meow: { + default: 'dog', + }, + camelCaseOption: { + default: 'foo', + }, + }, +}); + +if (cli.flags.camelCaseOption === 'foo') { + for (const flagKey of Object.keys(cli.flags)) { + console.log(flagKey); + } +} else { + console.log(cli.flags.camelCaseOption); +}