@photostructure/fs-metadata 0.0.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/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2024 Matthew McEachen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,311 @@
1
+ # @photostructure/fs-metadata
2
+
3
+ A cross-platform native Node.js module for retrieving filesystem metadata including mount points, volume information, and space utilization statistics.
4
+
5
+ Built and supported by [PhotoStructure](https://photostructure.com).
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@photostructure/fs-metadata.svg)](https://www.npmjs.com/package/@photostructure/fs-metadata)
8
+ [![Test](https://github.com/photostructure/fs-metadata/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/photostructure/fs-metadata/actions/workflows/test.yml)
9
+ [![GitHub issues](https://img.shields.io/github/issues/photostructure/fs-metadata.svg)](https://github.com/photostructure/fs-metadata/issues)
10
+ [![Known Vulnerabilities](https://snyk.io/test/github/photostructure/fs-metadata/badge.svg?targetFile=package.json)](https://snyk.io/test/github/photostructure/fs-metadata?targetFile=package.json)
11
+ [![Node-API v9 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v9%20Badge.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#node-api-version-matrix)
12
+ [![View on GitHub](https://img.shields.io/badge/View%20on-GitHub-blue)](https://github.com/photostructure/fs-metadata)
13
+
14
+ ## Features
15
+
16
+ - List all mounted volumes/drives on the system
17
+ - Get detailed volume metadata including:
18
+ - Total size, used space, and available space
19
+ - Filesystem type and volume label
20
+ - Volume UUID (when available)
21
+ - Remote/network share information
22
+ - Cross-platform support:
23
+ - Windows (x64, arm64)
24
+ - macOS (x64, arm64)
25
+ - Linux (x64, arm64) (including Gnome GIO/`GVfs` mounts, if available)
26
+ - Written in modern TypeScript with full type definitions
27
+ - Native async implementations avoid blocking the event loop
28
+ - Support for both ESM and CJS consumers
29
+ - Comprehensive test coverage
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ npm install @photostructure/fs-metadata
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ```ts
40
+ import {
41
+ getVolumeMountPoints,
42
+ getVolumeMetadata,
43
+ } from "@photostructure/fs-metadata";
44
+
45
+ // List all mounted volumes
46
+ const mountPoints = await getVolumeMountPoints();
47
+ console.dir({ mountPoints });
48
+ // Example output: ['C:\\', 'D:\\'] on Windows
49
+ // Example output: ['/', '/home', '/Users'] on Unix-like systems
50
+
51
+ // Get metadata for a specific volume
52
+ const metadata = await getVolumeMetadata("C:\\"); // Windows
53
+ // Or for Unix-like systems:
54
+ // const metadata = await getVolumeMetadata('/');
55
+ ```
56
+
57
+ If you're using CommonJS:
58
+
59
+ ```js
60
+ const {
61
+ getVolumeMountPoints,
62
+ getVolumeMetadata,
63
+ } = require("@photostructure/fs-metadata");
64
+
65
+ // Usage is the same as the ESM example above
66
+ ```
67
+
68
+ ## Documentation
69
+
70
+ [Read the API here](https://photostructure.github.io/fs-metadata/modules.html)
71
+
72
+ ## Options
73
+
74
+ ### Timeouts
75
+
76
+ There is a [default timeout](https://photostructure.github.io/fs-metadata/variables/TimeoutMsDefault.html) applied to all operations. This may not be sufficient for some OSes and volumes--especially powered-down optical drives (which may take 10s of seconds to wake up). Disable timeouts by setting `{timeoutMs: 0}`.
77
+
78
+ ### Filtering
79
+
80
+ Linux and macOS have a (surprisingly large) number of mountpoints that are for internal use (especially if your Linux distribution uses `snap` and/or other loopback ~~hacks~~ systems).
81
+
82
+ This library tries to avoid those with a bunch of exclusion patterns--see the [Options](https://photostructure.github.io/fs-metadata/interfaces/Options.html) interface for details.
83
+
84
+ To disable these filters, provide an empty array for these `excluded*` fields, like so:
85
+
86
+ ```ts
87
+ const allMountPoints = await getVolumeMountPoints({
88
+ excludedFileSystemTypes: [],
89
+ excludedMountPointGlobs: [],
90
+ onlyDirectories: false,
91
+ });
92
+ ```
93
+
94
+ ## Platform-Specific Behaviors
95
+
96
+ This module's results are inherently platform-specific. Here are some things to
97
+ keep in mind:
98
+
99
+ ### Mount Points
100
+
101
+ #### Windows
102
+
103
+ - Mount points are drive letters with trailing backslash (e.g., `C:\`, `D:\`)
104
+ - Network shares appear as mounted drives with UNC paths
105
+ - Volume GUIDs are available through Windows API
106
+ - Hidden and system volumes may be included
107
+
108
+ #### macOS
109
+
110
+ - Uses forward slashes for paths (e.g., `/`, `/Users`)
111
+ - Volume UUIDs may be available through the DiskArbitration framework
112
+ - Time Machine volumes should be detected and handled appropriately
113
+
114
+ #### Linux
115
+
116
+ - Uses forward slashes for paths (e.g., `/`, `/home`)
117
+ - Network mounts (NFS/CIFS) handled through mount table
118
+ - If `GIO` support is installed, it will be queried for additional mountpoints and volume metadata
119
+ - Depending on your distribution, you may want to use `{ linuxMountTablePath: "/etc/mtab" }` instead of the default, `/proc/mounts`.
120
+ - UUID detection is via `libblkid`, which must be installed.
121
+
122
+ ### Volume Metadata
123
+
124
+ #### Windows
125
+
126
+ - Size information from GetDiskFreeSpaceEx
127
+ - Volume information (label, filesystem) from GetVolumeInformation
128
+ - Remote status from GetDriveType
129
+ - `fileSystem` will be `NTFS` for remote filesystems, as that's how Windows presents the local volume. Fixing this to be more accurate requires additional heuristics that have diminshing returns.
130
+ - The UUID is the volume serial number that the operating system assigns when a hard disk is formatted, and **not the physical UUID assigned by the manufacturer**. This lets us avoid one more syscall (and it's a doozy, the Windows Management Instrumentation (WMI) Win32_PhysicalMedia function loves to hang).
131
+
132
+ #### macOS
133
+
134
+ - Size calculations via statvfs
135
+ - Volume details through DiskArbitration framework
136
+ - Network share detection via volume characteristics
137
+ - Time Machine volume detection
138
+
139
+ #### Linux
140
+
141
+ - Size information from statvfs
142
+ - Filesystem type from mount table
143
+ - Block device metadata via libblkid
144
+ - Network filesystem detection from mount options
145
+ - Optional GIO integration for additional metadata
146
+
147
+ ### Filesystem Types
148
+
149
+ #### Windows
150
+
151
+ - NTFS
152
+ - FAT32
153
+ - exFAT
154
+ - ReFS
155
+ - Network shares (CIFS/SMB)
156
+
157
+ #### macOS
158
+
159
+ - APFS (default since macOS High Sierra)
160
+ - HFS+ (legacy)
161
+ - FAT32
162
+ - exFAT
163
+ - Network shares (AFP, SMB, NFS)
164
+
165
+ #### Linux
166
+
167
+ - ext2/3/4
168
+ - XFS
169
+ - Btrfs
170
+ - ZFS
171
+ - Network filesystems (NFS, CIFS)
172
+ - Pseudo filesystems (procfs, sysfs) - excluded by default
173
+
174
+ ### Default Excluded Mount Points
175
+
176
+ #### Windows
177
+
178
+ - None by default
179
+
180
+ #### macOS
181
+
182
+ - `/dev`
183
+ - `/dev/fd`
184
+ - System volume internal mounts
185
+
186
+ #### Linux
187
+
188
+ - `/proc`
189
+ - `/sys`
190
+ - `/dev`
191
+ - `/run`
192
+ - Snap mounts
193
+ - Other virtual filesystems
194
+
195
+ ### Network Share Metadata
196
+
197
+ #### Windows
198
+
199
+ - UNC paths parsed for host/share information
200
+ - SMB/CIFS protocol support
201
+ - Network status via GetDriveType
202
+
203
+ #### macOS
204
+
205
+ - AFP and SMB protocol support
206
+ - Network status via volume characteristics
207
+ - Host/share parsing from mount URLs
208
+
209
+ #### Linux
210
+
211
+ - NFS and CIFS support
212
+ - Network detection from filesystem type
213
+ - Remote info parsed from mount spec
214
+
215
+ ### Performance Considerations
216
+
217
+ #### Windows
218
+
219
+ - Drive letter enumeration is fast
220
+ - Volume metadata queries may block
221
+
222
+ #### macOS
223
+
224
+ - DiskArbitration queries are generally fast
225
+ - Network volume operations may be slow
226
+
227
+ #### Linux
228
+
229
+ - Mount table parsing is fast
230
+ - Block device operations may block
231
+ - GIO operations are asynchronous
232
+
233
+ ### Error Handling
234
+
235
+ #### Windows
236
+
237
+ - Access denied errors for restricted volumes
238
+ - Network timeout errors for disconnected shares
239
+ - Invalid drive letter errors
240
+
241
+ #### macOS
242
+
243
+ - DiskArbitration framework errors
244
+ - Network disconnection handling
245
+ - Volume unmount detection
246
+
247
+ #### Linux
248
+
249
+ - Mount table parsing errors
250
+ - Block device access errors
251
+ - GIO operation failures
252
+ - Network filesystem timeouts
253
+
254
+ ### Configuration Options
255
+
256
+ Common options across platforms:
257
+
258
+ - Timeout duration
259
+ - Excluded mount point patterns
260
+ - Directory-only filter
261
+
262
+ Platform-specific options:
263
+
264
+ - Linux: Mount table path selection
265
+ - Linux: GIO support enable/disable
266
+ - Windows: Network share handling
267
+ - macOS: Time Machine volume handling
268
+
269
+ ### Recommendations
270
+
271
+ #### Windows
272
+
273
+ - Handle access denied errors gracefully
274
+ - Check drive type before operations
275
+
276
+ #### macOS
277
+
278
+ - Monitor volume mount/unmount notifications
279
+ - Handle Time Machine volumes appropriately
280
+ - Check network status before operations
281
+
282
+ #### Linux
283
+
284
+ - Use default mount table when possible
285
+ - Enable GIO support if available
286
+ - Handle remote filesystem timeouts
287
+
288
+ ## Building from Source
289
+
290
+ Requirements:
291
+
292
+ - Supported Node.js version
293
+ - Python 3
294
+ - C++ build tools:
295
+ - Windows: Visual Studio Build Tools
296
+ - macOS: Xcode Command Line Tools
297
+ - Linux: GCC and development headers
298
+
299
+ ## License
300
+
301
+ MIT
302
+
303
+ ## Contributing
304
+
305
+ Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
306
+
307
+ Please make sure to update tests and documentation as appropriate.
308
+
309
+ ## Security
310
+
311
+ If you discover a security vulnerability, please send an email to [security@photostructure.com](mailto:security@photostructure.com)
package/binding.gyp ADDED
@@ -0,0 +1,111 @@
1
+ {
2
+ "variables": {
3
+ "enable_gio%": "false"
4
+ },
5
+ "targets": [
6
+ {
7
+ "target_name": "node_fs_meta",
8
+ "sources": [
9
+ "src/binding.cpp"
10
+ ],
11
+ "include_dirs": [
12
+ "<!@(node -p \"require('node-addon-api').include\")",
13
+ "src"
14
+ ],
15
+ "dependencies": [
16
+ "<!(node -p \"require('node-addon-api').gyp\")"
17
+ ],
18
+ "defines": [
19
+ "NAPI_CPP_EXCEPTIONS"
20
+ ],
21
+ "conditions": [
22
+ [
23
+ "OS=='linux'",
24
+ {
25
+ "sources": [
26
+ "src/linux/blkid_cache.cpp",
27
+ "src/linux/volume_metadata.cpp"
28
+ ],
29
+ "libraries": [
30
+ "-lblkid"
31
+ ],
32
+ "cflags": [
33
+ "-fPIC"
34
+ ],
35
+ "cflags_cc": [
36
+ "-fexceptions",
37
+ "-fPIC"
38
+ ],
39
+ "conditions": [
40
+ [
41
+ "enable_gio=='true'",
42
+ {
43
+ "sources": [
44
+ "src/linux/gio_utils.cpp",
45
+ "src/linux/gio_worker.cpp"
46
+ ],
47
+ "defines": [
48
+ "ENABLE_GIO=1"
49
+ ],
50
+ "libraries": [
51
+ "<!@(pkg-config --libs gio-2.0)"
52
+ ],
53
+ "cflags": [
54
+ "<!@(pkg-config --cflags gio-2.0)"
55
+ ]
56
+ }
57
+ ]
58
+ ]
59
+ }
60
+ ],
61
+ [
62
+ "OS=='win'",
63
+ {
64
+ "sources": [
65
+ "src/windows/volume_mount_points.cpp",
66
+ "src/windows/volume_metadata.cpp"
67
+ ],
68
+ "libraries": [
69
+ "-lMpr.lib"
70
+ ],
71
+ "msvs_settings": {
72
+ "VCCLCompilerTool": {
73
+ "ExceptionHandling": 1,
74
+ "RuntimeTypeInfo": "true"
75
+ }
76
+ }
77
+ }
78
+ ],
79
+ [
80
+ "OS=='mac'",
81
+ {
82
+ "sources": [
83
+ "src/darwin/volume_mount_points.cpp",
84
+ "src/darwin/volume_metadata.cpp"
85
+ ],
86
+ "xcode_settings": {
87
+ "CLANG_CXX_LANGUAGE_STANDARD": "c++17",
88
+ "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
89
+ "CLANG_CXX_LIBRARY": "libc++",
90
+ "MACOSX_DEPLOYMENT_TARGET": "10.15"
91
+ },
92
+ "cflags": [
93
+ "-fexceptions",
94
+ "-fPIC"
95
+ ],
96
+ "cflags_cc": [
97
+ "-fexceptions"
98
+ ],
99
+ "link_settings": {
100
+ "libraries": [
101
+ "DiskArbitration.framework",
102
+ "Foundation.framework",
103
+ "IOKit.framework"
104
+ ]
105
+ }
106
+ }
107
+ ]
108
+ ]
109
+ }
110
+ ]
111
+ }
package/package.json ADDED
@@ -0,0 +1,121 @@
1
+ {
2
+ "name": "@photostructure/fs-metadata",
3
+ "version": "0.0.1",
4
+ "description": "Cross-platform native filesystem metadata retrieval for Node.js",
5
+ "homepage": "https://photostructure.github.io/fs-metadata/",
6
+ "type": "module",
7
+ "main": "dist/cjs/index.cjs",
8
+ "module": "dist/esm/index.mjs",
9
+ "// exports": "https://nodejs.org/api/packages.html#conditional-exports",
10
+ "exports": {
11
+ ".": {
12
+ "require": {
13
+ "default": "./lib/cjs/index.cjs",
14
+ "types": "./lib/cjs/index.d.ts"
15
+ },
16
+ "import": {
17
+ "default": "./lib/esm/index.js",
18
+ "types": "./lib/esm/index.d.ts"
19
+ }
20
+ }
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+ssh://git@github.com/photostructure/fs-metadata.git"
25
+ },
26
+ "license": "MIT",
27
+ "scripts": {
28
+ "install": "node-gyp-build",
29
+ "clean": "run-p clean:*",
30
+ "clean:dist": "rimraf dist",
31
+ "clean:gyp": "node-gyp clean",
32
+ "// scripts/configure.js checks if gio is installed": "",
33
+ "configure": "node scripts/configure.mjs",
34
+ "// prebuild": "is called by .github/workflows/build.yml",
35
+ "preprebuild": "run-s clean configure",
36
+ "prebuild": "prebuildify --napi --tag-libc --strip",
37
+ "tsc": "run-p tsc:*",
38
+ "tsc:esm": "tsc -p tsconfig.esm.json",
39
+ "tsc:cjs": "tsc -p tsconfig.cjs.json",
40
+ "tsc:tests": "tsc -p tsconfig.json",
41
+ "watch": "tsc --watch",
42
+ "docs": "typedoc --out docs src/index.ts",
43
+ "jest:coverage": "jest --coverage",
44
+ "jest:watch": "npm t -- --watch",
45
+ "jest:clear": "jest --clearCache",
46
+ "// tests": "is called by .github/workflows/test.yml",
47
+ "tests": "run-s test test:memory",
48
+ "test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js",
49
+ "// test:memory:todo": "set up valgrind or similar",
50
+ "test:memory": "cross-env TEST_MEMORY=1 node --expose-gc --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js src/__tests__/memory.test.ts",
51
+ "lint": "eslint",
52
+ "lint:fix": "eslint --fix",
53
+ "fmt": "run-p fmt:*",
54
+ "// fmt:cpp": "on ubuntu: `sudo apt install clang-format`",
55
+ "fmt:cpp": "clang-format --style=LLVM -i src/*/*.cpp src/*/*.h || true",
56
+ "fmt:js": "prettier --write \"scripts/**/*.?js\" \"*.?js\"",
57
+ "fmt:json": "prettier --write \"**/*.json\"",
58
+ "fmt:pkg": "npm pkg fix",
59
+ "fmt:ts": "prettier --write \"src/**/*.ts\"",
60
+ "// precommit": "is called manually before committing",
61
+ "precommit": "run-s clean fmt lint prebuild tsc tests",
62
+ "// release": "is called by .github/workflows/release.yml and should only be run via GitHub Actions",
63
+ "prerelease": "tsc",
64
+ "release": "release-it"
65
+ },
66
+ "gypfile": true,
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
70
+ "engines": {
71
+ "node": ">=18.0.0"
72
+ },
73
+ "os": [
74
+ "darwin",
75
+ "linux",
76
+ "win32"
77
+ ],
78
+ "cpu": [
79
+ "x64",
80
+ "arm64"
81
+ ],
82
+ "keywords": [
83
+ "filesystem",
84
+ "metadata",
85
+ "native",
86
+ "node-addon",
87
+ "windows",
88
+ "linux",
89
+ "macos",
90
+ "cross-platform"
91
+ ],
92
+ "dependencies": {
93
+ "node-addon-api": "^8.2.2",
94
+ "node-gyp-build": "^4.8.4"
95
+ },
96
+ "devDependencies": {
97
+ "@eslint/js": "^9.15.0",
98
+ "@types/jest": "^29.5.14",
99
+ "@types/node": "^22.9.1",
100
+ "@typescript-eslint/eslint-plugin": "^8.15.0",
101
+ "@typescript-eslint/parser": "^8.15.0",
102
+ "cross-env": "^7.0.3",
103
+ "eslint": "^9.15.0",
104
+ "globals": "^15.12.0",
105
+ "jest": "^29.7.0",
106
+ "jest-environment-node": "^29.7.0",
107
+ "jest-extended": "^4.0.2",
108
+ "node-gyp": "^10.2.0",
109
+ "npm-run-all": "4.1.5",
110
+ "prebuildify": "^6.0.1",
111
+ "prettier": "^3.3.3",
112
+ "prettier-plugin-organize-imports": "4.1.0",
113
+ "release-it": "^17.10.0",
114
+ "rimraf": "^5.0.9",
115
+ "terser": "^5.36.0",
116
+ "ts-jest": "^29.2.5",
117
+ "typedoc": "^0.26.11",
118
+ "typescript": "^5.6.3",
119
+ "typescript-eslint": "^8.15.0"
120
+ }
121
+ }
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ // scripts/configure.mjs
4
+
5
+ import { execSync } from "node:child_process";
6
+ import { writeFileSync } from "node:fs";
7
+ import { platform } from "node:os";
8
+ import { argv } from "node:process";
9
+ import { pathToFileURL } from "node:url";
10
+
11
+ function hasGio() {
12
+ if (platform() !== "linux") return false;
13
+ try {
14
+ execSync("pkg-config --exists gio-2.0", { stdio: "ignore" });
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ export function configure() {
22
+ // Create a gyp config file that node-gyp will read
23
+ const config = {
24
+ variables: {
25
+ "enable_gio%": hasGio() ? "true" : "false",
26
+ },
27
+ };
28
+
29
+ const payload = JSON.stringify(config, null, 2);
30
+ writeFileSync("config.gypi", payload);
31
+ }
32
+
33
+ // If the script is run directly, call the configure function
34
+ if (import.meta.url === pathToFileURL(argv[1]).href) {
35
+ configure();
36
+ }
@@ -0,0 +1,68 @@
1
+ // src/binding.cpp
2
+
3
+ #include <napi.h>
4
+ #include <string>
5
+
6
+ #if defined(_WIN32)
7
+ #include "windows/fs_meta.h"
8
+ #elif defined(__APPLE__)
9
+ #include "darwin/fs_meta.h"
10
+ #elif defined(__linux__)
11
+ #include "common/volume_metadata.h"
12
+ #ifdef ENABLE_GIO
13
+ #include "linux/gio_utils.h"
14
+ #endif
15
+ #endif
16
+
17
+ namespace {
18
+
19
+ Napi::Value GetVolumeMetadata(const Napi::CallbackInfo& info) {
20
+ Napi::Env env = info.Env();
21
+
22
+ if (info.Length() < 1 || !info[0].IsString()) {
23
+ throw Napi::TypeError::New(env, "String expected for mountPoint");
24
+ }
25
+
26
+ std::string mountPoint = info[0].As<Napi::String>();
27
+ Napi::Object options = info.Length() > 1 && info[1].IsObject()
28
+ ? info[1].As<Napi::Object>()
29
+ : Napi::Object::New(env);
30
+
31
+ return FSMeta::GetVolumeMetadata(env, mountPoint, options);
32
+ }
33
+
34
+ #ifdef ENABLE_GIO
35
+ Napi::Value GetGioMountPoints(const Napi::CallbackInfo& info) {
36
+ Napi::Env env = info.Env();
37
+ return FSMeta::gio::GetMountPoints(env);
38
+ }
39
+ #endif
40
+
41
+ #if defined(_WIN32) || defined(__APPLE__)
42
+ Napi::Value GetVolumeMountPoints(const Napi::CallbackInfo& info) {
43
+ Napi::Env env = info.Env();
44
+ return FSMeta::GetVolumeMountPoints(env);
45
+ }
46
+ #endif
47
+
48
+ Napi::Object Init(Napi::Env env, Napi::Object exports) {
49
+
50
+ #if defined(_WIN32) || defined(__APPLE__)
51
+ exports.Set("getVolumeMountPoints",
52
+ Napi::Function::New(env, GetVolumeMountPoints));
53
+ #endif
54
+
55
+ exports.Set("getVolumeMetadata",
56
+ Napi::Function::New(env, GetVolumeMetadata));
57
+
58
+ #ifdef ENABLE_GIO
59
+ exports.Set("getGioMountPoints",
60
+ Napi::Function::New(env, GetGioMountPoints));
61
+ #endif
62
+
63
+ return exports;
64
+ }
65
+
66
+ NODE_API_MODULE(node_fs_meta, Init)
67
+
68
+ } // namespace
@@ -0,0 +1,19 @@
1
+ // src/common/error_utils.h
2
+ #pragma once
3
+ #include <stdexcept>
4
+ #include <string>
5
+
6
+ namespace FSMeta {
7
+
8
+ class FSException : public std::runtime_error {
9
+ public:
10
+ explicit FSException(const std::string &message)
11
+ : std::runtime_error(message) {}
12
+ };
13
+
14
+ inline std::string CreateErrorMessage(const char *operation, int error) {
15
+ return std::string(operation) +
16
+ " failed with error: " + std::to_string(error);
17
+ }
18
+
19
+ } // namespace FSMeta