@photostructure/fs-metadata 1.4.1 → 2.0.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/CHANGELOG.md +23 -0
- package/CLAUDE.md +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -13
- package/prebuilds/darwin-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/darwin-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-arm64/@photostructure+fs-metadata.glibc.node +0 -0
- package/prebuilds/win32-x64/@photostructure+fs-metadata.glibc.node +0 -0
- package/scripts/post-build.mjs +13 -4
- package/scripts/prebuildify-wrapper.ts +13 -4
- package/scripts/precommit.ts +4 -0
- package/src/common/metadata_worker.h +2 -1
- package/src/common/shutdown.h +4 -6
- package/src/fs.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@photostructure/fs-metadata",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"default": "./dist/index.cjs"
|
|
14
14
|
},
|
|
15
15
|
"import": {
|
|
16
|
-
"types": "./dist/index.d.
|
|
16
|
+
"types": "./dist/index.d.mts",
|
|
17
17
|
"default": "./dist/index.mjs"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
"lint:native": "tsx scripts/clang-tidy.ts",
|
|
47
47
|
"lint:tsc": "tsc --noEmit",
|
|
48
48
|
"lint:eslint": "eslint",
|
|
49
|
+
"// check:exports": "verify package.json exports + type declarations resolve correctly (arethetypeswrong). Requires `npm run build:dist` first.",
|
|
50
|
+
"check:exports": "attw --pack .",
|
|
49
51
|
"fmt": "run-p fmt:*",
|
|
50
52
|
"// fmt:cpp": "on ubuntu: `sudo apt install clang-format`. Note that windows emits `invalid format` with this || true approach, but it works and is better than introducing Yet Another Script Script (like scripts/clang-format.mjs).",
|
|
51
53
|
"fmt:cpp": "clang-format --style=LLVM -i src/*.cpp src/*/*.cpp src/*/*.h || echo \"problem with clang-format\"",
|
|
@@ -68,7 +70,7 @@
|
|
|
68
70
|
"access": "public"
|
|
69
71
|
},
|
|
70
72
|
"engines": {
|
|
71
|
-
"node": ">=
|
|
73
|
+
"node": ">=22"
|
|
72
74
|
},
|
|
73
75
|
"os": [
|
|
74
76
|
"darwin",
|
|
@@ -90,32 +92,33 @@
|
|
|
90
92
|
"cross-platform"
|
|
91
93
|
],
|
|
92
94
|
"dependencies": {
|
|
93
|
-
"node-addon-api": "^8.
|
|
95
|
+
"node-addon-api": "^8.8.0",
|
|
94
96
|
"node-gyp-build": "^4.8.4"
|
|
95
97
|
},
|
|
96
98
|
"devDependencies": {
|
|
99
|
+
"@arethetypeswrong/cli": "^0.18.3",
|
|
97
100
|
"@types/jest": "^30.0.0",
|
|
98
|
-
"@types/node": "^25.
|
|
101
|
+
"@types/node": "^25.9.1",
|
|
99
102
|
"@types/semver": "^7.7.1",
|
|
100
103
|
"cross-env": "^10.1.0",
|
|
101
104
|
"del-cli": "^7.0.0",
|
|
102
105
|
"eslint": "9.39.1",
|
|
103
106
|
"eslint-plugin-regexp": "^3.1.0",
|
|
104
107
|
"eslint-plugin-security": "^4.0.0",
|
|
105
|
-
"globals": "^17.
|
|
106
|
-
"jest": "^30.
|
|
107
|
-
"jest-environment-node": "^30.
|
|
108
|
+
"globals": "^17.6.0",
|
|
109
|
+
"jest": "^30.4.2",
|
|
110
|
+
"jest-environment-node": "^30.4.1",
|
|
108
111
|
"jest-extended": "^7.0.0",
|
|
109
112
|
"node-gyp": "^12.3.0",
|
|
110
|
-
"npm-check-updates": "^22.
|
|
111
|
-
"npm-run-all2": "
|
|
113
|
+
"npm-check-updates": "^22.2.2",
|
|
114
|
+
"npm-run-all2": "9.0.1",
|
|
112
115
|
"prebuildify": "^6.0.1",
|
|
113
116
|
"prettier": "^3.8.3",
|
|
114
117
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
115
|
-
"terser": "^5.
|
|
116
|
-
"ts-jest": "^29.4.
|
|
118
|
+
"terser": "^5.48.0",
|
|
119
|
+
"ts-jest": "^29.4.11",
|
|
117
120
|
"tsup": "^8.5.1",
|
|
118
|
-
"tsx": "^4.
|
|
121
|
+
"tsx": "^4.22.4",
|
|
119
122
|
"typedoc": "^0.28.19",
|
|
120
123
|
"typescript": "^5.9.3",
|
|
121
124
|
"typescript-eslint": "^8.57.2"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/scripts/post-build.mjs
CHANGED
|
@@ -7,15 +7,24 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const distDir = join(__dirname, "..", "dist");
|
|
9
9
|
|
|
10
|
-
// Copy .d.ts to .d.cts
|
|
11
|
-
|
|
10
|
+
// Copy .d.ts to .d.cts and .d.mts so each exports condition resolves to a
|
|
11
|
+
// declaration file whose module format matches its JavaScript counterpart.
|
|
12
|
+
//
|
|
13
|
+
// Without a .d.mts file, the `import` condition's types (`index.d.ts`) are
|
|
14
|
+
// interpreted as CommonJS (the package has no `"type": "module"`), while the
|
|
15
|
+
// resolved JavaScript (`index.mjs`) is ESM. That mismatch is the "Masquerading
|
|
16
|
+
// as CJS" / FalseCJS problem reported by arethetypeswrong. A .d.cts pairs with
|
|
17
|
+
// the CJS `.cjs` output; a .d.mts pairs with the ESM `.mjs` output.
|
|
18
|
+
async function createDualTypes() {
|
|
12
19
|
try {
|
|
13
20
|
await copyFile(join(distDir, "index.d.ts"), join(distDir, "index.d.cts"));
|
|
14
21
|
console.log("Created index.d.cts for CommonJS type safety");
|
|
22
|
+
await copyFile(join(distDir, "index.d.ts"), join(distDir, "index.d.mts"));
|
|
23
|
+
console.log("Created index.d.mts for ESM type safety");
|
|
15
24
|
} catch (error) {
|
|
16
|
-
console.error("Error creating
|
|
25
|
+
console.error("Error creating dual declaration files:", error);
|
|
17
26
|
process.exit(1);
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
createDualTypes();
|
|
@@ -21,6 +21,11 @@ console.log(`Building for platform: ${currentPlatform}, arch: ${currentArch}`);
|
|
|
21
21
|
// Set up environment variables to help node-gyp
|
|
22
22
|
const env = { ...process.env };
|
|
23
23
|
|
|
24
|
+
// Architecture-specific compiler defines for Windows. Tracked in a local so we
|
|
25
|
+
// can log the value we set without reading it back out of the environment
|
|
26
|
+
// (which CodeQL flags as clear-text logging of process environment data).
|
|
27
|
+
let clDefines: string | undefined;
|
|
28
|
+
|
|
24
29
|
// Set architecture-specific defines for Windows
|
|
25
30
|
if (currentPlatform === "win32") {
|
|
26
31
|
// Try various environment variables that might work
|
|
@@ -30,9 +35,13 @@ if (currentPlatform === "win32") {
|
|
|
30
35
|
|
|
31
36
|
// Try setting compiler flags directly
|
|
32
37
|
if (currentArch === "x64") {
|
|
33
|
-
|
|
38
|
+
clDefines = "/D_M_X64 /D_WIN64 /D_AMD64_";
|
|
34
39
|
} else if (currentArch === "arm64") {
|
|
35
|
-
|
|
40
|
+
clDefines = "/D_M_ARM64 /D_WIN64";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (clDefines) {
|
|
44
|
+
env.CL = clDefines;
|
|
36
45
|
}
|
|
37
46
|
}
|
|
38
47
|
|
|
@@ -53,8 +62,8 @@ if (process.argv.length > 2) {
|
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
console.log(`Running: prebuildify ${args.join(" ")}`);
|
|
56
|
-
if (currentPlatform === "win32" &&
|
|
57
|
-
console.log(`CL environment variable: ${
|
|
65
|
+
if (currentPlatform === "win32" && clDefines) {
|
|
66
|
+
console.log(`CL environment variable: ${clDefines}`);
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
// Spawn prebuildify with the arguments
|
package/scripts/precommit.ts
CHANGED
|
@@ -36,6 +36,10 @@ run({ cmd: "npm run fmt", desc: "Formatting code" });
|
|
|
36
36
|
run({ cmd: "npm run lint", desc: "Running linting checks" });
|
|
37
37
|
run({ cmd: "npm run docs", desc: "TypeDoc generation" });
|
|
38
38
|
run({ cmd: "npm run build:dist", desc: "Building distribution files" });
|
|
39
|
+
run({
|
|
40
|
+
cmd: "npm run check:exports",
|
|
41
|
+
desc: "Verifying package exports & type declarations (arethetypeswrong)",
|
|
42
|
+
});
|
|
39
43
|
|
|
40
44
|
// Detect if we're using glibc (vs musl)
|
|
41
45
|
// Check process.report for musl loader - if not found, assume glibc
|
|
@@ -14,7 +14,8 @@ protected:
|
|
|
14
14
|
|
|
15
15
|
MetadataWorkerBase(const std::string &path,
|
|
16
16
|
const Napi::Promise::Deferred &deferred)
|
|
17
|
-
: SafeAsyncWorker(deferred.Env()), mountPoint(path), deferred_(deferred) {
|
|
17
|
+
: SafeAsyncWorker(deferred.Env()), mountPoint(path), deferred_(deferred) {
|
|
18
|
+
}
|
|
18
19
|
|
|
19
20
|
void OnError(const Napi::Error &error) override {
|
|
20
21
|
Napi::HandleScope scope(Env());
|
package/src/common/shutdown.h
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
// can never escape AsyncWorker callbacks.
|
|
5
5
|
//
|
|
6
6
|
// Why this exists: AsyncWorker::OnWorkComplete can run during
|
|
7
|
-
// node::FreeEnvironment cleanup. If napi_resolve_deferred /
|
|
8
|
-
// fail at that point (env tearing down), node-addon-api
|
|
9
|
-
// Napi::Error. With NAPI_CPP_EXCEPTIONS the rethrow path inside
|
|
7
|
+
// node::FreeEnvironment cleanup. If napi_resolve_deferred /
|
|
8
|
+
// napi_reject_deferred fail at that point (env tearing down), node-addon-api
|
|
9
|
+
// throws a C++ Napi::Error. With NAPI_CPP_EXCEPTIONS the rethrow path inside
|
|
10
10
|
// WrapVoidCallback then calls ThrowAsJavaScriptException, which can also fail,
|
|
11
11
|
// letting the C++ exception escape into a libuv cleanup hook frame that has
|
|
12
12
|
// no catch - terminate() / SIGABRT.
|
|
@@ -150,9 +150,7 @@ protected:
|
|
|
150
150
|
|
|
151
151
|
void SetError(const std::string &error) { error_ = error; }
|
|
152
152
|
|
|
153
|
-
bool IsShuttingDown() const {
|
|
154
|
-
return FSMeta::IsShuttingDown(shutdownState_);
|
|
155
|
-
}
|
|
153
|
+
bool IsShuttingDown() const { return FSMeta::IsShuttingDown(shutdownState_); }
|
|
156
154
|
|
|
157
155
|
private:
|
|
158
156
|
std::shared_ptr<ShutdownState> shutdownState_;
|
package/src/fs.ts
CHANGED
|
@@ -10,7 +10,10 @@ import { withTimeout } from "./async";
|
|
|
10
10
|
*/
|
|
11
11
|
export async function statAsync(
|
|
12
12
|
path: PathLike,
|
|
13
|
-
|
|
13
|
+
// `throwIfNoEntry?: true` selects the overload that resolves to
|
|
14
|
+
// Promise<Stats> rather than Promise<Stats | undefined>; this wrapper always
|
|
15
|
+
// throws (rather than returning undefined) when the path doesn't exist.
|
|
16
|
+
options?: StatOptions & { bigint?: false; throwIfNoEntry?: true },
|
|
14
17
|
): Promise<Stats> {
|
|
15
18
|
return stat(path, options);
|
|
16
19
|
}
|