@socketsecurity/lib 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/abort.js +60 -1
- package/dist/abort.js.map +2 -2
- package/dist/agent.js +289 -1
- package/dist/agent.js.map +2 -2
- package/dist/ansi.js +60 -1
- package/dist/ansi.js.map +2 -2
- package/dist/argv/flags.js +282 -1
- package/dist/argv/flags.js.map +2 -2
- package/dist/argv/parse.js +171 -1
- package/dist/argv/parse.js.map +2 -2
- package/dist/arrays.js +85 -1
- package/dist/arrays.js.map +2 -2
- package/dist/bin.js +419 -5
- package/dist/bin.js.map +2 -2
- package/dist/cacache.js +139 -1
- package/dist/cacache.js.map +2 -2
- package/dist/cache-with-ttl.js +223 -1
- package/dist/cache-with-ttl.js.map +2 -2
- package/dist/constants/agents.js +126 -1
- package/dist/constants/agents.js.map +2 -2
- package/dist/constants/core.js +57 -2
- package/dist/constants/core.js.map +2 -2
- package/dist/constants/encoding.js +48 -1
- package/dist/constants/encoding.js.map +2 -2
- package/dist/constants/github.js +30 -1
- package/dist/constants/github.js.map +2 -2
- package/dist/constants/licenses.js +66 -1
- package/dist/constants/licenses.js.map +2 -2
- package/dist/constants/node.js +185 -1
- package/dist/constants/node.js.map +2 -2
- package/dist/constants/packages.js +128 -1
- package/dist/constants/packages.js.map +2 -2
- package/dist/constants/paths.js +150 -1
- package/dist/constants/paths.js.map +2 -2
- package/dist/constants/platform.js +41 -1
- package/dist/constants/platform.js.map +2 -2
- package/dist/constants/process.js +52 -1
- package/dist/constants/process.js.map +2 -2
- package/dist/constants/socket.js +102 -1
- package/dist/constants/socket.js.map +2 -2
- package/dist/constants/testing.js +36 -1
- package/dist/constants/testing.js.map +2 -2
- package/dist/constants/time.js +39 -1
- package/dist/constants/time.js.map +2 -2
- package/dist/constants/typescript.js +54 -1
- package/dist/constants/typescript.js.map +2 -2
- package/dist/cover/code.js +135 -1
- package/dist/cover/code.js.map +2 -2
- package/dist/cover/formatters.js +101 -11
- package/dist/cover/formatters.js.map +2 -2
- package/dist/cover/type.js +63 -1
- package/dist/cover/type.js.map +2 -2
- package/dist/cover/types.js +15 -1
- package/dist/cover/types.js.map +2 -2
- package/dist/debug.js +337 -2
- package/dist/debug.js.map +2 -2
- package/dist/dlx-binary.js +408 -7
- package/dist/dlx-binary.js.map +2 -2
- package/dist/dlx-package.js +278 -7
- package/dist/dlx-package.js.map +2 -2
- package/dist/dlx.js +214 -7
- package/dist/dlx.js.map +2 -2
- package/dist/effects/pulse-frames.js +64 -1
- package/dist/effects/pulse-frames.js.map +2 -2
- package/dist/effects/text-shimmer.js +174 -1
- package/dist/effects/text-shimmer.js.map +2 -2
- package/dist/effects/types.js +15 -1
- package/dist/effects/types.js.map +2 -2
- package/dist/effects/ultra.js +61 -1
- package/dist/effects/ultra.js.map +2 -2
- package/dist/env/ci.js +31 -1
- package/dist/env/ci.js.map +2 -2
- package/dist/env/debug.js +30 -1
- package/dist/env/debug.js.map +2 -2
- package/dist/env/github.js +65 -1
- package/dist/env/github.js.map +2 -2
- package/dist/env/helpers.js +47 -1
- package/dist/env/helpers.js.map +2 -2
- package/dist/env/home.js +30 -1
- package/dist/env/home.js.map +2 -2
- package/dist/env/locale.js +40 -1
- package/dist/env/locale.js.map +2 -2
- package/dist/env/node-auth-token.js +30 -1
- package/dist/env/node-auth-token.js.map +2 -2
- package/dist/env/node-env.js +30 -1
- package/dist/env/node-env.js.map +2 -2
- package/dist/env/npm.js +50 -1
- package/dist/env/npm.js.map +2 -2
- package/dist/env/package-manager.js +73 -1
- package/dist/env/package-manager.js.map +2 -2
- package/dist/env/path.js +30 -1
- package/dist/env/path.js.map +2 -2
- package/dist/env/pre-commit.js +31 -1
- package/dist/env/pre-commit.js.map +2 -2
- package/dist/env/rewire.js +72 -1
- package/dist/env/rewire.js.map +2 -2
- package/dist/env/shell.js +30 -1
- package/dist/env/shell.js.map +2 -2
- package/dist/env/socket-cli-shadow.js +51 -1
- package/dist/env/socket-cli-shadow.js.map +2 -2
- package/dist/env/socket-cli.js +86 -1
- package/dist/env/socket-cli.js.map +2 -2
- package/dist/env/socket.js +101 -1
- package/dist/env/socket.js.map +2 -2
- package/dist/env/temp-dir.js +40 -1
- package/dist/env/temp-dir.js.map +2 -2
- package/dist/env/term.js +30 -1
- package/dist/env/term.js.map +2 -2
- package/dist/env/test.js +43 -1
- package/dist/env/test.js.map +2 -2
- package/dist/env/windows.js +45 -1
- package/dist/env/windows.js.map +2 -2
- package/dist/env/xdg.js +40 -1
- package/dist/env/xdg.js.map +2 -2
- package/dist/env.js +170 -1
- package/dist/env.js.map +2 -2
- package/dist/fs.js +670 -7
- package/dist/fs.js.map +2 -2
- package/dist/functions.js +68 -1
- package/dist/functions.js.map +2 -2
- package/dist/git.js +329 -2
- package/dist/git.js.map +2 -2
- package/dist/github.js +202 -1
- package/dist/github.js.map +2 -2
- package/dist/globs.js +149 -1
- package/dist/globs.js.map +2 -2
- package/dist/http-request.js +335 -3
- package/dist/http-request.js.map +2 -2
- package/dist/index.js +69 -1
- package/dist/index.js.map +2 -2
- package/dist/ipc.js +244 -1
- package/dist/ipc.js.map +2 -2
- package/dist/json.js +73 -1
- package/dist/json.js.map +2 -2
- package/dist/links/index.js +60 -1
- package/dist/links/index.js.map +2 -2
- package/dist/logger.js +1383 -6
- package/dist/logger.js.map +2 -2
- package/dist/maintained-node-versions.js +35 -1
- package/dist/maintained-node-versions.js.map +2 -2
- package/dist/memoization.js +210 -1
- package/dist/memoization.js.map +2 -2
- package/dist/objects.js +311 -1
- package/dist/objects.js.map +2 -2
- package/dist/packages/editable.js +356 -9
- package/dist/packages/editable.js.map +2 -2
- package/dist/packages/exports.js +162 -1
- package/dist/packages/exports.js.map +2 -2
- package/dist/packages/isolation.js +187 -1
- package/dist/packages/isolation.js.map +2 -2
- package/dist/packages/licenses.js +214 -1
- package/dist/packages/licenses.js.map +2 -2
- package/dist/packages/manifest.js +190 -1
- package/dist/packages/manifest.js.map +2 -2
- package/dist/packages/normalize.js +132 -1
- package/dist/packages/normalize.js.map +2 -2
- package/dist/packages/operations.js +320 -1
- package/dist/packages/operations.js.map +2 -2
- package/dist/packages/paths.js +53 -1
- package/dist/packages/paths.js.map +2 -2
- package/dist/packages/provenance.js +178 -1
- package/dist/packages/provenance.js.map +2 -2
- package/dist/packages/specs.js +83 -1
- package/dist/packages/specs.js.map +2 -2
- package/dist/packages/validation.js +51 -1
- package/dist/packages/validation.js.map +2 -2
- package/dist/packages.js +129 -1
- package/dist/packages.js.map +2 -2
- package/dist/path.js +446 -1
- package/dist/path.js.map +2 -2
- package/dist/paths/rewire.js +79 -1
- package/dist/paths/rewire.js.map +2 -2
- package/dist/paths.js +190 -1
- package/dist/paths.js.map +2 -2
- package/dist/performance.js +216 -15
- package/dist/performance.js.map +2 -2
- package/dist/process-lock.js +287 -8
- package/dist/process-lock.js.map +2 -2
- package/dist/promise-queue.js +109 -1
- package/dist/promise-queue.js.map +2 -2
- package/dist/promises.js +267 -1
- package/dist/promises.js.map +2 -2
- package/dist/prompts/index.js +45 -1
- package/dist/prompts/index.js.map +2 -2
- package/dist/prompts.js +58 -1
- package/dist/prompts.js.map +2 -2
- package/dist/regexps.js +30 -1
- package/dist/regexps.js.map +2 -2
- package/dist/sea.js +44 -1
- package/dist/sea.js.map +2 -2
- package/dist/shadow.js +58 -1
- package/dist/shadow.js.map +2 -2
- package/dist/signal-exit.js +248 -1
- package/dist/signal-exit.js.map +2 -2
- package/dist/sorts.js +94 -1
- package/dist/sorts.js.map +2 -2
- package/dist/spawn.js +200 -1
- package/dist/spawn.js.map +2 -2
- package/dist/spinner.js +961 -1
- package/dist/spinner.js.map +2 -2
- package/dist/ssri.js +71 -1
- package/dist/ssri.js.map +2 -2
- package/dist/stdio/clear.js +82 -1
- package/dist/stdio/clear.js.map +2 -2
- package/dist/stdio/divider.js +89 -3
- package/dist/stdio/divider.js.map +2 -2
- package/dist/stdio/footer.js +94 -2
- package/dist/stdio/footer.js.map +2 -2
- package/dist/stdio/header.js +100 -2
- package/dist/stdio/header.js.map +2 -2
- package/dist/stdio/mask.js +207 -5
- package/dist/stdio/mask.js.map +2 -2
- package/dist/stdio/progress.js +209 -2
- package/dist/stdio/progress.js.map +2 -2
- package/dist/stdio/prompts.js +88 -1
- package/dist/stdio/prompts.js.map +2 -2
- package/dist/stdio/stderr.js +89 -2
- package/dist/stdio/stderr.js.map +2 -2
- package/dist/stdio/stdout.js +103 -2
- package/dist/stdio/stdout.js.map +2 -2
- package/dist/streams.js +78 -1
- package/dist/streams.js.map +2 -2
- package/dist/strings.js +251 -3
- package/dist/strings.js.map +2 -2
- package/dist/suppress-warnings.js +98 -1
- package/dist/suppress-warnings.js.map +2 -2
- package/dist/tables.js +128 -3
- package/dist/tables.js.map +2 -2
- package/dist/temporary-executor.js +53 -1
- package/dist/temporary-executor.js.map +2 -2
- package/dist/themes/context.js +71 -1
- package/dist/themes/context.js.map +2 -2
- package/dist/themes/index.js +57 -1
- package/dist/themes/index.js.map +2 -2
- package/dist/themes/themes.js +195 -1
- package/dist/themes/themes.js.map +2 -2
- package/dist/themes/types.js +15 -1
- package/dist/themes/types.js.map +2 -2
- package/dist/themes/utils.js +116 -1
- package/dist/themes/utils.js.map +2 -2
- package/dist/types.js +59 -1
- package/dist/types.js.map +2 -2
- package/dist/url.js +142 -1
- package/dist/url.js.map +2 -2
- package/dist/utils/get-ipc.js +58 -1
- package/dist/utils/get-ipc.js.map +2 -2
- package/dist/validation/json-parser.js +127 -1
- package/dist/validation/json-parser.js.map +2 -2
- package/dist/validation/types.js +15 -1
- package/dist/validation/types.js.map +2 -2
- package/dist/versions.js +154 -1
- package/dist/versions.js.map +2 -2
- package/dist/words.js +50 -1
- package/dist/words.js.map +2 -2
- package/dist/zod.js +27 -1
- package/dist/zod.js.map +2 -2
- package/package.json +1 -1
package/dist/performance.js
CHANGED
|
@@ -1,18 +1,219 @@
|
|
|
1
1
|
/* Socket Lib - Built with esbuild */
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var performance_exports = {};
|
|
20
|
+
__export(performance_exports, {
|
|
21
|
+
clearPerformanceMetrics: () => clearPerformanceMetrics,
|
|
22
|
+
generatePerformanceReport: () => generatePerformanceReport,
|
|
23
|
+
getPerformanceMetrics: () => getPerformanceMetrics,
|
|
24
|
+
getPerformanceSummary: () => getPerformanceSummary,
|
|
25
|
+
measure: () => measure,
|
|
26
|
+
measureSync: () => measureSync,
|
|
27
|
+
perfCheckpoint: () => perfCheckpoint,
|
|
28
|
+
perfTimer: () => perfTimer,
|
|
29
|
+
printPerformanceSummary: () => printPerformanceSummary,
|
|
30
|
+
trackMemory: () => trackMemory
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(performance_exports);
|
|
33
|
+
var import_debug = require("./debug");
|
|
34
|
+
const performanceMetrics = [];
|
|
35
|
+
function isPerfEnabled() {
|
|
36
|
+
return process.env["DEBUG"]?.includes("perf") || false;
|
|
37
|
+
}
|
|
38
|
+
function perfTimer(operation, metadata) {
|
|
39
|
+
if (!isPerfEnabled()) {
|
|
40
|
+
return () => {
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const start = performance.now();
|
|
44
|
+
(0, import_debug.debugLog)(`[perf] [START] ${operation}`);
|
|
45
|
+
return (additionalMetadata) => {
|
|
46
|
+
const duration = performance.now() - start;
|
|
47
|
+
const metric = {
|
|
48
|
+
operation,
|
|
49
|
+
// Round to 2 decimals
|
|
50
|
+
duration: Math.round(duration * 100) / 100,
|
|
51
|
+
timestamp: Date.now(),
|
|
52
|
+
metadata: { ...metadata, ...additionalMetadata }
|
|
53
|
+
};
|
|
54
|
+
performanceMetrics.push(metric);
|
|
55
|
+
(0, import_debug.debugLog)(`[perf] [END] ${operation} - ${metric.duration}ms`);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function measure(operation, fn, metadata) {
|
|
59
|
+
const stop = perfTimer(operation, metadata);
|
|
60
|
+
try {
|
|
61
|
+
const result = await fn();
|
|
62
|
+
stop({ success: true });
|
|
63
|
+
const metric = performanceMetrics[performanceMetrics.length - 1];
|
|
64
|
+
return { result, duration: metric?.duration || 0 };
|
|
65
|
+
} catch (e) {
|
|
66
|
+
stop({
|
|
67
|
+
success: false,
|
|
68
|
+
error: e instanceof Error ? e.message : "Unknown"
|
|
69
|
+
});
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function measureSync(operation, fn, metadata) {
|
|
74
|
+
const stop = perfTimer(operation, metadata);
|
|
75
|
+
try {
|
|
76
|
+
const result = fn();
|
|
77
|
+
stop({ success: true });
|
|
78
|
+
const metric = performanceMetrics[performanceMetrics.length - 1];
|
|
79
|
+
return { result, duration: metric?.duration || 0 };
|
|
80
|
+
} catch (e) {
|
|
81
|
+
stop({
|
|
82
|
+
success: false,
|
|
83
|
+
error: e instanceof Error ? e.message : "Unknown"
|
|
84
|
+
});
|
|
85
|
+
throw e;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function getPerformanceMetrics() {
|
|
89
|
+
return [...performanceMetrics];
|
|
90
|
+
}
|
|
91
|
+
function clearPerformanceMetrics() {
|
|
92
|
+
performanceMetrics.length = 0;
|
|
93
|
+
(0, import_debug.debugLog)("[perf] Cleared performance metrics");
|
|
94
|
+
}
|
|
95
|
+
function getPerformanceSummary() {
|
|
96
|
+
const summary = /* @__PURE__ */ Object.create(null);
|
|
97
|
+
for (const metric of performanceMetrics) {
|
|
98
|
+
const { duration, operation } = metric;
|
|
99
|
+
if (!summary[operation]) {
|
|
100
|
+
summary[operation] = {
|
|
101
|
+
count: 0,
|
|
102
|
+
total: 0,
|
|
103
|
+
min: Number.POSITIVE_INFINITY,
|
|
104
|
+
max: Number.NEGATIVE_INFINITY
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const stats = summary[operation];
|
|
108
|
+
stats.count++;
|
|
109
|
+
stats.total += duration;
|
|
110
|
+
stats.min = Math.min(stats.min, duration);
|
|
111
|
+
stats.max = Math.max(stats.max, duration);
|
|
112
|
+
}
|
|
113
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
114
|
+
for (const { 0: operation, 1: stats } of Object.entries(summary)) {
|
|
115
|
+
result[operation] = {
|
|
116
|
+
count: stats.count,
|
|
117
|
+
total: Math.round(stats.total * 100) / 100,
|
|
118
|
+
avg: Math.round(stats.total / stats.count * 100) / 100,
|
|
119
|
+
min: Math.round(stats.min * 100) / 100,
|
|
120
|
+
max: Math.round(stats.max * 100) / 100
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
function printPerformanceSummary() {
|
|
126
|
+
if (!isPerfEnabled() || performanceMetrics.length === 0) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const summary = getPerformanceSummary();
|
|
130
|
+
const operations = Object.keys(summary).sort();
|
|
131
|
+
(0, import_debug.debugLog)("[perf]\n=== Performance Summary ===");
|
|
132
|
+
for (const operation of operations) {
|
|
133
|
+
const stats = summary[operation];
|
|
134
|
+
(0, import_debug.debugLog)(
|
|
135
|
+
`[perf] ${operation}: ${stats.count} calls, avg ${stats.avg}ms (min ${stats.min}ms, max ${stats.max}ms, total ${stats.total}ms)`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
(0, import_debug.debugLog)("[perf] =========================\n");
|
|
139
|
+
}
|
|
140
|
+
function perfCheckpoint(checkpoint, metadata) {
|
|
141
|
+
if (!isPerfEnabled()) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const metric = {
|
|
145
|
+
operation: `checkpoint:${checkpoint}`,
|
|
146
|
+
duration: 0,
|
|
147
|
+
timestamp: Date.now(),
|
|
148
|
+
...metadata ? { metadata } : {}
|
|
149
|
+
};
|
|
150
|
+
performanceMetrics.push(metric);
|
|
151
|
+
(0, import_debug.debugLog)(`[perf] [CHECKPOINT] ${checkpoint}`);
|
|
152
|
+
}
|
|
153
|
+
function trackMemory(label) {
|
|
154
|
+
if (!isPerfEnabled()) {
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
const usage = process.memoryUsage();
|
|
158
|
+
const heapUsedMB = Math.round(usage.heapUsed / 1024 / 1024 * 100) / 100;
|
|
159
|
+
(0, import_debug.debugLog)(`[perf] [MEMORY] ${label}: ${heapUsedMB}MB heap used`);
|
|
160
|
+
const metric = {
|
|
161
|
+
operation: `checkpoint:memory:${label}`,
|
|
162
|
+
duration: 0,
|
|
163
|
+
timestamp: Date.now(),
|
|
164
|
+
metadata: {
|
|
165
|
+
heapUsed: heapUsedMB,
|
|
166
|
+
heapTotal: Math.round(usage.heapTotal / 1024 / 1024 * 100) / 100,
|
|
167
|
+
external: Math.round(usage.external / 1024 / 1024 * 100) / 100
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
performanceMetrics.push(metric);
|
|
171
|
+
return heapUsedMB;
|
|
172
|
+
}
|
|
173
|
+
function generatePerformanceReport() {
|
|
174
|
+
if (!isPerfEnabled() || performanceMetrics.length === 0) {
|
|
175
|
+
return "(no performance data collected - enable with DEBUG=perf)";
|
|
176
|
+
}
|
|
177
|
+
const summary = getPerformanceSummary();
|
|
178
|
+
const operations = Object.keys(summary).sort();
|
|
179
|
+
let report = "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n";
|
|
180
|
+
report += "\u2551 Performance Report \u2551\n";
|
|
181
|
+
report += "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n\n";
|
|
182
|
+
for (const operation of operations) {
|
|
183
|
+
const stats = summary[operation];
|
|
184
|
+
report += `${operation}:
|
|
185
|
+
`;
|
|
186
|
+
report += ` Calls: ${stats.count}
|
|
187
|
+
`;
|
|
188
|
+
report += ` Avg: ${stats.avg}ms
|
|
189
|
+
`;
|
|
190
|
+
report += ` Min: ${stats.min}ms
|
|
191
|
+
`;
|
|
192
|
+
report += ` Max: ${stats.max}ms
|
|
193
|
+
`;
|
|
194
|
+
report += ` Total: ${stats.total}ms
|
|
8
195
|
|
|
9
|
-
`;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
const totalDuration = Object.values(summary).reduce(
|
|
199
|
+
(sum, s) => sum + s.total,
|
|
200
|
+
0
|
|
201
|
+
);
|
|
202
|
+
report += `Total measured time: ${Math.round(totalDuration * 100) / 100}ms
|
|
203
|
+
`;
|
|
204
|
+
return report;
|
|
205
|
+
}
|
|
206
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
207
|
+
0 && (module.exports = {
|
|
208
|
+
clearPerformanceMetrics,
|
|
209
|
+
generatePerformanceReport,
|
|
210
|
+
getPerformanceMetrics,
|
|
211
|
+
getPerformanceSummary,
|
|
212
|
+
measure,
|
|
213
|
+
measureSync,
|
|
214
|
+
perfCheckpoint,
|
|
215
|
+
perfTimer,
|
|
216
|
+
printPerformanceSummary,
|
|
217
|
+
trackMemory
|
|
218
|
+
});
|
|
18
219
|
//# sourceMappingURL=performance.js.map
|
package/dist/performance.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/performance.ts"],
|
|
4
4
|
"sourcesContent": ["/**\n * @fileoverview Performance monitoring utilities for profiling and optimization.\n * Provides timing, profiling, and performance metric collection for identifying bottlenecks.\n */\n\nimport { debugLog } from './debug'\n\n/**\n * Performance metrics collected during execution.\n */\ntype PerformanceMetrics = {\n operation: string\n duration: number\n timestamp: number\n metadata?: Record<string, unknown>\n}\n\n/**\n * Global metrics collection (only in debug mode).\n */\nconst performanceMetrics: PerformanceMetrics[] = []\n\n/**\n * Check if performance tracking is enabled.\n */\nfunction isPerfEnabled(): boolean {\n return process.env['DEBUG']?.includes('perf') || false\n}\n\n/**\n * Start a performance timer for an operation.\n * Returns a stop function that records the duration.\n *\n * @param operation - Name of the operation being timed\n * @param metadata - Optional metadata to attach to the metric\n * @returns Stop function that completes the timing\n *\n * @example\n * import { perfTimer } from '@socketsecurity/lib/performance'\n *\n * const stop = perfTimer('api-call')\n * await fetchData()\n * stop({ endpoint: '/npm/lodash/score' })\n */\nexport function perfTimer(\n operation: string,\n metadata?: Record<string, unknown>,\n): (additionalMetadata?: Record<string, unknown>) => void {\n if (!isPerfEnabled()) {\n // No-op if perf tracking disabled\n return () => {}\n }\n\n const start = performance.now()\n debugLog(`[perf] [START] ${operation}`)\n\n return (additionalMetadata?: Record<string, unknown>) => {\n const duration = performance.now() - start\n const metric: PerformanceMetrics = {\n operation,\n // Round to 2 decimals\n duration: Math.round(duration * 100) / 100,\n timestamp: Date.now(),\n metadata: { ...metadata, ...additionalMetadata },\n }\n\n performanceMetrics.push(metric)\n debugLog(`[perf] [END] ${operation} - ${metric.duration}ms`)\n }\n}\n\n/**\n * Measure execution time of an async function.\n *\n * @param operation - Name of the operation\n * @param fn - Async function to measure\n * @param metadata - Optional metadata\n * @returns Result of the function and duration\n *\n * @example\n * import { measure } from '@socketsecurity/lib/performance'\n *\n * const { result, duration } = await measure('fetch-packages', async () => {\n * return await fetchPackages()\n * })\n * console.log(`Fetched packages in ${duration}ms`)\n */\nexport async function measure<T>(\n operation: string,\n fn: () => Promise<T>,\n metadata?: Record<string, unknown>,\n): Promise<{ result: T; duration: number }> {\n const stop = perfTimer(operation, metadata)\n\n try {\n const result = await fn()\n stop({ success: true })\n\n const metric = performanceMetrics[performanceMetrics.length - 1]\n return { result, duration: metric?.duration || 0 }\n } catch (e) {\n stop({\n success: false,\n error: e instanceof Error ? e.message : 'Unknown',\n })\n throw e\n }\n}\n\n/**\n * Measure synchronous function execution time.\n *\n * @param operation - Name of the operation\n * @param fn - Synchronous function to measure\n * @param metadata - Optional metadata\n * @returns Result of the function and duration\n *\n * @example\n * import { measureSync } from '@socketsecurity/lib/performance'\n *\n * const { result, duration } = measureSync('parse-json', () => {\n * return JSON.parse(data)\n * })\n */\nexport function measureSync<T>(\n operation: string,\n fn: () => T,\n metadata?: Record<string, unknown>,\n): { result: T; duration: number } {\n const stop = perfTimer(operation, metadata)\n\n try {\n const result = fn()\n stop({ success: true })\n\n const metric = performanceMetrics[performanceMetrics.length - 1]\n return { result, duration: metric?.duration || 0 }\n } catch (e) {\n stop({\n success: false,\n error: e instanceof Error ? e.message : 'Unknown',\n })\n throw e\n }\n}\n\n/**\n * Get all collected performance metrics.\n * Only available when DEBUG=perf is enabled.\n *\n * @returns Array of performance metrics\n *\n * @example\n * import { getPerformanceMetrics } from '@socketsecurity/lib/performance'\n *\n * const metrics = getPerformanceMetrics()\n * console.log(metrics)\n */\nexport function getPerformanceMetrics(): PerformanceMetrics[] {\n return [...performanceMetrics]\n}\n\n/**\n * Clear all collected performance metrics.\n *\n * @example\n * import { clearPerformanceMetrics } from '@socketsecurity/lib/performance'\n *\n * clearPerformanceMetrics()\n */\nexport function clearPerformanceMetrics(): void {\n performanceMetrics.length = 0\n debugLog('[perf] Cleared performance metrics')\n}\n\n/**\n * Get performance summary statistics.\n *\n * @returns Summary of metrics grouped by operation\n *\n * @example\n * import { getPerformanceSummary } from '@socketsecurity/lib/performance'\n *\n * const summary = getPerformanceSummary()\n * console.log(summary)\n * // {\n * // 'api-call': { count: 5, total: 1234, avg: 246.8, min: 100, max: 500 },\n * // 'file-read': { count: 10, total: 50, avg: 5, min: 2, max: 15 }\n * // }\n */\nexport function getPerformanceSummary(): Record<\n string,\n {\n count: number\n total: number\n avg: number\n min: number\n max: number\n }\n> {\n const summary: Record<\n string,\n { count: number; total: number; min: number; max: number }\n > = Object.create(null)\n\n for (const metric of performanceMetrics) {\n const { duration, operation } = metric\n\n if (!summary[operation]) {\n summary[operation] = {\n count: 0,\n total: 0,\n min: Number.POSITIVE_INFINITY,\n max: Number.NEGATIVE_INFINITY,\n }\n }\n\n const stats = summary[operation] as {\n count: number\n total: number\n min: number\n max: number\n }\n stats.count++\n stats.total += duration\n stats.min = Math.min(stats.min, duration)\n stats.max = Math.max(stats.max, duration)\n }\n\n // Calculate averages and return with proper typing\n const result: Record<\n string,\n { count: number; total: number; avg: number; min: number; max: number }\n > = Object.create(null)\n\n for (const { 0: operation, 1: stats } of Object.entries(summary)) {\n result[operation] = {\n count: stats.count,\n total: Math.round(stats.total * 100) / 100,\n avg: Math.round((stats.total / stats.count) * 100) / 100,\n min: Math.round(stats.min * 100) / 100,\n max: Math.round(stats.max * 100) / 100,\n }\n }\n\n return result\n}\n\n/**\n * Print performance summary to console.\n * Only prints when DEBUG=perf is enabled.\n *\n * @example\n * import { printPerformanceSummary } from '@socketsecurity/lib/performance'\n *\n * printPerformanceSummary()\n * // Performance Summary:\n * // api-call: 5 calls, avg 246.8ms (min 100ms, max 500ms, total 1234ms)\n * // file-read: 10 calls, avg 5ms (min 2ms, max 15ms, total 50ms)\n */\nexport function printPerformanceSummary(): void {\n if (!isPerfEnabled() || performanceMetrics.length === 0) {\n return\n }\n\n const summary = getPerformanceSummary()\n const operations = Object.keys(summary).sort()\n\n debugLog('[perf]\\n=== Performance Summary ===')\n\n for (const operation of operations) {\n const stats = summary[operation] as {\n count: number\n total: number\n avg: number\n min: number\n max: number\n }\n debugLog(\n `[perf] ${operation}: ${stats.count} calls, avg ${stats.avg}ms (min ${stats.min}ms, max ${stats.max}ms, total ${stats.total}ms)`,\n )\n }\n\n debugLog('[perf] =========================\\n')\n}\n\n/**\n * Mark a checkpoint in performance tracking.\n * Useful for tracking progress through complex operations.\n *\n * @param checkpoint - Name of the checkpoint\n * @param metadata - Optional metadata\n *\n * @example\n * import { perfCheckpoint } from '@socketsecurity/lib/performance'\n *\n * perfCheckpoint('start-scan')\n * // ... do work ...\n * perfCheckpoint('fetch-packages', { count: 50 })\n * // ... do work ...\n * perfCheckpoint('analyze-issues', { issueCount: 10 })\n * perfCheckpoint('end-scan')\n */\nexport function perfCheckpoint(\n checkpoint: string,\n metadata?: Record<string, unknown>,\n): void {\n if (!isPerfEnabled()) {\n return\n }\n\n const metric: PerformanceMetrics = {\n operation: `checkpoint:${checkpoint}`,\n duration: 0,\n timestamp: Date.now(),\n ...(metadata ? { metadata } : {}),\n }\n\n performanceMetrics.push(metric)\n debugLog(`[perf] [CHECKPOINT] ${checkpoint}`)\n}\n\n/**\n * Track memory usage at a specific point.\n * Only available when DEBUG=perf is enabled.\n *\n * @param label - Label for this memory snapshot\n * @returns Memory usage in MB\n *\n * @example\n * import { trackMemory } from '@socketsecurity/lib/performance'\n *\n * const memBefore = trackMemory('before-operation')\n * await heavyOperation()\n * const memAfter = trackMemory('after-operation')\n * console.log(`Memory increased by ${memAfter - memBefore}MB`)\n */\nexport function trackMemory(label: string): number {\n if (!isPerfEnabled()) {\n return 0\n }\n\n const usage = process.memoryUsage()\n const heapUsedMB = Math.round((usage.heapUsed / 1024 / 1024) * 100) / 100\n\n debugLog(`[perf] [MEMORY] ${label}: ${heapUsedMB}MB heap used`)\n\n const metric: PerformanceMetrics = {\n operation: `checkpoint:memory:${label}`,\n duration: 0,\n timestamp: Date.now(),\n metadata: {\n heapUsed: heapUsedMB,\n heapTotal: Math.round((usage.heapTotal / 1024 / 1024) * 100) / 100,\n external: Math.round((usage.external / 1024 / 1024) * 100) / 100,\n },\n }\n\n performanceMetrics.push(metric)\n\n return heapUsedMB\n}\n\n/**\n * Create a performance report for the current execution.\n * Only available when DEBUG=perf is enabled.\n *\n * @returns Formatted performance report\n *\n * @example\n * import { generatePerformanceReport } from '@socketsecurity/lib/performance'\n *\n * console.log(generatePerformanceReport())\n * // \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n * // \u2551 Performance Report \u2551\n * // \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n * //\n * // api-call:\n * // Calls: 5\n * // Avg: 246.8ms\n * // Min: 100ms\n * // Max: 500ms\n * // Total: 1234ms\n */\nexport function generatePerformanceReport(): string {\n if (!isPerfEnabled() || performanceMetrics.length === 0) {\n return '(no performance data collected - enable with DEBUG=perf)'\n }\n\n const summary = getPerformanceSummary()\n const operations = Object.keys(summary).sort()\n\n let report = '\\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\\n'\n report += '\u2551 Performance Report \u2551\\n'\n report += '\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\\n\\n'\n\n for (const operation of operations) {\n const stats = summary[operation] as {\n count: number\n total: number\n avg: number\n min: number\n max: number\n }\n report += `${operation}:\\n`\n report += ` Calls: ${stats.count}\\n`\n report += ` Avg: ${stats.avg}ms\\n`\n report += ` Min: ${stats.min}ms\\n`\n report += ` Max: ${stats.max}ms\\n`\n report += ` Total: ${stats.total}ms\\n\\n`\n }\n\n const totalDuration = Object.values(summary).reduce(\n (sum, s) => sum + s.total,\n 0,\n )\n report += `Total measured time: ${Math.round(totalDuration * 100) / 100}ms\\n`\n\n return report\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
6
|
-
"names": [
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
package/dist/process-lock.js
CHANGED
|
@@ -1,14 +1,293 @@
|
|
|
1
1
|
/* Socket Lib - Built with esbuild */
|
|
2
|
-
var
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var process_lock_exports = {};
|
|
20
|
+
__export(process_lock_exports, {
|
|
21
|
+
processLock: () => processLock
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(process_lock_exports);
|
|
24
|
+
var import_fs = require("fs");
|
|
25
|
+
var import_fs2 = require("./fs");
|
|
26
|
+
var import_logger = require("./logger");
|
|
27
|
+
var import_promises = require("./promises");
|
|
28
|
+
var import_signal_exit = require("./signal-exit");
|
|
29
|
+
const logger = (0, import_logger.getDefaultLogger)();
|
|
30
|
+
class ProcessLockManager {
|
|
31
|
+
activeLocks = /* @__PURE__ */ new Set();
|
|
32
|
+
touchTimers = /* @__PURE__ */ new Map();
|
|
33
|
+
exitHandlerRegistered = false;
|
|
34
|
+
/**
|
|
35
|
+
* Ensure process exit handler is registered for cleanup.
|
|
36
|
+
* Registers a handler that cleans up all active locks when the process exits.
|
|
37
|
+
*/
|
|
38
|
+
ensureExitHandler() {
|
|
39
|
+
if (this.exitHandlerRegistered) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
(0, import_signal_exit.onExit)(() => {
|
|
43
|
+
for (const timer of this.touchTimers.values()) {
|
|
44
|
+
clearInterval(timer);
|
|
45
|
+
}
|
|
46
|
+
this.touchTimers.clear();
|
|
47
|
+
for (const lockPath of this.activeLocks) {
|
|
48
|
+
try {
|
|
49
|
+
if ((0, import_fs.existsSync)(lockPath)) {
|
|
50
|
+
(0, import_fs2.safeDeleteSync)(lockPath, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.exitHandlerRegistered = true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Touch a lock file to update its mtime.
|
|
60
|
+
* This prevents the lock from being detected as stale during long operations.
|
|
61
|
+
*
|
|
62
|
+
* @param lockPath - Path to the lock directory
|
|
63
|
+
*/
|
|
64
|
+
touchLock(lockPath) {
|
|
65
|
+
try {
|
|
66
|
+
if ((0, import_fs.existsSync)(lockPath)) {
|
|
67
|
+
const now = /* @__PURE__ */ new Date();
|
|
68
|
+
(0, import_fs.utimesSync)(lockPath, now, now);
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
logger.warn(
|
|
72
|
+
`Failed to touch lock ${lockPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Start periodic touching of a lock file.
|
|
78
|
+
* Aligned with npm npx strategy to prevent false stale detection.
|
|
79
|
+
*
|
|
80
|
+
* @param lockPath - Path to the lock directory
|
|
81
|
+
* @param intervalMs - Touch interval in milliseconds
|
|
82
|
+
*/
|
|
83
|
+
startTouchTimer(lockPath, intervalMs) {
|
|
84
|
+
if (intervalMs <= 0 || this.touchTimers.has(lockPath)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const timer = setInterval(() => {
|
|
88
|
+
this.touchLock(lockPath);
|
|
89
|
+
}, intervalMs);
|
|
90
|
+
timer.unref();
|
|
91
|
+
this.touchTimers.set(lockPath, timer);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stop periodic touching of a lock file.
|
|
95
|
+
*
|
|
96
|
+
* @param lockPath - Path to the lock directory
|
|
97
|
+
*/
|
|
98
|
+
stopTouchTimer(lockPath) {
|
|
99
|
+
const timer = this.touchTimers.get(lockPath);
|
|
100
|
+
if (timer) {
|
|
101
|
+
clearInterval(timer);
|
|
102
|
+
this.touchTimers.delete(lockPath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a lock is stale based on mtime.
|
|
107
|
+
* Uses second-level granularity to avoid APFS floating-point precision issues.
|
|
108
|
+
* Aligned with npm's npx locking strategy.
|
|
109
|
+
*
|
|
110
|
+
* @param lockPath - Path to the lock directory
|
|
111
|
+
* @param staleMs - Stale timeout in milliseconds
|
|
112
|
+
* @returns True if lock exists and is stale
|
|
113
|
+
*/
|
|
114
|
+
isStale(lockPath, staleMs) {
|
|
115
|
+
try {
|
|
116
|
+
if (!(0, import_fs.existsSync)(lockPath)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const stats = (0, import_fs.statSync)(lockPath);
|
|
120
|
+
const ageSeconds = Math.floor((Date.now() - stats.mtime.getTime()) / 1e3);
|
|
121
|
+
const staleSeconds = Math.floor(staleMs / 1e3);
|
|
122
|
+
return ageSeconds > staleSeconds;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Acquire a lock using mkdir for atomic operation.
|
|
129
|
+
* Handles stale locks and includes exit cleanup.
|
|
130
|
+
*
|
|
131
|
+
* This method attempts to create a lock directory atomically. If the lock
|
|
132
|
+
* already exists, it checks if it's stale and removes it before retrying.
|
|
133
|
+
* Uses exponential backoff with jitter for retry attempts.
|
|
134
|
+
*
|
|
135
|
+
* @param lockPath - Path to the lock directory
|
|
136
|
+
* @param options - Lock acquisition options
|
|
137
|
+
* @returns Release function to unlock
|
|
138
|
+
* @throws Error if lock cannot be acquired after all retries
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* const release = await processLock.acquire('/tmp/my-lock')
|
|
143
|
+
* try {
|
|
144
|
+
* // Critical section
|
|
145
|
+
* } finally {
|
|
146
|
+
* release()
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
async acquire(lockPath, options = {}) {
|
|
151
|
+
const {
|
|
152
|
+
baseDelayMs = 100,
|
|
153
|
+
maxDelayMs = 1e3,
|
|
154
|
+
retries = 3,
|
|
155
|
+
staleMs = 5e3,
|
|
156
|
+
touchIntervalMs = 2e3
|
|
157
|
+
} = options;
|
|
158
|
+
this.ensureExitHandler();
|
|
159
|
+
return await (0, import_promises.pRetry)(
|
|
160
|
+
async () => {
|
|
161
|
+
try {
|
|
162
|
+
if ((0, import_fs.existsSync)(lockPath) && this.isStale(lockPath, staleMs)) {
|
|
163
|
+
logger.log(`Removing stale lock: ${lockPath}`);
|
|
164
|
+
try {
|
|
165
|
+
(0, import_fs2.safeDeleteSync)(lockPath, { recursive: true });
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if ((0, import_fs.existsSync)(lockPath)) {
|
|
170
|
+
throw new Error(`Lock already exists: ${lockPath}`);
|
|
171
|
+
}
|
|
172
|
+
(0, import_fs.mkdirSync)(lockPath, { recursive: true });
|
|
173
|
+
this.activeLocks.add(lockPath);
|
|
174
|
+
this.startTouchTimer(lockPath, touchIntervalMs);
|
|
175
|
+
return () => this.release(lockPath);
|
|
176
|
+
} catch (error) {
|
|
177
|
+
const code = error.code;
|
|
178
|
+
if (code === "EEXIST") {
|
|
179
|
+
if (this.isStale(lockPath, staleMs)) {
|
|
180
|
+
throw new Error(`Stale lock detected: ${lockPath}`);
|
|
181
|
+
}
|
|
182
|
+
throw new Error(`Lock already exists: ${lockPath}`);
|
|
183
|
+
}
|
|
184
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
185
|
+
throw new Error(
|
|
186
|
+
`Permission denied creating lock: ${lockPath}. Check directory permissions or run with appropriate access.`,
|
|
187
|
+
{ cause: error }
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (code === "EROFS") {
|
|
191
|
+
throw new Error(
|
|
192
|
+
`Cannot create lock on read-only filesystem: ${lockPath}`,
|
|
193
|
+
{ cause: error }
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
if (code === "ENOTDIR") {
|
|
197
|
+
const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Cannot create lock directory: ${lockPath}
|
|
3
200
|
A path component is a file when it should be a directory.
|
|
4
|
-
Parent path: ${
|
|
201
|
+
Parent path: ${parentDir}
|
|
5
202
|
To resolve:
|
|
6
|
-
1. Check if "${
|
|
203
|
+
1. Check if "${parentDir}" contains a file instead of a directory
|
|
7
204
|
2. Remove any conflicting files in the path
|
|
8
|
-
3. Ensure the full parent directory structure exists`,
|
|
9
|
-
|
|
205
|
+
3. Ensure the full parent directory structure exists`,
|
|
206
|
+
{ cause: error }
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (code === "ENOENT") {
|
|
210
|
+
const parentDir = lockPath.slice(0, lockPath.lastIndexOf("/"));
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Cannot create lock directory: ${lockPath}
|
|
213
|
+
Parent directory does not exist: ${parentDir}
|
|
10
214
|
To resolve:
|
|
11
|
-
1. Ensure the parent directory "${
|
|
12
|
-
2. Create the directory structure: mkdir -p "${
|
|
13
|
-
3. Check filesystem permissions allow directory creation`,
|
|
215
|
+
1. Ensure the parent directory "${parentDir}" exists
|
|
216
|
+
2. Create the directory structure: mkdir -p "${parentDir}"
|
|
217
|
+
3. Check filesystem permissions allow directory creation`,
|
|
218
|
+
{ cause: error }
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
throw new Error(`Failed to acquire lock: ${lockPath}`, {
|
|
222
|
+
cause: error
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
retries,
|
|
228
|
+
baseDelayMs,
|
|
229
|
+
maxDelayMs,
|
|
230
|
+
jitter: true
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Release a lock and remove from tracking.
|
|
236
|
+
* Stops periodic touching and removes the lock directory.
|
|
237
|
+
*
|
|
238
|
+
* @param lockPath - Path to the lock directory
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* processLock.release('/tmp/my-lock')
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
release(lockPath) {
|
|
246
|
+
this.stopTouchTimer(lockPath);
|
|
247
|
+
try {
|
|
248
|
+
if ((0, import_fs.existsSync)(lockPath)) {
|
|
249
|
+
(0, import_fs2.safeDeleteSync)(lockPath, { recursive: true });
|
|
250
|
+
}
|
|
251
|
+
this.activeLocks.delete(lockPath);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
logger.warn(
|
|
254
|
+
`Failed to release lock ${lockPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Execute a function with exclusive lock protection.
|
|
260
|
+
* Automatically handles lock acquisition, execution, and cleanup.
|
|
261
|
+
*
|
|
262
|
+
* This is the recommended way to use process locks, as it guarantees
|
|
263
|
+
* cleanup even if the callback throws an error.
|
|
264
|
+
*
|
|
265
|
+
* @param lockPath - Path to the lock directory
|
|
266
|
+
* @param fn - Function to execute while holding the lock
|
|
267
|
+
* @param options - Lock acquisition options
|
|
268
|
+
* @returns Result of the callback function
|
|
269
|
+
* @throws Error from callback or lock acquisition failure
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* const result = await processLock.withLock('/tmp/my-lock', async () => {
|
|
274
|
+
* // Critical section
|
|
275
|
+
* return someValue
|
|
276
|
+
* })
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
async withLock(lockPath, fn, options) {
|
|
280
|
+
const release = await this.acquire(lockPath, options);
|
|
281
|
+
try {
|
|
282
|
+
return await fn();
|
|
283
|
+
} finally {
|
|
284
|
+
release();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const processLock = new ProcessLockManager();
|
|
289
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
290
|
+
0 && (module.exports = {
|
|
291
|
+
processLock
|
|
292
|
+
});
|
|
14
293
|
//# sourceMappingURL=process-lock.js.map
|