@zokugun/fs-path 0.1.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.
Files changed (67) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +153 -0
  3. package/lib/cjs/absolute.cjs +6 -0
  4. package/lib/cjs/absolute.d.cts +3 -0
  5. package/lib/cjs/dir.cjs +6 -0
  6. package/lib/cjs/dir.d.cts +3 -0
  7. package/lib/cjs/index.cjs +50 -0
  8. package/lib/cjs/index.d.cts +47 -0
  9. package/lib/cjs/is-in-dir.cjs +18 -0
  10. package/lib/cjs/is-in-dir.d.cts +3 -0
  11. package/lib/cjs/is-in-dirs.cjs +38 -0
  12. package/lib/cjs/is-in-dirs.d.cts +3 -0
  13. package/lib/cjs/is-safe-path.cjs +42 -0
  14. package/lib/cjs/is-safe-path.d.cts +8 -0
  15. package/lib/cjs/is-safe-segment.cjs +27 -0
  16. package/lib/cjs/is-safe-segment.d.cts +4 -0
  17. package/lib/cjs/join.cjs +14 -0
  18. package/lib/cjs/join.d.cts +3 -0
  19. package/lib/cjs/parent.cjs +14 -0
  20. package/lib/cjs/parent.d.cts +3 -0
  21. package/lib/cjs/platform.cjs +67 -0
  22. package/lib/cjs/platform.d.cts +2 -0
  23. package/lib/cjs/resolve.cjs +42 -0
  24. package/lib/cjs/resolve.d.cts +3 -0
  25. package/lib/cjs/sanitize.cjs +62 -0
  26. package/lib/cjs/sanitize.d.cts +10 -0
  27. package/lib/cjs/types.cjs +2 -0
  28. package/lib/cjs/types.d.cts +34 -0
  29. package/lib/cjs/untildify.cjs +25 -0
  30. package/lib/cjs/untildify.d.cts +3 -0
  31. package/lib/cjs/utils/get-home.cjs +12 -0
  32. package/lib/cjs/utils/get-home.d.cts +1 -0
  33. package/lib/cjs/utils/get-user-home.cjs +18 -0
  34. package/lib/cjs/utils/get-user-home.d.cts +1 -0
  35. package/lib/esm/absolute.d.mts +3 -0
  36. package/lib/esm/absolute.mjs +3 -0
  37. package/lib/esm/dir.d.mts +3 -0
  38. package/lib/esm/dir.mjs +3 -0
  39. package/lib/esm/index.d.mts +47 -0
  40. package/lib/esm/index.mjs +29 -0
  41. package/lib/esm/is-in-dir.d.mts +3 -0
  42. package/lib/esm/is-in-dir.mjs +15 -0
  43. package/lib/esm/is-in-dirs.d.mts +3 -0
  44. package/lib/esm/is-in-dirs.mjs +35 -0
  45. package/lib/esm/is-safe-path.d.mts +8 -0
  46. package/lib/esm/is-safe-path.mjs +36 -0
  47. package/lib/esm/is-safe-segment.d.mts +4 -0
  48. package/lib/esm/is-safe-segment.mjs +21 -0
  49. package/lib/esm/join.d.mts +3 -0
  50. package/lib/esm/join.mjs +11 -0
  51. package/lib/esm/parent.d.mts +3 -0
  52. package/lib/esm/parent.mjs +11 -0
  53. package/lib/esm/platform.d.mts +2 -0
  54. package/lib/esm/platform.mjs +61 -0
  55. package/lib/esm/resolve.d.mts +3 -0
  56. package/lib/esm/resolve.mjs +36 -0
  57. package/lib/esm/sanitize.d.mts +10 -0
  58. package/lib/esm/sanitize.mjs +56 -0
  59. package/lib/esm/types.d.mts +34 -0
  60. package/lib/esm/types.mjs +1 -0
  61. package/lib/esm/untildify.d.mts +3 -0
  62. package/lib/esm/untildify.mjs +22 -0
  63. package/lib/esm/utils/get-home.d.mts +1 -0
  64. package/lib/esm/utils/get-home.mjs +6 -0
  65. package/lib/esm/utils/get-user-home.d.mts +1 -0
  66. package/lib/esm/utils/get-user-home.mjs +12 -0
  67. package/package.json +83 -0
