@lark-apaas/miaoda-cli 0.1.2-alpha.ccfdc05 → 0.1.2-alpha.d0d2ae1
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 +7 -8
- package/dist/api/db/api.js +250 -6
- package/dist/api/db/client.js +36 -0
- package/dist/api/db/index.js +9 -1
- package/dist/api/file/api.js +15 -0
- package/dist/api/file/index.js +2 -1
- package/dist/api/index.js +1 -7
- package/dist/cli/commands/db/index.js +137 -0
- package/dist/cli/commands/file/index.js +7 -0
- package/dist/cli/commands/index.js +6 -10
- package/dist/cli/commands/shared.js +3 -81
- package/dist/cli/handlers/db/audit.js +285 -0
- package/dist/cli/handlers/db/changelog.js +117 -0
- package/dist/cli/handlers/db/data.js +1 -1
- package/dist/cli/handlers/db/index.js +17 -1
- package/dist/cli/handlers/db/migration.js +213 -0
- package/dist/cli/handlers/{app/update.js → db/quota.js} +29 -20
- package/dist/cli/handlers/db/recovery.js +228 -0
- package/dist/cli/handlers/file/index.js +3 -1
- package/dist/cli/handlers/{deploy/error-log.js → file/quota.js} +27 -22
- package/dist/main.js +7 -27
- package/dist/utils/http.js +0 -118
- package/dist/utils/index.js +1 -13
- package/dist/utils/output.js +29 -338
- package/package.json +5 -7
- package/dist/api/app/api.js +0 -25
- package/dist/api/app/index.js +0 -15
- package/dist/api/app/schemas.js +0 -79
- package/dist/api/app/types.js +0 -58
- package/dist/api/deploy/api.js +0 -60
- package/dist/api/deploy/index.js +0 -16
- package/dist/api/deploy/schemas.js +0 -103
- package/dist/api/deploy/types.js +0 -22
- package/dist/api/observability/api.js +0 -52
- package/dist/api/observability/index.js +0 -16
- package/dist/api/observability/schemas.js +0 -60
- package/dist/api/observability/types.js +0 -27
- package/dist/cli/commands/app/index.js +0 -62
- package/dist/cli/commands/deploy/index.js +0 -145
- package/dist/cli/commands/observability/index.js +0 -237
- package/dist/cli/handlers/app/get.js +0 -48
- package/dist/cli/handlers/app/index.js +0 -7
- package/dist/cli/handlers/deploy/deploy.js +0 -83
- package/dist/cli/handlers/deploy/get.js +0 -70
- package/dist/cli/handlers/deploy/helpers.js +0 -41
- package/dist/cli/handlers/deploy/history.js +0 -70
- package/dist/cli/handlers/deploy/index.js +0 -14
- package/dist/cli/handlers/deploy/polling.js +0 -139
- package/dist/cli/handlers/observability/analytics.js +0 -212
- package/dist/cli/handlers/observability/helpers.js +0 -66
- package/dist/cli/handlers/observability/index.js +0 -12
- package/dist/cli/handlers/observability/log.js +0 -94
- package/dist/cli/handlers/observability/metric.js +0 -208
- package/dist/cli/handlers/observability/trace.js +0 -102
- package/dist/cli/version.js +0 -15
- package/dist/utils/devops-error.js +0 -28
- package/dist/utils/git.js +0 -29
- package/dist/utils/time.js +0 -203
|
@@ -1,208 +0,0 @@
|
|
|
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.handleObservabilityMetric = handleObservabilityMetric;
|
|
37
|
-
const api = __importStar(require("../../../api/index"));
|
|
38
|
-
const output_1 = require("../../../utils/output");
|
|
39
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
40
|
-
const helpers_1 = require("./helpers");
|
|
41
|
-
/**
|
|
42
|
-
* PRD <metric-name> + --series → 服务端 metric name → 表头列名(=对应 --series 取值)。
|
|
43
|
-
*
|
|
44
|
-
* - 缺省 --series 时返回该 cliName 下所有相关线。
|
|
45
|
-
* - latency / requests 的 error 线 v1.0.122 起由独立 metric 提供(不再 is_error filter)。
|
|
46
|
-
*
|
|
47
|
-
* 表头标签直接用 --series 名("total"/"error"/"p50"/"p99");单一指标则用 cliName。
|
|
48
|
-
*/
|
|
49
|
-
const METRIC_LABELS = {
|
|
50
|
-
cpu: { cpu_usage: "cpu" },
|
|
51
|
-
memory: { mem_usage: "memory" },
|
|
52
|
-
requests: {
|
|
53
|
-
client_api_request_count: "total",
|
|
54
|
-
client_api_request_error_count: "error",
|
|
55
|
-
},
|
|
56
|
-
latency: {
|
|
57
|
-
client_api_request_latency_p50: "p50",
|
|
58
|
-
client_api_request_latency_p99: "p99",
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
/** miaoda observability metric <metric-name> */
|
|
62
|
-
async function handleObservabilityMetric(opts) {
|
|
63
|
-
if (!opts.metricName)
|
|
64
|
-
(0, shared_1.failArgs)("<metric-name> 必填");
|
|
65
|
-
const appID = (0, shared_1.resolveAppId)({ appId: opts.appId });
|
|
66
|
-
const { metricNames, labelByMetric, extraFilters } = resolveMetricSelection(opts.metricName, opts.series);
|
|
67
|
-
const filters = (0, helpers_1.buildFieldFilters)([
|
|
68
|
-
{ key: "referer_path", value: opts.page ? (0, helpers_1.eqFilter)(opts.page) : undefined },
|
|
69
|
-
{ key: "api", value: opts.api ? (0, helpers_1.eqFilter)(opts.api) : undefined },
|
|
70
|
-
...extraFilters,
|
|
71
|
-
]);
|
|
72
|
-
// since/until 直接以秒透传到 BAM;当前未做桶对齐(如需开启把 until
|
|
73
|
-
// 用 ceilMsToBucket(untilMs, downSample as GranularityBucket) 包一层即可)。
|
|
74
|
-
const downSample = opts.downSample ?? "1m";
|
|
75
|
-
const nowMs = Date.now();
|
|
76
|
-
const sinceMs = (0, helpers_1.parseToMs)(opts.since) ?? nowMs - 30 * 86_400_000;
|
|
77
|
-
const untilMs = (0, helpers_1.parseToMs)(opts.until) ?? nowMs;
|
|
78
|
-
const req = {
|
|
79
|
-
appID,
|
|
80
|
-
appEnv: "runtime",
|
|
81
|
-
metricNames,
|
|
82
|
-
startTimestamp: (0, helpers_1.msToSec)(sinceMs),
|
|
83
|
-
endTimestamp: (0, helpers_1.msToSec)(untilMs),
|
|
84
|
-
filters,
|
|
85
|
-
downSample,
|
|
86
|
-
needPackLackPoint: false,
|
|
87
|
-
};
|
|
88
|
-
const resp = await api.observability.queryMetricsData(req);
|
|
89
|
-
// requests 的 count / error_count:
|
|
90
|
-
// - BAM 在该时间点无数据时会传 null,或者 values 里干脆缺 key
|
|
91
|
-
// - CLI 按"请求过的 metricNames"逐一兜底为 0,让"没有请求"和"没有数据"
|
|
92
|
-
// 在表格 / JSON 里都显式呈现成 0,避免空格 / 缺字段被误解为缺失
|
|
93
|
-
// latency / cpu / memory 不做这个兜底——p50 没数据 ≠ 延迟为 0。
|
|
94
|
-
if (opts.metricName === "requests") {
|
|
95
|
-
fillRequestedMetricsWithZero(resp, metricNames);
|
|
96
|
-
}
|
|
97
|
-
emitMetricsResponse(resp, labelByMetric);
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* 按"客户端请求过的 metricNames"兜底缺失/为 null 的值为 0;不去动 BAM 多返回的
|
|
101
|
-
* 其他字段(防御性,避免误改不属于本次查询的数据)。
|
|
102
|
-
*/
|
|
103
|
-
function fillRequestedMetricsWithZero(resp, requestedMetricNames) {
|
|
104
|
-
for (const point of resp.points ?? []) {
|
|
105
|
-
for (const name of requestedMetricNames) {
|
|
106
|
-
point.values[name] ??= 0;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
// ── 渲染 ─────────
|
|
111
|
-
//
|
|
112
|
-
// BAM v1.0.123 起返回 points: [{timestamp, dimensions, values: {metricName: v}}]——
|
|
113
|
-
// 服务端已把多 metric 合并到同 timestamp 的 row,下游直接平铺即可。
|
|
114
|
-
// JSON 模式:原样透传 points(保留 BAM 原 metricName 作为 values 的 key)。
|
|
115
|
-
// Pretty 模式:把 values 里的 metricName 重命名成 CLI label(p50/p99/total 等),
|
|
116
|
-
// 再走 buildPivotSchema 渲染。
|
|
117
|
-
function emitMetricsResponse(resp, labelByMetric) {
|
|
118
|
-
const points = resp.points ?? [];
|
|
119
|
-
// metric 不分页,但仍补齐 has_more / next_cursor 以对齐 log/trace 的信封形状
|
|
120
|
-
if ((0, output_1.isJsonMode)()) {
|
|
121
|
-
(0, output_1.emit)({ data: points, next_cursor: null, has_more: false });
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
const { rows, seriesLabels } = renameAndSort(points, labelByMetric);
|
|
125
|
-
if (rows.length === 0) {
|
|
126
|
-
(0, output_1.emit)({ data: [], next_cursor: null, has_more: false });
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
const hasLatency = Object.keys(labelByMetric).some((n) => n.includes("latency"));
|
|
130
|
-
(0, output_1.emit)({ data: rows, next_cursor: null, has_more: false }, buildPivotSchema(seriesLabels, hasLatency));
|
|
131
|
-
}
|
|
132
|
-
function renameAndSort(points, labelByMetric) {
|
|
133
|
-
// 列顺序按 labelByMetric 声明顺序,避免 BAM 返回顺序波动影响表头
|
|
134
|
-
const seriesLabels = Object.values(labelByMetric);
|
|
135
|
-
// TODO: 当 dimensions 非空(groupBy 多 series)时,把 dimensions 也并入 row
|
|
136
|
-
const rows = points.map((point) => {
|
|
137
|
-
const row = { timestamp: point.timestamp };
|
|
138
|
-
for (const [metricName, value] of Object.entries(point.values)) {
|
|
139
|
-
const label = labelByMetric[metricName] ?? metricName;
|
|
140
|
-
row[label] = value;
|
|
141
|
-
}
|
|
142
|
-
return row;
|
|
143
|
-
});
|
|
144
|
-
// 按时间倒序,与 log/trace 的"最新在前"风格一致
|
|
145
|
-
rows.sort((a, b) => b.timestamp - a.timestamp);
|
|
146
|
-
return { rows, seriesLabels };
|
|
147
|
-
}
|
|
148
|
-
function buildPivotSchema(seriesLabels, hasLatency) {
|
|
149
|
-
const valueFormat = hasLatency ? output_1.fmt.durationMs() : undefined;
|
|
150
|
-
return {
|
|
151
|
-
columns: [
|
|
152
|
-
{ key: "timestamp", label: "time", format: output_1.fmt.sec() },
|
|
153
|
-
...seriesLabels.map((label) => ({
|
|
154
|
-
key: label,
|
|
155
|
-
label,
|
|
156
|
-
...(valueFormat ? { format: valueFormat } : {}),
|
|
157
|
-
})),
|
|
158
|
-
],
|
|
159
|
-
strict: true,
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* 解析 <metric-name> + --series 的组合:决定最终 metricNames、表头 label 映射、附加过滤。
|
|
164
|
-
*
|
|
165
|
-
* label 直接用 --series 取值("total"/"error"/"p50"/"p99");单一指标 cliName 也作为 label。
|
|
166
|
-
*/
|
|
167
|
-
function resolveMetricSelection(cliName, series) {
|
|
168
|
-
const extras = [];
|
|
169
|
-
if (cliName === "latency") {
|
|
170
|
-
if (series === "p99") {
|
|
171
|
-
return single("client_api_request_latency_p99", "p99", extras);
|
|
172
|
-
}
|
|
173
|
-
if (series === "p50") {
|
|
174
|
-
return single("client_api_request_latency_p50", "p50", extras);
|
|
175
|
-
}
|
|
176
|
-
return all(METRIC_LABELS.latency, extras);
|
|
177
|
-
}
|
|
178
|
-
if (cliName === "requests") {
|
|
179
|
-
// v1.0.122 起 error 线由独立 metric 提供,不再走 is_error filter
|
|
180
|
-
if (series === "total") {
|
|
181
|
-
return single("client_api_request_count", "total", extras);
|
|
182
|
-
}
|
|
183
|
-
if (series === "error") {
|
|
184
|
-
return single("client_api_request_error_count", "error", extras);
|
|
185
|
-
}
|
|
186
|
-
return all(METRIC_LABELS.requests, extras);
|
|
187
|
-
}
|
|
188
|
-
if (cliName === "cpu")
|
|
189
|
-
return all(METRIC_LABELS.cpu, extras);
|
|
190
|
-
if (cliName === "memory")
|
|
191
|
-
return all(METRIC_LABELS.memory, extras);
|
|
192
|
-
// 兜底:CLI 名直接作为 metric name + label
|
|
193
|
-
return single(cliName, cliName, extras);
|
|
194
|
-
}
|
|
195
|
-
function single(metricName, label, extras) {
|
|
196
|
-
return {
|
|
197
|
-
metricNames: [metricName],
|
|
198
|
-
labelByMetric: { [metricName]: label },
|
|
199
|
-
extraFilters: extras,
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
function all(labelByMetric, extras) {
|
|
203
|
-
return {
|
|
204
|
-
metricNames: Object.keys(labelByMetric),
|
|
205
|
-
labelByMetric,
|
|
206
|
-
extraFilters: extras,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
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.handleObservabilityTraceList = handleObservabilityTraceList;
|
|
37
|
-
exports.handleObservabilityTraceGet = handleObservabilityTraceGet;
|
|
38
|
-
const api = __importStar(require("../../../api/index"));
|
|
39
|
-
const output_1 = require("../../../utils/output");
|
|
40
|
-
const shared_1 = require("../../../cli/commands/shared");
|
|
41
|
-
const index_1 = require("../../../api/observability/index");
|
|
42
|
-
const helpers_1 = require("./helpers");
|
|
43
|
-
/** miaoda observability trace list */
|
|
44
|
-
async function handleObservabilityTraceList(opts) {
|
|
45
|
-
const appID = (0, shared_1.resolveAppId)({ appId: opts.appId });
|
|
46
|
-
const appEnv = "runtime";
|
|
47
|
-
const limit = (0, helpers_1.validateLimit)(opts.limit ?? 50);
|
|
48
|
-
// 过滤 key 对齐 BAM Span 字段名:
|
|
49
|
-
// - 顶层字段:traceID(注意大小写)
|
|
50
|
-
// - attributes 业务字段:user_id(snake_case)
|
|
51
|
-
// - 入口 span:BAM 没有 entrySpanName fieldFilter,统一走 fuzzyFilter(trace endpoint
|
|
52
|
-
// 默认作用于 span name),所以 --root-span 不进 fieldFilters
|
|
53
|
-
const fieldFilters = (0, helpers_1.buildFieldFilters)([
|
|
54
|
-
{ key: "trace_id", value: opts.traceId ? (0, helpers_1.eqFilter)(opts.traceId) : undefined },
|
|
55
|
-
{ key: "user_id", value: opts.userId ? (0, helpers_1.eqFilter)(opts.userId, "i64") : undefined },
|
|
56
|
-
]);
|
|
57
|
-
const req = {
|
|
58
|
-
appID,
|
|
59
|
-
appEnv,
|
|
60
|
-
startTimestampNs: (0, helpers_1.parseToNs)(opts.since),
|
|
61
|
-
endTimestampNs: (0, helpers_1.parseToNs)(opts.until),
|
|
62
|
-
limit,
|
|
63
|
-
pageToken: opts.cursor,
|
|
64
|
-
fieldFilters,
|
|
65
|
-
fuzzyFilter: opts.rootSpan ? (0, helpers_1.fuzzyFilter)(opts.rootSpan) : undefined,
|
|
66
|
-
};
|
|
67
|
-
const resp = await api.observability.searchTraces(req);
|
|
68
|
-
emitSearchTracesResponse(resp);
|
|
69
|
-
}
|
|
70
|
-
function emitSearchTracesResponse(resp) {
|
|
71
|
-
(0, output_1.emit)({
|
|
72
|
-
data: resp.spans ?? [],
|
|
73
|
-
next_cursor: resp.hasMore ? resp.nextPageToken : null,
|
|
74
|
-
has_more: resp.hasMore,
|
|
75
|
-
}, index_1.spanSchema);
|
|
76
|
-
}
|
|
77
|
-
/** miaoda observability trace get <trace-id> */
|
|
78
|
-
async function handleObservabilityTraceGet(opts) {
|
|
79
|
-
if (!opts.traceId)
|
|
80
|
-
(0, shared_1.failArgs)("<trace-id> 必填");
|
|
81
|
-
const appID = (0, shared_1.resolveAppId)({ appId: opts.appId });
|
|
82
|
-
const appEnv = "runtime";
|
|
83
|
-
const resp = await api.observability.getTraces({
|
|
84
|
-
appID,
|
|
85
|
-
appEnv,
|
|
86
|
-
traceID: opts.traceId,
|
|
87
|
-
withLogSeverityCount: opts.withLogSeverityCount,
|
|
88
|
-
});
|
|
89
|
-
emitGetTraceResponse(resp);
|
|
90
|
-
}
|
|
91
|
-
function emitGetTraceResponse(resp) {
|
|
92
|
-
// JSON 模式:保持单条信封语义,便于下游一次解析
|
|
93
|
-
if ((0, output_1.isJsonMode)()) {
|
|
94
|
-
(0, output_1.emit)({
|
|
95
|
-
data: { spans: resp.spans ?? [], isBreak: resp.isBreak },
|
|
96
|
-
});
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// Pretty 模式:先打头部 key-value(断链状态等元信息),再按 spanSchema 渲染主表
|
|
100
|
-
(0, output_1.emit)({ data: { isBreak: resp.isBreak } });
|
|
101
|
-
(0, output_1.emit)({ data: resp.spans ?? [] }, index_1.spanSchema);
|
|
102
|
-
}
|
package/dist/cli/version.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveRootVersionArg = resolveRootVersionArg;
|
|
4
|
-
function resolveRootVersionArg(args) {
|
|
5
|
-
if (args.length === 1 && (args[0] === "-v" || args[0] === "--version"))
|
|
6
|
-
return "show";
|
|
7
|
-
if (args.some(isLooseVersionArg))
|
|
8
|
-
return "invalid-variant";
|
|
9
|
-
if (args.includes("-v") || args.includes("--version"))
|
|
10
|
-
return "invalid-placement";
|
|
11
|
-
return "none";
|
|
12
|
-
}
|
|
13
|
-
function isLooseVersionArg(arg) {
|
|
14
|
-
return ((arg.startsWith("-v") && arg !== "-v") || (arg.startsWith("--version") && arg !== "--version"));
|
|
15
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mapDevopsError = mapDevopsError;
|
|
4
|
-
const error_1 = require("./error");
|
|
5
|
-
/**
|
|
6
|
-
* 把 BAM lark.apaas.devops 的业务码(数字字符串)映射成 CLI 错误码。
|
|
7
|
-
* 来源:服务端技术方案 wiki L7P8wlNQ5iyShLkxzlOcCo8LnTg「业务错误码映射表」。
|
|
8
|
-
*
|
|
9
|
-
* 放在 utils 下而不是某个具体 api 域里:app / deploy 都跑在 lark.apaas.devops
|
|
10
|
-
* 这同一 PSM,业务码命名空间也共享;boundaries 规则又禁止 api 域间互引。
|
|
11
|
-
*/
|
|
12
|
-
function mapDevopsError(bizCode, message) {
|
|
13
|
-
switch (bizCode) {
|
|
14
|
-
case "400002577":
|
|
15
|
-
case "400002569":
|
|
16
|
-
return new error_1.AppError("APP_NOT_FOUND", message, {
|
|
17
|
-
next_actions: ["Run `miaoda app list` to see available apps"],
|
|
18
|
-
});
|
|
19
|
-
case "400002579":
|
|
20
|
-
return new error_1.AppError("APP_PERMISSION_DENIED", message);
|
|
21
|
-
case "400002575":
|
|
22
|
-
return new error_1.AppError("INVALID_ARG_VALUE", message, {
|
|
23
|
-
next_actions: ["缩短 --name / --description 后重试(后端有长度限制)"],
|
|
24
|
-
});
|
|
25
|
-
default:
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
}
|
package/dist/utils/git.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCurrentGitBranch = getCurrentGitBranch;
|
|
4
|
-
const node_child_process_1 = require("node:child_process");
|
|
5
|
-
/**
|
|
6
|
-
* 读取 cwd 所在仓库的当前分支名。
|
|
7
|
-
*
|
|
8
|
-
* 不在 git 仓库、git 不可用、或处于 detached HEAD 时返回 undefined,
|
|
9
|
-
* 让调用方决定回退策略(如交给后端使用应用默认分支)。
|
|
10
|
-
*/
|
|
11
|
-
function getCurrentGitBranch(cwd = process.cwd()) {
|
|
12
|
-
let result;
|
|
13
|
-
try {
|
|
14
|
-
result = (0, node_child_process_1.spawnSync)("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
15
|
-
cwd,
|
|
16
|
-
encoding: "utf8",
|
|
17
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
if (result.status !== 0)
|
|
24
|
-
return undefined;
|
|
25
|
-
const branch = result.stdout.trim();
|
|
26
|
-
if (!branch || branch === "HEAD")
|
|
27
|
-
return undefined;
|
|
28
|
-
return branch;
|
|
29
|
-
}
|
package/dist/utils/time.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TIMESTAMP_HELP = void 0;
|
|
4
|
-
exports.parseTimeToMs = parseTimeToMs;
|
|
5
|
-
exports.msToNs = msToNs;
|
|
6
|
-
exports.msToSec = msToSec;
|
|
7
|
-
exports.parseToMs = parseToMs;
|
|
8
|
-
exports.parseToNs = parseToNs;
|
|
9
|
-
exports.parseToSec = parseToSec;
|
|
10
|
-
exports.floorMsToBucket = floorMsToBucket;
|
|
11
|
-
exports.ceilMsToBucket = ceilMsToBucket;
|
|
12
|
-
const error_1 = require("./error");
|
|
13
|
-
exports.TIMESTAMP_HELP = "支持格式:" +
|
|
14
|
-
"相对时间 30m/1h/2d/1w;" +
|
|
15
|
-
"日期 2026-04-01(本地时区当日 00:00:00);" +
|
|
16
|
-
"本地日期+时间 2026-04-01T10:00:00(按本地时区,T 分隔);" +
|
|
17
|
-
"带时区 ISO 2026-04-01T10:00:00Z(UTC)或 2026-04-01T10:00:00+08:00(指定偏移)。" +
|
|
18
|
-
"禁止用空格分隔:'YYYY-MM-DD HH:mm:ss' 不带引号会被 shell 拆成两个参数。";
|
|
19
|
-
/**
|
|
20
|
-
* 解析时间字符串到毫秒时间戳;不匹配任一支持格式抛 ARGS_INVALID。
|
|
21
|
-
*
|
|
22
|
-
* 时区约定(重要):
|
|
23
|
-
* - 不带显式时区的形式(YYYY-MM-DD、YYYY-MM-DDTHH:mm:ss)一律按
|
|
24
|
-
* **本地时区**解释,与 pretty 输出(output.ts:renderDate 用 getFullYear 等本地方法)形成
|
|
25
|
-
* 输入/输出闭环:用户复制输出文本作为 --since 不会差时区。
|
|
26
|
-
* - 带显式时区(结尾 Z 或 ±HH:MM / ±HHMM)按显式时区解析,跨机器一致。
|
|
27
|
-
* - 因此跨机器同步使用时建议带显式时区;同机器复制粘贴 pretty 输出更省事。
|
|
28
|
-
*
|
|
29
|
-
* 拒绝 Date.parse 松散接受的形式:YYYY/MM/DD、自然语言('April 1 2026')、单独年份等。
|
|
30
|
-
*
|
|
31
|
-
* 失败抛 AppError("ARGS_INVALID", ...);CLI 层用 withHelp 自动转 exit 2 + help。
|
|
32
|
-
*/
|
|
33
|
-
function parseTimeToMs(input, now = new Date()) {
|
|
34
|
-
// 1. 相对时间:30m / 1h / 2d / 1w
|
|
35
|
-
const relative = /^(\d+)([mhdw])$/.exec(input);
|
|
36
|
-
if (relative) {
|
|
37
|
-
const n = Number(relative[1]);
|
|
38
|
-
const unit = relative[2];
|
|
39
|
-
const factor = unit === "m"
|
|
40
|
-
? 60_000
|
|
41
|
-
: unit === "h"
|
|
42
|
-
? 3_600_000
|
|
43
|
-
: unit === "d"
|
|
44
|
-
? 86_400_000
|
|
45
|
-
: /* w */ 604_800_000;
|
|
46
|
-
return now.getTime() - n * factor;
|
|
47
|
-
}
|
|
48
|
-
// 2. 纯日期:YYYY-MM-DD → 本地当日 00:00:00
|
|
49
|
-
const date = /^(\d{4})-(\d{2})-(\d{2})$/.exec(input);
|
|
50
|
-
if (date) {
|
|
51
|
-
return localDateMs(input, date[1], date[2], date[3], "00", "00", "00", "0");
|
|
52
|
-
}
|
|
53
|
-
// 3. 本地日期+时间:YYYY-MM-DDTHH:mm:ss[.SSS](不带时区,T 分隔)。
|
|
54
|
-
// 不接受空格分隔——'YYYY-MM-DD HH:mm:ss' 不带引号会被 shell 拆成两个参数,
|
|
55
|
-
// 宁可不支持也不要让 agent 踩"看起来传了 since 实际只传了一半"的坑。
|
|
56
|
-
const localDt = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/.exec(input);
|
|
57
|
-
if (localDt) {
|
|
58
|
-
// capture 7 是可选 .SSS 组,运行时可能 undefined;TS lib 的 RegExp match 索引
|
|
59
|
-
// 类型把它标成 string,所以这里显式 cast 让 ?? 在 lint 视角下也"必要"。
|
|
60
|
-
const msPart = localDt[7] ?? "0";
|
|
61
|
-
return localDateMs(input, localDt[1], localDt[2], localDt[3], localDt[4], localDt[5], localDt[6], msPart);
|
|
62
|
-
}
|
|
63
|
-
// 4. 带显式时区的 ISO 8601:YYYY-MM-DDTHH:mm:ss[.SSS](Z|±HH:MM|±HHMM)
|
|
64
|
-
const iso = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?(Z|[+-](\d{2}):?(\d{2}))$/.exec(input);
|
|
65
|
-
if (iso) {
|
|
66
|
-
validateDateTimeParts(input, iso[1], iso[2], iso[3], iso[4], iso[5], iso[6]);
|
|
67
|
-
if (iso[7] !== "Z")
|
|
68
|
-
validateOffset(input, iso[8], iso[9]);
|
|
69
|
-
const ms = Date.parse(input);
|
|
70
|
-
if (Number.isNaN(ms))
|
|
71
|
-
failInvalidTimestamp(input);
|
|
72
|
-
return ms;
|
|
73
|
-
}
|
|
74
|
-
failInvalidTimestamp(input);
|
|
75
|
-
}
|
|
76
|
-
function localDateMs(input, y, mo, d, h, mi, s, msPart) {
|
|
77
|
-
validateDateTimeParts(input, y, mo, d, h, mi, s);
|
|
78
|
-
// 毫秒位补齐到 3 位再截断("5" → 500,"12" → 120,"123" → 123)
|
|
79
|
-
const ms = Number(msPart.padEnd(3, "0").slice(0, 3));
|
|
80
|
-
const date = new Date(Number(y), Number(mo) - 1, Number(d), Number(h), Number(mi), Number(s), ms);
|
|
81
|
-
if (date.getFullYear() !== Number(y) ||
|
|
82
|
-
date.getMonth() !== Number(mo) - 1 ||
|
|
83
|
-
date.getDate() !== Number(d) ||
|
|
84
|
-
date.getHours() !== Number(h) ||
|
|
85
|
-
date.getMinutes() !== Number(mi) ||
|
|
86
|
-
date.getSeconds() !== Number(s) ||
|
|
87
|
-
date.getMilliseconds() !== ms) {
|
|
88
|
-
failInvalidTimestamp(input);
|
|
89
|
-
}
|
|
90
|
-
return date.getTime();
|
|
91
|
-
}
|
|
92
|
-
function validateDateTimeParts(input, y, mo, d, h, mi, s) {
|
|
93
|
-
const year = Number(y);
|
|
94
|
-
const month = Number(mo);
|
|
95
|
-
const day = Number(d);
|
|
96
|
-
const hour = Number(h);
|
|
97
|
-
const minute = Number(mi);
|
|
98
|
-
const second = Number(s);
|
|
99
|
-
if (month < 1 || month > 12 || hour > 23 || minute > 59 || second > 59) {
|
|
100
|
-
failInvalidTimestamp(input);
|
|
101
|
-
}
|
|
102
|
-
const utc = new Date(Date.UTC(year, month - 1, day));
|
|
103
|
-
if (utc.getUTCFullYear() !== year ||
|
|
104
|
-
utc.getUTCMonth() !== month - 1 ||
|
|
105
|
-
utc.getUTCDate() !== day) {
|
|
106
|
-
failInvalidTimestamp(input);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function validateOffset(input, h, mi) {
|
|
110
|
-
if (h === undefined || mi === undefined)
|
|
111
|
-
failInvalidTimestamp(input);
|
|
112
|
-
const hour = Number(h);
|
|
113
|
-
const minute = Number(mi);
|
|
114
|
-
if (hour > 23 || minute > 59)
|
|
115
|
-
failInvalidTimestamp(input);
|
|
116
|
-
}
|
|
117
|
-
function failInvalidTimestamp(input) {
|
|
118
|
-
throw new error_1.AppError("ARGS_INVALID", `无法解析时间 '${input}'。${exports.TIMESTAMP_HELP}`);
|
|
119
|
-
}
|
|
120
|
-
/** 毫秒 → 纳秒(字符串,避免 JS Number 精度丢失) */
|
|
121
|
-
function msToNs(ms) {
|
|
122
|
-
return `${String(ms)}000000`;
|
|
123
|
-
}
|
|
124
|
-
/** 毫秒 → 秒(字符串,向下取整) */
|
|
125
|
-
function msToSec(ms) {
|
|
126
|
-
return String(Math.floor(ms / 1000));
|
|
127
|
-
}
|
|
128
|
-
/** 解析到毫秒数;input 为空返回 undefined */
|
|
129
|
-
function parseToMs(input, now) {
|
|
130
|
-
if (!input)
|
|
131
|
-
return undefined;
|
|
132
|
-
return parseTimeToMs(input, now);
|
|
133
|
-
}
|
|
134
|
-
/** 解析到纳秒字符串;input 为空返回 undefined */
|
|
135
|
-
function parseToNs(input, now) {
|
|
136
|
-
if (!input)
|
|
137
|
-
return undefined;
|
|
138
|
-
return msToNs(parseTimeToMs(input, now));
|
|
139
|
-
}
|
|
140
|
-
/** 解析到秒字符串;input 为空返回 undefined */
|
|
141
|
-
function parseToSec(input, now) {
|
|
142
|
-
if (!input)
|
|
143
|
-
return undefined;
|
|
144
|
-
return msToSec(parseTimeToMs(input, now));
|
|
145
|
-
}
|
|
146
|
-
// ── 桶边界对齐 ──
|
|
147
|
-
//
|
|
148
|
-
// metric 的 down-sample 与 analytics 的 timeAggregationUnit 都按 UTC 桶切片。
|
|
149
|
-
// 当用户传的 since/until 落在桶中间,服务端可能返回不到该桶(边界数据丢失)。
|
|
150
|
-
// 约定:since 向下取整、until 向上取整,把 since/until 各自所在桶完整纳入。
|
|
151
|
-
//
|
|
152
|
-
// 周界以 ISO 周(周一为周首,UTC);月按 UTC 月初对齐。
|
|
153
|
-
const MS_MIN = 60_000;
|
|
154
|
-
const MS_HOUR = 3_600_000;
|
|
155
|
-
const MS_DAY = 86_400_000;
|
|
156
|
-
/** 把 ms 向下对齐到桶起点(UTC)。未识别的 bucket 原样返回。 */
|
|
157
|
-
function floorMsToBucket(ms, bucket) {
|
|
158
|
-
switch (bucket) {
|
|
159
|
-
case "1m":
|
|
160
|
-
return Math.floor(ms / MS_MIN) * MS_MIN;
|
|
161
|
-
case "1h":
|
|
162
|
-
return Math.floor(ms / MS_HOUR) * MS_HOUR;
|
|
163
|
-
case "1d":
|
|
164
|
-
case "DAY": {
|
|
165
|
-
const d = new Date(ms);
|
|
166
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
|
|
167
|
-
}
|
|
168
|
-
case "WEEK": {
|
|
169
|
-
const d = new Date(ms);
|
|
170
|
-
const offsetDays = (d.getUTCDay() + 6) % 7; // 距上一个周一的天数
|
|
171
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() - offsetDays);
|
|
172
|
-
}
|
|
173
|
-
case "MONTH": {
|
|
174
|
-
const d = new Date(ms);
|
|
175
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1);
|
|
176
|
-
}
|
|
177
|
-
default:
|
|
178
|
-
return ms;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
/** 把 ms 向上对齐到下一个桶起点(UTC);恰在边界则不变。 */
|
|
182
|
-
function ceilMsToBucket(ms, bucket) {
|
|
183
|
-
const floor = floorMsToBucket(ms, bucket);
|
|
184
|
-
if (floor === ms)
|
|
185
|
-
return ms;
|
|
186
|
-
switch (bucket) {
|
|
187
|
-
case "1m":
|
|
188
|
-
return floor + MS_MIN;
|
|
189
|
-
case "1h":
|
|
190
|
-
return floor + MS_HOUR;
|
|
191
|
-
case "1d":
|
|
192
|
-
case "DAY":
|
|
193
|
-
return floor + MS_DAY;
|
|
194
|
-
case "WEEK":
|
|
195
|
-
return floor + 7 * MS_DAY;
|
|
196
|
-
case "MONTH": {
|
|
197
|
-
const d = new Date(floor);
|
|
198
|
-
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1);
|
|
199
|
-
}
|
|
200
|
-
default:
|
|
201
|
-
return ms;
|
|
202
|
-
}
|
|
203
|
-
}
|