@scriptdb/cli 1.0.4 → 1.0.6
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/dist/index.js +67 -269
- package/package.json +3 -4
package/dist/index.js
CHANGED
|
@@ -9,273 +9,6 @@ import { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from "
|
|
|
9
9
|
import { join } from "path";
|
|
10
10
|
import { homedir } from "os";
|
|
11
11
|
|
|
12
|
-
// ../../node_modules/.bun/ps-list@9.0.0/node_modules/ps-list/index.js
|
|
13
|
-
import process2 from "node:process";
|
|
14
|
-
import fs from "node:fs";
|
|
15
|
-
import { promisify } from "node:util";
|
|
16
|
-
import path from "node:path";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
18
|
-
import childProcess from "node:child_process";
|
|
19
|
-
var __dirname2 = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
-
var DEFAULT_MAX_BUFFER = 64000000;
|
|
21
|
-
var MAXIMUM_PATH_COMBINATION_ATTEMPTS = 6;
|
|
22
|
-
var execFile = promisify(childProcess.execFile);
|
|
23
|
-
var PROCESS_FIELDS = {
|
|
24
|
-
CPU_PERCENT: "%cpu",
|
|
25
|
-
MEMORY_PERCENT: "%mem",
|
|
26
|
-
PROCESS_ID: "pid",
|
|
27
|
-
PARENT_PROCESS_ID: "ppid",
|
|
28
|
-
USER_ID: "uid",
|
|
29
|
-
START_TIME: "lstart",
|
|
30
|
-
COMMAND_NAME: "comm",
|
|
31
|
-
ARGUMENTS: "args"
|
|
32
|
-
};
|
|
33
|
-
var buildProcessCommandFlags = (includeAllUsersProcesses) => (includeAllUsersProcesses === false ? "" : "a") + "wwxo";
|
|
34
|
-
var makeStartTime = (startTimeString) => {
|
|
35
|
-
if (!startTimeString) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const parsedDate = new Date(startTimeString);
|
|
39
|
-
return Number.isNaN(parsedDate.getTime()) ? undefined : parsedDate;
|
|
40
|
-
};
|
|
41
|
-
var extractExecutablePath = (commandLine) => {
|
|
42
|
-
if (!commandLine) {
|
|
43
|
-
return "";
|
|
44
|
-
}
|
|
45
|
-
if (!commandLine.startsWith("/") && !commandLine.startsWith('"')) {
|
|
46
|
-
return "";
|
|
47
|
-
}
|
|
48
|
-
if (commandLine.startsWith('"')) {
|
|
49
|
-
const quotedPathMatch = commandLine.match(/^"([^"]+)"/);
|
|
50
|
-
if (quotedPathMatch && fs.existsSync(quotedPathMatch[1])) {
|
|
51
|
-
return quotedPathMatch[1];
|
|
52
|
-
}
|
|
53
|
-
return "";
|
|
54
|
-
}
|
|
55
|
-
const commandParts = commandLine.split(" ");
|
|
56
|
-
const firstCommandToken = commandParts[0];
|
|
57
|
-
if (fs.existsSync(firstCommandToken)) {
|
|
58
|
-
return firstCommandToken;
|
|
59
|
-
}
|
|
60
|
-
const maximumCombinationAttempts = Math.min(commandParts.length, MAXIMUM_PATH_COMBINATION_ATTEMPTS);
|
|
61
|
-
for (let tokenCount = 2;tokenCount <= maximumCombinationAttempts; tokenCount++) {
|
|
62
|
-
const candidateExecutablePath = commandParts.slice(0, tokenCount).join(" ");
|
|
63
|
-
if (fs.existsSync(candidateExecutablePath)) {
|
|
64
|
-
return candidateExecutablePath;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return "";
|
|
68
|
-
};
|
|
69
|
-
var resolveExecutablePath = (operatingSystemPlatform, processId, commandLine) => {
|
|
70
|
-
if (operatingSystemPlatform === "linux" && processId) {
|
|
71
|
-
try {
|
|
72
|
-
const symbolicLink = fs.readlinkSync(`/proc/${processId}/exe`);
|
|
73
|
-
return symbolicLink.replace(/\s+\(deleted\)$/, "");
|
|
74
|
-
} catch {}
|
|
75
|
-
}
|
|
76
|
-
return extractExecutablePath(commandLine);
|
|
77
|
-
};
|
|
78
|
-
var parseNumericField = (fieldValue, parserFunction = Number.parseInt, defaultValue = 0) => {
|
|
79
|
-
if (!fieldValue) {
|
|
80
|
-
return defaultValue;
|
|
81
|
-
}
|
|
82
|
-
const parsedValue = parserFunction(fieldValue, 10);
|
|
83
|
-
return Number.isNaN(parsedValue) ? defaultValue : parsedValue;
|
|
84
|
-
};
|
|
85
|
-
var parseIntegerOrUndefined = (fieldValue) => {
|
|
86
|
-
if (fieldValue === undefined || fieldValue === "") {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const parsedValue = Number.parseInt(fieldValue, 10);
|
|
90
|
-
return Number.isNaN(parsedValue) ? undefined : parsedValue;
|
|
91
|
-
};
|
|
92
|
-
var parseProcessFields = ({ processId, parentProcessId, userId, cpuUsage, memoryUsage, commandName, startTimeString, command }) => {
|
|
93
|
-
const parsedProcessId = parseNumericField(processId);
|
|
94
|
-
const parsedParentProcessId = parseNumericField(parentProcessId);
|
|
95
|
-
const parsedUserId = parseIntegerOrUndefined(userId);
|
|
96
|
-
const parsedCpuUsagePercentage = parseNumericField(cpuUsage, Number.parseFloat);
|
|
97
|
-
const parsedMemoryUsagePercentage = parseNumericField(memoryUsage, Number.parseFloat);
|
|
98
|
-
const resolvedExecutablePath = resolveExecutablePath(process2.platform, parsedProcessId, command);
|
|
99
|
-
const derivedProcessName = resolvedExecutablePath ? path.basename(resolvedExecutablePath) : commandName || "";
|
|
100
|
-
return {
|
|
101
|
-
pid: parsedProcessId,
|
|
102
|
-
ppid: parsedParentProcessId,
|
|
103
|
-
uid: parsedUserId,
|
|
104
|
-
cpu: parsedCpuUsagePercentage,
|
|
105
|
-
memory: parsedMemoryUsagePercentage,
|
|
106
|
-
name: derivedProcessName,
|
|
107
|
-
path: resolvedExecutablePath,
|
|
108
|
-
startTime: makeStartTime(startTimeString),
|
|
109
|
-
cmd: command || ""
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
|
-
var windows = async () => {
|
|
113
|
-
let binary;
|
|
114
|
-
switch (process2.arch) {
|
|
115
|
-
case "x64": {
|
|
116
|
-
binary = "fastlist-0.3.0-x64.exe";
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
case "ia32": {
|
|
120
|
-
binary = "fastlist-0.3.0-x86.exe";
|
|
121
|
-
break;
|
|
122
|
-
}
|
|
123
|
-
case "arm64": {
|
|
124
|
-
throw new Error("Windows ARM64 is not supported yet.");
|
|
125
|
-
}
|
|
126
|
-
default: {
|
|
127
|
-
throw new Error(`Unsupported architecture: ${process2.arch}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const binaryPath = path.join(__dirname2, "vendor", binary);
|
|
131
|
-
const { stdout } = await execFile(binaryPath, {
|
|
132
|
-
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
133
|
-
windowsHide: true,
|
|
134
|
-
encoding: "utf8"
|
|
135
|
-
});
|
|
136
|
-
return stdout.trim().split(/\r?\n/).map((line) => line.split("\t")).map(([processId, parentProcessId, processName]) => ({
|
|
137
|
-
pid: Number.parseInt(processId, 10),
|
|
138
|
-
ppid: Number.parseInt(parentProcessId, 10),
|
|
139
|
-
name: processName
|
|
140
|
-
}));
|
|
141
|
-
};
|
|
142
|
-
var nonWindowsFallbackMultipleCalls = async (options = {}) => {
|
|
143
|
-
const processDataByProcessId = {};
|
|
144
|
-
const processCommandFlags = buildProcessCommandFlags(options.all);
|
|
145
|
-
const fields = [
|
|
146
|
-
PROCESS_FIELDS.COMMAND_NAME,
|
|
147
|
-
PROCESS_FIELDS.ARGUMENTS,
|
|
148
|
-
PROCESS_FIELDS.PARENT_PROCESS_ID,
|
|
149
|
-
PROCESS_FIELDS.USER_ID,
|
|
150
|
-
PROCESS_FIELDS.CPU_PERCENT,
|
|
151
|
-
PROCESS_FIELDS.MEMORY_PERCENT,
|
|
152
|
-
PROCESS_FIELDS.START_TIME
|
|
153
|
-
];
|
|
154
|
-
await Promise.all(fields.map(async (fieldName) => {
|
|
155
|
-
const { stdout } = await execFile("ps", [processCommandFlags, `${PROCESS_FIELDS.PROCESS_ID}=,${fieldName}=`], {
|
|
156
|
-
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
157
|
-
encoding: "utf8",
|
|
158
|
-
env: {
|
|
159
|
-
...process2.env,
|
|
160
|
-
LC_ALL: "C",
|
|
161
|
-
LANG: "C"
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
for (const line of stdout.trim().split(`
|
|
165
|
-
`)) {
|
|
166
|
-
const trimmedLine = line.trim();
|
|
167
|
-
const spaceIndex = trimmedLine.indexOf(" ");
|
|
168
|
-
if (spaceIndex === -1) {
|
|
169
|
-
const processId2 = trimmedLine;
|
|
170
|
-
const fieldValue2 = "";
|
|
171
|
-
processDataByProcessId[processId2] ??= {};
|
|
172
|
-
processDataByProcessId[processId2][fieldName] = fieldValue2;
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
const processId = trimmedLine.slice(0, spaceIndex);
|
|
176
|
-
const fieldValue = trimmedLine.slice(spaceIndex + 1).trim();
|
|
177
|
-
processDataByProcessId[processId] ??= {};
|
|
178
|
-
processDataByProcessId[processId][fieldName] = fieldValue;
|
|
179
|
-
}
|
|
180
|
-
}));
|
|
181
|
-
return Object.entries(processDataByProcessId).filter(([, data]) => data[PROCESS_FIELDS.COMMAND_NAME] && data[PROCESS_FIELDS.PARENT_PROCESS_ID] !== undefined).map(([processId, data]) => parseProcessFields({
|
|
182
|
-
processId,
|
|
183
|
-
parentProcessId: data[PROCESS_FIELDS.PARENT_PROCESS_ID],
|
|
184
|
-
userId: data[PROCESS_FIELDS.USER_ID],
|
|
185
|
-
cpuUsage: data[PROCESS_FIELDS.CPU_PERCENT],
|
|
186
|
-
memoryUsage: data[PROCESS_FIELDS.MEMORY_PERCENT],
|
|
187
|
-
commandName: data[PROCESS_FIELDS.COMMAND_NAME],
|
|
188
|
-
startTimeString: data[PROCESS_FIELDS.START_TIME],
|
|
189
|
-
command: data[PROCESS_FIELDS.ARGUMENTS] ?? ""
|
|
190
|
-
}));
|
|
191
|
-
};
|
|
192
|
-
var nonWindowsCall = async (options = {}) => {
|
|
193
|
-
const processCommandFlags = buildProcessCommandFlags(options.all);
|
|
194
|
-
const executeFileOptions = {
|
|
195
|
-
maxBuffer: DEFAULT_MAX_BUFFER,
|
|
196
|
-
encoding: "utf8",
|
|
197
|
-
env: {
|
|
198
|
-
...process2.env,
|
|
199
|
-
LC_ALL: "C",
|
|
200
|
-
LANG: "C"
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
const processFieldCommaSeparatedList = [
|
|
204
|
-
PROCESS_FIELDS.PROCESS_ID,
|
|
205
|
-
PROCESS_FIELDS.PARENT_PROCESS_ID,
|
|
206
|
-
PROCESS_FIELDS.USER_ID,
|
|
207
|
-
PROCESS_FIELDS.CPU_PERCENT,
|
|
208
|
-
PROCESS_FIELDS.MEMORY_PERCENT,
|
|
209
|
-
PROCESS_FIELDS.START_TIME,
|
|
210
|
-
PROCESS_FIELDS.COMMAND_NAME
|
|
211
|
-
].map((fieldName) => `${fieldName}=`).join(",");
|
|
212
|
-
const commandFieldCommaSeparatedList = [
|
|
213
|
-
PROCESS_FIELDS.PROCESS_ID,
|
|
214
|
-
PROCESS_FIELDS.ARGUMENTS
|
|
215
|
-
].map((fieldName) => `${fieldName}=`).join(",");
|
|
216
|
-
const processListingPromises = [
|
|
217
|
-
execFile("ps", [processCommandFlags, processFieldCommaSeparatedList], executeFileOptions),
|
|
218
|
-
execFile("ps", [processCommandFlags, commandFieldCommaSeparatedList], executeFileOptions)
|
|
219
|
-
];
|
|
220
|
-
const [processOutput, commandOutput] = await Promise.all(processListingPromises);
|
|
221
|
-
const processLines = processOutput.stdout.trim().split(`
|
|
222
|
-
`);
|
|
223
|
-
const commandLines = commandOutput.stdout.trim().split(`
|
|
224
|
-
`);
|
|
225
|
-
const commandLinesByProcessId = {};
|
|
226
|
-
for (const line of commandLines) {
|
|
227
|
-
const trimmedLine = line.trim();
|
|
228
|
-
const spaceIndex = trimmedLine.indexOf(" ");
|
|
229
|
-
if (spaceIndex === -1) {
|
|
230
|
-
const processId2 = trimmedLine;
|
|
231
|
-
commandLinesByProcessId[processId2] = "";
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
const processId = trimmedLine.slice(0, spaceIndex);
|
|
235
|
-
const command = trimmedLine.slice(spaceIndex + 1).trim();
|
|
236
|
-
commandLinesByProcessId[processId] = command;
|
|
237
|
-
}
|
|
238
|
-
const processes = [];
|
|
239
|
-
for (const line of processLines) {
|
|
240
|
-
const trimmedLine = line.trim();
|
|
241
|
-
if (!trimmedLine) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
const processLineRegexMatch = trimmedLine.match(/^(\d+)\s+(\d+)\s+(\d+)\s+([\d.]+)\s+([\d.]+)\s+(.+)/);
|
|
245
|
-
if (!processLineRegexMatch) {
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
const [, processId, parentProcessId, userId, cpuUsage, memoryUsage, dateAndCommandPortion] = processLineRegexMatch;
|
|
249
|
-
const startTimeRegexMatch = dateAndCommandPortion.match(/^((?:\w{3}\s+){2}\d{1,2}\s+(?:\d{2}:){2}\d{2}\s+\d{4})\s+(.*)$/);
|
|
250
|
-
let startTimeString = "";
|
|
251
|
-
let processCommandName = dateAndCommandPortion;
|
|
252
|
-
if (startTimeRegexMatch) {
|
|
253
|
-
startTimeString = startTimeRegexMatch[1];
|
|
254
|
-
processCommandName = startTimeRegexMatch[2] || "";
|
|
255
|
-
}
|
|
256
|
-
processes.push(parseProcessFields({
|
|
257
|
-
processId,
|
|
258
|
-
parentProcessId,
|
|
259
|
-
userId,
|
|
260
|
-
cpuUsage,
|
|
261
|
-
memoryUsage,
|
|
262
|
-
commandName: processCommandName,
|
|
263
|
-
startTimeString,
|
|
264
|
-
command: commandLinesByProcessId[processId] ?? ""
|
|
265
|
-
}));
|
|
266
|
-
}
|
|
267
|
-
return processes;
|
|
268
|
-
};
|
|
269
|
-
var nonWindows = async (options = {}) => {
|
|
270
|
-
try {
|
|
271
|
-
return await nonWindowsCall(options);
|
|
272
|
-
} catch {
|
|
273
|
-
return nonWindowsFallbackMultipleCalls(options);
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
|
-
var psList = process2.platform === "win32" ? windows : nonWindows;
|
|
277
|
-
var ps_list_default = psList;
|
|
278
|
-
|
|
279
12
|
// src/shell.ts
|
|
280
13
|
import { createInterface } from "readline";
|
|
281
14
|
import Client from "@scriptdb/client";
|
|
@@ -504,6 +237,71 @@ Examples:
|
|
|
504
237
|
}
|
|
505
238
|
|
|
506
239
|
// src/index.ts
|
|
240
|
+
async function getProcessList() {
|
|
241
|
+
try {
|
|
242
|
+
if (process.platform === "win32") {
|
|
243
|
+
const output = execSync("wmic process get ProcessId,WorkingSetSize /format:csv", {
|
|
244
|
+
encoding: "utf8",
|
|
245
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
246
|
+
});
|
|
247
|
+
const lines = output.split(`
|
|
248
|
+
`).slice(1);
|
|
249
|
+
const processes = [];
|
|
250
|
+
for (const line of lines) {
|
|
251
|
+
const parts = line.split(",").map((p) => p.trim());
|
|
252
|
+
if (parts.length >= 2 && parts[0] && parts[1]) {
|
|
253
|
+
const pid = parseInt(parts[0], 10);
|
|
254
|
+
const memory = parseInt(parts[1], 10);
|
|
255
|
+
if (!isNaN(pid) && !isNaN(memory)) {
|
|
256
|
+
processes.push({ pid, memory });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return processes;
|
|
261
|
+
} else if (process.platform === "darwin") {
|
|
262
|
+
const output = execSync("ps -eo pid,pcpu,rss", {
|
|
263
|
+
encoding: "utf8",
|
|
264
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
265
|
+
});
|
|
266
|
+
const lines = output.split(`
|
|
267
|
+
`).slice(1);
|
|
268
|
+
const processes = [];
|
|
269
|
+
for (const line of lines) {
|
|
270
|
+
const match = line.trim().match(/\s*(\d+)\s+([\d.]+)\s+(\d+)/);
|
|
271
|
+
if (match) {
|
|
272
|
+
processes.push({
|
|
273
|
+
pid: parseInt(match[1], 10),
|
|
274
|
+
cpu: parseFloat(match[2]),
|
|
275
|
+
memory: parseInt(match[3], 10) * 1024
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return processes;
|
|
280
|
+
} else {
|
|
281
|
+
const output = execSync("ps -eo pid,pcpu,rss", {
|
|
282
|
+
encoding: "utf8",
|
|
283
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
284
|
+
});
|
|
285
|
+
const lines = output.split(`
|
|
286
|
+
`).slice(1);
|
|
287
|
+
const processes = [];
|
|
288
|
+
for (const line of lines) {
|
|
289
|
+
const match = line.trim().match(/\s*(\d+)\s+([\d.]+)\s+(\d+)/);
|
|
290
|
+
if (match) {
|
|
291
|
+
processes.push({
|
|
292
|
+
pid: parseInt(match[1], 10),
|
|
293
|
+
cpu: parseFloat(match[2]),
|
|
294
|
+
memory: parseInt(match[3], 10) * 1024
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return processes;
|
|
299
|
+
}
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error("Failed to get process list:", error);
|
|
302
|
+
return [];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
507
305
|
var SCRIPTDB_DIR = join(homedir(), ".scriptdb");
|
|
508
306
|
var PID_FILE = join(SCRIPTDB_DIR, "scriptdb.pid");
|
|
509
307
|
var LOG_FILE = join(SCRIPTDB_DIR, "scriptdb.log");
|
|
@@ -629,7 +427,7 @@ async function statusCommand() {
|
|
|
629
427
|
console.log(` PID: ${pid}`);
|
|
630
428
|
console.log(` Logs: ${LOG_FILE}`);
|
|
631
429
|
try {
|
|
632
|
-
const processes = await
|
|
430
|
+
const processes = await getProcessList();
|
|
633
431
|
const proc = processes.find((p) => p.pid === pid);
|
|
634
432
|
if (proc) {
|
|
635
433
|
if (proc.cpu !== undefined) {
|
|
@@ -765,7 +563,7 @@ function ensureScriptDBDir() {
|
|
|
765
563
|
if (!existsSync(PACKAGE_JSON)) {
|
|
766
564
|
const packageJsonContent = {
|
|
767
565
|
name: "scriptdb-workspace",
|
|
768
|
-
version: "1.0.
|
|
566
|
+
version: "1.0.6",
|
|
769
567
|
description: "ScriptDB workspace for custom scripts, services, and databases",
|
|
770
568
|
private: true,
|
|
771
569
|
devDependencies: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scriptdb/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "CLI tool to start and manage ScriptDB server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,8 +38,7 @@
|
|
|
38
38
|
"typescript": "^5.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@scriptdb/server": "^1.0.
|
|
42
|
-
"@scriptdb/client": "^1.0.
|
|
43
|
-
"ps-list": "^9.0.0"
|
|
41
|
+
"@scriptdb/server": "^1.0.6",
|
|
42
|
+
"@scriptdb/client": "^1.0.6"
|
|
44
43
|
}
|
|
45
44
|
}
|