@@ -0,0 +1,62 @@
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.sanitize = sanitize;
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ const fs_path_sanitize_1 = require("@zokugun/fs-path-sanitize");
9
+ const is_it_type_1 = require("@zokugun/is-it-type");
10
+ const xtry_1 = require("@zokugun/xtry");
11
+ function sanitize(_nodePath, localPath) {
12
+ let target;
13
+ if (localPath.separator === '\\') {
14
+ target = 'windows.safe';
15
+ }
16
+ else {
17
+ const system = node_os_1.default.platform();
18
+ target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
19
+ }
20
+ const sanitizer = fs_path_sanitize_1.Sanitizer.getInstance(target);
21
+ return (path, options = {}) => {
22
+ const resolvedPath = localPath.resolve(path);
23
+ let parents;
24
+ if ((0, is_it_type_1.isString)(options.parent)) {
25
+ parents = [options.parent];
26
+ }
27
+ if ((0, is_it_type_1.isString)(options.parents)) {
28
+ parents = [options.parents];
29
+ }
30
+ else if ((0, is_it_type_1.isArray)(options.parents)) {
31
+ parents = options.parents;
32
+ }
33
+ let sanitizedPath;
34
+ if (!options.target || options.target === 'auto') {
35
+ sanitizedPath = sanitizer.sanitizePath(resolvedPath, {
36
+ absolute: true,
37
+ replacement: options.replacement,
38
+ });
39
+ }
40
+ else {
41
+ sanitizedPath = (0, fs_path_sanitize_1.sanitizePath)(resolvedPath, {
42
+ absolute: true,
43
+ replacement: options.replacement,
44
+ target: options.target,
45
+ });
46
+ }
47
+ if (sanitizedPath.fails) {
48
+ return sanitizedPath;
49
+ }
50
+ if (parents) {
51
+ if (localPath.isInDirs(sanitizedPath.value, parents)) {
52
+ return sanitizedPath;
53
+ }
54
+ else {
55
+ return (0, xtry_1.err)('Invalid path: not within allowed parents');
56
+ }
57
+ }
58
+ else {
59
+ return sanitizedPath;
60
+ }
61
+ };
62
+ }
@@ -0,0 +1,10 @@
1
+ import type path from 'node:path';
2
+ import { type Target } from '@zokugun/fs-path-sanitize';
3
+ import { type DResult } from '@zokugun/xtry';
4
+ import { type PlatformPath } from './types.cjs';
5
+ export declare function sanitize(_nodePath: path.PlatformPath, localPath: PlatformPath): (path: string, options?: {
6
+ parent?: string | null;
7
+ parents?: string | string[] | null;
8
+ replacement?: string | null;
9
+ target?: Target | 'auto';
10
+ }) => DResult<string>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,34 @@
1
+ import { type Target } from '@zokugun/fs-path-sanitize';
2
+ import { type DResult } from '@zokugun/xtry';
3
+ export type PlatformPath = {
4
+ readonly delimiter: ';' | ':';
5
+ readonly separator: '\\' | '/';
6
+ readonly posix: PlatformPath;
7
+ readonly win32: PlatformPath;
8
+ absolute: (...paths: string[]) => string;
9
+ dir: (path: string) => string;
10
+ extension: (path: string) => string;
11
+ isAbsolute: (path: string) => boolean;
12
+ isInDir: (file: string, dir: string) => boolean;
13
+ isInDirs: (file: string, directories: string[]) => boolean;
14
+ isSafePath: (path: string, options?: {
15
+ parent?: string | null;
16
+ parents?: string | string[] | null;
17
+ target?: Target | 'auto';
18
+ }) => boolean;
19
+ isSafeSegment: (segment: string, target?: Target | 'auto') => boolean;
20
+ join: (...paths: string[]) => string;
21
+ leaf: (path: string, suffix?: string) => string;
22
+ matchesGlob?: (path: string, pattern: string) => boolean;
23
+ normalize: (path: string) => string;
24
+ parent: (file: string) => string;
25
+ relative: (from: string, to: string) => string;
26
+ resolve: (...paths: string[]) => string;
27
+ sanitize: (path: string, options?: {
28
+ parent?: string | null;
29
+ parents?: string | string[] | null;
30
+ replacement?: string | null;
31
+ target?: Target | 'auto';
32
+ }) => DResult<string>;
33
+ untildify: (path: string) => string;
34
+ };
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.untildify = untildify;
4
+ const is_it_type_1 = require("@zokugun/is-it-type");
5
+ const get_home_js_1 = require("./utils/get-home.cjs");
6
+ const get_user_home_js_1 = require("./utils/get-user-home.cjs");
7
+ const TILDE_REGEX = /^~(?=$|\/|\\)/;
8
+ const USER_REGEX = /^~([^/\\]+)(.*)$/;
9
+ function untildify(_nodePath, _localPath) {
10
+ return (path) => {
11
+ const homedir = (0, get_home_js_1.getHome)();
12
+ if ((0, is_it_type_1.isString)(homedir) && TILDE_REGEX.test(path)) {
13
+ return homedir + path.slice(1);
14
+ }
15
+ const match = USER_REGEX.exec(path);
16
+ if (match) {
17
+ const [, username, rest] = match;
18
+ const userHome = (0, get_user_home_js_1.getUserHome)(username);
19
+ if ((0, is_it_type_1.isString)(userHome)) {
20
+ return userHome + rest;
21
+ }
22
+ }
23
+ return path;
24
+ };
25
+ }
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.cjs';
3
+ export declare function untildify(_nodePath: path.PlatformPath, _localPath: PlatformPath): (path: string) => string;
@@ -0,0 +1,12 @@
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.getHome = getHome;
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ let $home;
9
+ function getHome() {
10
+ $home ??= node_os_1.default.homedir();
11
+ return $home;
12
+ }
@@ -0,0 +1 @@
1
+ export declare function getHome(): string;
@@ -0,0 +1,18 @@
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.getUserHome = getUserHome;
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ const get_home_js_1 = require("./get-home.cjs");
9
+ let $username;
10
+ function getUserHome(username) {
11
+ $username ??= node_os_1.default.userInfo().username;
12
+ if (username === $username) {
13
+ return (0, get_home_js_1.getHome)();
14
+ }
15
+ else {
16
+ return null;
17
+ }
18
+ }
@@ -0,0 +1 @@
1
+ export declare function getUserHome(username: string): string | null;
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function absolute(nodePath: path.PlatformPath, localPath: PlatformPath): (...paths: string[]) => string;
@@ -0,0 +1,3 @@
1
+ export function absolute(nodePath, localPath) {
2
+ return (...paths) => nodePath.resolve(localPath.resolve(...paths));
3
+ }
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function dir(nodePath: path.PlatformPath, _localPath: PlatformPath): (path: string) => string;
@@ -0,0 +1,3 @@
1
+ export function dir(nodePath, _localPath) {
2
+ return (path) => nodePath.parse(path).dir;
3
+ }
@@ -0,0 +1,47 @@
1
+ import { type PlatformPath } from './types.mjs';
2
+ declare const absolute: (...paths: string[]) => string, delimiter: ";" | ":", extension: (path: string) => string, isAbsolute: (path: string) => boolean, join: (...paths: string[]) => string, leaf: (path: string, suffix?: string) => string, matchesGlob: ((path: string, pattern: string) => boolean) | undefined, normalize: (path: string) => string, parent: (file: string) => string, isInDir: (file: string, dir: string) => boolean, isInDirs: (file: string, directories: string[]) => boolean, isSafePath: (path: string, options?: {
3
+ parent?: string | null;
4
+ parents?: string | string[] | null;
5
+ target?: Target | "auto";
6
+ }) => boolean, isSafeSegment: (segment: string, target?: Target | "auto") => boolean, posix: PlatformPath, relative: (from: string, to: string) => string, resolve: (...paths: string[]) => string, sanitize: (path: string, options?: {
7
+ parent?: string | null;
8
+ parents?: string | string[] | null;
9
+ replacement?: string | null;
10
+ target?: Target | "auto";
11
+ }) => DResult<string>, separator: "\\" | "/", untildify: (path: string) => string, win32: PlatformPath;
12
+ export { type PlatformPath, absolute, delimiter, extension, isAbsolute, join, leaf, matchesGlob, normalize, parent, isInDir, isInDirs, isSafePath, isSafeSegment, posix, relative, resolve, sanitize, separator, untildify, win32, };
13
+ import { type Target } from "@zokugun/fs-path-sanitize";
14
+ import { type DResult } from "@zokugun/xtry";
15
+ declare const _default: {
16
+ PlatformPath: PlatformPath;
17
+ absolute: (...paths: string[]) => string;
18
+ delimiter: ";" | ":";
19
+ extension: (path: string) => string;
20
+ isAbsolute: (path: string) => boolean;
21
+ join: (...paths: string[]) => string;
22
+ leaf: (path: string, suffix?: string) => string;
23
+ matchesGlob: ((path: string, pattern: string) => boolean) | undefined;
24
+ normalize: (path: string) => string;
25
+ parent: (file: string) => string;
26
+ isInDir: (file: string, dir: string) => boolean;
27
+ isInDirs: (file: string, directories: string[]) => boolean;
28
+ isSafePath: (path: string, options?: {
29
+ parent?: string | null;
30
+ parents?: string | string[] | null;
31
+ target?: Target | "auto";
32
+ }) => boolean;
33
+ isSafeSegment: (segment: string, target?: Target | "auto") => boolean;
34
+ posix: PlatformPath;
35
+ relative: (from: string, to: string) => string;
36
+ resolve: (...paths: string[]) => string;
37
+ sanitize: (path: string, options?: {
38
+ parent?: string | null;
39
+ parents?: string | string[] | null;
40
+ replacement?: string | null;
41
+ target?: Target | "auto";
42
+ }) => DResult<string>;
43
+ separator: "\\" | "/";
44
+ untildify: (path: string) => string;
45
+ win32: PlatformPath;
46
+ };
47
+ export default _default;
@@ -0,0 +1,29 @@
1
+ import { DEFAULT_PLATFORM } from './platform.mjs';
2
+ const { absolute, delimiter, extension, isAbsolute, join, leaf, matchesGlob, normalize, parent, isInDir, isInDirs, isSafePath, isSafeSegment, posix, relative, resolve, sanitize, separator, untildify, win32, } = DEFAULT_PLATFORM;
3
+ /* eslint-disable unicorn/prefer-export-from */
4
+ export { absolute, delimiter, extension, isAbsolute, join, leaf, matchesGlob, normalize, parent, isInDir, isInDirs, isSafePath, isSafeSegment, posix, relative, resolve, sanitize, separator, untildify, win32, };
5
+ /* eslint-enable unicorn/prefer-export-from */
6
+ // eslint-disable-next-line import/no-anonymous-default-export
7
+ export default {
8
+ PlatformPath: undefined,
9
+ absolute,
10
+ delimiter,
11
+ extension,
12
+ isAbsolute,
13
+ join,
14
+ leaf,
15
+ matchesGlob,
16
+ normalize,
17
+ parent,
18
+ isInDir,
19
+ isInDirs,
20
+ isSafePath,
21
+ isSafeSegment,
22
+ posix,
23
+ relative,
24
+ resolve,
25
+ sanitize,
26
+ separator,
27
+ untildify,
28
+ win32,
29
+ };
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function isInDir(_nodePath: path.PlatformPath, localPath: PlatformPath): (path: string, parent: string) => boolean;
@@ -0,0 +1,15 @@
1
+ export function isInDir(_nodePath, localPath) {
2
+ return (path, parent) => {
3
+ let resolvedPath = localPath.resolve(path);
4
+ let resolvedParent = localPath.resolve(parent);
5
+ if (localPath.separator === '\\') {
6
+ resolvedPath = resolvedPath.toLowerCase();
7
+ resolvedParent = resolvedParent.toLowerCase();
8
+ }
9
+ if (resolvedPath === resolvedParent) {
10
+ return true;
11
+ }
12
+ const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
13
+ return resolvedPath.startsWith(suffixedParent);
14
+ };
15
+ }
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function isInDirs(_nodePath: path.PlatformPath, localPath: PlatformPath): (path: string, parents: string[]) => boolean;
@@ -0,0 +1,35 @@
1
+ // eslint-disable-next-line unicorn/prevent-abbreviations
2
+ export function isInDirs(_nodePath, localPath) {
3
+ if (localPath.separator === '\\') {
4
+ return (path, parents) => {
5
+ const resolvedPath = localPath.resolve(path).toLowerCase();
6
+ for (const parent of parents) {
7
+ const resolvedParent = localPath.resolve(parent).toLowerCase();
8
+ if (resolvedPath === resolvedParent) {
9
+ return true;
10
+ }
11
+ const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
12
+ if (resolvedPath.startsWith(suffixedParent)) {
13
+ return true;
14
+ }
15
+ }
16
+ return false;
17
+ };
18
+ }
19
+ else {
20
+ return (path, parents) => {
21
+ const resolvedPath = localPath.resolve(path);
22
+ for (const parent of parents) {
23
+ const resolvedParent = localPath.resolve(parent);
24
+ if (resolvedPath === resolvedParent) {
25
+ return true;
26
+ }
27
+ const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
28
+ if (resolvedPath.startsWith(suffixedParent)) {
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ };
34
+ }
35
+ }
@@ -0,0 +1,8 @@
1
+ import type path from 'node:path';
2
+ import { type Target } from '@zokugun/fs-path-sanitize';
3
+ import { type PlatformPath } from './types.mjs';
4
+ export declare function isSafePath(_nodePath: path.PlatformPath, localPath: PlatformPath): (path: string, options?: {
5
+ parent?: string | null;
6
+ parents?: string | string[] | null;
7
+ target?: Target | 'auto';
8
+ }) => boolean;
@@ -0,0 +1,36 @@
1
+ import os from 'node:os';
2
+ import { isSafePath as isSafe, Sanitizer } from '@zokugun/fs-path-sanitize';
3
+ import { isArray, isString } from '@zokugun/is-it-type';
4
+ export function isSafePath(_nodePath, localPath) {
5
+ let target;
6
+ if (localPath.separator === '\\') {
7
+ target = 'windows.safe';
8
+ }
9
+ else {
10
+ const system = os.platform();
11
+ target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
12
+ }
13
+ const sanitizer = Sanitizer.getInstance(target);
14
+ return (path, options = {}) => {
15
+ let parents;
16
+ if (isString(options.parent)) {
17
+ parents = [options.parent];
18
+ }
19
+ if (isString(options.parents)) {
20
+ parents = [options.parents];
21
+ }
22
+ else if (isArray(options.parents)) {
23
+ parents = options.parents;
24
+ }
25
+ const safe = !options.target || options.target === 'auto' ? sanitizer.isSafePath(path) : isSafe(path, target);
26
+ if (!safe) {
27
+ return false;
28
+ }
29
+ else if (parents) {
30
+ return localPath.isInDirs(path, parents);
31
+ }
32
+ else {
33
+ return true;
34
+ }
35
+ };
36
+ }
@@ -0,0 +1,4 @@
1
+ import type path from 'node:path';
2
+ import { type Target } from '@zokugun/fs-path-sanitize';
3
+ import { type PlatformPath } from './types.mjs';
4
+ export declare function isSafeSegment(_nodePath: path.PlatformPath, localPath: PlatformPath): (segment: string, target?: Target | 'auto') => boolean;
@@ -0,0 +1,21 @@
1
+ import os from 'node:os';
2
+ import { isSafeSegment as isSafe, Sanitizer } from '@zokugun/fs-path-sanitize';
3
+ export function isSafeSegment(_nodePath, localPath) {
4
+ let target;
5
+ if (localPath.separator === '\\') {
6
+ target = 'windows.safe';
7
+ }
8
+ else {
9
+ const system = os.platform();
10
+ target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
11
+ }
12
+ const sanitizer = Sanitizer.getInstance(target);
13
+ return (segment, target) => {
14
+ if (!target || target === 'auto') {
15
+ return sanitizer.isSafePath(segment);
16
+ }
17
+ else {
18
+ return isSafe(segment, target);
19
+ }
20
+ };
21
+ }
@@ -0,0 +1,3 @@
1
+ import type path from 'path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function join(nodePath: path.PlatformPath, _localPath: PlatformPath): (...paths: string[]) => string;
@@ -0,0 +1,11 @@
1
+ export function join(nodePath, _localPath) {
2
+ return (...paths) => {
3
+ const joined = nodePath.join(...paths);
4
+ if (joined === '.') {
5
+ return '';
6
+ }
7
+ else {
8
+ return joined;
9
+ }
10
+ };
11
+ }
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function parent(nodePath: path.PlatformPath, _localPath: PlatformPath): (file: string) => string;
@@ -0,0 +1,11 @@
1
+ export function parent(nodePath, _localPath) {
2
+ return (file) => {
3
+ const parent = nodePath.dirname(file);
4
+ if (parent === '.') {
5
+ return '';
6
+ }
7
+ else {
8
+ return parent;
9
+ }
10
+ };
11
+ }
@@ -0,0 +1,2 @@
1
+ import { type PlatformPath } from './types.mjs';
2
+ export declare const DEFAULT_PLATFORM: PlatformPath;
@@ -0,0 +1,61 @@
1
+ import path from 'node:path';
2
+ import { absolute } from './absolute.mjs';
3
+ import { dir } from './dir.mjs';
4
+ import { isInDir } from './is-in-dir.mjs';
5
+ // eslint-disable-next-line unicorn/prevent-abbreviations
6
+ import { isInDirs } from './is-in-dirs.mjs';
7
+ import { isSafePath } from './is-safe-path.mjs';
8
+ import { isSafeSegment } from './is-safe-segment.mjs';
9
+ import { join } from './join.mjs';
10
+ import { parent } from './parent.mjs';
11
+ import { resolve } from './resolve.mjs';
12
+ import { sanitize } from './sanitize.mjs';
13
+ import { untildify } from './untildify.mjs';
14
+ function buildPlatform(path) {
15
+ const { basename: leaf, delimiter, extname: extension, isAbsolute, normalize, relative, sep: separator, } = path;
16
+ const result = {
17
+ delimiter,
18
+ separator,
19
+ extension,
20
+ isAbsolute,
21
+ leaf,
22
+ matchesGlob: path.matchesGlob ?? undefined,
23
+ normalize,
24
+ relative,
25
+ };
26
+ result.absolute = absolute(path, result);
27
+ result.dir = dir(path, result);
28
+ result.isInDir = isInDir(path, result);
29
+ result.isInDirs = isInDirs(path, result);
30
+ result.isSafePath = isSafePath(path, result);
31
+ result.isSafeSegment = isSafeSegment(path, result);
32
+ result.join = join(path, result);
33
+ result.parent = parent(path, result);
34
+ result.resolve = resolve(path, result);
35
+ result.sanitize = sanitize(path, result);
36
+ result.untildify = untildify(path, result);
37
+ return result;
38
+ }
39
+ const POSIX_PLATFORM = buildPlatform(path.posix);
40
+ const WIN32_PLATFORM = buildPlatform(path.win32);
41
+ Object.defineProperties(POSIX_PLATFORM, {
42
+ posix: {
43
+ value: POSIX_PLATFORM,
44
+ writable: false,
45
+ },
46
+ win32: {
47
+ value: WIN32_PLATFORM,
48
+ writable: false,
49
+ },
50
+ });
51
+ Object.defineProperties(WIN32_PLATFORM, {
52
+ posix: {
53
+ value: POSIX_PLATFORM,
54
+ writable: false,
55
+ },
56
+ win32: {
57
+ value: WIN32_PLATFORM,
58
+ writable: false,
59
+ },
60
+ });
61
+ export const DEFAULT_PLATFORM = (path === path.posix ? POSIX_PLATFORM : WIN32_PLATFORM);
@@ -0,0 +1,3 @@
1
+ import type path from 'node:path';
2
+ import { type PlatformPath } from './types.mjs';
3
+ export declare function resolve(nodePath: path.PlatformPath, _localPath: PlatformPath): (...paths: string[]) => string;
@@ -0,0 +1,36 @@
1
+ import process from 'node:process';
2
+ import { isString } from '@zokugun/is-it-type';
3
+ import { getHome } from './utils/get-home.mjs';
4
+ import { getUserHome } from './utils/get-user-home.mjs';
5
+ const TILDE_REGEX = /^~(?=$|\/|\\)/;
6
+ const USER_REGEX = /^~([^/\\]+)(.*)$/;
7
+ export function resolve(nodePath, _localPath) {
8
+ return (...paths) => {
9
+ if (paths.length === 0) {
10
+ return process.cwd();
11
+ }
12
+ else if (nodePath.isAbsolute(paths[0])) {
13
+ return nodePath.normalize(nodePath.join(...paths));
14
+ }
15
+ else if (TILDE_REGEX.test(paths[0])) {
16
+ const homedir = getHome();
17
+ if (isString(homedir)) {
18
+ paths.shift();
19
+ return nodePath.normalize(nodePath.join(homedir, ...paths));
20
+ }
21
+ }
22
+ else {
23
+ const match = USER_REGEX.exec(paths[0]);
24
+ if (match) {
25
+ const [, username, rest] = match;
26
+ const userHome = getUserHome(username);
27
+ if (isString(userHome)) {
28
+ paths.shift();
29
+ return nodePath.normalize(nodePath.join(userHome + rest, ...paths));
30
+ }
31
+ }
32
+ }
33
+ paths.unshift();
34
+ return nodePath.normalize(nodePath.join(process.cwd(), ...paths));
35
+ };
36
+ }
@@ -0,0 +1,10 @@
1
+ import type path from 'node:path';
2
+ import { type Target } from '@zokugun/fs-path-sanitize';
3
+ import { type DResult } from '@zokugun/xtry';
4
+ import { type PlatformPath } from './types.mjs';
5
+ export declare function sanitize(_nodePath: path.PlatformPath, localPath: PlatformPath): (path: string, options?: {
6
+ parent?: string | null;
7
+ parents?: string | string[] | null;
8
+ replacement?: string | null;
9
+ target?: Target | 'auto';
10
+ }) => DResult<string>;
@@ -0,0 +1,56 @@
1
+ import os from 'node:os';
2
+ import { sanitizePath, Sanitizer } from '@zokugun/fs-path-sanitize';
3
+ import { isArray, isString } from '@zokugun/is-it-type';
4
+ import { err } from '@zokugun/xtry';
5
+ export function sanitize(_nodePath, localPath) {
6
+ let target;
7
+ if (localPath.separator === '\\') {
8
+ target = 'windows.safe';
9
+ }
10
+ else {
11
+ const system = os.platform();
12
+ target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
13
+ }
14
+ const sanitizer = Sanitizer.getInstance(target);
15
+ return (path, options = {}) => {
16
+ const resolvedPath = localPath.resolve(path);
17
+ let parents;
18
+ if (isString(options.parent)) {
19
+ parents = [options.parent];
20
+ }
21
+ if (isString(options.parents)) {
22
+ parents = [options.parents];
23
+ }
24
+ else if (isArray(options.parents)) {
25
+ parents = options.parents;
26
+ }
27
+ let sanitizedPath;
28
+ if (!options.target || options.target === 'auto') {
29
+ sanitizedPath = sanitizer.sanitizePath(resolvedPath, {
30
+ absolute: true,
31
+ replacement: options.replacement,
32
+ });
33
+ }
34
+ else {
35
+ sanitizedPath = sanitizePath(resolvedPath, {
36
+ absolute: true,
37
+ replacement: options.replacement,
38
+ target: options.target,
39
+ });
40
+ }
41
+ if (sanitizedPath.fails) {
42
+ return sanitizedPath;
43
+ }
44
+ if (parents) {
45
+ if (localPath.isInDirs(sanitizedPath.value, parents)) {
46
+ return sanitizedPath;
47
+ }
48
+ else {
49
+ return err('Invalid path: not within allowed parents');
50
+ }
51
+ }
52
+ else {
53
+ return sanitizedPath;
54
+ }
55
+ };
56
+ }