@socketsecurity/lib
Advanced tools
| /** | ||
| * @fileoverview NPM lifecycle script names. | ||
| * | ||
| * Standard npm lifecycle hooks that can be defined in package.json scripts. | ||
| * https://docs.npmjs.com/cli/v10/using-npm/scripts#life-cycle-scripts | ||
| */ | ||
| declare const lifecycleScriptNames: Set<string>; | ||
| export { lifecycleScriptNames }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var lifecycle_script_names_exports = {}; | ||
| __export(lifecycle_script_names_exports, { | ||
| lifecycleScriptNames: () => lifecycleScriptNames | ||
| }); | ||
| module.exports = __toCommonJS(lifecycle_script_names_exports); | ||
| const lifecycleScriptNames = new Set( | ||
| [ | ||
| "dependencies", | ||
| "prepublishOnly", | ||
| ...[ | ||
| "install", | ||
| "pack", | ||
| "prepare", | ||
| "publish", | ||
| "restart", | ||
| "start", | ||
| "stop", | ||
| "version" | ||
| ].map((n) => [`pre${n}`, n, `post${n}`]) | ||
| ].flat() | ||
| ); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| lifecycleScriptNames | ||
| }); |
| declare const maintainedNodeVersions: readonly string[] & { | ||
| current: string; | ||
| last: string; | ||
| next: string; | ||
| previous: string; | ||
| }; | ||
| export { maintainedNodeVersions }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var maintained_node_versions_exports = {}; | ||
| __export(maintained_node_versions_exports, { | ||
| maintainedNodeVersions: () => maintainedNodeVersions | ||
| }); | ||
| module.exports = __toCommonJS(maintained_node_versions_exports); | ||
| const ObjectFreeze = Object.freeze; | ||
| const next = "25.0.0"; | ||
| const current = "22.20.0"; | ||
| const previous = "20.19.5"; | ||
| const last = "18.20.8"; | ||
| const maintainedNodeVersions = ObjectFreeze( | ||
| Object.assign([last, previous, current, next], { | ||
| current, | ||
| last, | ||
| next, | ||
| previous | ||
| }) | ||
| ); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| maintainedNodeVersions | ||
| }); |
| /* c8 ignore next - External semver call */ | ||
| declare const packageDefaultNodeRange: string; | ||
| export { packageDefaultNodeRange }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var package_default_node_range_exports = {}; | ||
| __export(package_default_node_range_exports, { | ||
| packageDefaultNodeRange: () => packageDefaultNodeRange | ||
| }); | ||
| module.exports = __toCommonJS(package_default_node_range_exports); | ||
| var import_maintained_node_versions = require("./maintained-node-versions"); | ||
| var semver = __toESM(require("../external/semver.js")); | ||
| const packageDefaultNodeRange = `>=${semver.parse(import_maintained_node_versions.maintainedNodeVersions.last).major}`; | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| packageDefaultNodeRange | ||
| }); |
| /** | ||
| * @fileoverview Default Socket security categories for packages. | ||
| */ | ||
| // Default category for new packages | ||
| declare const packageDefaultSocketCategories: readonly string[]; | ||
| export { packageDefaultSocketCategories }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var package_default_socket_categories_exports = {}; | ||
| __export(package_default_socket_categories_exports, { | ||
| packageDefaultSocketCategories: () => packageDefaultSocketCategories | ||
| }); | ||
| module.exports = __toCommonJS(package_default_socket_categories_exports); | ||
| const packageDefaultSocketCategories = Object.freeze(["cleanup"]); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| packageDefaultSocketCategories | ||
| }); |
| import type { SpawnExtra, SpawnOptions } from '../spawn'; | ||
| import { spawn } from '../spawn'; | ||
| export interface DlxBinaryOptions { | ||
| /** | ||
| * URL to download the binary from. | ||
| */ | ||
| url: string; | ||
| /** | ||
| * Optional name for the cached binary (defaults to URL hash). | ||
| */ | ||
| name?: string | undefined; | ||
| /** | ||
| * Expected checksum (sha256) for verification. | ||
| */ | ||
| checksum?: string | undefined; | ||
| /** | ||
| * Cache TTL in milliseconds (default: 7 days). | ||
| */ | ||
| cacheTtl?: number | undefined; | ||
| /** | ||
| * Force re-download even if cached. | ||
| * Aligns with npm/npx --force flag. | ||
| */ | ||
| force?: boolean | undefined; | ||
| /** | ||
| * Skip confirmation prompts (auto-approve). | ||
| * Aligns with npx --yes/-y flag. | ||
| */ | ||
| yes?: boolean | undefined; | ||
| /** | ||
| * Suppress output (quiet mode). | ||
| * Aligns with npx --quiet/-q and pnpm --silent/-s flags. | ||
| */ | ||
| quiet?: boolean | undefined; | ||
| /** | ||
| * Additional spawn options. | ||
| */ | ||
| spawnOptions?: SpawnOptions | undefined; | ||
| } | ||
| export interface DlxBinaryResult { | ||
| /** Path to the cached binary. */ | ||
| binaryPath: string; | ||
| /** Whether the binary was newly downloaded. */ | ||
| downloaded: boolean; | ||
| /** The spawn promise for the running process. */ | ||
| spawnPromise: ReturnType<typeof spawn>; | ||
| } | ||
| /** | ||
| * Metadata structure for cached binaries (.dlx-metadata.json). | ||
| * Unified schema shared across TypeScript (dlxBinary) and C++ (socket_macho_decompress). | ||
| * | ||
| * Core Fields (present in all implementations): | ||
| * - version: Schema version (currently "1.0.0") | ||
| * - cache_key: First 16 chars of SHA-512 hash (matches directory name) | ||
| * - timestamp: Unix timestamp in milliseconds | ||
| * - checksum: Full hash of cached binary (SHA-512 for C++, SHA-256 for TypeScript) | ||
| * - checksum_algorithm: "sha512" or "sha256" | ||
| * - platform: "darwin" | "linux" | "win32" | ||
| * - arch: "x64" | "arm64" | ||
| * - size: Size of cached binary in bytes | ||
| * - source: Origin information | ||
| * - type: "download" (from URL) or "decompression" (from embedded binary) | ||
| * - url: Download URL (if type is "download") | ||
| * - path: Source binary path (if type is "decompression") | ||
| * | ||
| * Extra Fields (implementation-specific): | ||
| * - For C++ decompression: | ||
| * - compressed_size: Size of compressed data in bytes | ||
| * - compression_algorithm: Brotli level (numeric) | ||
| * - compression_ratio: original_size / compressed_size | ||
| * | ||
| * Example (TypeScript download): | ||
| * ```json | ||
| * { | ||
| * "version": "1.0.0", | ||
| * "cache_key": "a1b2c3d4e5f67890", | ||
| * "timestamp": 1730332800000, | ||
| * "checksum": "sha256-abc123...", | ||
| * "checksum_algorithm": "sha256", | ||
| * "platform": "darwin", | ||
| * "arch": "arm64", | ||
| * "size": 15000000, | ||
| * "source": { | ||
| * "type": "download", | ||
| * "url": "https://example.com/binary" | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * Example (C++ decompression): | ||
| * ```json | ||
| * { | ||
| * "version": "1.0.0", | ||
| * "cache_key": "0123456789abcdef", | ||
| * "timestamp": 1730332800000, | ||
| * "checksum": "sha512-def456...", | ||
| * "checksum_algorithm": "sha512", | ||
| * "platform": "darwin", | ||
| * "arch": "arm64", | ||
| * "size": 13000000, | ||
| * "source": { | ||
| * "type": "decompression", | ||
| * "path": "/usr/local/bin/socket" | ||
| * }, | ||
| * "extra": { | ||
| * "compressed_size": 1700000, | ||
| * "compression_algorithm": 3, | ||
| * "compression_ratio": 7.647 | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * @internal This interface documents the metadata file format. | ||
| */ | ||
| export interface DlxMetadata { | ||
| version: string; | ||
| cache_key: string; | ||
| timestamp: number; | ||
| checksum: string; | ||
| checksum_algorithm: string; | ||
| platform: string; | ||
| arch: string; | ||
| size: number; | ||
| source?: { | ||
| type: 'download' | 'decompression'; | ||
| url?: string; | ||
| path?: string; | ||
| }; | ||
| extra?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Clean expired entries from the DLX cache. | ||
| */ | ||
| export declare function cleanDlxCache(maxAge?: number): Promise<number>; | ||
| /** | ||
| * Download and execute a binary from a URL with caching. | ||
| */ | ||
| export declare function dlxBinary(args: readonly string[] | string[], options?: DlxBinaryOptions | undefined, spawnExtra?: SpawnExtra | undefined): Promise<DlxBinaryResult>; | ||
| /** | ||
| * Download a binary from a URL with caching (without execution). | ||
| * Similar to downloadPackage from dlx-package. | ||
| * | ||
| * @returns Object containing the path to the cached binary and whether it was downloaded | ||
| */ | ||
| export declare function downloadBinary(options: Omit<DlxBinaryOptions, 'spawnOptions'>): Promise<{ | ||
| binaryPath: string; | ||
| downloaded: boolean; | ||
| }>; | ||
| /** | ||
| * Execute a cached binary without re-downloading. | ||
| * Similar to executePackage from dlx-package. | ||
| * Binary must have been previously downloaded via downloadBinary or dlxBinary. | ||
| * | ||
| * @param binaryPath Path to the cached binary (from downloadBinary result) | ||
| * @param args Arguments to pass to the binary | ||
| * @param spawnOptions Spawn options for execution | ||
| * @param spawnExtra Extra spawn configuration | ||
| * @returns The spawn promise for the running process | ||
| */ | ||
| export declare function executeBinary(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>; | ||
| /** | ||
| * Get the DLX binary cache directory path. | ||
| * Returns normalized path for cross-platform compatibility. | ||
| * Uses same directory as dlx-package for unified DLX storage. | ||
| */ | ||
| export declare function getDlxCachePath(): string; | ||
| /** | ||
| * Get information about cached binaries. | ||
| */ | ||
| export declare function listDlxCache(): Promise<Array<{ | ||
| age: number; | ||
| arch: string; | ||
| checksum: string; | ||
| name: string; | ||
| platform: string; | ||
| size: number; | ||
| url: string; | ||
| }>>; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var binary_exports = {}; | ||
| __export(binary_exports, { | ||
| cleanDlxCache: () => cleanDlxCache, | ||
| dlxBinary: () => dlxBinary, | ||
| downloadBinary: () => downloadBinary, | ||
| executeBinary: () => executeBinary, | ||
| getDlxCachePath: () => getDlxCachePath, | ||
| listDlxCache: () => listDlxCache | ||
| }); | ||
| module.exports = __toCommonJS(binary_exports); | ||
| var import_crypto = require("crypto"); | ||
| var import_os = __toESM(require("os")); | ||
| var import_path = __toESM(require("path")); | ||
| var import_platform = require("../constants/platform"); | ||
| var import_time = require("../constants/time"); | ||
| var import_cache = require("./cache"); | ||
| var import_manifest = require("./manifest"); | ||
| var import_http_request = require("../http-request"); | ||
| var import_fs = require("../fs"); | ||
| var import_objects = require("../objects"); | ||
| var import_normalize = require("../paths/normalize"); | ||
| var import_socket = require("../paths/socket"); | ||
| var import_process_lock = require("../process-lock"); | ||
| var import_spawn = require("../spawn"); | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| function getMetadataPath(cacheEntryPath) { | ||
| return import_path.default.join(cacheEntryPath, ".dlx-metadata.json"); | ||
| } | ||
| async function isCacheValid(cacheEntryPath, cacheTtl) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| const metaPath = getMetadataPath(cacheEntryPath); | ||
| if (!fs.existsSync(metaPath)) { | ||
| return false; | ||
| } | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!(0, import_objects.isObjectObject)(metadata)) { | ||
| return false; | ||
| } | ||
| const now = Date.now(); | ||
| const timestamp = metadata["timestamp"]; | ||
| if (typeof timestamp !== "number" || timestamp <= 0) { | ||
| return false; | ||
| } | ||
| const age = now - timestamp; | ||
| return age < cacheTtl; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| async function downloadBinaryFile(url, destPath, checksum) { | ||
| const cacheEntryDir = import_path.default.dirname(destPath); | ||
| const lockPath = import_path.default.join(cacheEntryDir, "concurrency.lock"); | ||
| return await import_process_lock.processLock.withLock( | ||
| lockPath, | ||
| async () => { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (fs.existsSync(destPath)) { | ||
| const stats = await fs.promises.stat(destPath); | ||
| if (stats.size > 0) { | ||
| const fileBuffer2 = await fs.promises.readFile(destPath); | ||
| const hasher2 = (0, import_crypto.createHash)("sha256"); | ||
| hasher2.update(fileBuffer2); | ||
| return hasher2.digest("hex"); | ||
| } | ||
| } | ||
| try { | ||
| await (0, import_http_request.httpDownload)(url, destPath); | ||
| } catch (e) { | ||
| throw new Error( | ||
| `Failed to download binary from ${url} | ||
| Destination: ${destPath} | ||
| Check your internet connection or verify the URL is accessible.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| const fileBuffer = await fs.promises.readFile(destPath); | ||
| const hasher = (0, import_crypto.createHash)("sha256"); | ||
| hasher.update(fileBuffer); | ||
| const actualChecksum = hasher.digest("hex"); | ||
| if (checksum && actualChecksum !== checksum) { | ||
| await (0, import_fs.safeDelete)(destPath); | ||
| throw new Error( | ||
| `Checksum mismatch: expected ${checksum}, got ${actualChecksum}` | ||
| ); | ||
| } | ||
| if (!import_platform.WIN32) { | ||
| await fs.promises.chmod(destPath, 493); | ||
| } | ||
| return actualChecksum; | ||
| }, | ||
| { | ||
| // Align with npm npx locking strategy. | ||
| staleMs: 5e3, | ||
| touchIntervalMs: 2e3 | ||
| } | ||
| ); | ||
| } | ||
| async function writeMetadata(cacheEntryPath, cacheKey, url, binaryName, checksum, size) { | ||
| const metaPath = getMetadataPath(cacheEntryPath); | ||
| const metadata = { | ||
| version: "1.0.0", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| checksum, | ||
| checksum_algorithm: "sha256", | ||
| platform: import_os.default.platform(), | ||
| arch: import_os.default.arch(), | ||
| size, | ||
| source: { | ||
| type: "download", | ||
| url | ||
| } | ||
| }; | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2)); | ||
| try { | ||
| const spec = `${url}:${binaryName}`; | ||
| await import_manifest.dlxManifest.setBinaryEntry(spec, cacheKey, { | ||
| checksum, | ||
| checksum_algorithm: "sha256", | ||
| platform: import_os.default.platform(), | ||
| arch: import_os.default.arch(), | ||
| size, | ||
| source: { | ||
| type: "download", | ||
| url | ||
| } | ||
| }); | ||
| } catch { | ||
| } | ||
| } | ||
| async function cleanDlxCache(maxAge = import_time.DLX_BINARY_CACHE_TTL) { | ||
| const cacheDir = getDlxCachePath(); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (!fs.existsSync(cacheDir)) { | ||
| return 0; | ||
| } | ||
| let cleaned = 0; | ||
| const now = Date.now(); | ||
| const entries = await fs.promises.readdir(cacheDir); | ||
| for (const entry of entries) { | ||
| const entryPath = import_path.default.join(cacheDir, entry); | ||
| const metaPath = getMetadataPath(entryPath); | ||
| try { | ||
| if (!await (0, import_fs.isDir)(entryPath)) { | ||
| continue; | ||
| } | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) { | ||
| continue; | ||
| } | ||
| const timestamp = metadata["timestamp"]; | ||
| const age = typeof timestamp === "number" && timestamp > 0 ? now - timestamp : Number.POSITIVE_INFINITY; | ||
| if (age > maxAge) { | ||
| await (0, import_fs.safeDelete)(entryPath, { force: true, recursive: true }); | ||
| cleaned += 1; | ||
| } | ||
| } catch { | ||
| try { | ||
| const contents = await fs.promises.readdir(entryPath); | ||
| if (!contents.length) { | ||
| await (0, import_fs.safeDelete)(entryPath); | ||
| cleaned += 1; | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| return cleaned; | ||
| } | ||
| async function dlxBinary(args, options, spawnExtra) { | ||
| const { | ||
| cacheTtl = import_time.DLX_BINARY_CACHE_TTL, | ||
| checksum, | ||
| force: userForce = false, | ||
| name, | ||
| spawnOptions, | ||
| url, | ||
| yes | ||
| } = { __proto__: null, ...options }; | ||
| const force = yes === true ? true : userForce; | ||
| const cacheDir = getDlxCachePath(); | ||
| const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`; | ||
| const spec = `${url}:${binaryName}`; | ||
| const cacheKey = (0, import_cache.generateCacheKey)(spec); | ||
| const cacheEntryDir = import_path.default.join(cacheDir, cacheKey); | ||
| const binaryPath = (0, import_normalize.normalizePath)(import_path.default.join(cacheEntryDir, binaryName)); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| let downloaded = false; | ||
| let computedChecksum = checksum; | ||
| if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) { | ||
| try { | ||
| const metaPath = getMetadataPath(cacheEntryDir); | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (metadata && typeof metadata === "object" && !Array.isArray(metadata) && typeof metadata["checksum"] === "string") { | ||
| computedChecksum = metadata["checksum"]; | ||
| } else { | ||
| downloaded = true; | ||
| } | ||
| } catch { | ||
| downloaded = true; | ||
| } | ||
| } else { | ||
| downloaded = true; | ||
| } | ||
| if (downloaded) { | ||
| try { | ||
| await (0, import_fs.safeMkdir)(cacheEntryDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating binary cache directory: ${cacheEntryDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to create binary cache directory: ${cacheEntryDir}`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| computedChecksum = await downloadBinaryFile(url, binaryPath, checksum); | ||
| const stats = await fs.promises.stat(binaryPath); | ||
| await writeMetadata( | ||
| cacheEntryDir, | ||
| cacheKey, | ||
| url, | ||
| binaryName, | ||
| computedChecksum || "", | ||
| stats.size | ||
| ); | ||
| } | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const finalSpawnOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| env: { | ||
| ...spawnOptions?.env, | ||
| PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}` | ||
| }, | ||
| shell: true | ||
| } : spawnOptions; | ||
| const spawnPromise = (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra); | ||
| return { | ||
| binaryPath, | ||
| downloaded, | ||
| spawnPromise | ||
| }; | ||
| } | ||
| async function downloadBinary(options) { | ||
| const { | ||
| cacheTtl = import_time.DLX_BINARY_CACHE_TTL, | ||
| checksum, | ||
| force = false, | ||
| name, | ||
| url | ||
| } = { __proto__: null, ...options }; | ||
| const cacheDir = getDlxCachePath(); | ||
| const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`; | ||
| const spec = `${url}:${binaryName}`; | ||
| const cacheKey = (0, import_cache.generateCacheKey)(spec); | ||
| const cacheEntryDir = import_path.default.join(cacheDir, cacheKey); | ||
| const binaryPath = (0, import_normalize.normalizePath)(import_path.default.join(cacheEntryDir, binaryName)); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| let downloaded = false; | ||
| if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) { | ||
| downloaded = false; | ||
| } else { | ||
| try { | ||
| await (0, import_fs.safeMkdir)(cacheEntryDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating binary cache directory: ${cacheEntryDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to create binary cache directory: ${cacheEntryDir}`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| const computedChecksum = await downloadBinaryFile(url, binaryPath, checksum); | ||
| const stats = await fs.promises.stat(binaryPath); | ||
| await writeMetadata( | ||
| cacheEntryDir, | ||
| cacheKey, | ||
| url, | ||
| binaryName, | ||
| computedChecksum || "", | ||
| stats.size | ||
| ); | ||
| downloaded = true; | ||
| } | ||
| return { | ||
| binaryPath, | ||
| downloaded | ||
| }; | ||
| } | ||
| function executeBinary(binaryPath, args, spawnOptions, spawnExtra) { | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const cacheEntryDir = import_path.default.dirname(binaryPath); | ||
| const finalSpawnOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| env: { | ||
| ...spawnOptions?.env, | ||
| PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}` | ||
| }, | ||
| shell: true | ||
| } : spawnOptions; | ||
| return (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra); | ||
| } | ||
| function getDlxCachePath() { | ||
| return (0, import_socket.getSocketDlxDir)(); | ||
| } | ||
| async function listDlxCache() { | ||
| const cacheDir = getDlxCachePath(); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (!fs.existsSync(cacheDir)) { | ||
| return []; | ||
| } | ||
| const results = []; | ||
| const now = Date.now(); | ||
| const entries = await fs.promises.readdir(cacheDir); | ||
| for (const entry of entries) { | ||
| const entryPath = import_path.default.join(cacheDir, entry); | ||
| try { | ||
| if (!await (0, import_fs.isDir)(entryPath)) { | ||
| continue; | ||
| } | ||
| const metaPath = getMetadataPath(entryPath); | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) { | ||
| continue; | ||
| } | ||
| const metaObj = metadata; | ||
| const source = metaObj["source"]; | ||
| const url = source?.["url"] || metaObj["url"] || ""; | ||
| const files = await fs.promises.readdir(entryPath); | ||
| const binaryFile = files.find((f) => !f.startsWith(".")); | ||
| if (binaryFile) { | ||
| const binaryPath = import_path.default.join(entryPath, binaryFile); | ||
| const binaryStats = await fs.promises.stat(binaryPath); | ||
| results.push({ | ||
| age: now - (metaObj["timestamp"] || 0), | ||
| arch: metaObj["arch"] || "unknown", | ||
| checksum: metaObj["checksum"] || "", | ||
| name: binaryFile, | ||
| platform: metaObj["platform"] || "unknown", | ||
| size: binaryStats.size, | ||
| url | ||
| }); | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| return results; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| cleanDlxCache, | ||
| dlxBinary, | ||
| downloadBinary, | ||
| executeBinary, | ||
| getDlxCachePath, | ||
| listDlxCache | ||
| }); |
| /** | ||
| * Generate a cache directory name using npm/npx approach. | ||
| * Uses first 16 characters of SHA-512 hash (like npm/npx). | ||
| * | ||
| * Rationale for SHA-512 truncated (vs full SHA-256): | ||
| * - Matches npm/npx ecosystem behavior | ||
| * - Shorter paths for Windows MAX_PATH compatibility (260 chars) | ||
| * - 16 hex chars = 64 bits = acceptable collision risk for local cache | ||
| * - Collision probability ~1 in 18 quintillion with 1000 entries | ||
| * | ||
| * Input strategy (aligned with npx): | ||
| * - npx uses package spec strings (e.g., '@scope/pkg@1.0.0', 'prettier@3.0.0') | ||
| * - Caller provides complete spec string with version for accurate cache keying | ||
| * - For package installs: Use PURL-style spec with version | ||
| * Examples: 'npm:prettier@3.0.0', 'pypi:requests@2.31.0', 'gem:rails@7.0.0' | ||
| * Note: Socket uses shorthand format without 'pkg:' prefix | ||
| * (handled by @socketregistry/packageurl-js) | ||
| * - For binary downloads: Use URL:name for uniqueness | ||
| * | ||
| * Reference: npm/cli v11.6.2 libnpmexec/lib/index.js#L233-L244 | ||
| * https://github.com/npm/cli/blob/v11.6.2/workspaces/libnpmexec/lib/index.js#L233-L244 | ||
| * Implementation: packages.map().sort().join('\n') → SHA-512 → slice(0,16) | ||
| * npx hashes the package spec (name@version), not just name | ||
| */ | ||
| export declare function generateCacheKey(spec: string): string; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var cache_exports = {}; | ||
| __export(cache_exports, { | ||
| generateCacheKey: () => generateCacheKey | ||
| }); | ||
| module.exports = __toCommonJS(cache_exports); | ||
| var import_node_crypto = require("node:crypto"); | ||
| function generateCacheKey(spec) { | ||
| return (0, import_node_crypto.createHash)("sha512").update(spec).digest("hex").substring(0, 16); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| generateCacheKey | ||
| }); |
| /** | ||
| * Clear all DLX package installations. | ||
| */ | ||
| export declare function clearDlx(): Promise<void>; | ||
| /** | ||
| * Clear all DLX package installations synchronously. | ||
| */ | ||
| export declare function clearDlxSync(): void; | ||
| /** | ||
| * Check if the DLX directory exists. | ||
| */ | ||
| export declare function dlxDirExists(): boolean; | ||
| /** | ||
| * Check if the DLX directory exists asynchronously. | ||
| */ | ||
| export declare function dlxDirExistsAsync(): Promise<boolean>; | ||
| /** | ||
| * Ensure the DLX directory exists, creating it if necessary. | ||
| */ | ||
| export declare function ensureDlxDir(): Promise<void>; | ||
| /** | ||
| * Ensure the DLX directory exists synchronously, creating it if necessary. | ||
| */ | ||
| export declare function ensureDlxDirSync(): void; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var dir_exports = {}; | ||
| __export(dir_exports, { | ||
| clearDlx: () => clearDlx, | ||
| clearDlxSync: () => clearDlxSync, | ||
| dlxDirExists: () => dlxDirExists, | ||
| dlxDirExistsAsync: () => dlxDirExistsAsync, | ||
| ensureDlxDir: () => ensureDlxDir, | ||
| ensureDlxDirSync: () => ensureDlxDirSync | ||
| }); | ||
| module.exports = __toCommonJS(dir_exports); | ||
| var import_fs = require("../fs"); | ||
| var import_socket = require("../paths/socket"); | ||
| var import_promises = require("../promises"); | ||
| var import_packages = require("./packages"); | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| async function clearDlx() { | ||
| const packages = await (0, import_packages.listDlxPackagesAsync)(); | ||
| await (0, import_promises.pEach)(packages, (pkg) => (0, import_packages.removeDlxPackage)(pkg)); | ||
| } | ||
| function clearDlxSync() { | ||
| const packages = (0, import_packages.listDlxPackages)(); | ||
| for (const pkg of packages) { | ||
| (0, import_packages.removeDlxPackageSync)(pkg); | ||
| } | ||
| } | ||
| function dlxDirExists() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| return fs.existsSync((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| async function dlxDirExistsAsync() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| await fs.promises.access((0, import_socket.getSocketDlxDir)()); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| async function ensureDlxDir() { | ||
| await (0, import_fs.safeMkdir)((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| function ensureDlxDirSync() { | ||
| (0, import_fs.safeMkdirSync)((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| clearDlx, | ||
| clearDlxSync, | ||
| dlxDirExists, | ||
| dlxDirExistsAsync, | ||
| ensureDlxDir, | ||
| ensureDlxDirSync | ||
| }); |
| /** | ||
| * Details for npm package entries. | ||
| */ | ||
| export interface PackageDetails { | ||
| installed_version: string; | ||
| size?: number; | ||
| update_check?: { | ||
| last_check: number; | ||
| last_notification: number; | ||
| latest_known: string; | ||
| }; | ||
| } | ||
| /** | ||
| * Details for binary download entries. | ||
| */ | ||
| export interface BinaryDetails { | ||
| checksum: string; | ||
| checksum_algorithm: 'sha256' | 'sha512'; | ||
| platform: string; | ||
| arch: string; | ||
| size: number; | ||
| source: { | ||
| type: 'download'; | ||
| url: string; | ||
| }; | ||
| } | ||
| /** | ||
| * Unified manifest entry for all cached items (packages and binaries). | ||
| * Shared fields at root, type-specific fields in details. | ||
| */ | ||
| export interface ManifestEntry { | ||
| type: 'package' | 'binary'; | ||
| cache_key: string; | ||
| timestamp: number; | ||
| details: PackageDetails | BinaryDetails; | ||
| } | ||
| /** | ||
| * Type guard for package entries. | ||
| */ | ||
| export declare function isPackageEntry(entry: ManifestEntry): entry is ManifestEntry & { | ||
| details: PackageDetails; | ||
| }; | ||
| /** | ||
| * Type guard for binary entries. | ||
| */ | ||
| export declare function isBinaryEntry(entry: ManifestEntry): entry is ManifestEntry & { | ||
| details: BinaryDetails; | ||
| }; | ||
| /** | ||
| * Legacy store record format (deprecated, for migration). | ||
| */ | ||
| export interface StoreRecord { | ||
| timestampFetch: number; | ||
| timestampNotification: number; | ||
| version: string; | ||
| } | ||
| export interface DlxManifestOptions { | ||
| /** | ||
| * Custom manifest file path (defaults to ~/.socket/_dlx/.dlx-manifest.json). | ||
| */ | ||
| manifestPath?: string; | ||
| } | ||
| /** | ||
| * DLX manifest storage manager with atomic operations. | ||
| * Supports both legacy format (package name keys) and new unified manifest format (spec keys). | ||
| */ | ||
| export declare class DlxManifest { | ||
| private readonly manifestPath; | ||
| private readonly lockPath; | ||
| constructor(options?: DlxManifestOptions); | ||
| /** | ||
| * Read the entire manifest file. | ||
| */ | ||
| private readManifest; | ||
| /** | ||
| * Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11"). | ||
| */ | ||
| getManifestEntry(spec: string): ManifestEntry | undefined; | ||
| /** | ||
| * Get cached update information for a package (legacy format). | ||
| * @deprecated Use getManifestEntry() for new code. | ||
| */ | ||
| get(name: string): StoreRecord | undefined; | ||
| /** | ||
| * Set a package manifest entry. | ||
| */ | ||
| setPackageEntry(spec: string, cacheKey: string, details: PackageDetails): Promise<void>; | ||
| /** | ||
| * Set a binary manifest entry. | ||
| */ | ||
| setBinaryEntry(spec: string, cacheKey: string, details: BinaryDetails): Promise<void>; | ||
| private writeManifest; | ||
| /** | ||
| * Store update information for a package (legacy format). | ||
| * @deprecated Use setPackageEntry() for new code. | ||
| */ | ||
| set(name: string, record: StoreRecord): Promise<void>; | ||
| /** | ||
| * Clear cached data for a specific entry. | ||
| */ | ||
| clear(name: string): Promise<void>; | ||
| /** | ||
| * Clear all cached data. | ||
| */ | ||
| clearAll(): Promise<void>; | ||
| /** | ||
| * Check if cached data is fresh based on TTL. | ||
| */ | ||
| isFresh(record: StoreRecord | undefined, ttlMs: number): boolean; | ||
| /** | ||
| * Get all cached package names. | ||
| */ | ||
| getAllPackages(): string[]; | ||
| } | ||
| // Export singleton instance using default manifest location. | ||
| export declare const dlxManifest: DlxManifest; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var manifest_exports = {}; | ||
| __export(manifest_exports, { | ||
| DlxManifest: () => DlxManifest, | ||
| dlxManifest: () => dlxManifest, | ||
| isBinaryEntry: () => isBinaryEntry, | ||
| isPackageEntry: () => isPackageEntry | ||
| }); | ||
| module.exports = __toCommonJS(manifest_exports); | ||
| var import_fs = require("fs"); | ||
| var import_path = __toESM(require("path")); | ||
| var import_fs2 = require("../fs"); | ||
| var import_logger = require("../logger"); | ||
| var import_socket = require("../paths/socket"); | ||
| var import_process_lock = require("../process-lock"); | ||
| const logger = (0, import_logger.getDefaultLogger)(); | ||
| const MANIFEST_FILE_NAME = ".dlx-manifest.json"; | ||
| function isPackageEntry(entry) { | ||
| return entry.type === "package"; | ||
| } | ||
| function isBinaryEntry(entry) { | ||
| return entry.type === "binary"; | ||
| } | ||
| class DlxManifest { | ||
| manifestPath; | ||
| lockPath; | ||
| constructor(options = {}) { | ||
| this.manifestPath = options.manifestPath ?? import_path.default.join((0, import_socket.getSocketDlxDir)(), MANIFEST_FILE_NAME); | ||
| this.lockPath = `${this.manifestPath}.lock`; | ||
| } | ||
| /** | ||
| * Read the entire manifest file. | ||
| */ | ||
| readManifest() { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| const rawContent = (0, import_fs2.readFileUtf8Sync)(this.manifestPath); | ||
| const content = (typeof rawContent === "string" ? rawContent : rawContent.toString("utf8")).trim(); | ||
| if (!content) { | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| return JSON.parse(content); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to read manifest: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| } | ||
| /** | ||
| * Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11"). | ||
| */ | ||
| getManifestEntry(spec) { | ||
| const data = this.readManifest(); | ||
| const entry = data[spec]; | ||
| if (entry && "type" in entry) { | ||
| return entry; | ||
| } | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Get cached update information for a package (legacy format). | ||
| * @deprecated Use getManifestEntry() for new code. | ||
| */ | ||
| get(name) { | ||
| const data = this.readManifest(); | ||
| const entry = data[name]; | ||
| if (entry && !("type" in entry)) { | ||
| return entry; | ||
| } | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Set a package manifest entry. | ||
| */ | ||
| async setPackageEntry(spec, cacheKey, details) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| const data = this.readManifest(); | ||
| data[spec] = { | ||
| type: "package", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| details | ||
| }; | ||
| await this.writeManifest(data); | ||
| }); | ||
| } | ||
| /** | ||
| * Set a binary manifest entry. | ||
| */ | ||
| async setBinaryEntry(spec, cacheKey, details) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| const data = this.readManifest(); | ||
| data[spec] = { | ||
| type: "binary", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| details | ||
| }; | ||
| await this.writeManifest(data); | ||
| }); | ||
| } | ||
| /** | ||
| * Write the manifest file atomically. | ||
| */ | ||
| async writeManifest(data) { | ||
| const manifestDir = import_path.default.dirname(this.manifestPath); | ||
| try { | ||
| (0, import_fs2.safeMkdirSync)(manifestDir, { recursive: true }); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| const content = JSON.stringify(data, null, 2); | ||
| const tempPath = `${this.manifestPath}.tmp`; | ||
| try { | ||
| (0, import_fs.writeFileSync)(tempPath, content, "utf8"); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, content, "utf8"); | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| } catch (error) { | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
| /** | ||
| * Store update information for a package (legacy format). | ||
| * @deprecated Use setPackageEntry() for new code. | ||
| */ | ||
| async set(name, record) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| let data = /* @__PURE__ */ Object.create(null); | ||
| try { | ||
| if ((0, import_fs.existsSync)(this.manifestPath)) { | ||
| const content2 = (0, import_fs.readFileSync)(this.manifestPath, "utf8"); | ||
| if (content2.trim()) { | ||
| data = JSON.parse(content2); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| data[name] = record; | ||
| const manifestDir = import_path.default.dirname(this.manifestPath); | ||
| try { | ||
| (0, import_fs2.safeMkdirSync)(manifestDir, { recursive: true }); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| const content = JSON.stringify(data, null, 2); | ||
| const tempPath = `${this.manifestPath}.tmp`; | ||
| try { | ||
| (0, import_fs.writeFileSync)(tempPath, content, "utf8"); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, content, "utf8"); | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| } catch (error) { | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| throw error; | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Clear cached data for a specific entry. | ||
| */ | ||
| async clear(name) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return; | ||
| } | ||
| const content = (0, import_fs.readFileSync)(this.manifestPath, "utf8"); | ||
| if (!content.trim()) { | ||
| return; | ||
| } | ||
| const data = JSON.parse(content); | ||
| delete data[name]; | ||
| const updatedContent = JSON.stringify(data, null, 2); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, updatedContent, "utf8"); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to clear cache for ${name}: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Clear all cached data. | ||
| */ | ||
| async clearAll() { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| try { | ||
| if ((0, import_fs.existsSync)(this.manifestPath)) { | ||
| (0, import_fs.unlinkSync)(this.manifestPath); | ||
| } | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to clear all cache: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Check if cached data is fresh based on TTL. | ||
| */ | ||
| isFresh(record, ttlMs) { | ||
| if (!record) { | ||
| return false; | ||
| } | ||
| const age = Date.now() - record.timestampFetch; | ||
| return age < ttlMs; | ||
| } | ||
| /** | ||
| * Get all cached package names. | ||
| */ | ||
| getAllPackages() { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return []; | ||
| } | ||
| const rawContent = (0, import_fs2.readFileUtf8Sync)(this.manifestPath); | ||
| const content = (typeof rawContent === "string" ? rawContent : rawContent.toString("utf8")).trim(); | ||
| if (!content) { | ||
| return []; | ||
| } | ||
| const data = JSON.parse(content); | ||
| return Object.keys(data); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to get package list: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| return []; | ||
| } | ||
| } | ||
| } | ||
| const dlxManifest = new DlxManifest(); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| DlxManifest, | ||
| dlxManifest, | ||
| isBinaryEntry, | ||
| isPackageEntry | ||
| }); |
| import type { SpawnExtra, SpawnOptions } from '../spawn'; | ||
| import { spawn } from '../spawn'; | ||
| export interface DownloadPackageResult { | ||
| /** Path to the installed package directory. */ | ||
| packageDir: string; | ||
| /** Path to the binary. */ | ||
| binaryPath: string; | ||
| /** Whether the package was newly installed. */ | ||
| installed: boolean; | ||
| } | ||
| export interface DlxPackageOptions { | ||
| /** | ||
| * Package to install (e.g., '@cyclonedx/cdxgen@10.0.0'). | ||
| * Aligns with npx --package flag. | ||
| */ | ||
| package: string; | ||
| /** | ||
| * Binary name to execute (optional - auto-detected in most cases). | ||
| * | ||
| * Auto-detection logic: | ||
| * 1. If package has only one binary, uses it automatically | ||
| * 2. Tries user-provided binaryName | ||
| * 3. Tries last segment of package name (e.g., 'cli' from '@socketsecurity/cli') | ||
| * 4. Falls back to first binary | ||
| * | ||
| * Only needed when package has multiple binaries and auto-detection fails. | ||
| * | ||
| * @example | ||
| * // Auto-detected (single binary) | ||
| * { package: '@socketsecurity/cli' } // Finds 'socket' binary automatically | ||
| * | ||
| * // Explicit (multiple binaries) | ||
| * { package: 'some-tool', binaryName: 'specific-tool' } | ||
| */ | ||
| binaryName?: string | undefined; | ||
| /** | ||
| * Force reinstallation even if package exists. | ||
| * Aligns with npx --yes/-y flag behavior. | ||
| */ | ||
| force?: boolean | undefined; | ||
| /** | ||
| * Skip confirmation prompts (auto-approve). | ||
| * Aligns with npx --yes/-y flag. | ||
| */ | ||
| yes?: boolean | undefined; | ||
| /** | ||
| * Suppress output (quiet mode). | ||
| * Aligns with npx --quiet/-q and pnpm --silent/-s flags. | ||
| */ | ||
| quiet?: boolean | undefined; | ||
| /** | ||
| * Additional spawn options for the execution. | ||
| */ | ||
| spawnOptions?: SpawnOptions | undefined; | ||
| } | ||
| export interface DlxPackageResult { | ||
| /** Path to the installed package directory. */ | ||
| packageDir: string; | ||
| /** Path to the binary that was executed. */ | ||
| binaryPath: string; | ||
| /** Whether the package was newly installed. */ | ||
| installed: boolean; | ||
| /** The spawn promise for the running process. */ | ||
| spawnPromise: ReturnType<typeof spawn>; | ||
| } | ||
| /** | ||
| * Execute a package via DLX - install if needed and run its binary. | ||
| * | ||
| * This is the Socket equivalent of npx/pnpm dlx/yarn dlx, but using | ||
| * our own cache directory (~/.socket/_dlx) and installation logic. | ||
| * | ||
| * Auto-forces reinstall for version ranges to get latest within range. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Download and execute cdxgen | ||
| * const result = await dlxPackage( | ||
| * ['--version'], | ||
| * { package: '@cyclonedx/cdxgen@10.0.0' } | ||
| * ) | ||
| * await result.spawnPromise | ||
| * ``` | ||
| */ | ||
| export declare function dlxPackage(args: readonly string[] | string[], options?: DlxPackageOptions | undefined, spawnExtra?: SpawnExtra | undefined): Promise<DlxPackageResult>; | ||
| /** | ||
| * Download and install a package without executing it. | ||
| * This is useful for self-update or when you need the package files | ||
| * but don't want to run the binary immediately. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Install @socketsecurity/cli without running it | ||
| * const result = await downloadPackage({ | ||
| * package: '@socketsecurity/cli@1.2.0', | ||
| * force: true | ||
| * }) | ||
| * console.log('Installed to:', result.packageDir) | ||
| * console.log('Binary at:', result.binaryPath) | ||
| * ``` | ||
| */ | ||
| export declare function downloadPackage(options: DlxPackageOptions): Promise<DownloadPackageResult>; | ||
| /** | ||
| * Execute a package's binary with cross-platform shell handling. | ||
| * The package must already be installed (use downloadPackage first). | ||
| * | ||
| * On Windows, script files (.bat, .cmd, .ps1) require shell: true. | ||
| * Matches npm/npx execution behavior. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Execute an already-installed package | ||
| * const downloaded = await downloadPackage({ package: 'cowsay@1.5.0' }) | ||
| * const result = await executePackage( | ||
| * downloaded.binaryPath, | ||
| * ['Hello World'], | ||
| * { stdio: 'inherit' } | ||
| * ) | ||
| * ``` | ||
| */ | ||
| export declare function executePackage(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var package_exports = {}; | ||
| __export(package_exports, { | ||
| dlxPackage: () => dlxPackage, | ||
| downloadPackage: () => downloadPackage, | ||
| executePackage: () => executePackage | ||
| }); | ||
| module.exports = __toCommonJS(package_exports); | ||
| var import_node_fs = __toESM(require("node:fs")); | ||
| var import_path = __toESM(require("path")); | ||
| var import_platform = require("../constants/platform"); | ||
| var import_packages = require("../constants/packages"); | ||
| var import_cache = require("./cache"); | ||
| var import_arborist = __toESM(require("../external/@npmcli/arborist")); | ||
| var import_libnpmexec = __toESM(require("../external/libnpmexec")); | ||
| var import_npm_package_arg = __toESM(require("../external/npm-package-arg")); | ||
| var import_pacote = __toESM(require("../external/pacote")); | ||
| var import_fs = require("../fs"); | ||
| var import_normalize = require("../paths/normalize"); | ||
| var import_socket = require("../paths/socket"); | ||
| var import_process_lock = require("../process-lock"); | ||
| var import_spawn = require("../spawn"); | ||
| const rangeOperatorsRegExp = /[~^><=xX* ]|\|\|/; | ||
| function parsePackageSpec(spec) { | ||
| try { | ||
| const parsed = (0, import_npm_package_arg.default)(spec); | ||
| const version = parsed.type === "tag" ? parsed.fetchSpec : parsed.type === "version" || parsed.type === "range" ? parsed.fetchSpec : void 0; | ||
| return { | ||
| name: parsed.name || spec, | ||
| version | ||
| }; | ||
| } catch { | ||
| const atIndex = spec.lastIndexOf("@"); | ||
| if (atIndex === -1 || spec.startsWith("@")) { | ||
| return { name: spec, version: void 0 }; | ||
| } | ||
| return { | ||
| name: spec.slice(0, atIndex), | ||
| version: spec.slice(atIndex + 1) | ||
| }; | ||
| } | ||
| } | ||
| async function ensurePackageInstalled(packageName, packageSpec, force) { | ||
| const cacheKey = (0, import_cache.generateCacheKey)(packageSpec); | ||
| const packageDir = (0, import_normalize.normalizePath)(import_path.default.join((0, import_socket.getSocketDlxDir)(), cacheKey)); | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| try { | ||
| await (0, import_fs.safeMkdir)(packageDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating package directory: ${packageDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create package directory on read-only filesystem: ${packageDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error(`Failed to create package directory: ${packageDir}`, { | ||
| cause: e | ||
| }); | ||
| } | ||
| const lockPath = import_path.default.join(packageDir, "concurrency.lock"); | ||
| return await import_process_lock.processLock.withLock( | ||
| lockPath, | ||
| async () => { | ||
| if (!force && import_node_fs.default.existsSync(installedDir)) { | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| if (import_node_fs.default.existsSync(pkgJsonPath)) { | ||
| return { installed: false, packageDir }; | ||
| } | ||
| } | ||
| const pacoteCachePath = (0, import_packages.getPacoteCachePath)(); | ||
| try { | ||
| await import_pacote.default.extract(packageSpec, installedDir, { | ||
| // Use consistent pacote cache path (respects npm cache locations when available). | ||
| cache: pacoteCachePath || import_path.default.join(packageDir, ".cache") | ||
| }); | ||
| const arb = new import_arborist.default({ | ||
| path: installedDir, | ||
| cache: pacoteCachePath || import_path.default.join(packageDir, ".cache"), | ||
| // Skip devDependencies (production-only like npx). | ||
| omit: ["dev"], | ||
| // Security: Skip install/preinstall/postinstall scripts to prevent arbitrary code execution. | ||
| ignoreScripts: true, | ||
| // Security: Enable binary links (needed for dlx to execute the package binary). | ||
| binLinks: true, | ||
| // Suppress funding messages (unneeded for ephemeral dlx installs). | ||
| fund: false, | ||
| // Skip audit (unneeded for ephemeral dlx installs). | ||
| audit: false, | ||
| // Suppress output (unneeded for ephemeral dlx installs). | ||
| silent: true | ||
| }); | ||
| await arb.buildIdealTree(); | ||
| await arb.reify({ save: false }); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "E404" || code === "ETARGET") { | ||
| throw new Error( | ||
| `Package not found: ${packageSpec} | ||
| Verify the package exists on npm registry and check the version. | ||
| Visit https://www.npmjs.com/package/${packageName} to see available versions.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "ENOTFOUND" || code === "ETIMEDOUT" || code === "EAI_AGAIN") { | ||
| throw new Error( | ||
| `Network error installing ${packageSpec} | ||
| Check your internet connection and try again.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to install package: ${packageSpec} | ||
| Destination: ${installedDir} | ||
| Check npm registry connectivity or package name.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| return { installed: true, packageDir }; | ||
| }, | ||
| { | ||
| // Align with npm npx locking strategy. | ||
| staleMs: 5e3, | ||
| touchIntervalMs: 2e3 | ||
| } | ||
| ); | ||
| } | ||
| function resolveBinaryPath(basePath) { | ||
| if (!import_platform.WIN32) { | ||
| return basePath; | ||
| } | ||
| const extensions = [".cmd", ".bat", ".ps1", ".exe", ""]; | ||
| for (const ext of extensions) { | ||
| const testPath = basePath + ext; | ||
| if (import_node_fs.default.existsSync(testPath)) { | ||
| return testPath; | ||
| } | ||
| } | ||
| return basePath; | ||
| } | ||
| function findBinaryPath(packageDir, packageName, binaryName) { | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| const pkgJson = (0, import_fs.readJsonSync)(pkgJsonPath); | ||
| const bin = pkgJson["bin"]; | ||
| let binName; | ||
| let binPath; | ||
| if (typeof bin === "string") { | ||
| binPath = bin; | ||
| } else if (typeof bin === "object" && bin !== null) { | ||
| const binObj = bin; | ||
| const binKeys = Object.keys(binObj); | ||
| if (binKeys.length === 1) { | ||
| binName = binKeys[0]; | ||
| binPath = binObj[binName]; | ||
| } else { | ||
| try { | ||
| const { getBinFromManifest } = import_libnpmexec.default; | ||
| binName = getBinFromManifest({ | ||
| name: packageName, | ||
| bin: binObj, | ||
| _id: `${packageName}@${pkgJson.version || "unknown"}` | ||
| }); | ||
| binPath = binObj[binName]; | ||
| } catch { | ||
| const lastSegment = packageName.split("/").pop(); | ||
| const candidates = [ | ||
| binaryName, | ||
| lastSegment, | ||
| packageName.replace(/^@[^/]+\//, "") | ||
| ].filter(Boolean); | ||
| for (const candidate of candidates) { | ||
| if (candidate && binObj[candidate]) { | ||
| binName = candidate; | ||
| binPath = binObj[candidate]; | ||
| break; | ||
| } | ||
| } | ||
| if (!binPath && binKeys.length > 0) { | ||
| binName = binKeys[0]; | ||
| binPath = binObj[binName]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (!binPath) { | ||
| throw new Error(`No binary found for package "${packageName}"`); | ||
| } | ||
| const rawPath = (0, import_normalize.normalizePath)(import_path.default.join(installedDir, binPath)); | ||
| return resolveBinaryPath(rawPath); | ||
| } | ||
| async function dlxPackage(args, options, spawnExtra) { | ||
| const downloadResult = await downloadPackage(options); | ||
| const spawnPromise = executePackage( | ||
| downloadResult.binaryPath, | ||
| args, | ||
| options?.spawnOptions, | ||
| spawnExtra | ||
| ); | ||
| return { | ||
| ...downloadResult, | ||
| spawnPromise | ||
| }; | ||
| } | ||
| function makePackageBinsExecutable(packageDir, packageName) { | ||
| if (import_platform.WIN32) { | ||
| return; | ||
| } | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| try { | ||
| const pkgJson = (0, import_fs.readJsonSync)(pkgJsonPath); | ||
| const bin = pkgJson["bin"]; | ||
| if (!bin) { | ||
| return; | ||
| } | ||
| const binPaths = []; | ||
| if (typeof bin === "string") { | ||
| binPaths.push(bin); | ||
| } else if (typeof bin === "object" && bin !== null) { | ||
| const binObj = bin; | ||
| binPaths.push(...Object.values(binObj)); | ||
| } | ||
| for (const binPath of binPaths) { | ||
| const fullPath = (0, import_normalize.normalizePath)(import_path.default.join(installedDir, binPath)); | ||
| if (import_node_fs.default.existsSync(fullPath)) { | ||
| try { | ||
| import_node_fs.default.chmodSync(fullPath, 493); | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| async function downloadPackage(options) { | ||
| const { | ||
| binaryName, | ||
| force: userForce, | ||
| package: packageSpec, | ||
| yes | ||
| } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { name: packageName, version: packageVersion } = parsePackageSpec(packageSpec); | ||
| const isVersionRange = packageVersion !== void 0 && rangeOperatorsRegExp.test(packageVersion); | ||
| const force = userForce !== void 0 ? userForce : yes === true ? true : isVersionRange; | ||
| const fullPackageSpec = packageVersion ? `${packageName}@${packageVersion}` : packageName; | ||
| const { installed, packageDir } = await ensurePackageInstalled( | ||
| packageName, | ||
| fullPackageSpec, | ||
| force | ||
| ); | ||
| const binaryPath = findBinaryPath(packageDir, packageName, binaryName); | ||
| makePackageBinsExecutable(packageDir, packageName); | ||
| return { | ||
| binaryPath, | ||
| installed, | ||
| packageDir | ||
| }; | ||
| } | ||
| function executePackage(binaryPath, args, spawnOptions, spawnExtra) { | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const finalOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| shell: true | ||
| } : spawnOptions; | ||
| return (0, import_spawn.spawn)(binaryPath, args, finalOptions, spawnExtra); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| dlxPackage, | ||
| downloadPackage, | ||
| executePackage | ||
| }); |
| /** | ||
| * Check if a package is installed in DLX. | ||
| */ | ||
| export declare function isDlxPackageInstalled(packageName: string): boolean; | ||
| /** | ||
| * Check if a package is installed in DLX asynchronously. | ||
| */ | ||
| export declare function isDlxPackageInstalledAsync(packageName: string): Promise<boolean>; | ||
| /** | ||
| * List all packages installed in DLX. | ||
| */ | ||
| export declare function listDlxPackages(): string[]; | ||
| /** | ||
| * List all packages installed in DLX asynchronously. | ||
| */ | ||
| export declare function listDlxPackagesAsync(): Promise<string[]>; | ||
| /** | ||
| * Remove a DLX package installation. | ||
| */ | ||
| export declare function removeDlxPackage(packageName: string): Promise<void>; | ||
| /** | ||
| * Remove a DLX package installation synchronously. | ||
| */ | ||
| export declare function removeDlxPackageSync(packageName: string): void; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var packages_exports = {}; | ||
| __export(packages_exports, { | ||
| isDlxPackageInstalled: () => isDlxPackageInstalled, | ||
| isDlxPackageInstalledAsync: () => isDlxPackageInstalledAsync, | ||
| listDlxPackages: () => listDlxPackages, | ||
| listDlxPackagesAsync: () => listDlxPackagesAsync, | ||
| removeDlxPackage: () => removeDlxPackage, | ||
| removeDlxPackageSync: () => removeDlxPackageSync | ||
| }); | ||
| module.exports = __toCommonJS(packages_exports); | ||
| var import_fs = require("../fs"); | ||
| var import_socket = require("../paths/socket"); | ||
| var import_paths = require("./paths"); | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| function isDlxPackageInstalled(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| return fs.existsSync((0, import_paths.getDlxInstalledPackageDir)(packageName)); | ||
| } | ||
| async function isDlxPackageInstalledAsync(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| await fs.promises.access((0, import_paths.getDlxInstalledPackageDir)(packageName)); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| function listDlxPackages() { | ||
| try { | ||
| return (0, import_fs.readDirNamesSync)((0, import_socket.getSocketDlxDir)(), { sort: true }); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
| async function listDlxPackagesAsync() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| const entries = await fs.promises.readdir((0, import_socket.getSocketDlxDir)(), { | ||
| withFileTypes: true | ||
| }); | ||
| return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort(); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
| async function removeDlxPackage(packageName) { | ||
| const packageDir = (0, import_paths.getDlxPackageDir)(packageName); | ||
| try { | ||
| await (0, import_fs.safeDelete)(packageDir, { recursive: true, force: true }); | ||
| } catch (e) { | ||
| throw new Error(`Failed to remove DLX package "${packageName}"`, { | ||
| cause: e | ||
| }); | ||
| } | ||
| } | ||
| function removeDlxPackageSync(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| const packageDir = (0, import_paths.getDlxPackageDir)(packageName); | ||
| try { | ||
| fs.rmSync(packageDir, { recursive: true, force: true }); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied removing DLX package "${packageName}" | ||
| Directory: ${packageDir} | ||
| To resolve: | ||
| 1. Check file/directory permissions | ||
| 2. Close any programs using files in this directory | ||
| 3. Try running with elevated privileges if necessary | ||
| 4. Manually remove: rm -rf "${packageDir}"`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot remove DLX package "${packageName}" from read-only filesystem | ||
| Directory: ${packageDir} | ||
| The filesystem is mounted read-only.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to remove DLX package "${packageName}" | ||
| Directory: ${packageDir} | ||
| Check permissions and ensure no programs are using this directory.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| isDlxPackageInstalled, | ||
| isDlxPackageInstalledAsync, | ||
| listDlxPackages, | ||
| listDlxPackagesAsync, | ||
| removeDlxPackage, | ||
| removeDlxPackageSync | ||
| }); |
| /** | ||
| * Get the installed package directory within DLX node_modules. | ||
| */ | ||
| export declare function getDlxInstalledPackageDir(packageName: string): string; | ||
| /** | ||
| * Get the DLX installation directory for a specific package. | ||
| */ | ||
| export declare function getDlxPackageDir(packageName: string): string; | ||
| /** | ||
| * Get the package.json path for a DLX installed package. | ||
| */ | ||
| export declare function getDlxPackageJsonPath(packageName: string): string; | ||
| /** | ||
| * Get the node_modules directory for a DLX package installation. | ||
| */ | ||
| export declare function getDlxPackageNodeModulesDir(packageName: string): string; | ||
| /** | ||
| * Check if a file path is within the Socket DLX directory. | ||
| * This is useful for determining if a binary or file is managed by Socket's DLX system. | ||
| * | ||
| * @param filePath - Absolute or relative path to check | ||
| * @returns true if the path is within ~/.socket/_dlx/, false otherwise | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * isInSocketDlx('/home/user/.socket/_dlx/abc123/bin/socket') // true | ||
| * isInSocketDlx('/usr/local/bin/socket') // false | ||
| * isInSocketDlx(process.argv[0]) // Check if current binary is in DLX | ||
| * ``` | ||
| */ | ||
| export declare function isInSocketDlx(filePath: string): boolean; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var paths_exports = {}; | ||
| __export(paths_exports, { | ||
| getDlxInstalledPackageDir: () => getDlxInstalledPackageDir, | ||
| getDlxPackageDir: () => getDlxPackageDir, | ||
| getDlxPackageJsonPath: () => getDlxPackageJsonPath, | ||
| getDlxPackageNodeModulesDir: () => getDlxPackageNodeModulesDir, | ||
| isInSocketDlx: () => isInSocketDlx | ||
| }); | ||
| module.exports = __toCommonJS(paths_exports); | ||
| var import_normalize = require("../paths/normalize"); | ||
| var import_socket = require("../paths/socket"); | ||
| let _path; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getPath() { | ||
| if (_path === void 0) { | ||
| _path = require("node:path"); | ||
| } | ||
| return _path; | ||
| } | ||
| function getDlxInstalledPackageDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)( | ||
| path.join(getDlxPackageNodeModulesDir(packageName), packageName) | ||
| ); | ||
| } | ||
| function getDlxPackageDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)(path.join((0, import_socket.getSocketDlxDir)(), packageName)); | ||
| } | ||
| function getDlxPackageJsonPath(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)( | ||
| path.join(getDlxInstalledPackageDir(packageName), "package.json") | ||
| ); | ||
| } | ||
| function getDlxPackageNodeModulesDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)(path.join(getDlxPackageDir(packageName), "node_modules")); | ||
| } | ||
| function isInSocketDlx(filePath) { | ||
| if (!filePath) { | ||
| return false; | ||
| } | ||
| const path = /* @__PURE__ */ getPath(); | ||
| const dlxDir = (0, import_socket.getSocketDlxDir)(); | ||
| const absolutePath = (0, import_normalize.normalizePath)(path.resolve(filePath)); | ||
| return absolutePath.startsWith(`${dlxDir}/`); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| getDlxInstalledPackageDir, | ||
| getDlxPackageDir, | ||
| getDlxPackageJsonPath, | ||
| getDlxPackageNodeModulesDir, | ||
| isInSocketDlx | ||
| }); |
| import type { EditableJsonConstructor } from './types'; | ||
| /** | ||
| * Get the EditableJson class for JSON file manipulation. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { getEditableJsonClass } from '@socketsecurity/lib/json' | ||
| * | ||
| * const EditableJson = getEditableJsonClass<MyConfigType>() | ||
| * const config = await EditableJson.load('./config.json') | ||
| * config.update({ someField: 'newValue' }) | ||
| * await config.save({ sort: true }) | ||
| * ``` | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function getEditableJsonClass<T = Record<string, unknown>>(): EditableJsonConstructor<T>; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var edit_exports = {}; | ||
| __export(edit_exports, { | ||
| getEditableJsonClass: () => getEditableJsonClass | ||
| }); | ||
| module.exports = __toCommonJS(edit_exports); | ||
| var import_format = require("./format"); | ||
| const identSymbol = import_format.INDENT_SYMBOL; | ||
| const newlineSymbol = import_format.NEWLINE_SYMBOL; | ||
| const JSONParse = JSON.parse; | ||
| let _EditableJsonClass; | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| async function retryWrite(filepath, content, retries = 3, baseDelay = 10) { | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| for (let attempt = 0; attempt <= retries; attempt++) { | ||
| try { | ||
| await fsPromises.writeFile(filepath, content); | ||
| return; | ||
| } catch (err) { | ||
| const isLastAttempt = attempt === retries; | ||
| const isEperm = err instanceof Error && "code" in err && (err.code === "EPERM" || err.code === "EBUSY"); | ||
| if (!isEperm || isLastAttempt) { | ||
| throw err; | ||
| } | ||
| const delay = baseDelay * 2 ** attempt; | ||
| await new Promise((resolve) => setTimeout(resolve, delay)); | ||
| } | ||
| } | ||
| } | ||
| function parseJson(content) { | ||
| return JSONParse(content); | ||
| } | ||
| async function readFile(filepath) { | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| return await fsPromises.readFile(filepath, "utf8"); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getEditableJsonClass() { | ||
| if (_EditableJsonClass === void 0) { | ||
| _EditableJsonClass = class EditableJson { | ||
| _canSave = true; | ||
| _content = {}; | ||
| _path = void 0; | ||
| _readFileContent = ""; | ||
| _readFileJson = void 0; | ||
| get content() { | ||
| return this._content; | ||
| } | ||
| get filename() { | ||
| const path = this._path; | ||
| if (!path) { | ||
| return ""; | ||
| } | ||
| return path; | ||
| } | ||
| get path() { | ||
| return this._path; | ||
| } | ||
| static async create(path, opts = {}) { | ||
| const instance = new EditableJson(); | ||
| instance.create(path); | ||
| return opts.data ? instance.update(opts.data) : instance; | ||
| } | ||
| static async load(path, opts = {}) { | ||
| const instance = new EditableJson(); | ||
| if (!opts.create) { | ||
| return await instance.load(path); | ||
| } | ||
| try { | ||
| return await instance.load(path); | ||
| } catch (err) { | ||
| if (!err.message.includes("ENOENT") && !err.message.includes("no such file")) { | ||
| throw err; | ||
| } | ||
| return instance.create(path); | ||
| } | ||
| } | ||
| create(path) { | ||
| this._path = path; | ||
| this._content = {}; | ||
| this._canSave = true; | ||
| return this; | ||
| } | ||
| fromContent(data) { | ||
| this._content = data; | ||
| this._canSave = false; | ||
| return this; | ||
| } | ||
| fromJSON(data) { | ||
| const parsed = parseJson(data); | ||
| const indent = (0, import_format.detectIndent)(data); | ||
| const newline = (0, import_format.detectNewline)(data); | ||
| parsed[identSymbol] = indent; | ||
| parsed[newlineSymbol] = newline; | ||
| this._content = parsed; | ||
| return this; | ||
| } | ||
| async load(path, create) { | ||
| this._path = path; | ||
| let parseErr; | ||
| try { | ||
| this._readFileContent = await readFile(this.filename); | ||
| } catch (err) { | ||
| if (!create) { | ||
| throw err; | ||
| } | ||
| parseErr = err; | ||
| } | ||
| if (parseErr) { | ||
| throw parseErr; | ||
| } | ||
| this.fromJSON(this._readFileContent); | ||
| this._readFileJson = parseJson(this._readFileContent); | ||
| return this; | ||
| } | ||
| update(content) { | ||
| this._content = { | ||
| ...this._content, | ||
| ...content | ||
| }; | ||
| return this; | ||
| } | ||
| async save(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No file path to save to"); | ||
| } | ||
| if (!(0, import_format.shouldSave)( | ||
| this.content, | ||
| this._readFileJson, | ||
| this._readFileContent, | ||
| options | ||
| )) { | ||
| return false; | ||
| } | ||
| const content = (0, import_format.stripFormattingSymbols)( | ||
| this.content | ||
| ); | ||
| const sortedContent = options?.sort ? (0, import_format.sortKeys)(content) : content; | ||
| const formatting = (0, import_format.getFormattingFromContent)( | ||
| this.content | ||
| ); | ||
| const fileContent = (0, import_format.stringifyWithFormatting)(sortedContent, formatting); | ||
| await retryWrite(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = parseJson(fileContent); | ||
| return true; | ||
| } | ||
| saveSync(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No file path to save to"); | ||
| } | ||
| if (!(0, import_format.shouldSave)( | ||
| this.content, | ||
| this._readFileJson, | ||
| this._readFileContent, | ||
| options | ||
| )) { | ||
| return false; | ||
| } | ||
| const content = (0, import_format.stripFormattingSymbols)( | ||
| this.content | ||
| ); | ||
| const sortedContent = options?.sort ? (0, import_format.sortKeys)(content) : content; | ||
| const formatting = (0, import_format.getFormattingFromContent)( | ||
| this.content | ||
| ); | ||
| const fileContent = (0, import_format.stringifyWithFormatting)(sortedContent, formatting); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| fs.writeFileSync(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = parseJson(fileContent); | ||
| return true; | ||
| } | ||
| willSave(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| return false; | ||
| } | ||
| return (0, import_format.shouldSave)( | ||
| this.content, | ||
| this._readFileJson, | ||
| this._readFileContent, | ||
| options | ||
| ); | ||
| } | ||
| }; | ||
| } | ||
| return _EditableJsonClass; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| getEditableJsonClass | ||
| }); |
| /** | ||
| * @fileoverview Shared utilities for JSON formatting preservation and manipulation. | ||
| * Provides functions for detecting and preserving indentation, line endings, and | ||
| * determining when JSON files should be saved based on content changes. | ||
| */ | ||
| /** | ||
| * Symbols used to store formatting metadata in JSON objects. | ||
| */ | ||
| export declare const INDENT_SYMBOL: unique symbol; | ||
| export declare const NEWLINE_SYMBOL: unique symbol; | ||
| /** | ||
| * Formatting metadata for JSON files. | ||
| */ | ||
| export interface JsonFormatting { | ||
| indent: string | number; | ||
| newline: string; | ||
| } | ||
| /** | ||
| * Options for determining if a save should occur. | ||
| */ | ||
| export interface ShouldSaveOptions { | ||
| ignoreWhitespace?: boolean; | ||
| sort?: boolean; | ||
| sortFn?: (obj: Record<string, unknown>) => Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Detect indentation from a JSON string. | ||
| * Supports space-based indentation (returns count) or mixed indentation (returns string). | ||
| * | ||
| * @param json - JSON string to analyze | ||
| * @returns Number of spaces or indentation string, defaults to 2 if not detected | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * detectIndent('{\n "key": "value"\n}') // => 2 | ||
| * detectIndent('{\n "key": "value"\n}') // => 4 | ||
| * detectIndent('{\n\t"key": "value"\n}') // => '\t' | ||
| * ``` | ||
| */ | ||
| export declare function detectIndent(json: string): string | number; | ||
| /** | ||
| * Detect newline character(s) from a JSON string. | ||
| * Supports LF (\n) and CRLF (\r\n) line endings. | ||
| * | ||
| * @param json - JSON string to analyze | ||
| * @returns Line ending string ('\n' or '\r\n'), defaults to '\n' if not detected | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * detectNewline('{\n "key": "value"\n}') // => '\n' | ||
| * detectNewline('{\r\n "key": "value"\r\n}') // => '\r\n' | ||
| * ``` | ||
| */ | ||
| export declare function detectNewline(json: string): string; | ||
| /** | ||
| * Extract formatting metadata from a JSON string. | ||
| * | ||
| * @param json - JSON string to analyze | ||
| * @returns Object containing indent and newline formatting | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const formatting = extractFormatting('{\n "key": "value"\n}') | ||
| * // => { indent: 2, newline: '\n' } | ||
| * ``` | ||
| */ | ||
| export declare function extractFormatting(json: string): JsonFormatting; | ||
| /** | ||
| * Get default formatting for JSON files. | ||
| * | ||
| * @returns Default formatting (2 spaces, LF line endings) | ||
| */ | ||
| export declare function getDefaultFormatting(): JsonFormatting; | ||
| /** | ||
| * Sort object keys alphabetically. | ||
| * Creates a new object with sorted keys (does not mutate input). | ||
| * | ||
| * @param obj - Object to sort | ||
| * @returns New object with alphabetically sorted keys | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * sortKeys({ z: 3, a: 1, m: 2 }) | ||
| * // => { a: 1, m: 2, z: 3 } | ||
| * ``` | ||
| */ | ||
| export declare function sortKeys(obj: Record<string, unknown>): Record<string, unknown>; | ||
| /** | ||
| * Stringify JSON with specific formatting. | ||
| * Applies indentation and line ending preferences. | ||
| * | ||
| * @param content - Object to stringify | ||
| * @param formatting - Formatting preferences (indent and newline) | ||
| * @returns Formatted JSON string with trailing newline | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * stringifyWithFormatting( | ||
| * { key: 'value' }, | ||
| * { indent: 4, newline: '\r\n' } | ||
| * ) | ||
| * // => '{\r\n "key": "value"\r\n}\r\n' | ||
| * ``` | ||
| */ | ||
| export declare function stringifyWithFormatting(content: Record<string, unknown>, formatting: JsonFormatting): string; | ||
| /** | ||
| * Strip formatting symbols from content object. | ||
| * Removes Symbol.for('indent') and Symbol.for('newline') from the object. | ||
| * | ||
| * @param content - Content object with potential symbol properties | ||
| * @returns Object with symbols removed | ||
| */ | ||
| export declare function stripFormattingSymbols(content: Record<string | symbol, unknown>): Record<string, unknown>; | ||
| /** | ||
| * Extract formatting from content object that has symbol-based metadata. | ||
| * | ||
| * @param content - Content object with Symbol.for('indent') and Symbol.for('newline') | ||
| * @returns Formatting metadata, or defaults if symbols not present | ||
| */ | ||
| export declare function getFormattingFromContent(content: Record<string | symbol, unknown>): JsonFormatting; | ||
| /** | ||
| * Determine if content should be saved based on changes and options. | ||
| * Compares current content with original content and respects options like | ||
| * ignoreWhitespace and sort. | ||
| * | ||
| * @param currentContent - Current content object (may include formatting symbols) | ||
| * @param originalContent - Original content for comparison (may include formatting symbols) | ||
| * @param originalFileContent - Original file content as string (for whitespace comparison) | ||
| * @param options - Options controlling save behavior | ||
| * @returns true if content should be saved, false otherwise | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const current = { key: 'new-value', [Symbol.for('indent')]: 2 } | ||
| * const original = { key: 'old-value', [Symbol.for('indent')]: 2 } | ||
| * shouldSave(current, original, '{\n "key": "old-value"\n}\n') | ||
| * // => true | ||
| * ``` | ||
| */ | ||
| export declare function shouldSave(currentContent: Record<string | symbol, unknown>, originalContent: Record<string | symbol, unknown> | undefined, originalFileContent: string, options?: ShouldSaveOptions): boolean; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var format_exports = {}; | ||
| __export(format_exports, { | ||
| INDENT_SYMBOL: () => INDENT_SYMBOL, | ||
| NEWLINE_SYMBOL: () => NEWLINE_SYMBOL, | ||
| detectIndent: () => detectIndent, | ||
| detectNewline: () => detectNewline, | ||
| extractFormatting: () => extractFormatting, | ||
| getDefaultFormatting: () => getDefaultFormatting, | ||
| getFormattingFromContent: () => getFormattingFromContent, | ||
| shouldSave: () => shouldSave, | ||
| sortKeys: () => sortKeys, | ||
| stringifyWithFormatting: () => stringifyWithFormatting, | ||
| stripFormattingSymbols: () => stripFormattingSymbols | ||
| }); | ||
| module.exports = __toCommonJS(format_exports); | ||
| const INDENT_SYMBOL = Symbol.for("indent"); | ||
| const NEWLINE_SYMBOL = Symbol.for("newline"); | ||
| function detectIndent(json) { | ||
| const match = json.match(/^[{[][\r\n]+(\s+)/m); | ||
| if (!match) { | ||
| return 2; | ||
| } | ||
| const indent = match[1]; | ||
| if (/^ +$/.test(indent)) { | ||
| return indent.length; | ||
| } | ||
| return indent; | ||
| } | ||
| function detectNewline(json) { | ||
| const match = json.match(/\r?\n/); | ||
| return match ? match[0] : "\n"; | ||
| } | ||
| function extractFormatting(json) { | ||
| return { | ||
| indent: detectIndent(json), | ||
| newline: detectNewline(json) | ||
| }; | ||
| } | ||
| function getDefaultFormatting() { | ||
| return { | ||
| indent: 2, | ||
| newline: "\n" | ||
| }; | ||
| } | ||
| function sortKeys(obj) { | ||
| const sorted = { __proto__: null }; | ||
| const keys = Object.keys(obj).sort(); | ||
| for (const key of keys) { | ||
| sorted[key] = obj[key]; | ||
| } | ||
| return sorted; | ||
| } | ||
| function stringifyWithFormatting(content, formatting) { | ||
| const { indent, newline } = formatting; | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| return `${JSON.stringify(content, void 0, format)} | ||
| `.replace(/\n/g, eol); | ||
| } | ||
| function stripFormattingSymbols(content) { | ||
| const { | ||
| [INDENT_SYMBOL]: _indent, | ||
| [NEWLINE_SYMBOL]: _newline, | ||
| ...rest | ||
| } = content; | ||
| return rest; | ||
| } | ||
| function getFormattingFromContent(content) { | ||
| const indent = content[INDENT_SYMBOL]; | ||
| const newline = content[NEWLINE_SYMBOL]; | ||
| return { | ||
| indent: indent === void 0 || indent === null ? 2 : indent, | ||
| newline: newline === void 0 || newline === null ? "\n" : newline | ||
| }; | ||
| } | ||
| function shouldSave(currentContent, originalContent, originalFileContent, options = {}) { | ||
| const { ignoreWhitespace = false, sort = false, sortFn } = options; | ||
| const content = stripFormattingSymbols(currentContent); | ||
| const sortedContent = sortFn ? sortFn(content) : sort ? sortKeys(content) : content; | ||
| const origContent = originalContent ? stripFormattingSymbols(originalContent) : {}; | ||
| if (ignoreWhitespace) { | ||
| const util = require("node:util"); | ||
| return !util.isDeepStrictEqual(sortedContent, origContent); | ||
| } | ||
| const formatting = getFormattingFromContent(currentContent); | ||
| const newFileContent = stringifyWithFormatting(sortedContent, formatting); | ||
| return newFileContent.trim() !== originalFileContent.trim(); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| INDENT_SYMBOL, | ||
| NEWLINE_SYMBOL, | ||
| detectIndent, | ||
| detectNewline, | ||
| extractFormatting, | ||
| getDefaultFormatting, | ||
| getFormattingFromContent, | ||
| shouldSave, | ||
| sortKeys, | ||
| stringifyWithFormatting, | ||
| stripFormattingSymbols | ||
| }); |
| import type { JsonParseOptions, JsonPrimitive, JsonValue } from './types'; | ||
| /** | ||
| * Check if a value is a JSON primitive type. | ||
| * JSON primitives are: `null`, `boolean`, `number`, or `string`. | ||
| * | ||
| * @param value - Value to check | ||
| * @returns `true` if value is a JSON primitive, `false` otherwise | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isJsonPrimitive(null) // => true | ||
| * isJsonPrimitive(true) // => true | ||
| * isJsonPrimitive(42) // => true | ||
| * isJsonPrimitive('hello') // => true | ||
| * isJsonPrimitive({}) // => false | ||
| * isJsonPrimitive([]) // => false | ||
| * isJsonPrimitive(undefined) // => false | ||
| * ``` | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function isJsonPrimitive(value: unknown): value is JsonPrimitive; | ||
| /** | ||
| * Parse JSON content with automatic Buffer handling and BOM stripping. | ||
| * Provides safer JSON parsing with helpful error messages and optional error suppression. | ||
| * | ||
| * Features: | ||
| * - Automatic UTF-8 Buffer conversion | ||
| * - BOM (Byte Order Mark) stripping for cross-platform compatibility | ||
| * - Enhanced error messages with filepath context | ||
| * - Optional error suppression (returns `undefined` instead of throwing) | ||
| * - Optional reviver for transforming parsed values | ||
| * | ||
| * @param content - JSON string or Buffer to parse | ||
| * @param options - Optional parsing configuration | ||
| * @returns Parsed JSON value, or `undefined` if parsing fails and `throws` is `false` | ||
| * | ||
| * @throws {SyntaxError} When JSON is invalid and `throws` is `true` (default) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Basic usage | ||
| * const data = jsonParse('{"name":"example"}') | ||
| * console.log(data.name) // => 'example' | ||
| * | ||
| * // Parse Buffer with UTF-8 BOM | ||
| * const buffer = Buffer.from('\uFEFF{"value":42}') | ||
| * const data = jsonParse(buffer) | ||
| * console.log(data.value) // => 42 | ||
| * | ||
| * // Enhanced error messages with filepath | ||
| * try { | ||
| * jsonParse('invalid', { filepath: 'config.json' }) | ||
| * } catch (err) { | ||
| * console.error(err.message) | ||
| * // => "config.json: Unexpected token i in JSON at position 0" | ||
| * } | ||
| * | ||
| * // Suppress errors | ||
| * const result = jsonParse('invalid', { throws: false }) | ||
| * console.log(result) // => undefined | ||
| * | ||
| * // Transform values with reviver | ||
| * const json = '{"created":"2024-01-15T10:30:00Z"}' | ||
| * const data = jsonParse(json, { | ||
| * reviver: (key, value) => { | ||
| * if (key === 'created' && typeof value === 'string') { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * }) | ||
| * console.log(data.created instanceof Date) // => true | ||
| * ``` | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function jsonParse(content: string | Buffer, options?: JsonParseOptions | undefined): JsonValue | undefined; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var parse_exports = {}; | ||
| __export(parse_exports, { | ||
| isJsonPrimitive: () => isJsonPrimitive, | ||
| jsonParse: () => jsonParse | ||
| }); | ||
| module.exports = __toCommonJS(parse_exports); | ||
| var import_strings = require("../strings"); | ||
| const JSONParse = JSON.parse; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function isBuffer(x) { | ||
| if (!x || typeof x !== "object") { | ||
| return false; | ||
| } | ||
| const obj = x; | ||
| if (typeof obj["length"] !== "number") { | ||
| return false; | ||
| } | ||
| if (typeof obj["copy"] !== "function" || typeof obj["slice"] !== "function") { | ||
| return false; | ||
| } | ||
| if (typeof obj["length"] === "number" && obj["length"] > 0 && typeof obj[0] !== "number") { | ||
| return false; | ||
| } | ||
| const Ctor = x.constructor; | ||
| return !!(typeof Ctor?.isBuffer === "function" && Ctor.isBuffer(x)); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function isJsonPrimitive(value) { | ||
| return value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string"; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function jsonParse(content, options) { | ||
| const { filepath, reviver, throws } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const shouldThrow = throws === void 0 || !!throws; | ||
| const jsonStr = /* @__PURE__ */ isBuffer(content) ? content.toString("utf8") : content; | ||
| try { | ||
| return JSONParse((0, import_strings.stripBom)(jsonStr), reviver); | ||
| } catch (e) { | ||
| if (shouldThrow) { | ||
| const error = e; | ||
| if (error && typeof filepath === "string") { | ||
| error.message = `${filepath}: ${error.message}`; | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| isJsonPrimitive, | ||
| jsonParse | ||
| }); |
| /** | ||
| * @fileoverview JSON type definitions and interfaces. | ||
| */ | ||
| /** | ||
| * JSON primitive types: `null`, `boolean`, `number`, or `string`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const primitives: JsonPrimitive[] = [null, true, 42, 'hello'] | ||
| * ``` | ||
| */ | ||
| export type JsonPrimitive = null | boolean | number | string; | ||
| /** | ||
| * A JSON array containing JSON values. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const arr: JsonArray = [1, 'two', { three: 3 }, [4, 5]] | ||
| * ``` | ||
| */ | ||
| export interface JsonArray extends Array<JsonValue> { | ||
| } | ||
| /** | ||
| * A JSON object with string keys and JSON values. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const obj: JsonObject = { | ||
| * name: 'example', | ||
| * count: 42, | ||
| * active: true, | ||
| * nested: { key: 'value' } | ||
| * } | ||
| * ``` | ||
| */ | ||
| export interface JsonObject { | ||
| [key: string]: JsonValue; | ||
| } | ||
| /** | ||
| * Any valid JSON value: primitive, object, or array. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const values: JsonValue[] = [ | ||
| * null, | ||
| * true, | ||
| * 42, | ||
| * 'hello', | ||
| * { key: 'value' }, | ||
| * [1, 2, 3] | ||
| * ] | ||
| * ``` | ||
| */ | ||
| export type JsonValue = JsonPrimitive | JsonObject | JsonArray; | ||
| /** | ||
| * Reviver function for transforming parsed JSON values. | ||
| * Called for each key-value pair during parsing. | ||
| * | ||
| * @param key - The object key or array index being parsed | ||
| * @param value - The parsed value | ||
| * @returns The transformed value (or original if no transform needed) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Convert date strings to Date objects | ||
| * const reviver: JsonReviver = (key, value) => { | ||
| * if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * ``` | ||
| */ | ||
| export type JsonReviver = (key: string, value: unknown) => unknown; | ||
| /** | ||
| * Options for JSON parsing operations. | ||
| */ | ||
| export interface JsonParseOptions { | ||
| /** | ||
| * Optional filepath for improved error messages. | ||
| * When provided, errors will be prefixed with the filepath. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Error message will be: "config.json: Unexpected token } in JSON" | ||
| * jsonParse('invalid', { filepath: 'config.json' }) | ||
| * ``` | ||
| */ | ||
| filepath?: string | undefined; | ||
| /** | ||
| * Optional reviver function to transform parsed values. | ||
| * Called for each key-value pair during parsing. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Convert ISO date strings to Date objects | ||
| * const options = { | ||
| * reviver: (key, value) => { | ||
| * if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * } | ||
| * ``` | ||
| */ | ||
| reviver?: JsonReviver | undefined; | ||
| /** | ||
| * Whether to throw on parse errors. | ||
| * When `false`, returns `undefined` instead of throwing. | ||
| * | ||
| * @default true | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Throws error | ||
| * jsonParse('invalid', { throws: true }) | ||
| * | ||
| * // Returns undefined | ||
| * const result = jsonParse('invalid', { throws: false }) | ||
| * ``` | ||
| */ | ||
| throws?: boolean | undefined; | ||
| } | ||
| /** | ||
| * Options for saving editable JSON files. | ||
| */ | ||
| export interface EditableJsonSaveOptions { | ||
| /** | ||
| * Whether to ignore whitespace-only changes when determining if save is needed. | ||
| * @default false | ||
| */ | ||
| ignoreWhitespace?: boolean | undefined; | ||
| /** | ||
| * Whether to sort object keys alphabetically before saving. | ||
| * @default false | ||
| */ | ||
| sort?: boolean | undefined; | ||
| } | ||
| /** | ||
| * Options for creating or loading editable JSON instances. | ||
| */ | ||
| export interface EditableJsonOptions<T = Record<string, unknown>> { | ||
| /** | ||
| * File path for the JSON file (optional for in-memory instances). | ||
| */ | ||
| path?: string | undefined; | ||
| /** | ||
| * Whether to create the file if it doesn't exist during load. | ||
| * @default false | ||
| */ | ||
| create?: boolean | undefined; | ||
| /** | ||
| * Initial data to populate the instance with. | ||
| */ | ||
| data?: T | undefined; | ||
| } | ||
| /** | ||
| * EditableJson instance interface for JSON file manipulation. | ||
| * Provides core functionality for loading, editing, and saving JSON files | ||
| * while preserving formatting (indentation and line endings). | ||
| */ | ||
| export interface EditableJsonInstance<T = Record<string, unknown>> { | ||
| /** | ||
| * The parsed JSON content as a readonly object. | ||
| * @readonly | ||
| */ | ||
| content: Readonly<T>; | ||
| /** | ||
| * Create a new JSON file at the specified path. | ||
| * @param path - The file path where JSON will be created | ||
| */ | ||
| create(path: string): this; | ||
| /** | ||
| * Initialize the instance from a content object. | ||
| * Note: Disables saving when used (no file path associated). | ||
| * @param content - The JSON content object | ||
| */ | ||
| fromContent(content: unknown): this; | ||
| /** | ||
| * Initialize the instance from a JSON string. | ||
| * @param json - The JSON content as a string | ||
| */ | ||
| fromJSON(json: string): this; | ||
| /** | ||
| * Load a JSON file from the specified path. | ||
| * @param path - The file path to load | ||
| * @param create - Whether to create the file if it doesn't exist | ||
| */ | ||
| load(path: string, create?: boolean): Promise<this>; | ||
| /** | ||
| * Update the JSON content with new values. | ||
| * @param content - Partial object with fields to update | ||
| */ | ||
| update(content: Partial<T>): this; | ||
| /** | ||
| * Save the JSON file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| */ | ||
| save(options?: EditableJsonSaveOptions): Promise<boolean>; | ||
| /** | ||
| * Synchronously save the JSON file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| */ | ||
| saveSync(options?: EditableJsonSaveOptions): boolean; | ||
| /** | ||
| * Check if the JSON will be saved based on current changes. | ||
| * @param options - Save options to evaluate | ||
| */ | ||
| willSave(options?: EditableJsonSaveOptions): boolean; | ||
| /** | ||
| * The full path to the JSON file. | ||
| * @readonly | ||
| */ | ||
| readonly filename: string; | ||
| /** | ||
| * The directory path containing the JSON file. | ||
| * @readonly | ||
| */ | ||
| readonly path: string | undefined; | ||
| } | ||
| /** | ||
| * EditableJson constructor interface. | ||
| */ | ||
| export interface EditableJsonConstructor<T = Record<string, unknown>> { | ||
| new (): EditableJsonInstance<T>; | ||
| create(path: string, opts?: EditableJsonOptions<T>): Promise<EditableJsonInstance<T>>; | ||
| load(path: string, opts?: EditableJsonOptions<T>): Promise<EditableJsonInstance<T>>; | ||
| } |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var types_exports = {}; | ||
| module.exports = __toCommonJS(types_exports); |
| import type { EditablePackageJsonOptions, NormalizeOptions, PackageJson, SaveOptions } from '../packages'; | ||
| // Define the interface for the dynamic class | ||
| interface EditablePackageJsonConstructor { | ||
| new (): EditablePackageJsonInstance; | ||
| fixSteps: unknown[]; | ||
| normalizeSteps: unknown[]; | ||
| prepareSteps: unknown[]; | ||
| create(path: string, opts?: EditablePackageJsonOptions): Promise<EditablePackageJsonInstance>; | ||
| fix(path: string, opts?: unknown): Promise<EditablePackageJsonInstance>; | ||
| load(path: string, opts?: EditablePackageJsonOptions): Promise<EditablePackageJsonInstance>; | ||
| normalize(path: string, opts?: NormalizeOptions): Promise<EditablePackageJsonInstance>; | ||
| prepare(path: string, opts?: unknown): Promise<EditablePackageJsonInstance>; | ||
| } | ||
| /** | ||
| * EditablePackageJson instance interface extending NPMCliPackageJson functionality. | ||
| * Provides enhanced package.json manipulation with Socket-specific features. | ||
| * @extends NPMCliPackageJson (from @npmcli/package-json) | ||
| */ | ||
| export interface EditablePackageJsonInstance { | ||
| /** | ||
| * The parsed package.json content as a readonly object. | ||
| * @readonly | ||
| */ | ||
| content: Readonly<PackageJson>; | ||
| /** | ||
| * Create a new package.json file at the specified path. | ||
| * @param path - The directory path where package.json will be created | ||
| */ | ||
| create(path: string): this; | ||
| /** | ||
| * Apply automatic fixes to the package.json based on npm standards. | ||
| * @param opts - Optional fix configuration | ||
| */ | ||
| fix(opts?: unknown | undefined): Promise<this>; | ||
| /** | ||
| * Initialize the instance from a content object. | ||
| * @param content - The package.json content object | ||
| */ | ||
| fromContent(content: unknown): this; | ||
| /** | ||
| * Initialize the instance from a JSON string. | ||
| * @param json - The package.json content as a JSON string | ||
| */ | ||
| fromJSON(json: string): this; | ||
| /** | ||
| * Load a package.json file from the specified path. | ||
| * @param path - The directory containing the package.json | ||
| * @param create - Whether to create the file if it doesn't exist | ||
| */ | ||
| load(path: string, create?: boolean): Promise<this>; | ||
| /** | ||
| * Normalize the package.json content according to npm standards. | ||
| * @param opts - Normalization options | ||
| */ | ||
| normalize(opts?: NormalizeOptions): Promise<this>; | ||
| /** | ||
| * Prepare the package.json for publishing. | ||
| * @param opts - Preparation options | ||
| */ | ||
| prepare(opts?: unknown): Promise<this>; | ||
| /** | ||
| * Update the package.json content with new values. | ||
| * @param content - Partial package.json object with fields to update | ||
| * @override from NPMCliPackageJson | ||
| */ | ||
| update(content: Partial<PackageJson>): this; | ||
| /** | ||
| * Save the package.json file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| * @override from NPMCliPackageJson | ||
| */ | ||
| save(options?: SaveOptions | undefined): Promise<boolean>; | ||
| /** | ||
| * Synchronously save the package.json file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| */ | ||
| saveSync(options?: SaveOptions | undefined): boolean; | ||
| /** | ||
| * Check if the package.json will be saved based on current changes. | ||
| * @param options - Save options to evaluate | ||
| */ | ||
| willSave(options?: SaveOptions | undefined): boolean; | ||
| } | ||
| /** | ||
| * Get the EditablePackageJson class for package.json manipulation. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function getEditablePackageJsonClass(): EditablePackageJsonConstructor; | ||
| /** | ||
| * Convert a package.json object to an editable instance. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function pkgJsonToEditable(pkgJson: PackageJson, options?: EditablePackageJsonOptions): unknown; | ||
| /** | ||
| * Convert package.json to editable instance with file persistence. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function toEditablePackageJson(pkgJson: PackageJson, options?: EditablePackageJsonOptions): Promise<unknown>; | ||
| /** | ||
| * Convert package.json to editable instance with file persistence synchronously. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function toEditablePackageJsonSync(pkgJson: PackageJson, options?: EditablePackageJsonOptions): unknown; | ||
| export {}; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var edit_exports = {}; | ||
| __export(edit_exports, { | ||
| getEditablePackageJsonClass: () => getEditablePackageJsonClass, | ||
| pkgJsonToEditable: () => pkgJsonToEditable, | ||
| toEditablePackageJson: () => toEditablePackageJson, | ||
| toEditablePackageJsonSync: () => toEditablePackageJsonSync | ||
| }); | ||
| module.exports = __toCommonJS(edit_exports); | ||
| var import_package_json = __toESM(require("../external/@npmcli/package-json")); | ||
| var import_read_package = require("../external/@npmcli/package-json/lib/read-package"); | ||
| var import_sort = require("../external/@npmcli/package-json/lib/sort"); | ||
| var import_format = require("../json/format"); | ||
| var import_normalize = require("../paths/normalize"); | ||
| var import_normalize2 = require("./normalize"); | ||
| var import_packages = require("../paths/packages"); | ||
| let _EditablePackageJsonClass; | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| let _path; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getPath() { | ||
| if (_path === void 0) { | ||
| _path = require("node:path"); | ||
| } | ||
| return _path; | ||
| } | ||
| let _util; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getUtil() { | ||
| if (_util === void 0) { | ||
| _util = require("node:util"); | ||
| } | ||
| return _util; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getEditablePackageJsonClass() { | ||
| if (_EditablePackageJsonClass === void 0) { | ||
| _EditablePackageJsonClass = class EditablePackageJson extends import_package_json.default { | ||
| static fixSteps = import_package_json.default.fixSteps; | ||
| static normalizeSteps = import_package_json.default.normalizeSteps; | ||
| static prepareSteps = import_package_json.default.prepareSteps; | ||
| _canSave = true; | ||
| _path = void 0; | ||
| _readFileContent = ""; | ||
| _readFileJson = void 0; | ||
| get content() { | ||
| return super.content; | ||
| } | ||
| get filename() { | ||
| const path = this._path; | ||
| if (!path) { | ||
| return ""; | ||
| } | ||
| if (path.endsWith("package.json")) { | ||
| return path; | ||
| } | ||
| const nodePath = /* @__PURE__ */ getPath(); | ||
| return nodePath.join(path, "package.json"); | ||
| } | ||
| static async create(path, opts = {}) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.create(path); | ||
| return opts.data ? p.update(opts.data) : p; | ||
| } | ||
| static async fix(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path, true); | ||
| return await p.fix(opts); | ||
| } | ||
| static async load(path, opts = {}) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| if (!opts.create) { | ||
| return await p.load(path); | ||
| } | ||
| try { | ||
| return await p.load(path); | ||
| } catch (err) { | ||
| if (!err.message.startsWith("Could not read package.json")) { | ||
| throw err; | ||
| } | ||
| return p.create(path); | ||
| } | ||
| } | ||
| static async normalize(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path); | ||
| return await p.normalize(opts); | ||
| } | ||
| static async prepare(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path, true); | ||
| return await p.prepare(opts); | ||
| } | ||
| create(path) { | ||
| super.create(path); | ||
| this._path = path; | ||
| return this; | ||
| } | ||
| async fix(opts = {}) { | ||
| await super.fix(opts); | ||
| return this; | ||
| } | ||
| fromContent(data) { | ||
| super.fromContent(data); | ||
| this._canSave = false; | ||
| return this; | ||
| } | ||
| fromJSON(data) { | ||
| super.fromJSON(data); | ||
| return this; | ||
| } | ||
| async load(path, create) { | ||
| this._path = path; | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| let parseErr; | ||
| try { | ||
| this._readFileContent = await (0, import_read_package.read)(this.filename); | ||
| } catch (err) { | ||
| if (!create) { | ||
| throw err; | ||
| } | ||
| parseErr = err; | ||
| } | ||
| if (parseErr) { | ||
| const nodePath = /* @__PURE__ */ getPath(); | ||
| const indexFile = nodePath.resolve(this.path || "", "index.js"); | ||
| let indexFileContent; | ||
| try { | ||
| indexFileContent = await fsPromises.readFile(indexFile, "utf8"); | ||
| } catch { | ||
| throw parseErr; | ||
| } | ||
| try { | ||
| this.fromContent(indexFileContent); | ||
| } catch { | ||
| throw parseErr; | ||
| } | ||
| this._canSave = false; | ||
| return this; | ||
| } | ||
| this.fromJSON(this._readFileContent); | ||
| this._readFileJson = (0, import_read_package.parse)(this._readFileContent); | ||
| return this; | ||
| } | ||
| async normalize(opts = {}) { | ||
| await super.normalize(opts); | ||
| return this; | ||
| } | ||
| get path() { | ||
| return this._path; | ||
| } | ||
| async prepare(opts = {}) { | ||
| await super.prepare(opts); | ||
| return this; | ||
| } | ||
| async save(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No package.json to save to"); | ||
| } | ||
| if (!(0, import_format.shouldSave)( | ||
| this.content, | ||
| this._readFileJson, | ||
| this._readFileContent, | ||
| { ...options, sortFn: options?.sort ? import_sort.packageSort : void 0 } | ||
| )) { | ||
| return false; | ||
| } | ||
| const content = (0, import_format.stripFormattingSymbols)( | ||
| this.content | ||
| ); | ||
| const sortedContent = options?.sort ? (0, import_sort.packageSort)(content) : content; | ||
| const formatting = (0, import_format.getFormattingFromContent)( | ||
| this.content | ||
| ); | ||
| const fileContent = (0, import_format.stringifyWithFormatting)(sortedContent, formatting); | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| await fsPromises.writeFile(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = (0, import_read_package.parse)(fileContent); | ||
| return true; | ||
| } | ||
| saveSync(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No package.json to save to"); | ||
| } | ||
| const { ignoreWhitespace = false, sort = false } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { | ||
| [Symbol.for("indent")]: indent, | ||
| [Symbol.for("newline")]: newline, | ||
| ...rest | ||
| } = this.content; | ||
| const content = sort ? (0, import_sort.packageSort)(rest) : rest; | ||
| if (ignoreWhitespace && (/* @__PURE__ */ getUtil()).isDeepStrictEqual(content, this._readFileJson)) { | ||
| return false; | ||
| } | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| const fileContent = `${JSON.stringify( | ||
| content, | ||
| void 0, | ||
| format | ||
| )} | ||
| `.replace(/\n/g, eol); | ||
| if (!ignoreWhitespace && fileContent.trim() === this._readFileContent.trim()) { | ||
| return false; | ||
| } | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| fs.writeFileSync(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = (0, import_read_package.parse)(fileContent); | ||
| return true; | ||
| } | ||
| update(content) { | ||
| super.update(content); | ||
| return this; | ||
| } | ||
| willSave(options) { | ||
| const { ignoreWhitespace = false, sort = false } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| if (!this._canSave || this.content === void 0) { | ||
| return false; | ||
| } | ||
| const { | ||
| [Symbol.for("indent")]: indent, | ||
| [Symbol.for("newline")]: newline, | ||
| ...rest | ||
| } = this.content; | ||
| const content = sort ? (0, import_sort.packageSort)(rest) : rest; | ||
| if (ignoreWhitespace && (/* @__PURE__ */ getUtil()).isDeepStrictEqual(content, this._readFileJson)) { | ||
| return false; | ||
| } | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| const fileContent = `${JSON.stringify( | ||
| content, | ||
| void 0, | ||
| format | ||
| )} | ||
| `.replace(/\n/g, eol); | ||
| if (!ignoreWhitespace && fileContent.trim() === this._readFileContent.trim()) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }; | ||
| } | ||
| return _EditablePackageJsonClass; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function pkgJsonToEditable(pkgJson, options) { | ||
| const { normalize, ...normalizeOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| return new EditablePackageJson().fromContent( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, normalizeOptions) : pkgJson | ||
| ); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| async function toEditablePackageJson(pkgJson, options) { | ||
| const { path: filepath, ...pkgJsonToEditableOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { normalize, ...normalizeOptions } = pkgJsonToEditableOptions; | ||
| if (typeof filepath !== "string") { | ||
| return /* @__PURE__ */ pkgJsonToEditable(pkgJson, pkgJsonToEditableOptions); | ||
| } | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| const pkgJsonPath = (0, import_packages.resolvePackageJsonDirname)(filepath); | ||
| return (await EditablePackageJson.load(pkgJsonPath, { create: true })).fromJSON( | ||
| `${JSON.stringify( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, { | ||
| ...(0, import_normalize.isNodeModules)(pkgJsonPath) ? {} : { preserve: ["repository"] }, | ||
| ...normalizeOptions | ||
| }) : pkgJson, | ||
| null, | ||
| 2 | ||
| )} | ||
| ` | ||
| ); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function toEditablePackageJsonSync(pkgJson, options) { | ||
| const { path: filepath, ...pkgJsonToEditableOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { normalize, ...normalizeOptions } = pkgJsonToEditableOptions; | ||
| if (typeof filepath !== "string") { | ||
| return /* @__PURE__ */ pkgJsonToEditable(pkgJson, pkgJsonToEditableOptions); | ||
| } | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| const pkgJsonPath = (0, import_packages.resolvePackageJsonDirname)(filepath); | ||
| return new EditablePackageJson().create(pkgJsonPath).fromJSON( | ||
| `${JSON.stringify( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, { | ||
| ...(0, import_normalize.isNodeModules)(pkgJsonPath) ? {} : { preserve: ["repository"] }, | ||
| ...normalizeOptions | ||
| }) : pkgJson, | ||
| null, | ||
| 2 | ||
| )} | ||
| ` | ||
| ); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| getEditablePackageJsonClass, | ||
| pkgJsonToEditable, | ||
| toEditablePackageJson, | ||
| toEditablePackageJsonSync | ||
| }); |
+67
-0
@@ -8,2 +8,69 @@ # Changelog | ||
| ## [5.0.0](https://github.com/SocketDev/socket-lib/releases/tag/v5.0.0) - 2025-12-04 | ||
| ### Added | ||
| - **json/edit**: New `EditableJson` base class for generic JSON file manipulation with formatting preservation | ||
| - Extracted from `EditablePackageJson` to enable code reuse via composition pattern | ||
| - Supports reading, modifying, and writing JSON files while preserving formatting | ||
| - Export: `@socketsecurity/lib/json/edit` | ||
| - **json/format**: New JSON formatting utilities for consistent JSON manipulation | ||
| - Functions for analyzing and preserving JSON formatting patterns | ||
| - Export: `@socketsecurity/lib/json/format` | ||
| - **json/parse**: New JSON parsing utilities | ||
| - `isJsonPrimitive()`: Check if value is a JSON primitive type | ||
| - `jsonParse()`: Parse JSON with error handling | ||
| - Export: `@socketsecurity/lib/json/parse` | ||
| - **json/types**: New JSON type definitions and interfaces | ||
| - Export: `@socketsecurity/lib/json/types` | ||
| - **dlx/cache**: New DLX cache utilities | ||
| - `generateCacheKey()`: Generate cache keys for DLX packages | ||
| - Export: `@socketsecurity/lib/dlx/cache` | ||
| - **dlx/dir**: New DLX directory management utilities | ||
| - `clearDlx()`, `clearDlxSync()`: Clear DLX directory | ||
| - `dlxDirExists()`, `dlxDirExistsAsync()`: Check if DLX directory exists | ||
| - `ensureDlxDir()`, `ensureDlxDirSync()`: Ensure DLX directory exists | ||
| - Export: `@socketsecurity/lib/dlx/dir` | ||
| - **dlx/packages**: New DLX package management utilities | ||
| - `isDlxPackageInstalled()`, `isDlxPackageInstalledAsync()`: Check if package is installed | ||
| - `listDlxPackages()`, `listDlxPackagesAsync()`: List installed packages | ||
| - `removeDlxPackage()`, `removeDlxPackageSync()`: Remove installed packages | ||
| - Export: `@socketsecurity/lib/dlx/packages` | ||
| - **dlx/paths**: New DLX path utilities | ||
| - `getDlxPackageDir()`: Get package directory path | ||
| - `getDlxInstalledPackageDir()`: Get installed package directory path | ||
| - `getDlxPackageJsonPath()`: Get package.json path | ||
| - `getDlxPackageNodeModulesDir()`: Get node_modules directory path | ||
| - `isInSocketDlx()`: Check if path is in DLX directory | ||
| - Export: `@socketsecurity/lib/dlx/paths` | ||
| ### Changed | ||
| - **BREAKING**: Reorganized module paths for better structure and discoverability | ||
| - `@socketsecurity/lib/json/editable` → `@socketsecurity/lib/json/edit` | ||
| - `@socketsecurity/lib/packages/editable` → `@socketsecurity/lib/packages/edit` | ||
| - `@socketsecurity/lib/maintained-node-versions` → `@socketsecurity/lib/constants/maintained-node-versions` | ||
| - `@socketsecurity/lib/package-default-node-range` → `@socketsecurity/lib/constants/package-default-node-range` | ||
| - `@socketsecurity/lib/package-default-socket-categories` → `@socketsecurity/lib/constants/package-default-socket-categories` | ||
| - `@socketsecurity/lib/lifecycle-script-names` → `@socketsecurity/lib/constants/lifecycle-script-names` | ||
| - `@socketsecurity/lib/dlx` → Split into `@socketsecurity/lib/dlx/cache`, `@socketsecurity/lib/dlx/dir`, `@socketsecurity/lib/dlx/packages`, `@socketsecurity/lib/dlx/paths` | ||
| - `@socketsecurity/lib/dlx-binary` → `@socketsecurity/lib/dlx/binary` | ||
| - `@socketsecurity/lib/dlx-manifest` → `@socketsecurity/lib/dlx/manifest` | ||
| - `@socketsecurity/lib/dlx-package` → `@socketsecurity/lib/dlx/package` | ||
| - **json**: Reorganized JSON utilities into modular submodules (json/edit, json/format, json/parse, json/types) | ||
| - Removed barrel index file in favor of direct submodule imports | ||
| - Better separation of concerns and tree-shaking | ||
| - **dlx**: Split monolithic DLX module into focused submodules (cache, dir, packages, paths) | ||
| - Improved modularity and maintainability | ||
| - Better code organization and discoverability | ||
| ## [4.4.0](https://github.com/SocketDev/socket-lib/releases/tag/v4.4.0) - 2025-11-25 | ||
@@ -10,0 +77,0 @@ |
@@ -44,3 +44,3 @@ "use strict"; | ||
| module.exports = __toCommonJS(node_exports); | ||
| var import_maintained_node_versions = require("../maintained-node-versions"); | ||
| var import_maintained_node_versions = require("./maintained-node-versions"); | ||
| const NODE_VERSION = process.version; | ||
@@ -47,0 +47,0 @@ function getNodeVersion() { |
@@ -46,5 +46,5 @@ "use strict"; | ||
| var import_npm = require("../env/npm"); | ||
| var import_lifecycle_script_names = require("../lifecycle-script-names"); | ||
| var import_package_default_node_range = require("../package-default-node-range"); | ||
| var import_package_default_socket_categories = require("../package-default-socket-categories"); | ||
| var import_lifecycle_script_names = require("./lifecycle-script-names"); | ||
| var import_package_default_node_range = require("./package-default-node-range"); | ||
| var import_package_default_socket_categories = require("./package-default-socket-categories"); | ||
| var import_package_extensions = require("../package-extensions"); | ||
@@ -51,0 +51,0 @@ var import_pacote = __toESM(require("../external/pacote")); |
+3
-3
@@ -7,3 +7,3 @@ /** | ||
| import type { MakeDirectoryOptions, ObjectEncodingOptions, OpenMode, PathLike } from 'fs'; | ||
| import type { JsonReviver } from './json'; | ||
| import type { JsonReviver } from './json/types'; | ||
| import { type Remap } from './objects'; | ||
@@ -549,3 +549,3 @@ /** | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function readJson(filepath: PathLike, options?: ReadJsonOptions | string | undefined): Promise<import("./json").JsonValue>; | ||
| export declare function readJson(filepath: PathLike, options?: ReadJsonOptions | string | undefined): Promise<import("./json/types").JsonValue>; | ||
| /** | ||
@@ -580,3 +580,3 @@ * Read and parse a JSON file synchronously. | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function readJsonSync(filepath: PathLike, options?: ReadJsonOptions | string | undefined): import("./json").JsonValue; | ||
| export declare function readJsonSync(filepath: PathLike, options?: ReadJsonOptions | string | undefined): import("./json/types").JsonValue; | ||
| /** | ||
@@ -583,0 +583,0 @@ * Safely delete a file or directory asynchronously with built-in protections. |
+3
-3
@@ -57,3 +57,3 @@ "use strict"; | ||
| var import_globs = require("./globs"); | ||
| var import_json = require("./json"); | ||
| var import_parse = require("./json/parse"); | ||
| var import_objects = require("./objects"); | ||
@@ -459,3 +459,3 @@ var import_normalize = require("./paths/normalize"); | ||
| } | ||
| return (0, import_json.jsonParse)(content, { | ||
| return (0, import_parse.jsonParse)(content, { | ||
| filepath: String(filepath), | ||
@@ -503,3 +503,3 @@ reviver, | ||
| } | ||
| return (0, import_json.jsonParse)(content, { | ||
| return (0, import_parse.jsonParse)(content, { | ||
| filepath: String(filepath), | ||
@@ -506,0 +506,0 @@ reviver, |
@@ -6,3 +6,3 @@ /** | ||
| import type { CategoryString } from './types'; | ||
| import { getEditablePackageJsonClass, pkgJsonToEditable, toEditablePackageJson, toEditablePackageJsonSync } from './packages/editable'; | ||
| import { getEditablePackageJsonClass, pkgJsonToEditable, toEditablePackageJson, toEditablePackageJsonSync } from './packages/edit'; | ||
| import { findTypesForSubpath, getExportFilePaths, getSubpaths, isConditionalExports, isSubpathExports, resolvePackageJsonEntryExports } from './packages/exports'; | ||
@@ -23,3 +23,3 @@ import { isolatePackage } from './packages/isolation'; | ||
| // Re-export the EditablePackageJson instance type for convenient access | ||
| export type EditablePackageJson = import('./packages/editable').EditablePackageJsonInstance; | ||
| export type EditablePackageJson = import('./packages/edit').EditablePackageJsonInstance; | ||
| /** | ||
@@ -26,0 +26,0 @@ * Extended PackageJson type based on NPMCliPackageJson.Content with Socket-specific additions. |
+5
-5
@@ -34,3 +34,3 @@ "use strict"; | ||
| findTypesForSubpath: () => import_exports.findTypesForSubpath, | ||
| getEditablePackageJsonClass: () => import_editable.getEditablePackageJsonClass, | ||
| getEditablePackageJsonClass: () => import_edit.getEditablePackageJsonClass, | ||
| getExportFilePaths: () => import_exports.getExportFilePaths, | ||
@@ -54,3 +54,3 @@ getProvenanceDetails: () => import_provenance.getProvenanceDetails, | ||
| parseSpdxExp: () => import_licenses.parseSpdxExp, | ||
| pkgJsonToEditable: () => import_editable.pkgJsonToEditable, | ||
| pkgJsonToEditable: () => import_edit.pkgJsonToEditable, | ||
| readPackageJson: () => import_operations.readPackageJson, | ||
@@ -67,4 +67,4 @@ readPackageJsonSync: () => import_operations.readPackageJsonSync, | ||
| resolveRegistryPackageName: () => import_operations.resolveRegistryPackageName, | ||
| toEditablePackageJson: () => import_editable.toEditablePackageJson, | ||
| toEditablePackageJsonSync: () => import_editable.toEditablePackageJsonSync, | ||
| toEditablePackageJson: () => import_edit.toEditablePackageJson, | ||
| toEditablePackageJsonSync: () => import_edit.toEditablePackageJsonSync, | ||
| unescapeScope: () => import_normalize.unescapeScope, | ||
@@ -74,3 +74,3 @@ visitLicenses: () => import_licenses.visitLicenses | ||
| module.exports = __toCommonJS(packages_exports); | ||
| var import_editable = require("./packages/editable"); | ||
| var import_edit = require("./packages/edit"); | ||
| var import_exports = require("./packages/exports"); | ||
@@ -77,0 +77,0 @@ var import_isolation = require("./packages/isolation"); |
@@ -58,3 +58,3 @@ "use strict"; | ||
| var import_specs = require("./specs"); | ||
| var import_editable = require("./editable"); | ||
| var import_edit = require("./edit"); | ||
| const abortSignal = (0, import_process.getAbortSignal)(); | ||
@@ -165,3 +165,3 @@ const packageExtensions = (0, import_packages.getPackageExtensions)(); | ||
| if (editable) { | ||
| return await (0, import_editable.toEditablePackageJson)(pkgJson, { | ||
| return await (0, import_edit.toEditablePackageJson)(pkgJson, { | ||
| path: filepath, | ||
@@ -185,3 +185,3 @@ normalize, | ||
| if (editable) { | ||
| return (0, import_editable.toEditablePackageJsonSync)(pkgJson, { | ||
| return (0, import_edit.toEditablePackageJsonSync)(pkgJson, { | ||
| path: filepath, | ||
@@ -188,0 +188,0 @@ normalize, |
+58
-34
| { | ||
| "name": "@socketsecurity/lib", | ||
| "version": "4.4.0", | ||
| "version": "5.0.0", | ||
| "packageManager": "pnpm@10.22.0", | ||
@@ -154,2 +154,10 @@ "license": "MIT", | ||
| }, | ||
| "./constants/lifecycle-script-names": { | ||
| "types": "./dist/constants/lifecycle-script-names.d.ts", | ||
| "default": "./dist/constants/lifecycle-script-names.js" | ||
| }, | ||
| "./constants/maintained-node-versions": { | ||
| "types": "./dist/constants/maintained-node-versions.d.ts", | ||
| "default": "./dist/constants/maintained-node-versions.js" | ||
| }, | ||
| "./constants/node": { | ||
@@ -159,2 +167,10 @@ "types": "./dist/constants/node.d.ts", | ||
| }, | ||
| "./constants/package-default-node-range": { | ||
| "types": "./dist/constants/package-default-node-range.d.ts", | ||
| "default": "./dist/constants/package-default-node-range.js" | ||
| }, | ||
| "./constants/package-default-socket-categories": { | ||
| "types": "./dist/constants/package-default-socket-categories.d.ts", | ||
| "default": "./dist/constants/package-default-socket-categories.js" | ||
| }, | ||
| "./constants/packages": { | ||
@@ -208,18 +224,30 @@ "types": "./dist/constants/packages.d.ts", | ||
| }, | ||
| "./dlx": { | ||
| "types": "./dist/dlx.d.ts", | ||
| "default": "./dist/dlx.js" | ||
| "./dlx/binary": { | ||
| "types": "./dist/dlx/binary.d.ts", | ||
| "default": "./dist/dlx/binary.js" | ||
| }, | ||
| "./dlx-binary": { | ||
| "types": "./dist/dlx-binary.d.ts", | ||
| "default": "./dist/dlx-binary.js" | ||
| "./dlx/cache": { | ||
| "types": "./dist/dlx/cache.d.ts", | ||
| "default": "./dist/dlx/cache.js" | ||
| }, | ||
| "./dlx-manifest": { | ||
| "types": "./dist/dlx-manifest.d.ts", | ||
| "default": "./dist/dlx-manifest.js" | ||
| "./dlx/dir": { | ||
| "types": "./dist/dlx/dir.d.ts", | ||
| "default": "./dist/dlx/dir.js" | ||
| }, | ||
| "./dlx-package": { | ||
| "types": "./dist/dlx-package.d.ts", | ||
| "default": "./dist/dlx-package.js" | ||
| "./dlx/manifest": { | ||
| "types": "./dist/dlx/manifest.d.ts", | ||
| "default": "./dist/dlx/manifest.js" | ||
| }, | ||
| "./dlx/package": { | ||
| "types": "./dist/dlx/package.d.ts", | ||
| "default": "./dist/dlx/package.js" | ||
| }, | ||
| "./dlx/packages": { | ||
| "types": "./dist/dlx/packages.d.ts", | ||
| "default": "./dist/dlx/packages.js" | ||
| }, | ||
| "./dlx/paths": { | ||
| "types": "./dist/dlx/paths.d.ts", | ||
| "default": "./dist/dlx/paths.js" | ||
| }, | ||
| "./effects/pulse-frames": { | ||
@@ -361,10 +389,18 @@ "types": "./dist/effects/pulse-frames.d.ts", | ||
| }, | ||
| "./json": { | ||
| "types": "./dist/json.d.ts", | ||
| "default": "./dist/json.js" | ||
| "./json/edit": { | ||
| "types": "./dist/json/edit.d.ts", | ||
| "default": "./dist/json/edit.js" | ||
| }, | ||
| "./lifecycle-script-names": { | ||
| "types": "./dist/lifecycle-script-names.d.ts", | ||
| "default": "./dist/lifecycle-script-names.js" | ||
| "./json/format": { | ||
| "types": "./dist/json/format.d.ts", | ||
| "default": "./dist/json/format.js" | ||
| }, | ||
| "./json/parse": { | ||
| "types": "./dist/json/parse.d.ts", | ||
| "default": "./dist/json/parse.js" | ||
| }, | ||
| "./json/types": { | ||
| "types": "./dist/json/types.d.ts", | ||
| "default": "./dist/json/types.js" | ||
| }, | ||
| "./links": { | ||
@@ -382,6 +418,2 @@ "types": "./dist/links/index.d.ts", | ||
| }, | ||
| "./maintained-node-versions": { | ||
| "types": "./dist/maintained-node-versions.d.ts", | ||
| "default": "./dist/maintained-node-versions.js" | ||
| }, | ||
| "./memoization": { | ||
@@ -395,10 +427,2 @@ "types": "./dist/memoization.d.ts", | ||
| }, | ||
| "./package-default-node-range": { | ||
| "types": "./dist/package-default-node-range.d.ts", | ||
| "default": "./dist/package-default-node-range.js" | ||
| }, | ||
| "./package-default-socket-categories": { | ||
| "types": "./dist/package-default-socket-categories.d.ts", | ||
| "default": "./dist/package-default-socket-categories.js" | ||
| }, | ||
| "./package-extensions": { | ||
@@ -412,5 +436,5 @@ "types": "./dist/package-extensions.d.ts", | ||
| }, | ||
| "./packages/editable": { | ||
| "types": "./dist/packages/editable.d.ts", | ||
| "default": "./dist/packages/editable.js" | ||
| "./packages/edit": { | ||
| "types": "./dist/packages/edit.d.ts", | ||
| "default": "./dist/packages/edit.js" | ||
| }, | ||
@@ -417,0 +441,0 @@ "./packages/exports": { |
| import type { SpawnExtra, SpawnOptions } from './spawn'; | ||
| import { spawn } from './spawn'; | ||
| export interface DlxBinaryOptions { | ||
| /** | ||
| * URL to download the binary from. | ||
| */ | ||
| url: string; | ||
| /** | ||
| * Optional name for the cached binary (defaults to URL hash). | ||
| */ | ||
| name?: string | undefined; | ||
| /** | ||
| * Expected checksum (sha256) for verification. | ||
| */ | ||
| checksum?: string | undefined; | ||
| /** | ||
| * Cache TTL in milliseconds (default: 7 days). | ||
| */ | ||
| cacheTtl?: number | undefined; | ||
| /** | ||
| * Force re-download even if cached. | ||
| * Aligns with npm/npx --force flag. | ||
| */ | ||
| force?: boolean | undefined; | ||
| /** | ||
| * Skip confirmation prompts (auto-approve). | ||
| * Aligns with npx --yes/-y flag. | ||
| */ | ||
| yes?: boolean | undefined; | ||
| /** | ||
| * Suppress output (quiet mode). | ||
| * Aligns with npx --quiet/-q and pnpm --silent/-s flags. | ||
| */ | ||
| quiet?: boolean | undefined; | ||
| /** | ||
| * Additional spawn options. | ||
| */ | ||
| spawnOptions?: SpawnOptions | undefined; | ||
| } | ||
| export interface DlxBinaryResult { | ||
| /** Path to the cached binary. */ | ||
| binaryPath: string; | ||
| /** Whether the binary was newly downloaded. */ | ||
| downloaded: boolean; | ||
| /** The spawn promise for the running process. */ | ||
| spawnPromise: ReturnType<typeof spawn>; | ||
| } | ||
| /** | ||
| * Metadata structure for cached binaries (.dlx-metadata.json). | ||
| * Unified schema shared across TypeScript (dlxBinary) and C++ (socket_macho_decompress). | ||
| * | ||
| * Core Fields (present in all implementations): | ||
| * - version: Schema version (currently "1.0.0") | ||
| * - cache_key: First 16 chars of SHA-512 hash (matches directory name) | ||
| * - timestamp: Unix timestamp in milliseconds | ||
| * - checksum: Full hash of cached binary (SHA-512 for C++, SHA-256 for TypeScript) | ||
| * - checksum_algorithm: "sha512" or "sha256" | ||
| * - platform: "darwin" | "linux" | "win32" | ||
| * - arch: "x64" | "arm64" | ||
| * - size: Size of cached binary in bytes | ||
| * - source: Origin information | ||
| * - type: "download" (from URL) or "decompression" (from embedded binary) | ||
| * - url: Download URL (if type is "download") | ||
| * - path: Source binary path (if type is "decompression") | ||
| * | ||
| * Extra Fields (implementation-specific): | ||
| * - For C++ decompression: | ||
| * - compressed_size: Size of compressed data in bytes | ||
| * - compression_algorithm: Brotli level (numeric) | ||
| * - compression_ratio: original_size / compressed_size | ||
| * | ||
| * Example (TypeScript download): | ||
| * ```json | ||
| * { | ||
| * "version": "1.0.0", | ||
| * "cache_key": "a1b2c3d4e5f67890", | ||
| * "timestamp": 1730332800000, | ||
| * "checksum": "sha256-abc123...", | ||
| * "checksum_algorithm": "sha256", | ||
| * "platform": "darwin", | ||
| * "arch": "arm64", | ||
| * "size": 15000000, | ||
| * "source": { | ||
| * "type": "download", | ||
| * "url": "https://example.com/binary" | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * Example (C++ decompression): | ||
| * ```json | ||
| * { | ||
| * "version": "1.0.0", | ||
| * "cache_key": "0123456789abcdef", | ||
| * "timestamp": 1730332800000, | ||
| * "checksum": "sha512-def456...", | ||
| * "checksum_algorithm": "sha512", | ||
| * "platform": "darwin", | ||
| * "arch": "arm64", | ||
| * "size": 13000000, | ||
| * "source": { | ||
| * "type": "decompression", | ||
| * "path": "/usr/local/bin/socket" | ||
| * }, | ||
| * "extra": { | ||
| * "compressed_size": 1700000, | ||
| * "compression_algorithm": 3, | ||
| * "compression_ratio": 7.647 | ||
| * } | ||
| * } | ||
| * ``` | ||
| * | ||
| * @internal This interface documents the metadata file format. | ||
| */ | ||
| export interface DlxMetadata { | ||
| version: string; | ||
| cache_key: string; | ||
| timestamp: number; | ||
| checksum: string; | ||
| checksum_algorithm: string; | ||
| platform: string; | ||
| arch: string; | ||
| size: number; | ||
| source?: { | ||
| type: 'download' | 'decompression'; | ||
| url?: string; | ||
| path?: string; | ||
| }; | ||
| extra?: Record<string, unknown>; | ||
| } | ||
| /** | ||
| * Clean expired entries from the DLX cache. | ||
| */ | ||
| export declare function cleanDlxCache(maxAge?: number): Promise<number>; | ||
| /** | ||
| * Download and execute a binary from a URL with caching. | ||
| */ | ||
| export declare function dlxBinary(args: readonly string[] | string[], options?: DlxBinaryOptions | undefined, spawnExtra?: SpawnExtra | undefined): Promise<DlxBinaryResult>; | ||
| /** | ||
| * Download a binary from a URL with caching (without execution). | ||
| * Similar to downloadPackage from dlx-package. | ||
| * | ||
| * @returns Object containing the path to the cached binary and whether it was downloaded | ||
| */ | ||
| export declare function downloadBinary(options: Omit<DlxBinaryOptions, 'spawnOptions'>): Promise<{ | ||
| binaryPath: string; | ||
| downloaded: boolean; | ||
| }>; | ||
| /** | ||
| * Execute a cached binary without re-downloading. | ||
| * Similar to executePackage from dlx-package. | ||
| * Binary must have been previously downloaded via downloadBinary or dlxBinary. | ||
| * | ||
| * @param binaryPath Path to the cached binary (from downloadBinary result) | ||
| * @param args Arguments to pass to the binary | ||
| * @param spawnOptions Spawn options for execution | ||
| * @param spawnExtra Extra spawn configuration | ||
| * @returns The spawn promise for the running process | ||
| */ | ||
| export declare function executeBinary(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>; | ||
| /** | ||
| * Get the DLX binary cache directory path. | ||
| * Returns normalized path for cross-platform compatibility. | ||
| * Uses same directory as dlx-package for unified DLX storage. | ||
| */ | ||
| export declare function getDlxCachePath(): string; | ||
| /** | ||
| * Get information about cached binaries. | ||
| */ | ||
| export declare function listDlxCache(): Promise<Array<{ | ||
| age: number; | ||
| arch: string; | ||
| checksum: string; | ||
| name: string; | ||
| platform: string; | ||
| size: number; | ||
| url: string; | ||
| }>>; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var dlx_binary_exports = {}; | ||
| __export(dlx_binary_exports, { | ||
| cleanDlxCache: () => cleanDlxCache, | ||
| dlxBinary: () => dlxBinary, | ||
| downloadBinary: () => downloadBinary, | ||
| executeBinary: () => executeBinary, | ||
| getDlxCachePath: () => getDlxCachePath, | ||
| listDlxCache: () => listDlxCache | ||
| }); | ||
| module.exports = __toCommonJS(dlx_binary_exports); | ||
| var import_crypto = require("crypto"); | ||
| var import_os = __toESM(require("os")); | ||
| var import_path = __toESM(require("path")); | ||
| var import_platform = require("./constants/platform"); | ||
| var import_time = require("./constants/time"); | ||
| var import_dlx = require("./dlx"); | ||
| var import_dlx_manifest = require("./dlx-manifest"); | ||
| var import_http_request = require("./http-request"); | ||
| var import_fs = require("./fs"); | ||
| var import_objects = require("./objects"); | ||
| var import_normalize = require("./paths/normalize"); | ||
| var import_socket = require("./paths/socket"); | ||
| var import_process_lock = require("./process-lock"); | ||
| var import_spawn = require("./spawn"); | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| function getMetadataPath(cacheEntryPath) { | ||
| return import_path.default.join(cacheEntryPath, ".dlx-metadata.json"); | ||
| } | ||
| async function isCacheValid(cacheEntryPath, cacheTtl) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| const metaPath = getMetadataPath(cacheEntryPath); | ||
| if (!fs.existsSync(metaPath)) { | ||
| return false; | ||
| } | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!(0, import_objects.isObjectObject)(metadata)) { | ||
| return false; | ||
| } | ||
| const now = Date.now(); | ||
| const timestamp = metadata["timestamp"]; | ||
| if (typeof timestamp !== "number" || timestamp <= 0) { | ||
| return false; | ||
| } | ||
| const age = now - timestamp; | ||
| return age < cacheTtl; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| async function downloadBinaryFile(url, destPath, checksum) { | ||
| const cacheEntryDir = import_path.default.dirname(destPath); | ||
| const lockPath = import_path.default.join(cacheEntryDir, "concurrency.lock"); | ||
| return await import_process_lock.processLock.withLock( | ||
| lockPath, | ||
| async () => { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (fs.existsSync(destPath)) { | ||
| const stats = await fs.promises.stat(destPath); | ||
| if (stats.size > 0) { | ||
| const fileBuffer2 = await fs.promises.readFile(destPath); | ||
| const hasher2 = (0, import_crypto.createHash)("sha256"); | ||
| hasher2.update(fileBuffer2); | ||
| return hasher2.digest("hex"); | ||
| } | ||
| } | ||
| try { | ||
| await (0, import_http_request.httpDownload)(url, destPath); | ||
| } catch (e) { | ||
| throw new Error( | ||
| `Failed to download binary from ${url} | ||
| Destination: ${destPath} | ||
| Check your internet connection or verify the URL is accessible.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| const fileBuffer = await fs.promises.readFile(destPath); | ||
| const hasher = (0, import_crypto.createHash)("sha256"); | ||
| hasher.update(fileBuffer); | ||
| const actualChecksum = hasher.digest("hex"); | ||
| if (checksum && actualChecksum !== checksum) { | ||
| await (0, import_fs.safeDelete)(destPath); | ||
| throw new Error( | ||
| `Checksum mismatch: expected ${checksum}, got ${actualChecksum}` | ||
| ); | ||
| } | ||
| if (!import_platform.WIN32) { | ||
| await fs.promises.chmod(destPath, 493); | ||
| } | ||
| return actualChecksum; | ||
| }, | ||
| { | ||
| // Align with npm npx locking strategy. | ||
| staleMs: 5e3, | ||
| touchIntervalMs: 2e3 | ||
| } | ||
| ); | ||
| } | ||
| async function writeMetadata(cacheEntryPath, cacheKey, url, binaryName, checksum, size) { | ||
| const metaPath = getMetadataPath(cacheEntryPath); | ||
| const metadata = { | ||
| version: "1.0.0", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| checksum, | ||
| checksum_algorithm: "sha256", | ||
| platform: import_os.default.platform(), | ||
| arch: import_os.default.arch(), | ||
| size, | ||
| source: { | ||
| type: "download", | ||
| url | ||
| } | ||
| }; | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2)); | ||
| try { | ||
| const spec = `${url}:${binaryName}`; | ||
| await import_dlx_manifest.dlxManifest.setBinaryEntry(spec, cacheKey, { | ||
| checksum, | ||
| checksum_algorithm: "sha256", | ||
| platform: import_os.default.platform(), | ||
| arch: import_os.default.arch(), | ||
| size, | ||
| source: { | ||
| type: "download", | ||
| url | ||
| } | ||
| }); | ||
| } catch { | ||
| } | ||
| } | ||
| async function cleanDlxCache(maxAge = import_time.DLX_BINARY_CACHE_TTL) { | ||
| const cacheDir = getDlxCachePath(); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (!fs.existsSync(cacheDir)) { | ||
| return 0; | ||
| } | ||
| let cleaned = 0; | ||
| const now = Date.now(); | ||
| const entries = await fs.promises.readdir(cacheDir); | ||
| for (const entry of entries) { | ||
| const entryPath = import_path.default.join(cacheDir, entry); | ||
| const metaPath = getMetadataPath(entryPath); | ||
| try { | ||
| if (!await (0, import_fs.isDir)(entryPath)) { | ||
| continue; | ||
| } | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) { | ||
| continue; | ||
| } | ||
| const timestamp = metadata["timestamp"]; | ||
| const age = typeof timestamp === "number" && timestamp > 0 ? now - timestamp : Number.POSITIVE_INFINITY; | ||
| if (age > maxAge) { | ||
| await (0, import_fs.safeDelete)(entryPath, { force: true, recursive: true }); | ||
| cleaned += 1; | ||
| } | ||
| } catch { | ||
| try { | ||
| const contents = await fs.promises.readdir(entryPath); | ||
| if (!contents.length) { | ||
| await (0, import_fs.safeDelete)(entryPath); | ||
| cleaned += 1; | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| return cleaned; | ||
| } | ||
| async function dlxBinary(args, options, spawnExtra) { | ||
| const { | ||
| cacheTtl = import_time.DLX_BINARY_CACHE_TTL, | ||
| checksum, | ||
| force: userForce = false, | ||
| name, | ||
| spawnOptions, | ||
| url, | ||
| yes | ||
| } = { __proto__: null, ...options }; | ||
| const force = yes === true ? true : userForce; | ||
| const cacheDir = getDlxCachePath(); | ||
| const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`; | ||
| const spec = `${url}:${binaryName}`; | ||
| const cacheKey = (0, import_dlx.generateCacheKey)(spec); | ||
| const cacheEntryDir = import_path.default.join(cacheDir, cacheKey); | ||
| const binaryPath = (0, import_normalize.normalizePath)(import_path.default.join(cacheEntryDir, binaryName)); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| let downloaded = false; | ||
| let computedChecksum = checksum; | ||
| if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) { | ||
| try { | ||
| const metaPath = getMetadataPath(cacheEntryDir); | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (metadata && typeof metadata === "object" && !Array.isArray(metadata) && typeof metadata["checksum"] === "string") { | ||
| computedChecksum = metadata["checksum"]; | ||
| } else { | ||
| downloaded = true; | ||
| } | ||
| } catch { | ||
| downloaded = true; | ||
| } | ||
| } else { | ||
| downloaded = true; | ||
| } | ||
| if (downloaded) { | ||
| try { | ||
| await (0, import_fs.safeMkdir)(cacheEntryDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating binary cache directory: ${cacheEntryDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to create binary cache directory: ${cacheEntryDir}`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| computedChecksum = await downloadBinaryFile(url, binaryPath, checksum); | ||
| const stats = await fs.promises.stat(binaryPath); | ||
| await writeMetadata( | ||
| cacheEntryDir, | ||
| cacheKey, | ||
| url, | ||
| binaryName, | ||
| computedChecksum || "", | ||
| stats.size | ||
| ); | ||
| } | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const finalSpawnOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| env: { | ||
| ...spawnOptions?.env, | ||
| PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}` | ||
| }, | ||
| shell: true | ||
| } : spawnOptions; | ||
| const spawnPromise = (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra); | ||
| return { | ||
| binaryPath, | ||
| downloaded, | ||
| spawnPromise | ||
| }; | ||
| } | ||
| async function downloadBinary(options) { | ||
| const { | ||
| cacheTtl = import_time.DLX_BINARY_CACHE_TTL, | ||
| checksum, | ||
| force = false, | ||
| name, | ||
| url | ||
| } = { __proto__: null, ...options }; | ||
| const cacheDir = getDlxCachePath(); | ||
| const binaryName = name || `binary-${process.platform}-${import_os.default.arch()}`; | ||
| const spec = `${url}:${binaryName}`; | ||
| const cacheKey = (0, import_dlx.generateCacheKey)(spec); | ||
| const cacheEntryDir = import_path.default.join(cacheDir, cacheKey); | ||
| const binaryPath = (0, import_normalize.normalizePath)(import_path.default.join(cacheEntryDir, binaryName)); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| let downloaded = false; | ||
| if (!force && fs.existsSync(cacheEntryDir) && await isCacheValid(cacheEntryDir, cacheTtl)) { | ||
| downloaded = false; | ||
| } else { | ||
| try { | ||
| await (0, import_fs.safeMkdir)(cacheEntryDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating binary cache directory: ${cacheEntryDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create binary cache directory on read-only filesystem: ${cacheEntryDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to create binary cache directory: ${cacheEntryDir}`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| const computedChecksum = await downloadBinaryFile(url, binaryPath, checksum); | ||
| const stats = await fs.promises.stat(binaryPath); | ||
| await writeMetadata( | ||
| cacheEntryDir, | ||
| cacheKey, | ||
| url, | ||
| binaryName, | ||
| computedChecksum || "", | ||
| stats.size | ||
| ); | ||
| downloaded = true; | ||
| } | ||
| return { | ||
| binaryPath, | ||
| downloaded | ||
| }; | ||
| } | ||
| function executeBinary(binaryPath, args, spawnOptions, spawnExtra) { | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const cacheEntryDir = import_path.default.dirname(binaryPath); | ||
| const finalSpawnOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| env: { | ||
| ...spawnOptions?.env, | ||
| PATH: `${cacheEntryDir}${import_path.default.delimiter}${process.env["PATH"] || ""}` | ||
| }, | ||
| shell: true | ||
| } : spawnOptions; | ||
| return (0, import_spawn.spawn)(binaryPath, args, finalSpawnOptions, spawnExtra); | ||
| } | ||
| function getDlxCachePath() { | ||
| return (0, import_socket.getSocketDlxDir)(); | ||
| } | ||
| async function listDlxCache() { | ||
| const cacheDir = getDlxCachePath(); | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| if (!fs.existsSync(cacheDir)) { | ||
| return []; | ||
| } | ||
| const results = []; | ||
| const now = Date.now(); | ||
| const entries = await fs.promises.readdir(cacheDir); | ||
| for (const entry of entries) { | ||
| const entryPath = import_path.default.join(cacheDir, entry); | ||
| try { | ||
| if (!await (0, import_fs.isDir)(entryPath)) { | ||
| continue; | ||
| } | ||
| const metaPath = getMetadataPath(entryPath); | ||
| const metadata = await (0, import_fs.readJson)(metaPath, { throws: false }); | ||
| if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) { | ||
| continue; | ||
| } | ||
| const metaObj = metadata; | ||
| const source = metaObj["source"]; | ||
| const url = source?.["url"] || metaObj["url"] || ""; | ||
| const files = await fs.promises.readdir(entryPath); | ||
| const binaryFile = files.find((f) => !f.startsWith(".")); | ||
| if (binaryFile) { | ||
| const binaryPath = import_path.default.join(entryPath, binaryFile); | ||
| const binaryStats = await fs.promises.stat(binaryPath); | ||
| results.push({ | ||
| age: now - (metaObj["timestamp"] || 0), | ||
| arch: metaObj["arch"] || "unknown", | ||
| checksum: metaObj["checksum"] || "", | ||
| name: binaryFile, | ||
| platform: metaObj["platform"] || "unknown", | ||
| size: binaryStats.size, | ||
| url | ||
| }); | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| return results; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| cleanDlxCache, | ||
| dlxBinary, | ||
| downloadBinary, | ||
| executeBinary, | ||
| getDlxCachePath, | ||
| listDlxCache | ||
| }); |
| /** | ||
| * Details for npm package entries. | ||
| */ | ||
| export interface PackageDetails { | ||
| installed_version: string; | ||
| size?: number; | ||
| update_check?: { | ||
| last_check: number; | ||
| last_notification: number; | ||
| latest_known: string; | ||
| }; | ||
| } | ||
| /** | ||
| * Details for binary download entries. | ||
| */ | ||
| export interface BinaryDetails { | ||
| checksum: string; | ||
| checksum_algorithm: 'sha256' | 'sha512'; | ||
| platform: string; | ||
| arch: string; | ||
| size: number; | ||
| source: { | ||
| type: 'download'; | ||
| url: string; | ||
| }; | ||
| } | ||
| /** | ||
| * Unified manifest entry for all cached items (packages and binaries). | ||
| * Shared fields at root, type-specific fields in details. | ||
| */ | ||
| export interface ManifestEntry { | ||
| type: 'package' | 'binary'; | ||
| cache_key: string; | ||
| timestamp: number; | ||
| details: PackageDetails | BinaryDetails; | ||
| } | ||
| /** | ||
| * Type guard for package entries. | ||
| */ | ||
| export declare function isPackageEntry(entry: ManifestEntry): entry is ManifestEntry & { | ||
| details: PackageDetails; | ||
| }; | ||
| /** | ||
| * Type guard for binary entries. | ||
| */ | ||
| export declare function isBinaryEntry(entry: ManifestEntry): entry is ManifestEntry & { | ||
| details: BinaryDetails; | ||
| }; | ||
| /** | ||
| * Legacy store record format (deprecated, for migration). | ||
| */ | ||
| export interface StoreRecord { | ||
| timestampFetch: number; | ||
| timestampNotification: number; | ||
| version: string; | ||
| } | ||
| export interface DlxManifestOptions { | ||
| /** | ||
| * Custom manifest file path (defaults to ~/.socket/_dlx/.dlx-manifest.json). | ||
| */ | ||
| manifestPath?: string; | ||
| } | ||
| /** | ||
| * DLX manifest storage manager with atomic operations. | ||
| * Supports both legacy format (package name keys) and new unified manifest format (spec keys). | ||
| */ | ||
| export declare class DlxManifest { | ||
| private readonly manifestPath; | ||
| private readonly lockPath; | ||
| constructor(options?: DlxManifestOptions); | ||
| /** | ||
| * Read the entire manifest file. | ||
| */ | ||
| private readManifest; | ||
| /** | ||
| * Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11"). | ||
| */ | ||
| getManifestEntry(spec: string): ManifestEntry | undefined; | ||
| /** | ||
| * Get cached update information for a package (legacy format). | ||
| * @deprecated Use getManifestEntry() for new code. | ||
| */ | ||
| get(name: string): StoreRecord | undefined; | ||
| /** | ||
| * Set a package manifest entry. | ||
| */ | ||
| setPackageEntry(spec: string, cacheKey: string, details: PackageDetails): Promise<void>; | ||
| /** | ||
| * Set a binary manifest entry. | ||
| */ | ||
| setBinaryEntry(spec: string, cacheKey: string, details: BinaryDetails): Promise<void>; | ||
| private writeManifest; | ||
| /** | ||
| * Store update information for a package (legacy format). | ||
| * @deprecated Use setPackageEntry() for new code. | ||
| */ | ||
| set(name: string, record: StoreRecord): Promise<void>; | ||
| /** | ||
| * Clear cached data for a specific entry. | ||
| */ | ||
| clear(name: string): Promise<void>; | ||
| /** | ||
| * Clear all cached data. | ||
| */ | ||
| clearAll(): Promise<void>; | ||
| /** | ||
| * Check if cached data is fresh based on TTL. | ||
| */ | ||
| isFresh(record: StoreRecord | undefined, ttlMs: number): boolean; | ||
| /** | ||
| * Get all cached package names. | ||
| */ | ||
| getAllPackages(): string[]; | ||
| } | ||
| // Export singleton instance using default manifest location. | ||
| export declare const dlxManifest: DlxManifest; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var dlx_manifest_exports = {}; | ||
| __export(dlx_manifest_exports, { | ||
| DlxManifest: () => DlxManifest, | ||
| dlxManifest: () => dlxManifest, | ||
| isBinaryEntry: () => isBinaryEntry, | ||
| isPackageEntry: () => isPackageEntry | ||
| }); | ||
| module.exports = __toCommonJS(dlx_manifest_exports); | ||
| var import_fs = require("fs"); | ||
| var import_path = __toESM(require("path")); | ||
| var import_fs2 = require("./fs"); | ||
| var import_logger = require("./logger"); | ||
| var import_socket = require("./paths/socket"); | ||
| var import_process_lock = require("./process-lock"); | ||
| const logger = (0, import_logger.getDefaultLogger)(); | ||
| const MANIFEST_FILE_NAME = ".dlx-manifest.json"; | ||
| function isPackageEntry(entry) { | ||
| return entry.type === "package"; | ||
| } | ||
| function isBinaryEntry(entry) { | ||
| return entry.type === "binary"; | ||
| } | ||
| class DlxManifest { | ||
| manifestPath; | ||
| lockPath; | ||
| constructor(options = {}) { | ||
| this.manifestPath = options.manifestPath ?? import_path.default.join((0, import_socket.getSocketDlxDir)(), MANIFEST_FILE_NAME); | ||
| this.lockPath = `${this.manifestPath}.lock`; | ||
| } | ||
| /** | ||
| * Read the entire manifest file. | ||
| */ | ||
| readManifest() { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| const rawContent = (0, import_fs2.readFileUtf8Sync)(this.manifestPath); | ||
| const content = (typeof rawContent === "string" ? rawContent : rawContent.toString("utf8")).trim(); | ||
| if (!content) { | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| return JSON.parse(content); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to read manifest: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| return /* @__PURE__ */ Object.create(null); | ||
| } | ||
| } | ||
| /** | ||
| * Get a manifest entry by spec (e.g., "@socketsecurity/cli@^2.0.11"). | ||
| */ | ||
| getManifestEntry(spec) { | ||
| const data = this.readManifest(); | ||
| const entry = data[spec]; | ||
| if (entry && "type" in entry) { | ||
| return entry; | ||
| } | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Get cached update information for a package (legacy format). | ||
| * @deprecated Use getManifestEntry() for new code. | ||
| */ | ||
| get(name) { | ||
| const data = this.readManifest(); | ||
| const entry = data[name]; | ||
| if (entry && !("type" in entry)) { | ||
| return entry; | ||
| } | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Set a package manifest entry. | ||
| */ | ||
| async setPackageEntry(spec, cacheKey, details) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| const data = this.readManifest(); | ||
| data[spec] = { | ||
| type: "package", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| details | ||
| }; | ||
| await this.writeManifest(data); | ||
| }); | ||
| } | ||
| /** | ||
| * Set a binary manifest entry. | ||
| */ | ||
| async setBinaryEntry(spec, cacheKey, details) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| const data = this.readManifest(); | ||
| data[spec] = { | ||
| type: "binary", | ||
| cache_key: cacheKey, | ||
| timestamp: Date.now(), | ||
| details | ||
| }; | ||
| await this.writeManifest(data); | ||
| }); | ||
| } | ||
| /** | ||
| * Write the manifest file atomically. | ||
| */ | ||
| async writeManifest(data) { | ||
| const manifestDir = import_path.default.dirname(this.manifestPath); | ||
| try { | ||
| (0, import_fs2.safeMkdirSync)(manifestDir, { recursive: true }); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| const content = JSON.stringify(data, null, 2); | ||
| const tempPath = `${this.manifestPath}.tmp`; | ||
| try { | ||
| (0, import_fs.writeFileSync)(tempPath, content, "utf8"); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, content, "utf8"); | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| } catch (error) { | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
| /** | ||
| * Store update information for a package (legacy format). | ||
| * @deprecated Use setPackageEntry() for new code. | ||
| */ | ||
| async set(name, record) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| let data = /* @__PURE__ */ Object.create(null); | ||
| try { | ||
| if ((0, import_fs.existsSync)(this.manifestPath)) { | ||
| const content2 = (0, import_fs.readFileSync)(this.manifestPath, "utf8"); | ||
| if (content2.trim()) { | ||
| data = JSON.parse(content2); | ||
| } | ||
| } | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| data[name] = record; | ||
| const manifestDir = import_path.default.dirname(this.manifestPath); | ||
| try { | ||
| (0, import_fs2.safeMkdirSync)(manifestDir, { recursive: true }); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| const content = JSON.stringify(data, null, 2); | ||
| const tempPath = `${this.manifestPath}.tmp`; | ||
| try { | ||
| (0, import_fs.writeFileSync)(tempPath, content, "utf8"); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, content, "utf8"); | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| } catch (error) { | ||
| try { | ||
| if ((0, import_fs.existsSync)(tempPath)) { | ||
| (0, import_fs.unlinkSync)(tempPath); | ||
| } | ||
| } catch { | ||
| } | ||
| throw error; | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Clear cached data for a specific entry. | ||
| */ | ||
| async clear(name) { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return; | ||
| } | ||
| const content = (0, import_fs.readFileSync)(this.manifestPath, "utf8"); | ||
| if (!content.trim()) { | ||
| return; | ||
| } | ||
| const data = JSON.parse(content); | ||
| delete data[name]; | ||
| const updatedContent = JSON.stringify(data, null, 2); | ||
| (0, import_fs.writeFileSync)(this.manifestPath, updatedContent, "utf8"); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to clear cache for ${name}: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Clear all cached data. | ||
| */ | ||
| async clearAll() { | ||
| await import_process_lock.processLock.withLock(this.lockPath, async () => { | ||
| try { | ||
| if ((0, import_fs.existsSync)(this.manifestPath)) { | ||
| (0, import_fs.unlinkSync)(this.manifestPath); | ||
| } | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to clear all cache: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| /** | ||
| * Check if cached data is fresh based on TTL. | ||
| */ | ||
| isFresh(record, ttlMs) { | ||
| if (!record) { | ||
| return false; | ||
| } | ||
| const age = Date.now() - record.timestampFetch; | ||
| return age < ttlMs; | ||
| } | ||
| /** | ||
| * Get all cached package names. | ||
| */ | ||
| getAllPackages() { | ||
| try { | ||
| if (!(0, import_fs.existsSync)(this.manifestPath)) { | ||
| return []; | ||
| } | ||
| const rawContent = (0, import_fs2.readFileUtf8Sync)(this.manifestPath); | ||
| const content = (typeof rawContent === "string" ? rawContent : rawContent.toString("utf8")).trim(); | ||
| if (!content) { | ||
| return []; | ||
| } | ||
| const data = JSON.parse(content); | ||
| return Object.keys(data); | ||
| } catch (error) { | ||
| logger.warn( | ||
| `Failed to get package list: ${error instanceof Error ? error.message : String(error)}` | ||
| ); | ||
| return []; | ||
| } | ||
| } | ||
| } | ||
| const dlxManifest = new DlxManifest(); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| DlxManifest, | ||
| dlxManifest, | ||
| isBinaryEntry, | ||
| isPackageEntry | ||
| }); |
| import type { SpawnExtra, SpawnOptions } from './spawn'; | ||
| import { spawn } from './spawn'; | ||
| export interface DownloadPackageResult { | ||
| /** Path to the installed package directory. */ | ||
| packageDir: string; | ||
| /** Path to the binary. */ | ||
| binaryPath: string; | ||
| /** Whether the package was newly installed. */ | ||
| installed: boolean; | ||
| } | ||
| export interface DlxPackageOptions { | ||
| /** | ||
| * Package to install (e.g., '@cyclonedx/cdxgen@10.0.0'). | ||
| * Aligns with npx --package flag. | ||
| */ | ||
| package: string; | ||
| /** | ||
| * Binary name to execute (optional - auto-detected in most cases). | ||
| * | ||
| * Auto-detection logic: | ||
| * 1. If package has only one binary, uses it automatically | ||
| * 2. Tries user-provided binaryName | ||
| * 3. Tries last segment of package name (e.g., 'cli' from '@socketsecurity/cli') | ||
| * 4. Falls back to first binary | ||
| * | ||
| * Only needed when package has multiple binaries and auto-detection fails. | ||
| * | ||
| * @example | ||
| * // Auto-detected (single binary) | ||
| * { package: '@socketsecurity/cli' } // Finds 'socket' binary automatically | ||
| * | ||
| * // Explicit (multiple binaries) | ||
| * { package: 'some-tool', binaryName: 'specific-tool' } | ||
| */ | ||
| binaryName?: string | undefined; | ||
| /** | ||
| * Force reinstallation even if package exists. | ||
| * Aligns with npx --yes/-y flag behavior. | ||
| */ | ||
| force?: boolean | undefined; | ||
| /** | ||
| * Skip confirmation prompts (auto-approve). | ||
| * Aligns with npx --yes/-y flag. | ||
| */ | ||
| yes?: boolean | undefined; | ||
| /** | ||
| * Suppress output (quiet mode). | ||
| * Aligns with npx --quiet/-q and pnpm --silent/-s flags. | ||
| */ | ||
| quiet?: boolean | undefined; | ||
| /** | ||
| * Additional spawn options for the execution. | ||
| */ | ||
| spawnOptions?: SpawnOptions | undefined; | ||
| } | ||
| export interface DlxPackageResult { | ||
| /** Path to the installed package directory. */ | ||
| packageDir: string; | ||
| /** Path to the binary that was executed. */ | ||
| binaryPath: string; | ||
| /** Whether the package was newly installed. */ | ||
| installed: boolean; | ||
| /** The spawn promise for the running process. */ | ||
| spawnPromise: ReturnType<typeof spawn>; | ||
| } | ||
| /** | ||
| * Execute a package via DLX - install if needed and run its binary. | ||
| * | ||
| * This is the Socket equivalent of npx/pnpm dlx/yarn dlx, but using | ||
| * our own cache directory (~/.socket/_dlx) and installation logic. | ||
| * | ||
| * Auto-forces reinstall for version ranges to get latest within range. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Download and execute cdxgen | ||
| * const result = await dlxPackage( | ||
| * ['--version'], | ||
| * { package: '@cyclonedx/cdxgen@10.0.0' } | ||
| * ) | ||
| * await result.spawnPromise | ||
| * ``` | ||
| */ | ||
| export declare function dlxPackage(args: readonly string[] | string[], options?: DlxPackageOptions | undefined, spawnExtra?: SpawnExtra | undefined): Promise<DlxPackageResult>; | ||
| /** | ||
| * Download and install a package without executing it. | ||
| * This is useful for self-update or when you need the package files | ||
| * but don't want to run the binary immediately. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Install @socketsecurity/cli without running it | ||
| * const result = await downloadPackage({ | ||
| * package: '@socketsecurity/cli@1.2.0', | ||
| * force: true | ||
| * }) | ||
| * console.log('Installed to:', result.packageDir) | ||
| * console.log('Binary at:', result.binaryPath) | ||
| * ``` | ||
| */ | ||
| export declare function downloadPackage(options: DlxPackageOptions): Promise<DownloadPackageResult>; | ||
| /** | ||
| * Execute a package's binary with cross-platform shell handling. | ||
| * The package must already be installed (use downloadPackage first). | ||
| * | ||
| * On Windows, script files (.bat, .cmd, .ps1) require shell: true. | ||
| * Matches npm/npx execution behavior. | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * // Execute an already-installed package | ||
| * const downloaded = await downloadPackage({ package: 'cowsay@1.5.0' }) | ||
| * const result = await executePackage( | ||
| * downloaded.binaryPath, | ||
| * ['Hello World'], | ||
| * { stdio: 'inherit' } | ||
| * ) | ||
| * ``` | ||
| */ | ||
| export declare function executePackage(binaryPath: string, args: readonly string[] | string[], spawnOptions?: SpawnOptions | undefined, spawnExtra?: SpawnExtra | undefined): ReturnType<typeof spawn>; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var dlx_package_exports = {}; | ||
| __export(dlx_package_exports, { | ||
| dlxPackage: () => dlxPackage, | ||
| downloadPackage: () => downloadPackage, | ||
| executePackage: () => executePackage | ||
| }); | ||
| module.exports = __toCommonJS(dlx_package_exports); | ||
| var import_node_fs = __toESM(require("node:fs")); | ||
| var import_path = __toESM(require("path")); | ||
| var import_platform = require("./constants/platform"); | ||
| var import_packages = require("./constants/packages"); | ||
| var import_dlx = require("./dlx"); | ||
| var import_arborist = __toESM(require("./external/@npmcli/arborist")); | ||
| var import_libnpmexec = __toESM(require("./external/libnpmexec")); | ||
| var import_npm_package_arg = __toESM(require("./external/npm-package-arg")); | ||
| var import_pacote = __toESM(require("./external/pacote")); | ||
| var import_fs = require("./fs"); | ||
| var import_normalize = require("./paths/normalize"); | ||
| var import_socket = require("./paths/socket"); | ||
| var import_process_lock = require("./process-lock"); | ||
| var import_spawn = require("./spawn"); | ||
| const rangeOperatorsRegExp = /[~^><=xX* ]|\|\|/; | ||
| function parsePackageSpec(spec) { | ||
| try { | ||
| const parsed = (0, import_npm_package_arg.default)(spec); | ||
| const version = parsed.type === "tag" ? parsed.fetchSpec : parsed.type === "version" || parsed.type === "range" ? parsed.fetchSpec : void 0; | ||
| return { | ||
| name: parsed.name || spec, | ||
| version | ||
| }; | ||
| } catch { | ||
| const atIndex = spec.lastIndexOf("@"); | ||
| if (atIndex === -1 || spec.startsWith("@")) { | ||
| return { name: spec, version: void 0 }; | ||
| } | ||
| return { | ||
| name: spec.slice(0, atIndex), | ||
| version: spec.slice(atIndex + 1) | ||
| }; | ||
| } | ||
| } | ||
| async function ensurePackageInstalled(packageName, packageSpec, force) { | ||
| const cacheKey = (0, import_dlx.generateCacheKey)(packageSpec); | ||
| const packageDir = (0, import_normalize.normalizePath)(import_path.default.join((0, import_socket.getSocketDlxDir)(), cacheKey)); | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| try { | ||
| await (0, import_fs.safeMkdir)(packageDir); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied creating package directory: ${packageDir} | ||
| Please check directory permissions or run with appropriate access.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot create package directory on read-only filesystem: ${packageDir} | ||
| Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error(`Failed to create package directory: ${packageDir}`, { | ||
| cause: e | ||
| }); | ||
| } | ||
| const lockPath = import_path.default.join(packageDir, "concurrency.lock"); | ||
| return await import_process_lock.processLock.withLock( | ||
| lockPath, | ||
| async () => { | ||
| if (!force && import_node_fs.default.existsSync(installedDir)) { | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| if (import_node_fs.default.existsSync(pkgJsonPath)) { | ||
| return { installed: false, packageDir }; | ||
| } | ||
| } | ||
| const pacoteCachePath = (0, import_packages.getPacoteCachePath)(); | ||
| try { | ||
| await import_pacote.default.extract(packageSpec, installedDir, { | ||
| // Use consistent pacote cache path (respects npm cache locations when available). | ||
| cache: pacoteCachePath || import_path.default.join(packageDir, ".cache") | ||
| }); | ||
| const arb = new import_arborist.default({ | ||
| path: installedDir, | ||
| cache: pacoteCachePath || import_path.default.join(packageDir, ".cache"), | ||
| // Skip devDependencies (production-only like npx). | ||
| omit: ["dev"], | ||
| // Security: Skip install/preinstall/postinstall scripts to prevent arbitrary code execution. | ||
| ignoreScripts: true, | ||
| // Security: Enable binary links (needed for dlx to execute the package binary). | ||
| binLinks: true, | ||
| // Suppress funding messages (unneeded for ephemeral dlx installs). | ||
| fund: false, | ||
| // Skip audit (unneeded for ephemeral dlx installs). | ||
| audit: false, | ||
| // Suppress output (unneeded for ephemeral dlx installs). | ||
| silent: true | ||
| }); | ||
| await arb.buildIdealTree(); | ||
| await arb.reify({ save: false }); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "E404" || code === "ETARGET") { | ||
| throw new Error( | ||
| `Package not found: ${packageSpec} | ||
| Verify the package exists on npm registry and check the version. | ||
| Visit https://www.npmjs.com/package/${packageName} to see available versions.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "ENOTFOUND" || code === "ETIMEDOUT" || code === "EAI_AGAIN") { | ||
| throw new Error( | ||
| `Network error installing ${packageSpec} | ||
| Check your internet connection and try again.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to install package: ${packageSpec} | ||
| Destination: ${installedDir} | ||
| Check npm registry connectivity or package name.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| return { installed: true, packageDir }; | ||
| }, | ||
| { | ||
| // Align with npm npx locking strategy. | ||
| staleMs: 5e3, | ||
| touchIntervalMs: 2e3 | ||
| } | ||
| ); | ||
| } | ||
| function resolveBinaryPath(basePath) { | ||
| if (!import_platform.WIN32) { | ||
| return basePath; | ||
| } | ||
| const extensions = [".cmd", ".bat", ".ps1", ".exe", ""]; | ||
| for (const ext of extensions) { | ||
| const testPath = basePath + ext; | ||
| if (import_node_fs.default.existsSync(testPath)) { | ||
| return testPath; | ||
| } | ||
| } | ||
| return basePath; | ||
| } | ||
| function findBinaryPath(packageDir, packageName, binaryName) { | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| const pkgJson = (0, import_fs.readJsonSync)(pkgJsonPath); | ||
| const bin = pkgJson["bin"]; | ||
| let binName; | ||
| let binPath; | ||
| if (typeof bin === "string") { | ||
| binPath = bin; | ||
| } else if (typeof bin === "object" && bin !== null) { | ||
| const binObj = bin; | ||
| const binKeys = Object.keys(binObj); | ||
| if (binKeys.length === 1) { | ||
| binName = binKeys[0]; | ||
| binPath = binObj[binName]; | ||
| } else { | ||
| try { | ||
| const { getBinFromManifest } = import_libnpmexec.default; | ||
| binName = getBinFromManifest({ | ||
| name: packageName, | ||
| bin: binObj, | ||
| _id: `${packageName}@${pkgJson.version || "unknown"}` | ||
| }); | ||
| binPath = binObj[binName]; | ||
| } catch { | ||
| const lastSegment = packageName.split("/").pop(); | ||
| const candidates = [ | ||
| binaryName, | ||
| lastSegment, | ||
| packageName.replace(/^@[^/]+\//, "") | ||
| ].filter(Boolean); | ||
| for (const candidate of candidates) { | ||
| if (candidate && binObj[candidate]) { | ||
| binName = candidate; | ||
| binPath = binObj[candidate]; | ||
| break; | ||
| } | ||
| } | ||
| if (!binPath && binKeys.length > 0) { | ||
| binName = binKeys[0]; | ||
| binPath = binObj[binName]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| if (!binPath) { | ||
| throw new Error(`No binary found for package "${packageName}"`); | ||
| } | ||
| const rawPath = (0, import_normalize.normalizePath)(import_path.default.join(installedDir, binPath)); | ||
| return resolveBinaryPath(rawPath); | ||
| } | ||
| async function dlxPackage(args, options, spawnExtra) { | ||
| const downloadResult = await downloadPackage(options); | ||
| const spawnPromise = executePackage( | ||
| downloadResult.binaryPath, | ||
| args, | ||
| options?.spawnOptions, | ||
| spawnExtra | ||
| ); | ||
| return { | ||
| ...downloadResult, | ||
| spawnPromise | ||
| }; | ||
| } | ||
| function makePackageBinsExecutable(packageDir, packageName) { | ||
| if (import_platform.WIN32) { | ||
| return; | ||
| } | ||
| const installedDir = (0, import_normalize.normalizePath)( | ||
| import_path.default.join(packageDir, "node_modules", packageName) | ||
| ); | ||
| const pkgJsonPath = import_path.default.join(installedDir, "package.json"); | ||
| try { | ||
| const pkgJson = (0, import_fs.readJsonSync)(pkgJsonPath); | ||
| const bin = pkgJson["bin"]; | ||
| if (!bin) { | ||
| return; | ||
| } | ||
| const binPaths = []; | ||
| if (typeof bin === "string") { | ||
| binPaths.push(bin); | ||
| } else if (typeof bin === "object" && bin !== null) { | ||
| const binObj = bin; | ||
| binPaths.push(...Object.values(binObj)); | ||
| } | ||
| for (const binPath of binPaths) { | ||
| const fullPath = (0, import_normalize.normalizePath)(import_path.default.join(installedDir, binPath)); | ||
| if (import_node_fs.default.existsSync(fullPath)) { | ||
| try { | ||
| import_node_fs.default.chmodSync(fullPath, 493); | ||
| } catch { | ||
| } | ||
| } | ||
| } | ||
| } catch { | ||
| } | ||
| } | ||
| async function downloadPackage(options) { | ||
| const { | ||
| binaryName, | ||
| force: userForce, | ||
| package: packageSpec, | ||
| yes | ||
| } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { name: packageName, version: packageVersion } = parsePackageSpec(packageSpec); | ||
| const isVersionRange = packageVersion !== void 0 && rangeOperatorsRegExp.test(packageVersion); | ||
| const force = userForce !== void 0 ? userForce : yes === true ? true : isVersionRange; | ||
| const fullPackageSpec = packageVersion ? `${packageName}@${packageVersion}` : packageName; | ||
| const { installed, packageDir } = await ensurePackageInstalled( | ||
| packageName, | ||
| fullPackageSpec, | ||
| force | ||
| ); | ||
| const binaryPath = findBinaryPath(packageDir, packageName, binaryName); | ||
| makePackageBinsExecutable(packageDir, packageName); | ||
| return { | ||
| binaryPath, | ||
| installed, | ||
| packageDir | ||
| }; | ||
| } | ||
| function executePackage(binaryPath, args, spawnOptions, spawnExtra) { | ||
| const needsShell = import_platform.WIN32 && /\.(?:bat|cmd|ps1)$/i.test(binaryPath); | ||
| const finalOptions = needsShell ? { | ||
| ...spawnOptions, | ||
| shell: true | ||
| } : spawnOptions; | ||
| return (0, import_spawn.spawn)(binaryPath, args, finalOptions, spawnExtra); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| dlxPackage, | ||
| downloadPackage, | ||
| executePackage | ||
| }); |
-104
| /** | ||
| * Generate a cache directory name using npm/npx approach. | ||
| * Uses first 16 characters of SHA-512 hash (like npm/npx). | ||
| * | ||
| * Rationale for SHA-512 truncated (vs full SHA-256): | ||
| * - Matches npm/npx ecosystem behavior | ||
| * - Shorter paths for Windows MAX_PATH compatibility (260 chars) | ||
| * - 16 hex chars = 64 bits = acceptable collision risk for local cache | ||
| * - Collision probability ~1 in 18 quintillion with 1000 entries | ||
| * | ||
| * Input strategy (aligned with npx): | ||
| * - npx uses package spec strings (e.g., '@scope/pkg@1.0.0', 'prettier@3.0.0') | ||
| * - Caller provides complete spec string with version for accurate cache keying | ||
| * - For package installs: Use PURL-style spec with version | ||
| * Examples: 'npm:prettier@3.0.0', 'pypi:requests@2.31.0', 'gem:rails@7.0.0' | ||
| * Note: Socket uses shorthand format without 'pkg:' prefix | ||
| * (handled by @socketregistry/packageurl-js) | ||
| * - For binary downloads: Use URL:name for uniqueness | ||
| * | ||
| * Reference: npm/cli v11.6.2 libnpmexec/lib/index.js#L233-L244 | ||
| * https://github.com/npm/cli/blob/v11.6.2/workspaces/libnpmexec/lib/index.js#L233-L244 | ||
| * Implementation: packages.map().sort().join('\n') → SHA-512 → slice(0,16) | ||
| * npx hashes the package spec (name@version), not just name | ||
| */ | ||
| export declare function generateCacheKey(spec: string): string; | ||
| /** | ||
| * Clear all DLX package installations. | ||
| */ | ||
| export declare function clearDlx(): Promise<void>; | ||
| /** | ||
| * Clear all DLX package installations synchronously. | ||
| */ | ||
| export declare function clearDlxSync(): void; | ||
| /** | ||
| * Check if the DLX directory exists. | ||
| */ | ||
| export declare function dlxDirExists(): boolean; | ||
| /** | ||
| * Check if the DLX directory exists asynchronously. | ||
| */ | ||
| export declare function dlxDirExistsAsync(): Promise<boolean>; | ||
| /** | ||
| * Ensure the DLX directory exists, creating it if necessary. | ||
| */ | ||
| export declare function ensureDlxDir(): Promise<void>; | ||
| /** | ||
| * Ensure the DLX directory exists synchronously, creating it if necessary. | ||
| */ | ||
| export declare function ensureDlxDirSync(): void; | ||
| /** | ||
| * Get the installed package directory within DLX node_modules. | ||
| */ | ||
| export declare function getDlxInstalledPackageDir(packageName: string): string; | ||
| /** | ||
| * Get the DLX installation directory for a specific package. | ||
| */ | ||
| export declare function getDlxPackageDir(packageName: string): string; | ||
| /** | ||
| * Get the package.json path for a DLX installed package. | ||
| */ | ||
| export declare function getDlxPackageJsonPath(packageName: string): string; | ||
| /** | ||
| * Get the node_modules directory for a DLX package installation. | ||
| */ | ||
| export declare function getDlxPackageNodeModulesDir(packageName: string): string; | ||
| /** | ||
| * Check if a file path is within the Socket DLX directory. | ||
| * This is useful for determining if a binary or file is managed by Socket's DLX system. | ||
| * | ||
| * @param filePath - Absolute or relative path to check | ||
| * @returns true if the path is within ~/.socket/_dlx/, false otherwise | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * isInSocketDlx('/home/user/.socket/_dlx/abc123/bin/socket') // true | ||
| * isInSocketDlx('/usr/local/bin/socket') // false | ||
| * isInSocketDlx(process.argv[0]) // Check if current binary is in DLX | ||
| * ``` | ||
| */ | ||
| export declare function isInSocketDlx(filePath: string): boolean; | ||
| /** | ||
| * Check if a package is installed in DLX. | ||
| */ | ||
| export declare function isDlxPackageInstalled(packageName: string): boolean; | ||
| /** | ||
| * Check if a package is installed in DLX asynchronously. | ||
| */ | ||
| export declare function isDlxPackageInstalledAsync(packageName: string): Promise<boolean>; | ||
| /** | ||
| * List all packages installed in DLX. | ||
| */ | ||
| export declare function listDlxPackages(): string[]; | ||
| /** | ||
| * List all packages installed in DLX asynchronously. | ||
| */ | ||
| export declare function listDlxPackagesAsync(): Promise<string[]>; | ||
| /** | ||
| * Remove a DLX package installation. | ||
| */ | ||
| export declare function removeDlxPackage(packageName: string): Promise<void>; | ||
| /** | ||
| * Remove a DLX package installation synchronously. | ||
| */ | ||
| export declare function removeDlxPackageSync(packageName: string): void; |
-220
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var dlx_exports = {}; | ||
| __export(dlx_exports, { | ||
| clearDlx: () => clearDlx, | ||
| clearDlxSync: () => clearDlxSync, | ||
| dlxDirExists: () => dlxDirExists, | ||
| dlxDirExistsAsync: () => dlxDirExistsAsync, | ||
| ensureDlxDir: () => ensureDlxDir, | ||
| ensureDlxDirSync: () => ensureDlxDirSync, | ||
| generateCacheKey: () => generateCacheKey, | ||
| getDlxInstalledPackageDir: () => getDlxInstalledPackageDir, | ||
| getDlxPackageDir: () => getDlxPackageDir, | ||
| getDlxPackageJsonPath: () => getDlxPackageJsonPath, | ||
| getDlxPackageNodeModulesDir: () => getDlxPackageNodeModulesDir, | ||
| isDlxPackageInstalled: () => isDlxPackageInstalled, | ||
| isDlxPackageInstalledAsync: () => isDlxPackageInstalledAsync, | ||
| isInSocketDlx: () => isInSocketDlx, | ||
| listDlxPackages: () => listDlxPackages, | ||
| listDlxPackagesAsync: () => listDlxPackagesAsync, | ||
| removeDlxPackage: () => removeDlxPackage, | ||
| removeDlxPackageSync: () => removeDlxPackageSync | ||
| }); | ||
| module.exports = __toCommonJS(dlx_exports); | ||
| var import_crypto = require("crypto"); | ||
| var import_fs = require("./fs"); | ||
| var import_normalize = require("./paths/normalize"); | ||
| var import_socket = require("./paths/socket"); | ||
| var import_promises = require("./promises"); | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| function generateCacheKey(spec) { | ||
| return (0, import_crypto.createHash)("sha512").update(spec).digest("hex").substring(0, 16); | ||
| } | ||
| let _path; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getPath() { | ||
| if (_path === void 0) { | ||
| _path = require("node:path"); | ||
| } | ||
| return _path; | ||
| } | ||
| async function clearDlx() { | ||
| const packages = await listDlxPackagesAsync(); | ||
| await (0, import_promises.pEach)(packages, (pkg) => removeDlxPackage(pkg)); | ||
| } | ||
| function clearDlxSync() { | ||
| const packages = listDlxPackages(); | ||
| for (const pkg of packages) { | ||
| removeDlxPackageSync(pkg); | ||
| } | ||
| } | ||
| function dlxDirExists() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| return fs.existsSync((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| async function dlxDirExistsAsync() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| await fs.promises.access((0, import_socket.getSocketDlxDir)()); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| async function ensureDlxDir() { | ||
| await (0, import_fs.safeMkdir)((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| function ensureDlxDirSync() { | ||
| (0, import_fs.safeMkdirSync)((0, import_socket.getSocketDlxDir)()); | ||
| } | ||
| function getDlxInstalledPackageDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)( | ||
| path.join(getDlxPackageNodeModulesDir(packageName), packageName) | ||
| ); | ||
| } | ||
| function getDlxPackageDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)(path.join((0, import_socket.getSocketDlxDir)(), packageName)); | ||
| } | ||
| function getDlxPackageJsonPath(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)( | ||
| path.join(getDlxInstalledPackageDir(packageName), "package.json") | ||
| ); | ||
| } | ||
| function getDlxPackageNodeModulesDir(packageName) { | ||
| const path = /* @__PURE__ */ getPath(); | ||
| return (0, import_normalize.normalizePath)(path.join(getDlxPackageDir(packageName), "node_modules")); | ||
| } | ||
| function isInSocketDlx(filePath) { | ||
| if (!filePath) { | ||
| return false; | ||
| } | ||
| const path = /* @__PURE__ */ getPath(); | ||
| const dlxDir = (0, import_socket.getSocketDlxDir)(); | ||
| const absolutePath = (0, import_normalize.normalizePath)(path.resolve(filePath)); | ||
| return absolutePath.startsWith(`${dlxDir}/`); | ||
| } | ||
| function isDlxPackageInstalled(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| return fs.existsSync(getDlxInstalledPackageDir(packageName)); | ||
| } | ||
| async function isDlxPackageInstalledAsync(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| await fs.promises.access(getDlxInstalledPackageDir(packageName)); | ||
| return true; | ||
| } catch { | ||
| return false; | ||
| } | ||
| } | ||
| function listDlxPackages() { | ||
| try { | ||
| return (0, import_fs.readDirNamesSync)((0, import_socket.getSocketDlxDir)(), { sort: true }); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
| async function listDlxPackagesAsync() { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| try { | ||
| const entries = await fs.promises.readdir((0, import_socket.getSocketDlxDir)(), { | ||
| withFileTypes: true | ||
| }); | ||
| return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort(); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
| async function removeDlxPackage(packageName) { | ||
| const packageDir = getDlxPackageDir(packageName); | ||
| try { | ||
| await (0, import_fs.safeDelete)(packageDir, { recursive: true, force: true }); | ||
| } catch (e) { | ||
| throw new Error(`Failed to remove DLX package "${packageName}"`, { | ||
| cause: e | ||
| }); | ||
| } | ||
| } | ||
| function removeDlxPackageSync(packageName) { | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| const packageDir = getDlxPackageDir(packageName); | ||
| try { | ||
| fs.rmSync(packageDir, { recursive: true, force: true }); | ||
| } catch (e) { | ||
| const code = e.code; | ||
| if (code === "EACCES" || code === "EPERM") { | ||
| throw new Error( | ||
| `Permission denied removing DLX package "${packageName}" | ||
| Directory: ${packageDir} | ||
| To resolve: | ||
| 1. Check file/directory permissions | ||
| 2. Close any programs using files in this directory | ||
| 3. Try running with elevated privileges if necessary | ||
| 4. Manually remove: rm -rf "${packageDir}"`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| if (code === "EROFS") { | ||
| throw new Error( | ||
| `Cannot remove DLX package "${packageName}" from read-only filesystem | ||
| Directory: ${packageDir} | ||
| The filesystem is mounted read-only.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| throw new Error( | ||
| `Failed to remove DLX package "${packageName}" | ||
| Directory: ${packageDir} | ||
| Check permissions and ensure no programs are using this directory.`, | ||
| { cause: e } | ||
| ); | ||
| } | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| clearDlx, | ||
| clearDlxSync, | ||
| dlxDirExists, | ||
| dlxDirExistsAsync, | ||
| ensureDlxDir, | ||
| ensureDlxDirSync, | ||
| generateCacheKey, | ||
| getDlxInstalledPackageDir, | ||
| getDlxPackageDir, | ||
| getDlxPackageJsonPath, | ||
| getDlxPackageNodeModulesDir, | ||
| isDlxPackageInstalled, | ||
| isDlxPackageInstalledAsync, | ||
| isInSocketDlx, | ||
| listDlxPackages, | ||
| listDlxPackagesAsync, | ||
| removeDlxPackage, | ||
| removeDlxPackageSync | ||
| }); |
-196
| /** | ||
| * JSON primitive types: `null`, `boolean`, `number`, or `string`. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const primitives: JsonPrimitive[] = [null, true, 42, 'hello'] | ||
| * ``` | ||
| */ | ||
| export type JsonPrimitive = null | boolean | number | string; | ||
| /** | ||
| * Any valid JSON value: primitive, object, or array. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const values: JsonValue[] = [ | ||
| * null, | ||
| * true, | ||
| * 42, | ||
| * 'hello', | ||
| * { key: 'value' }, | ||
| * [1, 2, 3] | ||
| * ] | ||
| * ``` | ||
| */ | ||
| export type JsonValue = JsonPrimitive | JsonObject | JsonArray; | ||
| /** | ||
| * A JSON object with string keys and JSON values. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const obj: JsonObject = { | ||
| * name: 'example', | ||
| * count: 42, | ||
| * active: true, | ||
| * nested: { key: 'value' } | ||
| * } | ||
| * ``` | ||
| */ | ||
| export interface JsonObject { | ||
| [key: string]: JsonValue; | ||
| } | ||
| /** | ||
| * A JSON array containing JSON values. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const arr: JsonArray = [1, 'two', { three: 3 }, [4, 5]] | ||
| * ``` | ||
| */ | ||
| export interface JsonArray extends Array<JsonValue> { | ||
| } | ||
| /** | ||
| * Reviver function for transforming parsed JSON values. | ||
| * Called for each key-value pair during parsing. | ||
| * | ||
| * @param key - The object key or array index being parsed | ||
| * @param value - The parsed value | ||
| * @returns The transformed value (or original if no transform needed) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Convert date strings to Date objects | ||
| * const reviver: JsonReviver = (key, value) => { | ||
| * if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * ``` | ||
| */ | ||
| export type JsonReviver = (key: string, value: unknown) => unknown; | ||
| /** | ||
| * Options for JSON parsing operations. | ||
| */ | ||
| export interface JsonParseOptions { | ||
| /** | ||
| * Optional filepath for improved error messages. | ||
| * When provided, errors will be prefixed with the filepath. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Error message will be: "config.json: Unexpected token } in JSON" | ||
| * jsonParse('invalid', { filepath: 'config.json' }) | ||
| * ``` | ||
| */ | ||
| filepath?: string | undefined; | ||
| /** | ||
| * Optional reviver function to transform parsed values. | ||
| * Called for each key-value pair during parsing. | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Convert ISO date strings to Date objects | ||
| * const options = { | ||
| * reviver: (key, value) => { | ||
| * if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * } | ||
| * ``` | ||
| */ | ||
| reviver?: JsonReviver | undefined; | ||
| /** | ||
| * Whether to throw on parse errors. | ||
| * When `false`, returns `undefined` instead of throwing. | ||
| * | ||
| * @default true | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Throws error | ||
| * jsonParse('invalid', { throws: true }) | ||
| * | ||
| * // Returns undefined | ||
| * const result = jsonParse('invalid', { throws: false }) | ||
| * ``` | ||
| */ | ||
| throws?: boolean | undefined; | ||
| } | ||
| /** | ||
| * Check if a value is a JSON primitive type. | ||
| * JSON primitives are: `null`, `boolean`, `number`, or `string`. | ||
| * | ||
| * @param value - Value to check | ||
| * @returns `true` if value is a JSON primitive, `false` otherwise | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * isJsonPrimitive(null) // => true | ||
| * isJsonPrimitive(true) // => true | ||
| * isJsonPrimitive(42) // => true | ||
| * isJsonPrimitive('hello') // => true | ||
| * isJsonPrimitive({}) // => false | ||
| * isJsonPrimitive([]) // => false | ||
| * isJsonPrimitive(undefined) // => false | ||
| * ``` | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function isJsonPrimitive(value: unknown): value is JsonPrimitive; | ||
| /** | ||
| * Parse JSON content with automatic Buffer handling and BOM stripping. | ||
| * Provides safer JSON parsing with helpful error messages and optional error suppression. | ||
| * | ||
| * Features: | ||
| * - Automatic UTF-8 Buffer conversion | ||
| * - BOM (Byte Order Mark) stripping for cross-platform compatibility | ||
| * - Enhanced error messages with filepath context | ||
| * - Optional error suppression (returns `undefined` instead of throwing) | ||
| * - Optional reviver for transforming parsed values | ||
| * | ||
| * @param content - JSON string or Buffer to parse | ||
| * @param options - Optional parsing configuration | ||
| * @returns Parsed JSON value, or `undefined` if parsing fails and `throws` is `false` | ||
| * | ||
| * @throws {SyntaxError} When JSON is invalid and `throws` is `true` (default) | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * // Basic usage | ||
| * const data = jsonParse('{"name":"example"}') | ||
| * console.log(data.name) // => 'example' | ||
| * | ||
| * // Parse Buffer with UTF-8 BOM | ||
| * const buffer = Buffer.from('\uFEFF{"value":42}') | ||
| * const data = jsonParse(buffer) | ||
| * console.log(data.value) // => 42 | ||
| * | ||
| * // Enhanced error messages with filepath | ||
| * try { | ||
| * jsonParse('invalid', { filepath: 'config.json' }) | ||
| * } catch (err) { | ||
| * console.error(err.message) | ||
| * // => "config.json: Unexpected token i in JSON at position 0" | ||
| * } | ||
| * | ||
| * // Suppress errors | ||
| * const result = jsonParse('invalid', { throws: false }) | ||
| * console.log(result) // => undefined | ||
| * | ||
| * // Transform values with reviver | ||
| * const json = '{"created":"2024-01-15T10:30:00Z"}' | ||
| * const data = jsonParse(json, { | ||
| * reviver: (key, value) => { | ||
| * if (key === 'created' && typeof value === 'string') { | ||
| * return new Date(value) | ||
| * } | ||
| * return value | ||
| * } | ||
| * }) | ||
| * console.log(data.created instanceof Date) // => true | ||
| * ``` | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function jsonParse(content: string | Buffer, options?: JsonParseOptions | undefined): JsonValue | undefined; |
-75
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var json_exports = {}; | ||
| __export(json_exports, { | ||
| isJsonPrimitive: () => isJsonPrimitive, | ||
| jsonParse: () => jsonParse | ||
| }); | ||
| module.exports = __toCommonJS(json_exports); | ||
| var import_strings = require("./strings"); | ||
| const JSONParse = JSON.parse; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function isBuffer(x) { | ||
| if (!x || typeof x !== "object") { | ||
| return false; | ||
| } | ||
| const obj = x; | ||
| if (typeof obj["length"] !== "number") { | ||
| return false; | ||
| } | ||
| if (typeof obj["copy"] !== "function" || typeof obj["slice"] !== "function") { | ||
| return false; | ||
| } | ||
| if (typeof obj["length"] === "number" && obj["length"] > 0 && typeof obj[0] !== "number") { | ||
| return false; | ||
| } | ||
| const Ctor = x.constructor; | ||
| return !!(typeof Ctor?.isBuffer === "function" && Ctor.isBuffer(x)); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function isJsonPrimitive(value) { | ||
| return value === null || typeof value === "boolean" || typeof value === "number" || typeof value === "string"; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function jsonParse(content, options) { | ||
| const { filepath, reviver, throws } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const shouldThrow = throws === void 0 || !!throws; | ||
| const jsonStr = /* @__PURE__ */ isBuffer(content) ? content.toString("utf8") : content; | ||
| try { | ||
| return JSONParse((0, import_strings.stripBom)(jsonStr), reviver); | ||
| } catch (e) { | ||
| if (shouldThrow) { | ||
| const error = e; | ||
| if (error && typeof filepath === "string") { | ||
| error.message = `${filepath}: ${error.message}`; | ||
| } | ||
| throw error; | ||
| } | ||
| } | ||
| return void 0; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| isJsonPrimitive, | ||
| jsonParse | ||
| }); |
| /** | ||
| * @fileoverview NPM lifecycle script names. | ||
| * | ||
| * Standard npm lifecycle hooks that can be defined in package.json scripts. | ||
| * https://docs.npmjs.com/cli/v10/using-npm/scripts#life-cycle-scripts | ||
| */ | ||
| declare const lifecycleScriptNames: Set<string>; | ||
| export { lifecycleScriptNames }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var lifecycle_script_names_exports = {}; | ||
| __export(lifecycle_script_names_exports, { | ||
| lifecycleScriptNames: () => lifecycleScriptNames | ||
| }); | ||
| module.exports = __toCommonJS(lifecycle_script_names_exports); | ||
| const lifecycleScriptNames = new Set( | ||
| [ | ||
| "dependencies", | ||
| "prepublishOnly", | ||
| ...[ | ||
| "install", | ||
| "pack", | ||
| "prepare", | ||
| "publish", | ||
| "restart", | ||
| "start", | ||
| "stop", | ||
| "version" | ||
| ].map((n) => [`pre${n}`, n, `post${n}`]) | ||
| ].flat() | ||
| ); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| lifecycleScriptNames | ||
| }); |
| declare const maintainedNodeVersions: readonly string[] & { | ||
| current: string; | ||
| last: string; | ||
| next: string; | ||
| previous: string; | ||
| }; | ||
| export { maintainedNodeVersions }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var maintained_node_versions_exports = {}; | ||
| __export(maintained_node_versions_exports, { | ||
| maintainedNodeVersions: () => maintainedNodeVersions | ||
| }); | ||
| module.exports = __toCommonJS(maintained_node_versions_exports); | ||
| const ObjectFreeze = Object.freeze; | ||
| const next = "25.0.0"; | ||
| const current = "22.20.0"; | ||
| const previous = "20.19.5"; | ||
| const last = "18.20.8"; | ||
| const maintainedNodeVersions = ObjectFreeze( | ||
| Object.assign([last, previous, current, next], { | ||
| current, | ||
| last, | ||
| next, | ||
| previous | ||
| }) | ||
| ); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| maintainedNodeVersions | ||
| }); |
| /* c8 ignore next - External semver call */ | ||
| declare const packageDefaultNodeRange: string; | ||
| export { packageDefaultNodeRange }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var package_default_node_range_exports = {}; | ||
| __export(package_default_node_range_exports, { | ||
| packageDefaultNodeRange: () => packageDefaultNodeRange | ||
| }); | ||
| module.exports = __toCommonJS(package_default_node_range_exports); | ||
| var import_maintained_node_versions = require("./maintained-node-versions"); | ||
| var semver = __toESM(require("./external/semver.js")); | ||
| const packageDefaultNodeRange = `>=${semver.parse(import_maintained_node_versions.maintainedNodeVersions.last).major}`; | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| packageDefaultNodeRange | ||
| }); |
| /** | ||
| * @fileoverview Default Socket security categories for packages. | ||
| */ | ||
| // Default category for new packages | ||
| declare const packageDefaultSocketCategories: readonly string[]; | ||
| export { packageDefaultSocketCategories }; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var package_default_socket_categories_exports = {}; | ||
| __export(package_default_socket_categories_exports, { | ||
| packageDefaultSocketCategories: () => packageDefaultSocketCategories | ||
| }); | ||
| module.exports = __toCommonJS(package_default_socket_categories_exports); | ||
| const packageDefaultSocketCategories = Object.freeze(["cleanup"]); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| packageDefaultSocketCategories | ||
| }); |
| import type { EditablePackageJsonOptions, NormalizeOptions, PackageJson, SaveOptions } from '../packages'; | ||
| // Define the interface for the dynamic class | ||
| interface EditablePackageJsonConstructor { | ||
| new (): EditablePackageJsonInstance; | ||
| fixSteps: unknown[]; | ||
| normalizeSteps: unknown[]; | ||
| prepareSteps: unknown[]; | ||
| create(path: string, opts?: EditablePackageJsonOptions): Promise<EditablePackageJsonInstance>; | ||
| fix(path: string, opts?: unknown): Promise<EditablePackageJsonInstance>; | ||
| load(path: string, opts?: EditablePackageJsonOptions): Promise<EditablePackageJsonInstance>; | ||
| normalize(path: string, opts?: NormalizeOptions): Promise<EditablePackageJsonInstance>; | ||
| prepare(path: string, opts?: unknown): Promise<EditablePackageJsonInstance>; | ||
| } | ||
| /** | ||
| * EditablePackageJson instance interface extending NPMCliPackageJson functionality. | ||
| * Provides enhanced package.json manipulation with Socket-specific features. | ||
| * @extends NPMCliPackageJson (from @npmcli/package-json) | ||
| */ | ||
| export interface EditablePackageJsonInstance { | ||
| /** | ||
| * The parsed package.json content as a readonly object. | ||
| * @readonly | ||
| */ | ||
| content: Readonly<PackageJson>; | ||
| /** | ||
| * Create a new package.json file at the specified path. | ||
| * @param path - The directory path where package.json will be created | ||
| */ | ||
| create(path: string): this; | ||
| /** | ||
| * Apply automatic fixes to the package.json based on npm standards. | ||
| * @param opts - Optional fix configuration | ||
| */ | ||
| fix(opts?: unknown | undefined): Promise<this>; | ||
| /** | ||
| * Initialize the instance from a content object. | ||
| * @param content - The package.json content object | ||
| */ | ||
| fromContent(content: unknown): this; | ||
| /** | ||
| * Initialize the instance from a JSON string. | ||
| * @param json - The package.json content as a JSON string | ||
| */ | ||
| fromJSON(json: string): this; | ||
| /** | ||
| * Load a package.json file from the specified path. | ||
| * @param path - The directory containing the package.json | ||
| * @param create - Whether to create the file if it doesn't exist | ||
| */ | ||
| load(path: string, create?: boolean): Promise<this>; | ||
| /** | ||
| * Normalize the package.json content according to npm standards. | ||
| * @param opts - Normalization options | ||
| */ | ||
| normalize(opts?: NormalizeOptions): Promise<this>; | ||
| /** | ||
| * Prepare the package.json for publishing. | ||
| * @param opts - Preparation options | ||
| */ | ||
| prepare(opts?: unknown): Promise<this>; | ||
| /** | ||
| * Update the package.json content with new values. | ||
| * @param content - Partial package.json object with fields to update | ||
| * @override from NPMCliPackageJson | ||
| */ | ||
| update(content: Partial<PackageJson>): this; | ||
| /** | ||
| * Save the package.json file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| * @override from NPMCliPackageJson | ||
| */ | ||
| save(options?: SaveOptions | undefined): Promise<boolean>; | ||
| /** | ||
| * Synchronously save the package.json file to disk. | ||
| * @param options - Save options for formatting and sorting | ||
| */ | ||
| saveSync(options?: SaveOptions | undefined): boolean; | ||
| /** | ||
| * Check if the package.json will be saved based on current changes. | ||
| * @param options - Save options to evaluate | ||
| */ | ||
| willSave(options?: SaveOptions | undefined): boolean; | ||
| } | ||
| /** | ||
| * Get the EditablePackageJson class for package.json manipulation. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function getEditablePackageJsonClass(): EditablePackageJsonConstructor; | ||
| /** | ||
| * Convert a package.json object to an editable instance. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function pkgJsonToEditable(pkgJson: PackageJson, options?: EditablePackageJsonOptions): unknown; | ||
| /** | ||
| * Convert package.json to editable instance with file persistence. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function toEditablePackageJson(pkgJson: PackageJson, options?: EditablePackageJsonOptions): Promise<unknown>; | ||
| /** | ||
| * Convert package.json to editable instance with file persistence synchronously. | ||
| */ | ||
| /*@__NO_SIDE_EFFECTS__*/ | ||
| export declare function toEditablePackageJsonSync(pkgJson: PackageJson, options?: EditablePackageJsonOptions): unknown; | ||
| export {}; |
| "use strict"; | ||
| /* Socket Lib - Built with esbuild */ | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var editable_exports = {}; | ||
| __export(editable_exports, { | ||
| getEditablePackageJsonClass: () => getEditablePackageJsonClass, | ||
| pkgJsonToEditable: () => pkgJsonToEditable, | ||
| toEditablePackageJson: () => toEditablePackageJson, | ||
| toEditablePackageJsonSync: () => toEditablePackageJsonSync | ||
| }); | ||
| module.exports = __toCommonJS(editable_exports); | ||
| var import_package_json = __toESM(require("../external/@npmcli/package-json")); | ||
| var import_read_package = require("../external/@npmcli/package-json/lib/read-package"); | ||
| var import_sort = require("../external/@npmcli/package-json/lib/sort"); | ||
| var import_normalize = require("../paths/normalize"); | ||
| var import_normalize2 = require("./normalize"); | ||
| var import_packages = require("../paths/packages"); | ||
| const identSymbol = Symbol.for("indent"); | ||
| const newlineSymbol = Symbol.for("newline"); | ||
| let _EditablePackageJsonClass; | ||
| let _fs; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getFs() { | ||
| if (_fs === void 0) { | ||
| _fs = require("node:fs"); | ||
| } | ||
| return _fs; | ||
| } | ||
| let _path; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getPath() { | ||
| if (_path === void 0) { | ||
| _path = require("node:path"); | ||
| } | ||
| return _path; | ||
| } | ||
| let _util; | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getUtil() { | ||
| if (_util === void 0) { | ||
| _util = require("node:util"); | ||
| } | ||
| return _util; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function getEditablePackageJsonClass() { | ||
| if (_EditablePackageJsonClass === void 0) { | ||
| _EditablePackageJsonClass = class EditablePackageJson extends import_package_json.default { | ||
| static fixSteps = import_package_json.default.fixSteps; | ||
| static normalizeSteps = import_package_json.default.normalizeSteps; | ||
| static prepareSteps = import_package_json.default.prepareSteps; | ||
| _canSave = true; | ||
| _path = void 0; | ||
| _readFileContent = ""; | ||
| _readFileJson = void 0; | ||
| get content() { | ||
| return super.content; | ||
| } | ||
| get filename() { | ||
| const path = this._path; | ||
| if (!path) { | ||
| return ""; | ||
| } | ||
| if (path.endsWith("package.json")) { | ||
| return path; | ||
| } | ||
| const nodePath = /* @__PURE__ */ getPath(); | ||
| return nodePath.join(path, "package.json"); | ||
| } | ||
| static async create(path, opts = {}) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.create(path); | ||
| return opts.data ? p.update(opts.data) : p; | ||
| } | ||
| static async fix(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path, true); | ||
| return await p.fix(opts); | ||
| } | ||
| static async load(path, opts = {}) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| if (!opts.create) { | ||
| return await p.load(path); | ||
| } | ||
| try { | ||
| return await p.load(path); | ||
| } catch (err) { | ||
| if (!err.message.startsWith("Could not read package.json")) { | ||
| throw err; | ||
| } | ||
| return p.create(path); | ||
| } | ||
| } | ||
| static async normalize(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path); | ||
| return await p.normalize(opts); | ||
| } | ||
| static async prepare(path, opts) { | ||
| const p = new _EditablePackageJsonClass(); | ||
| await p.load(path, true); | ||
| return await p.prepare(opts); | ||
| } | ||
| create(path) { | ||
| super.create(path); | ||
| this._path = path; | ||
| return this; | ||
| } | ||
| async fix(opts = {}) { | ||
| await super.fix(opts); | ||
| return this; | ||
| } | ||
| fromContent(data) { | ||
| super.fromContent(data); | ||
| this._canSave = false; | ||
| return this; | ||
| } | ||
| fromJSON(data) { | ||
| super.fromJSON(data); | ||
| return this; | ||
| } | ||
| async load(path, create) { | ||
| this._path = path; | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| let parseErr; | ||
| try { | ||
| this._readFileContent = await (0, import_read_package.read)(this.filename); | ||
| } catch (err) { | ||
| if (!create) { | ||
| throw err; | ||
| } | ||
| parseErr = err; | ||
| } | ||
| if (parseErr) { | ||
| const nodePath = /* @__PURE__ */ getPath(); | ||
| const indexFile = nodePath.resolve(this.path || "", "index.js"); | ||
| let indexFileContent; | ||
| try { | ||
| indexFileContent = await fsPromises.readFile(indexFile, "utf8"); | ||
| } catch { | ||
| throw parseErr; | ||
| } | ||
| try { | ||
| this.fromContent(indexFileContent); | ||
| } catch { | ||
| throw parseErr; | ||
| } | ||
| this._canSave = false; | ||
| return this; | ||
| } | ||
| this.fromJSON(this._readFileContent); | ||
| this._readFileJson = (0, import_read_package.parse)(this._readFileContent); | ||
| return this; | ||
| } | ||
| async normalize(opts = {}) { | ||
| await super.normalize(opts); | ||
| return this; | ||
| } | ||
| get path() { | ||
| return this._path; | ||
| } | ||
| async prepare(opts = {}) { | ||
| await super.prepare(opts); | ||
| return this; | ||
| } | ||
| async save(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No package.json to save to"); | ||
| } | ||
| const { ignoreWhitespace = false, sort = false } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { | ||
| [identSymbol]: indent, | ||
| [newlineSymbol]: newline, | ||
| ...rest | ||
| } = this.content; | ||
| const content = sort ? (0, import_sort.packageSort)(rest) : rest; | ||
| const { | ||
| [identSymbol]: _indent, | ||
| [newlineSymbol]: _newline, | ||
| ...origContent | ||
| } = this._readFileJson || {}; | ||
| if (ignoreWhitespace && (/* @__PURE__ */ getUtil()).isDeepStrictEqual(content, origContent)) { | ||
| return false; | ||
| } | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| const fileContent = `${JSON.stringify( | ||
| content, | ||
| void 0, | ||
| format | ||
| )} | ||
| `.replace(/\n/g, eol); | ||
| if (!ignoreWhitespace && fileContent.trim() === this._readFileContent.trim()) { | ||
| return false; | ||
| } | ||
| const { promises: fsPromises } = /* @__PURE__ */ getFs(); | ||
| await fsPromises.writeFile(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = (0, import_read_package.parse)(fileContent); | ||
| return true; | ||
| } | ||
| saveSync(options) { | ||
| if (!this._canSave || this.content === void 0) { | ||
| throw new Error("No package.json to save to"); | ||
| } | ||
| const { ignoreWhitespace = false, sort = false } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { | ||
| [Symbol.for("indent")]: indent, | ||
| [Symbol.for("newline")]: newline, | ||
| ...rest | ||
| } = this.content; | ||
| const content = sort ? (0, import_sort.packageSort)(rest) : rest; | ||
| if (ignoreWhitespace && (/* @__PURE__ */ getUtil()).isDeepStrictEqual(content, this._readFileJson)) { | ||
| return false; | ||
| } | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| const fileContent = `${JSON.stringify( | ||
| content, | ||
| void 0, | ||
| format | ||
| )} | ||
| `.replace(/\n/g, eol); | ||
| if (!ignoreWhitespace && fileContent.trim() === this._readFileContent.trim()) { | ||
| return false; | ||
| } | ||
| const fs = /* @__PURE__ */ getFs(); | ||
| fs.writeFileSync(this.filename, fileContent); | ||
| this._readFileContent = fileContent; | ||
| this._readFileJson = (0, import_read_package.parse)(fileContent); | ||
| return true; | ||
| } | ||
| update(content) { | ||
| super.update(content); | ||
| return this; | ||
| } | ||
| willSave(options) { | ||
| const { ignoreWhitespace = false, sort = false } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| if (!this._canSave || this.content === void 0) { | ||
| return false; | ||
| } | ||
| const { | ||
| [Symbol.for("indent")]: indent, | ||
| [Symbol.for("newline")]: newline, | ||
| ...rest | ||
| } = this.content; | ||
| const content = sort ? (0, import_sort.packageSort)(rest) : rest; | ||
| if (ignoreWhitespace && (/* @__PURE__ */ getUtil()).isDeepStrictEqual(content, this._readFileJson)) { | ||
| return false; | ||
| } | ||
| const format = indent === void 0 || indent === null ? " " : indent; | ||
| const eol = newline === void 0 || newline === null ? "\n" : newline; | ||
| const fileContent = `${JSON.stringify( | ||
| content, | ||
| void 0, | ||
| format | ||
| )} | ||
| `.replace(/\n/g, eol); | ||
| if (!ignoreWhitespace && fileContent.trim() === this._readFileContent.trim()) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }; | ||
| } | ||
| return _EditablePackageJsonClass; | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function pkgJsonToEditable(pkgJson, options) { | ||
| const { normalize, ...normalizeOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| return new EditablePackageJson().fromContent( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, normalizeOptions) : pkgJson | ||
| ); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| async function toEditablePackageJson(pkgJson, options) { | ||
| const { path: filepath, ...pkgJsonToEditableOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { normalize, ...normalizeOptions } = pkgJsonToEditableOptions; | ||
| if (typeof filepath !== "string") { | ||
| return /* @__PURE__ */ pkgJsonToEditable(pkgJson, pkgJsonToEditableOptions); | ||
| } | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| const pkgJsonPath = (0, import_packages.resolvePackageJsonDirname)(filepath); | ||
| return (await EditablePackageJson.load(pkgJsonPath, { create: true })).fromJSON( | ||
| `${JSON.stringify( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, { | ||
| ...(0, import_normalize.isNodeModules)(pkgJsonPath) ? {} : { preserve: ["repository"] }, | ||
| ...normalizeOptions | ||
| }) : pkgJson, | ||
| null, | ||
| 2 | ||
| )} | ||
| ` | ||
| ); | ||
| } | ||
| // @__NO_SIDE_EFFECTS__ | ||
| function toEditablePackageJsonSync(pkgJson, options) { | ||
| const { path: filepath, ...pkgJsonToEditableOptions } = { | ||
| __proto__: null, | ||
| ...options | ||
| }; | ||
| const { normalize, ...normalizeOptions } = pkgJsonToEditableOptions; | ||
| if (typeof filepath !== "string") { | ||
| return /* @__PURE__ */ pkgJsonToEditable(pkgJson, pkgJsonToEditableOptions); | ||
| } | ||
| const EditablePackageJson = /* @__PURE__ */ getEditablePackageJsonClass(); | ||
| const pkgJsonPath = (0, import_packages.resolvePackageJsonDirname)(filepath); | ||
| return new EditablePackageJson().create(pkgJsonPath).fromJSON( | ||
| `${JSON.stringify( | ||
| normalize ? (0, import_normalize2.normalizePackageJson)(pkgJson, { | ||
| ...(0, import_normalize.isNodeModules)(pkgJsonPath) ? {} : { preserve: ["repository"] }, | ||
| ...normalizeOptions | ||
| }) : pkgJson, | ||
| null, | ||
| 2 | ||
| )} | ||
| ` | ||
| ); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| getEditablePackageJsonClass, | ||
| pkgJsonToEditable, | ||
| toEditablePackageJson, | ||
| toEditablePackageJsonSync | ||
| }); |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 20 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 20 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
6674286
0.43%324
3.85%180865
0.39%308
0.33%