@lark-apaas/miaoda-cli 0.1.5-beta.27ede41 → 0.1.6-alpha.388541c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/app/index.js +66 -6
- package/dist/cli/commands/index.js +36 -1
- package/dist/cli/commands/skills/index.js +18 -2
- package/dist/cli/handlers/app/index.js +4 -1
- package/dist/cli/handlers/app/init.js +53 -9
- package/dist/cli/handlers/app/sync.js +219 -0
- package/dist/cli/handlers/skills/sync.js +15 -4
- package/dist/config/fullstack-cli-pin.js +17 -0
- package/dist/config/sync-configs/design-stack.js +98 -0
- package/dist/config/sync-configs/index.js +62 -0
- package/dist/config/sync-configs/nestjs-react-fullstack.js +177 -0
- package/dist/config/sync.js +14 -0
- package/dist/services/app/init/install.js +35 -13
- package/dist/services/app/init/template.js +28 -6
- package/dist/utils/coding-steering.js +112 -28
- package/dist/utils/file-ops.js +45 -0
- package/dist/utils/githooks.js +55 -0
- package/dist/utils/merge-json.js +63 -0
- package/dist/utils/platform-sync.js +160 -0
- package/dist/utils/sync-rule.js +295 -0
- package/package.json +5 -3
- package/upgrade/templates/README.md +34 -0
- package/upgrade/templates/design-stack/templates/.githooks/pre-commit +4 -0
- package/upgrade/templates/design-stack/templates/scripts/dev-local.sh +53 -0
- package/upgrade/templates/design-stack/templates/scripts/dev.sh +25 -0
- package/upgrade/templates/design-stack/templates/scripts/hooks/run-precommit.js +37 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.githooks/pre-commit +4 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.gitignore.append +8 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/.spark_project +16 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/drizzle.config.ts +55 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/helper/gen-openapi.ts +34 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/nest-cli.json +25 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/build.sh +207 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev-local.sh +61 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev.js +295 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/dev.sh +25 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/hooks/run-precommit.js +37 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/lint.js +150 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/prune-smart.js +330 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/scripts/run.sh +8 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/server/global.d.ts +19 -0
- package/upgrade/templates/nestjs-react-fullstack/templates/tsconfig.node.json +5 -0
|
@@ -6,7 +6,7 @@ const index_1 = require("../../../cli/handlers/app/index");
|
|
|
6
6
|
const error_1 = require("../../../utils/error");
|
|
7
7
|
function registerAppCommands(program, opts = {}) {
|
|
8
8
|
const description = opts.includeInit
|
|
9
|
-
? '应用元数据管理:查看 / 修改 / 初始化'
|
|
9
|
+
? '应用元数据管理:查看 / 修改 / 初始化 / 升级平台资产'
|
|
10
10
|
: '应用元数据管理:查看 / 修改';
|
|
11
11
|
const appCmd = program.command('app').description(description);
|
|
12
12
|
appCmd.action(() => {
|
|
@@ -21,8 +21,57 @@ function registerAppCommands(program, opts = {}) {
|
|
|
21
21
|
registerAppUpdate(appCmd);
|
|
22
22
|
if (opts.includeInit) {
|
|
23
23
|
registerAppInit(appCmd);
|
|
24
|
+
registerAppSync(appCmd);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
function registerAppSync(parent) {
|
|
28
|
+
const cmd = parent
|
|
29
|
+
.command('sync')
|
|
30
|
+
.alias('upgrade')
|
|
31
|
+
.description('一站式同步:按 stack 的 SyncRule 全套 apply + 按钉死版本表升 @lark-apaas/* deps + npm install')
|
|
32
|
+
.option('--dir <path>', '项目目录,默认 cwd(需含 .spark/meta.json)')
|
|
33
|
+
.addHelpText('after', `
|
|
34
|
+
别名
|
|
35
|
+
miaoda app sync 与 miaoda app upgrade 等价(upgrade 是历史别名,新调用方请用 sync)。
|
|
36
|
+
|
|
37
|
+
流程
|
|
38
|
+
1. 按 stack 的 SyncRule[] 全套 apply(src/config/sync-configs/<stack>.ts 定义):
|
|
39
|
+
directory → 整个目录拷贝(.sh 自动 +x)
|
|
40
|
+
file → 单文件覆盖(可选 onlyIfExists / overwrite)
|
|
41
|
+
merge-json → JSON deep merge(可选 arrayMerge by key 去重)
|
|
42
|
+
add-script → npm script 不存在时添加(overwrite=false 默认不覆盖)
|
|
43
|
+
patch-script → npm script 以指定前缀开头时改写(守护用户自定义)
|
|
44
|
+
add-line → 行不存在时追加到文件
|
|
45
|
+
remove-line → 行存在时移除
|
|
46
|
+
delete-file/delete-directory → 删除
|
|
47
|
+
沙箱里跑的 fullstack-cli sync 走同一套 rule 类型,行为对齐;miaoda app sync 在此之上
|
|
48
|
+
补 dev:local 等本地开发独有规则。
|
|
49
|
+
2. 平台 deps 钉版本:按 handlers/app/sync.ts 里 PINNED_PLATFORM_VERSIONS 升 user app 已装的
|
|
50
|
+
@lark-apaas/* 包;表外 / 未装的不动。
|
|
51
|
+
3. activateGitHooks:core.hooksPath 一次性指向 .githooks/。
|
|
52
|
+
4. npm install --no-audit --no-fund --ignore-scripts。--ignore-scripts 是为绕开
|
|
53
|
+
action-plugin postinstall 在 npm install 时缺平台 env 的卡点(需要时再
|
|
54
|
+
FORCE_AUTHN_INNERAPI_DOMAIN=... npm install 手动跑一次)。
|
|
55
|
+
|
|
56
|
+
JSON 输出
|
|
57
|
+
{"data": {"stack": "...",
|
|
58
|
+
"appliedRules": [{"type": "...", "action": "...", "path": "...", "detail": "..."}],
|
|
59
|
+
"syncedFiles": [...],
|
|
60
|
+
"mergedJsonFiles": [{"path": "...", "keys": [...]}],
|
|
61
|
+
"patchedScripts": [...],
|
|
62
|
+
"upgradedPackages": [{"name": "...", "from": "...", "to": "...", "section": "..."}]}}
|
|
63
|
+
|
|
64
|
+
示例
|
|
65
|
+
$ miaoda app sync
|
|
66
|
+
$ miaoda app sync --dir /path/to/app
|
|
67
|
+
$ miaoda app upgrade # 等价于 miaoda app sync
|
|
68
|
+
`);
|
|
69
|
+
cmd.action((0, shared_1.withHelp)(cmd, async (rawOpts) => {
|
|
70
|
+
await (0, index_1.handleAppSync)({
|
|
71
|
+
dir: rawOpts.dir,
|
|
72
|
+
});
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
26
75
|
function registerAppGet(parent) {
|
|
27
76
|
const cmd = parent
|
|
28
77
|
.command('get')
|
|
@@ -70,20 +119,28 @@ JSON 输出
|
|
|
70
119
|
function registerAppInit(parent) {
|
|
71
120
|
const cmd = parent
|
|
72
121
|
.command('init')
|
|
73
|
-
.description('初始化应用代码:抓 template
|
|
122
|
+
.description('初始化应用代码:抓 template 渲染、同步 upgrade/templates、装 .agent/steering/ skills、写 .spark/meta.json。.spark/meta.json 已存在则直接退出')
|
|
74
123
|
.option('--template <stack>', `技术栈短名(${index_1.SUPPORTED_STACKS.join(' / ')})`)
|
|
75
124
|
.option('--conf <json>', 'init 配置 JSON。支持 {"version": "<template 版本>"} / {"steeringVersion": "<steering 版本>"},均默认 latest')
|
|
76
125
|
.option('--skip-install', '跳过依赖安装', false)
|
|
126
|
+
.addOption((0, shared_1.appIdOption)())
|
|
77
127
|
.addHelpText('after', `
|
|
78
128
|
幂等
|
|
79
129
|
.spark/meta.json 已存在时直接退出(initialized=false, reason=already_initialized),
|
|
80
|
-
不再触发 template
|
|
130
|
+
不再触发 template 渲染、不重新跑 upgrade/templates 同步、不重新拉 skills、不安装依赖。
|
|
81
131
|
meta.json 在 init 流程最后才写,写了 = 已完整成功一次;
|
|
82
132
|
上一次失败留下半渲染状态时(package.json 在但 meta.json 没在)允许重跑。
|
|
83
133
|
|
|
84
|
-
应用身份(
|
|
85
|
-
|
|
86
|
-
|
|
134
|
+
应用身份(app_id)
|
|
135
|
+
--app-id <id>(或 MIAODA_APP_ID env)提供时写入 .spark/meta.json 的 app_id 字段;
|
|
136
|
+
未提供则不写。运行端命令(deploy / file / plugin 等)仍优先读 MIAODA_APP_ID env,
|
|
137
|
+
env 未设置时回退到 meta.json.app_id。
|
|
138
|
+
|
|
139
|
+
平台同步(upgrade/templates)
|
|
140
|
+
init 内嵌一次 upgrade/templates 同步(跟 app upgrade 共用同一份 util):
|
|
141
|
+
从 miaoda-cli 自带的 upgrade/templates/<stack>/ 同步 files/(覆盖)+ patches/
|
|
142
|
+
(JSON deep merge,含 scripts.dev:local 等)。目标 stack 未纳入 upgrade/templates/
|
|
143
|
+
时跳过(不报错)。后续要升 @lark-apaas/* 平台包到最新 alpha,跑 'miaoda app upgrade'。
|
|
87
144
|
|
|
88
145
|
依赖安装
|
|
89
146
|
默认:npm install --no-audit --no-fund
|
|
@@ -97,10 +154,12 @@ function registerAppInit(parent) {
|
|
|
97
154
|
JSON 输出
|
|
98
155
|
已初始化:{"data": {"initialized": false, "reason": "already_initialized", "targetDir": "..."}}
|
|
99
156
|
新初始化:{"data": {"initialized": true, "template": "...", "templateVersion": "...", "steeringVersion": "...",
|
|
157
|
+
"appId": "...", "platformStackFound": true, "platformSyncedFiles": [...],
|
|
100
158
|
"installed": true, "installSource": "cache|npm|skipped", "installHash": "...", ...}}
|
|
101
159
|
|
|
102
160
|
示例
|
|
103
161
|
$ miaoda app init --template vite-react
|
|
162
|
+
$ miaoda app init --template nestjs-react-fullstack --app-id app_xxx
|
|
104
163
|
$ miaoda app init --template vite-react --conf '{"version": "0.1.0-alpha.1"}'
|
|
105
164
|
$ miaoda app init --template vite-react --conf '{"steeringVersion": "0.1.0"}'
|
|
106
165
|
$ miaoda app init --template vite-react --skip-install
|
|
@@ -112,6 +171,7 @@ JSON 输出
|
|
|
112
171
|
template: rawOpts.template,
|
|
113
172
|
conf,
|
|
114
173
|
skipInstall: rawOpts.skipInstall,
|
|
174
|
+
appId: rawOpts.appId,
|
|
115
175
|
});
|
|
116
176
|
}));
|
|
117
177
|
}
|
|
@@ -9,24 +9,59 @@ 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
|
+
// scene 跟 dispatcher(MIAODA_APP_TYPE)同语义层级 —— app 业务类型维度,
|
|
13
|
+
// 对齐后端 devops app_common.AppType 枚举:
|
|
14
|
+
// 3 = AppType_APPLICATION(全栈应用,当前仅 nestjs-react-fullstack 一个 stack)
|
|
15
|
+
// 4 = AppType_DESIGN(design-stack,SSR 渲染、无业务逻辑、无数据库)
|
|
16
|
+
// 7 = miaoda-cli 自定义 modern 占位(后端枚举无 7,沙箱目前不传)
|
|
17
|
+
// 其它(0/1/2/5/6 / 未设)→ default(命令全开,本地 dev / CI / 兼容回退)
|
|
18
|
+
// stack 维度(nestjs-react-fullstack / vite-react / ...)是正交的,
|
|
19
|
+
// skills sync 内部按 .spark/meta.json.stack 拉对应 coding-steering/steering/<stack>/ 子目录。
|
|
12
20
|
function resolveScene(appType, _archType) {
|
|
13
21
|
if (appType === '7')
|
|
14
22
|
return 'modern';
|
|
23
|
+
if (appType === '3')
|
|
24
|
+
return 'application';
|
|
25
|
+
if (appType === '4')
|
|
26
|
+
return 'design';
|
|
15
27
|
return 'default';
|
|
16
28
|
}
|
|
17
29
|
const SCENE_REGISTRARS = {
|
|
18
30
|
default: (p) => {
|
|
19
|
-
|
|
31
|
+
// init / upgrade / skills 都挂出来:本地用户不需要 export MIAODA_APP_TYPE=3
|
|
32
|
+
// 就能跑 `miaoda app init` / `miaoda app upgrade` / `miaoda skills sync`。
|
|
33
|
+
// 其它 scene 的差异(design 裁 db/file,modern 拆 deploy)仍按 MIAODA_APP_TYPE 路由
|
|
34
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
20
35
|
(0, index_5.registerDeployCommands)(p);
|
|
21
36
|
(0, index_2.registerDbCommands)(p);
|
|
22
37
|
(0, index_1.registerFileCommands)(p);
|
|
23
38
|
(0, index_3.registerObservabilityCommands)(p);
|
|
39
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
24
40
|
},
|
|
25
41
|
modern: (p) => {
|
|
26
42
|
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
27
43
|
(0, modern_1.registerDeployCommandsModern)(p);
|
|
28
44
|
(0, index_6.registerSkillsCommands)(p);
|
|
29
45
|
},
|
|
46
|
+
// application scene(AppType_APPLICATION=3):
|
|
47
|
+
// 在 default 命令集基础上加 skills(按 meta.json.stack 拉对应 stack 技能)
|
|
48
|
+
// + app init(新一代应用走 init 写 .spark/meta.json)
|
|
49
|
+
application: (p) => {
|
|
50
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
51
|
+
(0, index_5.registerDeployCommands)(p);
|
|
52
|
+
(0, index_2.registerDbCommands)(p);
|
|
53
|
+
(0, index_1.registerFileCommands)(p);
|
|
54
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
55
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
56
|
+
},
|
|
57
|
+
// design scene(AppType_DESIGN=4):design-stack 仅 SSR 渲染、无后端业务逻辑、
|
|
58
|
+
// 无数据库、无 UGC 文件。命令集裁掉 db / file,保留 deploy / observability / app(init) / skills。
|
|
59
|
+
design: (p) => {
|
|
60
|
+
(0, index_4.registerAppCommands)(p, { includeInit: true });
|
|
61
|
+
(0, index_5.registerDeployCommands)(p);
|
|
62
|
+
(0, index_3.registerObservabilityCommands)(p);
|
|
63
|
+
(0, index_6.registerSkillsCommands)(p);
|
|
64
|
+
},
|
|
30
65
|
};
|
|
31
66
|
function readEnv(name) {
|
|
32
67
|
const v = process.env[name]?.trim();
|
|
@@ -21,18 +21,33 @@ function registerSkillsCommands(program) {
|
|
|
21
21
|
function registerSkillsSync(parent) {
|
|
22
22
|
const cmd = parent
|
|
23
23
|
.command('sync')
|
|
24
|
-
.description('同步 coding-steering(latest 或指定版本)到
|
|
24
|
+
.description('同步 coding-steering(latest 或指定版本)到 user app')
|
|
25
25
|
.argument('[version]', 'coding-steering 包版本或 dist-tag,缺省 latest')
|
|
26
26
|
.option('--dir <path>', '项目目录,默认当前目录', '.')
|
|
27
|
+
.option('--local', '走本地 dev / agent 输出形态:拷到 .agents/skills 平铺 + 创建 .claude/skills 软链。' +
|
|
28
|
+
'不传时退回老形态:拷到 .agent/skills/steering/<stack>/skills/(跟沙箱端 update-skills.sh 对齐)', false)
|
|
27
29
|
.addHelpText('after', `
|
|
28
30
|
前置要求
|
|
29
31
|
当前目录(或 --dir)已走过 'miaoda app init'(.spark/meta.json 含 stack)
|
|
30
32
|
|
|
33
|
+
输出形态(--local 切换)
|
|
34
|
+
默认(不传 --local):
|
|
35
|
+
.agent/skills/steering/<stack>/skills/<skill>/...
|
|
36
|
+
.agent/skills/steering/<stack>/tech.md
|
|
37
|
+
(老链路,沙箱端 update-skills.sh 也输出这套结构)
|
|
38
|
+
|
|
39
|
+
传 --local:
|
|
40
|
+
.agents/skills/<skill>/... ← 平铺,无 stack 命名空间
|
|
41
|
+
.agents/tech.md
|
|
42
|
+
.claude/skills → ../.agents/skills(软链,让 Claude Code 识别同一份)
|
|
43
|
+
|
|
31
44
|
JSON 输出
|
|
32
|
-
{"data": {"stack": "...", "version": "...", "syncedSkills": [...], "techSynced": true|false
|
|
45
|
+
{"data": {"stack": "...", "version": "...", "syncedSkills": [...], "techSynced": true|false,
|
|
46
|
+
"claudeSkillsLink": "created|updated|noop|conflict" // 仅 --local 时}}
|
|
33
47
|
|
|
34
48
|
示例
|
|
35
49
|
$ miaoda skills sync
|
|
50
|
+
$ miaoda skills sync --local # 本地 dev / agent 用
|
|
36
51
|
$ miaoda skills sync 0.2.0
|
|
37
52
|
$ miaoda skills sync --dir ./my-app
|
|
38
53
|
`);
|
|
@@ -40,6 +55,7 @@ JSON 输出
|
|
|
40
55
|
await (0, index_1.handleSkillsSync)({
|
|
41
56
|
dir: rawOpts.dir,
|
|
42
57
|
version,
|
|
58
|
+
local: rawOpts.local,
|
|
43
59
|
});
|
|
44
60
|
}));
|
|
45
61
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SUPPORTED_STACKS = exports.handleAppInit = exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
3
|
+
exports.SUPPORTED_STACKS = exports.handleAppUpgrade = exports.handleAppSync = exports.handleAppInit = exports.handleAppUpdate = exports.handleAppGet = void 0;
|
|
4
4
|
var get_1 = require("./get");
|
|
5
5
|
Object.defineProperty(exports, "handleAppGet", { enumerable: true, get: function () { return get_1.handleAppGet; } });
|
|
6
6
|
var update_1 = require("./update");
|
|
7
7
|
Object.defineProperty(exports, "handleAppUpdate", { enumerable: true, get: function () { return update_1.handleAppUpdate; } });
|
|
8
8
|
var init_1 = require("./init");
|
|
9
9
|
Object.defineProperty(exports, "handleAppInit", { enumerable: true, get: function () { return init_1.handleAppInit; } });
|
|
10
|
+
var sync_1 = require("./sync");
|
|
11
|
+
Object.defineProperty(exports, "handleAppSync", { enumerable: true, get: function () { return sync_1.handleAppSync; } });
|
|
12
|
+
Object.defineProperty(exports, "handleAppUpgrade", { enumerable: true, get: function () { return sync_1.handleAppUpgrade; } });
|
|
10
13
|
// commands 层渲染 help 时需要这份枚举;从 handler barrel 转发,避免 commands → services 越界
|
|
11
14
|
var index_1 = require("../../../services/app/init/index");
|
|
12
15
|
Object.defineProperty(exports, "SUPPORTED_STACKS", { enumerable: true, get: function () { return index_1.SUPPORTED_STACKS; } });
|
|
@@ -8,13 +8,17 @@ const node_fs_1 = __importDefault(require("node:fs"));
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const index_1 = require("../../../services/app/init/index");
|
|
10
10
|
const coding_steering_1 = require("../../../utils/coding-steering");
|
|
11
|
+
const logger_1 = require("../../../utils/logger");
|
|
12
|
+
const githooks_1 = require("../../../utils/githooks");
|
|
13
|
+
const sync_1 = require("../../../cli/handlers/app/sync");
|
|
11
14
|
const error_1 = require("../../../utils/error");
|
|
12
15
|
const output_1 = require("../../../utils/output");
|
|
13
16
|
/**
|
|
14
17
|
* miaoda app init
|
|
15
18
|
*
|
|
16
|
-
*
|
|
17
|
-
* 写入 .spark/meta.json
|
|
19
|
+
* 一站式本地脚手架:render template → upgrade/templates sync → skills sync → install deps,把
|
|
20
|
+
* {stack, version, archType, app_id?} 写入 .spark/meta.json。--app-id(或 MIAODA_APP_ID)提供时
|
|
21
|
+
* 持久化 app_id;运行端命令仍优先读 env,未设置时回退到 meta.json。
|
|
18
22
|
*
|
|
19
23
|
* 幂等:.spark/meta.json 存在即表示已完整成功一次,直接退出,不重跑任何子步骤。
|
|
20
24
|
* 半渲染状态(package.json 在但 meta.json 不在)会重新跑完整流程。
|
|
@@ -50,24 +54,52 @@ async function handleAppInit(opts) {
|
|
|
50
54
|
const version = opts.conf?.version;
|
|
51
55
|
const projectName = node_path_1.default.basename(targetDir);
|
|
52
56
|
const tplResult = (0, index_1.renderTemplate)({ stack, version, targetDir, projectName });
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
// sync 紧跟 template 渲染之后,赶在 install 之前:
|
|
58
|
+
// 这样 directory / merge-json / add-script 等 rule 都已落地,install 出来的 lockfile
|
|
59
|
+
// 与最终态对齐;patches 还能覆盖 template 提供的同名文件。
|
|
60
|
+
const syncRunResult = (0, sync_1.runStackSync)(stack, targetDir, 'init');
|
|
61
|
+
const syncSummary = (0, sync_1.summarizeSyncResults)(syncRunResult);
|
|
62
|
+
// template 渲染下来的 @lark-apaas/* 版本可能落后 PINNED 表,赶在 install 之前钉到表版本,
|
|
63
|
+
// 这样一次 npm install 就直接装最终版本,不需要 install 完再补一遍。
|
|
64
|
+
const upgradedPackages = (0, sync_1.upgradePlatformDeps)(targetDir, 'init');
|
|
65
|
+
// skills 同步软失败:拉不到 coding-steering 包不该阻断 writeSparkMeta /
|
|
66
|
+
// activateGitHooks(之前会让 .spark/meta.json 没写,下次 init 半渲染状态又得重跑全套)。
|
|
67
|
+
let steeringResult;
|
|
68
|
+
let steeringError;
|
|
69
|
+
try {
|
|
70
|
+
steeringResult = (0, coding_steering_1.syncCodingSteering)({
|
|
71
|
+
stack,
|
|
72
|
+
targetDir,
|
|
73
|
+
version: opts.conf?.steeringVersion,
|
|
74
|
+
logPrefix: 'init',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
steeringError = err instanceof Error ? err.message : String(err);
|
|
79
|
+
(0, logger_1.log)('init', `⚠ skills sync failed (continuing init): ${steeringError}`);
|
|
80
|
+
steeringResult = { version: 'unknown', syncedSkills: [], techSynced: false };
|
|
81
|
+
}
|
|
59
82
|
const installResult = (0, index_1.installDependencies)({
|
|
60
83
|
targetDir,
|
|
61
84
|
skip: opts.skipInstall,
|
|
62
85
|
quietStdout: (0, output_1.isJsonMode)(),
|
|
63
86
|
});
|
|
87
|
+
// template 自带 .githooks/pre-commit;如果用户项目已 git init,顺便设上 core.hooksPath。
|
|
88
|
+
const hookActivation = (0, githooks_1.activateGitHooks)(targetDir);
|
|
64
89
|
(0, index_1.writeSparkMeta)(targetDir, {
|
|
65
90
|
stack,
|
|
66
91
|
version: tplResult.version,
|
|
67
92
|
archType: tplResult.archType,
|
|
93
|
+
app_id: opts.appId,
|
|
94
|
+
steeringVersion: steeringResult.version,
|
|
68
95
|
});
|
|
96
|
+
const syncedSummary = syncRunResult.stackFound
|
|
97
|
+
? syncRunResult.rulesApplied.length > 0
|
|
98
|
+
? `${syncRunResult.rulesApplied.length.toString()} rule(s)`
|
|
99
|
+
: 'legacy'
|
|
100
|
+
: 'skipped';
|
|
69
101
|
if (!(0, output_1.isJsonMode)()) {
|
|
70
|
-
process.stdout.write(`✓ Initialized ${stack} (template ${tplResult.version}, steering ${steeringResult.version}, install ${installResult.source}) in ${targetDir}\n`);
|
|
102
|
+
process.stdout.write(`✓ Initialized ${stack} (template ${tplResult.version}, steering ${steeringResult.version}, sync ${syncedSummary}, install ${installResult.source}) in ${targetDir}\n`);
|
|
71
103
|
}
|
|
72
104
|
(0, output_1.emit)({
|
|
73
105
|
data: {
|
|
@@ -77,12 +109,24 @@ async function handleAppInit(opts) {
|
|
|
77
109
|
templateVersion: tplResult.version,
|
|
78
110
|
steeringVersion: steeringResult.version,
|
|
79
111
|
archType: tplResult.archType,
|
|
112
|
+
appId: opts.appId,
|
|
80
113
|
syncedSkills: steeringResult.syncedSkills,
|
|
81
114
|
techSynced: steeringResult.techSynced,
|
|
115
|
+
steeringError,
|
|
116
|
+
// sync 流程的产出:rule-driven 时 appliedRules + 一系列汇总字段;fallback 到旧 platform-sync
|
|
117
|
+
// 时只填 platformSyncedFiles / platformMergedJsonFiles;stack 不识别时全空且 platformStackFound=false。
|
|
118
|
+
platformStackFound: syncRunResult.stackFound,
|
|
119
|
+
appliedRules: syncSummary.appliedRules,
|
|
120
|
+
platformSyncedFiles: syncSummary.syncedFiles,
|
|
121
|
+
platformMergedJsonFiles: syncSummary.mergedJsonFiles,
|
|
122
|
+
patchedScripts: syncSummary.patchedScripts,
|
|
123
|
+
upgradedPackages,
|
|
124
|
+
gitHooks: hookActivation.action,
|
|
82
125
|
installed: installResult.installed,
|
|
83
126
|
installSource: installResult.source,
|
|
84
127
|
installHash: installResult.hash,
|
|
85
128
|
cacheZip: installResult.cacheZip,
|
|
129
|
+
installError: installResult.error,
|
|
86
130
|
},
|
|
87
131
|
});
|
|
88
132
|
}
|
|
@@ -0,0 +1,219 @@
|
|
|
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.handleAppUpgrade = void 0;
|
|
7
|
+
exports.handleAppSync = handleAppSync;
|
|
8
|
+
exports.runStackSync = runStackSync;
|
|
9
|
+
exports.summarizeSyncResults = summarizeSyncResults;
|
|
10
|
+
exports.upgradePlatformDeps = upgradePlatformDeps;
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
const sync_configs_1 = require("../../../config/sync-configs");
|
|
15
|
+
const sync_rule_1 = require("../../../utils/sync-rule");
|
|
16
|
+
const platform_sync_1 = require("../../../utils/platform-sync");
|
|
17
|
+
const githooks_1 = require("../../../utils/githooks");
|
|
18
|
+
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
19
|
+
const error_1 = require("../../../utils/error");
|
|
20
|
+
const output_1 = require("../../../utils/output");
|
|
21
|
+
const logger_1 = require("../../../utils/logger");
|
|
22
|
+
/**
|
|
23
|
+
* 平台包钉死版本表 —— `miaoda app sync` 不查 npm dist-tags,直接按这张表把
|
|
24
|
+
* user app 已有的 @lark-apaas/* 依赖钉到对应版本。
|
|
25
|
+
*
|
|
26
|
+
* 为什么不跟 alpha dist-tag:alpha 通道被多个团队共享,外部 prerelease 时常打过去,
|
|
27
|
+
* 自动跟 alpha 会把回归版本(如 fullstack-vite-preset@1.0.24-alpha.5 退化没读 .env.local)
|
|
28
|
+
* 拉进 user app。维护这张白名单可控性更高,每次升基线时人工 review 一次再改这里。
|
|
29
|
+
*
|
|
30
|
+
* 表里没有的 @lark-apaas/* 包:sync 不动(既不升也不报错);user app 没装的包也不引入。
|
|
31
|
+
* 改这张表请同步把 user app 端到端 smoke 跑一次(init → sync → npm run dev)。
|
|
32
|
+
*/
|
|
33
|
+
const PINNED_PLATFORM_VERSIONS = {
|
|
34
|
+
'@lark-apaas/auth-sdk': '0.1.5-alpha.4',
|
|
35
|
+
'@lark-apaas/client-toolkit': '1.2.47-alpha.0',
|
|
36
|
+
'@lark-apaas/client-toolkit-lite': '1.1.8-alpha.0',
|
|
37
|
+
'@lark-apaas/dataloom': '0.1.2-alpha.6',
|
|
38
|
+
'@lark-apaas/db-schema-sync': '0.1.6-alpha.2',
|
|
39
|
+
'@lark-apaas/express-core': '1.0.4-alpha.7',
|
|
40
|
+
'@lark-apaas/fullstack-cli': '1.1.49-alpha.0',
|
|
41
|
+
'@lark-apaas/fullstack-nestjs-core': '1.1.52-alpha.1',
|
|
42
|
+
'@lark-apaas/fullstack-rspack-preset': '1.0.56-alpha.8',
|
|
43
|
+
'@lark-apaas/fullstack-vite-preset': '1.0.24-alpha.9',
|
|
44
|
+
'@lark-apaas/http-client': '0.1.7-alpha.8',
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* miaoda app sync [--dir <path>]
|
|
48
|
+
*
|
|
49
|
+
* 一站式同步:把当前 stack 的 sync 规则全套 apply 到 user app,对齐沙箱里
|
|
50
|
+
* `npm run upgrade → npx fullstack-cli sync` 的行为,并补 miaoda-cli 本地开发独有规则。
|
|
51
|
+
*
|
|
52
|
+
* 执行流:
|
|
53
|
+
* 1. SyncRule[] 全量 apply —— 来自 src/config/sync-configs/<stack>.ts。每个 stack
|
|
54
|
+
* 自带模板资源在 upgrade/templates/<stack>/templates/。表里没有该 stack 时回退到
|
|
55
|
+
* 旧 platform-sync 兜底(兼容尚未迁移的 stack)。
|
|
56
|
+
* 2. PINNED 平台 deps 钉版本 —— user app 已装的 @lark-apaas/* 升到 PINNED 表。
|
|
57
|
+
* 3. activateGitHooks —— 设置 core.hooksPath(template 自带 .githooks/pre-commit)。
|
|
58
|
+
* 4. npm install --no-audit --no-fund --ignore-scripts —— 物化新版本,绕开
|
|
59
|
+
* action-plugin postinstall 在缺平台 env 时的 ENOENT。
|
|
60
|
+
*
|
|
61
|
+
* 需要 .spark/meta.json 已含 stack(走过 `miaoda app init`)。
|
|
62
|
+
* 不动 .agent/skills/(那是 `miaoda skills sync` 的事)。
|
|
63
|
+
*/
|
|
64
|
+
async function handleAppSync(opts) {
|
|
65
|
+
await Promise.resolve();
|
|
66
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
67
|
+
const meta = (0, spark_meta_1.readSparkMeta)(targetDir);
|
|
68
|
+
if (meta.stack === undefined || meta.stack === '') {
|
|
69
|
+
throw new error_1.AppError('SYNC_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
70
|
+
}
|
|
71
|
+
// 1. apply SyncRule[],stack 没注册时回退到旧 platform-sync 兜底;都不识别就报错
|
|
72
|
+
const syncResults = runStackSync(meta.stack, targetDir, 'sync');
|
|
73
|
+
if (!syncResults.stackFound) {
|
|
74
|
+
throw new error_1.AppError('SYNC_STACK_NOT_SUPPORTED', `stack '${meta.stack}' has no SyncConfig and no upgrade/templates/${meta.stack}/ — 该 stack 暂未纳入 sync 范围`, {
|
|
75
|
+
next_actions: [
|
|
76
|
+
`src/config/sync-configs/${meta.stack}.ts 加 SyncConfig 并在 STACK_REGISTRY 注册`,
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// 2. @lark-apaas/* dep pin(按 PINNED_PLATFORM_VERSIONS 表,user app 已装才钉)
|
|
81
|
+
const upgradedPackages = upgradePlatformDeps(targetDir, 'sync');
|
|
82
|
+
// 3. activate git hooks(template 自带 .githooks/pre-commit,core.hooksPath 一次性设置)
|
|
83
|
+
const hookActivation = (0, githooks_1.activateGitHooks)(targetDir);
|
|
84
|
+
// 4. npm install —— 跟 init 一样软失败,install 挂了不该阻断 emit / sync 总结输出
|
|
85
|
+
(0, logger_1.log)('sync', 'Running npm install --ignore-scripts...');
|
|
86
|
+
let installError;
|
|
87
|
+
try {
|
|
88
|
+
(0, node_child_process_1.execFileSync)('npm', ['install', '--no-audit', '--no-fund', '--ignore-scripts'], {
|
|
89
|
+
cwd: targetDir,
|
|
90
|
+
stdio: (0, output_1.isJsonMode)() ? ['ignore', 'ignore', 'inherit'] : 'inherit',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
installError = err instanceof Error ? err.message : String(err);
|
|
95
|
+
(0, logger_1.log)('sync', `⚠ npm install failed (continuing): ${installError}`);
|
|
96
|
+
}
|
|
97
|
+
(0, output_1.emit)({
|
|
98
|
+
data: {
|
|
99
|
+
stack: meta.stack,
|
|
100
|
+
...summarizeSyncResults(syncResults),
|
|
101
|
+
upgradedPackages,
|
|
102
|
+
gitHooks: hookActivation.action,
|
|
103
|
+
installError,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** 老命令 `miaoda app upgrade` 的 handler 名,保留为 sync handler 的 alias。 */
|
|
108
|
+
exports.handleAppUpgrade = handleAppSync;
|
|
109
|
+
/**
|
|
110
|
+
* 给 stack 应用 sync rules(sync handler + init handler 共用)。
|
|
111
|
+
* stack 在 STACK_REGISTRY 注册时走新 SyncRule 机制,否则回落到旧 platform-sync。
|
|
112
|
+
*
|
|
113
|
+
* stack 完全不识别(既不在 STACK_REGISTRY 也无 upgrade/templates/<stack>/ 目录)时返回
|
|
114
|
+
* `stackFound: false` 而非抛错 —— 让调用方按场景决定:sync handler 抛 AppError,init handler
|
|
115
|
+
* 允许(fresh init 时 stack 还在加注册的过渡期)。
|
|
116
|
+
*/
|
|
117
|
+
function runStackSync(stack, targetDir, logPrefix) {
|
|
118
|
+
const config = (0, sync_configs_1.getSyncConfig)(stack);
|
|
119
|
+
if (config !== null) {
|
|
120
|
+
const sourceRoot = (0, sync_configs_1.getStackTemplatesRoot)(stack);
|
|
121
|
+
if (!node_fs_1.default.existsSync(sourceRoot)) {
|
|
122
|
+
throw new error_1.AppError('SYNC_TEMPLATES_MISSING', `upgrade/templates/${stack}/templates/ not found at ${sourceRoot} — cli 安装异常?`);
|
|
123
|
+
}
|
|
124
|
+
(0, logger_1.log)(logPrefix, `Applying ${config.sync.length.toString()} sync rule(s) for stack '${stack}'`);
|
|
125
|
+
const rulesApplied = (0, sync_rule_1.applySyncRules)(config.sync, { sourceRoot, targetDir, logPrefix });
|
|
126
|
+
return { stackFound: true, rulesApplied };
|
|
127
|
+
}
|
|
128
|
+
// fallback:表外 stack 仍用旧 platform-sync 机制(files/ overlay + patches/ deep merge)
|
|
129
|
+
(0, logger_1.log)(logPrefix, `Stack '${stack}' not in new sync registry, falling back to legacy platform-sync`);
|
|
130
|
+
const legacy = (0, platform_sync_1.syncPlatformControlled)({ stack, targetDir, logPrefix });
|
|
131
|
+
return {
|
|
132
|
+
stackFound: legacy.stackFound,
|
|
133
|
+
rulesApplied: [],
|
|
134
|
+
legacy: { syncedFiles: legacy.syncedFiles, mergedJsonFiles: legacy.mergedJsonFiles },
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** 把 SyncRuleResult[] / legacy 输出汇总成 emit data 里的几组字段,便于诊断。 */
|
|
138
|
+
function summarizeSyncResults(result) {
|
|
139
|
+
if (result.legacy !== undefined) {
|
|
140
|
+
return {
|
|
141
|
+
appliedRules: [],
|
|
142
|
+
syncedFiles: result.legacy.syncedFiles,
|
|
143
|
+
mergedJsonFiles: result.legacy.mergedJsonFiles,
|
|
144
|
+
patchedScripts: [],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const appliedRules = result.rulesApplied.map((r) => ({
|
|
148
|
+
type: r.rule.type,
|
|
149
|
+
action: r.action,
|
|
150
|
+
path: r.path,
|
|
151
|
+
detail: r.detail,
|
|
152
|
+
}));
|
|
153
|
+
const syncedFiles = [];
|
|
154
|
+
for (const r of result.rulesApplied) {
|
|
155
|
+
if ((r.action === 'synced' || r.action === 'created') && r.path !== undefined) {
|
|
156
|
+
syncedFiles.push(r.path);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const mergedJsonFiles = [];
|
|
160
|
+
for (const r of result.rulesApplied) {
|
|
161
|
+
if (r.rule.type !== 'merge-json')
|
|
162
|
+
continue;
|
|
163
|
+
if (r.action !== 'merged' && r.action !== 'created')
|
|
164
|
+
continue;
|
|
165
|
+
if (r.path === undefined)
|
|
166
|
+
continue;
|
|
167
|
+
mergedJsonFiles.push({
|
|
168
|
+
path: r.path,
|
|
169
|
+
keys: r.detail !== undefined ? r.detail.split(',').filter(Boolean) : [],
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const patchedScripts = result.rulesApplied
|
|
173
|
+
.filter((r) => (r.rule.type === 'patch-script' || r.rule.type === 'add-script') &&
|
|
174
|
+
(r.action === 'patched' || r.action === 'created'))
|
|
175
|
+
.map((r) => r.rule.name);
|
|
176
|
+
return { appliedRules, syncedFiles, mergedJsonFiles, patchedScripts };
|
|
177
|
+
}
|
|
178
|
+
function readPackageJson(pkgJsonPath) {
|
|
179
|
+
if (!node_fs_1.default.existsSync(pkgJsonPath))
|
|
180
|
+
return null;
|
|
181
|
+
return JSON.parse(node_fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* 把 user app package.json 里已装的 @lark-apaas/* 包钉到 PINNED_PLATFORM_VERSIONS 表版本。
|
|
185
|
+
* 由 `miaoda app sync` 和 `miaoda app init`(template 渲染后、install 之前)共用。
|
|
186
|
+
*
|
|
187
|
+
* - user app 已装的 PINNED 包 → 钉到表版本
|
|
188
|
+
* - user app 未装的 PINNED 包 → 不引入(sync 的职责是对齐,不是塞依赖)
|
|
189
|
+
* - 装着但不在 PINNED 表的 @lark-apaas/* 包 → 完全不动
|
|
190
|
+
*
|
|
191
|
+
* @param logPrefix 用于 `[<prefix>] deps.xxx: a → b` 日志前缀;sync 流程传 'sync',init 流程传 'init'。
|
|
192
|
+
*/
|
|
193
|
+
function upgradePlatformDeps(targetDir, logPrefix = 'sync') {
|
|
194
|
+
const pkgJsonPath = node_path_1.default.join(targetDir, 'package.json');
|
|
195
|
+
const pkg = readPackageJson(pkgJsonPath);
|
|
196
|
+
if (!pkg)
|
|
197
|
+
return [];
|
|
198
|
+
const updated = [];
|
|
199
|
+
for (const section of ['dependencies', 'devDependencies']) {
|
|
200
|
+
const deps = pkg[section];
|
|
201
|
+
if (!deps || typeof deps !== 'object')
|
|
202
|
+
continue;
|
|
203
|
+
for (const name of Object.keys(deps)) {
|
|
204
|
+
if (!Object.prototype.hasOwnProperty.call(PINNED_PLATFORM_VERSIONS, name))
|
|
205
|
+
continue;
|
|
206
|
+
const target = PINNED_PLATFORM_VERSIONS[name];
|
|
207
|
+
const from = deps[name];
|
|
208
|
+
if (from === target)
|
|
209
|
+
continue;
|
|
210
|
+
deps[name] = target;
|
|
211
|
+
updated.push({ name, from, to: target, section });
|
|
212
|
+
(0, logger_1.log)(logPrefix, ` ${section}.${name}: ${from} → ${target}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (updated.length > 0) {
|
|
216
|
+
node_fs_1.default.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
|
|
217
|
+
}
|
|
218
|
+
return updated;
|
|
219
|
+
}
|
|
@@ -10,10 +10,10 @@ const spark_meta_1 = require("../../../utils/spark-meta");
|
|
|
10
10
|
const error_1 = require("../../../utils/error");
|
|
11
11
|
const output_1 = require("../../../utils/output");
|
|
12
12
|
/**
|
|
13
|
-
* miaoda skills sync [
|
|
13
|
+
* miaoda skills sync [version] [--dir <path>]
|
|
14
14
|
*
|
|
15
|
-
* 从 .spark/meta.json 读 stack
|
|
16
|
-
* 同步到 <dir>/.agent/steering/。需要先跑过 `miaoda app init`。
|
|
15
|
+
* 从 .spark/meta.json 读 stack(+ 默认 steeringVersion),把 coding-steering 包内对应 stack
|
|
16
|
+
* 的 skills + tech.md 同步到 <dir>/.agent/steering/。需要先跑过 `miaoda app init`。
|
|
17
17
|
*/
|
|
18
18
|
async function handleSkillsSync(opts) {
|
|
19
19
|
await Promise.resolve();
|
|
@@ -22,17 +22,28 @@ async function handleSkillsSync(opts) {
|
|
|
22
22
|
if (meta.stack === undefined || meta.stack === '') {
|
|
23
23
|
throw new error_1.AppError('SKILLS_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
24
24
|
}
|
|
25
|
+
const version = opts.version ?? meta.steeringVersion;
|
|
26
|
+
const versionSource = opts.version
|
|
27
|
+
? 'cli-arg'
|
|
28
|
+
: meta.steeringVersion
|
|
29
|
+
? 'meta.json'
|
|
30
|
+
: 'default-latest';
|
|
25
31
|
const result = (0, coding_steering_1.syncCodingSteering)({
|
|
26
32
|
stack: meta.stack,
|
|
27
33
|
targetDir,
|
|
28
|
-
version
|
|
34
|
+
version,
|
|
35
|
+
outputLayout: opts.local === true ? 'flat' : 'nested',
|
|
29
36
|
});
|
|
30
37
|
(0, output_1.emit)({
|
|
31
38
|
data: {
|
|
32
39
|
stack: meta.stack,
|
|
33
40
|
version: result.version,
|
|
41
|
+
versionSource,
|
|
34
42
|
syncedSkills: result.syncedSkills,
|
|
35
43
|
techSynced: result.techSynced,
|
|
44
|
+
...(result.claudeSkillsLink !== undefined
|
|
45
|
+
? { claudeSkillsLink: result.claudeSkillsLink }
|
|
46
|
+
: {}),
|
|
36
47
|
},
|
|
37
48
|
});
|
|
38
49
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FULLSTACK_CLI_PIN_SPEC = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 临时钉死 `@lark-apaas/fullstack-cli` 的 npx 调用版本。
|
|
6
|
+
*
|
|
7
|
+
* 用于 user app `package.json` 里所有 `npx -y @lark-apaas/fullstack-cli ...` 调用 ——
|
|
8
|
+
* sync 规则会按本常量生成 `npx -y <FULLSTACK_CLI_PIN_SPEC> ...`,确保 user app 每次
|
|
9
|
+
* postinstall / gen-db-schema / sync 都拉到验证过能装插件的版本(避免 npx 拉 latest
|
|
10
|
+
* 时碰到外部 prerelease 回归版本)。
|
|
11
|
+
*
|
|
12
|
+
* 维护:
|
|
13
|
+
* - 跟 src/cli/handlers/app/sync.ts 里 PINNED_PLATFORM_VERSIONS['@lark-apaas/fullstack-cli']
|
|
14
|
+
* **保持一致**(前者用于 user app dependencies dep bump,后者用于 npm script 里 npx 调用)
|
|
15
|
+
* - 一旦 latest fullstack-cli 稳定且 token 鉴权回归 OK,可以去掉版本钉,让 npx 走 latest
|
|
16
|
+
*/
|
|
17
|
+
exports.FULLSTACK_CLI_PIN_SPEC = '@lark-apaas/fullstack-cli@1.1.49-alpha.0';
|