qa-control 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,10 +6,9 @@ Quality assurance tool for node/npm projects
6
6
  ![extending](https://img.shields.io/badge/stability-extending-orange.svg)
7
7
  [![npm-version](https://img.shields.io/npm/v/qa-control.svg)](https://npmjs.org/package/qa-control)
8
8
  [![downloads](https://img.shields.io/npm/dm/qa-control.svg)](https://npmjs.org/package/qa-control)
9
- [![build](https://github.com/codenautas/qa-control/workflows/node.js.yml/badge.svg)](https://github.com/codenautas/qa-control/workflows/node.js.yml)
9
+ [![build](https://github.com/codenautas/qa-control/actions/workflows/node.js.yml/badge.svg)](https://github.com/codenautas/qa-control/actions/workflows/node.js.yml)
10
10
  [![coverage](https://img.shields.io/coveralls/codenautas/qa-control/master.svg)](https://coveralls.io/r/codenautas/qa-control)
11
- [![climate](https://img.shields.io/codeclimate/github/codenautas/qa-control.svg)](https://codeclimate.com/github/codenautas/qa-control)
12
- [![dependencies](https://img.shields.io/david/codenautas/qa-control.svg)](https://david-dm.org/codenautas/qa-control)
11
+ [![dependencies](https://snyk.io/test/github/codenautas/qa-control/badge.svg)](https://snyk.io/test/github/codenautas/qa-control)
13
12
  [![qa-control](http://codenautas.com/github/codenautas/qa-control.svg)](http://codenautas.com/github/codenautas/qa-control)
14
13
 
15
14
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  var stripBom = require("strip-bom-string");
4
4
  var semver = require("semver");
5
- var jsh = require('jshint');
6
5
  var esl = require('eslint');
7
6
  var eslintLinter = new esl.Linter();
8
7
  function eslintrcToFlatConfig(rc) {
@@ -10,7 +9,7 @@ function eslintrcToFlatConfig(rc) {
10
9
  if (rc.rules) { flat.rules = rc.rules; }
11
10
  var sourceType = (rc.env && rc.env.node) ? 'commonjs' : 'script';
12
11
  flat.languageOptions = { ecmaVersion: 'latest', sourceType: sourceType };
13
- flat.linterOptions = { reportUnusedDisableDirectives: 'off' };
12
+ flat.linterOptions = { reportUnusedDisableDirectives: false };
14
13
  return flat;
15
14
  }
16
15
  var multilang = require('multilang');
@@ -18,6 +17,20 @@ var fs = require('fs-promise');
18
17
  var Path = require('path');
19
18
  var yaml = require('js-yaml');
20
19
 
20
+ /** @param {string} realRegex */
21
+ function softRegExp(realRegex) {
22
+ var re=realRegex.replace(/\\/g, '\\\\')
23
+ .replace(/\s*(=+)\s*/g,'\\s*$1\\s*')
24
+ .replace(/ /g, '\\s+')
25
+ .replace(/\(/g, '\\(')
26
+ .replace(/\)/g, '\\)');
27
+ return new RegExp(re, 'im');
28
+ }
29
+
30
+ /**
31
+ * @param {object} qaControl
32
+ * @returns {QADefinition}
33
+ */
21
34
  module.exports = function(qaControl){
22
35
  return {
23
36
  fileNameMainDoc: 'LEEME.md',
@@ -53,7 +66,6 @@ module.exports = function(qaControl){
53
66
  return !!packageJson['qa-control']["test-appveyor"];
54
67
  }
55
68
  },
56
- '.jshintrc':{ presentIf: function(pj) { return pj['qa-control'] && pj['qa-control'].profile !== 'minimum'; } },
57
69
  '.eslintrc.yml':{ presentIf: function(pj) { return pj['qa-control'] && pj['qa-control'].profile !== 'minimum'; } }
58
70
  },
59
71
  cucardas:{
@@ -119,7 +131,7 @@ module.exports = function(qaControl){
119
131
  check: function(packageJson){
120
132
  return !packageJson['qa-control']['test-appveyor'];
121
133
  },
122
- md:'[![build](https://github.com/xxx/yyy/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/workflows/node.js.yml)',
134
+ md:'[![build](https://github.com/xxx/yyy/actions/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/actions/workflows/node.js.yml)',
123
135
  imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
124
136
  docDescription: 'linux/build'
125
137
  },
@@ -127,7 +139,7 @@ module.exports = function(qaControl){
127
139
  check: function(packageJson){
128
140
  return !!packageJson['qa-control']['test-appveyor'];
129
141
  },
130
- md:'[![linux](https://github.com/xxx/yyy/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/workflows/node.js.yml)',
142
+ md:'[![linux](https://github.com/xxx/yyy/actions/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/actions/workflows/node.js.yml)',
131
143
  imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
132
144
  hideInManual: true,
133
145
  },
@@ -147,14 +159,6 @@ module.exports = function(qaControl){
147
159
  imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/coverage.png',
148
160
  docDescription: ''
149
161
  },
150
- climate:{
151
- check: function(packageJson){
152
- return packageJson['qa-control'].coverage || ! packageJson['qa-control'].purpose;
153
- },
154
- md:'[![climate](https://img.shields.io/codeclimate/github/xxx/yyy.svg)](https://codeclimate.com/github/xxx/yyy)',
155
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/climate.png',
156
- docDescription: ''
157
- },
158
162
  dependencies:{
159
163
  mandatory:true,
160
164
  md:'[![dependencies](https://snyk.io/test/github/xxx/yyy/badge.svg)](https://snyk.io/test/github/xxx/yyy)',
@@ -165,17 +169,15 @@ module.exports = function(qaControl){
165
169
  mandatory:false,
166
170
  md:'[![qa-control](http://codenautas.com/github/xxx/yyy.svg)](http://codenautas.com/github/xxx/yyy)',
167
171
  docDescription: ''
172
+ },
173
+ 'outdated-deps':{
174
+ forbidden:true
175
+ },
176
+ 'climate':{
177
+ forbidden:true
168
178
  }
169
179
  },
170
180
  customs:{
171
- softRegExp:function(realRegex) {
172
- var re=realRegex.replace(/\\/g, '\\\\')
173
- .replace(/\s*(=+)\s*/g,'\\s*$1\\s*')
174
- .replace(/ /g, '\\s+')
175
- .replace(/\(/g, '\\(')
176
- .replace(/\)/g, '\\)');
177
- return new RegExp(re, 'im');
178
- },
179
181
  funtion_eid:{
180
182
  detect:'function eid',
181
183
  match:'function eid(id){ return document.getElementById(id); }'
@@ -190,7 +192,6 @@ module.exports = function(qaControl){
190
192
  match:"var Path = require('path');"
191
193
  }
192
194
  },
193
- jshint_options: { "asi": false, "curly": true, "forin": true },
194
195
  eslint_options: {
195
196
  "env": {
196
197
  "node": false
@@ -353,9 +354,13 @@ module.exports = function(qaControl){
353
354
  /*jshint forin: false */
354
355
  for(var nombreCucarda in cucardas) {
355
356
  var cucarda = cucardas[nombreCucarda];
356
- var cucaID = '!['+/!\[([-a-z]+)]/.exec(cucarda.md)[1]+']';
357
- var cucaStr = cucarda.md.replace(/\bxxx\b/g,repo).replace(/\byyy\b/g,modulo);
358
- if(readme.indexOf(cucaID) === -1) {
357
+ var cucaID = cucarda.forbidden ? '!['+nombreCucarda+']' : '!['+/!\[([-a-z]+)]/.exec(cucarda.md)[1]+']';
358
+ var cucaStr = cucarda.md ? cucarda.md.replace(/\bxxx\b/g,repo).replace(/\byyy\b/g,modulo) : '';
359
+ if(cucarda.forbidden) {
360
+ if(readme.indexOf(cucaID) !== -1) {
361
+ warns.push({warning:'forbidden_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
362
+ }
363
+ } else if(readme.indexOf(cucaID) === -1) {
359
364
  if(cucarda.mandatory) {
360
365
  warns.push({warning:'lack_of_mandatory_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
361
366
  }
@@ -396,7 +401,7 @@ module.exports = function(qaControl){
396
401
  if(isMatchFunc) {
397
402
  return str.indexOf(strOrRegexp) !== -1;
398
403
  } else {
399
- return customs.softRegExp(strOrRegexp).test(str);
404
+ return softRegExp(strOrRegexp).test(str);
400
405
  }
401
406
  };
402
407
  }
@@ -481,35 +486,6 @@ module.exports = function(qaControl){
481
486
  }
482
487
  }]
483
488
  },
484
- jshint:{
485
- eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
486
- mandatory:false,
487
- checks:[{
488
- warnings:function(info){
489
- if(info.packageJson['qa-control'] && info.packageJson['qa-control'].profile === 'minimum') { return []; }
490
- var warns = [];
491
- var jshintOpts = JSON.parse(info.files['.jshintrc'].content);
492
- for(var file in info.files) {
493
- if(file.match(/(.js)$/)) {
494
- var content = info.files[file].content;
495
- jsh.JSHINT(content, jshintOpts , false);
496
- var data = jsh.JSHINT.data();
497
- if(data.errors) {
498
- if(qaControl.verbose){
499
- console.log('JSHINT output:');
500
- console.log('jshintOpts',jshintOpts);
501
- console.log('There are '+data.length+ " JSHINT errors");
502
- console.log(data.errors);
503
- //console.log(data);
504
- }
505
- warns.push({warning:'jshint_warnings_in_file_1', params:[file], scoring:{jshint:1}});
506
- }
507
- }
508
- }
509
- return warns;
510
- }
511
- }]
512
- },
513
489
  eslint:{
514
490
  eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
515
491
  checks:[{
@@ -520,7 +496,7 @@ module.exports = function(qaControl){
520
496
  for(var file in info.files) {
521
497
  if(file.match(/(.js)$/)) {
522
498
  var content = info.files[file].content;
523
- var data = eslintLinter.verify(content, eslintOpts);
499
+ var data = eslintLinter.verify(content || '', eslintOpts);
524
500
  if(data.length) {
525
501
  if(qaControl.verbose){
526
502
  console.log('ESLINT output:');
@@ -574,7 +550,8 @@ module.exports = function(qaControl){
574
550
  for(var file in info.files) {
575
551
  if(file.match(/(.js)$/)) {
576
552
  var content = info.files[file].content;
577
- var lines = info.files[file].content.split(/\r?\n/);
553
+ if(content === undefined) { continue; }
554
+ var lines = content.split(/\r?\n/);
578
555
  var prevLine = null;
579
556
  for(var l=0; l<lines.length; ++l) {
580
557
  var line = lines[l];
@@ -647,9 +624,6 @@ module.exports = function(qaControl){
647
624
  checks:[{
648
625
  warnings:function(info) {
649
626
  var warns = [];
650
- if('jshintConfig' in info.packageJson) {
651
- warns.push({warning:'unexpected_jshintconfig_section_in_package_json', scoring:{conventions:1}});
652
- }
653
627
  if('eslintConfig' in info.packageJson) {
654
628
  warns.push({warning:'unexpected_eslintconfig_section_in_package_json', scoring:{conventions:1}});
655
629
  }
@@ -661,12 +635,12 @@ module.exports = function(qaControl){
661
635
  checks:[{
662
636
  warnings:function(info) {
663
637
  var warns = [];
664
- var nonRecomended = ['best-promise', 'lodash', 'promise-plus'];
638
+ var nonRecomended = ['best-promise', 'eslint', 'lodash', 'promise-plus'];
665
639
  var dependencies = info.packageJson.dependencies;
666
640
  var devDependencies = info.packageJson.devDependencies;
667
641
  if(dependencies) {
668
642
  nonRecomended.forEach(function(badDep) {
669
- if(badDep in dependencies || badDep in devDependencies) {
643
+ if(badDep in (dependencies||{}) || (devDependencies && badDep in devDependencies)) {
670
644
  warns.push({warning:'non_recomended_dependency_1_in_package_json', params:[badDep], scoring:{dependencies:1}});
671
645
  }
672
646
  });
@@ -9,7 +9,7 @@ var fs = require('fs-promise');
9
9
  var path = require('path');
10
10
 
11
11
  program
12
- .version(require('../package').version)
12
+ .version(require('../package.json').version)
13
13
  .argument('[projectDirectory]', 'Project directory to check')
14
14
  .usage('[[options] projectDirectory|--list-langs]')
15
15
  .option('-l, --lang [lang]', 'Language to generate')
@@ -21,7 +21,7 @@ program
21
21
 
22
22
  var opts = program.opts();
23
23
 
24
- if( ( !opts.init && !opts.listLangs && (""==program.args && !opts.projectDir))
24
+ if( ( !opts.init && !opts.listLangs && (program.args.length===0 && !opts.projectDir))
25
25
  || (opts.lang && false === opts.lang in qaControl.msgs) )
26
26
  {
27
27
  program.help();
package/bin/qa-control.js CHANGED
@@ -41,16 +41,14 @@ qaControl.msgs={
41
41
  lack_of_cucarda_marker_in_readme:'falta la sección "cucardas" en README.md',
42
42
  lack_of_mandatory_cucarda_1: 'falta la cucarda oblicatoria $1',
43
43
  wrong_format_in_cucarda_1: 'la cucarda "$1" tiene formato incorrecto',
44
+ forbidden_cucarda_1: 'la cucarda "$1" no debe usarse en README.md',
44
45
  lack_of_mandatory_line_1_in_file_2: 'falta la linea obligatoria $1 en el archivo $2',
45
46
  file_1_does_not_match_custom_2: '$1 no respeta la custombre $2',
46
47
  first_lines_does_not_match_in_file_1: 'las primeras líneas no coinciden en $1',
47
48
  repository_name_not_found: 'packageJson.repository no tiene el formato /{[-a-zA-Z0-9_.]+}\/[-a-zA-Z0-9_.]+/',
48
49
  using_normal_promise_in_file_1: 'se han usado Promise(s) normales en "$1"',
49
50
  packagejson_main_file_1_does_not_exists: 'no existe el archivo "main" ($1) declarado en package.json',
50
- jshint_warnings_in_file_1: 'el archivo "$1" tiene warnings de JSHint',
51
51
  eslint_warnings_in_file_1: 'el archivo "$1" tiene warnings de ESLint',
52
- lack_of_jshintconfig_section_in_package_json: 'falta la sección "jshintConfig" en package.json',
53
- incorrect_jshintconfig_option_1_in_package_json: 'la opcion "$1" en "jshintConfig" es incorrecta en package.json',
54
52
  readme_multilang_not_sincronized_with_file_1: 'README.md no esta sincronizado con "$1" para multilang',
55
53
  lack_of_repository_section_in_package_json: 'Falta la sección "repository" en package.json',
56
54
  invalid_repository_section_in_package_json: 'La sección "repository" en package.json es inválida',
@@ -59,7 +57,6 @@ qaControl.msgs={
59
57
  lack_of_files_section_in_package_json: 'Falta la sección "files" en package.json',
60
58
  invalid_files_section_in_package_json: 'La sección "files" en package.json es inválida',
61
59
  incorrect_ecmascript_versions_in_package_json: 'Las versiones de ECMAScript utilizadas en package.json son incorrectas',
62
- unexpected_jshintconfig_section_in_package_json: 'No se esperaba la sección jshintConfig en package.json',
63
60
  non_recomended_dependency_1_in_package_json: 'Dependencia no recomendada "$1" en package.json'
64
61
  }
65
62
  };
@@ -120,6 +117,7 @@ qaControl.generateCucardas = function generateCucardas(cucardas, packageJson) {
120
117
  /*eslint-disable guard-for-in */
121
118
  for(var nombreCucarda in cucardas) {
122
119
  var cucarda = cucardas[nombreCucarda];
120
+ if(cucarda.forbidden) { continue; }
123
121
  if(!cucarda.check || cucarda.check(packageJson)) {
124
122
  var cucaStr = cucarda.md.replace(/\bxxx\b/g,repo).replace(/\byyy\b/g,modulo);
125
123
  cucaFileContent += cucaStr +'\n';
@@ -239,7 +237,7 @@ var configReading=(function(){
239
237
  });
240
238
 
241
239
  qaControl.loadProject = function loadProject(projectDir) {
242
- var info = {projectDir:projectDir};
240
+ var info = /** @type {ProjectInfo} */ ({projectDir:projectDir});
243
241
  var cmsgs = qaControl.cmdMsgs[qaControl.lang];
244
242
  if(qaControl.verbose) { process.stdout.write(cmsgs.msg_starting+projectDir+"'...\n"); }
245
243
  return Promise.resolve().then(function(){
@@ -266,7 +264,7 @@ qaControl.loadProject = function loadProject(projectDir) {
266
264
  /*jshint forin: true */
267
265
  /*eslint-enable guard-for-in */
268
266
  if(files.indexOf('package.json') !== -1) {
269
- info.packageJson = {};
267
+ info.packageJson = /** @type {PackageJson} */ ({});
270
268
  }
271
269
  return Promise.all(files.map(function(file){
272
270
  var iFile = Path.normalize(projectDir+'/'+file);
@@ -318,7 +316,7 @@ qaControl.controlInfo=function controlInfo(info, opts){
318
316
  var cmsgs = qaControl.cmdMsgs[qaControl.lang];
319
317
  var rules = qaControl.definition.rules;
320
318
  var silenced = ((info.packageJson || {})['qa-control'] || {}).silenced || [];
321
- var cadenaDePromesas = Promise.resolve().then();
319
+ var cadenaDePromesas = Promise.resolve(/** @type {Warning[]} */ ([]));
322
320
  info.scoring = opts && opts.scoring;
323
321
  forEach(rules, function(rule, ruleName) {
324
322
  rule.checks.forEach(function(checkInfo){
@@ -364,7 +362,7 @@ qaControl.stringizeWarnings = function stringizeWarnings(warns, lang) {
364
362
  if(numParams) {
365
363
  //console.log(warn.warning, msg, " tiene ", numParams.length, " parametros y params tiene ", warn.params)
366
364
  for(var p=0; p<numParams.length; ++p) {
367
- msg = msg.replace('$'+parseInt(p+1,10), warn.params[p]);
365
+ msg = msg.replace('$'+(p+1), warn.params[p]);
368
366
  }
369
367
  }
370
368
  if(qaControl.verbose) {
package/bin/qac-init.js CHANGED
@@ -102,7 +102,7 @@ qacInit.ask = function ask(param, msgs, callback) {
102
102
  stdin.resume();
103
103
  var prompt = param.prompt || param.name.substring(0,1).toUpperCase()+param.name.substring(1);
104
104
  stdout.write(prompt+def+ ": ");
105
- stdin.once('data', function(data) {
105
+ stdin.once('data', function(/** @type {any} */ data) {
106
106
  data = data.toString().trim();
107
107
  if(data === '') { data = param.def; }
108
108
  if((param.valid && param.valid(data)) || (! param.valid && data !== '')) {
@@ -254,7 +254,7 @@ qacInit.configParams = [
254
254
  },
255
255
  post: function(ctx) {
256
256
  var contributors = ctx.input.existingJson.contributors || [];
257
- var nae = this.parseNE(ctx.result[this.name]);
257
+ var nae = /** @type {{name: string, email: string}} */ (this.parseNE(ctx.result[this.name]));
258
258
  contributors.push({'name':nae.name, 'email':nae.email});
259
259
  return contributors.length ? contributors : null;
260
260
  },
@@ -293,8 +293,8 @@ qacInit.init = function init(initParams) {
293
293
  var inputParams;
294
294
  var tplData = {
295
295
  vars: {},
296
- tpls: [],
297
- other: []
296
+ tpls: /** @type {string[]} */ ([]),
297
+ other: /** @type {string[]} */ ([])
298
298
  };
299
299
  var packageJS;
300
300
  return qacInit.initDefaults(initParams).then(function(initResult) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "qa-control",
3
3
  "description": "QA control of things that nobody controls",
4
- "version": "0.6.0",
4
+ "version": "0.6.2",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/qa-control",
@@ -19,25 +19,31 @@
19
19
  "qa-control": "./bin/qa-control-run.js"
20
20
  },
21
21
  "main": "./bin/qa-control.js",
22
+ "overrides": {
23
+ "diff": ">=8.0.2",
24
+ "serialize-javascript": ">=7.0.0",
25
+ "uuid": ">=14.0.0"
26
+ },
22
27
  "dependencies": {
23
- "commander": "~14.0.3",
24
- "eslint": "~10.3.0",
25
- "fs-extra": "~11.3.5",
26
- "fs-promise": "~2.0.3",
27
- "js-yaml": "~4.1.1",
28
- "jshint": "~2.13.6",
29
- "parameters": "~0.8.1",
30
- "semver": "~7.8.0",
31
- "strip-bom-string": "~1.0.0",
32
- "best-globals": "~2.1.3",
33
- "multilang": "~1.2.0"
28
+ "best-globals": "^2.1.4",
29
+ "commander": "^14.0.3",
30
+ "eslint": "^10.3.0",
31
+ "fs-extra": "^11.3.5",
32
+ "fs-promise": "^2.0.3",
33
+ "js-yaml": "^4.1.1",
34
+ "multilang": "^1.2.1",
35
+ "semver": "^7.8.0",
36
+ "strip-bom-string": "^1.0.0"
34
37
  },
35
38
  "devDependencies": {
36
- "expect.js": "~0.3.1",
37
- "istanbul": "~0.4.5",
38
- "mocha": "~11.7.5",
39
- "sinon": "~22.0.0",
40
- "expect-called": "~0.4.0"
39
+ "@types/mocha": "^10.0.10",
40
+ "@types/node": "^25.7.0",
41
+ "expect-called": "^0.4.0",
42
+ "expect.js": "^0.3.1",
43
+ "mocha": "^11.7.5",
44
+ "nyc": "^18.0.0",
45
+ "sinon": "^22.0.0",
46
+ "typescript": "^6.0.3"
41
47
  },
42
48
  "engines": {
43
49
  "node": ">= 10"
@@ -45,11 +51,12 @@
45
51
  "scripts": {
46
52
  "test": "mocha --reporter spec --bail --check-leaks test/",
47
53
  "test-nc": "mocha --reporter spec --bail --check-leaks --no-colors test/",
48
- "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
49
- "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
54
+ "test-ci": "nyc --reporter=lcov mocha --reporter spec --check-leaks test/",
55
+ "test-cov": "nyc mocha --reporter dot --check-leaks test/",
50
56
  "start": "node example/server.js",
51
- "report": "istanbul report",
57
+ "report": "nyc report",
52
58
  "qac": "node bin/qa-control-run.js . -v",
59
+ "typecheck": "tsc",
53
60
  "all": "npm test && npm run test-cov && npm run report && npm run qac"
54
61
  },
55
62
  "files": [