@ubean/cli 0.6.1 → 0.6.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/README.md +676 -0
- package/README.zh-CN.md +635 -0
- package/dist/cli.js +76 -189
- package/package.json +14 -14
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { basename, join, relative, resolve } from "pathe";
|
|
4
4
|
import { getLogger, setDebugLogging, setMinLevel } from "@ubean/shared/logger";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
6
|
-
import {
|
|
6
|
+
import { checkProjectDependencies, loadUbeanConfig, resolveModules, resolvePrerenderConfig, resolveSsrConfig } from "@ubean/config";
|
|
7
7
|
import { readFile, rm } from "node:fs/promises";
|
|
8
8
|
import { generateOpenApiTypesFromServer, generateTypes } from "@ubean/build/codegen";
|
|
9
9
|
import { buildWithEnvironments } from "@ubean/build/production";
|
|
@@ -15,7 +15,6 @@ import { DEVTOOLS_PASS_THROUGH_PREFIXES, createCloudflarePreviewRunner, createVi
|
|
|
15
15
|
import { ubeanVite } from "@ubean/build/vue";
|
|
16
16
|
import { ubeanIslandsPlugin } from "@ubean/islands/vite";
|
|
17
17
|
import { findAvailablePort, findUserViteConfig, getLanAddresses, isLoopbackHost, isWildcardHost } from "@ubean/shared/node";
|
|
18
|
-
import { execSync } from "node:child_process";
|
|
19
18
|
import { createServer as createServer$1 } from "node:http";
|
|
20
19
|
//#region src/shared/exit.ts
|
|
21
20
|
/**
|
|
@@ -90,7 +89,7 @@ export default defineConfig({
|
|
|
90
89
|
// Build options (platform preset lives here — a top-level \`preset\` field
|
|
91
90
|
// is silently ignored, so always nest it under \`build\`).
|
|
92
91
|
build: {
|
|
93
|
-
preset: 'standard', // 'standard' | 'node' | 'cloudflare' | 'vercel' | 'netlify' | 'bun' | 'deno' | 'aws' | 'azure'
|
|
92
|
+
preset: 'standard', // 'standard' | 'node' | 'cloudflare' | 'cloudflare-dev' | 'vercel' | 'vercel-edge' | 'netlify' | 'bun' | 'deno' | 'aws' | 'azure'
|
|
94
93
|
outputDir: 'dist'
|
|
95
94
|
},
|
|
96
95
|
|
|
@@ -499,9 +498,9 @@ const buildCommand = {
|
|
|
499
498
|
* - CLI 只装配插件、起 Vite server、打印 banner,并订阅扫描做命令级事务(类型生成、
|
|
500
499
|
* DevTools 数据上报)。
|
|
501
500
|
*
|
|
502
|
-
*
|
|
503
|
-
* (可选依赖 + `config.devtools.enabled`
|
|
504
|
-
*
|
|
501
|
+
* 保留一处 CLI 专有接线(无法下沉):`@ubean/devtools` / `@devframes/vite` 的按需加载
|
|
502
|
+
* (可选依赖 + `config.devtools.enabled` 闸门)。DevTools 的 scaffold CRUD 由注入的
|
|
503
|
+
* `scaffoldOps` 提供。
|
|
505
504
|
*/
|
|
506
505
|
const logger$8 = getLogger("dev-server");
|
|
507
506
|
/**
|
|
@@ -527,42 +526,57 @@ async function createDevViteServer(options) {
|
|
|
527
526
|
const isBackendMode = config.mode === "backend";
|
|
528
527
|
let viteServer = null;
|
|
529
528
|
const rescanDev = () => peekDevScanCoordinator(viteServer)?.rescan();
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
529
|
+
let refreshDevtools;
|
|
530
|
+
const devtoolsPlugins = [];
|
|
531
|
+
if (devtoolsEnabled) try {
|
|
532
|
+
const [{ viteDevframeHub }, { createUbeanDevframe, UBEAN_ANCHOR_DOCK }] = await Promise.all([import("@devframes/vite/hub"), import("@ubean/devtools")]);
|
|
533
|
+
const devframe = createUbeanDevframe({
|
|
534
|
+
getScanResult: options.devtools?.getScanResult,
|
|
535
|
+
getConfigMeta: options.devtools?.getConfigMeta,
|
|
536
|
+
getCustomTabs: options.devtools?.getCustomTabs,
|
|
537
|
+
getCwd: () => cwd,
|
|
538
|
+
scaffoldOps: {
|
|
539
|
+
createFsOps,
|
|
540
|
+
scaffold,
|
|
541
|
+
deleteScaffold,
|
|
542
|
+
recoverScaffold
|
|
543
|
+
},
|
|
544
|
+
getApp: () => getDevApp(viteServer) ?? void 0,
|
|
545
|
+
triggerRescan: async () => {
|
|
546
|
+
await rescanDev();
|
|
547
|
+
},
|
|
548
|
+
basePath: `${config.devtools.route.replace(/\/$/, "")}/`,
|
|
549
|
+
registerRefresh: (fn) => {
|
|
550
|
+
refreshDevtools = fn;
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
devtoolsPlugins.push(viteDevframeHub({
|
|
554
|
+
devframes: [{
|
|
555
|
+
devframe,
|
|
556
|
+
dock: UBEAN_ANCHOR_DOCK
|
|
557
|
+
}],
|
|
558
|
+
quiet: true,
|
|
559
|
+
auth: false
|
|
560
|
+
}));
|
|
561
|
+
} catch {}
|
|
562
|
+
const builtinPlugins = [
|
|
563
|
+
...devtoolsPlugins,
|
|
564
|
+
...hasUserViteConfig ? [] : [ubeanDevRequestPlugin({
|
|
565
|
+
passThrough: devtoolsEnabled ? [...DEVTOOLS_PASS_THROUGH_PREFIXES] : [],
|
|
566
|
+
devtoolsRedirect: devtoolsEnabled
|
|
567
|
+
})],
|
|
568
|
+
...hasUserViteConfig ? [] : [
|
|
569
|
+
ubeanPlugin({
|
|
570
|
+
config,
|
|
571
|
+
registry: createVirtualRegistry()
|
|
572
|
+
}),
|
|
573
|
+
...isBackendMode ? [] : ubeanVite({
|
|
574
|
+
config,
|
|
575
|
+
registry: createVirtualRegistry()
|
|
576
|
+
}),
|
|
577
|
+
...isBackendMode ? [] : [ubeanIslandsPlugin()]
|
|
578
|
+
]
|
|
579
|
+
];
|
|
566
580
|
const { plugins } = await resolveModules({
|
|
567
581
|
cwd,
|
|
568
582
|
config,
|
|
@@ -580,11 +594,6 @@ async function createDevViteServer(options) {
|
|
|
580
594
|
},
|
|
581
595
|
appType: "custom",
|
|
582
596
|
plugins,
|
|
583
|
-
devtools: {
|
|
584
|
-
enabled: devtoolsEnabled,
|
|
585
|
-
clientAuth: false,
|
|
586
|
-
builtinDevTools: false
|
|
587
|
-
},
|
|
588
597
|
optimizeDeps: { exclude: [
|
|
589
598
|
"ubean",
|
|
590
599
|
"vue-router",
|
|
@@ -631,6 +640,9 @@ async function createDevViteServer(options) {
|
|
|
631
640
|
async rescan() {
|
|
632
641
|
await rescanDev();
|
|
633
642
|
},
|
|
643
|
+
refreshDevtools() {
|
|
644
|
+
refreshDevtools?.();
|
|
645
|
+
},
|
|
634
646
|
async stop() {
|
|
635
647
|
const server = viteServer;
|
|
636
648
|
viteServer = null;
|
|
@@ -775,6 +787,7 @@ const devCommand = {
|
|
|
775
787
|
if (logging.lifecycle) logger$6.info(`File change detected: ${lastChangedFile}`);
|
|
776
788
|
}
|
|
777
789
|
currentScanResult = result;
|
|
790
|
+
devServer?.refreshDevtools();
|
|
778
791
|
try {
|
|
779
792
|
await generateTypes(result, {
|
|
780
793
|
cwd,
|
|
@@ -899,11 +912,13 @@ const devtoolsCommand = {
|
|
|
899
912
|
logger$5.info("");
|
|
900
913
|
logger$5.info(" Access:");
|
|
901
914
|
logger$5.info(" - Start dev server: pnpm dev");
|
|
902
|
-
logger$5.info(" - Open DevTools
|
|
915
|
+
logger$5.info(" - Open the DevTools URL printed in the dev server banner (default /_devtools)");
|
|
916
|
+
logger$5.info(" which redirects to the devframe hub shell.");
|
|
903
917
|
logger$5.info("");
|
|
904
918
|
logger$5.info(" Configuration (ubean.config.ts):");
|
|
905
919
|
logger$5.info(" devtools: {");
|
|
906
920
|
logger$5.info(" enabled: true, // Enable/disable DevTools (dev only)");
|
|
921
|
+
logger$5.info(" route: '/_devtools' // Panel path (optional)");
|
|
907
922
|
logger$5.info(" }");
|
|
908
923
|
logger$5.info("");
|
|
909
924
|
logger$5.info(" Features:");
|
|
@@ -929,7 +944,7 @@ const devtoolsCommand = {
|
|
|
929
944
|
} },
|
|
930
945
|
async run({ args }) {
|
|
931
946
|
const port = args.port;
|
|
932
|
-
logger$5.info(`http://localhost:${port}/
|
|
947
|
+
logger$5.info(`http://localhost:${port}/_devtools`);
|
|
933
948
|
}
|
|
934
949
|
}
|
|
935
950
|
}
|
|
@@ -1398,147 +1413,10 @@ async function ensureBuildDir(cwd, buildDir) {
|
|
|
1398
1413
|
const fullPath = join(cwd, buildDir);
|
|
1399
1414
|
if (!existsSync(fullPath)) mkdirSync(fullPath, { recursive: true });
|
|
1400
1415
|
}
|
|
1401
|
-
/**
|
|
1402
|
-
* Detects the package manager used in the project by inspecting lockfiles.
|
|
1403
|
-
* Priority: pnpm > yarn > bun > npm (npm as default fallback).
|
|
1404
|
-
*
|
|
1405
|
-
* 导出供单测复用(OPT-04 4c)。
|
|
1406
|
-
*/
|
|
1407
|
-
function detectPackageManager(cwd) {
|
|
1408
|
-
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
1409
|
-
if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
|
|
1410
|
-
if (existsSync(join(cwd, "bun.lockb")) || existsSync(join(cwd, "bun.lock"))) return "bun";
|
|
1411
|
-
return "npm";
|
|
1412
|
-
}
|
|
1413
|
-
/**
|
|
1414
|
-
* Builds the install command args for a given package manager and package list.
|
|
1415
|
-
* Examples:
|
|
1416
|
-
* pnpm → ['add', '@ubean/integrations@^0.1.3']
|
|
1417
|
-
* npm → ['install', '@ubean/integrations@^0.1.3']
|
|
1418
|
-
*
|
|
1419
|
-
* 导出供单测复用(OPT-04 4c)。
|
|
1420
|
-
*/
|
|
1421
|
-
function buildInstallCommand(pm, packages) {
|
|
1422
|
-
switch (pm) {
|
|
1423
|
-
case "pnpm": return {
|
|
1424
|
-
cmd: "pnpm",
|
|
1425
|
-
args: ["add", ...packages]
|
|
1426
|
-
};
|
|
1427
|
-
case "yarn": return {
|
|
1428
|
-
cmd: "yarn",
|
|
1429
|
-
args: ["add", ...packages]
|
|
1430
|
-
};
|
|
1431
|
-
case "bun": return {
|
|
1432
|
-
cmd: "bun",
|
|
1433
|
-
args: ["add", ...packages]
|
|
1434
|
-
};
|
|
1435
|
-
default: return {
|
|
1436
|
-
cmd: "npm",
|
|
1437
|
-
args: ["install", ...packages]
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
}
|
|
1441
|
-
/**
|
|
1442
|
-
* Extracts the bare package name from a module path.
|
|
1443
|
-
* '@ubean/integrations/pwa' → '@ubean/integrations'
|
|
1444
|
-
* '@ubean/icon/vite' → '@ubean/icon'
|
|
1445
|
-
*
|
|
1446
|
-
* 导出供单测复用(OPT-04 4c)。
|
|
1447
|
-
*/
|
|
1448
|
-
function extractPackageName(modulePath) {
|
|
1449
|
-
if (modulePath.startsWith("@")) return modulePath.split("/").slice(0, 2).join("/");
|
|
1450
|
-
return modulePath.split("/")[0];
|
|
1451
|
-
}
|
|
1452
|
-
/**
|
|
1453
|
-
* Reads the `ubean` package version from the project's package.json so we can
|
|
1454
|
-
* install matching versions of `@ubean/*` extension packages.
|
|
1455
|
-
* Returns `null` if ubean isn't declared or version can't be parsed.
|
|
1456
|
-
*
|
|
1457
|
-
* 导出供单测复用(OPT-04 4c)。
|
|
1458
|
-
*/
|
|
1459
|
-
function getUbeanVersion(cwd) {
|
|
1460
|
-
try {
|
|
1461
|
-
const pkgPath = join(cwd, "package.json");
|
|
1462
|
-
if (!existsSync(pkgPath)) return null;
|
|
1463
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1464
|
-
const spec = pkg.dependencies?.ubean || pkg.devDependencies?.ubean;
|
|
1465
|
-
if (!spec) return null;
|
|
1466
|
-
const match = spec.match(/\d+\.\d+\.\d+/);
|
|
1467
|
-
return match ? match[0] : null;
|
|
1468
|
-
} catch {
|
|
1469
|
-
return null;
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
/**
|
|
1473
|
-
* Probes whether a module is importable (i.e., installed in node_modules).
|
|
1474
|
-
* Uses dynamic import — same mechanism as `loadBuiltinModule` so detection
|
|
1475
|
-
* behavior matches what the runtime will actually encounter.
|
|
1476
|
-
*/
|
|
1477
|
-
async function isModuleInstalled(modulePath) {
|
|
1478
|
-
try {
|
|
1479
|
-
await import(
|
|
1480
|
-
/* @vite-ignore */
|
|
1481
|
-
modulePath
|
|
1482
|
-
);
|
|
1483
|
-
return true;
|
|
1484
|
-
} catch {
|
|
1485
|
-
return false;
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
/**
|
|
1489
|
-
* Detects built-in modules enabled in config but not installed, and
|
|
1490
|
-
* auto-installs them using the project's package manager.
|
|
1491
|
-
*
|
|
1492
|
-
* Behavior:
|
|
1493
|
-
* - When `autoInstall` is `false`, only prints warnings with install commands.
|
|
1494
|
-
* - When `autoInstall` is `true` and a package.json exists, runs the install.
|
|
1495
|
-
* - Version pinning: installs `@ubean/<pkg>@^<ubean-version>` to keep in sync.
|
|
1496
|
-
* - Failures fall back to warnings (non-fatal — prepare should still proceed).
|
|
1497
|
-
*/
|
|
1498
|
-
async function ensureBuiltinModules(cwd, config, autoInstall) {
|
|
1499
|
-
const missing = [];
|
|
1500
|
-
for (const builtin of BUILTIN_MODULES) {
|
|
1501
|
-
const configValue = config[builtin.key];
|
|
1502
|
-
if (isBuiltinDisabled(configValue)) continue;
|
|
1503
|
-
const packageName = extractPackageName(builtin.modulePath);
|
|
1504
|
-
if (!await isModuleInstalled(builtin.modulePath)) missing.push({
|
|
1505
|
-
key: builtin.key,
|
|
1506
|
-
packageName
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
if (missing.length === 0) return;
|
|
1510
|
-
const pm = detectPackageManager(cwd);
|
|
1511
|
-
const ubeanVersion = getUbeanVersion(cwd);
|
|
1512
|
-
const packagesToInstall = missing.map((m) => ubeanVersion ? `${m.packageName}@^${ubeanVersion}` : m.packageName);
|
|
1513
|
-
if (!autoInstall || !existsSync(join(cwd, "package.json"))) {
|
|
1514
|
-
for (const m of missing) {
|
|
1515
|
-
const versionSuffix = ubeanVersion ? `@^${ubeanVersion}` : "";
|
|
1516
|
-
logger$2.warn(`Built-in module "${m.key}" is enabled but \`${m.packageName}\` is not installed. Run: ${pm} add ${m.packageName}${versionSuffix}`);
|
|
1517
|
-
}
|
|
1518
|
-
return;
|
|
1519
|
-
}
|
|
1520
|
-
logger$2.info(`Auto-installing missing built-in module packages: ${packagesToInstall.join(", ")}`);
|
|
1521
|
-
logger$2.info(`Using package manager: ${pm}`);
|
|
1522
|
-
const { cmd, args } = buildInstallCommand(pm, packagesToInstall);
|
|
1523
|
-
try {
|
|
1524
|
-
execSync([cmd, ...args].join(" "), {
|
|
1525
|
-
cwd,
|
|
1526
|
-
stdio: "inherit",
|
|
1527
|
-
env: { ...process.env }
|
|
1528
|
-
});
|
|
1529
|
-
logger$2.info(`Installed: ${packagesToInstall.join(", ")}`);
|
|
1530
|
-
} catch (err) {
|
|
1531
|
-
logger$2.error(`Failed to auto-install packages: ${err instanceof Error ? err.message : String(err)}`);
|
|
1532
|
-
for (const m of missing) {
|
|
1533
|
-
const versionSuffix = ubeanVersion ? `@^${ubeanVersion}` : "";
|
|
1534
|
-
logger$2.warn(`Please install manually: ${pm} add ${m.packageName}${versionSuffix}`);
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
1416
|
const prepareCommand = {
|
|
1539
1417
|
meta: {
|
|
1540
1418
|
name: "prepare",
|
|
1541
|
-
description: "Generate type definitions and
|
|
1419
|
+
description: "Generate type definitions and check project dependencies"
|
|
1542
1420
|
},
|
|
1543
1421
|
args: {
|
|
1544
1422
|
cwd: {
|
|
@@ -1548,7 +1426,7 @@ const prepareCommand = {
|
|
|
1548
1426
|
},
|
|
1549
1427
|
install: {
|
|
1550
1428
|
type: "boolean",
|
|
1551
|
-
description: "
|
|
1429
|
+
description: "Prompt to install missing project dependencies (use --no-install to only warn)",
|
|
1552
1430
|
default: true
|
|
1553
1431
|
}
|
|
1554
1432
|
},
|
|
@@ -1556,7 +1434,16 @@ const prepareCommand = {
|
|
|
1556
1434
|
const cwd = resolve(args.cwd || process.cwd());
|
|
1557
1435
|
logger$2.info(`Preparing ubean project at ${cwd}...`);
|
|
1558
1436
|
const config = await loadUbeanConfig(cwd);
|
|
1559
|
-
await
|
|
1437
|
+
await checkProjectDependencies({
|
|
1438
|
+
cwd,
|
|
1439
|
+
config,
|
|
1440
|
+
srcDir: config.srcDir,
|
|
1441
|
+
mode: args.install !== false ? "prompt" : "warn",
|
|
1442
|
+
logger: {
|
|
1443
|
+
info: (message) => logger$2.info(message),
|
|
1444
|
+
warn: (message) => logger$2.warn(message)
|
|
1445
|
+
}
|
|
1446
|
+
});
|
|
1560
1447
|
const typesDir = ".ubean";
|
|
1561
1448
|
await ensureBuildDir(cwd, typesDir);
|
|
1562
1449
|
logger$2.info("Scanning project files...");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ubean/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "CLI for ubean (ubean-next binary: dev, build, prepare, init, preview, page, env, config, devtools, api/layout/middleware/cron/plugin scaffolds) plus the Vite dev server runner",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ubean-next": "./bin/ubean-next.mjs"
|
|
@@ -24,29 +24,29 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@ubean/build": "0.6.
|
|
28
|
-
"@ubean/config": "0.6.
|
|
29
|
-
"@ubean/i18n": "0.6.
|
|
30
|
-
"@ubean/islands": "0.6.
|
|
31
|
-
"@ubean/preset": "0.6.
|
|
32
|
-
"@ubean/scan": "0.6.
|
|
33
|
-
"@ubean/shared": "0.6.
|
|
27
|
+
"@ubean/build": "0.6.3",
|
|
28
|
+
"@ubean/config": "0.6.3",
|
|
29
|
+
"@ubean/i18n": "0.6.3",
|
|
30
|
+
"@ubean/islands": "0.6.3",
|
|
31
|
+
"@ubean/preset": "0.6.3",
|
|
32
|
+
"@ubean/scan": "0.6.3",
|
|
33
|
+
"@ubean/shared": "0.6.3",
|
|
34
34
|
"citty": "^0.2.2",
|
|
35
35
|
"kolorist": "^1.8.0",
|
|
36
36
|
"pathe": "^2.0.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^26.6.5",
|
|
40
|
-
"env-runner": "0.3.
|
|
40
|
+
"env-runner": "0.3.4",
|
|
41
41
|
"typescript": "npm:typescript-native-bridge@latest",
|
|
42
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
43
|
-
"vite-plus": "1.
|
|
42
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
|
|
43
|
+
"vite-plus": "1.3.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@ubean/content": "0.6.
|
|
47
|
-
"@ubean/devtools": "0.6.
|
|
46
|
+
"@ubean/content": "0.6.3",
|
|
47
|
+
"@ubean/devtools": "0.6.3",
|
|
48
48
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
49
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.
|
|
49
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.3.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependenciesMeta": {
|
|
52
52
|
"@ubean/content": {
|