@socketsecurity/lib 5.4.1 → 5.5.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 CHANGED
@@ -5,6 +5,22 @@ 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.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.5.0) - 2026-01-12
9
+
10
+ ### Added
11
+
12
+ - **dlx/detect**: Executable type detection utilities for DLX cache and local file paths
13
+ - `detectDlxExecutableType()`: Detects Node.js packages vs native binaries in DLX cache by checking for node_modules/ directory
14
+ - `detectExecutableType()`: Generic entry point that routes to appropriate detection strategy
15
+ - `detectLocalExecutableType()`: Detects executables on local filesystem by checking package.json bin field or file extension
16
+ - `isJsFilePath()`: Validates if a file path has .js, .mjs, or .cjs extension
17
+ - `isNativeBinary()`: Simplified helper that returns true for native binary executables
18
+ - `isNodePackage()`: Simplified helper that returns true for Node.js packages
19
+
20
+ ### Fixed
21
+
22
+ - **releases/github**: Sort releases by published_at to reliably find latest release instead of relying on creation order
23
+
8
24
  ## [5.4.1](https://github.com/SocketDev/socket-lib/releases/tag/v5.4.1) - 2026-01-10
9
25
 
10
26
  ### 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,38 @@ 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 (isMatch) {
143
+ const hasMatchingAsset = assets.some(
144
+ (a) => isMatch(a.name)
145
+ );
146
+ if (!hasMatchingAsset) {
147
+ return false;
148
+ }
147
149
  }
150
+ return true;
148
151
  }
152
+ );
153
+ if (matchingReleases.length === 0) {
149
154
  if (!quiet) {
150
- logger.info(`Found release: ${tag}`);
155
+ logger.info(`No ${toolPrefix} release found in latest 100 releases`);
151
156
  }
152
- return tag;
157
+ return null;
153
158
  }
159
+ matchingReleases.sort(
160
+ (a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime()
161
+ );
162
+ const latestRelease = matchingReleases[0];
163
+ const tag = latestRelease.tag_name;
154
164
  if (!quiet) {
155
- logger.info(`No ${toolPrefix} release found in latest 100 releases`);
165
+ logger.info(`Found release: ${tag}`);
156
166
  }
157
- return null;
167
+ return tag;
158
168
  },
159
169
  {
160
170
  ...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.0",
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"