@socketsecurity/lib 5.4.1 → 5.5.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/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [5.5.1](https://github.com/SocketDev/socket-lib/releases/tag/v5.5.1) - 2026-01-12
9
+
10
+ ### Fixed
11
+
12
+ - Fixed dotenvx compatibility with pre-commit hooks
13
+ - Fixed empty releases being returned when finding latest release
14
+
15
+ ## [5.5.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.5.0) - 2026-01-12
16
+
17
+ ### Added
18
+
19
+ - **dlx/detect**: Executable type detection utilities for DLX cache and local file paths
20
+ - `detectDlxExecutableType()`: Detects Node.js packages vs native binaries in DLX cache by checking for node_modules/ directory
21
+ - `detectExecutableType()`: Generic entry point that routes to appropriate detection strategy
22
+ - `detectLocalExecutableType()`: Detects executables on local filesystem by checking package.json bin field or file extension
23
+ - `isJsFilePath()`: Validates if a file path has .js, .mjs, or .cjs extension
24
+ - `isNativeBinary()`: Simplified helper that returns true for native binary executables
25
+ - `isNodePackage()`: Simplified helper that returns true for Node.js packages
26
+
27
+ ### Fixed
28
+
29
+ - **releases/github**: Sort releases by published_at to reliably find latest release instead of relying on creation order
30
+
8
31
  ## [5.4.1](https://github.com/SocketDev/socket-lib/releases/tag/v5.4.1) - 2026-01-10
9
32
 
10
33
  ### Fixed
@@ -0,0 +1,66 @@
1
+ export type ExecutableType = 'package' | 'binary' | 'unknown';
2
+ export interface ExecutableDetectionResult {
3
+ type: ExecutableType;
4
+ method: 'dlx-cache' | 'package-json' | 'file-extension';
5
+ packageJsonPath?: string;
6
+ inDlxCache?: boolean;
7
+ }
8
+ /**
9
+ * Detect if a path is a Node.js package or native binary executable.
10
+ * Works for both DLX cache paths and local filesystem paths.
11
+ *
12
+ * Detection strategy:
13
+ * 1. If in DLX cache: Use detectDlxExecutableType()
14
+ * 2. Otherwise: Use detectLocalExecutableType()
15
+ *
16
+ * @param filePath - Path to executable (DLX cache or local filesystem)
17
+ * @returns Detection result with type, method, and metadata
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const result = detectExecutableType('/path/to/tool')
22
+ * if (result.type === 'package') {
23
+ * spawnNode([filePath, ...args])
24
+ * } else {
25
+ * spawn(filePath, args)
26
+ * }
27
+ * ```
28
+ */
29
+ export declare function detectExecutableType(filePath: string): ExecutableDetectionResult;
30
+ /**
31
+ * Detect executable type for paths in DLX cache.
32
+ * Uses filesystem structure (node_modules/ presence).
33
+ *
34
+ * @param filePath - Path within DLX cache (~/.socket/_dlx/)
35
+ * @returns Detection result
36
+ */
37
+ export declare function detectDlxExecutableType(filePath: string): ExecutableDetectionResult;
38
+ /**
39
+ * Detect executable type for local filesystem paths.
40
+ * Uses package.json and file extension checks.
41
+ *
42
+ * @param filePath - Local filesystem path (not in DLX cache)
43
+ * @returns Detection result
44
+ */
45
+ export declare function detectLocalExecutableType(filePath: string): ExecutableDetectionResult;
46
+ /**
47
+ * Check if a file path indicates a Node.js script.
48
+ *
49
+ * @param filePath - Path to check
50
+ * @returns True if file has .js, .mjs, or .cjs extension
51
+ */
52
+ export declare function isJsFilePath(filePath: string): boolean;
53
+ /**
54
+ * Simplified helper: Is this a native binary executable?
55
+ *
56
+ * @param filePath - Path to check
57
+ * @returns True if detected as native binary (not Node.js package)
58
+ */
59
+ export declare function isNativeBinary(filePath: string): boolean;
60
+ /**
61
+ * Simplified helper: Is this a Node.js package?
62
+ *
63
+ * @param filePath - Path to check
64
+ * @returns True if detected as Node.js package
65
+ */
66
+ export declare function isNodePackage(filePath: string): boolean;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /* Socket Lib - Built with esbuild */
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var detect_exports = {};
21
+ __export(detect_exports, {
22
+ detectDlxExecutableType: () => detectDlxExecutableType,
23
+ detectExecutableType: () => detectExecutableType,
24
+ detectLocalExecutableType: () => detectLocalExecutableType,
25
+ isJsFilePath: () => isJsFilePath,
26
+ isNativeBinary: () => isNativeBinary,
27
+ isNodePackage: () => isNodePackage
28
+ });
29
+ module.exports = __toCommonJS(detect_exports);
30
+ var import_paths = require("./paths");
31
+ var import_socket = require("../paths/socket");
32
+ let _fs;
33
+ let _path;
34
+ // @__NO_SIDE_EFFECTS__
35
+ function getFs() {
36
+ if (_fs === void 0) {
37
+ _fs = require("fs");
38
+ }
39
+ return _fs;
40
+ }
41
+ // @__NO_SIDE_EFFECTS__
42
+ function getPath() {
43
+ if (_path === void 0) {
44
+ _path = require("path");
45
+ }
46
+ return _path;
47
+ }
48
+ const NODE_JS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs"]);
49
+ function detectExecutableType(filePath) {
50
+ if ((0, import_paths.isInSocketDlx)(filePath)) {
51
+ return detectDlxExecutableType(filePath);
52
+ }
53
+ return detectLocalExecutableType(filePath);
54
+ }
55
+ function detectDlxExecutableType(filePath) {
56
+ const fs = /* @__PURE__ */ getFs();
57
+ const path = /* @__PURE__ */ getPath();
58
+ const dlxDir = (0, import_socket.getSocketDlxDir)();
59
+ const absolutePath = path.resolve(filePath);
60
+ const relativePath = path.relative(dlxDir, absolutePath);
61
+ const cacheKey = relativePath.split(path.sep)[0];
62
+ const cacheDir = path.join(dlxDir, cacheKey);
63
+ if (fs.existsSync(path.join(cacheDir, "node_modules"))) {
64
+ return {
65
+ type: "package",
66
+ method: "dlx-cache",
67
+ inDlxCache: true
68
+ };
69
+ }
70
+ return {
71
+ type: "binary",
72
+ method: "dlx-cache",
73
+ inDlxCache: true
74
+ };
75
+ }
76
+ function detectLocalExecutableType(filePath) {
77
+ const fs = /* @__PURE__ */ getFs();
78
+ const packageJsonPath = findPackageJson(filePath);
79
+ if (packageJsonPath !== void 0) {
80
+ try {
81
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
82
+ if (packageJson.bin) {
83
+ return {
84
+ type: "package",
85
+ method: "package-json",
86
+ packageJsonPath,
87
+ inDlxCache: false
88
+ };
89
+ }
90
+ } catch {
91
+ }
92
+ }
93
+ if (isJsFilePath(filePath)) {
94
+ return {
95
+ inDlxCache: false,
96
+ method: "file-extension",
97
+ type: "package"
98
+ };
99
+ }
100
+ return {
101
+ type: "binary",
102
+ method: "file-extension",
103
+ inDlxCache: false
104
+ };
105
+ }
106
+ function findPackageJson(filePath) {
107
+ const fs = /* @__PURE__ */ getFs();
108
+ const path = /* @__PURE__ */ getPath();
109
+ let currentDir = path.dirname(path.resolve(filePath));
110
+ const root = path.parse(currentDir).root;
111
+ while (currentDir !== root) {
112
+ const packageJsonPath = path.join(currentDir, "package.json");
113
+ if (fs.existsSync(packageJsonPath)) {
114
+ return packageJsonPath;
115
+ }
116
+ currentDir = path.dirname(currentDir);
117
+ }
118
+ return void 0;
119
+ }
120
+ function isJsFilePath(filePath) {
121
+ const path = /* @__PURE__ */ getPath();
122
+ const ext = path.extname(filePath).toLowerCase();
123
+ return NODE_JS_EXTENSIONS.has(ext);
124
+ }
125
+ function isNativeBinary(filePath) {
126
+ return detectExecutableType(filePath).type === "binary";
127
+ }
128
+ function isNodePackage(filePath) {
129
+ return detectExecutableType(filePath).type === "package";
130
+ }
131
+ // Annotate the CommonJS export names for ESM import in node:
132
+ 0 && (module.exports = {
133
+ detectDlxExecutableType,
134
+ detectExecutableType,
135
+ detectLocalExecutableType,
136
+ isJsFilePath,
137
+ isNativeBinary,
138
+ isNodePackage
139
+ });
@@ -133,28 +133,41 @@ async function getLatestRelease(toolPrefix, repoConfig, options = {}) {
133
133
  throw new Error(`Failed to fetch releases: ${response.status}`);
134
134
  }
135
135
  const releases = JSON.parse(response.body.toString("utf8"));
136
- for (const release of releases) {
137
- const { assets, tag_name: tag } = release;
138
- if (!tag.startsWith(toolPrefix)) {
139
- continue;
140
- }
141
- if (isMatch) {
142
- const hasMatchingAsset = assets.some(
143
- (a) => isMatch(a.name)
144
- );
145
- if (!hasMatchingAsset) {
146
- continue;
136
+ const matchingReleases = releases.filter(
137
+ (release) => {
138
+ const { assets, tag_name: tag2 } = release;
139
+ if (!tag2.startsWith(toolPrefix)) {
140
+ return false;
141
+ }
142
+ if (!assets || assets.length === 0) {
143
+ return false;
147
144
  }
145
+ if (isMatch) {
146
+ const hasMatchingAsset = assets.some(
147
+ (a) => isMatch(a.name)
148
+ );
149
+ if (!hasMatchingAsset) {
150
+ return false;
151
+ }
152
+ }
153
+ return true;
148
154
  }
155
+ );
156
+ if (matchingReleases.length === 0) {
149
157
  if (!quiet) {
150
- logger.info(`Found release: ${tag}`);
158
+ logger.info(`No ${toolPrefix} release found in latest 100 releases`);
151
159
  }
152
- return tag;
160
+ return null;
153
161
  }
162
+ matchingReleases.sort(
163
+ (a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime()
164
+ );
165
+ const latestRelease = matchingReleases[0];
166
+ const tag = latestRelease.tag_name;
154
167
  if (!quiet) {
155
- logger.info(`No ${toolPrefix} release found in latest 100 releases`);
168
+ logger.info(`Found release: ${tag}`);
156
169
  }
157
- return null;
170
+ return tag;
158
171
  },
159
172
  {
160
173
  ...RETRY_CONFIG,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@socketsecurity/lib",
3
- "version": "5.4.1",
4
- "packageManager": "pnpm@10.27.0",
3
+ "version": "5.5.1",
4
+ "packageManager": "pnpm@10.28.0",
5
5
  "license": "MIT",
6
6
  "description": "Core utilities and infrastructure for Socket.dev security tools",
7
7
  "keywords": [
@@ -227,6 +227,10 @@
227
227
  "types": "./dist/dlx/cache.d.ts",
228
228
  "default": "./dist/dlx/cache.js"
229
229
  },
230
+ "./dlx/detect": {
231
+ "types": "./dist/dlx/detect.d.ts",
232
+ "default": "./dist/dlx/detect.js"
233
+ },
230
234
  "./dlx/dir": {
231
235
  "types": "./dist/dlx/dir.d.ts",
232
236
  "default": "./dist/dlx/dir.js"
@@ -722,7 +726,7 @@
722
726
  "@socketregistry/is-unicode-supported": "1.0.5",
723
727
  "@socketregistry/packageurl-js": "1.3.5",
724
728
  "@socketregistry/yocto-spinner": "1.0.25",
725
- "@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.4.0",
729
+ "@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.5.0",
726
730
  "@types/node": "24.9.2",
727
731
  "@typescript/native-preview": "7.0.0-dev.20250920.1",
728
732
  "@vitest/coverage-v8": "4.0.3",
@@ -791,6 +795,7 @@
791
795
  "@sigstore/sign": "4.1.0",
792
796
  "ansi-regex": "6.2.2",
793
797
  "debug": "4.4.3",
798
+ "execa": "5.1.1",
794
799
  "has-flag": "5.0.1",
795
800
  "isexe": "3.1.1",
796
801
  "lru-cache": "11.2.2",
@@ -808,7 +813,8 @@
808
813
  "patchedDependencies": {
809
814
  "@npmcli/run-script@10.0.0": "patches/@npmcli__run-script@10.0.0.patch",
810
815
  "@sigstore/sign@4.1.0": "patches/@sigstore__sign@4.1.0.patch",
811
- "node-gyp@11.5.0": "patches/node-gyp@11.5.0.patch"
816
+ "node-gyp@11.5.0": "patches/node-gyp@11.5.0.patch",
817
+ "execa@5.1.1": "patches/execa@5.1.1.patch"
812
818
  }
813
819
  }
814
820
  }