node-plume 1.0.1
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/cli/index.mjs +639 -0
- package/dist/index.d.ts +918 -0
- package/dist/index.mjs +3749 -0
- package/dist/start/app.mjs +3087 -0
- package/dist/start/chunk-EOB3JR5Y.mjs +239 -0
- package/dist/start/chunk-FSUAIZUX.mjs +244 -0
- package/dist/start/chunk-T7M5RXO7.mjs +239 -0
- package/dist/start/index.mjs +8 -0
- package/package.json +54 -0
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// src/cli/index.ts
|
|
10
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
|
+
import { Command } from "commander";
|
|
13
|
+
import pc6 from "picocolors";
|
|
14
|
+
|
|
15
|
+
// src/cli/init.ts
|
|
16
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync2 } from "fs";
|
|
17
|
+
import { join as join2 } from "path";
|
|
18
|
+
import pc from "picocolors";
|
|
19
|
+
|
|
20
|
+
// src/service/config/index.ts
|
|
21
|
+
import { extname as extname3, resolve as resolve3 } from "path";
|
|
22
|
+
|
|
23
|
+
// src/service/config/default.ts
|
|
24
|
+
var plumeDefaultConfig = Object.freeze({
|
|
25
|
+
app: {
|
|
26
|
+
name: "Plume Bot",
|
|
27
|
+
version: "1.0.0"
|
|
28
|
+
},
|
|
29
|
+
log: {
|
|
30
|
+
level: "info",
|
|
31
|
+
timestamp: true
|
|
32
|
+
},
|
|
33
|
+
transport: {
|
|
34
|
+
host: "127.0.0.1",
|
|
35
|
+
port: 23333,
|
|
36
|
+
path: "/api",
|
|
37
|
+
wsPath: "/ws",
|
|
38
|
+
cors: true,
|
|
39
|
+
enableHttp: true,
|
|
40
|
+
enableWebSocket: true,
|
|
41
|
+
maxBodySize: 1024 * 1024
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
var plumeConfigSections = Object.freeze(
|
|
45
|
+
Object.keys(plumeDefaultConfig)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// src/service/config/init.ts
|
|
49
|
+
import { dirname, extname as extname2, resolve as resolve2 } from "path";
|
|
50
|
+
|
|
51
|
+
// src/service/config/file/config.ts
|
|
52
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
53
|
+
import { basename, extname, join, resolve } from "path";
|
|
54
|
+
|
|
55
|
+
// src/service/config/tools.ts
|
|
56
|
+
function stringifyJSON(data) {
|
|
57
|
+
return `${JSON.stringify(data, null, 2)}
|
|
58
|
+
`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/service/config/file/config.ts
|
|
62
|
+
function resolveConfigDirectory(path = "config") {
|
|
63
|
+
return resolve(path);
|
|
64
|
+
}
|
|
65
|
+
function ensureConfigDirectory(path = "config") {
|
|
66
|
+
const directory = resolveConfigDirectory(path);
|
|
67
|
+
mkdirSync(directory, { recursive: true });
|
|
68
|
+
return directory;
|
|
69
|
+
}
|
|
70
|
+
function ensureDefaultConfigFiles(path = "config") {
|
|
71
|
+
const directory = ensureConfigDirectory(path);
|
|
72
|
+
const createdFiles = [];
|
|
73
|
+
for (const section of plumeConfigSections) {
|
|
74
|
+
const filePath = join(directory, `${section}.json`);
|
|
75
|
+
if (existsSync(filePath)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
writeConfigObject(filePath, plumeDefaultConfig[section]);
|
|
79
|
+
createdFiles.push(filePath);
|
|
80
|
+
}
|
|
81
|
+
return createdFiles;
|
|
82
|
+
}
|
|
83
|
+
function writeConfigObject(path, data) {
|
|
84
|
+
writeFileSync(path, stringifyJSON(data), "utf-8");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/service/config/init.ts
|
|
88
|
+
function initConfig(options = {}) {
|
|
89
|
+
const basePath = options.path ?? "config";
|
|
90
|
+
const useConfigDirectory = extname2(basePath) === "";
|
|
91
|
+
const configDirectory = useConfigDirectory ? ensureConfigDirectory(basePath) : ensureConfigDirectory(dirname(resolve2(basePath)));
|
|
92
|
+
const createdConfigFiles = useConfigDirectory ? ensureDefaultConfigFiles(basePath) : [];
|
|
93
|
+
return {
|
|
94
|
+
configDirectory,
|
|
95
|
+
createdConfigFiles
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/service/log.ts
|
|
100
|
+
import { createLogger } from "@plume/logger";
|
|
101
|
+
var LogService = class _LogService {
|
|
102
|
+
logger;
|
|
103
|
+
options;
|
|
104
|
+
outputs = [];
|
|
105
|
+
buffer = [];
|
|
106
|
+
maxBufferSize = 1e3;
|
|
107
|
+
suspended = false;
|
|
108
|
+
pending = [];
|
|
109
|
+
constructor(options = {}) {
|
|
110
|
+
this.options = {
|
|
111
|
+
level: "info",
|
|
112
|
+
timestamp: true,
|
|
113
|
+
...options
|
|
114
|
+
};
|
|
115
|
+
this.logger = createLogger({
|
|
116
|
+
level: this.options.level,
|
|
117
|
+
prefix: this.options.prefix,
|
|
118
|
+
timestamp: this.options.timestamp
|
|
119
|
+
});
|
|
120
|
+
if (this.options.outputs) {
|
|
121
|
+
this.outputs = this.options.outputs;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
get level() {
|
|
125
|
+
return this.options.level ?? "info";
|
|
126
|
+
}
|
|
127
|
+
setLevel(level) {
|
|
128
|
+
this.options.level = level;
|
|
129
|
+
this.logger.setLevel(level);
|
|
130
|
+
}
|
|
131
|
+
suspend() {
|
|
132
|
+
this.suspended = true;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
resume() {
|
|
136
|
+
if (!this.suspended) {
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
this.suspended = false;
|
|
140
|
+
for (const entry of this.pending) {
|
|
141
|
+
this.writeEntry(entry);
|
|
142
|
+
}
|
|
143
|
+
this.pending = [];
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
debug(message, ...args) {
|
|
147
|
+
this.log("debug", message, ...args);
|
|
148
|
+
}
|
|
149
|
+
info(message, ...args) {
|
|
150
|
+
this.log("info", message, ...args);
|
|
151
|
+
}
|
|
152
|
+
warn(message, ...args) {
|
|
153
|
+
this.log("warn", message, ...args);
|
|
154
|
+
}
|
|
155
|
+
error(message, ...args) {
|
|
156
|
+
this.log("error", message, ...args);
|
|
157
|
+
}
|
|
158
|
+
log(level, message, ...args) {
|
|
159
|
+
if (level === "silent") return;
|
|
160
|
+
const entry = {
|
|
161
|
+
level,
|
|
162
|
+
message,
|
|
163
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
164
|
+
args,
|
|
165
|
+
prefix: this.options.prefix
|
|
166
|
+
};
|
|
167
|
+
this.buffer.push(entry);
|
|
168
|
+
if (this.buffer.length > this.maxBufferSize) {
|
|
169
|
+
this.buffer.shift();
|
|
170
|
+
}
|
|
171
|
+
if (this.suspended) {
|
|
172
|
+
this.pending.push(entry);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.writeEntry(entry);
|
|
176
|
+
}
|
|
177
|
+
writeEntry(entry) {
|
|
178
|
+
switch (entry.level) {
|
|
179
|
+
case "debug":
|
|
180
|
+
this.logger.debug(entry.message, ...entry.args);
|
|
181
|
+
break;
|
|
182
|
+
case "info":
|
|
183
|
+
this.logger.info(entry.message, ...entry.args);
|
|
184
|
+
break;
|
|
185
|
+
case "warn":
|
|
186
|
+
this.logger.warn(entry.message, ...entry.args);
|
|
187
|
+
break;
|
|
188
|
+
case "error":
|
|
189
|
+
this.logger.error(entry.message, ...entry.args);
|
|
190
|
+
break;
|
|
191
|
+
case "silent":
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
for (const output of this.outputs) {
|
|
195
|
+
this.writeToOutput(output, entry);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
writeToOutput(output, entry) {
|
|
199
|
+
switch (output.type) {
|
|
200
|
+
case "console":
|
|
201
|
+
break;
|
|
202
|
+
case "file":
|
|
203
|
+
break;
|
|
204
|
+
case "custom":
|
|
205
|
+
if (output.handler) {
|
|
206
|
+
output.handler(entry.level, entry.message, ...entry.args);
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
addOutput(output) {
|
|
212
|
+
this.outputs.push(output);
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
removeOutput(output) {
|
|
216
|
+
const index = this.outputs.indexOf(output);
|
|
217
|
+
if (index > -1) {
|
|
218
|
+
this.outputs.splice(index, 1);
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
child(prefix) {
|
|
224
|
+
return new _LogService({
|
|
225
|
+
...this.options,
|
|
226
|
+
prefix: this.options.prefix ? `${this.options.prefix}:${prefix}` : prefix
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
getBuffer() {
|
|
230
|
+
return [...this.buffer];
|
|
231
|
+
}
|
|
232
|
+
clearBuffer() {
|
|
233
|
+
this.buffer = [];
|
|
234
|
+
}
|
|
235
|
+
flush() {
|
|
236
|
+
for (const output of this.outputs) {
|
|
237
|
+
if (output.type === "file" && output.path) {
|
|
238
|
+
const fs = __require("fs");
|
|
239
|
+
const content = this.buffer.map((e) => `[${e.timestamp.toISOString()}] [${e.level.toUpperCase()}] ${e.prefix ? `[${e.prefix}] ` : ""}${e.message}`).join("\n");
|
|
240
|
+
fs.appendFileSync(output.path, content + "\n");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
var logService = new LogService();
|
|
246
|
+
|
|
247
|
+
// src/cli/init.ts
|
|
248
|
+
async function initCommand(_options) {
|
|
249
|
+
const cwd = process.cwd();
|
|
250
|
+
const pkgPath = join2(cwd, "package.json");
|
|
251
|
+
if (!existsSync2(pkgPath)) {
|
|
252
|
+
console.error(pc.red("Error: No package.json found in current directory"));
|
|
253
|
+
console.log(pc.gray("Run `pnpm init` first to create a package.json"));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
const configDir = join2(cwd, "config");
|
|
257
|
+
const tsconfigPath = join2(cwd, "tsconfig.json");
|
|
258
|
+
const srcDir = join2(cwd, "src");
|
|
259
|
+
const mainPath = join2(srcDir, "main.ts");
|
|
260
|
+
mkdirSync2(configDir, { recursive: true });
|
|
261
|
+
mkdirSync2(srcDir, { recursive: true });
|
|
262
|
+
const initResult = initConfig({
|
|
263
|
+
path: configDir
|
|
264
|
+
});
|
|
265
|
+
for (const filePath of initResult.createdConfigFiles) {
|
|
266
|
+
console.log(pc.green(`Created ${filePath.replace(`${cwd}\\`, "")}`));
|
|
267
|
+
}
|
|
268
|
+
if (!existsSync2(tsconfigPath)) {
|
|
269
|
+
writeFileSync2(tsconfigPath, JSON.stringify(createTsConfig(), null, 2));
|
|
270
|
+
console.log(pc.green("Created tsconfig.json"));
|
|
271
|
+
}
|
|
272
|
+
if (!existsSync2(mainPath)) {
|
|
273
|
+
writeFileSync2(mainPath, createMainTs());
|
|
274
|
+
console.log(pc.green("Created src/main.ts"));
|
|
275
|
+
}
|
|
276
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
277
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
278
|
+
if (!pkg.scripts.app) {
|
|
279
|
+
pkg.scripts.app = "tsx src/main.ts";
|
|
280
|
+
pkg.scripts.start = "node dist/main.js";
|
|
281
|
+
pkg.scripts.build = "tsup src/main.ts --format esm --sourcemap --clean";
|
|
282
|
+
}
|
|
283
|
+
if (!pkg.dependencies?.["@plume/core"] && !pkg.devDependencies?.["@plume/core"]) {
|
|
284
|
+
if (!pkg.dependencies) pkg.dependencies = {};
|
|
285
|
+
pkg.dependencies["@plume/core"] = "^1.0.0";
|
|
286
|
+
}
|
|
287
|
+
writeFileSync2(pkgPath, JSON.stringify(pkg, null, 2));
|
|
288
|
+
console.log(pc.green("Updated package.json"));
|
|
289
|
+
console.log(pc.cyan("\nNext steps:"));
|
|
290
|
+
console.log(pc.gray(" pnpm install"));
|
|
291
|
+
console.log(pc.gray(" pnpm app"));
|
|
292
|
+
}
|
|
293
|
+
function createTsConfig() {
|
|
294
|
+
return {
|
|
295
|
+
compilerOptions: {
|
|
296
|
+
target: "ES2022",
|
|
297
|
+
module: "ESNext",
|
|
298
|
+
moduleResolution: "bundler",
|
|
299
|
+
strict: true,
|
|
300
|
+
esModuleInterop: true,
|
|
301
|
+
skipLibCheck: true,
|
|
302
|
+
outDir: "dist",
|
|
303
|
+
rootDir: "src"
|
|
304
|
+
},
|
|
305
|
+
include: ["src/**/*"],
|
|
306
|
+
exclude: ["node_modules", "dist"]
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function createMainTs() {
|
|
310
|
+
return `import { App, start } from '@plume/core'
|
|
311
|
+
|
|
312
|
+
export const app = new App({
|
|
313
|
+
name: 'my-bot',
|
|
314
|
+
logger: {
|
|
315
|
+
level: 'debug'
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
app.on('message', async ({ ctx, event }) => {
|
|
320
|
+
console.log('Received message:', event.text)
|
|
321
|
+
|
|
322
|
+
if (event.text === 'ping') {
|
|
323
|
+
console.log('pong')
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
start({ app }).then(() => {
|
|
328
|
+
console.log('Bot started!')
|
|
329
|
+
})
|
|
330
|
+
`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/cli/start.ts
|
|
334
|
+
import { spawn } from "child_process";
|
|
335
|
+
import { join as join3 } from "path";
|
|
336
|
+
import { existsSync as existsSync3 } from "fs";
|
|
337
|
+
import pc2 from "picocolors";
|
|
338
|
+
async function startCommand() {
|
|
339
|
+
const cwd = process.cwd();
|
|
340
|
+
const mainPath = join3(cwd, "src", "main.ts");
|
|
341
|
+
if (!existsSync3(mainPath)) {
|
|
342
|
+
console.error(pc2.red("Error: src/main.ts not found"));
|
|
343
|
+
console.log(pc2.gray("Run `plume init` to create the project structure"));
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
console.log(pc2.cyan("Starting Plume...\n"));
|
|
347
|
+
await runCommand("pnpm", ["exec", "tsx", "src/main.ts"]);
|
|
348
|
+
}
|
|
349
|
+
async function appCommand() {
|
|
350
|
+
return startCommand();
|
|
351
|
+
}
|
|
352
|
+
function runCommand(command, args) {
|
|
353
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
354
|
+
const child = spawn(command, args, {
|
|
355
|
+
cwd: process.cwd(),
|
|
356
|
+
stdio: "inherit",
|
|
357
|
+
shell: process.platform === "win32"
|
|
358
|
+
});
|
|
359
|
+
child.on("exit", (code) => {
|
|
360
|
+
if (code === 0) {
|
|
361
|
+
resolvePromise();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
rejectPromise(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
365
|
+
});
|
|
366
|
+
child.on("error", rejectPromise);
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/cli/pm2.ts
|
|
371
|
+
import { spawn as spawn2 } from "child_process";
|
|
372
|
+
import { join as join4 } from "path";
|
|
373
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
374
|
+
import pc3 from "picocolors";
|
|
375
|
+
async function pm2Command() {
|
|
376
|
+
const cwd = process.cwd();
|
|
377
|
+
const mainPath = join4(cwd, "src", "main.ts");
|
|
378
|
+
if (!existsSync4(mainPath)) {
|
|
379
|
+
console.error(pc3.red("Error: src/main.ts not found"));
|
|
380
|
+
process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
const pkgPath = join4(cwd, "package.json");
|
|
383
|
+
let appName = "plume-app";
|
|
384
|
+
if (existsSync4(pkgPath)) {
|
|
385
|
+
try {
|
|
386
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
387
|
+
appName = pkg.name || appName;
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
console.log(pc3.cyan(`Starting ${appName} with PM2...
|
|
392
|
+
`));
|
|
393
|
+
await runCommand2("pnpm", ["exec", "pm2", "start", "tsx", "--name", appName, "--", "src/main.ts"]);
|
|
394
|
+
}
|
|
395
|
+
async function stopCommand() {
|
|
396
|
+
const cwd = process.cwd();
|
|
397
|
+
const pkgPath = join4(cwd, "package.json");
|
|
398
|
+
let appName = "plume-app";
|
|
399
|
+
if (existsSync4(pkgPath)) {
|
|
400
|
+
try {
|
|
401
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
402
|
+
appName = pkg.name || appName;
|
|
403
|
+
} catch {
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
console.log(pc3.cyan(`Stopping ${appName}...
|
|
407
|
+
`));
|
|
408
|
+
await runCommand2("pnpm", ["exec", "pm2", "stop", appName]);
|
|
409
|
+
}
|
|
410
|
+
async function restartCommand(options) {
|
|
411
|
+
const cwd = process.cwd();
|
|
412
|
+
const pkgPath = join4(cwd, "package.json");
|
|
413
|
+
let appName = "plume-app";
|
|
414
|
+
if (existsSync4(pkgPath)) {
|
|
415
|
+
try {
|
|
416
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
417
|
+
appName = pkg.name || appName;
|
|
418
|
+
} catch {
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
const args = ["exec", "pm2", "restart", appName];
|
|
422
|
+
if (options.force) {
|
|
423
|
+
args.push("--force");
|
|
424
|
+
}
|
|
425
|
+
console.log(pc3.cyan(`Restarting ${appName}...
|
|
426
|
+
`));
|
|
427
|
+
await runCommand2("pnpm", args);
|
|
428
|
+
}
|
|
429
|
+
async function logCommand() {
|
|
430
|
+
const cwd = process.cwd();
|
|
431
|
+
const pkgPath = join4(cwd, "package.json");
|
|
432
|
+
let appName = "plume-app";
|
|
433
|
+
if (existsSync4(pkgPath)) {
|
|
434
|
+
try {
|
|
435
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
436
|
+
appName = pkg.name || appName;
|
|
437
|
+
} catch {
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
await runCommand2("pnpm", ["exec", "pm2", "logs", appName]);
|
|
441
|
+
}
|
|
442
|
+
function runCommand2(command, args) {
|
|
443
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
444
|
+
const child = spawn2(command, args, {
|
|
445
|
+
cwd: process.cwd(),
|
|
446
|
+
stdio: "inherit",
|
|
447
|
+
shell: process.platform === "win32"
|
|
448
|
+
});
|
|
449
|
+
child.on("exit", (code) => {
|
|
450
|
+
if (code === 0) {
|
|
451
|
+
resolvePromise();
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
rejectPromise(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
455
|
+
});
|
|
456
|
+
child.on("error", rejectPromise);
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/cli/update.ts
|
|
461
|
+
import { spawn as spawn3 } from "child_process";
|
|
462
|
+
import pc4 from "picocolors";
|
|
463
|
+
async function updateCommand(options) {
|
|
464
|
+
console.log(pc4.cyan("Updating dependencies...\n"));
|
|
465
|
+
const args = ["update"];
|
|
466
|
+
if (options.force) {
|
|
467
|
+
args.push("--force");
|
|
468
|
+
}
|
|
469
|
+
await runCommand3("pnpm", args);
|
|
470
|
+
console.log(pc4.green("\nDependencies updated successfully!"));
|
|
471
|
+
}
|
|
472
|
+
function runCommand3(command, args) {
|
|
473
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
474
|
+
const child = spawn3(command, args, {
|
|
475
|
+
cwd: process.cwd(),
|
|
476
|
+
stdio: "inherit",
|
|
477
|
+
shell: process.platform === "win32"
|
|
478
|
+
});
|
|
479
|
+
child.on("exit", (code) => {
|
|
480
|
+
if (code === 0) {
|
|
481
|
+
resolvePromise();
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
rejectPromise(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
485
|
+
});
|
|
486
|
+
child.on("error", rejectPromise);
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// src/cli/build-dep.ts
|
|
491
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
492
|
+
import { join as join5 } from "path";
|
|
493
|
+
import pc5 from "picocolors";
|
|
494
|
+
async function buildDepCommand(action, dependency) {
|
|
495
|
+
const cwd = process.cwd();
|
|
496
|
+
const workspacePath = join5(cwd, "pnpm-workspace.yaml");
|
|
497
|
+
if (!existsSync5(workspacePath)) {
|
|
498
|
+
console.error(pc5.red("Error: pnpm-workspace.yaml not found"));
|
|
499
|
+
process.exit(1);
|
|
500
|
+
}
|
|
501
|
+
const content = readFileSync4(workspacePath, "utf-8");
|
|
502
|
+
const lines = content.split("\n");
|
|
503
|
+
let onlyBuiltStart = -1;
|
|
504
|
+
let onlyBuiltEnd = -1;
|
|
505
|
+
const deps = [];
|
|
506
|
+
for (let i = 0; i < lines.length; i++) {
|
|
507
|
+
if (lines[i].includes("onlyBuiltDependencies:")) {
|
|
508
|
+
onlyBuiltStart = i;
|
|
509
|
+
}
|
|
510
|
+
if (onlyBuiltStart !== -1 && onlyBuiltEnd === -1) {
|
|
511
|
+
if (lines[i].trim().startsWith("-")) {
|
|
512
|
+
const dep = lines[i].trim().slice(1).trim();
|
|
513
|
+
if (dep) deps.push(dep);
|
|
514
|
+
} else if (lines[i].trim() && !lines[i].includes("onlyBuiltDependencies")) {
|
|
515
|
+
onlyBuiltEnd = i;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
switch (action) {
|
|
520
|
+
case "ls":
|
|
521
|
+
case "list":
|
|
522
|
+
console.log(pc5.cyan("Build dependencies:"));
|
|
523
|
+
if (deps.length === 0) {
|
|
524
|
+
console.log(pc5.gray(" (none)"));
|
|
525
|
+
} else {
|
|
526
|
+
deps.forEach((dep) => console.log(pc5.green(` - ${dep}`)));
|
|
527
|
+
}
|
|
528
|
+
break;
|
|
529
|
+
case "add":
|
|
530
|
+
if (!dependency) {
|
|
531
|
+
console.error(pc5.red("Error: Dependency name required for add action"));
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
const depsToAdd = dependency.split(",").map((d) => d.trim()).filter(Boolean);
|
|
535
|
+
for (const dep of depsToAdd) {
|
|
536
|
+
if (!deps.includes(dep)) {
|
|
537
|
+
deps.push(dep);
|
|
538
|
+
console.log(pc5.green(`Added: ${dep}`));
|
|
539
|
+
} else {
|
|
540
|
+
console.log(pc5.yellow(`Already exists: ${dep}`));
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
updateWorkspaceFile(workspacePath, content, deps);
|
|
544
|
+
break;
|
|
545
|
+
case "rm":
|
|
546
|
+
case "remove":
|
|
547
|
+
if (!dependency) {
|
|
548
|
+
console.error(pc5.red("Error: Dependency name required for rm action"));
|
|
549
|
+
process.exit(1);
|
|
550
|
+
}
|
|
551
|
+
const depsToRemove = dependency.split(",").map((d) => d.trim()).filter(Boolean);
|
|
552
|
+
for (const dep of depsToRemove) {
|
|
553
|
+
const index = deps.indexOf(dep);
|
|
554
|
+
if (index !== -1) {
|
|
555
|
+
deps.splice(index, 1);
|
|
556
|
+
console.log(pc5.green(`Removed: ${dep}`));
|
|
557
|
+
} else {
|
|
558
|
+
console.log(pc5.yellow(`Not found: ${dep}`));
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
updateWorkspaceFile(workspacePath, content, deps);
|
|
562
|
+
break;
|
|
563
|
+
default:
|
|
564
|
+
console.error(pc5.red(`Error: Unknown action "${action}". Use: add, rm, or ls`));
|
|
565
|
+
process.exit(1);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
function updateWorkspaceFile(path, content, deps) {
|
|
569
|
+
const lines = content.split("\n");
|
|
570
|
+
let onlyBuiltStart = -1;
|
|
571
|
+
let onlyBuiltEnd = -1;
|
|
572
|
+
for (let i = 0; i < lines.length; i++) {
|
|
573
|
+
if (lines[i].includes("onlyBuiltDependencies:")) {
|
|
574
|
+
onlyBuiltStart = i;
|
|
575
|
+
}
|
|
576
|
+
if (onlyBuiltStart !== -1 && onlyBuiltEnd === -1) {
|
|
577
|
+
if (lines[i].trim() && !lines[i].trim().startsWith("-") && !lines[i].includes("onlyBuiltDependencies")) {
|
|
578
|
+
onlyBuiltEnd = i;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (onlyBuiltStart === -1) {
|
|
583
|
+
lines.push("onlyBuiltDependencies:");
|
|
584
|
+
onlyBuiltStart = lines.length - 1;
|
|
585
|
+
onlyBuiltEnd = lines.length;
|
|
586
|
+
}
|
|
587
|
+
if (onlyBuiltEnd === -1) {
|
|
588
|
+
onlyBuiltEnd = lines.length;
|
|
589
|
+
}
|
|
590
|
+
const newLines = [
|
|
591
|
+
...lines.slice(0, onlyBuiltStart + 1),
|
|
592
|
+
...deps.map((dep) => ` - ${dep}`),
|
|
593
|
+
...lines.slice(onlyBuiltEnd)
|
|
594
|
+
];
|
|
595
|
+
writeFileSync3(path, newLines.join("\n"));
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/cli/index.ts
|
|
599
|
+
function getVersion() {
|
|
600
|
+
try {
|
|
601
|
+
const file = fileURLToPath(new URL("../../package.json", import.meta.url));
|
|
602
|
+
const packageJson = JSON.parse(readFileSync5(file, "utf-8"));
|
|
603
|
+
return packageJson.version;
|
|
604
|
+
} catch {
|
|
605
|
+
return "unknown";
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
var program = new Command();
|
|
609
|
+
program.name("plume").description("Modern CLI for developing and running Plume projects").version(getVersion(), "-v, --version", "\u663E\u793A\u7248\u672C\u53F7");
|
|
610
|
+
program.command("init").description("\u521D\u59CB\u5316 Plume \u9879\u76EE").option("-f, --force", "\u5F3A\u5236\u521D\u59CB\u5316\uFF0C\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u914D\u7F6E\u6587\u4EF6").option("-d, --dev", "\u5F00\u53D1\u6A21\u5F0F\u521D\u59CB\u5316").action((options) => {
|
|
611
|
+
process.env.PLUME_CLI = "true";
|
|
612
|
+
if (options.dev) {
|
|
613
|
+
process.env.NODE_ENV = "development";
|
|
614
|
+
}
|
|
615
|
+
initCommand(options);
|
|
616
|
+
});
|
|
617
|
+
program.command(".").description("\u524D\u53F0\u542F\u52A8").action(startCommand);
|
|
618
|
+
program.command("app").description("\u524D\u53F0\u542F\u52A8").action(appCommand);
|
|
619
|
+
program.command("start").description("\u524D\u53F0\u542F\u52A8").action(startCommand);
|
|
620
|
+
program.command("pm2").description("\u540E\u53F0\u8FD0\u884C").action(pm2Command);
|
|
621
|
+
program.command("stop").description("\u505C\u6B62\u540E\u53F0\u670D\u52A1").action(stopCommand);
|
|
622
|
+
program.command("rs").alias("restart").description("\u91CD\u542F\u540E\u53F0\u670D\u52A1").option("-f, --force", "\u5F3A\u5236\u91CD\u542F").action((options) => restartCommand(options));
|
|
623
|
+
program.command("log").alias("logs").description("\u67E5\u770B\u65E5\u5FD7").action(logCommand);
|
|
624
|
+
program.command("up").description("\u66F4\u65B0\u63D2\u4EF6").option("-f, --force", "\u5F3A\u5236\u66F4\u65B0").option("-s, --serial", "\u4E32\u884C\u66F4\u65B0").action((options) => updateCommand(options));
|
|
625
|
+
program.command("b").alias("allow-build").description("\u6784\u5EFA\u4F9D\u8D56\u7BA1\u7406 (pnpm v10.x)").argument("<action>", "\u64CD\u4F5C\u7C7B\u578B: add, rm, ls").argument("[dependency]", "\u4F9D\u8D56\u5305\u540D\u79F0 (add/rm\u64CD\u4F5C\u9700\u8981\uFF0C\u591A\u4E2A\u4F7F\u7528\u9017\u53F7\u5206\u5272)").action((action, dependency) => {
|
|
626
|
+
if (action === "add" && dependency) {
|
|
627
|
+
buildDepCommand("add", dependency);
|
|
628
|
+
} else if (action === "rm" && dependency) {
|
|
629
|
+
buildDepCommand("rm", dependency);
|
|
630
|
+
} else if (action === "ls") {
|
|
631
|
+
buildDepCommand("ls");
|
|
632
|
+
} else {
|
|
633
|
+
console.log(pc6.red("\u65E0\u6548\u7684\u547D\u4EE4\u3002\u6709\u6548\u547D\u4EE4: add <dependency>, rm <dependency>, ls"));
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
if (!process.argv?.[2]) {
|
|
637
|
+
process.argv.push("-h");
|
|
638
|
+
}
|
|
639
|
+
program.parse(process.argv);
|