@photostructure/fs-metadata 0.3.2 → 0.3.3
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 +13 -3
- package/README.md +3 -3
- package/dist/index.cjs +324 -215
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +329 -215
- package/dist/index.mjs.map +1 -1
- package/dist/types/debuglog.d.ts +2 -6
- package/dist/types/defer.d.ts +1 -2
- package/dist/types/dirname.d.ts +1 -0
- package/dist/types/hidden.d.ts +5 -42
- package/dist/types/index.d.ts +91 -2
- package/dist/types/linux/mount_points.d.ts +2 -2
- package/dist/types/linux/mtab.d.ts +2 -2
- package/dist/types/mount_point.d.ts +1 -46
- package/dist/types/options.d.ts +1 -47
- package/dist/types/platform.d.ts +1 -0
- package/dist/types/remote_info.d.ts +2 -34
- package/dist/types/stack_path.d.ts +2 -0
- package/dist/types/system_volume.d.ts +2 -2
- package/dist/types/types/hidden_metadata.d.ts +32 -0
- package/dist/types/types/mount_point.d.ts +46 -0
- package/dist/types/types/native_bindings.d.ts +3 -3
- package/dist/types/types/options.d.ts +47 -0
- package/dist/types/types/remote_info.d.ts +33 -0
- package/dist/types/types/volume_metadata.d.ts +46 -0
- package/dist/types/unc.d.ts +1 -1
- package/dist/types/units.d.ts +25 -3
- package/dist/types/volume_metadata.d.ts +4 -50
- package/dist/types/volume_mount_points.d.ts +3 -6
- package/jest.config.base.cjs +63 -0
- package/jest.config.cjs +3 -16
- package/package.json +12 -15
- package/prebuilds/darwin-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/src/async.ts +9 -0
- package/src/debuglog.ts +6 -2
- package/src/defer.ts +1 -1
- package/src/dirname.ts +13 -0
- package/src/global.d.ts +1 -0
- package/src/hidden.ts +6 -42
- package/src/{exports.ts → index.ts} +75 -30
- package/src/linux/mount_points.ts +4 -2
- package/src/linux/mtab.ts +3 -3
- package/src/mount_point.ts +2 -53
- package/src/options.ts +4 -53
- package/src/path.ts +12 -5
- package/src/platform.ts +5 -5
- package/src/remote_info.ts +44 -49
- package/src/stack_path.ts +71 -0
- package/src/system_volume.ts +3 -6
- package/src/test-utils/assert.ts +1 -1
- package/src/test-utils/debuglog-child.ts +15 -0
- package/src/types/hidden_metadata.ts +38 -0
- package/src/types/mount_point.ts +53 -0
- package/src/types/native_bindings.ts +3 -3
- package/src/types/options.ts +54 -0
- package/src/types/remote_info.ts +35 -0
- package/src/types/volume_metadata.ts +52 -0
- package/src/unc.ts +1 -1
- package/src/units.ts +39 -7
- package/src/volume_metadata.ts +9 -66
- package/src/volume_mount_points.ts +3 -6
- package/tsup.config.ts +1 -0
- package/dist/types/exports.d.ts +0 -99
- package/dist/types/setup.d.ts +0 -2
- package/src/index.cts +0 -15
- package/src/index.mts +0 -17
- package/src/setup.ts +0 -69
|
@@ -1,54 +1,8 @@
|
|
|
1
|
-
import type { MountPoint } from "./mount_point.js";
|
|
2
|
-
import { type Options } from "./options.js";
|
|
3
|
-
import { type RemoteInfo } from "./remote_info.js";
|
|
4
1
|
import type { GetVolumeMetadataOptions, NativeBindingsFn } from "./types/native_bindings.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export interface VolumeMetadata extends RemoteInfo, MountPoint {
|
|
11
|
-
/**
|
|
12
|
-
* The name of the partition
|
|
13
|
-
*/
|
|
14
|
-
label?: string;
|
|
15
|
-
/**
|
|
16
|
-
* Total size in bytes
|
|
17
|
-
*/
|
|
18
|
-
size?: number;
|
|
19
|
-
/**
|
|
20
|
-
* Used size in bytes
|
|
21
|
-
*/
|
|
22
|
-
used?: number;
|
|
23
|
-
/**
|
|
24
|
-
* Available size in bytes
|
|
25
|
-
*/
|
|
26
|
-
available?: number;
|
|
27
|
-
/**
|
|
28
|
-
* Path to the device or service that the mountpoint is from.
|
|
29
|
-
*
|
|
30
|
-
* Examples include `/dev/sda1`, `nfs-server:/export`,
|
|
31
|
-
* `//username@remoteHost/remoteShare`, or `//cifs-server/share`.
|
|
32
|
-
*
|
|
33
|
-
* May be undefined for remote volumes.
|
|
34
|
-
*/
|
|
35
|
-
mountFrom?: string;
|
|
36
|
-
/**
|
|
37
|
-
* The name of the mount. This may match the resolved mountPoint.
|
|
38
|
-
*/
|
|
39
|
-
mountName?: string;
|
|
40
|
-
/**
|
|
41
|
-
* UUID for the volume, like "c9b08f6e-b392-11ef-bf19-4b13bb7db4b4".
|
|
42
|
-
*
|
|
43
|
-
* On windows, this _may_ be the 128-bit volume UUID, but if that is not
|
|
44
|
-
* available, like in the case of remote volumes, we fallback to the 32-bit
|
|
45
|
-
* volume serial number, rendered in lowercase hexadecimal.
|
|
46
|
-
*/
|
|
47
|
-
uuid?: string;
|
|
48
|
-
}
|
|
49
|
-
export declare function getVolumeMetadata(o: GetVolumeMetadataOptions & Options, nativeFn: NativeBindingsFn): Promise<VolumeMetadata>;
|
|
50
|
-
export declare function getAllVolumeMetadata(opts: Required<Options> & {
|
|
2
|
+
import type { Options } from "./types/options.js";
|
|
3
|
+
import type { VolumeMetadata } from "./types/volume_metadata.js";
|
|
4
|
+
export declare function getVolumeMetadataImpl(o: GetVolumeMetadataOptions & Options, nativeFn: NativeBindingsFn): Promise<VolumeMetadata>;
|
|
5
|
+
export declare function getAllVolumeMetadataImpl(opts: Required<Options> & {
|
|
51
6
|
includeSystemVolumes?: boolean;
|
|
52
7
|
maxConcurrency?: number;
|
|
53
8
|
}, nativeFn: NativeBindingsFn): Promise<VolumeMetadata[]>;
|
|
54
|
-
export declare const _: undefined;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import { MountPoint } from "./mount_point.js";
|
|
2
|
-
import { Options } from "./options.js";
|
|
3
1
|
import { SystemVolumeConfig } from "./system_volume.js";
|
|
2
|
+
import type { MountPoint } from "./types/mount_point.js";
|
|
4
3
|
import type { NativeBindingsFn } from "./types/native_bindings.js";
|
|
4
|
+
import type { Options } from "./types/options.js";
|
|
5
5
|
export type GetVolumeMountPointOptions = Partial<Pick<Options, "timeoutMs" | "linuxMountTablePaths" | "maxConcurrency" | "includeSystemVolumes"> & SystemVolumeConfig>;
|
|
6
|
-
|
|
7
|
-
* Helper function for {@link getVolumeMountPoints}.
|
|
8
|
-
*/
|
|
9
|
-
export declare function getVolumeMountPoints(opts: Required<GetVolumeMountPointOptions>, nativeFn: NativeBindingsFn): Promise<MountPoint[]>;
|
|
6
|
+
export declare function getVolumeMountPointsImpl(opts: Required<GetVolumeMountPointOptions>, nativeFn: NativeBindingsFn): Promise<MountPoint[]>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
// jest.config.base.cjs
|
|
4
|
+
|
|
5
|
+
const { argv, platform } = require("node:process");
|
|
6
|
+
|
|
7
|
+
const otherPlatforms = ["linux", "darwin", "windows"]
|
|
8
|
+
.filter((ea) => ea !== (platform === "win32" ? "windows" : platform))
|
|
9
|
+
.map((ea) => `/${ea}/`);
|
|
10
|
+
|
|
11
|
+
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
12
|
+
const baseConfig = {
|
|
13
|
+
testEnvironment: "jest-environment-node",
|
|
14
|
+
roots: ["<rootDir>/src"],
|
|
15
|
+
coverageProvider: "v8",
|
|
16
|
+
moduleNameMapper: {
|
|
17
|
+
"^(\\.{1,2}/.*)\\.js$": "$1",
|
|
18
|
+
},
|
|
19
|
+
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
|
|
20
|
+
verbose: true,
|
|
21
|
+
silent: false,
|
|
22
|
+
randomize: true,
|
|
23
|
+
setupFilesAfterEnv: [
|
|
24
|
+
"jest-extended/all",
|
|
25
|
+
"<rootDir>/src/test-utils/jest-matchers.ts",
|
|
26
|
+
],
|
|
27
|
+
collectCoverage: !argv.includes("--no-coverage"),
|
|
28
|
+
coverageDirectory: "coverage",
|
|
29
|
+
coverageReporters: ["text", "lcov", "html"],
|
|
30
|
+
collectCoverageFrom: [
|
|
31
|
+
"src/**/*.ts",
|
|
32
|
+
// We have to include dist/*js because there are integration tests that
|
|
33
|
+
// import/require the root package directory:
|
|
34
|
+
"dist/*js",
|
|
35
|
+
],
|
|
36
|
+
coveragePathIgnorePatterns: [
|
|
37
|
+
"exports",
|
|
38
|
+
"setup",
|
|
39
|
+
"/test-utils/",
|
|
40
|
+
"\.d.ts$",
|
|
41
|
+
"/types/",
|
|
42
|
+
...otherPlatforms,
|
|
43
|
+
],
|
|
44
|
+
coverageThreshold: {
|
|
45
|
+
// As of 20250106 on linux:
|
|
46
|
+
// % Stmts | % Branch | % Funcs | % Lines
|
|
47
|
+
// 93.63 | 87.05 | 91.86 | 93.63
|
|
48
|
+
// As of 20250106 on darwin:
|
|
49
|
+
// % Stmts | % Branch | % Funcs | % Lines
|
|
50
|
+
// 85.91 | 84.03 | 88.69 | 85.91
|
|
51
|
+
// As of 20250106 on windows:
|
|
52
|
+
// % Stmts | % Branch | % Funcs | % Lines
|
|
53
|
+
// 85.91 | 84.03 | 88.69 | 85.91
|
|
54
|
+
global: {
|
|
55
|
+
statements: 80,
|
|
56
|
+
branches: 80,
|
|
57
|
+
functions: 80,
|
|
58
|
+
lines: 80,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
module.exports = baseConfig;
|
package/jest.config.cjs
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const baseConfig = require("./jest.config.base.cjs");
|
|
4
4
|
|
|
5
|
+
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
5
6
|
const config = {
|
|
7
|
+
...baseConfig,
|
|
6
8
|
displayName: "@photostructure/fs-metadata (CJS)",
|
|
7
|
-
testEnvironment: "jest-environment-node",
|
|
8
|
-
roots: ["<rootDir>/src"],
|
|
9
|
-
coverageProvider: "v8",
|
|
10
|
-
moduleNameMapper: {
|
|
11
|
-
"^(\\.{1,2}/.*)\\.js$": "$1",
|
|
12
|
-
},
|
|
13
9
|
transform: {
|
|
14
10
|
"^.+\\.(c)?ts$": [
|
|
15
11
|
"ts-jest",
|
|
@@ -19,15 +15,6 @@ const config = {
|
|
|
19
15
|
},
|
|
20
16
|
],
|
|
21
17
|
},
|
|
22
|
-
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
|
|
23
|
-
collectCoverage: false,
|
|
24
|
-
verbose: true,
|
|
25
|
-
silent: false,
|
|
26
|
-
randomize: true,
|
|
27
|
-
setupFilesAfterEnv: [
|
|
28
|
-
"jest-extended/all",
|
|
29
|
-
"<rootDir>/src/test-utils/jest-matchers.ts",
|
|
30
|
-
],
|
|
31
18
|
};
|
|
32
19
|
|
|
33
20
|
module.exports = config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photostructure/fs-metadata",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Cross-platform native filesystem metadata retrieval for Node.js",
|
|
5
5
|
"homepage": "https://photostructure.github.io/fs-metadata/",
|
|
6
6
|
"types": "./dist/types/index.d.ts",
|
|
@@ -26,18 +26,14 @@
|
|
|
26
26
|
"compile:esm": "tsc -p tsconfig.esm.json --noEmit",
|
|
27
27
|
"compile:cjs": "tsc -p tsconfig.cjs.json --noEmit",
|
|
28
28
|
"compile:types": "tsc -p tsconfig.types.json",
|
|
29
|
-
"postcompile:types": "mv dist/types/index.d.mts dist/types/index.d.ts",
|
|
30
|
-
"watch": "tsc --watch",
|
|
31
29
|
"bundle": "run-p bundle:* compile:types",
|
|
32
|
-
"bundle:cjs": "tsup src/index.
|
|
33
|
-
"bundle:esm": "tsup src/index.
|
|
34
|
-
"docs": "typedoc --tsconfig tsconfig.esm.json --out docs src/index.
|
|
35
|
-
"jest:coverage": "jest --coverage",
|
|
36
|
-
"jest:watch": "npm t -- --watch",
|
|
37
|
-
"jest:clear": "jest --clearCache",
|
|
30
|
+
"bundle:cjs": "tsup src/index.ts --format cjs --tsconfig tsconfig.cjs.json",
|
|
31
|
+
"bundle:esm": "tsup src/index.ts --format esm --tsconfig tsconfig.esm.json",
|
|
32
|
+
"docs": "typedoc --tsconfig tsconfig.esm.json --out docs src/index.ts",
|
|
38
33
|
"// tests": "`compile` validates the typescript compiles with tsc. `lint` checks for style issues. `bundle` uses tsup to emit the CJS and ESM rollups that the integration tests depend on. `test:*` runs the tests.",
|
|
34
|
+
"// test": "support `npm t name_of_file` (and don't fail due to missing coverage)",
|
|
35
|
+
"test": "npm run test:cjs -- --no-coverage",
|
|
39
36
|
"tests": "run-s compile lint bundle test:*",
|
|
40
|
-
"test": "npm run test:cjs",
|
|
41
37
|
"test:cjs": "jest --config jest.config.cjs",
|
|
42
38
|
"test:esm": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js --config jest.config.mjs",
|
|
43
39
|
"// test:memory:todo": "set up valgrind or similar",
|
|
@@ -52,7 +48,7 @@
|
|
|
52
48
|
"fmt:json": "prettier --write \"**/*.json\"",
|
|
53
49
|
"fmt:pkg": "npm pkg fix",
|
|
54
50
|
"fmt:ts": "prettier --write \"**/*.(c|m)?ts\"",
|
|
55
|
-
"precommit": "run-s fmt clean prebuild tests
|
|
51
|
+
"precommit": "run-s fmt clean prebuild tests",
|
|
56
52
|
"prepare-release": "npm run bundle",
|
|
57
53
|
"release": "release-it"
|
|
58
54
|
},
|
|
@@ -89,9 +85,9 @@
|
|
|
89
85
|
"devDependencies": {
|
|
90
86
|
"@eslint/js": "^9.17.0",
|
|
91
87
|
"@types/jest": "^29.5.14",
|
|
92
|
-
"@types/node": "^22.10.
|
|
93
|
-
"@typescript-eslint/eslint-plugin": "^8.19.
|
|
94
|
-
"@typescript-eslint/parser": "^8.19.
|
|
88
|
+
"@types/node": "^22.10.5",
|
|
89
|
+
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
90
|
+
"@typescript-eslint/parser": "^8.19.1",
|
|
95
91
|
"cross-env": "^7.0.3",
|
|
96
92
|
"del-cli": "^6.0.0",
|
|
97
93
|
"eslint": "^9.17.0",
|
|
@@ -110,8 +106,9 @@
|
|
|
110
106
|
"terser": "^5.37.0",
|
|
111
107
|
"ts-jest": "^29.2.5",
|
|
112
108
|
"tsup": "^8.3.5",
|
|
109
|
+
"tsx": "^4.19.2",
|
|
113
110
|
"typedoc": "^0.27.6",
|
|
114
111
|
"typescript": "^5.7.2",
|
|
115
|
-
"typescript-eslint": "^8.19.
|
|
112
|
+
"typescript-eslint": "^8.19.1"
|
|
116
113
|
}
|
|
117
114
|
}
|
|
Binary file
|
|
Binary file
|
package/src/async.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { availableParallelism } from "node:os";
|
|
|
2
2
|
import { env } from "node:process";
|
|
3
3
|
import { gt0, isNumber } from "./number.js";
|
|
4
4
|
import { isBlank } from "./string.js";
|
|
5
|
+
import { DayMs } from "./units.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* An error that is thrown when a promise does not resolve within the specified
|
|
@@ -53,6 +54,14 @@ export async function withTimeout<T>(opts: {
|
|
|
53
54
|
);
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
if (timeoutMs > DayMs) {
|
|
58
|
+
throw new TypeError(
|
|
59
|
+
desc +
|
|
60
|
+
": Invalid timeoutMs is too large: must be less than one day, but got " +
|
|
61
|
+
timeoutMs,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
if (timeoutMs === 0) {
|
|
57
66
|
return opts.promise;
|
|
58
67
|
}
|
package/src/debuglog.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { debuglog, format } from "node:util";
|
|
2
|
-
import { defer } from "./defer.js";
|
|
3
2
|
|
|
4
|
-
//
|
|
3
|
+
// inlined as a hack to get around relative imports broken in ts-node (used by
|
|
4
|
+
// the debuglog tests):
|
|
5
|
+
function defer<T>(thunk: () => T) {
|
|
6
|
+
let t: T;
|
|
7
|
+
return () => (t ??= thunk());
|
|
8
|
+
}
|
|
5
9
|
|
|
6
10
|
export const debugLogContext = defer(() => {
|
|
7
11
|
for (const ea of ["fs-metadata", "fs-meta"]) {
|
package/src/defer.ts
CHANGED
package/src/dirname.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getCallerDirname } from "./stack_path";
|
|
2
|
+
|
|
3
|
+
// Thanks to tsup shims, __dirname should always be defined except when run by
|
|
4
|
+
// jest (which will use the stack_path shim)
|
|
5
|
+
export function _dirname() {
|
|
6
|
+
try {
|
|
7
|
+
if (typeof __dirname !== "undefined") return __dirname;
|
|
8
|
+
} catch {
|
|
9
|
+
// ignore
|
|
10
|
+
}
|
|
11
|
+
// we must be in jest. Use the stack_path ~~hack~~ shim:
|
|
12
|
+
return getCallerDirname();
|
|
13
|
+
}
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="jest-extended" />
|
package/src/hidden.ts
CHANGED
|
@@ -6,45 +6,9 @@ import { WrappedError } from "./error.js";
|
|
|
6
6
|
import { canStatAsync, statAsync } from "./fs.js";
|
|
7
7
|
import { isRootDirectory, normalizePath } from "./path.js";
|
|
8
8
|
import { isWindows } from "./platform.js";
|
|
9
|
+
import type { HiddenMetadata } from "./types/hidden_metadata.js";
|
|
9
10
|
import type { NativeBindingsFn } from "./types/native_bindings.js";
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
* Represents the detailed state of a file or directory's hidden attribute
|
|
13
|
-
*/
|
|
14
|
-
export interface HiddenMetadata {
|
|
15
|
-
/**
|
|
16
|
-
* Whether the item is considered hidden by any method
|
|
17
|
-
*/
|
|
18
|
-
hidden: boolean;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Whether the item has a dot prefix (POSIX-style hidden). Windows doesn't
|
|
22
|
-
* care about dot prefixes.
|
|
23
|
-
*/
|
|
24
|
-
dotPrefix: boolean;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Whether the item has system hidden flags set, like via `chflags` on macOS
|
|
28
|
-
* or on Windows via `GetFileAttributesW`
|
|
29
|
-
*/
|
|
30
|
-
systemFlag: boolean;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Indicates which hiding methods are supported on the current platform
|
|
34
|
-
*/
|
|
35
|
-
supported: {
|
|
36
|
-
/**
|
|
37
|
-
* Whether dot prefix hiding is supported on the current operating system
|
|
38
|
-
*/
|
|
39
|
-
dotPrefix: boolean;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Whether system flag hiding is supported
|
|
43
|
-
*/
|
|
44
|
-
systemFlag: boolean;
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
12
|
const HiddenSupportByPlatform: Partial<
|
|
49
13
|
Record<NodeJS.Platform, Pick<HiddenMetadata, "supported">>
|
|
50
14
|
> = {
|
|
@@ -79,7 +43,7 @@ export const LocalSupport = HiddenSupportByPlatform[process.platform]
|
|
|
79
43
|
* @returns A boolean indicating if the item is hidden
|
|
80
44
|
* @throws {Error} If the file doesn't exist or permissions are insufficient
|
|
81
45
|
*/
|
|
82
|
-
export async function
|
|
46
|
+
export async function isHiddenImpl(
|
|
83
47
|
pathname: string,
|
|
84
48
|
nativeFn: NativeBindingsFn,
|
|
85
49
|
): Promise<boolean> {
|
|
@@ -93,7 +57,7 @@ export async function isHidden(
|
|
|
93
57
|
);
|
|
94
58
|
}
|
|
95
59
|
|
|
96
|
-
export async function
|
|
60
|
+
export async function isHiddenRecursiveImpl(
|
|
97
61
|
path: string,
|
|
98
62
|
nativeFn: NativeBindingsFn,
|
|
99
63
|
): Promise<boolean> {
|
|
@@ -102,7 +66,7 @@ export async function isHiddenRecursive(
|
|
|
102
66
|
throw new Error("Invalid path: " + JSON.stringify(path));
|
|
103
67
|
}
|
|
104
68
|
while (!isRootDirectory(norm)) {
|
|
105
|
-
if (await
|
|
69
|
+
if (await isHiddenImpl(norm, nativeFn)) {
|
|
106
70
|
return true;
|
|
107
71
|
}
|
|
108
72
|
norm = dirname(norm);
|
|
@@ -165,7 +129,7 @@ async function isSystemHidden(
|
|
|
165
129
|
* @returns An object containing detailed hidden state information
|
|
166
130
|
* @throws {Error} If the file doesn't exist or permissions are insufficient
|
|
167
131
|
*/
|
|
168
|
-
export async function
|
|
132
|
+
export async function getHiddenMetadataImpl(
|
|
169
133
|
pathname: string,
|
|
170
134
|
nativeFn: NativeBindingsFn,
|
|
171
135
|
): Promise<HiddenMetadata> {
|
|
@@ -193,7 +157,7 @@ export type SetHiddenResult = {
|
|
|
193
157
|
};
|
|
194
158
|
};
|
|
195
159
|
|
|
196
|
-
export async function
|
|
160
|
+
export async function setHiddenImpl(
|
|
197
161
|
pathname: string,
|
|
198
162
|
hide: boolean,
|
|
199
163
|
method: HideMethod,
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/index.ts
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
3
|
+
import NodeGypBuild from "node-gyp-build";
|
|
4
|
+
import { debug, debugLogContext, isDebugEnabled } from "./debuglog.js";
|
|
5
|
+
import { defer } from "./defer.js";
|
|
6
|
+
import { _dirname } from "./dirname.js";
|
|
7
|
+
import { findAncestorDir } from "./fs.js";
|
|
8
|
+
import type { HideMethod, SetHiddenResult } from "./hidden.js";
|
|
9
|
+
import {
|
|
10
|
+
getHiddenMetadataImpl,
|
|
11
|
+
isHiddenImpl,
|
|
12
|
+
isHiddenRecursiveImpl,
|
|
13
|
+
setHiddenImpl,
|
|
14
|
+
} from "./hidden.js";
|
|
6
15
|
import {
|
|
7
16
|
IncludeSystemVolumesDefault,
|
|
8
17
|
LinuxMountTablePathsDefault,
|
|
@@ -18,10 +27,19 @@ import type {
|
|
|
18
27
|
StringEnumType,
|
|
19
28
|
} from "./string_enum.js";
|
|
20
29
|
import type { SystemVolumeConfig } from "./system_volume.js";
|
|
30
|
+
import type { HiddenMetadata } from "./types/hidden_metadata.js";
|
|
31
|
+
import type { MountPoint } from "./types/mount_point.js";
|
|
32
|
+
import { NativeBindings } from "./types/native_bindings.js";
|
|
33
|
+
import type { Options } from "./types/options.js";
|
|
34
|
+
import type { VolumeMetadata } from "./types/volume_metadata.js";
|
|
21
35
|
import type { VolumeHealthStatus } from "./volume_health_status.js";
|
|
22
36
|
import { VolumeHealthStatuses } from "./volume_health_status.js";
|
|
23
|
-
import
|
|
37
|
+
import {
|
|
38
|
+
getAllVolumeMetadataImpl,
|
|
39
|
+
getVolumeMetadataImpl,
|
|
40
|
+
} from "./volume_metadata.js";
|
|
24
41
|
import type { GetVolumeMountPointOptions } from "./volume_mount_points.js";
|
|
42
|
+
import { getVolumeMountPointsImpl } from "./volume_mount_points.js";
|
|
25
43
|
|
|
26
44
|
export type {
|
|
27
45
|
GetVolumeMountPointOptions,
|
|
@@ -38,6 +56,28 @@ export type {
|
|
|
38
56
|
VolumeMetadata,
|
|
39
57
|
};
|
|
40
58
|
|
|
59
|
+
const nativeFn = defer<Promise<NativeBindings>>(async () => {
|
|
60
|
+
const start = Date.now();
|
|
61
|
+
try {
|
|
62
|
+
const dirname = _dirname();
|
|
63
|
+
const dir = await findAncestorDir(dirname, "binding.gyp");
|
|
64
|
+
if (dir == null) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
"Could not find bindings.gyp in any ancestor directory of " + dirname,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const bindings = NodeGypBuild(dir) as NativeBindings;
|
|
70
|
+
bindings.setDebugLogging(isDebugEnabled());
|
|
71
|
+
bindings.setDebugPrefix(debugLogContext() + ":native");
|
|
72
|
+
return bindings;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
debug("Loading native bindings failed: %s", error);
|
|
75
|
+
throw error;
|
|
76
|
+
} finally {
|
|
77
|
+
debug(`Native bindings took %d ms to load`, Date.now() - start);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
41
81
|
/**
|
|
42
82
|
* List all active local and remote mount points on the system.
|
|
43
83
|
*
|
|
@@ -48,9 +88,11 @@ export type {
|
|
|
48
88
|
*
|
|
49
89
|
* @param opts Optional filesystem operation settings to override default values
|
|
50
90
|
*/
|
|
51
|
-
export
|
|
91
|
+
export function getVolumeMountPoints(
|
|
52
92
|
opts?: Partial<GetVolumeMountPointOptions>,
|
|
53
|
-
): Promise<MountPoint[]
|
|
93
|
+
): Promise<MountPoint[]> {
|
|
94
|
+
return getVolumeMountPointsImpl(optionsWithDefaults(opts), nativeFn);
|
|
95
|
+
}
|
|
54
96
|
|
|
55
97
|
/**
|
|
56
98
|
* Get metadata for the volume at the given mount point.
|
|
@@ -58,10 +100,15 @@ export declare function getVolumeMountPoints(
|
|
|
58
100
|
* @param mountPoint Must be a non-blank string
|
|
59
101
|
* @param opts Optional filesystem operation settings
|
|
60
102
|
*/
|
|
61
|
-
export
|
|
103
|
+
export function getVolumeMetadata(
|
|
62
104
|
mountPoint: string,
|
|
63
105
|
opts?: Partial<Pick<Options, "timeoutMs">>,
|
|
64
|
-
): Promise<VolumeMetadata
|
|
106
|
+
): Promise<VolumeMetadata> {
|
|
107
|
+
return getVolumeMetadataImpl(
|
|
108
|
+
{ ...optionsWithDefaults(opts), mountPoint },
|
|
109
|
+
nativeFn,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
65
112
|
|
|
66
113
|
/**
|
|
67
114
|
* Retrieves metadata for all mounted volumes with optional filtering and
|
|
@@ -74,15 +121,17 @@ export declare function getVolumeMetadata(
|
|
|
74
121
|
* Defaults to the system's available parallelism: see
|
|
75
122
|
* {@link https://nodejs.org/api/os.html#osavailableparallelism | os.availableParallelism()}
|
|
76
123
|
* @param opts.timeoutMs - Maximum time to wait for
|
|
77
|
-
* {@link
|
|
124
|
+
* {@link getVolumeMountPointsImpl}, as well as **each** {@link getVolumeMetadataImpl}
|
|
78
125
|
* to complete. Defaults to {@link TimeoutMsDefault}
|
|
79
126
|
* @returns Promise that resolves to an array of either VolumeMetadata objects
|
|
80
127
|
* or error objects containing the mount point and error
|
|
81
128
|
* @throws Never - errors are caught and returned as part of the result array
|
|
82
129
|
*/
|
|
83
|
-
export
|
|
130
|
+
export function getAllVolumeMetadata(
|
|
84
131
|
opts?: Partial<Options> & { includeSystemVolumes?: boolean },
|
|
85
|
-
): Promise<VolumeMetadata[]
|
|
132
|
+
): Promise<VolumeMetadata[]> {
|
|
133
|
+
return getAllVolumeMetadataImpl(optionsWithDefaults(opts), nativeFn);
|
|
134
|
+
}
|
|
86
135
|
|
|
87
136
|
/**
|
|
88
137
|
* Check if a file or directory is hidden.
|
|
@@ -93,7 +142,9 @@ export declare function getAllVolumeMetadata(
|
|
|
93
142
|
* @param pathname Path to file or directory
|
|
94
143
|
* @returns Promise resolving to boolean indicating hidden state
|
|
95
144
|
*/
|
|
96
|
-
export
|
|
145
|
+
export function isHidden(pathname: string): Promise<boolean> {
|
|
146
|
+
return isHiddenImpl(pathname, nativeFn);
|
|
147
|
+
}
|
|
97
148
|
|
|
98
149
|
/**
|
|
99
150
|
* Check if a file or directory is hidden, or if any of its ancestor
|
|
@@ -102,7 +153,9 @@ export declare function isHidden(pathname: string): Promise<boolean>;
|
|
|
102
153
|
* @param pathname Path to file or directory
|
|
103
154
|
* @returns Promise resolving to boolean indicating hidden state
|
|
104
155
|
*/
|
|
105
|
-
export
|
|
156
|
+
export function isHiddenRecursive(pathname: string): Promise<boolean> {
|
|
157
|
+
return isHiddenRecursiveImpl(pathname, nativeFn);
|
|
158
|
+
}
|
|
106
159
|
|
|
107
160
|
/**
|
|
108
161
|
* Get detailed metadata about the hidden state of a file or directory.
|
|
@@ -110,9 +163,9 @@ export declare function isHiddenRecursive(pathname: string): Promise<boolean>;
|
|
|
110
163
|
* @param pathname Path to file or directory
|
|
111
164
|
* @returns Promise resolving to metadata about the hidden state
|
|
112
165
|
*/
|
|
113
|
-
export
|
|
114
|
-
pathname
|
|
115
|
-
|
|
166
|
+
export function getHiddenMetadata(pathname: string): Promise<HiddenMetadata> {
|
|
167
|
+
return getHiddenMetadataImpl(pathname, nativeFn);
|
|
168
|
+
}
|
|
116
169
|
|
|
117
170
|
/**
|
|
118
171
|
* Set the hidden state of a file or directory
|
|
@@ -128,21 +181,13 @@ export declare function getHiddenMetadata(
|
|
|
128
181
|
* @throws {Error} If the file doesn't exist, permissions are insufficient, or
|
|
129
182
|
* the requested method is unsupported
|
|
130
183
|
*/
|
|
131
|
-
export
|
|
184
|
+
export function setHidden(
|
|
132
185
|
pathname: string,
|
|
133
186
|
hidden: boolean,
|
|
134
|
-
method
|
|
135
|
-
): Promise<SetHiddenResult
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
getVolumeMountPoints: typeof getVolumeMountPoints;
|
|
139
|
-
getVolumeMetadata: typeof getVolumeMetadata;
|
|
140
|
-
getAllVolumeMetadata: typeof getAllVolumeMetadata;
|
|
141
|
-
isHidden: typeof isHidden;
|
|
142
|
-
isHiddenRecursive: typeof isHiddenRecursive;
|
|
143
|
-
getHiddenMetadata: typeof getHiddenMetadata;
|
|
144
|
-
setHidden: typeof setHidden;
|
|
145
|
-
};
|
|
187
|
+
method: HideMethod = "auto",
|
|
188
|
+
): Promise<SetHiddenResult> {
|
|
189
|
+
return setHiddenImpl(pathname, hidden, method, nativeFn);
|
|
190
|
+
}
|
|
146
191
|
|
|
147
192
|
export {
|
|
148
193
|
IncludeSystemVolumesDefault,
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { debug } from "../debuglog.js";
|
|
4
4
|
import { toError, WrappedError } from "../error.js";
|
|
5
|
-
import { isMountPoint
|
|
5
|
+
import { isMountPoint } from "../mount_point.js";
|
|
6
6
|
import { compactValues } from "../object.js";
|
|
7
|
-
import { optionsWithDefaults
|
|
7
|
+
import { optionsWithDefaults } from "../options.js";
|
|
8
|
+
import { type MountPoint } from "../types/mount_point.js";
|
|
8
9
|
import type { NativeBindingsFn } from "../types/native_bindings.js";
|
|
10
|
+
import type { Options } from "../types/options.js";
|
|
9
11
|
import { MountEntry, mountEntryToMountPoint, parseMtab } from "./mtab.js";
|
|
10
12
|
|
|
11
13
|
export async function getLinuxMountPoints(
|
package/src/linux/mtab.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// src/linux/mtab.ts
|
|
2
2
|
|
|
3
|
-
import { MountPoint } from "../mount_point.js";
|
|
4
3
|
import { toInt } from "../number.js";
|
|
5
4
|
import { normalizePosixPath } from "../path.js";
|
|
6
5
|
import { extractRemoteInfo } from "../remote_info.js";
|
|
@@ -11,7 +10,8 @@ import {
|
|
|
11
10
|
toNotBlank,
|
|
12
11
|
} from "../string.js";
|
|
13
12
|
import { isSystemVolume, SystemVolumeConfig } from "../system_volume.js";
|
|
14
|
-
import {
|
|
13
|
+
import type { MountPoint } from "../types/mount_point.js";
|
|
14
|
+
import type { VolumeMetadata } from "../types/volume_metadata.js";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Represents an entry in the mount table.
|
|
@@ -70,7 +70,7 @@ export function mountEntryToPartialVolumeMetadata(
|
|
|
70
70
|
fstype: entry.fs_vfstype,
|
|
71
71
|
mountFrom: entry.fs_spec,
|
|
72
72
|
isSystemVolume: isSystemVolume(entry.fs_file, entry.fs_vfstype, options),
|
|
73
|
-
remote: false, // < default to false
|
|
73
|
+
remote: false, // < default to false, but it may be overridden by extractRemoteInfo
|
|
74
74
|
...extractRemoteInfo(entry.fs_spec),
|
|
75
75
|
};
|
|
76
76
|
}
|