first-base 1.4.0 → 1.5.0

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/.node-version ADDED
@@ -0,0 +1 @@
1
+ v20.11.1
package/.npm-version ADDED
@@ -0,0 +1 @@
1
+ 10.2.4
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
4
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
5
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
6
+ var fs = require("fs");
7
+ var _require = require("nice-path"),
8
+ Path = _require.Path;
9
+ var strongRootDirIndicators = [".git", ".hg"];
10
+ var weakRootDirIndicators = ["package-lock.json", ".gitignore", ".hgignore"];
11
+ var veryWeakRootDirIndicators = ["package.json", "README.md"];
12
+ function hasFile(dir, filename) {
13
+ var fullPath = dir.concat(filename).toString();
14
+ console.log("checking for ".concat(fullPath));
15
+ try {
16
+ return fs.existsSync(fullPath);
17
+ } catch (err) {
18
+ return false;
19
+ }
20
+ }
21
+ function findRootDir(startingDir) {
22
+ var start = new Path(startingDir).normalize();
23
+ var searchDirs = [start];
24
+ var currentPath = start.replaceLast([]);
25
+ while (currentPath.segments.length > 0) {
26
+ searchDirs.push(currentPath);
27
+ currentPath = currentPath.replaceLast([]);
28
+ }
29
+ for (var _i = 0, _searchDirs = searchDirs; _i < _searchDirs.length; _i++) {
30
+ var dir = _searchDirs[_i];
31
+ var _iterator = _createForOfIteratorHelper(strongRootDirIndicators),
32
+ _step;
33
+ try {
34
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
35
+ var indicator = _step.value;
36
+ if (hasFile(dir, indicator)) {
37
+ return dir.toString();
38
+ }
39
+ }
40
+ } catch (err) {
41
+ _iterator.e(err);
42
+ } finally {
43
+ _iterator.f();
44
+ }
45
+ }
46
+ for (var _i2 = 0, _searchDirs2 = searchDirs; _i2 < _searchDirs2.length; _i2++) {
47
+ var _dir = _searchDirs2[_i2];
48
+ var _iterator2 = _createForOfIteratorHelper(weakRootDirIndicators),
49
+ _step2;
50
+ try {
51
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
52
+ var _indicator = _step2.value;
53
+ if (hasFile(_dir, _indicator)) {
54
+ return _dir.toString();
55
+ }
56
+ }
57
+ } catch (err) {
58
+ _iterator2.e(err);
59
+ } finally {
60
+ _iterator2.f();
61
+ }
62
+ }
63
+ for (var _i3 = 0, _searchDirs3 = searchDirs; _i3 < _searchDirs3.length; _i3++) {
64
+ var _dir2 = _searchDirs3[_i3];
65
+ var _iterator3 = _createForOfIteratorHelper(veryWeakRootDirIndicators),
66
+ _step3;
67
+ try {
68
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
69
+ var _indicator2 = _step3.value;
70
+ if (hasFile(_dir2, _indicator2)) {
71
+ return _dir2.toString();
72
+ }
73
+ }
74
+ } catch (err) {
75
+ _iterator3.e(err);
76
+ } finally {
77
+ _iterator3.f();
78
+ }
79
+ }
80
+ return start.toString();
81
+ }
82
+ module.exports = {
83
+ findRootDir: findRootDir
84
+ };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,16 @@ export type RunContext = {
18
18
  code: null | number;
19
19
  error: boolean;
20
20
  };
21
+ /**
22
+ * Same as {@link RunContext.result}, but with {@link sanitizers} run on
23
+ * stdout/stderr.
24
+ */
25
+ cleanResult(): {
26
+ stdout: string;
27
+ stderr: string;
28
+ code: null | number;
29
+ error: boolean;
30
+ };
21
31
  completion: Promise<void>;
22
32
  debug(): RunContext;
23
33
  outputContains(value: string | RegExp): Promise<void>;
@@ -32,3 +42,25 @@ export const spawn: ((cmd: string) => RunContext) &
32
42
  ((cmd: string, args: Array<string>) => RunContext) &
33
43
  ((cmd: string, options: Options) => RunContext) &
34
44
  ((cmd: string, args: Array<string>, options: Options) => RunContext);
45
+
46
+ /**
47
+ * An array of functions that will be run on stdout/stderr when calling
48
+ * {@link RunContext.cleanResult}.
49
+ *
50
+ * By default, it contains 5 functions, which are run in order:
51
+ *
52
+ * - `stripAnsi`: Removes ANSI control characters
53
+ * - `replaceRootDir`: Replaces eg `/home/suchipi/Code/first-base/src/index.js` with `<rootDir>/src/index.js`
54
+ * - This function searches upwards for the root dir using a heuristic, and caches results in the {@link Map} `replaceRootDir.cache`.
55
+ * - The heuristic is:
56
+ * - Look upwards for a folder containing `.git` or `.hg`
57
+ * - if none is found, look upwards for a folder containing `package-lock.json`, `.gitignore` or `.hgignore`,
58
+ * - if none is found, look upwards for a folder containing `package.json` or `README.md`
59
+ * - if none is found, consider the present working directory to be the root dir.
60
+ * - `replaceCwd`: Replaces the current working directory with `<cwd>`
61
+ * - `collapseStackTrace`: For Node.JS-style stack traces, replaces the long chain of "at ..." lines with a single "at somewhere" line
62
+ * - `omitThrowLineNumber`: For Node.JS error source display, removes the line number
63
+ *
64
+ * You can remove them or replace them or add to them by mutating the `sanitizers` Array.
65
+ */
66
+ export const sanitizers: Array<(str: string) => string>;
package/dist/index.js CHANGED
@@ -4,6 +4,8 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
4
4
  var normalSpawn = require("child_process").spawn;
