@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.
- package/LICENSE +22 -0
- package/README.md +153 -0
- package/lib/cjs/absolute.cjs +6 -0
- package/lib/cjs/absolute.d.cts +3 -0
- package/lib/cjs/dir.cjs +6 -0
- package/lib/cjs/dir.d.cts +3 -0
- package/lib/cjs/index.cjs +50 -0
- package/lib/cjs/index.d.cts +47 -0
- package/lib/cjs/is-in-dir.cjs +18 -0
- package/lib/cjs/is-in-dir.d.cts +3 -0
- package/lib/cjs/is-in-dirs.cjs +38 -0
- package/lib/cjs/is-in-dirs.d.cts +3 -0
- package/lib/cjs/is-safe-path.cjs +42 -0
- package/lib/cjs/is-safe-path.d.cts +8 -0
- package/lib/cjs/is-safe-segment.cjs +27 -0
- package/lib/cjs/is-safe-segment.d.cts +4 -0
- package/lib/cjs/join.cjs +14 -0
- package/lib/cjs/join.d.cts +3 -0
- package/lib/cjs/parent.cjs +14 -0
- package/lib/cjs/parent.d.cts +3 -0
- package/lib/cjs/platform.cjs +67 -0
- package/lib/cjs/platform.d.cts +2 -0
- package/lib/cjs/resolve.cjs +42 -0
- package/lib/cjs/resolve.d.cts +3 -0
- package/lib/cjs/sanitize.cjs +62 -0
- package/lib/cjs/sanitize.d.cts +10 -0
- package/lib/cjs/types.cjs +2 -0
- package/lib/cjs/types.d.cts +34 -0
- package/lib/cjs/untildify.cjs +25 -0
- package/lib/cjs/untildify.d.cts +3 -0
- package/lib/cjs/utils/get-home.cjs +12 -0
- package/lib/cjs/utils/get-home.d.cts +1 -0
- package/lib/cjs/utils/get-user-home.cjs +18 -0
- package/lib/cjs/utils/get-user-home.d.cts +1 -0
- package/lib/esm/absolute.d.mts +3 -0
- package/lib/esm/absolute.mjs +3 -0
- package/lib/esm/dir.d.mts +3 -0
- package/lib/esm/dir.mjs +3 -0
- package/lib/esm/index.d.mts +47 -0
- package/lib/esm/index.mjs +29 -0
- package/lib/esm/is-in-dir.d.mts +3 -0
- package/lib/esm/is-in-dir.mjs +15 -0
- package/lib/esm/is-in-dirs.d.mts +3 -0
- package/lib/esm/is-in-dirs.mjs +35 -0
- package/lib/esm/is-safe-path.d.mts +8 -0
- package/lib/esm/is-safe-path.mjs +36 -0
- package/lib/esm/is-safe-segment.d.mts +4 -0
- package/lib/esm/is-safe-segment.mjs +21 -0
- package/lib/esm/join.d.mts +3 -0
- package/lib/esm/join.mjs +11 -0
- package/lib/esm/parent.d.mts +3 -0
- package/lib/esm/parent.mjs +11 -0
- package/lib/esm/platform.d.mts +2 -0
- package/lib/esm/platform.mjs +61 -0
- package/lib/esm/resolve.d.mts +3 -0
- package/lib/esm/resolve.mjs +36 -0
- package/lib/esm/sanitize.d.mts +10 -0
- package/lib/esm/sanitize.mjs +56 -0
- package/lib/esm/types.d.mts +34 -0
- package/lib/esm/types.mjs +1 -0
- package/lib/esm/untildify.d.mts +3 -0
- package/lib/esm/untildify.mjs +22 -0
- package/lib/esm/utils/get-home.d.mts +1 -0
- package/lib/esm/utils/get-home.mjs +6 -0
- package/lib/esm/utils/get-user-home.d.mts +1 -0
- package/lib/esm/utils/get-user-home.mjs +12 -0
- package/package.json +83 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2026-present Baptiste Augrain
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
[@zokugun/fs-path](https://github.com/zokugun/node-fs-path)
|
|
2
|
+
===========================================================
|
|
3
|
+
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/@zokugun/fs-path)
|
|
6
|
+
[](https://ko-fi.com/daiyam)
|
|
7
|
+
[](https://liberapay.com/daiyam/donate)
|
|
8
|
+
[](https://paypal.me/daiyam99)
|
|
9
|
+
|
|
10
|
+
> Compact set of path utilities that complement Node's builtin `path` module.
|
|
11
|
+
|
|
12
|
+
Features
|
|
13
|
+
--------
|
|
14
|
+
|
|
15
|
+
- Tilde expansion: expand `~` to the current user's home directory with `untildify`.
|
|
16
|
+
- Safe joining and resolving: helpers that avoid common pitfalls when composing paths.
|
|
17
|
+
- Useful utilities: retrieve parent paths, absolute normalization, and platform-aware helpers.
|
|
18
|
+
- Small package with ESM and CJS builds
|
|
19
|
+
|
|
20
|
+
Installation
|
|
21
|
+
------------
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm add @zokugun/fs-path
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Quick Start
|
|
28
|
+
-----------
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { isInDir, join, resolve } from '@zokugun/fs-path'
|
|
32
|
+
|
|
33
|
+
const configDir = resolve('~/.config/myapp')
|
|
34
|
+
const dataFile = join(configDir, 'data.json')
|
|
35
|
+
|
|
36
|
+
console.log('Config dir:', configDir)
|
|
37
|
+
console.log('Data file:', dataFile)
|
|
38
|
+
|
|
39
|
+
console.log('Is data file inside config dir?', isInDir(dataFile, configDir))
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This example expands the current user's home directory, joins paths safely, and prints the resolved absolute path for `configDir`.
|
|
43
|
+
|
|
44
|
+
API reference
|
|
45
|
+
-------------
|
|
46
|
+
|
|
47
|
+
- `absolute(...paths: string[]): string`: Return an absolute path for the given segments. Uses the current platform resolution behavior.
|
|
48
|
+
- `dir(path: string): string`: Return the directory portion of `path` (empty string when the result is `.`).
|
|
49
|
+
- `extension(path: string): string`: Return the file extension (same as `path.extname`).
|
|
50
|
+
- `isAbsolute(path: string): boolean`: Return `true` when `path` is absolute for the current platform.
|
|
51
|
+
- `isInDir(path: string, parent: string): boolean`: Return `true` when `path` is equal to or contained within `parent`.
|
|
52
|
+
- `isInDirs(path: string, parents: string[]): boolean`: Return `true` when `path` is equal to or contained within in one of the `parents`.
|
|
53
|
+
- `isSafePath(path: string, options?): boolean`: Return `true` when `path` is considered safe for use (guards against suspicious segments such as `..` when appropriate for the platform).
|
|
54
|
+
- `isSafeSegment(segment: string, target?: Target | 'auto'): boolean`: Return `true` when a single path segment is safe (doesn't contain path separators or traversal sequences).
|
|
55
|
+
- `join(...paths: string[]): string`: Join path segments; returns empty string when the join result is `.`.
|
|
56
|
+
- `leaf(path: string, suffix?: string): string`: Return the basename of `path` (alias of `path.basename`).
|
|
57
|
+
- `matchesGlob?(path: string, pattern: string): boolean`: Optional platform-provided glob matcher when available.
|
|
58
|
+
- `normalize(path: string): string`: Normalize the path (same as `path.normalize`).
|
|
59
|
+
- `parent(path: string): string`: Return the parent directory of `file` (empty string when the result is `.`).
|
|
60
|
+
- `relative(from: string, to: string): string`: Compute the relative path from `from` to `to`.
|
|
61
|
+
- `resolve(...paths: string[]): string`: Resolve path segments to an absolute path. Supports tilde expansion:
|
|
62
|
+
- `~` expands to the current user's home directory.
|
|
63
|
+
- `~username/...` attempts to expand to that user's home directory when available.
|
|
64
|
+
- `sanitize(path: string, options?): Result<string>`: Return a sanitized form of `path` with unsafe segments normalized.
|
|
65
|
+
- `untildify(path: string): string`: Expand a leading `~` or `~username` to the home directory, or return `path` unchanged.
|
|
66
|
+
- `delimiter`: Platform-specific character (`;`/`:`).
|
|
67
|
+
- `separator`: Platform-specific character (`\`/`/`).
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
export type PlatformPath = {
|
|
71
|
+
readonly delimiter: ';' | ':';
|
|
72
|
+
readonly separator: '\\' | '/';
|
|
73
|
+
readonly posix: PlatformPath;
|
|
74
|
+
readonly win32: PlatformPath;
|
|
75
|
+
absolute: (...paths: string[]) => string;
|
|
76
|
+
dir: (path: string) => string;
|
|
77
|
+
extension: (path: string) => string;
|
|
78
|
+
isAbsolute: (path: string) => boolean;
|
|
79
|
+
isInDir(path: string, parent: string): boolean;
|
|
80
|
+
isInDirs(path: string, parents: string[]): boolean;
|
|
81
|
+
isSafePath: (path: string, options?: {
|
|
82
|
+
parent?: string | null;
|
|
83
|
+
parents?: string | string[] | null;
|
|
84
|
+
target?: Target | 'auto';
|
|
85
|
+
}) => boolean;
|
|
86
|
+
isSafeSegment: (segment: string, target?: Target | 'auto') => boolean;
|
|
87
|
+
join: (...paths: string[]) => string;
|
|
88
|
+
leaf: (path: string, suffix?: string) => string;
|
|
89
|
+
matchesGlob?: (path: string, pattern: string) => boolean;
|
|
90
|
+
normalize: (path: string) => string;
|
|
91
|
+
parent: (path: string) => string;
|
|
92
|
+
relative: (from: string, to: string) => string;
|
|
93
|
+
resolve: (...paths: string[]) => string;
|
|
94
|
+
sanitize(path: string, options?: {
|
|
95
|
+
parent?: string | null;
|
|
96
|
+
parents?: string | string[] | null;
|
|
97
|
+
replacement?: string | null;
|
|
98
|
+
target?: Target | 'auto'
|
|
99
|
+
}) => Result<string>
|
|
100
|
+
untildify: (path: string) => string;
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Comparison with Node's `path`
|
|
105
|
+
-----------------------------
|
|
106
|
+
|
|
107
|
+
This library intentionally mirrors many of Node's `path` APIs but provides small ergonomic differences and extra features where useful:
|
|
108
|
+
|
|
109
|
+
- `absolute(...paths)`: resolves using the runtime platform and always returns a normalized absolute path.
|
|
110
|
+
- `dir(path)`: returns `path.parse(path).dir` (similar to `path.dirname`, kept for API symmetry).
|
|
111
|
+
- `extension(path)`: alias of `path.extname`.
|
|
112
|
+
- `join(...paths)`: wraps `path.join`. Returns `''` instead of `.` when the joined result is the current directory.
|
|
113
|
+
- `isAbsolute(path)`, `normalize(path)`, `relative(from, to)`: direct mappings to `path.isAbsolute`, `path.normalize`, and `path.relative` respectively.
|
|
114
|
+
- `leaf(path, suffix?)`: alias of `path.basename`.
|
|
115
|
+
- `parent(file)`: wraps `path.dirname`. Returns `''` instead of `.` for consistency with `join`.
|
|
116
|
+
- `resolve(...paths)`: wraps `path.resolve` but adds tilde expansion (`~` and `~username`) before resolving.
|
|
117
|
+
- `untildify(path)`: purely handles `~` expansion; no direct equivalent in Node core.
|
|
118
|
+
- `delimiter`: same value as `path.delimiter` on the current platform.
|
|
119
|
+
- `separator`: same value as `path.sep` on the current platform.
|
|
120
|
+
|
|
121
|
+
Contributions
|
|
122
|
+
-------------
|
|
123
|
+
|
|
124
|
+
Contributions are most welcome. Please:
|
|
125
|
+
- Open issues and feature requests under the repository discussions.
|
|
126
|
+
- Follow the [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
127
|
+
|
|
128
|
+
Donations
|
|
129
|
+
---------
|
|
130
|
+
|
|
131
|
+
Support this project by becoming a financial contributor.
|
|
132
|
+
|
|
133
|
+
<table>
|
|
134
|
+
<tr>
|
|
135
|
+
<td><img src="https://raw.githubusercontent.com/daiyam/assets/master/icons/256/funding_kofi.png" alt="Ko-fi" width="80px" height="80px"></td>
|
|
136
|
+
<td><a href="https://ko-fi.com/daiyam" target="_blank">ko-fi.com/daiyam</a></td>
|
|
137
|
+
</tr>
|
|
138
|
+
<tr>
|
|
139
|
+
<td><img src="https://raw.githubusercontent.com/daiyam/assets/master/icons/256/funding_liberapay.png" alt="Liberapay" width="80px" height="80px"></td>
|
|
140
|
+
<td><a href="https://liberapay.com/daiyam/donate" target="_blank">liberapay.com/daiyam/donate</a></td>
|
|
141
|
+
</tr>
|
|
142
|
+
<tr>
|
|
143
|
+
<td><img src="https://raw.githubusercontent.com/daiyam/assets/master/icons/256/funding_paypal.png" alt="PayPal" width="80px" height="80px"></td>
|
|
144
|
+
<td><a href="https://paypal.me/daiyam99" target="_blank">paypal.me/daiyam99</a></td>
|
|
145
|
+
</tr>
|
|
146
|
+
</table>
|
|
147
|
+
|
|
148
|
+
License
|
|
149
|
+
-------
|
|
150
|
+
|
|
151
|
+
Copyright © 2026-present Baptiste Augrain
|
|
152
|
+
|
|
153
|
+
Licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
package/lib/cjs/dir.cjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.win32 = exports.untildify = exports.separator = exports.sanitize = exports.resolve = exports.relative = exports.posix = exports.isSafeSegment = exports.isSafePath = exports.isInDirs = exports.isInDir = exports.parent = exports.normalize = exports.matchesGlob = exports.leaf = exports.join = exports.isAbsolute = exports.extension = exports.delimiter = exports.absolute = void 0;
|
|
4
|
+
const platform_js_1 = require("./platform.cjs");
|
|
5
|
+
const { absolute, delimiter, extension, isAbsolute, join, leaf, matchesGlob, normalize, parent, isInDir, isInDirs, isSafePath, isSafeSegment, posix, relative, resolve, sanitize, separator, untildify, win32, } = platform_js_1.DEFAULT_PLATFORM;
|
|
6
|
+
exports.absolute = absolute;
|
|
7
|
+
exports.delimiter = delimiter;
|
|
8
|
+
exports.extension = extension;
|
|
9
|
+
exports.isAbsolute = isAbsolute;
|
|
10
|
+
exports.join = join;
|
|
11
|
+
exports.leaf = leaf;
|
|
12
|
+
exports.matchesGlob = matchesGlob;
|
|
13
|
+
exports.normalize = normalize;
|
|
14
|
+
exports.parent = parent;
|
|
15
|
+
exports.isInDir = isInDir;
|
|
16
|
+
exports.isInDirs = isInDirs;
|
|
17
|
+
exports.isSafePath = isSafePath;
|
|
18
|
+
exports.isSafeSegment = isSafeSegment;
|
|
19
|
+
exports.posix = posix;
|
|
20
|
+
exports.relative = relative;
|
|
21
|
+
exports.resolve = resolve;
|
|
22
|
+
exports.sanitize = sanitize;
|
|
23
|
+
exports.separator = separator;
|
|
24
|
+
exports.untildify = untildify;
|
|
25
|
+
exports.win32 = win32;
|
|
26
|
+
/* eslint-enable unicorn/prefer-export-from */
|
|
27
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
28
|
+
exports.default = {
|
|
29
|
+
PlatformPath: undefined,
|
|
30
|
+
absolute,
|
|
31
|
+
delimiter,
|
|
32
|
+
extension,
|
|
33
|
+
isAbsolute,
|
|
34
|
+
join,
|
|
35
|
+
leaf,
|
|
36
|
+
matchesGlob,
|
|
37
|
+
normalize,
|
|
38
|
+
parent,
|
|
39
|
+
isInDir,
|
|
40
|
+
isInDirs,
|
|
41
|
+
isSafePath,
|
|
42
|
+
isSafeSegment,
|
|
43
|
+
posix,
|
|
44
|
+
relative,
|
|
45
|
+
resolve,
|
|
46
|
+
sanitize,
|
|
47
|
+
separator,
|
|
48
|
+
untildify,
|
|
49
|
+
win32,
|
|
50
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type PlatformPath } from './types.cjs';
|
|
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/result";
|
|
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,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInDir = isInDir;
|
|
4
|
+
function isInDir(_nodePath, localPath) {
|
|
5
|
+
return (path, parent) => {
|
|
6
|
+
let resolvedPath = localPath.resolve(path);
|
|
7
|
+
let resolvedParent = localPath.resolve(parent);
|
|
8
|
+
if (localPath.separator === '\\') {
|
|
9
|
+
resolvedPath = resolvedPath.toLowerCase();
|
|
10
|
+
resolvedParent = resolvedParent.toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
if (resolvedPath === resolvedParent) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
|
|
16
|
+
return resolvedPath.startsWith(suffixedParent);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInDirs = isInDirs;
|
|
4
|
+
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
5
|
+
function isInDirs(_nodePath, localPath) {
|
|
6
|
+
if (localPath.separator === '\\') {
|
|
7
|
+
return (path, parents) => {
|
|
8
|
+
const resolvedPath = localPath.resolve(path).toLowerCase();
|
|
9
|
+
for (const parent of parents) {
|
|
10
|
+
const resolvedParent = localPath.resolve(parent).toLowerCase();
|
|
11
|
+
if (resolvedPath === resolvedParent) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
|
|
15
|
+
if (resolvedPath.startsWith(suffixedParent)) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return (path, parents) => {
|
|
24
|
+
const resolvedPath = localPath.resolve(path);
|
|
25
|
+
for (const parent of parents) {
|
|
26
|
+
const resolvedParent = localPath.resolve(parent);
|
|
27
|
+
if (resolvedPath === resolvedParent) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
const suffixedParent = resolvedParent.endsWith(localPath.separator) ? resolvedParent : resolvedParent + localPath.separator;
|
|
31
|
+
if (resolvedPath.startsWith(suffixedParent)) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.isSafePath = isSafePath;
|
|
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
|
+
function isSafePath(_nodePath, localPath) {
|
|
11
|
+
let target;
|
|
12
|
+
if (localPath.separator === '\\') {
|
|
13
|
+
target = 'windows.safe';
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const system = node_os_1.default.platform();
|
|
17
|
+
target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
|
|
18
|
+
}
|
|
19
|
+
const sanitizer = fs_path_sanitize_1.Sanitizer.getInstance(target);
|
|
20
|
+
return (path, options = {}) => {
|
|
21
|
+
let parents;
|
|
22
|
+
if ((0, is_it_type_1.isString)(options.parent)) {
|
|
23
|
+
parents = [options.parent];
|
|
24
|
+
}
|
|
25
|
+
if ((0, is_it_type_1.isString)(options.parents)) {
|
|
26
|
+
parents = [options.parents];
|
|
27
|
+
}
|
|
28
|
+
else if ((0, is_it_type_1.isArray)(options.parents)) {
|
|
29
|
+
parents = options.parents;
|
|
30
|
+
}
|
|
31
|
+
const safe = !options.target || options.target === 'auto' ? sanitizer.isSafePath(path) : (0, fs_path_sanitize_1.isSafePath)(path, target);
|
|
32
|
+
if (!safe) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
else if (parents) {
|
|
36
|
+
return localPath.isInDirs(path, parents);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -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.cjs';
|
|
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,27 @@
|
|
|
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.isSafeSegment = isSafeSegment;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
const fs_path_sanitize_1 = require("@zokugun/fs-path-sanitize");
|
|
9
|
+
function isSafeSegment(_nodePath, localPath) {
|
|
10
|
+
let target;
|
|
11
|
+
if (localPath.separator === '\\') {
|
|
12
|
+
target = 'windows.safe';
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
const system = node_os_1.default.platform();
|
|
16
|
+
target = system === 'darwin' ? 'macos.safe' : 'linux.safe';
|
|
17
|
+
}
|
|
18
|
+
const sanitizer = fs_path_sanitize_1.Sanitizer.getInstance(target);
|
|
19
|
+
return (segment, target) => {
|
|
20
|
+
if (!target || target === 'auto') {
|
|
21
|
+
return sanitizer.isSafePath(segment);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return (0, fs_path_sanitize_1.isSafeSegment)(segment, target);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -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.cjs';
|
|
4
|
+
export declare function isSafeSegment(_nodePath: path.PlatformPath, localPath: PlatformPath): (segment: string, target?: Target | 'auto') => boolean;
|
package/lib/cjs/join.cjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.join = join;
|
|
4
|
+
function join(nodePath, _localPath) {
|
|
5
|
+
return (...paths) => {
|
|
6
|
+
const joined = nodePath.join(...paths);
|
|
7
|
+
if (joined === '.') {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return joined;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parent = parent;
|
|
4
|
+
function parent(nodePath, _localPath) {
|
|
5
|
+
return (file) => {
|
|
6
|
+
const parent = nodePath.dirname(file);
|
|
7
|
+
if (parent === '.') {
|
|
8
|
+
return '';
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return parent;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
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.DEFAULT_PLATFORM = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const absolute_js_1 = require("./absolute.cjs");
|
|
9
|
+
const dir_js_1 = require("./dir.cjs");
|
|
10
|
+
const is_in_dir_js_1 = require("./is-in-dir.cjs");
|
|
11
|
+
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
12
|
+
const is_in_dirs_js_1 = require("./is-in-dirs.cjs");
|
|
13
|
+
const is_safe_path_js_1 = require("./is-safe-path.cjs");
|
|
14
|
+
const is_safe_segment_js_1 = require("./is-safe-segment.cjs");
|
|
15
|
+
const join_js_1 = require("./join.cjs");
|
|
16
|
+
const parent_js_1 = require("./parent.cjs");
|
|
17
|
+
const resolve_js_1 = require("./resolve.cjs");
|
|
18
|
+
const sanitize_js_1 = require("./sanitize.cjs");
|
|
19
|
+
const untildify_js_1 = require("./untildify.cjs");
|
|
20
|
+
function buildPlatform(path) {
|
|
21
|
+
const { basename: leaf, delimiter, extname: extension, isAbsolute, normalize, relative, sep: separator, } = path;
|
|
22
|
+
const result = {
|
|
23
|
+
delimiter,
|
|
24
|
+
separator,
|
|
25
|
+
extension,
|
|
26
|
+
isAbsolute,
|
|
27
|
+
leaf,
|
|
28
|
+
matchesGlob: path.matchesGlob ?? undefined,
|
|
29
|
+
normalize,
|
|
30
|
+
relative,
|
|
31
|
+
};
|
|
32
|
+
result.absolute = (0, absolute_js_1.absolute)(path, result);
|
|
33
|
+
result.dir = (0, dir_js_1.dir)(path, result);
|
|
34
|
+
result.isInDir = (0, is_in_dir_js_1.isInDir)(path, result);
|
|
35
|
+
result.isInDirs = (0, is_in_dirs_js_1.isInDirs)(path, result);
|
|
36
|
+
result.isSafePath = (0, is_safe_path_js_1.isSafePath)(path, result);
|
|
37
|
+
result.isSafeSegment = (0, is_safe_segment_js_1.isSafeSegment)(path, result);
|
|
38
|
+
result.join = (0, join_js_1.join)(path, result);
|
|
39
|
+
result.parent = (0, parent_js_1.parent)(path, result);
|
|
40
|
+
result.resolve = (0, resolve_js_1.resolve)(path, result);
|
|
41
|
+
result.sanitize = (0, sanitize_js_1.sanitize)(path, result);
|
|
42
|
+
result.untildify = (0, untildify_js_1.untildify)(path, result);
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
const POSIX_PLATFORM = buildPlatform(node_path_1.default.posix);
|
|
46
|
+
const WIN32_PLATFORM = buildPlatform(node_path_1.default.win32);
|
|
47
|
+
Object.defineProperties(POSIX_PLATFORM, {
|
|
48
|
+
posix: {
|
|
49
|
+
value: POSIX_PLATFORM,
|
|
50
|
+
writable: false,
|
|
51
|
+
},
|
|
52
|
+
win32: {
|
|
53
|
+
value: WIN32_PLATFORM,
|
|
54
|
+
writable: false,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
Object.defineProperties(WIN32_PLATFORM, {
|
|
58
|
+
posix: {
|
|
59
|
+
value: POSIX_PLATFORM,
|
|
60
|
+
writable: false,
|
|
61
|
+
},
|
|
62
|
+
win32: {
|
|
63
|
+
value: WIN32_PLATFORM,
|
|
64
|
+
writable: false,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
exports.DEFAULT_PLATFORM = (node_path_1.default === node_path_1.default.posix ? POSIX_PLATFORM : WIN32_PLATFORM);
|
|
@@ -0,0 +1,42 @@
|
|
|
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.resolve = resolve;
|
|
7
|
+
const node_process_1 = __importDefault(require("node:process"));
|
|
8
|
+
const is_it_type_1 = require("@zokugun/is-it-type");
|
|
9
|
+
const get_home_js_1 = require("./utils/get-home.cjs");
|
|
10
|
+
const get_user_home_js_1 = require("./utils/get-user-home.cjs");
|
|
11
|
+
const TILDE_REGEX = /^~(?=$|\/|\\)/;
|
|
12
|
+
const USER_REGEX = /^~([^/\\]+)(.*)$/;
|
|
13
|
+
function resolve(nodePath, _localPath) {
|
|
14
|
+
return (...paths) => {
|
|
15
|
+
if (paths.length === 0) {
|
|
16
|
+
return node_process_1.default.cwd();
|
|
17
|
+
}
|
|
18
|
+
else if (nodePath.isAbsolute(paths[0])) {
|
|
19
|
+
return nodePath.normalize(nodePath.join(...paths));
|
|
20
|
+
}
|
|
21
|
+
else if (TILDE_REGEX.test(paths[0])) {
|
|
22
|
+
const homedir = (0, get_home_js_1.getHome)();
|
|
23
|
+
if ((0, is_it_type_1.isString)(homedir)) {
|
|
24
|
+
paths.shift();
|
|
25
|
+
return nodePath.normalize(nodePath.join(homedir, ...paths));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
const match = USER_REGEX.exec(paths[0]);
|
|
30
|
+
if (match) {
|
|
31
|
+
const [, username, rest] = match;
|
|
32
|
+
const userHome = (0, get_user_home_js_1.getUserHome)(username);
|
|
33
|
+
if ((0, is_it_type_1.isString)(userHome)) {
|
|
34
|
+
paths.shift();
|
|
35
|
+
return nodePath.normalize(nodePath.join(userHome + rest, ...paths));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
paths.unshift();
|
|
40
|
+
return nodePath.normalize(nodePath.join(node_process_1.default.cwd(), ...paths));
|
|
41
|
+
};
|
|
42
|
+
}
|