@lark-apaas/miaoda-cli 0.1.2-alpha.55feccd → 0.1.2-alpha.5fec91b

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.
Files changed (55) hide show
  1. package/dist/api/app/api.js +25 -0
  2. package/dist/api/app/index.js +15 -0
  3. package/dist/api/app/schemas.js +79 -0
  4. package/dist/api/app/types.js +58 -0
  5. package/dist/api/db/api.js +6 -250
  6. package/dist/api/db/client.js +0 -36
  7. package/dist/api/db/index.js +1 -9
  8. package/dist/api/deploy/api.js +60 -0
  9. package/dist/api/deploy/index.js +16 -0
  10. package/dist/api/deploy/schemas.js +103 -0
  11. package/dist/api/deploy/types.js +22 -0
  12. package/dist/api/file/api.js +0 -15
  13. package/dist/api/file/index.js +1 -2
  14. package/dist/api/index.js +7 -1
  15. package/dist/api/observability/api.js +52 -0
  16. package/dist/api/observability/index.js +16 -0
  17. package/dist/api/observability/schemas.js +39 -0
  18. package/dist/api/observability/types.js +27 -0
  19. package/dist/cli/commands/app/index.js +62 -0
  20. package/dist/cli/commands/db/index.js +0 -137
  21. package/dist/cli/commands/deploy/index.js +140 -0
  22. package/dist/cli/commands/file/index.js +0 -7
  23. package/dist/cli/commands/index.js +6 -0
  24. package/dist/cli/commands/observability/index.js +229 -0
  25. package/dist/cli/commands/shared.js +61 -3
  26. package/dist/cli/handlers/app/get.js +48 -0
  27. package/dist/cli/handlers/app/index.js +7 -0
  28. package/dist/cli/handlers/{db/quota.js → app/update.js} +20 -29
  29. package/dist/cli/handlers/db/data.js +1 -1
  30. package/dist/cli/handlers/db/index.js +1 -17
  31. package/dist/cli/handlers/deploy/deploy.js +83 -0
  32. package/dist/cli/handlers/{file/quota.js → deploy/error-log.js} +22 -27
  33. package/dist/cli/handlers/deploy/get.js +70 -0
  34. package/dist/cli/handlers/deploy/helpers.js +41 -0
  35. package/dist/cli/handlers/deploy/history.js +70 -0
  36. package/dist/cli/handlers/deploy/index.js +14 -0
  37. package/dist/cli/handlers/deploy/polling.js +139 -0
  38. package/dist/cli/handlers/file/index.js +1 -3
  39. package/dist/cli/handlers/observability/analytics.js +190 -0
  40. package/dist/cli/handlers/observability/helpers.js +66 -0
  41. package/dist/cli/handlers/observability/index.js +12 -0
  42. package/dist/cli/handlers/observability/log.js +94 -0
  43. package/dist/cli/handlers/observability/metric.js +208 -0
  44. package/dist/cli/handlers/observability/trace.js +102 -0
  45. package/dist/utils/devops-error.js +28 -0
  46. package/dist/utils/git.js +29 -0
  47. package/dist/utils/http.js +118 -0
  48. package/dist/utils/index.js +13 -1
  49. package/dist/utils/output.js +338 -29
  50. package/dist/utils/time.js +132 -0
  51. package/package.json +7 -5
  52. package/dist/cli/handlers/db/audit.js +0 -285
  53. package/dist/cli/handlers/db/changelog.js +0 -117
  54. package/dist/cli/handlers/db/migration.js +0 -145
  55. package/dist/cli/handlers/db/recovery.js +0 -188
