Skip to content

Commit a48a600

Browse files
authored
fix: mixed posix/win32 namespaces (#197)
1 parent 5c4f321 commit a48a600

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

src/path.ts src/_path.ts

-7
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ const _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
2626
*/
2727
export const sep = "/";
2828

29-
/**
30-
* The platform-specific file delimiter.
31-
*
32-
* Equals to `";"` in windows and `":"` in all other platforms.
33-
*/
34-
export const delimiter = globalThis.process?.platform === "win32" ? ";" : ":";
35-
3629
export const normalize: typeof path.normalize = function (path: string) {
3730
if (path.length === 0) {
3831
return ".";

src/index.ts

+30-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
1-
import type NodePath from "node:path";
1+
import type { posix as Posix, win32 as Win32, PlatformPath } from "node:path";
22

3-
import * as path from "./path";
3+
import * as _path from "./_path";
44

5-
export * from "./path";
5+
export * from "./_path";
66

7-
export type Pathe = Omit<typeof NodePath, "posix" | "win32">;
7+
/**
8+
* The platform-specific file delimiter.
9+
*
10+
* Equals to `";"` in windows and `":"` in all other platforms.
11+
*/
12+
export const delimiter: ";" | ":" = /* @__PURE__ */ (() =>
13+
globalThis.process?.platform === "win32" ? ";" : ":")();
814

9-
export const posix = path satisfies Pathe;
15+
// Mix namespaces without side-effects of object to allow tree-shaking
1016

11-
export const win32 = path satisfies Pathe;
17+
const _platforms = { posix: undefined, win32: undefined } as {
18+
posix: typeof Posix;
19+
win32: typeof Win32;
20+
};
1221

13-
export default path satisfies Pathe;
22+
const mix = (del: ";" | ":" = delimiter) => {
23+
return new Proxy(_path, {
24+
get(_, prop) {
25+
if (prop === "delimiter") return del;
26+
if (prop === "posix") return posix;
27+
if (prop === "win32") return win32;
28+
return _platforms[prop] || _path[prop];
29+
},
30+
}) as unknown as PlatformPath;
31+
};
32+
33+
export const posix = /* @__PURE__ */ mix(":") as typeof Posix;
34+
export const win32 = /* @__PURE__ */ mix(";") as typeof Win32;
35+
36+
export default posix;

src/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { join } from "./path";
1+
import { join } from "./_path";
22
import { normalizeWindowsPath } from "./_internal";
33

44
const pathSeparators = new Set(["/", "\\", undefined]);

test/index.spec.ts

+11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
toNamespacedPath,
1717
normalizeString,
1818
matchesGlob,
19+
posix,
20+
win32,
1921
} from "../src";
2022

2123
import { normalizeWindowsPath } from "../src/_internal";
@@ -397,6 +399,8 @@ runTest("toNamespacedPath", toNamespacedPath, {
397399

398400
describe("constants", () => {
399401
it("delimiter", () => {
402+
expect(posix.delimiter).to.equal(":");
403+
expect(win32.delimiter).to.equal(";");
400404
expect(delimiter).to.equal(
401405
globalThis.process?.platform === "win32" ? ";" : ":",
402406
);
@@ -407,6 +411,13 @@ describe("constants", () => {
407411
});
408412
});
409413

414+
describe("mixed namespaces", () => {
415+
it("nested namespaces work", () => {
416+
expect(posix.win32.posix.delimiter).to.equal(":");
417+
expect(win32.posix.win32.delimiter).to.equal(";");
418+
});
419+
});
420+
410421
runTest("matchesGlob", matchesGlob, [
411422
["/foo/bar", "/foo/**", true],
412423
[String.raw`\foo\bar`, "/foo/**", true],

0 commit comments

Comments
 (0)