@rsdk/common.node 5.7.0-next.6 → 6.0.0-next.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/dist/deferred.js CHANGED
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  Object.defineProperty(exports, "__esModule", { value: true });
26
36
  exports.Deferred = void 0;
27
37
  const timers = __importStar(require("node:timers/promises"));
@@ -1 +1 @@
1
- {"version":3,"file":"deferred.js","sourceRoot":"","sources":["../src/deferred.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA+C;AAE/C,MAAa,QAAQ;IACV,OAAO,CAAmB;IAE3B,QAAQ,CAAmD;IAC3D,OAAO,CAA0B;IAEjC,MAAM,CAAK;IACX,OAAO,CAAK;IACZ,YAAY,GAAG,KAAK,CAAC;IACrB,WAAW,GAAG,KAAK,CAAC;IACpB,WAAW,GAAG,KAAK,CAAC;IAE5B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAClB,SAA2C;QAE3C,OAAO,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,CAAI;QACV,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,MAAS;QACd,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;CACF;AAlED,4BAkEC"}
1
+ {"version":3,"file":"deferred.js","sourceRoot":"","sources":["../src/deferred.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,6DAA+C;AAE/C,MAAa,QAAQ;IACV,OAAO,CAAmB;IAE3B,QAAQ,CAAmD;IAC3D,OAAO,CAA0B;IAEjC,MAAM,CAAK;IACX,OAAO,CAAK;IACZ,YAAY,GAAG,KAAK,CAAC;IACrB,WAAW,GAAG,KAAK,CAAC;IACpB,WAAW,GAAG,KAAK,CAAC;IAE5B;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;YACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAClB,SAA2C;QAE3C,OAAO,CAAC,CAAC,MAAM,SAAS,EAAE,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,CAAI;QACV,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,MAAS;QACd,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;CACF;AAlED,4BAkEC"}
package/dist/index.d.ts CHANGED
@@ -4,3 +4,5 @@ export { Deferred } from './deferred';
4
4
  export { MaybeReadonlyArray } from './types';
5
5
  export * from './misc';
6
6
  export * from './serialization';
7
+ export * from './parsers';
8
+ export * from './path';
package/dist/index.js CHANGED
@@ -23,4 +23,6 @@ var deferred_1 = require("./deferred");
23
23
  Object.defineProperty(exports, "Deferred", { enumerable: true, get: function () { return deferred_1.Deferred; } });
24
24
  __exportStar(require("./misc"), exports);
25
25
  __exportStar(require("./serialization"), exports);
26
+ __exportStar(require("./parsers"), exports);
27
+ __exportStar(require("./path"), exports);
26
28
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AAEtB,iEAAsD;AAA7C,oHAAA,WAAW,OAAA;AAEpB,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAIjB,yCAAuB;AACvB,kDAAgC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AAEtB,iEAAsD;AAA7C,oHAAA,WAAW,OAAA;AAEpB,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAIjB,yCAAuB;AACvB,kDAAgC;AAChC,4CAA0B;AAC1B,yCAAuB"}
@@ -0,0 +1,22 @@
1
+ import type { PropertyParser } from '@rsdk/common';
2
+ /**
3
+ * Options for FsPathParser
4
+ */
5
+ export type FsPathParserOptions = {
6
+ /**
7
+ * How to check if the file/directory exists:
8
+ * - 'strict' - check that exact path exists
9
+ * - 'dirname' - check only that parent directory exists
10
+ *
11
+ * Default: 'strict'
12
+ */
13
+ check?: 'strict' | 'dirname';
14
+ };
15
+ export declare class FsPathParser implements PropertyParser<string> {
16
+ private readonly objectType;
17
+ private readonly options;
18
+ constructor(objectType: 'file' | 'dir', options?: Partial<FsPathParserOptions>);
19
+ type(): string;
20
+ description(): string;
21
+ parse(value: unknown): string;
22
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /* eslint-disable unicorn/no-nested-ternary */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.FsPathParser = void 0;
8
+ const common_1 = require("@rsdk/common");
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const path_1 = require("../path");
12
+ class FsPathParser {
13
+ objectType;
14
+ options;
15
+ constructor(objectType, options) {
16
+ this.objectType = objectType;
17
+ const defaults = {
18
+ check: 'strict',
19
+ };
20
+ this.options = Object.assign(defaults, options || {});
21
+ }
22
+ type() {
23
+ return 'string(fs_path)';
24
+ }
25
+ description() {
26
+ return (0, common_1.text) `
27
+ Extracts path to file or directory. Checks that object exists on
28
+ file system and that application has access to it.
29
+ `;
30
+ }
31
+ parse(value) {
32
+ common_1.Assert.isString(value);
33
+ const [absolutePath, wasRelative] = path_1.Path.absolutize(value);
34
+ const pathToCheck = this.options.check === 'dirname'
35
+ ? node_path_1.default.dirname(absolutePath)
36
+ : absolutePath;
37
+ try {
38
+ if (!(0, node_fs_1.existsSync)(pathToCheck)) {
39
+ throw new Error('not exists');
40
+ }
41
+ (0, node_fs_1.accessSync)(pathToCheck);
42
+ }
43
+ catch {
44
+ const error = [
45
+ this.options.check === 'dirname' || this.objectType === 'dir'
46
+ ? 'Directory'
47
+ : 'File',
48
+ `<${pathToCheck}> not found or can't be accessed!`,
49
+ ];
50
+ if (wasRelative) {
51
+ error.push(' Since you have used relative path, check you current working directory is repos root.');
52
+ }
53
+ throw new Error(error.join(' '));
54
+ }
55
+ const stat = (0, node_fs_1.lstatSync)(pathToCheck);
56
+ /**
57
+ * Otherwise we'll have problems with IsNotDirectoryException
58
+ * when using symlinks.
59
+ */
60
+ if (stat.isSymbolicLink()) {
61
+ return value;
62
+ }
63
+ if (this.options.check === 'dirname' && !stat.isDirectory()) {
64
+ throw new Error(`<${pathToCheck}> is not a directory!`);
65
+ }
66
+ if (this.options.check === 'strict') {
67
+ const ok = this.objectType === 'dir' ? stat.isDirectory() : stat.isFile();
68
+ if (!ok) {
69
+ throw new Error(`<${pathToCheck}> is not a ${this.objectType}!`);
70
+ }
71
+ }
72
+ return value;
73
+ }
74
+ }
75
+ exports.FsPathParser = FsPathParser;
76
+ //# sourceMappingURL=fspath.parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fspath.parser.js","sourceRoot":"","sources":["../../src/parsers/fspath.parser.ts"],"names":[],"mappings":";AAAA,8CAA8C;;;;;;AAG9C,yCAA4C;AAC5C,qCAA4D;AAC5D,0DAA6B;AAE7B,kCAA+B;AAgB/B,MAAa,YAAY;IAIJ;IAHF,OAAO,CAAsB;IAE9C,YACmB,UAA0B,EAC3C,OAAsC;QADrB,eAAU,GAAV,UAAU,CAAgB;QAG3C,MAAM,QAAQ,GAAwB;YACpC,KAAK,EAAE,QAAQ;SAChB,CAAC;QAEF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI;QACF,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,WAAW;QACT,OAAO,IAAA,aAAI,EAAA;;;KAGV,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAc;QAClB,eAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEvB,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,GAAG,WAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAE3D,MAAM,WAAW,GACf,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS;YAC9B,CAAC,CAAC,mBAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YAC5B,CAAC,CAAC,YAAY,CAAC;QAEnB,IAAI,CAAC;YACH,IAAI,CAAC,IAAA,oBAAU,EAAC,WAAW,CAAC,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;YAChC,CAAC;YAED,IAAA,oBAAU,EAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,KAAK,GAAG;gBACZ,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,KAAK,KAAK;oBAC3D,CAAC,CAAC,WAAW;oBACb,CAAC,CAAC,MAAM;gBACV,IAAI,WAAW,mCAAmC;aACnD,CAAC;YAEF,IAAI,WAAW,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CACR,wFAAwF,CACzF,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,IAAI,GAAG,IAAA,mBAAS,EAAC,WAAW,CAAC,CAAC;QAEpC;;;WAGG;QACH,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,IAAI,WAAW,uBAAuB,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAC1E,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,IAAI,WAAW,cAAc,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAjFD,oCAiFC"}
@@ -0,0 +1 @@
1
+ export * from './fspath.parser';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./fspath.parser"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parsers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC"}
package/dist/path.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export declare class Path {
2
+ /**
3
+ * Converts a path to an absolute path
4
+ * @param value - The path to convert (can be relative or absolute)
5
+ * @returns A tuple containing:
6
+ * - The absolute path as a string
7
+ * - A boolean indicating whether the input path was relative (true) or absolute (false)
8
+ */
9
+ static absolutize(value: string): [string, boolean];
10
+ /**
11
+ * Splits a path into directory name and base name components
12
+ * @param value - The path to split
13
+ * @returns A tuple containing:
14
+ * - The directory path as a string
15
+ * - The base filename as a string
16
+ */
17
+ static split(value: string): [string, string];
18
+ }
package/dist/path.js ADDED
@@ -0,0 +1,36 @@
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.Path = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ class Path {
9
+ /**
10
+ * Converts a path to an absolute path
11
+ * @param value - The path to convert (can be relative or absolute)
12
+ * @returns A tuple containing:
13
+ * - The absolute path as a string
14
+ * - A boolean indicating whether the input path was relative (true) or absolute (false)
15
+ */
16
+ static absolutize(value) {
17
+ const normalizedPath = node_path_1.default.normalize(value);
18
+ const isAbsolute = node_path_1.default.isAbsolute(normalizedPath);
19
+ const absolutePath = isAbsolute
20
+ ? normalizedPath
21
+ : node_path_1.default.join(process.cwd(), normalizedPath);
22
+ return [absolutePath, !isAbsolute];
23
+ }
24
+ /**
25
+ * Splits a path into directory name and base name components
26
+ * @param value - The path to split
27
+ * @returns A tuple containing:
28
+ * - The directory path as a string
29
+ * - The base filename as a string
30
+ */
31
+ static split(value) {
32
+ return [node_path_1.default.dirname(value), node_path_1.default.basename(value)];
33
+ }
34
+ }
35
+ exports.Path = Path;
36
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAE7B,MAAa,IAAI;IACf;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,KAAa;QAC7B,MAAM,cAAc,GAAG,mBAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,mBAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,UAAU;YAC7B,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,mBAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;QAE7C,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,KAAa;QACxB,OAAO,CAAC,mBAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,mBAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,CAAC;CACF;AA5BD,oBA4BC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsdk/common.node",
3
- "version": "5.7.0-next.6",
3
+ "version": "6.0.0-next.1",
4
4
  "description": "Useful common classes, functions and types",
5
5
  "license": "Apache License 2.0",
6
6
  "publishConfig": {
@@ -14,12 +14,11 @@
14
14
  "prepublishOnly": "npm run build"
15
15
  },
16
16
  "dependencies": {
17
- "dotenv": "^16.0.0",
17
+ "@rsdk/common": "6.0.0-next.1",
18
+ "dotenv": "^16.3.1",
19
+ "rxjs": "^7.8.1",
18
20
  "toml": "^3.0.0",
19
21
  "yaml": "^2.6.1"
20
22
  },
21
- "peerDependencies": {
22
- "rxjs": "^7.1.0"
23
- },
24
- "gitHead": "287622c55e8717861544f0be502bb37a6b19bbfb"
23
+ "gitHead": "3114a76df17cf98d6f3cbb8a931599a883af6783"
25
24
  }
package/src/index.ts CHANGED
@@ -8,3 +8,5 @@ export { MaybeReadonlyArray } from './types';
8
8
 
9
9
  export * from './misc';
10
10
  export * from './serialization';
11
+ export * from './parsers';
12
+ export * from './path';
@@ -0,0 +1,105 @@
1
+ /* eslint-disable unicorn/no-nested-ternary */
2
+
3
+ import type { PropertyParser } from '@rsdk/common';
4
+ import { Assert, text } from '@rsdk/common';
5
+ import { accessSync, existsSync, lstatSync } from 'node:fs';
6
+ import path from 'node:path';
7
+
8
+ import { Path } from '../path';
9
+
10
+ /**
11
+ * Options for FsPathParser
12
+ */
13
+ export type FsPathParserOptions = {
14
+ /**
15
+ * How to check if the file/directory exists:
16
+ * - 'strict' - check that exact path exists
17
+ * - 'dirname' - check only that parent directory exists
18
+ *
19
+ * Default: 'strict'
20
+ */
21
+ check?: 'strict' | 'dirname';
22
+ };
23
+
24
+ export class FsPathParser implements PropertyParser<string> {
25
+ private readonly options: FsPathParserOptions;
26
+
27
+ constructor(
28
+ private readonly objectType: 'file' | 'dir',
29
+ options?: Partial<FsPathParserOptions>,
30
+ ) {
31
+ const defaults: FsPathParserOptions = {
32
+ check: 'strict',
33
+ };
34
+
35
+ this.options = Object.assign(defaults, options || {});
36
+ }
37
+
38
+ type(): string {
39
+ return 'string(fs_path)';
40
+ }
41
+
42
+ description(): string {
43
+ return text`
44
+ Extracts path to file or directory. Checks that object exists on
45
+ file system and that application has access to it.
46
+ `;
47
+ }
48
+
49
+ parse(value: unknown): string {
50
+ Assert.isString(value);
51
+
52
+ const [absolutePath, wasRelative] = Path.absolutize(value);
53
+
54
+ const pathToCheck =
55
+ this.options.check === 'dirname'
56
+ ? path.dirname(absolutePath)
57
+ : absolutePath;
58
+
59
+ try {
60
+ if (!existsSync(pathToCheck)) {
61
+ throw new Error('not exists');
62
+ }
63
+
64
+ accessSync(pathToCheck);
65
+ } catch {
66
+ const error = [
67
+ this.options.check === 'dirname' || this.objectType === 'dir'
68
+ ? 'Directory'
69
+ : 'File',
70
+ `<${pathToCheck}> not found or can't be accessed!`,
71
+ ];
72
+
73
+ if (wasRelative) {
74
+ error.push(
75
+ ' Since you have used relative path, check you current working directory is repos root.',
76
+ );
77
+ }
78
+
79
+ throw new Error(error.join(' '));
80
+ }
81
+
82
+ const stat = lstatSync(pathToCheck);
83
+
84
+ /**
85
+ * Otherwise we'll have problems with IsNotDirectoryException
86
+ * when using symlinks.
87
+ */
88
+ if (stat.isSymbolicLink()) {
89
+ return value;
90
+ }
91
+
92
+ if (this.options.check === 'dirname' && !stat.isDirectory()) {
93
+ throw new Error(`<${pathToCheck}> is not a directory!`);
94
+ }
95
+
96
+ if (this.options.check === 'strict') {
97
+ const ok = this.objectType === 'dir' ? stat.isDirectory() : stat.isFile();
98
+ if (!ok) {
99
+ throw new Error(`<${pathToCheck}> is not a ${this.objectType}!`);
100
+ }
101
+ }
102
+
103
+ return value;
104
+ }
105
+ }
@@ -0,0 +1 @@
1
+ export * from './fspath.parser';
package/src/path.ts ADDED
@@ -0,0 +1,31 @@
1
+ import path from 'node:path';
2
+
3
+ export class Path {
4
+ /**
5
+ * Converts a path to an absolute path
6
+ * @param value - The path to convert (can be relative or absolute)
7
+ * @returns A tuple containing:
8
+ * - The absolute path as a string
9
+ * - A boolean indicating whether the input path was relative (true) or absolute (false)
10
+ */
11
+ static absolutize(value: string): [string, boolean] {
12
+ const normalizedPath = path.normalize(value);
13
+ const isAbsolute = path.isAbsolute(normalizedPath);
14
+ const absolutePath = isAbsolute
15
+ ? normalizedPath
16
+ : path.join(process.cwd(), normalizedPath);
17
+
18
+ return [absolutePath, !isAbsolute];
19
+ }
20
+
21
+ /**
22
+ * Splits a path into directory name and base name components
23
+ * @param value - The path to split
24
+ * @returns A tuple containing:
25
+ * - The directory path as a string
26
+ * - The base filename as a string
27
+ */
28
+ static split(value: string): [string, string] {
29
+ return [path.dirname(value), path.basename(value)];
30
+ }
31
+ }