5
5
  var ptySpawn = require("node-pty").spawn;
6
6
  var stripAnsi = require("strip-ansi");
7
+ var _require = require("./sanitizers"),
8
+ sanitizers = _require.sanitizers;
7
9
 
8
10
  // Run a child process and return a "run context" object
9
11
  // to interact with it. Function signature is the same as
@@ -51,6 +53,17 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
51
53
  // true if the process errored out
52
54
  error: false
53
55
  },
56
+ // Return a version of result which has had the string sanitizers run on it
57
+ cleanResult: function cleanResult() {
58
+ return Object.assign({}, runContext.result, {
59
+ stdout: sanitizers.reduce(function (str, transformFn) {
60
+ return transformFn(str);
61
+ }, runContext.result.stdout),
62
+ stderr: sanitizers.reduce(function (str, transformFn) {
63
+ return transformFn(str);
64
+ }, runContext.result.stderr)
65
+ });
66
+ },
54
67
  // Promise that gets resolved when the child process completes.
55
68
  completion: null,
56
69
  debug: function debug() {
@@ -195,5 +208,6 @@ var spawn = function spawn(cmd, argsOrOptions, passedOptions) {
195
208
  return runContext;
196
209
  };
197
210
  module.exports = {
198
- spawn: spawn
211
+ spawn: spawn,
212
+ sanitizers: sanitizers
199
213
  };
@@ -33,6 +33,8 @@ interface Exports {
33
33
  spawn(cmd: string, args: Array<string>): RunContext;
34
34
  spawn(cmd: string, options: Options): RunContext;
35
35
  spawn(cmd: string, args: Array<string>, options: Options): RunContext;
36
+
37
+ sanitizers: Array<(str: string) => string>;
36
38
  }
37
39
 
38
40
  declare module.exports: Exports;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ var stripAnsi = require("strip-ansi");
4
+ var _require = require("./find-root-dir"),
5
+ findRootDir = _require.findRootDir;
6
+ function escapeRegex(str) {
7
+ return str.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&");
8
+ }
9
+ var sanitizers = [stripAnsi, Object.assign(function replaceRootDir(str) {
10
+ var here = process.cwd();
11
+ var rootDir = replaceRootDir.cache.get(here) || findRootDir(here);
12
+ replaceRootDir.cache.set(here, rootDir);
13
+ return str.replace(new RegExp(escapeRegex(rootDir), "g"), "<rootDir>");
14
+ }, {
15
+ cache: new Map()
16
+ }), function replaceCwd(str) {
17
+ return str.replace(new RegExp(escapeRegex(process.cwd()), "g"), "<cwd>");
18
+ }, function collapseStackTrace(str) {
19
+ return str
20
+ // replace stack trace lines with a single "at somewhere" line
21
+ // explanation of regexp:
22
+ // newline, optional ansi escape, zero or more whitespace(s), "at",
23
+ // whitespace(s), several non-newline characters... and that whole
24
+ // thing can happen more than once
25
+ .replaceAll(/(?:\n(?:\x1B\[\d+m)?(\s*)at\s+[^\n]+)+/g, "\n$1at somewhere");
26
+ }, function omitThrowLineNumber(str) {
27
+ // omit line number from eg. "<rootDir>/dist/match.js:57\n\t\t\t\tthrow"
28
+ return str.replaceAll(/(\.js):\d+(\s+throw)/g, "$1$2");
29
+ }];
30
+ module.exports = {
31
+ sanitizers: sanitizers
32
+ };
package/package.json CHANGED
@@ -1,14 +1,18 @@
1
1
  {
2
2
  "name": "first-base",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Integration testing for CLI applications",
5
5
  "main": "dist/index.js",
6
- "repository": "https://github.com/suchipi/first-base",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/suchipi/first-base.git"
9
+ },
7
10
  "author": "Lily Skye <me@suchipi.com>",
8
11
  "license": "MIT",
9
12
  "dependencies": {
10
13
  "node-pty": "^1.0.0",
11
- "strip-ansi": "^5.0.0"
14
+ "strip-ansi": "^5.0.0",
15
+ "nice-path": "^2.0.0"
12
16
  },
13
17
  "devDependencies": {
14
18
  "@babel/cli": "^7.23.4",
@@ -23,7 +27,10 @@
23
27
  "prettier": "^3.2.4"
24
28
  },
25
29
  "scripts": {
26
- "build": "mkdir -p dist; rm -rf dist/*; babel src/index.js --out-dir dist && cp src/index.js.flow dist/ && cp src/index.d.ts dist/",
30
+ "build": "mkdir -p dist; rm -rf dist/*; babel src --out-dir dist && cp src/index.js.flow dist/ && cp src/index.d.ts dist/",
27
31
  "test": "jest"
32
+ },
33
+ "jest": {
34
+ "prettierPath": null
28
35
  }
29
36
  }
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- *.flow