@socketsecurity/lib
Version:
Core utilities and infrastructure for Socket.dev security tools
297 lines (296 loc) • 9.48 kB
JavaScript
;
/* 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_paths = require("./paths");
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_paths.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
});