From ee78eb282d3c00e84c5411eca753e19005d76e7d Mon Sep 17 00:00:00 2001 From: mazuh Date: Mon, 13 Jun 2022 10:30:28 -0300 Subject: [PATCH 1/5] feat: lint option for javascript template --- README.md | 2 ++ args.js | 5 +++-- generate.js | 24 +++++++++++++++++++++++- help/generate.txt | 3 +++ test/generate.test.js | 19 +++++++++++++++++++ 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 896613dd..086c730c 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,7 @@ The sample code offers you the following npm tasks: [`pino-pretty`](https://github.com/pinojs/pino-pretty) pretty logging (not suitable for production) * `npm test` - runs the tests +* `npm run lint` - fixes files accordingly to linter rules, for templates generated with `--standardlint` You will find three different folders: - `plugins`: the folder where you will place all your custom plugins @@ -263,6 +264,7 @@ it will be overwritten. Use the `--integrate` flag with care. | --- | --- | | Use the TypeScript template | `--lang=ts`, `--lang=typescript` | | Overwrite it when the target directory is the current directory (`.`) | `--integrate`| +| For JavaScript template, optionally includes Standard linter to fix code style issues | `--standardlint`| ### generate-plugin diff --git a/args.js b/args.js index 8a7edb98..92a208ff 100644 --- a/args.js +++ b/args.js @@ -12,7 +12,7 @@ module.exports = function parseArgs (args) { 'populate--': true }, number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout'], - string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require'], + string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'standardlint'], boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug'], envPrefix: 'FASTIFY_', alias: { @@ -40,7 +40,8 @@ module.exports = function parseArgs (args) { debugPort: 9320, options: false, 'plugin-timeout': 10 * 1000, // everything should load in 10 seconds - lang: 'js' + lang: 'js', + standardlint: false } }) diff --git a/generate.js b/generate.js index c97f1aea..9e14b799 100755 --- a/generate.js +++ b/generate.js @@ -38,6 +38,10 @@ const javascriptTemplate = { log('debug', `run '${chalk.bold('npm start')}' to start the application`) log('debug', `run '${chalk.bold('npm run dev')}' to start the application with pino-colada pretty logging (not suitable for production)`) log('debug', `run '${chalk.bold('npm test')}' to execute the unit tests`) + + if (Object.keys(pkg.scripts).includes('lint')) { + log('debug', `run '${chalk.bold('npm lint')}' to run linter and fix code style issues`) + } } } @@ -149,7 +153,25 @@ function cli (args) { process.exit(1) } - const template = opts.lang === 'ts' || opts.lang === 'typescript' ? typescriptTemplate : javascriptTemplate + let template + if (opts.lang === 'ts' || opts.lang === 'typescript') { + template = typescriptTemplate + } else { + template = { ...javascriptTemplate } + + if (opts.standardlint) { + template.scripts = { + ...template.scripts, + pretest: 'standard', + lint: 'standard --fix' + } + + template.devDependencies = { + ...template.devDependencies, + standard: cliPkg.devDependencies.standard + } + } + } generate(dir, template).catch(function (err) { if (err) { diff --git a/help/generate.txt b/help/generate.txt index f2a111ad..250e21d4 100644 --- a/help/generate.txt +++ b/help/generate.txt @@ -11,3 +11,6 @@ OPTS --lang=ts, --lang=typescript use the TypeScript template + + --standardlint + for JavaScript template, optionally includes linter to fix code style issues diff --git a/test/generate.test.js b/test/generate.test.js index 1d8b14c2..812529bf 100644 --- a/test/generate.test.js +++ b/test/generate.test.js @@ -9,6 +9,7 @@ const { mkdirSync, readFileSync, readFile, + promises: fsPromises, unlink } = require('fs') const path = require('path') @@ -128,6 +129,24 @@ function define (t) { } }) + test('--standardlint option will add standard lint dependencies and scripts to javascript template', async (t) => { + t.plan(14 + 3) + try { + rimraf.sync(workdir) + await pExec('node ../generate workdir --standardlint', { cwd: path.join(workdir, '..') }) + + await verifyPkg(t) + + const data = await fsPromises.readFile(path.join(workdir, 'package.json')) + const pkg = JSON.parse(data) + t.equal(pkg.scripts.pretest, 'standard') + t.equal(pkg.scripts.lint, 'standard --fix') + t.equal(pkg.devDependencies.standard, cliPkg.devDependencies.standard) + } catch (err) { + t.error(err) + } + }) + function verifyPkg (t) { return new Promise((resolve, reject) => { const pkgFile = path.join(workdir, 'package.json') From bef3f12f83adc5658678133a5fb592f4932375a9 Mon Sep 17 00:00:00 2001 From: mazuh Date: Wed, 15 Jun 2022 05:40:26 -0300 Subject: [PATCH 2/5] chore: mark standardlint as as bool --- args.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/args.js b/args.js index 92a208ff..7c8a0a4d 100644 --- a/args.js +++ b/args.js @@ -12,8 +12,8 @@ module.exports = function parseArgs (args) { 'populate--': true }, number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout'], - string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'standardlint'], - boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug'], + string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require'], + boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug', 'standardlint'], envPrefix: 'FASTIFY_', alias: { port: ['p'], From 8a804c4f4ec6438303240d8ab1770b7ba7e11a2d Mon Sep 17 00:00:00 2001 From: mazuh Date: Mon, 20 Jun 2022 10:28:14 -0300 Subject: [PATCH 3/5] fix tests for windows removing directories with .sync is limited on windows so I refactored my test to always use an available folder instead of concurring with the existing one --- .gitignore | 2 +- test/generate.test.js | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 9eeaef70..f72f696b 100644 --- a/.gitignore +++ b/.gitignore @@ -148,7 +148,7 @@ yarn.lock test.sock # test artifacts -test/workdir +test/workdir* test/fixtures/*.js .vscode/launch.json .vscode/settings.json diff --git a/test/generate.test.js b/test/generate.test.js index 812529bf..dd7e6078 100644 --- a/test/generate.test.js +++ b/test/generate.test.js @@ -132,12 +132,15 @@ function define (t) { test('--standardlint option will add standard lint dependencies and scripts to javascript template', async (t) => { t.plan(14 + 3) try { - rimraf.sync(workdir) - await pExec('node ../generate workdir --standardlint', { cwd: path.join(workdir, '..') }) + const dir = path.join(__dirname, 'workdir-with-lint') + const cwd = path.join(dir, '..') + const bin = path.join('..', 'generate') + rimraf.sync(dir) + await pExec(`node ${bin} ${dir} --standardlint`, { cwd }) - await verifyPkg(t) + await verifyPkg(t, dir, 'workdir-with-lint') - const data = await fsPromises.readFile(path.join(workdir, 'package.json')) + const data = await fsPromises.readFile(path.join(dir, 'package.json')) const pkg = JSON.parse(data) t.equal(pkg.scripts.pretest, 'standard') t.equal(pkg.scripts.lint, 'standard --fix') @@ -147,14 +150,14 @@ function define (t) { } }) - function verifyPkg (t) { + function verifyPkg (t, dir = workdir, pkgName = 'workdir') { return new Promise((resolve, reject) => { - const pkgFile = path.join(workdir, 'package.json') + const pkgFile = path.join(dir, 'package.json') readFile(pkgFile, function (err, data) { err && reject(err) const pkg = JSON.parse(data) - t.equal(pkg.name, 'workdir') + t.equal(pkg.name, pkgName) // we are not checking author because it depends on global npm configs t.equal(pkg.version, '1.0.0') t.equal(pkg.description, 'This project was bootstrapped with Fastify-CLI.') From f1e136a5e23c87feef4844ff913ab05dbf9183b3 Mon Sep 17 00:00:00 2001 From: mazuh Date: Wed, 22 Jun 2022 11:50:59 -0300 Subject: [PATCH 4/5] apply a few reviews --- generate.js | 2 +- test/generate.test.js | 31 +++++++++++++------------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/generate.js b/generate.js index 9e14b799..bd8bd799 100755 --- a/generate.js +++ b/generate.js @@ -39,7 +39,7 @@ const javascriptTemplate = { log('debug', `run '${chalk.bold('npm run dev')}' to start the application with pino-colada pretty logging (not suitable for production)`) log('debug', `run '${chalk.bold('npm test')}' to execute the unit tests`) - if (Object.keys(pkg.scripts).includes('lint')) { + if (pkg.scripts.lint) { log('debug', `run '${chalk.bold('npm lint')}' to run linter and fix code style issues`) } } diff --git a/test/generate.test.js b/test/generate.test.js index dd7e6078..923d8585 100644 --- a/test/generate.test.js +++ b/test/generate.test.js @@ -130,24 +130,19 @@ function define (t) { }) test('--standardlint option will add standard lint dependencies and scripts to javascript template', async (t) => { - t.plan(14 + 3) - try { - const dir = path.join(__dirname, 'workdir-with-lint') - const cwd = path.join(dir, '..') - const bin = path.join('..', 'generate') - rimraf.sync(dir) - await pExec(`node ${bin} ${dir} --standardlint`, { cwd }) - - await verifyPkg(t, dir, 'workdir-with-lint') - - const data = await fsPromises.readFile(path.join(dir, 'package.json')) - const pkg = JSON.parse(data) - t.equal(pkg.scripts.pretest, 'standard') - t.equal(pkg.scripts.lint, 'standard --fix') - t.equal(pkg.devDependencies.standard, cliPkg.devDependencies.standard) - } catch (err) { - t.error(err) - } + const dir = path.join(__dirname, 'workdir-with-lint') + const cwd = path.join(dir, '..') + const bin = path.join('..', 'generate') + rimraf.sync(dir) + await pExec(`node ${bin} ${dir} --standardlint`, { cwd }) + + await verifyPkg(t, dir, 'workdir-with-lint') + + const data = await fsPromises.readFile(path.join(dir, 'package.json')) + const pkg = JSON.parse(data) + t.equal(pkg.scripts.pretest, 'standard') + t.equal(pkg.scripts.lint, 'standard --fix') + t.equal(pkg.devDependencies.standard, cliPkg.devDependencies.standard) }) function verifyPkg (t, dir = workdir, pkgName = 'workdir') { From 6d63abde931239c81e0e7acf10d4c3826a06b5ac Mon Sep 17 00:00:00 2001 From: mazuh Date: Thu, 23 Jun 2022 10:11:36 -0300 Subject: [PATCH 5/5] support ts-standard for typescript template --- README.md | 18 ------------ generate.js | 47 ++++++++++++++++++++++++-------- help/generate.txt | 2 +- test/generate-typescript.test.js | 27 +++++++++++++++--- 4 files changed, 59 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 086c730c..f98dc043 100644 --- a/README.md +++ b/README.md @@ -297,24 +297,6 @@ Finally, there will be a new `README.md` file, which provides internal informati * Encapsulation semantics * Compatible Fastify version -### linting - -`fastify-cli` is unopinionated on the choice of linter. We recommend you to add a linter, like so: - -```diff -"devDependencies": { -+ "standard": "^11.0.1", -} - -"scripts": { -+ "pretest": "standard", - "test": "tap test/**/*.test.js", - "start": "fastify start -l info app.js", - "dev": "fastify start -l info -P app.js", -+ "lint": "standard --fix" -}, -``` - ## Test helpers When you use `fastify-cli` to run your project you need a way to load your application because you can run the CLI command. diff --git a/generate.js b/generate.js index bd8bd799..1fae5adb 100755 --- a/generate.js +++ b/generate.js @@ -84,6 +84,10 @@ const typescriptTemplate = { log('debug', `run '${chalk.bold('npm build:ts')}' to compile the typescript application`) log('debug', `run '${chalk.bold('npm run dev')}' to start the application with pino-colada pretty logging (not suitable for production)`) log('debug', `run '${chalk.bold('npm test')}' to execute the unit tests`) + + if (pkg.scripts.lint) { + log('debug', `run '${chalk.bold('npm lint')}' to run linter and fix code style issues`) + } } } @@ -153,23 +157,42 @@ function cli (args) { process.exit(1) } + const isTypescript = opts.lang === 'ts' || opts.lang === 'typescript' + let template - if (opts.lang === 'ts' || opts.lang === 'typescript') { - template = typescriptTemplate + if (isTypescript) { + template = { ...typescriptTemplate } } else { template = { ...javascriptTemplate } + } - if (opts.standardlint) { - template.scripts = { - ...template.scripts, - pretest: 'standard', - lint: 'standard --fix' - } + if (opts.standardlint && isTypescript) { + template.scripts = { + ...template.scripts, + pretest: 'ts-standard', + lint: 'ts-standard --fix' + } - template.devDependencies = { - ...template.devDependencies, - standard: cliPkg.devDependencies.standard - } + template.devDependencies = { + ...template.devDependencies, + 'ts-standard': cliPkg.devDependencies['ts-standard'] + } + template['ts-standard'] = { + ignore: [ + 'dist', + 'src/**/*.js' + ] + } + } else if (opts.standardlint) { + template.scripts = { + ...template.scripts, + pretest: 'standard', + lint: 'standard --fix' + } + + template.devDependencies = { + ...template.devDependencies, + standard: cliPkg.devDependencies.standard } } diff --git a/help/generate.txt b/help/generate.txt index 250e21d4..0638c260 100644 --- a/help/generate.txt +++ b/help/generate.txt @@ -13,4 +13,4 @@ OPTS use the TypeScript template --standardlint - for JavaScript template, optionally includes linter to fix code style issues + optionally includes linter to fix code style issues diff --git a/test/generate-typescript.test.js b/test/generate-typescript.test.js index e8ec1783..ad2419f7 100644 --- a/test/generate-typescript.test.js +++ b/test/generate-typescript.test.js @@ -8,9 +8,11 @@ const t = require('tap') const { mkdirSync, readFileSync, - readFile + readFile, + promises: fsPromises } = require('fs') const path = require('path') +const { promisify } = require('util') const rimraf = require('rimraf') const walker = require('walker') const { generate, typescriptTemplate } = require('../generate') @@ -18,6 +20,7 @@ const workdir = path.join(__dirname, 'workdir') const appTemplateDir = path.join(__dirname, '..', 'templates', 'app-ts') const cliPkg = require('../package') const { exec } = require('child_process') +const pExec = promisify(exec) const minimatch = require('minimatch') const strip = require('strip-ansi') const expected = {} @@ -111,14 +114,30 @@ function define (t) { } }) - function verifyPkg (t) { + test('--standardlint option will add standard lint dependencies and scripts to typescript template', async (t) => { + const dir = path.join(__dirname, 'workdir-with-lint') + const cwd = path.join(dir, '..') + const bin = path.join('..', 'generate') + rimraf.sync(dir) + await pExec(`node ${bin} ${dir} --lang=ts --standardlint`, { cwd }) + + await verifyPkg(t, dir, 'workdir-with-lint') + + const data = await fsPromises.readFile(path.join(dir, 'package.json')) + const pkg = JSON.parse(data) + t.equal(pkg.scripts.pretest, 'ts-standard') + t.equal(pkg.scripts.lint, 'ts-standard --fix') + t.equal(pkg.devDependencies['ts-standard'], cliPkg.devDependencies['ts-standard']) + }) + + function verifyPkg (t, dir = workdir, pkgName = 'workdir') { return new Promise((resolve, reject) => { - const pkgFile = path.join(workdir, 'package.json') + const pkgFile = path.join(dir, 'package.json') readFile(pkgFile, function (err, data) { t.error(err) const pkg = JSON.parse(data) - t.equal(pkg.name, 'workdir') + t.equal(pkg.name, pkgName) // we are not checking author because it depends on global npm configs t.equal(pkg.version, '1.0.0') t.equal(pkg.description, 'This project was bootstrapped with Fastify-CLI.')