@lightfish/cli 0.0.4 → 0.0.5
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/lightfish.js +407 -9
- package/package.json +4 -1
package/dist/lightfish.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/lightfish.ts
|
|
4
4
|
import cac from "cac";
|
|
5
|
-
import { execa as
|
|
5
|
+
import { execa as execa4 } from "execa";
|
|
6
6
|
|
|
7
7
|
// src/commands/create.ts
|
|
8
8
|
import path4 from "path";
|
|
@@ -364,30 +364,409 @@ async function createProject(options = {}) {
|
|
|
364
364
|
return resolvedOptions;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
// src/
|
|
367
|
+
// src/commands/publish.ts
|
|
368
|
+
import fs8 from "fs";
|
|
369
|
+
import path8 from "path";
|
|
370
|
+
|
|
371
|
+
// src/utils/env.ts
|
|
368
372
|
import fs5 from "fs";
|
|
369
373
|
import path5 from "path";
|
|
374
|
+
import { parse } from "dotenv";
|
|
375
|
+
var DEFAULT_BASE_ROOT = "https://lf-frontend.oss-cn-beijing.aliyuncs.com";
|
|
376
|
+
function loadDotenv({ cwd, envPath }) {
|
|
377
|
+
let merged;
|
|
378
|
+
if (envPath) {
|
|
379
|
+
merged = readEnvFile(path5.resolve(cwd, envPath));
|
|
380
|
+
} else {
|
|
381
|
+
const base = readEnvFile(path5.resolve(cwd, ".env"));
|
|
382
|
+
const local = readEnvFile(path5.resolve(cwd, ".env.local"));
|
|
383
|
+
merged = { ...base, ...local };
|
|
384
|
+
}
|
|
385
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
386
|
+
if (process.env[key] === void 0) {
|
|
387
|
+
process.env[key] = value;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function readEnvFile(file) {
|
|
392
|
+
if (!fs5.existsSync(file)) return {};
|
|
393
|
+
return parse(fs5.readFileSync(file, "utf8"));
|
|
394
|
+
}
|
|
395
|
+
function getRequiredEnvNames({ notify, serverDetected }) {
|
|
396
|
+
const required = ["OSS_REGION", "OSS_BUCKET", "OSS_ACCESS_KEYID", "OSS_ACCESS_KEYSECRECT"];
|
|
397
|
+
if (notify) required.push("DEPLOY_API_URL");
|
|
398
|
+
if (serverDetected) required.push("DATABASE_URL");
|
|
399
|
+
return required;
|
|
400
|
+
}
|
|
401
|
+
function resolvePublishEnv(options, env = process.env) {
|
|
402
|
+
const required = getRequiredEnvNames(options);
|
|
403
|
+
const missing = required.filter((name) => !env[name]);
|
|
404
|
+
if (missing.length > 0) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
`\u7F3A\u5C11\u5FC5\u9700\u73AF\u5883\u53D8\u91CF:${missing.join(", ")}(\u8BF7\u5728 .env / .env.local \u6216\u73AF\u5883\u53D8\u91CF\u4E2D\u914D\u7F6E)`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
ossRegion: env.OSS_REGION,
|
|
411
|
+
ossBucket: env.OSS_BUCKET,
|
|
412
|
+
ossAccessKeyId: env.OSS_ACCESS_KEYID,
|
|
413
|
+
// 注意:变量名沿用 CI secrets 的拼写(SECRECT),保持 .env 兼容
|
|
414
|
+
ossAccessKeySecret: env.OSS_ACCESS_KEYSECRECT,
|
|
415
|
+
deployApiUrl: options.notify ? env.DEPLOY_API_URL : void 0,
|
|
416
|
+
databaseUrl: env.DATABASE_URL,
|
|
417
|
+
baseRoot: env.BASE_ROOT || DEFAULT_BASE_ROOT
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/utils/build.ts
|
|
422
|
+
import fs6 from "fs";
|
|
423
|
+
import path6 from "path";
|
|
424
|
+
import { execa as execa3 } from "execa";
|
|
425
|
+
var SERVER_CONFIG_FILES = [
|
|
426
|
+
"lightfish-server.config.js",
|
|
427
|
+
"lightfish-server.config.ts",
|
|
428
|
+
"lightfish-server.config.mjs",
|
|
429
|
+
"lightfish-server.config.cjs"
|
|
430
|
+
];
|
|
431
|
+
var VITE_CONFIG_FILES = [
|
|
432
|
+
"vite.config.ts",
|
|
433
|
+
"vite.config.js",
|
|
434
|
+
"vite.config.mts",
|
|
435
|
+
"vite.config.mjs",
|
|
436
|
+
"vite.config.cjs"
|
|
437
|
+
];
|
|
438
|
+
function readPackageJson(cwd) {
|
|
439
|
+
const file = path6.join(cwd, "package.json");
|
|
440
|
+
if (!fs6.existsSync(file)) return void 0;
|
|
441
|
+
return JSON.parse(fs6.readFileSync(file, "utf8"));
|
|
442
|
+
}
|
|
443
|
+
function hasVite(cwd) {
|
|
444
|
+
if (VITE_CONFIG_FILES.some((f) => fs6.existsSync(path6.join(cwd, f)))) return true;
|
|
445
|
+
const pkg = readPackageJson(cwd);
|
|
446
|
+
if (pkg) {
|
|
447
|
+
const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
448
|
+
if ("vite" in deps) return true;
|
|
449
|
+
}
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
function detectBuild(cwd) {
|
|
453
|
+
return {
|
|
454
|
+
vite: hasVite(cwd),
|
|
455
|
+
server: SERVER_CONFIG_FILES.some((f) => fs6.existsSync(path6.join(cwd, f)))
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
async function runBuildSteps(options) {
|
|
459
|
+
const detection = detectBuild(options.cwd);
|
|
460
|
+
if (!detection.vite && !detection.server) {
|
|
461
|
+
throw new Error("\u672A\u68C0\u6D4B\u5230 Vite \u6216 lightfish-server,\u65E0\u6CD5\u6784\u5EFA");
|
|
462
|
+
}
|
|
463
|
+
const execOptions = {
|
|
464
|
+
cwd: options.cwd,
|
|
465
|
+
preferLocal: true,
|
|
466
|
+
stdio: "inherit",
|
|
467
|
+
env: { ...process.env, ...options.env }
|
|
468
|
+
};
|
|
469
|
+
if (detection.vite) {
|
|
470
|
+
await execa3("vite", ["build"], execOptions);
|
|
471
|
+
}
|
|
472
|
+
if (detection.server) {
|
|
473
|
+
await execa3("lightfish-server", ["build"], execOptions);
|
|
474
|
+
await execa3("lightfish-server", ["db", "push"], execOptions);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/utils/oss.ts
|
|
479
|
+
import OSS from "ali-oss";
|
|
480
|
+
import fs7 from "fs";
|
|
481
|
+
import path7 from "path";
|
|
482
|
+
function withPrefix(prefix, key) {
|
|
483
|
+
const normalized = prefix.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
484
|
+
if (!normalized) return key;
|
|
485
|
+
return `${normalized}/${key}`;
|
|
486
|
+
}
|
|
487
|
+
function walkDir(dir, base = "") {
|
|
488
|
+
if (!fs7.existsSync(dir)) return [];
|
|
489
|
+
const entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
490
|
+
const files = [];
|
|
491
|
+
for (const entry of entries) {
|
|
492
|
+
const fullPath = path7.join(dir, entry.name);
|
|
493
|
+
const key = base ? `${base}/${entry.name}` : entry.name;
|
|
494
|
+
if (entry.isDirectory()) {
|
|
495
|
+
files.push(...walkDir(fullPath, key));
|
|
496
|
+
} else {
|
|
497
|
+
files.push({ localPath: fullPath, key });
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return files;
|
|
501
|
+
}
|
|
502
|
+
async function uploadDist(options, client) {
|
|
503
|
+
const oss = client ?? createClient(options);
|
|
504
|
+
const files = walkDir(options.distDir);
|
|
505
|
+
console.log(`[publish] Found ${files.length} files to upload`);
|
|
506
|
+
const results = await Promise.all(
|
|
507
|
+
files.map(({ localPath, key }) => {
|
|
508
|
+
const objectKey = withPrefix(options.objectPrefix, key);
|
|
509
|
+
return oss.put(objectKey, localPath).then((res) => ({ key: objectKey, ok: res.res.status === 200 })).catch((err) => {
|
|
510
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
511
|
+
console.error(`[publish] ERROR ${objectKey}: ${message}`);
|
|
512
|
+
return { key: objectKey, ok: false };
|
|
513
|
+
});
|
|
514
|
+
})
|
|
515
|
+
);
|
|
516
|
+
for (const r of results.filter((r2) => r2.ok)) {
|
|
517
|
+
console.log(`[publish] ok ${r.key}`);
|
|
518
|
+
}
|
|
519
|
+
const ok = results.filter((r) => r.ok).length;
|
|
520
|
+
const fail = results.filter((r) => !r.ok).length;
|
|
521
|
+
console.log(`[publish] Done: ${ok} succeeded, ${fail} failed`);
|
|
522
|
+
return { ok, fail };
|
|
523
|
+
}
|
|
524
|
+
function createClient(options) {
|
|
525
|
+
return new OSS({
|
|
526
|
+
region: options.region,
|
|
527
|
+
accessKeyId: options.accessKeyId,
|
|
528
|
+
accessKeySecret: options.accessKeySecret,
|
|
529
|
+
bucket: options.bucket
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// src/utils/notify.ts
|
|
534
|
+
async function notifyDeploy(options) {
|
|
535
|
+
const fetchFn = options.fetchImpl ?? fetch;
|
|
536
|
+
const body = JSON.stringify(options.payload);
|
|
537
|
+
console.log(`[publish] POST ${options.apiUrl}`);
|
|
538
|
+
console.log(`[publish] body: ${body}`);
|
|
539
|
+
let res;
|
|
540
|
+
try {
|
|
541
|
+
res = await fetchFn(options.apiUrl, {
|
|
542
|
+
method: "POST",
|
|
543
|
+
headers: { "Content-Type": "application/json" },
|
|
544
|
+
body
|
|
545
|
+
});
|
|
546
|
+
} catch (err) {
|
|
547
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
548
|
+
throw new Error(`\u90E8\u7F72 API \u8BF7\u6C42\u5931\u8D25:${message}`);
|
|
549
|
+
}
|
|
550
|
+
if (!res.ok) {
|
|
551
|
+
throw new Error(`\u90E8\u7F72 API \u8FD4\u56DE HTTP ${res.status}`);
|
|
552
|
+
}
|
|
553
|
+
let data;
|
|
554
|
+
try {
|
|
555
|
+
data = await res.json();
|
|
556
|
+
} catch {
|
|
557
|
+
throw new Error("\u90E8\u7F72 API \u54CD\u5E94\u975E JSON");
|
|
558
|
+
}
|
|
559
|
+
console.log(`[publish] response: ${JSON.stringify(data)}`);
|
|
560
|
+
if (typeof data?.success !== "boolean" || data.success !== true) {
|
|
561
|
+
throw new Error("\u90E8\u7F72 API \u672A\u8FD4\u56DE success=true");
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/commands/publish.ts
|
|
566
|
+
function generateVersion(date = /* @__PURE__ */ new Date()) {
|
|
567
|
+
return date.toISOString().replace(/[-T:.Z]/g, "").slice(0, 14);
|
|
568
|
+
}
|
|
569
|
+
function readPackageJsonName(cwd) {
|
|
570
|
+
const file = path8.join(cwd, "package.json");
|
|
571
|
+
if (!fs8.existsSync(file)) return void 0;
|
|
572
|
+
const pkg = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
573
|
+
return pkg.name;
|
|
574
|
+
}
|
|
575
|
+
function resolveAppName(options) {
|
|
576
|
+
if (options.app) return options.app;
|
|
577
|
+
const pkgName = readPackageJsonName(options.cwd);
|
|
578
|
+
if (pkgName) {
|
|
579
|
+
return pkgName.startsWith("@") ? pkgName.replace(/^@[^/]+\//, "") : pkgName;
|
|
580
|
+
}
|
|
581
|
+
throw new Error("\u65E0\u6CD5\u786E\u5B9A APP_NAME:\u8BF7\u901A\u8FC7 --app \u6307\u5B9A,\u6216\u786E\u4FDD package.json \u542B name \u5B57\u6BB5");
|
|
582
|
+
}
|
|
583
|
+
function assertNumericVersion(version) {
|
|
584
|
+
if (!/^\d+$/.test(version)) {
|
|
585
|
+
throw new Error(`version \u5FC5\u987B\u4E3A\u7EAF\u6570\u5B57(\u4E0E\u90E8\u7F72 API \u7684 number \u5951\u7EA6\u4E00\u81F4),\u6536\u5230:${version}`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function resolveOptions(options) {
|
|
589
|
+
const cwd = options.cwd ?? process.cwd();
|
|
590
|
+
const appName = resolveAppName({ cwd, app: options.app });
|
|
591
|
+
const version = options.version ?? generateVersion();
|
|
592
|
+
assertNumericVersion(version);
|
|
593
|
+
const distDir = path8.resolve(cwd, options.dist ?? "dist");
|
|
594
|
+
const notify = !options.noNotify;
|
|
595
|
+
const baseRoot = process.env.BASE_ROOT || DEFAULT_BASE_ROOT;
|
|
596
|
+
const root = baseRoot.replace(/\/+$/, "");
|
|
597
|
+
const viteBaseUrl = root ? `${root}/${appName}/${version}/` : `/${appName}/${version}/`;
|
|
598
|
+
const objectPrefix = `${appName}/${version}`;
|
|
599
|
+
const ossIndexUrl = `${root}/${appName}/${version}/index.html`;
|
|
600
|
+
return {
|
|
601
|
+
cwd,
|
|
602
|
+
appName,
|
|
603
|
+
version,
|
|
604
|
+
distDir,
|
|
605
|
+
baseRoot,
|
|
606
|
+
root,
|
|
607
|
+
viteBaseUrl,
|
|
608
|
+
objectPrefix,
|
|
609
|
+
ossIndexUrl,
|
|
610
|
+
notify,
|
|
611
|
+
skipBuild: options.skipBuild ?? false,
|
|
612
|
+
note: options.note
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
function printBuildPlanDryRun(detection) {
|
|
616
|
+
if (!detection.vite && !detection.server) {
|
|
617
|
+
console.log("[publish] (dry-run) \u672A\u68C0\u6D4B\u5230 Vite \u6216 lightfish-server,\u6784\u5EFA\u5C06\u5931\u8D25");
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
console.log("[publish] (dry-run) \u5C06\u6267\u884C\u6784\u5EFA:");
|
|
621
|
+
if (detection.vite) console.log("[publish] (dry-run) vite build");
|
|
622
|
+
if (detection.server) {
|
|
623
|
+
console.log("[publish] (dry-run) lightfish-server build");
|
|
624
|
+
console.log("[publish] (dry-run) lightfish-server db push");
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function printEnvDryRun(serverDetected, notify) {
|
|
628
|
+
const required = getRequiredEnvNames({ notify, serverDetected });
|
|
629
|
+
console.log("[publish] (dry-run) \u73AF\u5883\u53D8\u91CF\u9884\u68C0:");
|
|
630
|
+
for (const name of required) {
|
|
631
|
+
const present = process.env[name] !== void 0 && process.env[name] !== "";
|
|
632
|
+
console.log(`[publish] (dry-run) ${present ? "\u2713" : "\u2717"} ${name}`);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
function printUploadPlanDryRun(options) {
|
|
636
|
+
const files = walkDir(options.distDir);
|
|
637
|
+
if (files.length === 0) {
|
|
638
|
+
console.log(`[publish] (dry-run) \u4EA7\u7269\u76EE\u5F55 ${options.distDir} \u4E3A\u7A7A\u6216\u4E0D\u5B58\u5728(\u6784\u5EFA\u540E\u5C06\u751F\u6210)`);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
console.log(`[publish] (dry-run) \u5C06\u4E0A\u4F20 ${files.length} \u4E2A\u6587\u4EF6\u5230 OSS \u524D\u7F00:${options.objectPrefix}/`);
|
|
642
|
+
for (const { key } of files) {
|
|
643
|
+
console.log(`[publish] (dry-run) ${withPrefix(options.objectPrefix, key)}`);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
function buildNotifyPayload(params) {
|
|
647
|
+
const payload = {
|
|
648
|
+
id: params.appName,
|
|
649
|
+
version: Number(params.version),
|
|
650
|
+
ossIndexUrl: params.ossIndexUrl,
|
|
651
|
+
domain: `https://${params.appName}.lightfish.top`
|
|
652
|
+
};
|
|
653
|
+
if (params.note) payload.note = params.note;
|
|
654
|
+
return payload;
|
|
655
|
+
}
|
|
656
|
+
function printNotifyPlanDryRun(options, pubEnv) {
|
|
657
|
+
if (!options.notify) {
|
|
658
|
+
console.log("[publish] (dry-run) \u901A\u77E5\u5DF2\u8DF3\u8FC7(--no-notify)");
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const payload = buildNotifyPayload({
|
|
662
|
+
appName: options.appName,
|
|
663
|
+
version: options.version,
|
|
664
|
+
ossIndexUrl: options.ossIndexUrl,
|
|
665
|
+
note: options.note
|
|
666
|
+
});
|
|
667
|
+
console.log("[publish] (dry-run) \u5C06 POST \u901A\u77E5:");
|
|
668
|
+
console.log(`[publish] (dry-run) url: ${pubEnv.deployApiUrl ?? "(\u672A\u914D\u7F6E DEPLOY_API_URL)"}`);
|
|
669
|
+
console.log(`[publish] (dry-run) body: ${JSON.stringify(payload)}`);
|
|
670
|
+
}
|
|
671
|
+
async function runPublish(options = {}) {
|
|
672
|
+
const cwd = options.cwd ?? process.cwd();
|
|
673
|
+
loadDotenv({ cwd, envPath: options.envPath });
|
|
674
|
+
const resolved = resolveOptions(options);
|
|
675
|
+
console.log(`[publish] app=${resolved.appName} version=${resolved.version} dist=${resolved.distDir}`);
|
|
676
|
+
let serverDetected = false;
|
|
677
|
+
if (!resolved.skipBuild) {
|
|
678
|
+
const detection = detectBuild(resolved.cwd);
|
|
679
|
+
serverDetected = detection.server;
|
|
680
|
+
if (options.dryRun) {
|
|
681
|
+
printBuildPlanDryRun(detection);
|
|
682
|
+
} else {
|
|
683
|
+
console.log("[publish] \u5F00\u59CB\u6784\u5EFA...");
|
|
684
|
+
const buildEnv = {
|
|
685
|
+
VITE_BASE_URL: resolved.viteBaseUrl,
|
|
686
|
+
BASE_ROOT: resolved.baseRoot,
|
|
687
|
+
APP_NAME: resolved.appName,
|
|
688
|
+
BUILD_VERSION: resolved.version
|
|
689
|
+
};
|
|
690
|
+
if (process.env.DATABASE_URL) buildEnv.DATABASE_URL = process.env.DATABASE_URL;
|
|
691
|
+
await runBuildSteps({
|
|
692
|
+
cwd: resolved.cwd,
|
|
693
|
+
env: buildEnv
|
|
694
|
+
});
|
|
695
|
+
console.log("[publish] \u6784\u5EFA\u5B8C\u6210");
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const pubEnv = options.dryRun ? softResolveEnv(resolved.notify, serverDetected) : resolvePublishEnv({ notify: resolved.notify, serverDetected });
|
|
699
|
+
if (options.dryRun) {
|
|
700
|
+
printEnvDryRun(serverDetected, resolved.notify);
|
|
701
|
+
printUploadPlanDryRun(resolved);
|
|
702
|
+
printNotifyPlanDryRun(resolved, pubEnv);
|
|
703
|
+
console.log("[publish] (dry-run) \u5B8C\u6210,\u672A\u6267\u884C\u4EFB\u4F55\u526F\u4F5C\u7528");
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (!fs8.existsSync(resolved.distDir)) {
|
|
707
|
+
throw new Error(`\u4EA7\u7269\u76EE\u5F55\u4E0D\u5B58\u5728:${resolved.distDir}`);
|
|
708
|
+
}
|
|
709
|
+
console.log("[publish] \u5F00\u59CB\u4E0A\u4F20 OSS...");
|
|
710
|
+
const { fail } = await uploadDist({
|
|
711
|
+
region: pubEnv.ossRegion,
|
|
712
|
+
bucket: pubEnv.ossBucket,
|
|
713
|
+
accessKeyId: pubEnv.ossAccessKeyId,
|
|
714
|
+
accessKeySecret: pubEnv.ossAccessKeySecret,
|
|
715
|
+
objectPrefix: resolved.objectPrefix,
|
|
716
|
+
distDir: resolved.distDir
|
|
717
|
+
});
|
|
718
|
+
if (fail > 0) {
|
|
719
|
+
throw new Error(`OSS \u4E0A\u4F20\u6709 ${fail} \u4E2A\u6587\u4EF6\u5931\u8D25`);
|
|
720
|
+
}
|
|
721
|
+
console.log("[publish] OSS \u4E0A\u4F20\u5B8C\u6210");
|
|
722
|
+
if (resolved.notify) {
|
|
723
|
+
console.log("[publish] \u5F00\u59CB\u901A\u77E5\u90E8\u7F72 API...");
|
|
724
|
+
const payload = buildNotifyPayload({
|
|
725
|
+
appName: resolved.appName,
|
|
726
|
+
version: resolved.version,
|
|
727
|
+
ossIndexUrl: resolved.ossIndexUrl,
|
|
728
|
+
note: resolved.note
|
|
729
|
+
});
|
|
730
|
+
await notifyDeploy({ apiUrl: pubEnv.deployApiUrl, payload });
|
|
731
|
+
console.log("[publish] \u901A\u77E5\u5B8C\u6210");
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
function softResolveEnv(notify, serverDetected) {
|
|
735
|
+
return {
|
|
736
|
+
ossRegion: process.env.OSS_REGION ?? "",
|
|
737
|
+
ossBucket: process.env.OSS_BUCKET ?? "",
|
|
738
|
+
ossAccessKeyId: process.env.OSS_ACCESS_KEYID ?? "",
|
|
739
|
+
ossAccessKeySecret: process.env.OSS_ACCESS_KEYSECRECT ?? "",
|
|
740
|
+
deployApiUrl: notify ? process.env.DEPLOY_API_URL : void 0,
|
|
741
|
+
databaseUrl: process.env.DATABASE_URL,
|
|
742
|
+
baseRoot: process.env.BASE_ROOT || DEFAULT_BASE_ROOT
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// src/utils/package-info.ts
|
|
747
|
+
import fs9 from "fs";
|
|
748
|
+
import path9 from "path";
|
|
370
749
|
import { fileURLToPath } from "url";
|
|
371
|
-
var dirname =
|
|
750
|
+
var dirname = path9.dirname(fileURLToPath(import.meta.url));
|
|
372
751
|
function readPackageVersion() {
|
|
373
752
|
const packageJsonPathCandidates = [
|
|
374
753
|
// 源码模式:src/utils/package-info.ts -> packages/cli/package.json
|
|
375
|
-
|
|
754
|
+
path9.resolve(dirname, "../../package.json"),
|
|
376
755
|
// 构建产物模式:dist/lightfish.js -> packages/cli/package.json
|
|
377
|
-
|
|
756
|
+
path9.resolve(dirname, "../package.json")
|
|
378
757
|
];
|
|
379
|
-
const packageJsonPath = packageJsonPathCandidates.find((candidate) =>
|
|
758
|
+
const packageJsonPath = packageJsonPathCandidates.find((candidate) => fs9.existsSync(candidate));
|
|
380
759
|
if (!packageJsonPath) {
|
|
381
760
|
return "0.0.0";
|
|
382
761
|
}
|
|
383
|
-
const packageJson = JSON.parse(
|
|
762
|
+
const packageJson = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
384
763
|
return packageJson.version ?? "0.0.0";
|
|
385
764
|
}
|
|
386
765
|
|
|
387
766
|
// src/lightfish.ts
|
|
388
767
|
var cli = cac("lightfish");
|
|
389
768
|
async function runBuild() {
|
|
390
|
-
await
|
|
769
|
+
await execa4("vite", ["build"], {
|
|
391
770
|
cwd: process.cwd(),
|
|
392
771
|
preferLocal: true,
|
|
393
772
|
stdio: "inherit"
|
|
@@ -424,9 +803,28 @@ cli.command("build", "\u6267\u884C Vite \u6784\u5EFA\uFF0C\u540E\u7EED\u4F1A\u53
|
|
|
424
803
|
process.exitCode = 1;
|
|
425
804
|
}
|
|
426
805
|
});
|
|
806
|
+
cli.command("publish", "\u6784\u5EFA\u5E76\u90E8\u7F72\u5230 OSS\uFF0C\u901A\u77E5\u90E8\u7F72 API").option("--app <name>", "\u8986\u76D6 APP_NAME\uFF08\u9ED8\u8BA4 package.json#name \u53BB scope\uFF09").option("--version <v>", "\u8986\u76D6 BUILD_VERSION\uFF08\u9ED8\u8BA4 UTC \u65F6\u95F4\u6233 YYYYMMDDHHmmss\uFF09").option("--dist <dir>", "\u4EA7\u7269\u76EE\u5F55", { default: "dist" }).option("--note <text>", "\u901A\u77E5 body \u7684 note \u5B57\u6BB5\uFF0C\u4E0D\u4F20\u5219\u7701\u7565").option("--env <path>", "\u6307\u5B9A .env \u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4 cwd/.env + .env.local\uFF09").option("--no-build", "\u8DF3\u8FC7\u6784\u5EFA\uFF0C\u4F7F\u7528\u5DF2\u6709 dist").option("--no-notify", "\u8DF3\u8FC7\u901A\u77E5\u90E8\u7F72 API").option("--dry-run", "\u53EA\u6253\u5370\u5C06\u505A\u4EC0\u4E48\uFF0C\u4E0D\u6267\u884C").action(async (options) => {
|
|
807
|
+
try {
|
|
808
|
+
await runPublish({
|
|
809
|
+
app: options.app,
|
|
810
|
+
version: options.version,
|
|
811
|
+
dist: options.dist,
|
|
812
|
+
note: options.note,
|
|
813
|
+
envPath: options.env,
|
|
814
|
+
skipBuild: options.build === false,
|
|
815
|
+
noNotify: options.notify === false,
|
|
816
|
+
dryRun: options.dryRun
|
|
817
|
+
});
|
|
818
|
+
process.exit(0);
|
|
819
|
+
} catch (error) {
|
|
820
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
821
|
+
console.error(`\u53D1\u5E03\u5931\u8D25\uFF1A${message}`);
|
|
822
|
+
process.exit(1);
|
|
823
|
+
}
|
|
824
|
+
});
|
|
427
825
|
cli.command("", "\u663E\u793A\u5E2E\u52A9").action(() => {
|
|
428
826
|
cli.outputHelp();
|
|
429
827
|
});
|
|
430
828
|
cli.help();
|
|
431
|
-
cli.version(readPackageVersion());
|
|
829
|
+
cli.version(readPackageVersion(), "-v, --cli-version");
|
|
432
830
|
cli.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightfish/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
"lint": "tsc --noEmit"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"ali-oss": "^6.23.0",
|
|
21
22
|
"cac": "^7.0.0",
|
|
23
|
+
"dotenv": "^16.6.1",
|
|
22
24
|
"execa": "^9.6.1",
|
|
23
25
|
"fs-extra": "^11.3.5",
|
|
24
26
|
"prompts": "^2.4.2"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
29
|
+
"@types/ali-oss": "^6.23.3",
|
|
27
30
|
"@types/fs-extra": "^11.0.4",
|
|
28
31
|
"@types/prompts": "^2.4.9"
|
|
29
32
|
}
|