project-runner 0.1.0 → 0.1.2

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 ADDED
@@ -0,0 +1,648 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { resolve } from "path";
5
+
6
+ // src/utils/log.ts
7
+ var colors = {
8
+ reset: "\x1B[0m",
9
+ bold: "\x1B[1m",
10
+ dim: "\x1B[2m",
11
+ red: "\x1B[31m",
12
+ green: "\x1B[32m",
13
+ yellow: "\x1B[33m",
14
+ blue: "\x1B[34m",
15
+ magenta: "\x1B[35m",
16
+ cyan: "\x1B[36m",
17
+ white: "\x1B[37m",
18
+ gray: "\x1B[90m"
19
+ };
20
+ var isVerbose = false;
21
+ function setVerbose(verbose) {
22
+ isVerbose = verbose;
23
+ }
24
+ function log(message) {
25
+ if (isVerbose) {
26
+ console.log(`${colors.cyan}[pr]${colors.reset} ${message}`);
27
+ }
28
+ }
29
+ function info(message) {
30
+ console.log(`${colors.cyan}[pr]${colors.reset} ${message}`);
31
+ }
32
+ function success(message) {
33
+ console.log(`${colors.green}\u2713${colors.reset} ${message}`);
34
+ }
35
+ function warn(message) {
36
+ console.log(`${colors.yellow}\u26A0${colors.reset} ${message}`);
37
+ }
38
+ function error(message) {
39
+ console.error(`${colors.red}\u2717${colors.reset} ${message}`);
40
+ }
41
+ function execLog(command) {
42
+ console.log(`${colors.dim}>${colors.reset} ${colors.bold}${command}${colors.reset}`);
43
+ }
44
+ function newline() {
45
+ console.log();
46
+ }
47
+
48
+ // src/runner/executor.ts
49
+ import { spawn } from "child_process";
50
+ var currentProcess = null;
51
+ async function execute(cmd, options = {}) {
52
+ const { cwd = process.cwd(), env, silent = false } = options;
53
+ if (!silent) {
54
+ execLog(cmd.join(" "));
55
+ }
56
+ return new Promise((resolve2, reject) => {
57
+ const isWindows = process.platform === "win32";
58
+ const command = cmd[0] || "";
59
+ const args = cmd.slice(1);
60
+ currentProcess = spawn(command, args, {
61
+ cwd,
62
+ env: { ...process.env, ...env },
63
+ stdio: "inherit",
64
+ shell: isWindows
65
+ });
66
+ const proc = currentProcess;
67
+ proc.on("close", (code) => {
68
+ currentProcess = null;
69
+ resolve2(code ?? 0);
70
+ });
71
+ proc.on("error", (err) => {
72
+ currentProcess = null;
73
+ reject(err);
74
+ });
75
+ });
76
+ }
77
+ function setupSignalHandlers() {
78
+ process.on("SIGINT", () => {
79
+ if (currentProcess) {
80
+ currentProcess.kill();
81
+ }
82
+ process.exit(0);
83
+ });
84
+ process.on("SIGTERM", () => {
85
+ if (currentProcess) {
86
+ currentProcess.kill();
87
+ }
88
+ process.exit(0);
89
+ });
90
+ }
91
+
92
+ // src/analyzer/index.ts
93
+ import { readFile as readFile3, stat as stat4 } from "fs/promises";
94
+ import { join as join4 } from "path";
95
+
96
+ // src/analyzer/package-manager.ts
97
+ import { readFile, stat } from "fs/promises";
98
+ import { join } from "path";
99
+ var LOCKFILE_MAP = {
100
+ "bun.lockb": "bun",
101
+ "bun.lock": "bun",
102
+ "pnpm-lock.yaml": "pnpm",
103
+ "yarn.lock": "yarn",
104
+ "package-lock.json": "npm"
105
+ };
106
+ async function detectPackageManager(projectDir) {
107
+ const packageJsonPath = join(projectDir, "package.json");
108
+ const packageJson = await readPackageJson(packageJsonPath);
109
+ if (!packageJson) {
110
+ return { name: "npm", source: "default" };
111
+ }
112
+ if (packageJson.packageManager) {
113
+ const match = packageJson.packageManager.match(/^(npm|yarn|pnpm|bun)@(.+)$/);
114
+ if (match) {
115
+ return {
116
+ name: match[1],
117
+ version: match[2],
118
+ source: "packageManager"
119
+ };
120
+ }
121
+ }
122
+ if (packageJson.volta) {
123
+ for (const pm of ["pnpm", "yarn", "npm"]) {
124
+ if (packageJson.volta[pm]) {
125
+ return {
126
+ name: pm,
127
+ version: packageJson.volta[pm],
128
+ source: "volta"
129
+ };
130
+ }
131
+ }
132
+ }
133
+ for (const [lockfile, pm] of Object.entries(LOCKFILE_MAP)) {
134
+ const exists = await fileExists(join(projectDir, lockfile));
135
+ if (exists) {
136
+ return { name: pm, source: "lockfile" };
137
+ }
138
+ }
139
+ return { name: "npm", source: "default" };
140
+ }
141
+ function getRunCommand(pm, script) {
142
+ switch (pm) {
143
+ case "bun":
144
+ return ["bun", "run", script];
145
+ case "pnpm":
146
+ return ["pnpm", script];
147
+ case "yarn":
148
+ return ["yarn", script];
149
+ case "npm":
150
+ default:
151
+ return ["npm", "run", script];
152
+ }
153
+ }
154
+ function getInstallCommand(pm) {
155
+ switch (pm) {
156
+ case "bun":
157
+ return ["bun", "install"];
158
+ case "pnpm":
159
+ return ["pnpm", "install"];
160
+ case "yarn":
161
+ return ["yarn", "install"];
162
+ case "npm":
163
+ default:
164
+ return ["npm", "install"];
165
+ }
166
+ }
167
+ async function fileExists(path) {
168
+ try {
169
+ const stats = await stat(path);
170
+ return stats.isFile();
171
+ } catch {
172
+ return false;
173
+ }
174
+ }
175
+ async function readPackageJson(path) {
176
+ try {
177
+ const content = await readFile(path, "utf-8");
178
+ return JSON.parse(content);
179
+ } catch {
180
+ }
181
+ return null;
182
+ }
183
+
184
+ // src/analyzer/scripts.ts
185
+ import { readFile as readFile2, stat as stat2 } from "fs/promises";
186
+ import { join as join2 } from "path";
187
+ var DEV_PATTERNS = ["dev", "serve", "start:dev", "develop", "watch"];
188
+ var TEST_PATTERNS = ["test", "test:unit", "test:all", "spec"];
189
+ var BUILD_PATTERNS = ["build", "compile", "bundle", "dist"];
190
+ var START_PATTERNS = ["start", "serve", "preview", "production"];
191
+ async function fileExists2(path) {
192
+ try {
193
+ const stats = await stat2(path);
194
+ return stats.isFile();
195
+ } catch {
196
+ return false;
197
+ }
198
+ }
199
+ async function analyzeScripts(projectDir) {
200
+ const packageJsonPath = join2(projectDir, "package.json");
201
+ try {
202
+ if (!await fileExists2(packageJsonPath)) {
203
+ return null;
204
+ }
205
+ const content = await readFile2(packageJsonPath, "utf-8");
206
+ const packageJson = JSON.parse(content);
207
+ const scripts = packageJson.scripts || {};
208
+ const detected = {
209
+ dev: findMatchingScript(scripts, DEV_PATTERNS),
210
+ test: findMatchingScript(scripts, TEST_PATTERNS),
211
+ build: findMatchingScript(scripts, BUILD_PATTERNS),
212
+ start: findMatchingScript(scripts, START_PATTERNS)
213
+ };
214
+ return { scripts, detected };
215
+ } catch {
216
+ return null;
217
+ }
218
+ }
219
+ function findMatchingScript(scripts, patterns) {
220
+ const scriptNames = Object.keys(scripts);
221
+ for (const pattern of patterns) {
222
+ if (scripts[pattern]) {
223
+ return pattern;
224
+ }
225
+ }
226
+ for (const pattern of patterns) {
227
+ const fuzzyMatch = scriptNames.find((name) => {
228
+ if (!name.toLowerCase().includes(pattern.toLowerCase())) {
229
+ return false;
230
+ }
231
+ const scriptContent = scripts[name].toLowerCase();
232
+ if (scriptContent.includes("npm i") || scriptContent.includes("npm install") || scriptContent.includes("yarn install") || scriptContent.includes("pnpm install") || scriptContent.includes("bun install")) {
233
+ return false;
234
+ }
235
+ return true;
236
+ });
237
+ if (fuzzyMatch) {
238
+ return fuzzyMatch;
239
+ }
240
+ }
241
+ return void 0;
242
+ }
243
+
244
+ // src/analyzer/dependencies.ts
245
+ import { stat as stat3 } from "fs/promises";
246
+ import { join as join3 } from "path";
247
+ var LOCKFILES = [
248
+ "bun.lockb",
249
+ "bun.lock",
250
+ "pnpm-lock.yaml",
251
+ "yarn.lock",
252
+ "package-lock.json"
253
+ ];
254
+ async function checkDependencyStatus(projectDir) {
255
+ const nodeModulesPath = join3(projectDir, "node_modules");
256
+ const nodeModulesExists = await directoryExists(nodeModulesPath);
257
+ if (!nodeModulesExists) {
258
+ return {
259
+ hasNodeModules: false,
260
+ needsInstall: true,
261
+ reason: "node_modules \u4E0D\u5B58\u5728"
262
+ };
263
+ }
264
+ const lockfilePath = await findLockfile(projectDir);
265
+ if (lockfilePath) {
266
+ const lockfileMtime = await getModifiedTime(lockfilePath);
267
+ const nodeModulesMtime2 = await getModifiedTime(nodeModulesPath);
268
+ if (lockfileMtime && nodeModulesMtime2 && lockfileMtime > nodeModulesMtime2) {
269
+ return {
270
+ hasNodeModules: true,
271
+ needsInstall: true,
272
+ reason: "lockfile \u5DF2\u66F4\u65B0"
273
+ };
274
+ }
275
+ }
276
+ const packageJsonPath = join3(projectDir, "package.json");
277
+ const packageJsonMtime = await getModifiedTime(packageJsonPath);
278
+ const nodeModulesMtime = await getModifiedTime(nodeModulesPath);
279
+ if (packageJsonMtime && nodeModulesMtime && packageJsonMtime > nodeModulesMtime) {
280
+ return {
281
+ hasNodeModules: true,
282
+ needsInstall: true,
283
+ reason: "package.json \u5DF2\u66F4\u65B0"
284
+ };
285
+ }
286
+ return {
287
+ hasNodeModules: true,
288
+ needsInstall: false
289
+ };
290
+ }
291
+ async function findLockfile(projectDir) {
292
+ for (const lockfile of LOCKFILES) {
293
+ const lockfilePath = join3(projectDir, lockfile);
294
+ if (await fileExists3(lockfilePath)) {
295
+ return lockfilePath;
296
+ }
297
+ }
298
+ return null;
299
+ }
300
+ async function getModifiedTime(path) {
301
+ try {
302
+ const stats = await stat3(path);
303
+ return stats.mtimeMs;
304
+ } catch {
305
+ return null;
306
+ }
307
+ }
308
+ async function directoryExists(path) {
309
+ try {
310
+ const stats = await stat3(path);
311
+ return stats.isDirectory();
312
+ } catch {
313
+ return false;
314
+ }
315
+ }
316
+ async function fileExists3(path) {
317
+ try {
318
+ const stats = await stat3(path);
319
+ return stats.isFile();
320
+ } catch {
321
+ return false;
322
+ }
323
+ }
324
+
325
+ // src/analyzer/index.ts
326
+ async function fileExists4(path) {
327
+ try {
328
+ const stats = await stat4(path);
329
+ return stats.isFile();
330
+ } catch {
331
+ return false;
332
+ }
333
+ }
334
+ async function analyzeProject(projectDir) {
335
+ const packageJsonPath = join4(projectDir, "package.json");
336
+ const hasPackageJson = await fileExists4(packageJsonPath);
337
+ if (!hasPackageJson) {
338
+ return {
339
+ type: "unknown",
340
+ packageManager: { name: "npm", source: "default" },
341
+ scripts: null,
342
+ dependencies: { hasNodeModules: false, needsInstall: false }
343
+ };
344
+ }
345
+ let packageJson = {};
346
+ try {
347
+ const content = await readFile3(packageJsonPath, "utf-8");
348
+ packageJson = JSON.parse(content);
349
+ } catch {
350
+ }
351
+ const [packageManager, scripts, dependencies] = await Promise.all([
352
+ detectPackageManager(projectDir),
353
+ analyzeScripts(projectDir),
354
+ checkDependencyStatus(projectDir)
355
+ ]);
356
+ return {
357
+ type: "nodejs",
358
+ packageManager,
359
+ scripts,
360
+ dependencies,
361
+ name: packageJson.name,
362
+ version: packageJson.version,
363
+ description: packageJson.description
364
+ };
365
+ }
366
+
367
+ // src/cli/run.ts
368
+ async function runCommand(projectDir, options = {}) {
369
+ const { noInstall = false, forceInstall = false, scriptType = "dev" } = options;
370
+ log("\u6B63\u5728\u5206\u6790\u9879\u76EE...");
371
+ const project = await analyzeProject(projectDir);
372
+ if (project.type === "unknown") {
373
+ error("\u672A\u68C0\u6D4B\u5230\u9879\u76EE\u7C7B\u578B\u3002\u8BF7\u786E\u4FDD\u5F53\u524D\u76EE\u5F55\u5305\u542B package.json");
374
+ process.exit(1);
375
+ }
376
+ log(`\u9879\u76EE\u7C7B\u578B: ${project.type}`);
377
+ log(`\u5305\u7BA1\u7406\u5668: ${project.packageManager.name} (from ${project.packageManager.source})`);
378
+ if (!project.scripts) {
379
+ error("\u65E0\u6CD5\u8BFB\u53D6 package.json \u7684 scripts");
380
+ process.exit(1);
381
+ }
382
+ const scriptName = findScript(project, scriptType);
383
+ if (!scriptName) {
384
+ error(`\u672A\u627E\u5230 ${scriptType} \u76F8\u5173\u7684\u811A\u672C`);
385
+ showAvailableScripts(project);
386
+ process.exit(1);
387
+ }
388
+ log(`\u5C06\u6267\u884C\u811A\u672C: ${scriptName}`);
389
+ const shouldInstall = !noInstall && (forceInstall || project.dependencies.needsInstall);
390
+ if (shouldInstall) {
391
+ if (forceInstall) {
392
+ log("\u5F3A\u5236\u5B89\u88C5\u4F9D\u8D56...");
393
+ } else {
394
+ log(`\u4F9D\u8D56\u72B6\u6001: ${project.dependencies.reason || "\u9700\u8981\u5B89\u88C5"}`);
395
+ }
396
+ newline();
397
+ const installCmd = getInstallCommand(project.packageManager.name);
398
+ const installExitCode = await execute(installCmd, { cwd: projectDir });
399
+ if (installExitCode !== 0) {
400
+ error("\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25");
401
+ process.exit(installExitCode);
402
+ }
403
+ success("\u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210");
404
+ newline();
405
+ } else if (!noInstall) {
406
+ log("\u4F9D\u8D56\u72B6\u6001: \u5DF2\u662F\u6700\u65B0");
407
+ }
408
+ const runCmd = getRunCommand(project.packageManager.name, scriptName);
409
+ const exitCode = await execute(runCmd, { cwd: projectDir });
410
+ if (exitCode !== 0) {
411
+ process.exit(exitCode);
412
+ }
413
+ }
414
+ function findScript(project, scriptType) {
415
+ const scripts = project.scripts;
416
+ if (!scripts)
417
+ return void 0;
418
+ const detected = scripts.detected[scriptType];
419
+ if (detected) {
420
+ return detected;
421
+ }
422
+ if (scripts.scripts[scriptType]) {
423
+ return scriptType;
424
+ }
425
+ return void 0;
426
+ }
427
+ function showAvailableScripts(project) {
428
+ if (!project.scripts)
429
+ return;
430
+ const scriptNames = Object.keys(project.scripts.scripts);
431
+ if (scriptNames.length === 0) {
432
+ warn("package.json \u4E2D\u6CA1\u6709\u5B9A\u4E49\u4EFB\u4F55 scripts");
433
+ return;
434
+ }
435
+ info("\u53EF\u7528\u7684\u811A\u672C:");
436
+ for (const name of scriptNames) {
437
+ console.log(` - ${name}`);
438
+ }
439
+ console.log();
440
+ info("\u4F7F\u7528 qy <script> \u8FD0\u884C\u4EFB\u610F\u811A\u672C");
441
+ }
442
+
443
+ // src/cli/info.ts
444
+ async function infoCommand(projectDir) {
445
+ const project = await analyzeProject(projectDir);
446
+ if (project.type === "unknown") {
447
+ console.log(`${colors.red}\u2717${colors.reset} \u672A\u68C0\u6D4B\u5230\u9879\u76EE\u7C7B\u578B`);
448
+ console.log(" \u8BF7\u786E\u4FDD\u5F53\u524D\u76EE\u5F55\u5305\u542B package.json \u6216\u5176\u4ED6\u9879\u76EE\u914D\u7F6E\u6587\u4EF6");
449
+ return;
450
+ }
451
+ console.log();
452
+ console.log(`${colors.cyan}${colors.bold}pr - \u9879\u76EE\u5206\u6790\u7ED3\u679C${colors.reset}`);
453
+ console.log("\u2500".repeat(40));
454
+ if (project.name) {
455
+ console.log(`${colors.bold}\u9879\u76EE\u540D\u79F0:${colors.reset} ${project.name}`);
456
+ }
457
+ if (project.version) {
458
+ console.log(`${colors.bold}\u7248\u672C:${colors.reset} ${project.version}`);
459
+ }
460
+ if (project.description) {
461
+ console.log(`${colors.bold}\u63CF\u8FF0:${colors.reset} ${project.description}`);
462
+ }
463
+ console.log(`${colors.bold}\u9879\u76EE\u7C7B\u578B:${colors.reset} ${project.type}`);
464
+ const pm = project.packageManager;
465
+ let pmInfo = pm.name;
466
+ if (pm.version) {
467
+ pmInfo += `@${pm.version}`;
468
+ }
469
+ pmInfo += ` ${colors.dim}(${pm.source})${colors.reset}`;
470
+ console.log(`${colors.bold}\u5305\u7BA1\u7406\u5668:${colors.reset} ${pmInfo}`);
471
+ const deps = project.dependencies;
472
+ const depsStatus = deps.needsInstall ? `${colors.yellow}\u9700\u8981\u5B89\u88C5${colors.reset} (${deps.reason})` : `${colors.green}\u5DF2\u5C31\u7EEA${colors.reset}`;
473
+ console.log(`${colors.bold}\u4F9D\u8D56\u72B6\u6001:${colors.reset} ${depsStatus}`);
474
+ console.log();
475
+ if (project.scripts) {
476
+ const { scripts, detected } = project.scripts;
477
+ console.log(`${colors.bold}\u8BC6\u522B\u7684\u547D\u4EE4:${colors.reset}`);
478
+ if (detected.dev) {
479
+ console.log(` ${colors.green}pr run${colors.reset} \u2192 ${pm.name} ${detected.dev}`);
480
+ }
481
+ if (detected.test) {
482
+ console.log(` ${colors.green}pr test${colors.reset} \u2192 ${pm.name} ${detected.test}`);
483
+ }
484
+ if (detected.build) {
485
+ console.log(` ${colors.green}pr build${colors.reset} \u2192 ${pm.name} ${detected.build}`);
486
+ }
487
+ if (detected.start) {
488
+ console.log(` ${colors.green}pr start${colors.reset} \u2192 ${pm.name} ${detected.start}`);
489
+ }
490
+ console.log();
491
+ const allScripts = Object.keys(scripts);
492
+ if (allScripts.length > 0) {
493
+ console.log(`${colors.bold}\u6240\u6709\u811A\u672C:${colors.reset}`);
494
+ for (const name of allScripts) {
495
+ const cmd = scripts[name];
496
+ const displayCmd = cmd.length > 40 ? cmd.slice(0, 40) + "..." : cmd;
497
+ console.log(` ${colors.cyan}${name}${colors.reset} ${colors.dim}\u2192 ${displayCmd}${colors.reset}`);
498
+ }
499
+ }
500
+ }
501
+ console.log();
502
+ }
503
+
504
+ // src/cli/script.ts
505
+ async function scriptCommand(projectDir, scriptName) {
506
+ const project = await analyzeProject(projectDir);
507
+ if (project.type === "unknown") {
508
+ error("\u672A\u68C0\u6D4B\u5230\u9879\u76EE\u7C7B\u578B\u3002\u8BF7\u786E\u4FDD\u5F53\u524D\u76EE\u5F55\u5305\u542B package.json");
509
+ process.exit(1);
510
+ }
511
+ if (!project.scripts) {
512
+ error("\u65E0\u6CD5\u8BFB\u53D6 package.json \u7684 scripts");
513
+ process.exit(1);
514
+ }
515
+ const scripts = project.scripts.scripts;
516
+ if (!(scriptName in scripts)) {
517
+ error(`\u811A\u672C "${scriptName}" \u4E0D\u5B58\u5728`);
518
+ console.log();
519
+ showAvailableScripts2(scripts);
520
+ process.exit(1);
521
+ }
522
+ log(`\u5305\u7BA1\u7406\u5668: ${project.packageManager.name}`);
523
+ log(`\u6267\u884C\u811A\u672C: ${scriptName}`);
524
+ const runCmd = getRunCommand(project.packageManager.name, scriptName);
525
+ const exitCode = await execute(runCmd, { cwd: projectDir });
526
+ if (exitCode !== 0) {
527
+ process.exit(exitCode);
528
+ }
529
+ }
530
+ function showAvailableScripts2(scripts) {
531
+ const scriptNames = Object.keys(scripts);
532
+ if (scriptNames.length === 0) {
533
+ info("package.json \u4E2D\u6CA1\u6709\u5B9A\u4E49\u4EFB\u4F55\u811A\u672C");
534
+ return;
535
+ }
536
+ info("\u53EF\u7528\u7684\u811A\u672C:");
537
+ for (const name of scriptNames) {
538
+ console.log(` - ${name}`);
539
+ }
540
+ }
541
+
542
+ // src/index.ts
543
+ var VERSION = "0.1.2";
544
+ function parseArgs(args) {
545
+ const options = {
546
+ verbose: false,
547
+ dir: process.cwd(),
548
+ noInstall: false,
549
+ install: false
550
+ };
551
+ let command = "";
552
+ const remainingArgs = [];
553
+ let i = 0;
554
+ while (i < args.length) {
555
+ const arg = args[i];
556
+ if (arg === "-v" || arg === "--verbose") {
557
+ options.verbose = true;
558
+ } else if (arg === "-d" || arg === "--dir") {
559
+ options.dir = resolve(args[++i] || ".");
560
+ } else if (arg === "--no-install") {
561
+ options.noInstall = true;
562
+ } else if (arg === "-i" || arg === "--install") {
563
+ options.install = true;
564
+ } else if (arg === "-h" || arg === "--help") {
565
+ command = "help";
566
+ } else if (arg === "-V" || arg === "--version") {
567
+ command = "version";
568
+ } else if (!arg.startsWith("-")) {
569
+ if (!command) {
570
+ command = arg;
571
+ } else {
572
+ remainingArgs.push(arg);
573
+ }
574
+ }
575
+ i++;
576
+ }
577
+ return { command, options, args: remainingArgs };
578
+ }
579
+ function showHelp() {
580
+ console.log(`
581
+ ${"\x1B[36m"}pr${"\x1B[0m"} v${VERSION} - \u96F6\u914D\u7F6E\u667A\u80FD\u9879\u76EE\u8FD0\u884C\u5668 (project-runner)
582
+
583
+ ${"\x1B[1m"}\u7528\u6CD5:${"\x1B[0m"} pr <command> [options]
584
+
585
+ ${"\x1B[1m"}\u547D\u4EE4:${"\x1B[0m"}
586
+ run \u5B8C\u6574\u6D41\u7A0B\uFF1A\u68C0\u6D4B \u2192 install \u2192 \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668
587
+ test \u8FD0\u884C\u6D4B\u8BD5
588
+ build \u6784\u5EFA\u9879\u76EE
589
+ start \u751F\u4EA7\u6A21\u5F0F\u542F\u52A8
590
+ info \u663E\u793A\u9879\u76EE\u5206\u6790\u7ED3\u679C
591
+ <script> \u8FD0\u884C package.json \u4E2D\u7684\u4EFB\u610F\u811A\u672C
592
+
593
+ ${"\x1B[1m"}\u9009\u9879:${"\x1B[0m"}
594
+ -v, --verbose \u663E\u793A\u8BE6\u7EC6\u68C0\u6D4B\u8FC7\u7A0B
595
+ -d, --dir <path> \u6307\u5B9A\u9879\u76EE\u76EE\u5F55 (\u9ED8\u8BA4: \u5F53\u524D\u76EE\u5F55)
596
+ -i, --install \u5F3A\u5236\u6267\u884C\u4F9D\u8D56\u5B89\u88C5
597
+ --no-install \u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5\u6B65\u9AA4
598
+ -h, --help \u663E\u793A\u5E2E\u52A9\u4FE1\u606F
599
+ -V, --version \u663E\u793A\u7248\u672C\u53F7
600
+
601
+ ${"\x1B[1m"}\u793A\u4F8B:${"\x1B[0m"}
602
+ pr run \u4E00\u952E\u542F\u52A8\u9879\u76EE
603
+ pr run -i \u5F3A\u5236\u5B89\u88C5\u4F9D\u8D56\u540E\u542F\u52A8
604
+ pr run -v \u663E\u793A\u8BE6\u7EC6\u68C0\u6D4B\u8FC7\u7A0B
605
+ pr test \u8FD0\u884C\u6D4B\u8BD5
606
+ pr lint \u8FD0\u884C lint \u811A\u672C
607
+ pr info \u67E5\u770B\u9879\u76EE\u4FE1\u606F
608
+ `);
609
+ }
610
+ function showVersion() {
611
+ console.log(`pr v${VERSION}`);
612
+ }
613
+ async function main() {
614
+ setupSignalHandlers();
615
+ const { command, options, args } = parseArgs(process.argv.slice(2));
616
+ setVerbose(options.verbose);
617
+ switch (command) {
618
+ case "":
619
+ case "help":
620
+ showHelp();
621
+ break;
622
+ case "version":
623
+ showVersion();
624
+ break;
625
+ case "run":
626
+ await runCommand(options.dir, { noInstall: options.noInstall, forceInstall: options.install, scriptType: "dev" });
627
+ break;
628
+ case "test":
629
+ await runCommand(options.dir, { noInstall: true, scriptType: "test" });
630
+ break;
631
+ case "build":
632
+ await runCommand(options.dir, { noInstall: true, scriptType: "build" });
633
+ break;
634
+ case "start":
635
+ await runCommand(options.dir, { noInstall: true, scriptType: "start" });
636
+ break;
637
+ case "info":
638
+ await infoCommand(options.dir);
639
+ break;
640
+ default:
641
+ await scriptCommand(options.dir, command);
642
+ break;
643
+ }
644
+ }
645
+ main().catch((err) => {
646
+ error(err.message);
647
+ process.exit(1);
648
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-runner",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "零配置智能项目运行器 - 一键运行任意 Node.js 项目",
5
5
  "author": "liangzhenqi",
6
6
  "license": "MIT",
@@ -20,23 +20,23 @@
20
20
  "build",
21
21
  "test"
22
22
  ],
23
- "module": "src/index.ts",
24
23
  "type": "module",
25
24
  "bin": {
26
- "pr": "src/index.ts"
25
+ "pr": "dist/index.js"
27
26
  },
28
27
  "files": [
29
- "src",
28
+ "dist",
30
29
  "README.md"
31
30
  ],
32
31
  "scripts": {
33
32
  "dev": "bun run src/index.ts",
34
- "build": "bun build src/index.ts --outdir dist --target node",
35
- "link": "bun link",
36
- "prepublishOnly": "echo 'Ready to publish'"
33
+ "build": "node build.mjs",
34
+ "prepublishOnly": "npm run build"
37
35
  },
38
36
  "devDependencies": {
39
- "@types/bun": "latest"
37
+ "@types/bun": "latest",
38
+ "@types/node": "^20",
39
+ "esbuild": "^0.20.0"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "typescript": "^5"