From d0c1ca01661e6dac7595e3b7bc41e1562dd38110 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 11 Sep 2020 11:34:42 +0100 Subject: [PATCH] feat: generate ts types Adds a `generate-types` command to generate `*.d.ts` files. Largely inspired by @AuHau's work on https://github.com/achingbrain/uint8arrays/pull/4 --- .gitignore | 3 +- README.md | 32 +++++++++++++++++++-- cmds/generate-types.js | 17 ++++++++++++ package.json | 1 + src/generate-types/index.js | 55 +++++++++++++++++++++++++++++++++++++ test/generate-types.js | 17 ++++++++++++ test/node.js | 1 + 7 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 cmds/generate-types.js create mode 100644 src/generate-types/index.js create mode 100644 test/generate-types.js diff --git a/.gitignore b/.gitignore index 0c4e49dfa..0bb08c283 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ node_modules /docs .nyc_output *.log -.vscode \ No newline at end of file +.vscode +*.d.ts diff --git a/README.md b/README.md index f45b58475..b99f7b221 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ You can run your tests with `nyc` using ```bash $ npx nyc -s aegir test -t node -# to check the report locally +# to check the report locally $ npx nyc report --reporter=html && open coverage/index.html # or just for a text based reporter $ npx nyc report @@ -236,6 +236,34 @@ Pass the `--analyze` option to have Webpack generate a `stats.json` file for the aegir build --analyze ``` +### Generating types + +This will generate `.d.ts` files from files in your project. Suitable for use in a `prepublishOnly` [npm script](https://docs.npmjs.com/misc/scripts). + +```console +$ aegir generate-types PATTERN +``` + +It supports a glob pattern as the argument, but to prevent cli expansion you should wrap it in quotes: + +```console +$ aegir generate-types 'src/**/*.js' +``` + +Pass the `--overwrite` option to remove `.d.ts` files that would be generated: + +```console +$ aegir generate-types --overwrite 'src/**/*.js' +``` + +Any flags or config to pass to `tsc` can be specified as forward options: + +```console +$ aegir generate-types --overwrite 'src/**/*.js' -- --allowJs --esModuleInterop +``` + +Since these are generated files you may wish to add `*.d.ts` to your `.gitignore` file if you are generating types from JSDocs as part of a js project release. + ### Releasing 1. Run linting @@ -282,7 +310,7 @@ If you want no documentation generation you can pass `--no-docs` to the release #### Scoped Github Token -Performing a release involves creating new commits and tags and then pushing them back to the repository you are releasing from. In order to do this you should create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) and store it in the environmental variable `AEGIR_GHTOKEN`. +Performing a release involves creating new commits and tags and then pushing them back to the repository you are releasing from. In order to do this you should create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) and store it in the environmental variable `AEGIR_GHTOKEN`. The only access scope it needs is `public_repo`. diff --git a/cmds/generate-types.js b/cmds/generate-types.js new file mode 100644 index 000000000..ca19ffe5f --- /dev/null +++ b/cmds/generate-types.js @@ -0,0 +1,17 @@ +'use strict' + +module.exports = { + command: 'generate-types [input...]', + desc: 'Generate .d.ts files for the project', + builder: { + overwrite: { + type: 'boolean', + default: false, + describe: 'Whether to remove all .d.ts files in the project before running', + } + }, + handler (argv) { + const build = require('../src/generate-types') + return build(argv) + } +} diff --git a/package.json b/package.json index 2c09ee301..2f1f7ac53 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "git-validate": "^2.2.4", "globby": "^11.0.1", "ipfs-utils": "^2.3.0", + "it-all": "^1.0.2", "it-glob": "~0.0.8", "json-loader": "~0.5.7", "karma": "^5.1.0", diff --git a/src/generate-types/index.js b/src/generate-types/index.js new file mode 100644 index 000000000..95f95ff23 --- /dev/null +++ b/src/generate-types/index.js @@ -0,0 +1,55 @@ +'use strict' + +const { + exec +} = require('../utils') +const glob = require('it-glob') +const all = require('it-all') +const promisify = require('util').promisify +const rimraf = promisify(require('rimraf')) + +async function generateTypes (argv) { + const files = (await Promise.all( + argv.input.map(pattern => all(glob(process.cwd(), pattern, { + absolute: true, + nodir: true + }))) + )).reduce((acc, curr) => acc.concat(curr), []) + + if (!files.length) { + throw new Error(`Invalid input glob pattern ${argv.input.join()}`) + } + + if (argv.overwrite) { + // remove any .td.ts definitions that already exist for the input files + for (const path of files) { + if (!path.endsWith('.js')) { + continue + } + + // foo.js -> foo.d.ts + const tsDef = path.substring(0, path.length - 3) + '.d.ts' + + // will not error if the file does not exist + await rimraf(tsDef) + } + } + + const forwardOptions = argv['--'] ? argv['--'] : [] + const args = ['-d', '--emitDeclarationOnly'].concat(forwardOptions).concat(files) + + const cmd = exec(require.resolve('typescript/bin/tsc'), args, { + cwd: process.cwd() + }) + + cmd.stdout.on('data', data => { + console.info(data.toString()) // eslint-disable-line no-console + }) + cmd.stderr.on('data', data => { + console.error(data.toString()) // eslint-disable-line no-console + }) + + await cmd +} + +module.exports = generateTypes diff --git a/test/generate-types.js b/test/generate-types.js new file mode 100644 index 000000000..3ec10e298 --- /dev/null +++ b/test/generate-types.js @@ -0,0 +1,17 @@ +/* eslint-env mocha */ +'use strict' + +const generateTypes = require('../src/generate-types') + +describe('generate-types', () => { + it('generate types for itself (aegir)', function () { + this.timeout(60 * 1000) // slow ci is slow + return generateTypes({ + input: ['src/**/*.js'], + overwrite: true, + '--': [ + '--allowJs' + ] + }) + }) +}) diff --git a/test/node.js b/test/node.js index aea5af8f6..e23829f84 100644 --- a/test/node.js +++ b/test/node.js @@ -9,3 +9,4 @@ require('./dependency-check') require('./utils/echo-server') require('./utils/get-port') require('./config/user') +require('./generate-types')