@@ -1,145 +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
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.handleDbMigrationInit = handleDbMigrationInit;
40
- exports.handleDbMigrationDiff = handleDbMigrationDiff;
41
- exports.handleDbMigrationApply = handleDbMigrationApply;
42
- const node_readline_1 = __importDefault(require("node:readline"));
43
- const api = __importStar(require("../../../api/index"));
44
- const shared_1 = require("../../../cli/commands/shared");
45
- const output_1 = require("../../../utils/output");
46
- const render_1 = require("../../../utils/render");
47
- async function handleDbMigrationInit(opts) {
48
- const appId = (0, shared_1.resolveAppId)(opts);
49
- // 不可逆操作,TTY 默认要求 y/N;--yes 跳过
50
- if (!opts.yes && !(0, output_1.isJsonMode)()) {
51
- const ok = await confirm(`? Initialize multi-env (single → dev/online), this is IRREVERSIBLE${opts.syncData ? " and will copy existing data to dev" : ""}? (y/N) `);
52
- if (!ok) {
53
- (0, output_1.emit)("Aborted.");
54
- return;
55
- }
56
- }
57
- const result = await api.db.migrationInit({ appId, syncData: opts.syncData });
58
- if ((0, output_1.isJsonMode)()) {
59
- (0, output_1.emitOk)((0, output_1.snakeCaseKeys)(result));
60
- return;
61
- }
62
- const tty = (0, render_1.isStdoutTty)();
63
- (0, output_1.emit)((0, render_1.renderKeyValue)([
64
- ["Status", result.status],
65
- ["Environments", result.environments.join(", ")],
66
- ["Data synced", String(result.dataSynced)],
67
- ], tty));
68
- }
69
- async function handleDbMigrationDiff(opts) {
70
- const appId = (0, shared_1.resolveAppId)(opts);
71
- const result = await api.db.migrate({ appId, dryRun: true });
72
- renderDiff(result);
73
- }
74
- async function handleDbMigrationApply(opts) {
75
- const appId = (0, shared_1.resolveAppId)(opts);
76
- // TTY 下先 diff 给用户审;--yes 直接打到 online
77
- if (!opts.yes && !(0, output_1.isJsonMode)()) {
78
- const preview = await api.db.migrate({ appId, dryRun: true });
79
- if (preview.changes.length === 0) {
80
- (0, output_1.emit)(`Error: No pending changes between ${preview.from} and ${preview.to}`);
81
- (0, output_1.emit)(` hint: Make schema changes in dev first.`);
82
- process.exitCode = 1;
83
- return;
84
- }
85
- renderDiff(preview);
86
- const ok = await confirm(`? Apply ${String(preview.changes.length)} change(s) to ${preview.to}? (y/N) `);
87
- if (!ok) {
88
- (0, output_1.emit)("Aborted.");
89
- return;
90
- }
91
- }
92
- const result = await api.db.migrate({ appId, dryRun: false });
93
- if ((0, output_1.isJsonMode)()) {
94
- // PRD:{"status": "applied", "from": "dev", "to": "online", "changes_applied": 2}
95
- (0, output_1.emitOk)((0, output_1.snakeCaseKeys)({
96
- status: result.status ?? "applied",
97
- from: result.from,
98
- to: result.to,
99
- changesApplied: result.changesApplied ?? result.changes.length,
100
- }));
101
- return;
102
- }
103
- const tty = (0, render_1.isStdoutTty)();
104
- const prefix = tty ? "✓" : "OK";
105
- const arrow = tty ? "→" : "->";
106
- const applied = result.changesApplied ?? result.changes.length;
107
- (0, output_1.emit)(`${prefix} Applied ${result.from} ${arrow} ${result.to} (${String(applied)} changes)`);
108
- }
109
- // ── helpers ──
110
- // PRD diff 输出:
111
- // dev → online (2 changes):
112
- //
113
- // ALTER TABLE users ADD COLUMN avatar_url text;
114
- // CREATE INDEX idx_users_avatar ON users(avatar_url);
115
- function renderDiff(result) {
116
- if ((0, output_1.isJsonMode)()) {
117
- (0, output_1.emitOk)((0, output_1.snakeCaseKeys)({
118
- from: result.from,
119
- to: result.to,
120
- changes: result.changes.map((c) => ({
121
- type: c.type,
122
- table: c.table,
123
- statement: c.statement,
124
- })),
125
- }));
126
- return;
127
- }
128
- const tty = (0, render_1.isStdoutTty)();
129
- if (result.changes.length === 0) {
130
- (0, output_1.emit)(`No pending changes from ${result.from} to ${result.to}.`);
131
- return;
132
- }
133
- const arrow = tty ? "→" : "->";
134
- (0, output_1.emit)(`${result.from} ${arrow} ${result.to} (${String(result.changes.length)} changes):\n\n` +
135
- result.changes.map((c) => ` ${c.statement}`).join("\n"));
136
- }
137
- async function confirm(prompt) {
138
- const rl = node_readline_1.default.createInterface({ input: process.stdin, output: process.stderr });
139
- return new Promise((resolve) => {
140
- rl.question(prompt, (answer) => {
141
- rl.close();
142
- resolve(answer.trim().toLowerCase() === "y");
143
- });
144
- });
145
- }
@@ -1,188 +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
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.handleDbRecoveryDiff = handleDbRecoveryDiff;
40
- exports.handleDbRecoveryApply = handleDbRecoveryApply;
41
- const node_readline_1 = __importDefault(require("node:readline"));
42
- const api = __importStar(require("../../../api/index"));
43
- const shared_1 = require("../../../cli/commands/shared");
44
- const error_1 = require("../../../utils/error");
45
- const output_1 = require("../../../utils/output");
46
- const render_1 = require("../../../utils/render");
47
- // ── recovery diff ──
48
- async function handleDbRecoveryDiff(target, opts) {
49
- const appId = (0, shared_1.resolveAppId)(opts);
50
- const ts = normalizeTimestamp(target);
51
- const result = await api.db.recover({ appId, target: ts, dryRun: true });
52
- renderDiff(result);
53
- }
54
- async function handleDbRecoveryApply(target, opts) {
55
- const appId = (0, shared_1.resolveAppId)(opts);
56
- const ts = normalizeTimestamp(target);
57
- // PITR 高危:TTY 下先 diff 给用户审;--yes 直接执行
58
- if (!opts.yes && !(0, output_1.isJsonMode)()) {
59
- const preview = await api.db.recover({ appId, target: ts, dryRun: true });
60
- renderDiff(preview);
61
- const ok = await confirm(`? Restore database to ${preview.target}? This will overwrite current data. (y/N) `);
62
- if (!ok) {
63
- (0, output_1.emit)("Aborted.");
64
- return;
65
- }
66
- }
67
- const result = await api.db.recover({ appId, target: ts, dryRun: false });
68
- if ((0, output_1.isJsonMode)()) {
69
- // PRD:{"status": "restored", "target": "...", "tables_affected": 2, "elapsed_seconds": 30}
70
- (0, output_1.emitOk)((0, output_1.snakeCaseKeys)({
71
- status: result.status ?? "restored",
72
- target: result.target,
73
- tablesAffected: result.tablesAffected,
74
- elapsedSeconds: result.elapsedSeconds ?? 0,
75
- }));
76
- return;
77
- }
78
- const tty = (0, render_1.isStdoutTty)();
79
- const prefix = tty ? "✓" : "OK";
80
- (0, output_1.emit)(`${prefix} Database restored to ${result.target} ` +
81
- `(${String(result.tablesAffected)} tables affected, ${String(result.elapsedSeconds ?? 0)}s elapsed)`);
82
- }
83
- // ── helpers ──
84
- /**
85
- * 把用户传入的时间统一成 ISO 8601 UTC。
86
- * 接受:`YYYY-MM-DD` / `YYYY-MM-DD HH:MM:SS` / 完整 ISO 8601。
87
- */
88
- function normalizeTimestamp(input) {
89
- const FORMAT_HINT = "Use ISO 8601 / yyyy-mm-dd / yyyy-mm-dd HH:MM:SS.";
90
- if (input === "") {
91
- throw new error_1.AppError("ARGS_INVALID", "target timestamp is required", {
92
- next_actions: ["Usage: miaoda db recovery diff|apply <timestamp>"],
93
- });
94
- }
95
- if (/^\d{4}-\d{2}-\d{2}$/.test(input)) {
96
- return new Date(`${input}T00:00:00Z`).toISOString();
97
- }
98
- if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/.test(input)) {
99
- const d = new Date(input.replace(" ", "T"));
100
- if (Number.isNaN(d.getTime())) {
101
- throw new error_1.AppError("INVALID_TIMESTAMP", `Invalid timestamp format '${input}'`, {
102
- next_actions: [FORMAT_HINT],
103
- });
104
- }
105
- return d.toISOString();
106
- }
107
- const d = new Date(input);
108
- if (Number.isNaN(d.getTime())) {
109
- throw new error_1.AppError("INVALID_TIMESTAMP", `Invalid timestamp format '${input}'`, {
110
- next_actions: [FORMAT_HINT],
111
- });
112
- }
113
- return d.toISOString();
114
- }
115
- // PRD diff 输出(结构化 prose):
116
- // Recovery preview (→ 2026-04-15T10:00:00Z):
117
- //
118
- // tables affected: 2
119
- // users: +3 rows, -1 row, ~5 rows modified
120
- // orders: table will be restored (was dropped at 10:25:00)
121
- //
122
- // estimated time: ~30s
123
- function renderDiff(result) {
124
- if ((0, output_1.isJsonMode)()) {
125
- (0, output_1.emitOk)((0, output_1.snakeCaseKeys)({
126
- target: result.target,
127
- tablesAffected: result.tablesAffected,
128
- changes: result.changes.map((c) => ({
129
- table: c.table,
130
- inserted: c.inserted,
131
- deleted: c.deleted,
132
- modified: c.modified,
133
- action: c.action,
134
- droppedAt: c.droppedAt,
135
- })),
136
- estimatedSeconds: result.estimatedSeconds ?? 0,
137
- }));
138
- return;
139
- }
140
- const tty = (0, render_1.isStdoutTty)();
141
- const arrow = tty ? "→" : "->";
142
- if (result.changes.length === 0) {
143
- (0, output_1.emit)(`Recovery preview (${arrow} ${result.target}):\n\n` +
144
- ` No changes — database is already at this state.`);
145
- return;
146
- }
147
- const lines = [
148
- `Recovery preview (${arrow} ${result.target}):`,
149
- "",
150
- ` tables affected: ${String(result.tablesAffected)}`,
151
- ];
152
- for (const c of result.changes) {
153
- lines.push(` ${c.table}: ${describeChange(c)}`);
154
- }
155
- if (result.estimatedSeconds !== undefined) {
156
- lines.push("");
157
- lines.push(` estimated time: ~${String(result.estimatedSeconds)}s`);
158
- }
159
- (0, output_1.emit)(lines.join("\n"));
160
- }
161
- function describeChange(c) {
162
- if (c.action === "restore_table" || c.action === "drop" || c.action === "create") {
163
- const ts = c.droppedAt ? ` (was dropped at ${c.droppedAt})` : "";
164
- if (c.action === "restore_table")
165
- return `table will be restored${ts}`;
166
- if (c.action === "drop")
167
- return `table will be dropped${ts}`;
168
- return `table will be created${ts}`;
169
- }
170
- const parts = [];
171
- if (c.inserted !== undefined && c.inserted !== 0)
172
- parts.push(`+${String(c.inserted)} rows`);
173
- if (c.deleted !== undefined && c.deleted !== 0) {
174
- parts.push(`-${String(c.deleted)} ${c.deleted === 1 ? "row" : "rows"}`);
175
- }
176
- if (c.modified !== undefined && c.modified !== 0)
177
- parts.push(`~${String(c.modified)} rows modified`);
178
- return parts.length === 0 ? "no changes" : parts.join(", ");
179
- }
180
- async function confirm(prompt) {
181
- const rl = node_readline_1.default.createInterface({ input: process.stdin, output: process.stderr });
182
- return new Promise((resolve) => {
183
- rl.question(prompt, (answer) => {
184
- rl.close();
185
- resolve(answer.trim().toLowerCase() === "y");
186
- });
187
- });
188
- }