@appium/docutils 1.0.34 → 1.1.1

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/lib/validate.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import {fs, util} from '@appium/support';
7
+ import {fs, npm, util} from '@appium/support';
8
8
  import chalk from 'chalk';
9
9
  import _ from 'lodash';
10
10
  import {EventEmitter} from 'node:events';
@@ -13,6 +13,7 @@ import {satisfies} from 'semver';
13
13
  import {exec} from 'teen_process';
14
14
  import {
15
15
  DOCUTILS_PKG,
16
+ MESSAGE_PYTHON_MISSING,
16
17
  NAME_BIN,
17
18
  NAME_ERR_ENOENT,
18
19
  NAME_MKDOCS,
@@ -27,7 +28,15 @@ import {
27
28
  REQUIREMENTS_TXT_PATH,
28
29
  } from './constants';
29
30
  import {DocutilsError} from './error';
30
- import {findMkDocsYml, findPkgDir, readJson5, readMkDocsYml, whichNpm, findPython} from './fs';
31
+ import {
32
+ findMkDocsYml,
33
+ findPkgDir,
34
+ isMkDocsInstalled,
35
+ readJson5,
36
+ readMkDocsYml,
37
+ whichNpm,
38
+ findPython,
39
+ } from './fs';
31
40
  import {getLogger} from './logger';
32
41
  import {MkDocsYml, PipPackage} from './model';
33
42
  import {relative} from './util';
@@ -70,7 +79,7 @@ export type ValidationKind =
70
79
  export class DocutilsValidator extends EventEmitter {
71
80
  /**
72
81
  * Current working directory. Defaults to `process.cwd()`
73
- * @todo This cannot yet be overriden by user
82
+ * @todo This cannot yet be overridden by user
74
83
  */
75
84
  protected readonly cwd: string;
76
85
 
@@ -281,12 +290,16 @@ export class DocutilsValidator extends EventEmitter {
281
290
  * Validates that the correct version of `mkdocs` is installed
282
291
  */
283
292
  protected async validateMkDocs() {
284
- const pythonPath = this.pythonPath ?? (await findPython());
293
+ log.debug(`Validating MkDocs version`);
285
294
 
295
+ const pythonPath = this.pythonPath ?? (await findPython());
286
296
  if (!pythonPath) {
287
- return this.fail(
288
- `Could not find ${NAME_PYTHON} executable in PATH. If it is installed, check your PATH environment variable.`,
289
- );
297
+ return this.fail(MESSAGE_PYTHON_MISSING);
298
+ }
299
+
300
+ const mkdocsInstalled = await isMkDocsInstalled();
301
+ if (!mkdocsInstalled) {
302
+ return this.fail(`Could not find MkDocs executable; please run "${NAME_BIN} init"`);
290
303
  }
291
304
 
292
305
  let rawMkDocsVersion: string | undefined;
@@ -296,26 +309,21 @@ export class DocutilsValidator extends EventEmitter {
296
309
  return this.fail(`Failed to get MkDocs version: ${err}`);
297
310
  }
298
311
  const match = rawMkDocsVersion.match(MKDOCS_VERSION_REGEX);
299
- if (match) {
300
- const version = match[1];
301
- const reqs = await this.parseRequirementsTxt();
302
- const mkDocsPipPkg = _.find(reqs, {name: NAME_MKDOCS});
303
- if (!mkDocsPipPkg) {
304
- throw new DocutilsError(
305
- `No ${NAME_MKDOCS} package in ${REQUIREMENTS_TXT_PATH}. This is a bug.`,
306
- );
307
- }
308
- const {version: mkDocsReqdVersion} = mkDocsPipPkg;
309
- if (version !== mkDocsReqdVersion) {
310
- return this.fail(
311
- `${NAME_MKDOCS} is v${version}, but ${REQUIREMENTS_TXT_PATH} requires v${mkDocsReqdVersion}`,
312
- );
313
- }
314
- } else {
312
+ if (!match) {
313
+ return this.fail(`Could not parse MkDocs version. Output was ${rawMkDocsVersion}`);
314
+ }
315
+ const version = match[1];
316
+ const reqs = await this.parseRequirementsTxt();
317
+ const mkDocsPipPkg = _.find(reqs, {name: NAME_MKDOCS});
318
+ if (!mkDocsPipPkg) {
315
319
  throw new DocutilsError(
316
- `Could not parse version from MkDocs. This is a bug. Output was ${rawMkDocsVersion}`,
320
+ `No ${NAME_MKDOCS} package in ${REQUIREMENTS_TXT_PATH}. This is a bug`,
317
321
  );
318
322
  }
323
+ const {version: mkDocsReqdVersion} = mkDocsPipPkg;
324
+ if (version !== mkDocsReqdVersion) {
325
+ return this.fail(`MkDocs v${version} is installed, but v${mkDocsReqdVersion} is required`);
326
+ }
319
327
 
320
328
  this.ok('MkDocs install OK');
321
329
  }
@@ -325,13 +333,16 @@ export class DocutilsValidator extends EventEmitter {
325
333
  *
326
334
  * It checks if the file exists, if it can be parsed as YAML, and if it has a `site_name` property.
327
335
  */
328
- protected async validateMkDocsConfig(mkDocsYmlPath?: string) {
329
- mkDocsYmlPath = mkDocsYmlPath ?? this.mkDocsYmlPath ?? (await findMkDocsYml(this.cwd));
336
+ protected async validateMkDocsConfig() {
337
+ log.debug(`Validating ${NAME_MKDOCS_YML}`);
338
+
339
+ const mkDocsYmlPath = this.mkDocsYmlPath ?? (await findMkDocsYml(this.cwd));
330
340
  if (!mkDocsYmlPath) {
331
341
  return this.fail(
332
- `Could not find ${NAME_MKDOCS_YML} from ${this.cwd}. Run "${NAME_BIN} init" to create it`,
342
+ `Could not find ${NAME_MKDOCS_YML} from ${this.cwd}; please run "${NAME_BIN} init"`,
333
343
  );
334
344
  }
345
+
335
346
  let mkDocsYml: MkDocsYml;
336
347
  try {
337
348
  mkDocsYml = await readMkDocsYml(mkDocsYmlPath);
@@ -358,24 +369,25 @@ export class DocutilsValidator extends EventEmitter {
358
369
  * This is required because other validators need `npm exec` to work, which is only available in npm 7+.
359
370
  */
360
371
  protected async validateNpmVersion() {
372
+ log.debug(`Validating ${NAME_NPM} version`);
373
+
361
374
  const npmEngineRange = DOCUTILS_PKG.engines?.npm;
362
375
  if (!npmEngineRange) {
363
- throw new DocutilsError('Could not find property engines.npm in package.json. This is a bug');
376
+ throw new DocutilsError(`Could not find property 'engines.npm' in ${NAME_PACKAGE_JSON}. This is a bug`);
377
+ }
378
+
379
+ const npmPath = this.npmPath ?? (await whichNpm());
380
+ if (!npmPath) {
381
+ throw new DocutilsError(`Could not find ${NAME_NPM} in PATH. That seems weird, doesn't it?`);
364
382
  }
383
+
365
384
  try {
366
- const npmPath = this.npmPath ?? (await whichNpm());
367
- if (!npmPath) {
368
- throw new DocutilsError(
369
- `Could not find ${NAME_NPM} in PATH. That seems weird, doesn't it?`,
370
- );
371
- }
372
- const {stdout: npmVersion} = await exec(npmPath, ['-v']);
385
+ const {stdout: npmVersion} = await npm.exec('-v', [], {cwd: this.cwd});
373
386
  if (!satisfies(npmVersion.trim(), npmEngineRange)) {
374
- this.fail(`${NAME_NPM} is version ${npmVersion}, but ${npmEngineRange} is required`);
375
- return;
387
+ return this.fail(`${NAME_NPM} v${npmVersion} is installed, but ${npmEngineRange} is required`);
376
388
  }
377
389
  } catch {
378
- return this.fail(`Could not find ${this.npmPath} in PATH. Is it installed?`);
390
+ return this.fail(`Could not retrieve ${NAME_NPM} version`);
379
391
  }
380
392
  this.ok(`${NAME_NPM} version OK`);
381
393
  }
@@ -387,11 +399,14 @@ export class DocutilsValidator extends EventEmitter {
387
399
  * contents of our `requirements.txt`. Versions _must_ match exactly.
388
400
  */
389
401
  protected async validatePythonDeps() {
390
- let pipListOutput: string;
402
+ log.debug(`Validating required ${NAME_PYTHON} package versions`);
403
+
391
404
  const pythonPath = this.pythonPath ?? (await findPython());
392
405
  if (!pythonPath) {
393
- return this.fail(`Could not find ${NAME_PYTHON} in PATH. Is it installed?`);
406
+ return this.fail(MESSAGE_PYTHON_MISSING);
394
407
  }
408
+
409
+ let pipListOutput: string;
395
410
  try {
396
411
  ({stdout: pipListOutput} = await exec(pythonPath, [
397
412
  '-m',
@@ -401,16 +416,16 @@ export class DocutilsValidator extends EventEmitter {
401
416
  'json',
402
417
  ]));
403
418
  } catch {
404
- return this.fail(`Could not find ${NAME_PIP} in PATH. Is it installed?`);
419
+ return this.fail(
420
+ `Could not find ${NAME_PIP} installation for Python at ${pythonPath}. Is it installed?`
421
+ );
405
422
  }
406
423
 
407
424
  let installedPkgs: PipPackage[];
408
425
  try {
409
426
  installedPkgs = JSON.parse(pipListOutput) as PipPackage[];
410
427
  } catch {
411
- throw new DocutilsError(
412
- `Could not parse output of "${NAME_PIP} list" as JSON: ${pipListOutput}`,
413
- );
428
+ return this.fail(`Could not parse output of "${NAME_PIP} list" as JSON: ${pipListOutput}`);
414
429
  }
415
430
 
416
431
  const pkgsByName = _.mapValues(_.keyBy(installedPkgs, 'name'), 'version');
@@ -423,8 +438,7 @@ export class DocutilsValidator extends EventEmitter {
423
438
  const version = pkgsByName[reqdPkg.name];
424
439
  if (!version) {
425
440
  missingPackages.push(reqdPkg);
426
- }
427
- if (version !== reqdPkg.version) {
441
+ } else if (version !== reqdPkg.version) {
428
442
  invalidVersionPackages.push([reqdPkg, {name: reqdPkg.name, version}]);
429
443
  }
430
444
  }
@@ -464,36 +478,44 @@ export class DocutilsValidator extends EventEmitter {
464
478
  * Asserts that the Python version is 3.x
465
479
  */
466
480
  protected async validatePythonVersion() {
481
+ log.debug(`Validating ${NAME_PYTHON} version`);
482
+
467
483
  const pythonPath = this.pythonPath ?? (await findPython());
468
484
  if (!pythonPath) {
469
- return this.fail(`Could not find ${NAME_PYTHON} in PATH. Is it installed?`);
485
+ return this.fail(MESSAGE_PYTHON_MISSING);
470
486
  }
471
487
 
472
488
  try {
473
489
  const {stdout} = await exec(pythonPath, ['--version']);
474
490
  if (!stdout.includes(PYTHON_VER_STR)) {
475
- return this.fail(
476
- `Could not find Python 3.x in PATH; found ${stdout}. Please use --python-path`,
477
- );
491
+ return this.fail(`Could not find Python 3.x in PATH; found ${stdout}`);
478
492
  }
479
493
  } catch {
480
- return this.fail(`Could not find Python 3.x in PATH.`);
494
+ return this.fail(`Could not retrieve Python version`);
481
495
  }
482
496
  this.ok('Python version OK');
483
497
  }
484
498
 
485
499
  /**
486
- * Asserts that TypeScript is installed, runnable, the correct version, and a parseable `tsconfig.json` exists.
500
+ * Asserts that TypeScript is installed, runnable, and the correct version.
487
501
  */
488
502
  protected async validateTypeScript() {
503
+ log.debug(`Validating ${NAME_TYPESCRIPT} version`);
504
+
489
505
  const pkgDir = await this.findPkgDir();
490
506
  if (!pkgDir) {
491
- return this.fail(`Could not find package.json in ${this.cwd}`);
507
+ return this.fail(`Could not find ${NAME_PACKAGE_JSON} in ${this.cwd}`);
492
508
  }
509
+
510
+ const npmPath = this.npmPath ?? (await whichNpm());
511
+ if (!npmPath) {
512
+ throw new DocutilsError(`Could not find ${NAME_NPM} in PATH. That seems weird, doesn't it?`);
513
+ }
514
+
493
515
  let typeScriptVersion: string;
494
516
  let rawTypeScriptVersion: string;
495
517
  try {
496
- ({stdout: rawTypeScriptVersion} = await exec(NAME_NPM, ['exec', 'tsc', '--', '--version'], {
518
+ ({stdout: rawTypeScriptVersion} = await npm.exec('exec', ['tsc', '--', '--version'], {
497
519
  cwd: pkgDir,
498
520
  }));
499
521
  } catch {
@@ -510,16 +532,15 @@ export class DocutilsValidator extends EventEmitter {
510
532
  }
511
533
 
512
534
  const reqdTypeScriptVersion = DOCUTILS_PKG.dependencies?.typescript;
513
-
514
535
  if (!reqdTypeScriptVersion) {
515
536
  throw new DocutilsError(
516
- `Could not find a dep for ${NAME_TYPESCRIPT} in ${NAME_PACKAGE_JSON}. This is a bug.`,
537
+ `Could not find ${NAME_TYPESCRIPT} dependency in ${NAME_PACKAGE_JSON}. This is a bug`,
517
538
  );
518
539
  }
519
540
 
520
541
  if (!satisfies(typeScriptVersion, reqdTypeScriptVersion)) {
521
542
  return this.fail(
522
- `Found TypeScript version ${typeScriptVersion}, but ${reqdTypeScriptVersion} is required`,
543
+ `TypeScript v${typeScriptVersion} is installed, but v${reqdTypeScriptVersion} is required`,
523
544
  );
524
545
  }
525
546
  this.ok('TypeScript install OK');
@@ -529,25 +550,23 @@ export class DocutilsValidator extends EventEmitter {
529
550
  * Validates a `tsconfig.json` file
530
551
  */
531
552
  protected async validateTypeScriptConfig() {
553
+ log.debug(`Validating ${NAME_TSCONFIG_JSON}`);
554
+
532
555
  const pkgDir = await this.findPkgDir();
533
556
  if (!pkgDir) {
534
- return this.fail(new DocutilsError(`Could not find package.json in ${this.cwd}`));
557
+ return this.fail(`Could not find ${NAME_PACKAGE_JSON} in ${this.cwd}`);
535
558
  }
536
- const tsconfigJsonPath = (this.tsconfigJsonPath =
537
- this.tsconfigJsonPath ?? path.join(pkgDir, NAME_TSCONFIG_JSON));
559
+
560
+ const tsconfigJsonPath = this.tsconfigJsonPath ?? path.join(pkgDir, NAME_TSCONFIG_JSON);
538
561
  const relTsconfigJsonPath = relative(this.cwd, tsconfigJsonPath);
539
562
  try {
540
563
  await readJson5(tsconfigJsonPath);
541
564
  } catch (e) {
542
565
  if (e instanceof SyntaxError) {
543
- return this.fail(
544
- new DocutilsError(`Unparseable ${NAME_TSCONFIG_JSON} at ${relTsconfigJsonPath}: ${e}`),
545
- );
566
+ return this.fail(`Could not parse ${NAME_TSCONFIG_JSON} at ${relTsconfigJsonPath}: ${e}`);
546
567
  }
547
568
  return this.fail(
548
- new DocutilsError(
549
- `Missing ${NAME_TSCONFIG_JSON} at ${relTsconfigJsonPath}; "${NAME_BIN} init" can help`,
550
- ),
569
+ `Could not find ${NAME_TSCONFIG_JSON} at ${relTsconfigJsonPath}; please run "${NAME_BIN} init"`,
551
570
  );
552
571
  }
553
572
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appium/docutils",
3
- "version": "1.0.34",
3
+ "version": "1.1.1",
4
4
  "description": "Documentation generation utilities for Appium and related projects",
5
5
  "keywords": [
6
6
  "automation",
@@ -48,23 +48,23 @@
48
48
  "start": "node ./build/lib/cli/index.js"
49
49
  },
50
50
  "dependencies": {
51
- "@appium/support": "^6.0.8",
51
+ "@appium/support": "^6.1.1",
52
52
  "@appium/tsconfig": "^0.3.5",
53
53
  "@sliphua/lilconfig-ts-loader": "3.2.2",
54
54
  "chalk": "4.1.2",
55
- "consola": "3.4.0",
56
- "diff": "7.0.0",
55
+ "consola": "3.4.2",
56
+ "diff": "8.0.2",
57
57
  "json5": "2.2.3",
58
58
  "lilconfig": "3.1.3",
59
59
  "lodash": "4.17.21",
60
60
  "pkg-dir": "5.0.0",
61
61
  "read-pkg": "5.2.0",
62
- "semver": "7.7.1",
62
+ "semver": "7.7.2",
63
63
  "source-map-support": "0.5.21",
64
- "teen_process": "2.3.1",
65
- "type-fest": "4.37.0",
66
- "typescript": "5.8.2",
67
- "yaml": "2.7.0",
64
+ "teen_process": "2.3.2",
65
+ "type-fest": "4.41.0",
66
+ "typescript": "5.8.3",
67
+ "yaml": "2.8.0",
68
68
  "yargs": "17.7.2",
69
69
  "yargs-parser": "21.1.1"
70
70
  },
@@ -75,5 +75,5 @@
75
75
  "publishConfig": {
76
76
  "access": "public"
77
77
  },
78
- "gitHead": "603d1e7fb268342df1d7c12502210ab3c2f380f1"
78
+ "gitHead": "c8fe4412525f7e1fa237813cf83fe7d98f0125eb"
79
79
  }
package/requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  mkdocs==1.6.1
2
- mkdocs-git-revision-date-localized-plugin==1.4.5
3
- mkdocs-material==9.6.9
2
+ mkdocs-git-revision-date-localized-plugin==1.4.7
3
+ mkdocs-material==9.6.14
4
4
  mkdocs-redirects==1.2.2
5
5
  mike==2.1.3