@lark-apaas/miaoda-cli 0.1.22 → 0.1.24
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 +36 -2
- package/dist/api/comment/api.js +24 -0
- package/dist/api/comment/index.js +6 -0
- package/dist/api/comment/types.js +6 -0
- package/dist/api/deploy/index.js +3 -1
- package/dist/api/deploy/modern-types.js +4 -1
- package/dist/api/deploy/modern.js +8 -0
- package/dist/api/index.js +3 -1
- package/dist/cli/commands/app/index.js +4 -2
- package/dist/cli/commands/comment/index.js +55 -0
- package/dist/cli/commands/deploy/modern.js +34 -0
- package/dist/cli/commands/index.js +19 -0
- package/dist/cli/commands/registry/index.js +114 -0
- package/dist/cli/handlers/app/init.js +6 -2
- package/dist/cli/handlers/comment/index.js +7 -0
- package/dist/cli/handlers/comment/list.js +132 -0
- package/dist/cli/handlers/comment/resolve.js +44 -0
- package/dist/cli/handlers/deploy/index.js +3 -1
- package/dist/cli/handlers/deploy/patch.js +17 -0
- package/dist/cli/handlers/registry/add.js +97 -0
- package/dist/cli/handlers/registry/index.js +7 -0
- package/dist/cli/handlers/registry/list.js +48 -0
- package/dist/cli/handlers/registry/shared.js +25 -0
- package/dist/cli/handlers/skills/sync.js +12 -4
- package/dist/services/app/init/template.js +1 -0
- package/dist/services/deploy/modern/atoms/design-build.js +49 -0
- package/dist/services/deploy/modern/atoms/design-upload.js +74 -0
- package/dist/services/deploy/modern/atoms/index.js +6 -1
- package/dist/services/deploy/modern/atoms/tosutil.js +246 -0
- package/dist/services/deploy/modern/atoms/upload.js +4 -127
- package/dist/services/deploy/modern/check.js +28 -16
- package/dist/services/deploy/modern/patch/actions.js +61 -0
- package/dist/services/deploy/modern/patch/content.js +18 -0
- package/dist/services/deploy/modern/patch/index.js +46 -0
- package/dist/services/deploy/modern/patch/routes.js +37 -0
- package/dist/services/deploy/modern/patch/source-scan.js +58 -0
- package/dist/services/deploy/modern/pipelines/design-local.js +56 -0
- package/dist/services/deploy/modern/pipelines/index.js +3 -1
- package/dist/services/deploy/modern/protocol.js +7 -0
- package/dist/services/deploy/modern/run.js +10 -4
- package/dist/services/deploy/modern/template-key-map.js +4 -0
- package/dist/services/registry/index.js +293 -0
- package/dist/utils/http.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.handleCommentResolve = handleCommentResolve;
|
|
37
|
+
const api = __importStar(require("../../../api/index"));
|
|
38
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
39
|
+
const output_1 = require("../../../utils/output");
|
|
40
|
+
async function handleCommentResolve(commentId, opts) {
|
|
41
|
+
const appId = (0, shared_1.resolveAppId)({ appId: opts.appId });
|
|
42
|
+
await api.comment.resolveComment(appId, commentId);
|
|
43
|
+
(0, output_1.emitOk)({ comment_id: commentId, resolved: true });
|
|
44
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_POLL_INTERVAL_MS = exports.waitForPipeline = exports.handleDeployErrorLog = exports.handleDeployHistory = exports.handleDeployGet = exports.handleDeploy = void 0;
|
|
3
|
+
exports.handleDeployPatch = 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,3 +12,5 @@ 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; } });
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleDeployPatch = handleDeployPatch;
|
|
4
|
+
const index_1 = require("../../../services/deploy/modern/patch/index");
|
|
5
|
+
const output_1 = require("../../../utils/output");
|
|
6
|
+
/** miaoda deploy patch —— design-html 文件级增量发布 */
|
|
7
|
+
async function handleDeployPatch(opts) {
|
|
8
|
+
const result = await (0, index_1.patchDesignDeploy)({
|
|
9
|
+
appId: opts.appId,
|
|
10
|
+
projectDir: opts.dir ?? process.cwd(),
|
|
11
|
+
creates: opts.creates,
|
|
12
|
+
updates: opts.updates,
|
|
13
|
+
deletes: opts.deletes,
|
|
14
|
+
sessionID: opts.sessionID,
|
|
15
|
+
});
|
|
16
|
+
(0, output_1.emit)({ data: result });
|
|
17
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
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.handleRegistryAdd = handleRegistryAdd;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const index_1 = require("../../../services/registry/index");
|
|
9
|
+
const shared_1 = require("./shared");
|
|
10
|
+
const error_1 = require("../../../utils/error");
|
|
11
|
+
const output_1 = require("../../../utils/output");
|
|
12
|
+
/**
|
|
13
|
+
* miaoda registry add <name...> [--overwrite] [--dry-run] [--dir <path>] [--version <ver>]
|
|
14
|
+
*
|
|
15
|
+
* 解析 USAGE 块 Depends 传递闭包,把每个条目对应的 SDK 文件从 registry 包根的 <relPath>
|
|
16
|
+
* **保留相对路径**拷到项目根(--dir 指定目录的根)。
|
|
17
|
+
* skip-by-disk:目标已存在默认跳过,--overwrite 才覆盖。不写任何安装记账文件。
|
|
18
|
+
*/
|
|
19
|
+
async function handleRegistryAdd(opts) {
|
|
20
|
+
await Promise.resolve();
|
|
21
|
+
if (opts.names.length === 0) {
|
|
22
|
+
throw new error_1.AppError('ARGS_INVALID', 'registry add 至少需要一个条目名');
|
|
23
|
+
}
|
|
24
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
25
|
+
const stack = (0, shared_1.resolveRegistryStack)(targetDir);
|
|
26
|
+
const reg = (0, index_1.loadRegistry)({ stack, version: opts.version });
|
|
27
|
+
try {
|
|
28
|
+
const plan = (0, index_1.planAdd)({
|
|
29
|
+
entries: reg.entries,
|
|
30
|
+
targetDir,
|
|
31
|
+
names: opts.names,
|
|
32
|
+
});
|
|
33
|
+
const result = (0, index_1.applyAdd)(plan.files, {
|
|
34
|
+
overwrite: opts.overwrite === true,
|
|
35
|
+
dryRun: opts.dryRun === true,
|
|
36
|
+
});
|
|
37
|
+
// entries:**只列用户请求的条目**(opts.names 命中的),给它们的 usage / dependsOn,
|
|
38
|
+
// 让 Agent add 完直接拿到用法、无需再 `registry list`。被 Depends 传递拉进来的依赖是
|
|
39
|
+
// "管道"(照常在 added/skipped 里落地),不占 usage 位。请求的条目即使已存在被 skip
|
|
40
|
+
// 也回带 usage(status=skipped,Agent 借此判断磁盘上是 registry 版还是自己改过的旧版)。
|
|
41
|
+
const requestedRelPaths = new Set();
|
|
42
|
+
for (const token of opts.names) {
|
|
43
|
+
for (const e of plan.entries) {
|
|
44
|
+
if ((0, index_1.tokenMatches)(e, token))
|
|
45
|
+
requestedRelPaths.add(e.relPath);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// relPath → 落地的 PlannedFile(拿 dest / 落地状态)
|
|
49
|
+
const fileByRelPath = new Map(plan.files.map((f) => [f.srcRelPath, f]));
|
|
50
|
+
const addedSet = new Set(result.added);
|
|
51
|
+
const skippedSet = new Set(result.skipped);
|
|
52
|
+
const entries = plan.entries
|
|
53
|
+
.filter((e) => requestedRelPaths.has(e.relPath))
|
|
54
|
+
.map((e) => {
|
|
55
|
+
const f = fileByRelPath.get(e.relPath);
|
|
56
|
+
const dest = f?.dest ?? e.relPath.split('/').pop() ?? e.relPath;
|
|
57
|
+
const status = skippedSet.has(dest) && !addedSet.has(dest) ? 'skipped' : 'added';
|
|
58
|
+
return {
|
|
59
|
+
name: e.name,
|
|
60
|
+
file: e.relPath,
|
|
61
|
+
dest,
|
|
62
|
+
status,
|
|
63
|
+
usage: e.usage,
|
|
64
|
+
dependsOn: e.dependsOn,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
// 只透出对 add 完的 Agent 可操作的字段:项目里实际多了什么(added)、什么没动(skipped)、
|
|
68
|
+
// 请求条目怎么用(entries)。requested(纯回显)、resolved(包内诊断路径)不透出。
|
|
69
|
+
const data = {
|
|
70
|
+
registryVersion: reg.version,
|
|
71
|
+
added: result.added,
|
|
72
|
+
skipped: result.skipped,
|
|
73
|
+
dryRun: opts.dryRun === true,
|
|
74
|
+
entries,
|
|
75
|
+
};
|
|
76
|
+
if ((0, output_1.isJsonMode)()) {
|
|
77
|
+
(0, output_1.emit)({ data });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// pretty 是 Agent 不加 --json 时的默认载荷,也要对 AI 友好:信息量与 JSON 对齐,
|
|
81
|
+
// 但换成稳定 label + 逗号列表(无 JSON 数组、无 TTY 截断、空/默认值不打印),
|
|
82
|
+
// summary 在前、各请求条目的 USAGE 块原文在后。整体走一次纯字符串 emit(不进 key-value 渲染)。
|
|
83
|
+
const summaryLines = [`registry@${reg.version}`];
|
|
84
|
+
if (opts.dryRun === true)
|
|
85
|
+
summaryLines.push('dry-run: true (no files written)');
|
|
86
|
+
if (result.added.length > 0)
|
|
87
|
+
summaryLines.push(`added: ${result.added.join(', ')}`);
|
|
88
|
+
if (result.skipped.length > 0)
|
|
89
|
+
summaryLines.push(`skipped: ${result.skipped.join(', ')}`);
|
|
90
|
+
const blocks = entries.filter((e) => e.usage !== '').map((e) => `# ${e.dest}\n${e.usage}`);
|
|
91
|
+
const parts = [summaryLines.join('\n'), ...blocks];
|
|
92
|
+
(0, output_1.emit)(parts.join('\n\n'));
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
reg.cleanup();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleRegistryAdd = exports.handleRegistryList = void 0;
|
|
4
|
+
var list_1 = require("./list");
|
|
5
|
+
Object.defineProperty(exports, "handleRegistryList", { enumerable: true, get: function () { return list_1.handleRegistryList; } });
|
|
6
|
+
var add_1 = require("./add");
|
|
7
|
+
Object.defineProperty(exports, "handleRegistryAdd", { enumerable: true, get: function () { return add_1.handleRegistryAdd; } });
|
|
@@ -0,0 +1,48 @@
|
|
|
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.handleRegistryList = handleRegistryList;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const index_1 = require("../../../services/registry/index");
|
|
9
|
+
const shared_1 = require("./shared");
|
|
10
|
+
const output_1 = require("../../../utils/output");
|
|
11
|
+
/**
|
|
12
|
+
* miaoda registry list [--dir <path>] [--version <ver>]
|
|
13
|
+
*
|
|
14
|
+
* 从 .spark/meta.json 读 stack → runtime → 包名,拉对应 registry 包,从包根递归扫含 USAGE 块的 SDK 文件。
|
|
15
|
+
*
|
|
16
|
+
* - 默认(pretty):输出各条目 USAGE 块原文,带文件名分隔,给 Agent 直接读注释。
|
|
17
|
+
* - --json:输出 [{name, file, usage(原文字符串), dependsOn[]}],usage 保持原文不解析成字段。
|
|
18
|
+
* file 是相对包根的路径(如 scripts/deck-stage.js),即 add 后的落地相对路径。
|
|
19
|
+
*/
|
|
20
|
+
async function handleRegistryList(opts) {
|
|
21
|
+
await Promise.resolve();
|
|
22
|
+
const targetDir = node_path_1.default.resolve(opts.dir ?? process.cwd());
|
|
23
|
+
const stack = (0, shared_1.resolveRegistryStack)(targetDir);
|
|
24
|
+
const reg = (0, index_1.loadRegistry)({ stack, version: opts.version });
|
|
25
|
+
try {
|
|
26
|
+
if ((0, output_1.isJsonMode)()) {
|
|
27
|
+
(0, output_1.emit)({
|
|
28
|
+
data: reg.entries.map((e) => ({
|
|
29
|
+
name: e.name,
|
|
30
|
+
file: e.relPath,
|
|
31
|
+
usage: e.usage,
|
|
32
|
+
dependsOn: e.dependsOn,
|
|
33
|
+
})),
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// pretty:各条目 USAGE 块原文拼接,带文件路径分隔(让 Agent 直接读注释)
|
|
38
|
+
if (reg.entries.length === 0) {
|
|
39
|
+
(0, output_1.emit)('(no registry entries)');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const blocks = reg.entries.map((e) => `# ${e.relPath}\n${e.usage}`);
|
|
43
|
+
(0, output_1.emit)(blocks.join('\n\n'));
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
reg.cleanup();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveRegistryStack = resolveRegistryStack;
|
|
4
|
+
const spark_meta_1 = require("../../../utils/spark-meta");
|
|
5
|
+
const index_1 = require("../../../services/registry/index");
|
|
6
|
+
const error_1 = require("../../../utils/error");
|
|
7
|
+
/**
|
|
8
|
+
* 从 <targetDir>/.spark/meta.json 读 stack,校验该 stack 有组件 registry。
|
|
9
|
+
* 缺 stack → 提示先 init;stack 无 registry(无对应 runtime / runtime 无 registry 包)→ 提示支持哪些 stack。
|
|
10
|
+
*
|
|
11
|
+
* 这里只做「stack 是否在支持列表」的早校验给用户友好提示;包名的两跳解析
|
|
12
|
+
* (stack → runtime → 包)由 loadRegistry/resolveRegistryPackage 负责。
|
|
13
|
+
*/
|
|
14
|
+
function resolveRegistryStack(targetDir) {
|
|
15
|
+
const meta = (0, spark_meta_1.readSparkMeta)(targetDir);
|
|
16
|
+
if (meta.stack === undefined || meta.stack === '') {
|
|
17
|
+
throw new error_1.AppError('REGISTRY_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
18
|
+
}
|
|
19
|
+
if (!index_1.REGISTRY_SUPPORTED_STACKS.includes(meta.stack)) {
|
|
20
|
+
throw new error_1.AppError('REGISTRY_STACK_UNSUPPORTED', `stack "${meta.stack}" 没有组件 registry`, {
|
|
21
|
+
next_actions: [`支持 registry 的 stack:${index_1.REGISTRY_SUPPORTED_STACKS.join(', ') || '(none)'}`],
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return meta.stack;
|
|
25
|
+
}
|
|
@@ -15,8 +15,13 @@ 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
|
-
*
|
|
18
|
+
* 版本来源优先级(从高到低):
|
|
19
|
+
* 1. CLI `--version` flag(显式指定)
|
|
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 里钉。
|
|
20
25
|
*/
|
|
21
26
|
async function handleSkillsSync(opts) {
|
|
22
27
|
await Promise.resolve();
|
|
@@ -25,17 +30,20 @@ async function handleSkillsSync(opts) {
|
|
|
25
30
|
if (meta.stack === undefined || meta.stack === '') {
|
|
26
31
|
throw new error_1.AppError('SKILLS_META_INCOMPLETE', '.spark/meta.json missing stack — run `miaoda app init` first');
|
|
27
32
|
}
|
|
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';
|
|
28
36
|
const result = (0, coding_steering_1.syncCodingSteering)({
|
|
29
37
|
stack: meta.stack,
|
|
30
38
|
targetDir,
|
|
31
|
-
version:
|
|
39
|
+
version: effectiveVersion,
|
|
32
40
|
outputLayout: opts.local === true ? 'flat' : 'nested',
|
|
33
41
|
});
|
|
34
42
|
(0, output_1.emit)({
|
|
35
43
|
data: {
|
|
36
44
|
stack: meta.stack,
|
|
37
45
|
version: result.version,
|
|
38
|
-
versionSource
|
|
46
|
+
versionSource,
|
|
39
47
|
syncedSkills: result.syncedSkills,
|
|
40
48
|
techSynced: result.techSynced,
|
|
41
49
|
...(result.claudeSkillsLink !== undefined
|
|
@@ -16,6 +16,7 @@ exports.TEMPLATE_PACKAGE_BY_STACK = {
|
|
|
16
16
|
'vite-react': '@lark-apaas/coding-template-vite-react',
|
|
17
17
|
html: '@lark-apaas/coding-template-html',
|
|
18
18
|
'nestjs-react-fullstack': '@lark-apaas/coding-template-nestjs-react-fullstack',
|
|
19
|
+
'design-html': '@lark-apaas/coding-template-design-html',
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* 短名 → template 包钉版表。renderTemplate 默认按这张表取版本号,表外 stack 跟 npm latest。
|
|
@@ -0,0 +1,49 @@
|
|
|
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.buildDesignOutput = buildDesignOutput;
|
|
7
|
+
exports.cleanDesignDist = cleanDesignDist;
|
|
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
|
+
const constants_1 = require("../constants");
|
|
13
|
+
const source_scan_1 = require("../patch/source-scan");
|
|
14
|
+
const routes_1 = require("../patch/routes");
|
|
15
|
+
/**
|
|
16
|
+
* design-html buildless 闭环 build(替代模板 scripts/build.sh):
|
|
17
|
+
* 1. rm -rf <projectDir>/dist
|
|
18
|
+
* 2. 拷源码 → dist/output(套 EXCLUDES,与 routes 同一份 listSourceFiles)
|
|
19
|
+
* 3. 写 dist/output/routes.json = generateRoutes(projectDir)
|
|
20
|
+
* 不跑 npm run build、不依赖技术栈内 build.sh。
|
|
21
|
+
* fs / scan / routes 任何失败统一包成 AppError('DEPLOY_BUILD_FAILED'),与旧 runDesignBuild 对齐。
|
|
22
|
+
*/
|
|
23
|
+
function buildDesignOutput(opts) {
|
|
24
|
+
(0, logger_1.log)('deploy', 'Building (design, CLI)...');
|
|
25
|
+
try {
|
|
26
|
+
const distDir = node_path_1.default.join(opts.projectDir, constants_1.DIST_DIR);
|
|
27
|
+
const outputDir = node_path_1.default.join(distDir, constants_1.OUTPUT_DIR);
|
|
28
|
+
node_fs_1.default.rmSync(distDir, { recursive: true, force: true });
|
|
29
|
+
node_fs_1.default.mkdirSync(outputDir, { recursive: true });
|
|
30
|
+
for (const rel of (0, source_scan_1.listSourceFiles)(opts.projectDir)) {
|
|
31
|
+
const dest = node_path_1.default.join(outputDir, rel);
|
|
32
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(dest), { recursive: true });
|
|
33
|
+
node_fs_1.default.copyFileSync(node_path_1.default.join(opts.projectDir, rel), dest);
|
|
34
|
+
}
|
|
35
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(outputDir, 'routes.json'), (0, routes_1.generateRoutes)(opts.projectDir), 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err instanceof error_1.AppError)
|
|
39
|
+
throw err;
|
|
40
|
+
throw new error_1.AppError('DEPLOY_BUILD_FAILED', `design build failed: ${err.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 删除 <projectDir>/dist(本地构建产物)。幂等:不存在也不报错(force)。
|
|
45
|
+
* design 部署收尾调用,部署动作结束后不在用户项目里留产物。
|
|
46
|
+
*/
|
|
47
|
+
function cleanDesignDist(projectDir) {
|
|
48
|
+
node_fs_1.default.rmSync(node_path_1.default.join(projectDir, constants_1.DIST_DIR), { recursive: true, force: true });
|
|
49
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
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.uploadDesignArtifacts = uploadDesignArtifacts;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const error_1 = require("../../../../utils/error");
|
|
10
|
+
const logger_1 = require("../../../../utils/logger");
|
|
11
|
+
const constants_1 = require("../constants");
|
|
12
|
+
const protocol_1 = require("../protocol");
|
|
13
|
+
const tosutil_1 = require("./tosutil");
|
|
14
|
+
/** 递归收集 dir 下相对路径(posix 分隔),与 -flat 上传后远端 key 对齐。 */
|
|
15
|
+
function listLocalRelKeys(dir) {
|
|
16
|
+
const out = new Set();
|
|
17
|
+
const walk = (cur, rel) => {
|
|
18
|
+
for (const entry of node_fs_1.default.readdirSync(cur, { withFileTypes: true })) {
|
|
19
|
+
const childRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
20
|
+
if (entry.isDirectory())
|
|
21
|
+
walk(node_path_1.default.join(cur, entry.name), childRel);
|
|
22
|
+
else
|
|
23
|
+
out.add(childRel);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
walk(dir, '');
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* design 部署上传(省带宽):
|
|
31
|
+
* 1. 本地 dist/output ──cp(local→tos)──▶ output_backup_path/ (唯一一次上传)
|
|
32
|
+
* 2. output_backup_path ──cp(tos→tos,同凭证同桶)──▶ output_latest_path (服务端复制)
|
|
33
|
+
* 3. ls latest → 跟本地 diff → rm latest 里源端已无的对象 (精确镜像)
|
|
34
|
+
* design-html 只产 dist/output,无 output_resource / output_static / capability。
|
|
35
|
+
*/
|
|
36
|
+
async function uploadDesignArtifacts(opts) {
|
|
37
|
+
await Promise.resolve();
|
|
38
|
+
const tosutilPath = (0, tosutil_1.resolveTosutilPath)();
|
|
39
|
+
const outputDir = node_path_1.default.join(opts.projectDir, constants_1.DIST_DIR, constants_1.OUTPUT_DIR);
|
|
40
|
+
if (!node_fs_1.default.existsSync(outputDir)) {
|
|
41
|
+
throw new error_1.AppError('DEPLOY_NO_BUILD_OUTPUT', `Required directory missing: ${constants_1.DIST_DIR}/${constants_1.OUTPUT_DIR}`);
|
|
42
|
+
}
|
|
43
|
+
// 空产物防呆:本地一个文件都没有时,绝不继续(否则 latest 会被整体 prune 清空)。
|
|
44
|
+
const localKeys = listLocalRelKeys(outputDir);
|
|
45
|
+
if (localKeys.size === 0) {
|
|
46
|
+
throw new error_1.AppError('DEPLOY_UPLOAD_EMPTY', `No files under ${constants_1.DIST_DIR}/${constants_1.OUTPUT_DIR} to upload — check build output.`);
|
|
47
|
+
}
|
|
48
|
+
const cred = (0, protocol_1.parseTosUploadCredential)((0, protocol_1.requireDataKey)(opts.data, protocol_1.DataKey.OUTPUT_ALL_TOS_UPLOAD_CREDENTIAL), protocol_1.DataKey.OUTPUT_ALL_TOS_UPLOAD_CREDENTIAL);
|
|
49
|
+
const backupPath = (0, protocol_1.requireDataKey)(opts.data, protocol_1.DataKey.OUTPUT_BACKUP_PATH);
|
|
50
|
+
const latestPath = (0, protocol_1.requireDataKey)(opts.data, protocol_1.DataKey.OUTPUT_LATEST_PATH);
|
|
51
|
+
const base = (0, tosutil_1.tosutilUploadFromTos)(cred); // 鉴权 + bucket
|
|
52
|
+
// 1. 本地 → backup(version):唯一一次本地上传。
|
|
53
|
+
// -ddo(noDirObjects):不上传文件夹占位对象,避免 latest 残留 `src/` 这类空目录。
|
|
54
|
+
(0, logger_1.log)('deploy', `Uploading ${constants_1.OUTPUT_DIR} → ${backupPath}...`);
|
|
55
|
+
(0, tosutil_1.uploadDirWithCredential)(tosutilPath, outputDir, { ...base, prefix: backupPath }, 'output_backup', true);
|
|
56
|
+
// 2. backup → latest:服务端 tos→tos cp(不占带宽)
|
|
57
|
+
(0, logger_1.log)('deploy', `Server-side copy ${backupPath} → ${latestPath}...`);
|
|
58
|
+
(0, tosutil_1.copyTosToTos)(tosutilPath, base, backupPath, latestPath);
|
|
59
|
+
// 3. latest 精确镜像:删源端已不存在的对象。
|
|
60
|
+
// 安全阀:远端有对象但跟本地零重合时,判定为 key 形态/ls 解析不匹配,跳过 prune——
|
|
61
|
+
// 宁可漏删(latest 残留旧文件)也绝不误删整目录(数据丢失)。design-html 的 build.sh
|
|
62
|
+
// 必产稳定名的 routes.json / *.html,正常重合不会为空,零重合即异常信号。
|
|
63
|
+
const remoteKeys = (0, tosutil_1.listRemoteKeys)(tosutilPath, { ...base, prefix: latestPath });
|
|
64
|
+
const overlap = remoteKeys.filter((k) => localKeys.has(k));
|
|
65
|
+
if (remoteKeys.length > 0 && overlap.length === 0) {
|
|
66
|
+
(0, logger_1.log)('deploy', `⚠ latest 远端 ${String(remoteKeys.length)} 个对象与本地零重合,疑似 key 形态不匹配,跳过 prune(避免误删)`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const staleKeys = remoteKeys.filter((k) => !localKeys.has(k));
|
|
70
|
+
if (staleKeys.length > 0) {
|
|
71
|
+
(0, logger_1.log)('deploy', `Pruning ${String(staleKeys.length)} stale object(s) from latest...`);
|
|
72
|
+
(0, tosutil_1.removeRemoteKeys)(tosutilPath, { ...base, prefix: latestPath }, staleKeys);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.savePluginInstances = exports.LocalReleaseStatus = exports.finalizeLocalRelease = exports.createLocalRelease = exports.uploadArtifacts = exports.runBuild = exports.preRelease = exports.prepareDeployContext = void 0;
|
|
3
|
+
exports.savePluginInstances = exports.LocalReleaseStatus = exports.finalizeLocalRelease = exports.createLocalRelease = exports.uploadArtifacts = exports.uploadDesignArtifacts = exports.cleanDesignDist = exports.buildDesignOutput = exports.runBuild = exports.preRelease = exports.prepareDeployContext = void 0;
|
|
4
4
|
var context_1 = require("./context");
|
|
5
5
|
Object.defineProperty(exports, "prepareDeployContext", { enumerable: true, get: function () { return context_1.prepareDeployContext; } });
|
|
6
6
|
var pre_release_1 = require("./pre-release");
|
|
7
7
|
Object.defineProperty(exports, "preRelease", { enumerable: true, get: function () { return pre_release_1.preRelease; } });
|
|
8
8
|
var build_1 = require("./build");
|
|
9
9
|
Object.defineProperty(exports, "runBuild", { enumerable: true, get: function () { return build_1.runBuild; } });
|
|
10
|
+
var design_build_1 = require("./design-build");
|
|
11
|
+
Object.defineProperty(exports, "buildDesignOutput", { enumerable: true, get: function () { return design_build_1.buildDesignOutput; } });
|
|
12
|
+
Object.defineProperty(exports, "cleanDesignDist", { enumerable: true, get: function () { return design_build_1.cleanDesignDist; } });
|
|
13
|
+
var design_upload_1 = require("./design-upload");
|
|
14
|
+
Object.defineProperty(exports, "uploadDesignArtifacts", { enumerable: true, get: function () { return design_upload_1.uploadDesignArtifacts; } });
|
|
10
15
|
var upload_1 = require("./upload");
|
|
11
16
|
Object.defineProperty(exports, "uploadArtifacts", { enumerable: true, get: function () { return upload_1.uploadArtifacts; } });
|
|
12
17
|
var local_release_1 = require("./local-release");
|