@lark-apaas/miaoda-cli 0.1.21-alpha.90df4a0 → 0.1.21-beta.71cd6c4
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 +2 -36
- package/dist/api/deploy/index.js +1 -3
- package/dist/api/deploy/modern-types.js +1 -4
- package/dist/api/deploy/modern.js +0 -8
- package/dist/api/index.js +1 -3
- package/dist/cli/commands/app/index.js +21 -5
- package/dist/cli/commands/db/index.js +0 -3
- package/dist/cli/commands/deploy/modern.js +0 -34
- package/dist/cli/commands/file/index.js +4 -3
- package/dist/cli/commands/index.js +0 -19
- package/dist/cli/handlers/app/init.js +32 -17
- package/dist/cli/handlers/app/migrate.js +26 -0
- package/dist/cli/handlers/deploy/index.js +1 -3
- package/dist/cli/handlers/skills/sync.js +4 -12
- package/dist/config/migrate-configs/vite-react-to-nestjs-react-fullstack.js +9 -0
- package/dist/main.js +3 -0
- package/dist/services/app/init/import-source.js +67 -0
- package/dist/services/app/init/index.js +8 -1
- package/dist/services/app/init/template.js +47 -2
- package/dist/services/deploy/modern/atoms/index.js +1 -6
- package/dist/services/deploy/modern/atoms/upload.js +127 -4
- package/dist/services/deploy/modern/check.js +16 -28
- package/dist/services/deploy/modern/pipelines/index.js +1 -3
- package/dist/services/deploy/modern/protocol.js +0 -7
- package/dist/services/deploy/modern/run.js +4 -10
- package/dist/services/deploy/modern/template-key-map.js +0 -4
- package/dist/utils/http.js +1 -1
- package/package.json +1 -1
- package/dist/api/comment/api.js +0 -24
- package/dist/api/comment/index.js +0 -6
- package/dist/api/comment/types.js +0 -6
- package/dist/cli/commands/comment/index.js +0 -55
- package/dist/cli/commands/registry/index.js +0 -114
- package/dist/cli/handlers/comment/index.js +0 -7
- package/dist/cli/handlers/comment/list.js +0 -132
- package/dist/cli/handlers/comment/resolve.js +0 -44
- package/dist/cli/handlers/deploy/patch.js +0 -17
- package/dist/cli/handlers/registry/add.js +0 -97
- package/dist/cli/handlers/registry/index.js +0 -7
- package/dist/cli/handlers/registry/list.js +0 -48
- package/dist/cli/handlers/registry/shared.js +0 -25
- package/dist/services/deploy/modern/atoms/design-build.js +0 -49
- package/dist/services/deploy/modern/atoms/design-upload.js +0 -74
- package/dist/services/deploy/modern/atoms/tosutil.js +0 -246
- package/dist/services/deploy/modern/patch/actions.js +0 -61
- package/dist/services/deploy/modern/patch/content.js +0 -18
- package/dist/services/deploy/modern/patch/index.js +0 -46
- package/dist/services/deploy/modern/patch/routes.js +0 -37
- package/dist/services/deploy/modern/patch/source-scan.js +0 -58
- package/dist/services/deploy/modern/pipelines/design-local.js +0 -56
- package/dist/services/registry/index.js +0 -293
package/README.md
CHANGED
|
@@ -11,17 +11,12 @@ pnpm add -g @lark-apaas/miaoda-cli
|
|
|
11
11
|
## 使用
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
#
|
|
14
|
+
# 设置默认应用(需要应用上下文的命令可用 --app-id 覆盖)
|
|
15
15
|
export MIAODA_APP_ID=app_demo_xxx
|
|
16
16
|
|
|
17
17
|
# 文件操作
|
|
18
18
|
miaoda file ls
|
|
19
19
|
miaoda file upload ./local/path
|
|
20
|
-
|
|
21
|
-
# 评论操作
|
|
22
|
-
miaoda comment list --json
|
|
23
|
-
miaoda comment list --only-unresolved --json
|
|
24
|
-
miaoda comment resolve 1703677660120110076 --json
|
|
25
20
|
```
|
|
26
21
|
|
|
27
22
|
JSON 结构化输出(Agent 推荐):
|
|
@@ -46,38 +41,9 @@ miaoda file ls --output json
|
|
|
46
41
|
| `miaoda file ...` | 文件操作:上传、下载、元数据、签名下载、批量删除 |
|
|
47
42
|
| `miaoda db ...` | 数据操作:SQL 执行、表结构查询、数据导入导出 |
|
|
48
43
|
| `miaoda observability ...` | 线上日志、链路、前端源码堆栈反查、监控指标、运营指标 |
|
|
49
|
-
| `miaoda comment ...` | 应用评论:查看评论列表、解决评论 |
|
|
50
|
-
| `miaoda registry ...` | 组件 registry:列出 / copy-in design-html SDK 文件(本地执行) |
|
|
51
44
|
|
|
52
45
|
完整命令通过 `miaoda --help` 或 `miaoda <domain> --help` 查看。
|
|
53
46
|
|
|
54
|
-
## 组件 registry(design-html)
|
|
55
|
-
|
|
56
|
-
`miaoda registry` 为 design-html 技术栈提供 shadcn 式的「组件 registry」:把 SDK 文件**拷进**当前项目(copy-in),而非作为依赖安装。registry 是独立 npm 包,按运行时分发(design-html → buildless runtime → `@lark-apaas/coding-registry-buildless`)。
|
|
57
|
-
|
|
58
|
-
前置:当前目录(或 `--dir`)已走过 `miaoda app init`,`.spark/meta.json` 含 `stack=design-html`。
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
# 列出可用 SDK 条目(输出各文件 USAGE 注释块原文,便于 Agent 直接读用法)
|
|
62
|
-
miaoda registry list
|
|
63
|
-
miaoda registry list --json
|
|
64
|
-
|
|
65
|
-
# 把条目 copy-in 到当前项目(自动按 USAGE 块的 Depends 解析依赖闭包一并拷入)
|
|
66
|
-
miaoda registry add deck-slide
|
|
67
|
-
miaoda registry add foo.css theme --dry-run # 只报告将写 / 将跳,不落盘
|
|
68
|
-
miaoda registry add deck-slide --overwrite # 目标已存在时覆盖(默认跳过以保护改动)
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
要点:
|
|
72
|
-
|
|
73
|
-
- **条目**:registry 包根 `components/` · `scripts/` · `stylesheets/` 三个顶层目录(任意深度)下的代码文件即条目。USAGE 注释块**可选**(有则提供描述 + Depends,无则空描述、无依赖);包根直放文件、其它目录、非代码文件都不算条目。
|
|
74
|
-
- **寻址**:`add` / `Depends` 的 token 可写三种形式 —— `name`(去扩展名,如 `foo`)/ 完整文件名(如 `foo.css`)/ relPath(如 `stylesheets/foo.css`)。`name` **不要求唯一**,`list --json` 的 `file`(relPath)是永远无歧义的 canonical 地址。
|
|
75
|
-
- **多匹配全拉**:token 命中多个同名条目时全部 copy-in(如 `add foo` 把 `foo.jsx` + `foo.css` 一起拉),想只要其一就用完整文件名或 relPath。
|
|
76
|
-
- **拍平落地**:所有文件**拍平**到项目根(`scripts/deck-slide.js` → 项目 `deck-slide.js`,不保留子目录);闭包内同名 basename 撞车时后者覆盖前者。
|
|
77
|
-
- **skip-by-disk**:项目已有同名(拍平后的 basename)文件默认跳过,`--overwrite` 才覆盖;不写任何安装记账文件,项目文件树即状态。
|
|
78
|
-
- **add 回执带 usage**:`add` 结果的 `entries` 只列**你请求的条目**(不含被 `Depends` 传递拉进来的依赖——依赖照常落地在 `added`/`skipped`,但那是"管道"),逐条给出 `usage`(USAGE 块原文)与 `dependsOn`,Agent `add` 完即可直接读用法,无需再 `registry list`。请求的条目即使已存在被跳过也回带 usage(`status` 标 `added`/`skipped`,据此判断磁盘上是 registry 版还是你改过的旧版)。`--json` 结构为 `{registryVersion, added, skipped, dryRun, entries}`;pretty(默认)输出 `registry@<ver>` + `added:`/`skipped:` 逗号列表 + 各请求条目的 USAGE 块,稳定 label、无 JSON 数组、无截断,对 Agent 与人同样可读。
|
|
79
|
-
- `--version <ver>` 指定 registry 包版本或 dist-tag(缺省 `latest`),`--dir <path>` 指定项目目录(缺省当前目录)。
|
|
80
|
-
|
|
81
47
|
## 全局参数
|
|
82
48
|
|
|
83
49
|
- `--json [fields]`:输出结构化 JSON,可选字段级选择(如 `--json id,name`)。
|
|
@@ -89,7 +55,7 @@ miaoda registry add deck-slide --overwrite # 目标已存在时覆盖(
|
|
|
89
55
|
## 环境变量
|
|
90
56
|
|
|
91
57
|
- `MIAODA_APP_ID`:默认应用 ID,等价于 `--app-id`。
|
|
92
|
-
- `MIAODA_CANARY_HEADER`:HTTP 请求的 `x-tt-env` 小流量头取值。未设置时默认 `
|
|
58
|
+
- `MIAODA_CANARY_HEADER`:HTTP 请求的 `x-tt-env` 小流量头取值。未设置时默认 `boe_miaoda_doubao`;设为空字符串则不带该头(例:`export MIAODA_CANARY_HEADER=boe_xxx`)。值形如 `ppe_xxx` 时额外带上 `x-use-ppe: 1`。
|
|
93
59
|
|
|
94
60
|
## 输出契约
|
|
95
61
|
|
package/dist/api/deploy/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NodeStatus = exports.nodeStatusFromText = exports.nodeStatusText = exports.errorJobSchema = exports.deployGetSchema = exports.deployHistorySchema = exports.batchSavePluginInstances = exports.
|
|
3
|
+
exports.NodeStatus = exports.nodeStatusFromText = exports.nodeStatusText = exports.errorJobSchema = exports.deployGetSchema = exports.deployHistorySchema = exports.batchSavePluginInstances = exports.LocalReleaseStatus = exports.getModernLastPublishedVersion = exports.getModernReleaseStatus = exports.createModernRelease = exports.callbackStatic = exports.updateLocalRelease = exports.createLocalRelease = exports.preRelease = exports.queryPipelineInstance = exports.getErrorLog = exports.listPipelineInstances = exports.createRelease = void 0;
|
|
4
4
|
var api_1 = require("./api");
|
|
5
5
|
Object.defineProperty(exports, "createRelease", { enumerable: true, get: function () { return api_1.createRelease; } });
|
|
6
6
|
Object.defineProperty(exports, "listPipelineInstances", { enumerable: true, get: function () { return api_1.listPipelineInstances; } });
|
|
@@ -14,10 +14,8 @@ Object.defineProperty(exports, "callbackStatic", { enumerable: true, get: functi
|
|
|
14
14
|
Object.defineProperty(exports, "createModernRelease", { enumerable: true, get: function () { return modern_1.createRelease; } });
|
|
15
15
|
Object.defineProperty(exports, "getModernReleaseStatus", { enumerable: true, get: function () { return modern_1.getReleaseStatus; } });
|
|
16
16
|
Object.defineProperty(exports, "getModernLastPublishedVersion", { enumerable: true, get: function () { return modern_1.getLastPublishedVersion; } });
|
|
17
|
-
Object.defineProperty(exports, "applyTosDiff", { enumerable: true, get: function () { return modern_1.applyTosDiff; } });
|
|
18
17
|
var modern_types_1 = require("./modern-types");
|
|
19
18
|
Object.defineProperty(exports, "LocalReleaseStatus", { enumerable: true, get: function () { return modern_types_1.LocalReleaseStatus; } });
|
|
20
|
-
Object.defineProperty(exports, "TosActionType", { enumerable: true, get: function () { return modern_types_1.TosActionType; } });
|
|
21
19
|
var plugin_instances_1 = require("./plugin-instances");
|
|
22
20
|
Object.defineProperty(exports, "batchSavePluginInstances", { enumerable: true, get: function () { return plugin_instances_1.batchSavePluginInstances; } });
|
|
23
21
|
var schemas_1 = require("./schemas");
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
//
|
|
9
9
|
// 远端部署链路(B/C)所需的 release 接口先预留类型骨架,待 B/C 落地时启用。
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.
|
|
11
|
+
exports.LocalReleaseStatus = void 0;
|
|
12
12
|
/**
|
|
13
13
|
* localPublish 状态枚举(数值,与服务端 IDL 对齐)。
|
|
14
14
|
* CLI updateLocalRelease 只翻 Finished / Failed 两个终态;其它由后端流转。
|
|
@@ -21,6 +21,3 @@ exports.LocalReleaseStatus = {
|
|
|
21
21
|
Canceled: 4,
|
|
22
22
|
Rollback: 5,
|
|
23
23
|
};
|
|
24
|
-
// ── applyTosDiff(design-html 增量发布;后端应用 TOS diff) ──
|
|
25
|
-
/** 对齐 IDL publish.TosActionType(UNSPECIFIED=0 不用) */
|
|
26
|
-
exports.TosActionType = { CREATE: 1, UPDATE: 2, DELETE: 3 };
|
|
@@ -17,7 +17,6 @@ exports.callbackStatic = callbackStatic;
|
|
|
17
17
|
exports.createRelease = createRelease;
|
|
18
18
|
exports.getReleaseStatus = getReleaseStatus;
|
|
19
19
|
exports.getLastPublishedVersion = getLastPublishedVersion;
|
|
20
|
-
exports.applyTosDiff = applyTosDiff;
|
|
21
20
|
const http_1 = require("../../utils/http");
|
|
22
21
|
const devops_error_1 = require("../../utils/devops-error");
|
|
23
22
|
const DEFAULT_ERR_CODE = 'INTERNAL_DEVOPS_ERROR';
|
|
@@ -77,10 +76,3 @@ async function getLastPublishedVersion(req) {
|
|
|
77
76
|
const url = `/v1/devops/app/${encodeURIComponent(appID)}/last_published_version`;
|
|
78
77
|
return (0, http_1.postInnerApi)(url, {}, envelopeOpts('Failed to get last published version'));
|
|
79
78
|
}
|
|
80
|
-
// ── applyTosDiff ──
|
|
81
|
-
/** POST /v1/devops/app/:appID/apply_tos_diff —— 增量应用 TOS 文件 diff */
|
|
82
|
-
async function applyTosDiff(req) {
|
|
83
|
-
const { appID, ...body } = req;
|
|
84
|
-
const url = `/v1/devops/app/${encodeURIComponent(appID)}/apply_tos_diff`;
|
|
85
|
-
return (0, http_1.postInnerApi)(url, body, envelopeOpts('Failed to apply tos diff'));
|
|
86
|
-
}
|
package/dist/api/index.js
CHANGED
|
@@ -33,18 +33,16 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.deploy = exports.app = exports.observability = exports.db = exports.file = exports.plugin = void 0;
|
|
37
37
|
const _plugin = __importStar(require("../api/plugin/index"));
|
|
38
38
|
const _file = __importStar(require("../api/file/index"));
|
|
39
39
|
const _db = __importStar(require("../api/db/index"));
|
|
40
40
|
const _observability = __importStar(require("../api/observability/index"));
|
|
41
41
|
const _app = __importStar(require("../api/app/index"));
|
|
42
42
|
const _deploy = __importStar(require("../api/deploy/index"));
|
|
43
|
-
const _comment = __importStar(require("../api/comment/index"));
|
|
44
43
|
exports.plugin = { ..._plugin };
|
|
45
44
|
exports.file = { ..._file };
|
|
46
45
|
exports.db = { ..._db };
|
|
47
46
|
exports.observability = { ..._observability };
|
|
48
47
|
exports.app = { ..._app };
|
|
49
48
|
exports.deploy = { ..._deploy };
|
|
50
|
-
exports.comment = { ..._comment };
|
|
@@ -164,7 +164,9 @@ function registerAppInit(parent) {
|
|
|
164
164
|
.command('init')
|
|
165
165
|
.description('初始化应用代码:抓 template 渲染、同步 upgrade/templates、装 .agent/steering/ skills、写 .spark/meta.json。.spark/meta.json 已存在则直接退出')
|
|
166
166
|
.option('--template <stack>', `技术栈短名(${index_1.SUPPORTED_STACKS.join(' / ')})`)
|
|
167
|
-
.option('--
|
|
167
|
+
.option('--app-type <type>', 'aPaaS 业务类型(html / modern_html / jspage / full_stack);未传 --template 时用于解析技术栈')
|
|
168
|
+
.option('--source-path <path>', '导入源目录:把该目录内容聚合进脚手架 src/(当前仅 --app-type modern_html 生效)')
|
|
169
|
+
.option('--conf <json>', 'init 配置 JSON。支持 {"version": "<template 版本>"},默认 latest')
|
|
168
170
|
.option('--skip-install', '跳过依赖安装', false)
|
|
169
171
|
.option('--async-install', '派发后台进程装依赖并立即返回(与 --skip-install 互斥)', false)
|
|
170
172
|
.addOption((0, shared_1.appIdOption)())
|
|
@@ -180,6 +182,17 @@ function registerAppInit(parent) {
|
|
|
180
182
|
未提供则不写。运行端命令(deploy / file / plugin 等)仍优先读 MIAODA_APP_ID env,
|
|
181
183
|
env 未设置时回退到 meta.json.app_id。
|
|
182
184
|
|
|
185
|
+
技术栈解析(--template / --app-type)
|
|
186
|
+
--template 传了 → 直接用(vite-react / html / nestjs-react-fullstack)
|
|
187
|
+
否则 --app-type 传了 → 查表:html→html, modern_html→html, jspage→vite-react, full_stack→nestjs-react-fullstack
|
|
188
|
+
两者都没传 → 报错 ARGS_INVALID
|
|
189
|
+
|
|
190
|
+
源码导入(--source-path)
|
|
191
|
+
仅 --app-type modern_html 生效:把 <source-path> 整个目录递归聚合进 src/(同名覆盖,叠加保留)。
|
|
192
|
+
过滤:跳过 node_modules/.git/dist/build 目录,跳过 .env/.env.*/.DS_Store/.npmrc/package.json/lockfiles。
|
|
193
|
+
source-path 不存在 → 报错;非 modern_html 传了 source-path → 警告并忽略,继续正常 init。
|
|
194
|
+
app_type 不写入 .spark/meta.json。
|
|
195
|
+
|
|
183
196
|
平台同步(upgrade/templates)
|
|
184
197
|
init 内嵌一次 upgrade/templates 同步(跟 app upgrade 共用同一份 util):
|
|
185
198
|
从 miaoda-cli 自带的 upgrade/templates/<stack>/ 同步 files/(覆盖)+ patches/
|
|
@@ -208,7 +221,8 @@ function registerAppInit(parent) {
|
|
|
208
221
|
JSON 输出
|
|
209
222
|
已初始化:{"data": {"initialized": false, "reason": "already_initialized", "targetDir": "..."}}
|
|
210
223
|
新初始化:{"data": {"initialized": true, "template": "...", "templateVersion": "...", "steeringVersion": "...",
|
|
211
|
-
"appId": "...", "
|
|
224
|
+
"appId": "...", "appType": "modern_html", "sourceImported": true, "importedFileCount": 7,
|
|
225
|
+
"platformStackFound": true, "platformSyncedFiles": [...],
|
|
212
226
|
"installed": true, "installSource": "cache|npm|skipped", "installHash": "...", ...}}
|
|
213
227
|
async 模式:{"data": {"initialized": true, "asyncInstall": true, "installed": false,
|
|
214
228
|
"installSource": "async", "installPid": 123, "installLogPath": "...",
|
|
@@ -220,12 +234,16 @@ JSON 输出
|
|
|
220
234
|
$ miaoda app init --template vite-react --conf '{"version": "0.1.0"}'
|
|
221
235
|
$ miaoda app init --template vite-react --skip-install
|
|
222
236
|
$ miaoda app init --template vite-react --async-install
|
|
237
|
+
$ miaoda app init --app-type full_stack --app-id app_demo_xxx
|
|
238
|
+
$ miaoda app init --app-type modern_html --source-path ./my-assets
|
|
223
239
|
$ MIAODA_DEP_CACHE_DIR=/tmp/dep-cache miaoda app init --template vite-react
|
|
224
240
|
`);
|
|
225
241
|
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
226
242
|
const conf = parseInitConf(rawOpts.conf);
|
|
227
243
|
await (0, index_1.handleAppInit)({
|
|
228
244
|
template: rawOpts.template,
|
|
245
|
+
appType: rawOpts.appType,
|
|
246
|
+
sourcePath: rawOpts.sourcePath,
|
|
229
247
|
conf,
|
|
230
248
|
skipInstall: rawOpts.skipInstall,
|
|
231
249
|
appId: rawOpts.appId,
|
|
@@ -234,9 +252,7 @@ JSON 输出
|
|
|
234
252
|
}));
|
|
235
253
|
}
|
|
236
254
|
function parseInitConf(raw) {
|
|
237
|
-
|
|
238
|
-
// 一律视为不配置,回退默认(latest)。
|
|
239
|
-
if (raw === undefined || typeof raw === 'boolean' || raw.trim() === '')
|
|
255
|
+
if (raw === undefined)
|
|
240
256
|
return undefined;
|
|
241
257
|
let parsed;
|
|
242
258
|
try {
|
|
@@ -481,7 +481,6 @@ Examples:
|
|
|
481
481
|
'应用到 online;online 将无法直接更改数据库结构(仍可进行数据 DML 操作)。')
|
|
482
482
|
.usage('[flags]')
|
|
483
483
|
.option('--sync-data', '启用时将现有数据同步一份到 dev 环境')
|
|
484
|
-
.option('-y, --yes', '跳过确认提示直接执行')
|
|
485
484
|
.action(async function () {
|
|
486
485
|
await (0, index_1.handleDbMigrationInit)(this.optsWithGlobals());
|
|
487
486
|
})
|
|
@@ -562,7 +561,6 @@ Examples:
|
|
|
562
561
|
.summary('将 dev 的变更发布到 online(单事务原子)')
|
|
563
562
|
.description('将 dev 的变更发布到 online。')
|
|
564
563
|
.usage('[flags]')
|
|
565
|
-
.option('-y, --yes', '跳过确认提示直接执行')
|
|
566
564
|
.action(async function () {
|
|
567
565
|
await (0, index_1.handleDbMigrationApply)(this.optsWithGlobals());
|
|
568
566
|
})
|
|
@@ -681,7 +679,6 @@ Examples:
|
|
|
681
679
|
.description('将数据库恢复到指定时间点的状态。')
|
|
682
680
|
.usage('<timestamp> [flags]')
|
|
683
681
|
.argument('<timestamp>', '目标时间')
|
|
684
|
-
.option('-y, --yes', '跳过确认提示直接执行')
|
|
685
682
|
.action(async function (target) {
|
|
686
683
|
await (0, index_1.handleDbRecoveryApply)(target, this.optsWithGlobals());
|
|
687
684
|
})
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.registerDeployCommandsModern = registerDeployCommandsModern;
|
|
4
4
|
const shared_1 = require("../../../cli/commands/shared");
|
|
5
5
|
const modern_1 = require("../../../cli/handlers/deploy/modern");
|
|
6
|
-
const index_1 = require("../../../cli/handlers/deploy/index");
|
|
7
6
|
/**
|
|
8
7
|
* modern scene (MIAODA_APP_TYPE=7) 专用 deploy 注册。
|
|
9
8
|
* 仅披露顶层 `miaoda deploy`,CLI 表面对齐 openclaw-cli:`--dir / --skip-build`。
|
|
@@ -57,37 +56,4 @@ JSON 输出(stdout)
|
|
|
57
56
|
conf: rawOpts.conf,
|
|
58
57
|
});
|
|
59
58
|
}));
|
|
60
|
-
const patchCmd = deployCmd
|
|
61
|
-
.command('patch')
|
|
62
|
-
.description('design-html 增量发布:按文件 create/update/delete,.html 增删时同步 routes.json')
|
|
63
|
-
.option('--create <relpath>', '新增文件(可重复)', shared_1.collectRepeatedOption, [])
|
|
64
|
-
.option('--update <relpath>', '覆盖已有文件(可重复)', shared_1.collectRepeatedOption, [])
|
|
65
|
-
.option('--delete <relpath>', '删除文件(可重复)', shared_1.collectRepeatedOption, [])
|
|
66
|
-
.option('--session-id <id>', '会话 ID,发布时透传给下游(可选)')
|
|
67
|
-
.addHelpText('after', `
|
|
68
|
-
--dir 为项目目录(与 deploy 同名参数,默认当前目录)。
|
|
69
|
-
仅支持 design-html(design_local_deploy)。路径为工程根相对路径(= 服务端 latest 下 key),
|
|
70
|
-
禁绝对路径与 ".."。--create/--update 的本地文件必须存在。.html 被新增/删除(路由集合变化)
|
|
71
|
-
时自动重算并随包更新 routes.json;纯 --update 现有 .html 只改内容,不动 routes.json。
|
|
72
|
-
routes.json 每项为 {path, file}:path 为相对路径(不含 base 前缀,由消费侧拼接),file 为
|
|
73
|
-
对应源文件(如 / → index.html)。
|
|
74
|
-
|
|
75
|
-
JSON 输出
|
|
76
|
-
{"data": {"upsertCount": <n>, "deleteCount": <n>, "actionsSent": <n>, "routesRegenerated": <bool>}}
|
|
77
|
-
|
|
78
|
-
示例
|
|
79
|
-
$ miaoda deploy patch --update index.html
|
|
80
|
-
$ miaoda deploy patch --create blog/post.html --delete blog/old.html
|
|
81
|
-
$ miaoda deploy patch --update assets/app.js --update assets/app.css
|
|
82
|
-
`);
|
|
83
|
-
patchCmd.action((0, shared_1.withHelp)(patchCmd, async (rawOpts) => {
|
|
84
|
-
await (0, index_1.handleDeployPatch)({
|
|
85
|
-
appId: (0, shared_1.resolveAppId)({}),
|
|
86
|
-
dir: deployCmd.opts().dir ?? '.',
|
|
87
|
-
creates: rawOpts.create,
|
|
88
|
-
updates: rawOpts.update,
|
|
89
|
-
deletes: rawOpts.delete,
|
|
90
|
-
sessionId: rawOpts.sessionId,
|
|
91
|
-
});
|
|
92
|
-
}));
|
|
93
59
|
}
|
|
@@ -146,9 +146,10 @@ Examples:
|
|
|
146
146
|
.usage('[paths...] [flags]')
|
|
147
147
|
.argument('[paths...]', '要删除的文件,每项可填路径或文件名(自动识别)')
|
|
148
148
|
.option('-n, --name <name>', '按文件名删除(可重复指定)', (value, prev) => [...(prev ?? []), value])
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
// --yes 是 root 全局 option(见 main.ts),不在此重复声明;必须经 optsWithGlobals
|
|
150
|
+
// 读取(值挂在 root 上,本地 this.opts().yes 为 undefined),否则非交互场景确认门会误拦。
|
|
151
|
+
.action(async function (paths) {
|
|
152
|
+
await (0, index_1.handleFileRm)(paths, { ...this.optsWithGlobals(), appId: (0, shared_1.resolveAppId)({}) });
|
|
152
153
|
})
|
|
153
154
|
.addHelpText('after', `
|
|
154
155
|
Notes:
|
|
@@ -9,14 +9,11 @@ const index_4 = require("../../cli/commands/app/index");
|
|
|
9
9
|
const index_5 = require("../../cli/commands/deploy/index");
|
|
10
10
|
const modern_1 = require("../../cli/commands/deploy/modern");
|
|
11
11
|
const index_6 = require("../../cli/commands/skills/index");
|
|
12
|
-
const index_7 = require("../../cli/commands/comment/index");
|
|
13
|
-
const index_8 = require("../../cli/commands/registry/index");
|
|
14
12
|
// scene 跟 dispatcher(MIAODA_APP_TYPE)同语义层级 —— app 业务类型维度,
|
|
15
13
|
// 对齐后端 devops app_common.AppType 枚举:
|
|
16
14
|
// 3 = AppType_APPLICATION(全栈应用,当前仅 nestjs-react-fullstack 一个 stack)
|
|
17
15
|
// 4 = AppType_DESIGN(design-stack,SSR 渲染、无业务逻辑、无数据库)
|
|
18
16
|
// 7 = miaoda-cli 自定义 modern 占位(后端枚举无 7,沙箱目前不传)
|
|
19
|
-
// 8 = AppType_DESIGN_HTML(design-html,buildless 静态 HTML,命令集同 modern)
|
|
20
17
|
// 其它(0/1/2/5/6 / 未设)→ default(命令全开,本地 dev / CI / 兼容回退)
|
|
21
18
|
// stack 维度(nestjs-react-fullstack / vite-react / ...)是正交的,
|
|
22
19
|
// skills sync 内部按 .spark/meta.json.stack 拉对应 coding-steering/steering/<stack>/ 子目录。
|
|
@@ -27,8 +24,6 @@ function resolveScene(appType, _archType) {
|
|
|
27
24
|
return 'application';
|
|
28
25
|
if (appType === '4')
|
|
29
26
|
return 'design';
|
|
30
|
-
if (appType === '8')
|
|
31
|
-
return 'design-html';
|
|
32
27
|
return 'default';
|
|
33
28
|
}
|
|
34
29
|
const SCENE_REGISTRARS = {
|
|
@@ -42,13 +37,11 @@ const SCENE_REGISTRARS = {
|
|
|
42
37
|
(0, index_1.registerFileCommands)(p);
|
|
43
38
|
(0, index_3.registerObservabilityCommands)(p);
|
|
44
39
|
(0, index_6.registerSkillsCommands)(p);
|
|
45
|
-
(0, index_7.registerCommentCommands)(p);
|
|
46
40
|
},
|
|
47
41
|
modern: (p) => {
|
|
48
42
|
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
49
43
|
(0, modern_1.registerDeployCommandsModern)(p);
|
|
50
44
|
(0, index_6.registerSkillsCommands)(p);
|
|
51
|
-
(0, index_7.registerCommentCommands)(p);
|
|
52
45
|
},
|
|
53
46
|
// application scene(AppType_APPLICATION=3):
|
|
54
47
|
// 在 default 命令集基础上加 skills(按 meta.json.stack 拉对应 stack 技能)
|
|
@@ -60,7 +53,6 @@ const SCENE_REGISTRARS = {
|
|
|
60
53
|
(0, index_1.registerFileCommands)(p);
|
|
61
54
|
(0, index_3.registerObservabilityCommands)(p);
|
|
62
55
|
(0, index_6.registerSkillsCommands)(p);
|
|
63
|
-
(0, index_7.registerCommentCommands)(p);
|
|
64
56
|
},
|
|
65
57
|
// design scene(AppType_DESIGN=4):design-stack 仅 SSR 渲染、无后端业务逻辑、
|
|
66
58
|
// 无数据库、无 UGC 文件。命令集裁掉 db / file,保留 deploy / observability / app(init) / skills。
|
|
@@ -69,17 +61,6 @@ const SCENE_REGISTRARS = {
|
|
|
69
61
|
(0, index_5.registerDeployCommands)(p);
|
|
70
62
|
(0, index_3.registerObservabilityCommands)(p);
|
|
71
63
|
(0, index_6.registerSkillsCommands)(p);
|
|
72
|
-
(0, index_7.registerCommentCommands)(p);
|
|
73
|
-
},
|
|
74
|
-
// design-html scene(AppType_DESIGN_HTML=8):buildless 静态 HTML,
|
|
75
|
-
// 命令集与 modern 一致(app init/sync + modern 拆分版 deploy + skills),不挂 db/file/observability。
|
|
76
|
-
// 额外挂 registry(shadcn 式 copy-in SDK,design-html scene 专属)。
|
|
77
|
-
'design-html': (p) => {
|
|
78
|
-
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
79
|
-
(0, modern_1.registerDeployCommandsModern)(p);
|
|
80
|
-
(0, index_6.registerSkillsCommands)(p);
|
|
81
|
-
(0, index_8.registerRegistryCommands)(p);
|
|
82
|
-
(0, index_7.registerCommentCommands)(p);
|
|
83
64
|
},
|
|
84
65
|
};
|
|
85
66
|
function readEnv(name) {
|
|
@@ -51,30 +51,18 @@ async function handleAppInit(opts) {
|
|
|
51
51
|
});
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
const stack = opts.template;
|
|
55
|
-
if (!stack) {
|
|
56
|
-
throw new error_1.AppError('ARGS_INVALID', '缺少 --template <stack>', {
|
|
57
|
-
next_actions: [`可用 stack:${index_1.SUPPORTED_STACKS.join(', ')}`],
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if (!index_1.SUPPORTED_STACKS.includes(stack)) {
|
|
61
|
-
throw new error_1.AppError('ARGS_INVALID', `不支持的 template: ${stack}`, {
|
|
62
|
-
next_actions: [`可用 stack:${index_1.SUPPORTED_STACKS.join(', ')}`],
|
|
63
|
-
});
|
|
64
|
-
}
|
|
54
|
+
const stack = (0, index_1.resolveStack)({ template: opts.template, appType: opts.appType });
|
|
65
55
|
if (opts.asyncInstall && opts.skipInstall) {
|
|
66
56
|
throw new error_1.AppError('ARGS_INVALID', '--async-install 与 --skip-install 互斥');
|
|
67
57
|
}
|
|
68
58
|
const version = opts.conf?.version;
|
|
69
59
|
const projectName = node_path_1.default.basename(targetDir);
|
|
70
60
|
const tplResult = (0, index_1.renderTemplate)({ stack, version, targetDir, projectName });
|
|
61
|
+
// source_path 导入:当前仅 app_type=modern_html 生效。渲染完模板后、装依赖前叠加进 src/。
|
|
62
|
+
const sourceImport = applySourcePathImport(opts, targetDir);
|
|
71
63
|
// 先建 logs/,防止 user 跑 dev 之前 AI/工具 redirect 到 logs/*.log 因为父目录不存在直接挂
|
|
72
|
-
// (dev.js / dev-local.js 自己也建 logs/,但只在它启动后;启动前的 shell redirect 会先于此)
|
|
73
|
-
|
|
74
|
-
// 不预建 logs/ 以免在沙箱工作区留空目录。
|
|
75
|
-
if (!(0, env_1.isSandboxEnv)()) {
|
|
76
|
-
(0, logs_dir_1.ensureLogsDir)(targetDir);
|
|
77
|
-
}
|
|
64
|
+
// (dev.js / dev-local.js 自己也建 logs/,但只在它启动后;启动前的 shell redirect 会先于此)
|
|
65
|
+
(0, logs_dir_1.ensureLogsDir)(targetDir);
|
|
78
66
|
// skills 同步软失败:拉不到 coding-steering 包不该阻断 writeSparkMeta /
|
|
79
67
|
// activateGitHooks(之前会让 .spark/meta.json 没写,下次 init 半渲染状态又得重跑全套)。
|
|
80
68
|
// 按运行环境(isSandboxEnv:MIAODA_DEP_CACHE_DIR 非空)分流 outputLayout,不绑 stack:
|
|
@@ -139,6 +127,11 @@ async function handleAppInit(opts) {
|
|
|
139
127
|
steeringVersion: steeringResult.version,
|
|
140
128
|
archType: tplResult.archType,
|
|
141
129
|
appId: opts.appId,
|
|
130
|
+
appType: opts.appType,
|
|
131
|
+
sourcePath: opts.sourcePath,
|
|
132
|
+
sourceImported: sourceImport.sourceImported,
|
|
133
|
+
importedFileCount: sourceImport.importedFileCount,
|
|
134
|
+
sourceIgnoredReason: sourceImport.sourceIgnoredReason,
|
|
142
135
|
syncedSkills: steeringResult.syncedSkills,
|
|
143
136
|
techSynced: steeringResult.techSynced,
|
|
144
137
|
steeringError,
|
|
@@ -163,3 +156,25 @@ async function handleAppInit(opts) {
|
|
|
163
156
|
},
|
|
164
157
|
});
|
|
165
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* 处理 --source-path 导入:当前仅 app_type=modern_html 生效。
|
|
161
|
+
* - 未传 source_path → 什么都不做
|
|
162
|
+
* - modern_html → 调 importSourceSrc 把源目录聚合进 targetDir/src/
|
|
163
|
+
* - 传了 source_path 但非 modern_html → 警告并忽略,继续正常 init(退出码 0)
|
|
164
|
+
* 终端提示留在 handler 层(service 不做终端输出)。
|
|
165
|
+
*/
|
|
166
|
+
function applySourcePathImport(opts, targetDir) {
|
|
167
|
+
// 真值判断:未传或空串都视为"无 source_path"。
|
|
168
|
+
if (!opts.sourcePath) {
|
|
169
|
+
return { sourceImported: false };
|
|
170
|
+
}
|
|
171
|
+
if (opts.appType === 'modern_html') {
|
|
172
|
+
const { importedFileCount } = (0, index_1.importSourceSrc)({ sourcePath: opts.sourcePath, targetDir });
|
|
173
|
+
return { sourceImported: true, importedFileCount };
|
|
174
|
+
}
|
|
175
|
+
(0, logger_1.log)('init', '⚠ source-path ignored: 仅 app_type=modern_html 支持 source_path 导入');
|
|
176
|
+
if (!(0, output_1.isJsonMode)()) {
|
|
177
|
+
process.stdout.write('⚠ 不支持 source_path(仅 app_type=modern_html 生效),已忽略\n');
|
|
178
|
+
}
|
|
179
|
+
return { sourceImported: false, sourceIgnoredReason: 'not_modern_html' };
|
|
180
|
+
}
|
|
@@ -135,6 +135,32 @@ async function handleAppMigrate(opts) {
|
|
|
135
135
|
installError = err instanceof Error ? err.message : String(err);
|
|
136
136
|
(0, logger_1.log)('migrate', `⚠ npm install failed (continuing): ${installError}`);
|
|
137
137
|
}
|
|
138
|
+
// 重启 dev process 前清 vite cache —— migrate 改了 package.json + lockfile,
|
|
139
|
+
// 老 vite 进程的 .vite/deps cache 的 lockfileHash 跟新 lockfile 不一致。
|
|
140
|
+
// 不清的话 supervisor 拉起的新 vite cold start 会立即 "Re-optimizing because
|
|
141
|
+
// lockfile has changed", re-optimize 期间 ModuleGraph transform cache 跟
|
|
142
|
+
// deps middleware metadata 短暂不同步, 浏览器请求老 hash 触发
|
|
143
|
+
// ERR_OUTDATED_OPTIMIZED_DEP → 504 死锁(详见 fullstack-plugin#1143 的 504
|
|
144
|
+
// ignoreOutdatedRequests fix 注释)。直接 rm -rf 让新 vite 从干净状态 cold
|
|
145
|
+
// optimize, 一次写到位 lockfile 一致的 metadata, 不再触发中途 re-optimize。
|
|
146
|
+
//
|
|
147
|
+
// - 只在 SANDBOX_ID 非空时做(本地一般不会撞这条链路)
|
|
148
|
+
// - 只在 install 成功时做(install 挂了 node_modules 状态不对, 清 cache 也救不回来)
|
|
149
|
+
// - 软失败:.vite 不存在 / 删失败都不阻断
|
|
150
|
+
if (installError === undefined &&
|
|
151
|
+
process.env.SANDBOX_ID !== undefined &&
|
|
152
|
+
process.env.SANDBOX_ID !== '') {
|
|
153
|
+
const viteCacheDir = node_path_1.default.join(targetDir, 'node_modules', '.vite');
|
|
154
|
+
if (node_fs_1.default.existsSync(viteCacheDir)) {
|
|
155
|
+
(0, logger_1.log)('migrate', '清理 node_modules/.vite (vite cache 跟新 lockfile 错位会 504)...');
|
|
156
|
+
try {
|
|
157
|
+
node_fs_1.default.rmSync(viteCacheDir, { recursive: true, force: true });
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
(0, logger_1.log)('migrate', `⚠ 清 .vite 失败 (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
138
164
|
// 沙箱环境下重启 dev process —— scripts/dev.js 被 fullstack 版本覆盖了,但当前正在
|
|
139
165
|
// 跑的 node 进程仍按老逻辑工作(只起 vite,没起 nest),整体没切到 fullstack 模式。
|
|
140
166
|
// 通过 pkill 杀掉 dev.js 主进程,依赖沙箱平台 supervisor 自动重新 exec dev.sh → dev.js,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DEFAULT_POLL_INTERVAL_MS = exports.waitForPipeline = exports.handleDeployErrorLog = exports.handleDeployHistory = exports.handleDeployGet = exports.handleDeploy = void 0;
|
|
4
4
|
var deploy_1 = require("./deploy");
|
|
5
5
|
Object.defineProperty(exports, "handleDeploy", { enumerable: true, get: function () { return deploy_1.handleDeploy; } });
|
|
6
6
|
var get_1 = require("./get");
|
|
@@ -12,5 +12,3 @@ Object.defineProperty(exports, "handleDeployErrorLog", { enumerable: true, get:
|
|
|
12
12
|
var polling_1 = require("./polling");
|
|
13
13
|
Object.defineProperty(exports, "waitForPipeline", { enumerable: true, get: function () { return polling_1.waitForPipeline; } });
|
|
14
14
|
Object.defineProperty(exports, "DEFAULT_POLL_INTERVAL_MS", { enumerable: true, get: function () { return polling_1.DEFAULT_POLL_INTERVAL_MS; } });
|
|
15
|
-
var patch_1 = require("./patch");
|
|
16
|
-
Object.defineProperty(exports, "handleDeployPatch", { enumerable: true, get: function () { return patch_1.handleDeployPatch; } });
|
|
@@ -15,13 +15,8 @@ const output_1 = require("../../../utils/output");
|
|
|
15
15
|
* 从 .spark/meta.json 读 stack,把 coding-steering 包内对应 stack 的 skills + tech.md
|
|
16
16
|
* 同步到 <dir>/.agent/steering/。需要先跑过 `miaoda app init`。
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* 2. `FORCE_FRAMEWORK_ENVIRONMENT=boe` → dist-tag `dev`(BOE 测试灰度,跟随
|
|
21
|
-
* publish-alpha.sh 在 develop 分支打的 dev tag,便于在 BOE 沙箱里验证预发 steering)
|
|
22
|
-
* 3. 默认 `latest`
|
|
23
|
-
*
|
|
24
|
-
* **不读 meta.json**——steering 版本不在 meta 里钉。
|
|
18
|
+
* 版本来源:CLI `--version` flag 或默认 `latest`。**不读 meta.json**——steering 版本
|
|
19
|
+
* 不在 meta 里钉,每次 sync 都跟随 `--version` 显式传或退回 @latest。
|
|
25
20
|
*/
|
|
26
21
|
async function handleSkillsSync(opts) {
|
|
27
22
|
await Promise.resolve();
|
|
@@ -30,20 +25,17 @@ async function handleSkillsSync(opts) {
|
|
|
30
25
|
if (meta.stack === undefined || meta.stack === '') {
|
|
31
26
|
throw new error_1.AppError('SKILLS_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
32
27
|
}
|
|
33
|
-
const isBoe = process.env.FORCE_FRAMEWORK_ENVIRONMENT === 'boe';
|
|
34
|
-
const effectiveVersion = opts.version ?? (isBoe ? 'dev' : undefined);
|
|
35
|
-
const versionSource = opts.version !== undefined ? 'cli-arg' : isBoe ? 'boe-default-dev' : 'default-latest';
|
|
36
28
|
const result = (0, coding_steering_1.syncCodingSteering)({
|
|
37
29
|
stack: meta.stack,
|
|
38
30
|
targetDir,
|
|
39
|
-
version:
|
|
31
|
+
version: opts.version,
|
|
40
32
|
outputLayout: opts.local === true ? 'flat' : 'nested',
|
|
41
33
|
});
|
|
42
34
|
(0, output_1.emit)({
|
|
43
35
|
data: {
|
|
44
36
|
stack: meta.stack,
|
|
45
37
|
version: result.version,
|
|
46
|
-
versionSource,
|
|
38
|
+
versionSource: opts.version !== undefined ? 'cli-arg' : 'default-latest',
|
|
47
39
|
syncedSkills: result.syncedSkills,
|
|
48
40
|
techSynced: result.techSynced,
|
|
49
41
|
...(result.claudeSkillsLink !== undefined
|
|
@@ -70,6 +70,11 @@ exports.MIGRATE_CONFIG = {
|
|
|
70
70
|
// ESLint 9 flat config —— vite-react 用 eslint.config.mjs 已删,fullstack 用
|
|
71
71
|
// eslint.config.js (commonjs) + extends @lark-apaas/fullstack-presets;user 通常不改
|
|
72
72
|
{ type: 'file', from: 'eslint.config.js', to: 'eslint.config.js', overwrite: true },
|
|
73
|
+
// stylelint 配置 —— package.json 加了 `stylelint` script(下面 add-script 那条)
|
|
74
|
+
// + npm run precommit 会调它,缺配置文件时报 `No configuration provided for
|
|
75
|
+
// client/src/index.css`。fullstack template 的 .stylelintrc.js extends
|
|
76
|
+
// @lark-apaas/fullstack-presets 的 stylelintPresetsOfSimple。
|
|
77
|
+
{ type: 'file', from: '.stylelintrc.js', to: '.stylelintrc.js', overwrite: true },
|
|
73
78
|
// client/index.html:HBS 模板(fullstack 用,vite-react 用根 index.html 已删)
|
|
74
79
|
{ type: 'file', from: 'client/index.html', to: 'client/index.html', overwrite: true },
|
|
75
80
|
// scripts/ 整目录:fullstack 形态启动 / 构建 / lint 所需的 8 个平台脚本(dev.sh /
|
|
@@ -274,6 +279,10 @@ exports.MIGRATE_CONFIG = {
|
|
|
274
279
|
// (@lark-apaas/fullstack-presets/lib/simple/tsconfig/tsconfig.node.json);
|
|
275
280
|
// 不装会导致 nest build / type:check:server / vite dev 解析 tsconfig 时 ENOENT
|
|
276
281
|
'@lark-apaas/fullstack-presets',
|
|
282
|
+
// stylelint —— scripts.stylelint + npm run precommit 会调它,
|
|
283
|
+
// 缺依赖时 CI / 本地 precommit 报 "stylelint: command not found"。
|
|
284
|
+
// 配套的 .stylelintrc.js 由上面 file rule 从 template 搬过来。
|
|
285
|
+
'stylelint',
|
|
277
286
|
],
|
|
278
287
|
},
|
|
279
288
|
// ===== 7. 业务代码 codemod:lite → client-toolkit 包名替换 =====
|
package/dist/main.js
CHANGED
|
@@ -30,6 +30,9 @@ program
|
|
|
30
30
|
.argParser((0, shared_1.caseInsensitiveChoice)(['pretty', 'json']))
|
|
31
31
|
.default('pretty'))
|
|
32
32
|
.option('--verbose', 'debug 日志到 stderr')
|
|
33
|
+
// 全局接受 -y/--yes:作为 root 全局 option 下发到所有子命令解析(同 --json/--verbose),
|
|
34
|
+
// 让任意命令带 --yes 都不报 unknown option。对有确认门的破坏性命令生效,其余命令忽略。
|
|
35
|
+
.option('-y, --yes', '跳过确认提示(对有确认门的命令生效,其余命令忽略)')
|
|
33
36
|
.helpOption('-h, --help', '显示帮助信息')
|
|
34
37
|
.hook('preAction', (_thisCmd, actionCmd) => {
|
|
35
38
|
(0, log_id_1.generateLogId)();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.IMPORT_SKIP_FILES = exports.IMPORT_SKIP_DIRS = void 0;
|
|
7
|
+
exports.importSourceSrc = importSourceSrc;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const error_1 = require("../../../utils/error");
|
|
11
|
+
const logger_1 = require("../../../utils/logger");
|
|
12
|
+
/** 导入时跳过的目录名(任意层级命中即整目录跳过)。 */
|
|
13
|
+
exports.IMPORT_SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build']);
|
|
14
|
+
/** 导入时跳过的精确文件名。`.env.*`(如 .env.local)另由前缀规则处理。 */
|
|
15
|
+
exports.IMPORT_SKIP_FILES = new Set([
|
|
16
|
+
'.env',
|
|
17
|
+
'.DS_Store',
|
|
18
|
+
'.npmrc',
|
|
19
|
+
'package.json',
|
|
20
|
+
'package-lock.json',
|
|
21
|
+
'yarn.lock',
|
|
22
|
+
'pnpm-lock.yaml',
|
|
23
|
+
]);
|
|
24
|
+
function isSkippedFile(name) {
|
|
25
|
+
if (exports.IMPORT_SKIP_FILES.has(name))
|
|
26
|
+
return true;
|
|
27
|
+
// .env.local / .env.production 等一律跳过
|
|
28
|
+
if (name.startsWith('.env.'))
|
|
29
|
+
return true;
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 把整个 sourcePath 递归拷进 targetDir/src/(叠加,同名覆盖,不删目标已有文件),
|
|
34
|
+
* 按 IMPORT_SKIP_DIRS / IMPORT_SKIP_FILES 过滤。
|
|
35
|
+
* sourcePath 不存在或非目录 → 抛 ARGS_INVALID。
|
|
36
|
+
*/
|
|
37
|
+
function importSourceSrc(opts) {
|
|
38
|
+
const sourcePath = node_path_1.default.resolve(opts.sourcePath);
|
|
39
|
+
if (!node_fs_1.default.existsSync(sourcePath) || !node_fs_1.default.statSync(sourcePath).isDirectory()) {
|
|
40
|
+
throw new error_1.AppError('ARGS_INVALID', `--source-path 不存在或不是目录: ${opts.sourcePath}`);
|
|
41
|
+
}
|
|
42
|
+
const destSrc = node_path_1.default.join(opts.targetDir, 'src');
|
|
43
|
+
node_fs_1.default.mkdirSync(destSrc, { recursive: true });
|
|
44
|
+
let count = 0;
|
|
45
|
+
const walk = (relDir) => {
|
|
46
|
+
const absDir = node_path_1.default.join(sourcePath, relDir);
|
|
47
|
+
for (const entry of node_fs_1.default.readdirSync(absDir, { withFileTypes: true })) {
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
if (exports.IMPORT_SKIP_DIRS.has(entry.name))
|
|
50
|
+
continue;
|
|
51
|
+
walk(node_path_1.default.join(relDir, entry.name));
|
|
52
|
+
}
|
|
53
|
+
else if (entry.isFile()) {
|
|
54
|
+
if (isSkippedFile(entry.name))
|
|
55
|
+
continue;
|
|
56
|
+
const rel = node_path_1.default.join(relDir, entry.name);
|
|
57
|
+
const dest = node_path_1.default.join(destSrc, rel);
|
|
58
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(dest), { recursive: true });
|
|
59
|
+
node_fs_1.default.copyFileSync(node_path_1.default.join(sourcePath, rel), dest);
|
|
60
|
+
count += 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
walk('.');
|
|
65
|
+
(0, logger_1.log)('init', `Imported ${String(count)} file(s) from ${sourcePath} → src/`);
|
|
66
|
+
return { importedFileCount: count };
|
|
67
|
+
}
|