@serenity-js/core 3.19.0 → 3.20.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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.20.0](https://github.com/serenity-js/serenity-js/compare/v3.19.0...v3.20.0) (2024-03-02)
7
+
8
+
9
+ ### Features
10
+
11
+ * **core:** simplified reading and writing files in CrewMembers using the FileSystem ([7f0d0cc](https://github.com/serenity-js/serenity-js/commit/7f0d0cc6de675a526a6e9351fe94055501d87e2c)), closes [#2244](https://github.com/serenity-js/serenity-js/issues/2244)
12
+
13
+
14
+
15
+
16
+
6
17
  # [3.19.0](https://github.com/serenity-js/serenity-js/compare/v3.18.1...v3.19.0) (2024-03-01)
7
18
 
8
19
  **Note:** Version bump only for package @serenity-js/core
@@ -1,26 +1,43 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
3
  /// <reference types="node" />
4
- import type * as nodeFS from 'fs';
5
- import type { WriteFileOptions } from 'fs';
6
- import * as nodeOS from 'os';
4
+ /// <reference types="node" />
5
+ import * as nodeOS from 'node:os';
6
+ import type * as NodeFS from 'fs';
7
7
  import { Path } from './Path';
8
8
  export declare class FileSystem {
9
9
  private readonly root;
10
10
  private readonly fs;
11
11
  private readonly os;
12
12
  private readonly directoryMode;
13
- constructor(root: Path, fs?: typeof nodeFS, os?: typeof nodeOS, directoryMode?: number);
13
+ constructor(root: Path, fs?: typeof NodeFS, os?: typeof nodeOS, directoryMode?: number);
14
14
  resolve(relativeOrAbsolutePath: Path): Path;
15
- store(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, encoding?: WriteFileOptions): Promise<Path>;
16
- createReadStream(relativeOrAbsolutePathToFile: Path): nodeFS.ReadStream;
17
- createWriteStreamTo(relativeOrAbsolutePathToFile: Path): nodeFS.WriteStream;
18
- stat(relativeOrAbsolutePathToFile: Path): Promise<nodeFS.Stats>;
15
+ store(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, encoding?: NodeFS.WriteFileOptions): Promise<Path>;
16
+ readFile(relativeOrAbsolutePathToFile: Path, options?: {
17
+ encoding?: null | undefined;
18
+ flag?: string | undefined;
19
+ }): Promise<Buffer>;
20
+ readFile(relativeOrAbsolutePathToFile: Path, options: {
21
+ encoding: BufferEncoding;
22
+ flag?: string | undefined;
23
+ } | NodeJS.BufferEncoding): Promise<string>;
24
+ readFileSync(relativeOrAbsolutePathToFile: Path, options?: {
25
+ encoding?: null | undefined;
26
+ flag?: string | undefined;
27
+ }): Buffer;
28
+ readFileSync(relativeOrAbsolutePathToFile: Path, options: {
29
+ encoding: BufferEncoding;
30
+ flag?: string | undefined;
31
+ } | NodeJS.BufferEncoding): string;
32
+ writeFile(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, options?: NodeFS.WriteFileOptions): Promise<Path>;
33
+ writeFileSync(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, options?: NodeFS.WriteFileOptions): Path;
34
+ createReadStream(relativeOrAbsolutePathToFile: Path): NodeFS.ReadStream;
35
+ createWriteStreamTo(relativeOrAbsolutePathToFile: Path): NodeFS.WriteStream;
36
+ stat(relativeOrAbsolutePathToFile: Path): Promise<NodeFS.Stats>;
19
37
  exists(relativeOrAbsolutePathToFile: Path): boolean;
20
38
  remove(relativeOrAbsolutePathToFileOrDirectory: Path): Promise<void>;
21
39
  ensureDirectoryExistsAt(relativeOrAbsolutePathToDirectory: Path): Promise<Path>;
22
40
  rename(source: Path, destination: Path): Promise<void>;
23
41
  tempFilePath(prefix?: string, suffix?: string): Path;
24
- private write;
25
42
  }
26
43
  //# sourceMappingURL=FileSystem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../src/io/FileSystem.ts"],"names":[],"mappings":";;;AACA,OAAO,KAAK,KAAK,MAAM,MAAM,IAAI,CAAC;AAClC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAC;AAE3C,OAAO,KAAK,MAAM,MAAM,IAAI,CAAC;AAG7B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,qBAAa,UAAU;IAGf,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAHb,IAAI,EAAE,IAAI,EACV,EAAE,GAAE,OAAO,MAAmB,EAC9B,EAAE,GAAE,OAAO,MAAe,EAC1B,aAAa,SAAkD;IAI7E,OAAO,CAAC,sBAAsB,EAAE,IAAI,GAAG,IAAI;IAI3C,KAAK,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5H,gBAAgB,CAAC,4BAA4B,EAAE,IAAI,GAAG,MAAM,CAAC,UAAU;IAIvE,mBAAmB,CAAC,4BAA4B,EAAE,IAAI,GAAG,MAAM,CAAC,WAAW;IAI3E,IAAI,CAAC,4BAA4B,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;IAM/D,MAAM,CAAC,4BAA4B,EAAE,IAAI,GAAG,OAAO;IAInD,MAAM,CAAC,uCAAuC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BpE,uBAAuB,CAAC,iCAAiC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B/E,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,YAAY,CAAC,MAAM,SAAK,EAAE,MAAM,SAAS,GAAG,IAAI;IAIvD,OAAO,CAAC,KAAK;CAYhB"}
1
+ {"version":3,"file":"FileSystem.d.ts","sourceRoot":"","sources":["../../src/io/FileSystem.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AAGlC,OAAO,KAAK,KAAK,MAAM,MAAM,IAAI,CAAC;AAGlC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,qBAAa,UAAU;IAGf,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAHb,IAAI,EAAE,IAAI,EACV,EAAE,GAAE,OAAO,MAAmB,EAC9B,EAAE,GAAE,OAAO,MAAe,EAC1B,aAAa,SAAkD;IAI7E,OAAO,CAAC,sBAAsB,EAAE,IAAI,GAAG,IAAI;IAIrC,KAAK,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzI,QAAQ,CAAC,4BAA4B,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IACpI,QAAQ,CAAC,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;QAAE,QAAQ,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAAE,GAAG,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAKxJ,YAAY,CAAC,4BAA4B,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAAE,GAAG,MAAM;IAC/H,YAAY,CAAC,4BAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;QAAE,QAAQ,EAAE,cAAc,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAAE,GAAG,MAAM,CAAC,cAAc,GAAG,MAAM;IAK7I,SAAS,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5I,aAAa,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,gBAAgB,GAAG,IAAI;IAOjI,gBAAgB,CAAC,4BAA4B,EAAE,IAAI,GAAG,MAAM,CAAC,UAAU;IAIvE,mBAAmB,CAAC,4BAA4B,EAAE,IAAI,GAAG,MAAM,CAAC,WAAW;IAI3E,IAAI,CAAC,4BAA4B,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;IAI/D,MAAM,CAAC,4BAA4B,EAAE,IAAI,GAAG,OAAO;IAI7C,MAAM,CAAC,uCAAuC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BpE,uBAAuB,CAAC,iCAAiC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IASrF,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,YAAY,CAAC,MAAM,SAAK,EAAE,MAAM,SAAS,GAAG,IAAI;CAG1D"}
@@ -24,10 +24,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.FileSystem = void 0;
27
+ const nodeOS = __importStar(require("node:os"));
27
28
  const cuid2_1 = require("@paralleldrive/cuid2");
28
29
  const gracefulFS = __importStar(require("graceful-fs"));
29
- const nodeOS = __importStar(require("os"));
30
- const util_1 = require("util");
31
30
  const Path_1 = require("./Path");
32
31
  class FileSystem {
33
32
  root;
@@ -43,10 +42,25 @@ class FileSystem {
43
42
  resolve(relativeOrAbsolutePath) {
44
43
  return this.root.resolve(relativeOrAbsolutePath);
45
44
  }
46
- store(relativeOrAbsolutePathToFile, data, encoding) {
47
- return Promise.resolve()
48
- .then(() => this.ensureDirectoryExistsAt(relativeOrAbsolutePathToFile.directory()))
49
- .then(() => this.write(this.resolve(relativeOrAbsolutePathToFile), data, encoding));
45
+ async store(relativeOrAbsolutePathToFile, data, encoding) {
46
+ await this.ensureDirectoryExistsAt(relativeOrAbsolutePathToFile.directory());
47
+ return this.writeFile(relativeOrAbsolutePathToFile, data, encoding);
48
+ }
49
+ readFile(relativeOrAbsolutePathToFile, options) {
50
+ return this.fs.promises.readFile(this.resolve(relativeOrAbsolutePathToFile).value, options);
51
+ }
52
+ readFileSync(relativeOrAbsolutePathToFile, options) {
53
+ return this.fs.readFileSync(this.resolve(relativeOrAbsolutePathToFile).value, options);
54
+ }
55
+ async writeFile(relativeOrAbsolutePathToFile, data, options) {
56
+ const resolvedPath = this.resolve(relativeOrAbsolutePathToFile);
57
+ await this.fs.promises.writeFile(resolvedPath.value, data, options);
58
+ return resolvedPath;
59
+ }
60
+ writeFileSync(relativeOrAbsolutePathToFile, data, options) {
61
+ const resolvedPath = this.resolve(relativeOrAbsolutePathToFile);
62
+ this.fs.writeFileSync(resolvedPath.value, data, options);
63
+ return resolvedPath;
50
64
  }
51
65
  createReadStream(relativeOrAbsolutePathToFile) {
52
66
  return this.fs.createReadStream(this.resolve(relativeOrAbsolutePathToFile).value);
@@ -55,64 +69,44 @@ class FileSystem {
55
69
  return this.fs.createWriteStream(this.resolve(relativeOrAbsolutePathToFile).value);
56
70
  }
57
71
  stat(relativeOrAbsolutePathToFile) {
58
- const stat = (0, util_1.promisify)(this.fs.stat);
59
- return stat(this.resolve(relativeOrAbsolutePathToFile).value);
72
+ return this.fs.promises.stat(this.resolve(relativeOrAbsolutePathToFile).value);
60
73
  }
61
74
  exists(relativeOrAbsolutePathToFile) {
62
75
  return this.fs.existsSync(this.resolve(relativeOrAbsolutePathToFile).value);
63
76
  }
64
- remove(relativeOrAbsolutePathToFileOrDirectory) {
65
- const stat = (0, util_1.promisify)(this.fs.stat), unlink = (0, util_1.promisify)(this.fs.unlink), readdir = (0, util_1.promisify)(this.fs.readdir), rmdir = (0, util_1.promisify)(this.fs.rmdir);
66
- const absolutePath = this.resolve(relativeOrAbsolutePathToFileOrDirectory);
67
- return stat(absolutePath.value)
68
- .then(result => result.isFile()
69
- ? unlink(absolutePath.value)
70
- : readdir(absolutePath.value)
71
- .then(entries => Promise.all(entries.map(entry => this.remove(absolutePath.join(new Path_1.Path(entry))))).then(() => rmdir(absolutePath.value))))
72
- .then(() => void 0)
73
- .catch(error => {
77
+ async remove(relativeOrAbsolutePathToFileOrDirectory) {
78
+ try {
79
+ const absolutePath = this.resolve(relativeOrAbsolutePathToFileOrDirectory);
80
+ const stat = await this.stat(relativeOrAbsolutePathToFileOrDirectory);
81
+ if (stat.isFile()) {
82
+ await this.fs.promises.unlink(absolutePath.value);
83
+ }
84
+ else {
85
+ const entries = await this.fs.promises.readdir(absolutePath.value);
86
+ for (const entry of entries) {
87
+ await this.remove(absolutePath.join(new Path_1.Path(entry)));
88
+ }
89
+ await this.fs.promises.rmdir(absolutePath.value);
90
+ }
91
+ }
92
+ catch (error) {
74
93
  if (error?.code === 'ENOENT') {
75
94
  return void 0;
76
95
  }
77
96
  throw error;
78
- });
97
+ }
79
98
  }
80
- ensureDirectoryExistsAt(relativeOrAbsolutePathToDirectory) {
99
+ async ensureDirectoryExistsAt(relativeOrAbsolutePathToDirectory) {
81
100
  const absolutePath = this.resolve(relativeOrAbsolutePathToDirectory);
82
- return absolutePath.split().reduce((promisedParent, child) => {
83
- return promisedParent.then(parent => new Promise((resolve, reject) => {
84
- const current = parent.resolve(new Path_1.Path(child));
85
- this.fs.mkdir(current.value, this.directoryMode, error => {
86
- if (!error || error.code === 'EEXIST') {
87
- return resolve(current);
88
- }
89
- // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
90
- if (error.code === 'ENOENT') { // Throw the original parentDir error on `current` `ENOENT` failure.
91
- throw new Error(`EACCES: permission denied, mkdir '${parent.value}'`);
92
- }
93
- const caughtError = !!~['EACCES', 'EPERM', 'EISDIR'].indexOf(error.code);
94
- if (!caughtError || (caughtError && current.equals(relativeOrAbsolutePathToDirectory))) {
95
- throw error; // Throw if it's just the last created dir.
96
- }
97
- return resolve(current);
98
- });
99
- }));
100
- }, Promise.resolve(absolutePath.root()));
101
+ await this.fs.promises.mkdir(absolutePath.value, { recursive: true, mode: this.directoryMode });
102
+ return absolutePath;
101
103
  }
102
104
  rename(source, destination) {
103
- const rename = (0, util_1.promisify)(this.fs.rename);
104
- return rename(source.value, destination.value);
105
+ return this.fs.promises.rename(source.value, destination.value);
105
106
  }
106
107
  tempFilePath(prefix = '', suffix = '.tmp') {
107
108
  return Path_1.Path.from(this.fs.realpathSync(this.os.tmpdir()), `${prefix}${(0, cuid2_1.createId)()}${suffix}`);
108
109
  }
109
- write(path, data, encoding) {
110
- return new Promise((resolve, reject) => {
111
- this.fs.writeFile(path.value, data, encoding, error => error
112
- ? reject(error)
113
- : resolve(path));
114
- });
115
- }
116
110
  }
117
111
  exports.FileSystem = FileSystem;
118
112
  //# sourceMappingURL=FileSystem.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystem.js","sourceRoot":"","sources":["../../src/io/FileSystem.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileSystem.js","sourceRoot":"","sources":["../../src/io/FileSystem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { TinyType } from 'tiny-types';
2
+ /**
3
+ * A tiny type describing a version number, like `1.2.3`
4
+ */
5
+ export declare class Version extends TinyType {
6
+ private readonly version;
7
+ static fromJSON(version: string): Version;
8
+ constructor(version: string);
9
+ isLowerThan(other: Version): boolean;
10
+ isAtMost(other: Version): boolean;
11
+ /**
12
+ * @param other
13
+ */
14
+ isAtLeast(other: Version): boolean;
15
+ isHigherThan(other: Version): boolean;
16
+ /**
17
+ * @returns
18
+ * Major version number of a given package version, i.e. `1` in `1.2.3`
19
+ */
20
+ major(): number;
21
+ satisfies(range: string): boolean;
22
+ toString(): string;
23
+ }
24
+ //# sourceMappingURL=Version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Version.d.ts","sourceRoot":"","sources":["../../src/io/Version.ts"],"names":[],"mappings":"AACA,OAAO,EAA0C,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE9E;;GAEG;AACH,qBAAa,OAAQ,SAAQ,QAAQ;IAMrB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;gBAIZ,OAAO,EAAE,MAAM;IAK5C,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAIpC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAIjC;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAIlC,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAIrC;;;OAGG;IACH,KAAK,IAAI,MAAM;IAIf,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIjC,QAAQ,IAAI,MAAM;CAGrB"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Version = void 0;
7
+ const semver_1 = __importDefault(require("semver"));
8
+ const tiny_types_1 = require("tiny-types");
9
+ /**
10
+ * A tiny type describing a version number, like `1.2.3`
11
+ */
12
+ class Version extends tiny_types_1.TinyType {
13
+ version;
14
+ static fromJSON(version) {
15
+ return new Version(version);
16
+ }
17
+ constructor(version) {
18
+ super();
19
+ this.version = version;
20
+ (0, tiny_types_1.ensure)('version', version, (0, tiny_types_1.isDefined)(), (0, tiny_types_1.isString)(), isValid());
21
+ }
22
+ isLowerThan(other) {
23
+ return semver_1.default.lt(this.version, other.version, { loose: false });
24
+ }
25
+ isAtMost(other) {
26
+ return semver_1.default.lte(this.version, other.version, { loose: false });
27
+ }
28
+ /**
29
+ * @param other
30
+ */
31
+ isAtLeast(other) {
32
+ return semver_1.default.gte(this.version, other.version, { loose: false });
33
+ }
34
+ isHigherThan(other) {
35
+ return semver_1.default.gt(this.version, other.version, { loose: false });
36
+ }
37
+ /**
38
+ * @returns
39
+ * Major version number of a given package version, i.e. `1` in `1.2.3`
40
+ */
41
+ major() {
42
+ return Number(this.version.split('.')[0]);
43
+ }
44
+ satisfies(range) {
45
+ return semver_1.default.satisfies(this.version, range, { loose: false });
46
+ }
47
+ toString() {
48
+ return `${this.version}`;
49
+ }
50
+ }
51
+ exports.Version = Version;
52
+ /**
53
+ * @package
54
+ */
55
+ function isValid() {
56
+ return tiny_types_1.Predicate.to(`be a valid version number`, (version) => !!semver_1.default.valid(version));
57
+ }
58
+ //# sourceMappingURL=Version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Version.js","sourceRoot":"","sources":["../../src/io/Version.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAC5B,2CAA8E;AAE9E;;GAEG;AACH,MAAa,OAAQ,SAAQ,qBAAQ;IAMJ;IAJ7B,MAAM,CAAC,QAAQ,CAAC,OAAe;QAC3B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,YAA6B,OAAe;QACxC,KAAK,EAAE,CAAC;QADiB,YAAO,GAAP,OAAO,CAAQ;QAExC,IAAA,mBAAM,EAAC,SAAS,EAAE,OAAO,EAAE,IAAA,sBAAS,GAAE,EAAE,IAAA,qBAAQ,GAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,WAAW,CAAC,KAAc;QACtB,OAAO,gBAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,QAAQ,CAAC,KAAc;QACnB,OAAO,gBAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,KAAc;QACpB,OAAO,gBAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,YAAY,CAAC,KAAc;QACvB,OAAO,gBAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAED;;;OAGG;IACH,KAAK;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CAAC,KAAa;QACnB,OAAO,gBAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,QAAQ;QACJ,OAAO,GAAI,IAAI,CAAC,OAAQ,EAAE,CAAC;IAC/B,CAAC;CACJ;AA7CD,0BA6CC;AAED;;GAEG;AACH,SAAS,OAAO;IACZ,OAAO,sBAAS,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,OAAe,EAAE,EAAE,CACjE,CAAC,CAAE,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAC3B,CAAC;AACN,CAAC"}
package/lib/io/index.d.ts CHANGED
@@ -12,4 +12,5 @@ export * from './Path';
12
12
  export * from './reflection';
13
13
  export * from './RequirementsHierarchy';
14
14
  export * from './trimmed';
15
+ export * from './Version';
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
package/lib/io/index.js CHANGED
@@ -28,4 +28,5 @@ __exportStar(require("./Path"), exports);
28
28
  __exportStar(require("./reflection"), exports);
29
29
  __exportStar(require("./RequirementsHierarchy"), exports);
30
30
  __exportStar(require("./trimmed"), exports);
31
+ __exportStar(require("./Version"), exports);
31
32
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,mDAAiC;AACjC,2CAAyB;AACzB,+CAA6B;AAC7B,+CAA6B;AAC7B,uDAAqC;AACrC,2CAAyB;AACzB,8CAA4B;AAC5B,oDAAkC;AAClC,2CAAyB;AACzB,yCAAuB;AACvB,+CAA6B;AAC7B,0DAAwC;AACxC,4CAA0B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,mDAAiC;AACjC,2CAAyB;AACzB,+CAA6B;AAC7B,+CAA6B;AAC7B,uDAAqC;AACrC,2CAAyB;AACzB,8CAA4B;AAC5B,oDAAkC;AAClC,2CAAyB;AACzB,yCAAuB;AACvB,+CAA6B;AAC7B,0DAAwC;AACxC,4CAA0B;AAC1B,4CAA0B"}
@@ -1,14 +1,18 @@
1
- import { Version } from './Version';
1
+ import { Version } from '../Version';
2
2
  /**
3
3
  * Dynamically loads Node modules located relative to `cwd`.
4
4
  */
5
5
  export declare class ModuleLoader {
6
6
  readonly cwd: string;
7
+ readonly useRequireCache: boolean;
7
8
  /**
8
9
  * @param {string} cwd
9
10
  * Current working directory, relative to which Node modules should be resolved.
11
+ * @param useRequireCache
12
+ * Whether to use Node's `require.cache`. Defaults to `true`.
13
+ * Set to `false` to force Node to reload required modules on every call.
10
14
  */
11
- constructor(cwd: string);
15
+ constructor(cwd: string, useRequireCache?: boolean);
12
16
  /**
13
17
  * Returns `true` if a given module is available to be required, false otherwise.
14
18
  *
@@ -23,7 +27,7 @@ export declare class ModuleLoader {
23
27
  * NPM module id, for example `cucumber` or `@serenity-js/core`
24
28
  *
25
29
  * @returns
26
- * Path a given Node module
30
+ * Path to a given Node.js module
27
31
  */
28
32
  resolve(moduleId: string): string;
29
33
  /**
@@ -32,6 +36,7 @@ export declare class ModuleLoader {
32
36
  * @param moduleId
33
37
  */
34
38
  require(moduleId: string): any;
39
+ private cachedIfNeeded;
35
40
  /**
36
41
  * Returns {@apilink Version} of module specified by `moduleId`, based on its `package.json`.
37
42
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ModuleLoader.d.ts","sourceRoot":"","sources":["../../../src/io/loader/ModuleLoader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;GAEG;AACH,qBAAa,YAAY;aAMO,GAAG,EAAE,MAAM;IAJvC;;;OAGG;gBACyB,GAAG,EAAE,MAAM;IAGvC;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQvC;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAUjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;IAS9B;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGvC"}
1
+ {"version":3,"file":"ModuleLoader.d.ts","sourceRoot":"","sources":["../../../src/io/loader/ModuleLoader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;GAEG;AACH,qBAAa,YAAY;aAUD,GAAG,EAAE,MAAM;aACX,eAAe,EAAE,OAAO;IAT5C;;;;;;OAMG;gBAEiB,GAAG,EAAE,MAAM,EACX,eAAe,GAAE,OAAc;IAInD;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQvC;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAUjC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;IAS9B,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAGvC"}
@@ -27,18 +27,23 @@ exports.ModuleLoader = void 0;
27
27
  // eslint-disable-next-line @typescript-eslint/no-var-requires
28
28
  const Module = require('module'); // No type definitions available
29
29
  const path = __importStar(require("path")); // eslint-disable-line unicorn/import-style
30
- const Version_1 = require("./Version");
30
+ const Version_1 = require("../Version");
31
31
  /**
32
32
  * Dynamically loads Node modules located relative to `cwd`.
33
33
  */
34
34
  class ModuleLoader {
35
35
  cwd;
36
+ useRequireCache;
36
37
  /**
37
38
  * @param {string} cwd
38
39
  * Current working directory, relative to which Node modules should be resolved.
40
+ * @param useRequireCache
41
+ * Whether to use Node's `require.cache`. Defaults to `true`.
42
+ * Set to `false` to force Node to reload required modules on every call.
39
43
  */
40
- constructor(cwd) {
44
+ constructor(cwd, useRequireCache = true) {
41
45
  this.cwd = cwd;
46
+ this.useRequireCache = useRequireCache;
42
47
  }
43
48
  /**
44
49
  * Returns `true` if a given module is available to be required, false otherwise.
@@ -61,7 +66,7 @@ class ModuleLoader {
61
66
  * NPM module id, for example `cucumber` or `@serenity-js/core`
62
67
  *
63
68
  * @returns
64
- * Path a given Node module
69
+ * Path to a given Node.js module
65
70
  */
66
71
  resolve(moduleId) {
67
72
  const fromFile = path.join(this.cwd, 'noop.js');
@@ -78,12 +83,18 @@ class ModuleLoader {
78
83
  */
79
84
  require(moduleId) {
80
85
  try {
81
- return require(this.resolve(moduleId));
86
+ return require(this.cachedIfNeeded(this.resolve(moduleId)));
82
87
  }
83
88
  catch {
84
- return require(moduleId);
89
+ return require(this.cachedIfNeeded(moduleId));
85
90
  }
86
91
  }
92
+ cachedIfNeeded(moduleId) {
93
+ if (!this.useRequireCache) {
94
+ delete require.cache[moduleId];
95
+ }
96
+ return moduleId;
97
+ }
87
98
  /**
88
99
  * Returns {@apilink Version} of module specified by `moduleId`, based on its `package.json`.
89
100
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ModuleLoader.js","sourceRoot":"","sources":["../../../src/io/loader/ModuleLoader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8DAA8D;AAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,gCAAgC;AAClE,2CAA6B,CAAC,2CAA2C;AAEzE,uCAAoC;AAEpC;;GAEG;AACH,MAAa,YAAY;IAMO;IAJ5B;;;OAGG;IACH,YAA4B,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IACvC,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,QAAgB;QACzB,IAAI;YACA,OAAO,CAAC,CAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;SACpC;QAAC,MAAM;YACJ,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAgB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAEhD,OAAO,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE;YACrC,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;SAC3C,CAAC,CAAC;IACP,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,QAAgB;QACpB,IAAI;YACA,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;SAC1C;QACD,MAAM;YACF,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;SAC5B;IACL,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,QAAgB;QACtB,OAAO,IAAI,iBAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAI,QAAS,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3E,CAAC;CACJ;AAhED,oCAgEC"}
1
+ {"version":3,"file":"ModuleLoader.js","sourceRoot":"","sources":["../../../src/io/loader/ModuleLoader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8DAA8D;AAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,gCAAgC;AAClE,2CAA6B,CAAC,2CAA2C;AAEzE,wCAAqC;AAErC;;GAEG;AACH,MAAa,YAAY;IAUD;IACA;IATpB;;;;;;OAMG;IACH,YACoB,GAAW,EACX,kBAA2B,IAAI;QAD/B,QAAG,GAAH,GAAG,CAAQ;QACX,oBAAe,GAAf,eAAe,CAAgB;IAEnD,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,QAAgB;QACzB,IAAI;YACA,OAAO,CAAC,CAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;SACpC;QAAC,MAAM;YACJ,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAgB;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAEhD,OAAO,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE;YACrC,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;SAC3C,CAAC,CAAC;IACP,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,QAAgB;QACpB,IAAI;YACA,OAAO,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC/D;QACD,MAAM;YACF,OAAO,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;SACjD;IACL,CAAC;IAEO,cAAc,CAAC,QAAgB;QACnC,IAAI,CAAE,IAAI,CAAC,eAAe,EAAE;YACxB,OAAO,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;SAClC;QAED,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,QAAgB;QACtB,OAAO,IAAI,iBAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAI,QAAS,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3E,CAAC;CACJ;AA9ED,oCA8EC"}
@@ -2,5 +2,4 @@ export * from './ClassDescriptionParser';
2
2
  export * from './ClassDescriptor';
3
3
  export * from './ClassLoader';
4
4
  export * from './ModuleLoader';
5
- export * from './Version';
6
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/io/loader/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/io/loader/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
@@ -18,5 +18,4 @@ __exportStar(require("./ClassDescriptionParser"), exports);
18
18
  __exportStar(require("./ClassDescriptor"), exports);
19
19
  __exportStar(require("./ClassLoader"), exports);
20
20
  __exportStar(require("./ModuleLoader"), exports);
21
- __exportStar(require("./Version"), exports);
22
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/io/loader/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAyC;AACzC,oDAAkC;AAClC,gDAA8B;AAC9B,iDAA+B;AAC/B,4CAA0B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/io/loader/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAyC;AACzC,oDAAkC;AAClC,gDAA8B;AAC9B,iDAA+B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/core",
3
- "version": "3.19.0",
3
+ "version": "3.20.0",
4
4
  "description": "Serenity/JS Screenplay, reporting engine and core interfaces.",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -71,5 +71,5 @@
71
71
  "engines": {
72
72
  "node": "^16.13 || ^18.12 || ^20"
73
73
  },
74
- "gitHead": "6bc255b85d3e74d000b1584a64e460cc5adc1e23"
74
+ "gitHead": "2089afc60adb2751416fa6d800d4e7af95a99f25"
75
75
  }
@@ -1,9 +1,8 @@
1
+ import * as nodeOS from 'node:os';
2
+
1
3
  import { createId } from '@paralleldrive/cuid2';
2
- import type * as nodeFS from 'fs';
3
- import type { WriteFileOptions } from 'fs';
4
+ import type * as NodeFS from 'fs';
4
5
  import * as gracefulFS from 'graceful-fs';
5
- import * as nodeOS from 'os';
6
- import { promisify } from 'util';
7
6
 
8
7
  import { Path } from './Path';
9
8
 
@@ -11,7 +10,7 @@ export class FileSystem {
11
10
 
12
11
  constructor(
13
12
  private readonly root: Path,
14
- private readonly fs: typeof nodeFS = gracefulFS,
13
+ private readonly fs: typeof NodeFS = gracefulFS,
15
14
  private readonly os: typeof nodeOS = nodeOS,
16
15
  private readonly directoryMode = Number.parseInt('0777', 8) & (~process.umask()),
17
16
  ) {
@@ -21,108 +20,93 @@ export class FileSystem {
21
20
  return this.root.resolve(relativeOrAbsolutePath);
22
21
  }
23
22
 
24
- public store(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, encoding?: WriteFileOptions): Promise<Path> {
25
- return Promise.resolve()
26
- .then(() => this.ensureDirectoryExistsAt(relativeOrAbsolutePathToFile.directory()))
27
- .then(() => this.write(this.resolve(relativeOrAbsolutePathToFile), data, encoding));
23
+ public async store(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, encoding?: NodeFS.WriteFileOptions): Promise<Path> {
24
+ await this.ensureDirectoryExistsAt(relativeOrAbsolutePathToFile.directory());
25
+ return this.writeFile(relativeOrAbsolutePathToFile, data, encoding);
26
+ }
27
+
28
+ public readFile(relativeOrAbsolutePathToFile: Path, options?: { encoding?: null | undefined; flag?: string | undefined; }): Promise<Buffer>
29
+ public readFile(relativeOrAbsolutePathToFile: Path, options: { encoding: BufferEncoding; flag?: string | undefined; } | NodeJS.BufferEncoding): Promise<string>
30
+ public readFile(relativeOrAbsolutePathToFile: Path, options?: (NodeFS.ObjectEncodingOptions & { flag?: string | undefined; }) | NodeJS.BufferEncoding): Promise<string | Buffer> {
31
+ return this.fs.promises.readFile(this.resolve(relativeOrAbsolutePathToFile).value, options);
32
+ }
33
+
34
+ public readFileSync(relativeOrAbsolutePathToFile: Path, options?: { encoding?: null | undefined; flag?: string | undefined; }): Buffer
35
+ public readFileSync(relativeOrAbsolutePathToFile: Path, options: { encoding: BufferEncoding; flag?: string | undefined; } | NodeJS.BufferEncoding): string
36
+ public readFileSync(relativeOrAbsolutePathToFile: Path, options?: (NodeFS.ObjectEncodingOptions & { flag?: string | undefined; }) | NodeJS.BufferEncoding): string | Buffer {
37
+ return this.fs.readFileSync(this.resolve(relativeOrAbsolutePathToFile).value, options);
28
38
  }
29
39
 
30
- public createReadStream(relativeOrAbsolutePathToFile: Path): nodeFS.ReadStream {
40
+ public async writeFile(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, options?: NodeFS.WriteFileOptions): Promise<Path> {
41
+ const resolvedPath = this.resolve(relativeOrAbsolutePathToFile);
42
+ await this.fs.promises.writeFile(resolvedPath.value, data, options);
43
+
44
+ return resolvedPath;
45
+ }
46
+
47
+ public writeFileSync(relativeOrAbsolutePathToFile: Path, data: string | NodeJS.ArrayBufferView, options?: NodeFS.WriteFileOptions): Path {
48
+ const resolvedPath = this.resolve(relativeOrAbsolutePathToFile);
49
+ this.fs.writeFileSync(resolvedPath.value, data, options);
50
+
51
+ return resolvedPath;
52
+ }
53
+
54
+ public createReadStream(relativeOrAbsolutePathToFile: Path): NodeFS.ReadStream {
31
55
  return this.fs.createReadStream(this.resolve(relativeOrAbsolutePathToFile).value);
32
56
  }
33
57
 
34
- public createWriteStreamTo(relativeOrAbsolutePathToFile: Path): nodeFS.WriteStream {
58
+ public createWriteStreamTo(relativeOrAbsolutePathToFile: Path): NodeFS.WriteStream {
35
59
  return this.fs.createWriteStream(this.resolve(relativeOrAbsolutePathToFile).value);
36
60
  }
37
61
 
38
- public stat(relativeOrAbsolutePathToFile: Path): Promise<nodeFS.Stats> {
39
- const stat = promisify(this.fs.stat);
40
-
41
- return stat(this.resolve(relativeOrAbsolutePathToFile).value);
62
+ public stat(relativeOrAbsolutePathToFile: Path): Promise<NodeFS.Stats> {
63
+ return this.fs.promises.stat(this.resolve(relativeOrAbsolutePathToFile).value);
42
64
  }
43
65
 
44
66
  public exists(relativeOrAbsolutePathToFile: Path): boolean {
45
67
  return this.fs.existsSync(this.resolve(relativeOrAbsolutePathToFile).value);
46
68
  }
47
69
 
48
- public remove(relativeOrAbsolutePathToFileOrDirectory: Path): Promise<void> {
49
- const
50
- stat = promisify(this.fs.stat),
51
- unlink = promisify(this.fs.unlink),
52
- readdir = promisify(this.fs.readdir),
53
- rmdir = promisify(this.fs.rmdir);
54
-
55
- const absolutePath = this.resolve(relativeOrAbsolutePathToFileOrDirectory);
56
-
57
- return stat(absolutePath.value)
58
- .then(result =>
59
- result.isFile()
60
- ? unlink(absolutePath.value)
61
- : readdir(absolutePath.value)
62
- .then(entries =>
63
- Promise.all(entries.map(entry =>
64
- this.remove(absolutePath.join(new Path(entry)))),
65
- ).then(() => rmdir(absolutePath.value)),
66
- ),
67
- )
68
- .then(() => void 0)
69
- .catch(error => {
70
- if (error?.code === 'ENOENT') {
71
- return void 0;
70
+ public async remove(relativeOrAbsolutePathToFileOrDirectory: Path): Promise<void> {
71
+ try {
72
+ const absolutePath = this.resolve(relativeOrAbsolutePathToFileOrDirectory);
73
+
74
+ const stat = await this.stat(relativeOrAbsolutePathToFileOrDirectory);
75
+
76
+ if (stat.isFile()) {
77
+ await this.fs.promises.unlink(absolutePath.value);
78
+ }
79
+ else {
80
+ const entries = await this.fs.promises.readdir(absolutePath.value);
81
+ for (const entry of entries) {
82
+ await this.remove(absolutePath.join(new Path(entry)));
72
83
  }
73
- throw error;
74
- });
84
+
85
+ await this.fs.promises.rmdir(absolutePath.value);
86
+ }
87
+ }
88
+ catch (error) {
89
+ if (error?.code === 'ENOENT') {
90
+ return void 0;
91
+ }
92
+ throw error;
93
+ }
75
94
  }
76
95
 
77
- public ensureDirectoryExistsAt(relativeOrAbsolutePathToDirectory: Path): Promise<Path> {
96
+ public async ensureDirectoryExistsAt(relativeOrAbsolutePathToDirectory: Path): Promise<Path> {
78
97
 
79
98
  const absolutePath = this.resolve(relativeOrAbsolutePathToDirectory);
80
99
 
81
- return absolutePath.split().reduce((promisedParent, child) => {
82
- return promisedParent.then(parent => new Promise((resolve, reject) => {
83
- const current = parent.resolve(new Path(child));
84
-
85
- this.fs.mkdir(current.value, this.directoryMode, error => {
86
- if (! error || error.code === 'EEXIST') {
87
- return resolve(current);
88
- }
89
-
90
- // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
91
- if (error.code === 'ENOENT') { // Throw the original parentDir error on `current` `ENOENT` failure.
92
- throw new Error(`EACCES: permission denied, mkdir '${ parent.value }'`);
93
- }
94
-
95
- const caughtError = !! ~['EACCES', 'EPERM', 'EISDIR'].indexOf(error.code);
96
- if (! caughtError || (caughtError && current.equals(relativeOrAbsolutePathToDirectory))) {
97
- throw error; // Throw if it's just the last created dir.
98
- }
99
-
100
- return resolve(current);
101
- });
102
- }));
103
- }, Promise.resolve(absolutePath.root()));
100
+ await this.fs.promises.mkdir(absolutePath.value, { recursive: true, mode: this.directoryMode });
101
+
102
+ return absolutePath;
104
103
  }
105
104
 
106
105
  public rename(source: Path, destination: Path): Promise<void> {
107
- const rename = promisify(this.fs.rename);
108
-
109
- return rename(source.value, destination.value);
106
+ return this.fs.promises.rename(source.value, destination.value);
110
107
  }
111
108
 
112
109
  public tempFilePath(prefix = '', suffix = '.tmp'): Path {
113
110
  return Path.from(this.fs.realpathSync(this.os.tmpdir()), `${ prefix }${ createId() }${ suffix }`);
114
111
  }
115
-
116
- private write(path: Path, data: string | NodeJS.ArrayBufferView, encoding?: WriteFileOptions): Promise<Path> {
117
- return new Promise((resolve, reject) => {
118
- this.fs.writeFile(
119
- path.value,
120
- data,
121
- encoding,
122
- error => error
123
- ? reject(error)
124
- : resolve(path),
125
- );
126
- });
127
- }
128
112
  }
@@ -0,0 +1,61 @@
1
+ import semver from 'semver';
2
+ import { ensure, isDefined, isString, Predicate, TinyType } from 'tiny-types';
3
+
4
+ /**
5
+ * A tiny type describing a version number, like `1.2.3`
6
+ */
7
+ export class Version extends TinyType {
8
+
9
+ static fromJSON(version: string): Version {
10
+ return new Version(version);
11
+ }
12
+
13
+ constructor(private readonly version: string) {
14
+ super();
15
+ ensure('version', version, isDefined(), isString(), isValid());
16
+ }
17
+
18
+ isLowerThan(other: Version): boolean {
19
+ return semver.lt(this.version, other.version, { loose: false });
20
+ }
21
+
22
+ isAtMost(other: Version): boolean {
23
+ return semver.lte(this.version, other.version, { loose: false });
24
+ }
25
+
26
+ /**
27
+ * @param other
28
+ */
29
+ isAtLeast(other: Version): boolean {
30
+ return semver.gte(this.version, other.version, { loose: false });
31
+ }
32
+
33
+ isHigherThan(other: Version): boolean {
34
+ return semver.gt(this.version, other.version, { loose: false });
35
+ }
36
+
37
+ /**
38
+ * @returns
39
+ * Major version number of a given package version, i.e. `1` in `1.2.3`
40
+ */
41
+ major(): number {
42
+ return Number(this.version.split('.')[0]);
43
+ }
44
+
45
+ satisfies(range: string): boolean {
46
+ return semver.satisfies(this.version, range, { loose: false });
47
+ }
48
+
49
+ toString(): string {
50
+ return `${ this.version }`;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * @package
56
+ */
57
+ function isValid(): Predicate<string> {
58
+ return Predicate.to(`be a valid version number`, (version: string) =>
59
+ !! semver.valid(version),
60
+ );
61
+ }
package/src/io/index.ts CHANGED
@@ -12,3 +12,4 @@ export * from './Path';
12
12
  export * from './reflection';
13
13
  export * from './RequirementsHierarchy';
14
14
  export * from './trimmed';
15
+ export * from './Version';
@@ -2,7 +2,7 @@
2
2
  const Module = require('module'); // No type definitions available
3
3
  import * as path from 'path'; // eslint-disable-line unicorn/import-style
4
4
 
5
- import { Version } from './Version';
5
+ import { Version } from '../Version';
6
6
 
7
7
  /**
8
8
  * Dynamically loads Node modules located relative to `cwd`.
@@ -12,8 +12,14 @@ export class ModuleLoader {
12
12
  /**
13
13
  * @param {string} cwd
14
14
  * Current working directory, relative to which Node modules should be resolved.
15
+ * @param useRequireCache
16
+ * Whether to use Node's `require.cache`. Defaults to `true`.
17
+ * Set to `false` to force Node to reload required modules on every call.
15
18
  */
16
- constructor(public readonly cwd: string) {
19
+ constructor(
20
+ public readonly cwd: string,
21
+ public readonly useRequireCache: boolean = true,
22
+ ) {
17
23
  }
18
24
 
19
25
  /**
@@ -37,7 +43,7 @@ export class ModuleLoader {
37
43
  * NPM module id, for example `cucumber` or `@serenity-js/core`
38
44
  *
39
45
  * @returns
40
- * Path a given Node module
46
+ * Path to a given Node.js module
41
47
  */
42
48
  resolve(moduleId: string): string {
43
49
  const fromFile = path.join(this.cwd, 'noop.js');
@@ -56,13 +62,21 @@ export class ModuleLoader {
56
62
  */
57
63
  require(moduleId: string): any {
58
64
  try {
59
- return require(this.resolve(moduleId));
65
+ return require(this.cachedIfNeeded(this.resolve(moduleId)));
60
66
  }
61
67
  catch {
62
- return require(moduleId);
68
+ return require(this.cachedIfNeeded(moduleId));
63
69
  }
64
70
  }
65
71
 
72
+ private cachedIfNeeded(moduleId: string): string {
73
+ if (! this.useRequireCache) {
74
+ delete require.cache[moduleId];
75
+ }
76
+
77
+ return moduleId;
78
+ }
79
+
66
80
  /**
67
81
  * Returns {@apilink Version} of module specified by `moduleId`, based on its `package.json`.
68
82
  *
@@ -2,4 +2,3 @@ export * from './ClassDescriptionParser';
2
2
  export * from './ClassDescriptor';
3
3
  export * from './ClassLoader';
4
4
  export * from './ModuleLoader';
5
- export * from './Version';