@lark-apaas/miaoda-cli 0.1.0-alpha.097a394
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/LICENSE +13 -0
- package/README.md +66 -0
- package/bin/miaoda.js +2 -0
- package/dist/api/db/api.js +160 -0
- package/dist/api/db/client.js +108 -0
- package/dist/api/db/index.js +16 -0
- package/dist/api/db/parsers.js +157 -0
- package/dist/api/db/types.js +10 -0
- package/dist/api/file/api.js +420 -0
- package/dist/api/file/client.js +161 -0
- package/dist/api/file/detect.js +56 -0
- package/dist/api/file/index.js +17 -0
- package/dist/api/file/parsers.js +72 -0
- package/dist/api/file/types.js +3 -0
- package/dist/api/index.js +42 -0
- package/dist/api/plugin/api.js +243 -0
- package/dist/api/plugin/index.js +12 -0
- package/dist/api/plugin/types.js +3 -0
- package/dist/cli/commands/db/index.js +73 -0
- package/dist/cli/commands/file/index.js +67 -0
- package/dist/cli/commands/index.js +11 -0
- package/dist/cli/commands/plugin/index.js +204 -0
- package/dist/cli/commands/shared.js +53 -0
- package/dist/cli/handlers/db/data.js +167 -0
- package/dist/cli/handlers/db/index.js +11 -0
- package/dist/cli/handlers/db/schema.js +161 -0
- package/dist/cli/handlers/db/sql.js +173 -0
- package/dist/cli/handlers/file/cp.js +220 -0
- package/dist/cli/handlers/file/helpers.js +16 -0
- package/dist/cli/handlers/file/index.js +13 -0
- package/dist/cli/handlers/file/ls.js +109 -0
- package/dist/cli/handlers/file/rm.js +243 -0
- package/dist/cli/handlers/file/sign.js +96 -0
- package/dist/cli/handlers/file/stat.js +97 -0
- package/dist/cli/handlers/index.js +19 -0
- package/dist/cli/handlers/plugin/index.js +10 -0
- package/dist/cli/handlers/plugin/plugin-local.js +382 -0
- package/dist/cli/handlers/plugin/plugin.js +308 -0
- package/dist/cli/handlers/shared.js +139 -0
- package/dist/main.js +31 -0
- package/dist/utils/config.js +31 -0
- package/dist/utils/error.js +35 -0
- package/dist/utils/http.js +46 -0
- package/dist/utils/index.js +25 -0
- package/dist/utils/log_id.js +13 -0
- package/dist/utils/logger.js +15 -0
- package/dist/utils/output.js +59 -0
- package/package.json +53 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAttachment = parseAttachment;
|
|
4
|
+
exports.parseHead = parseHead;
|
|
5
|
+
/** 安全读取字符串字段(空字符串回退为默认值) */
|
|
6
|
+
function str(value, fallback = "") {
|
|
7
|
+
return typeof value === "string" && value.length > 0 ? value : fallback;
|
|
8
|
+
}
|
|
9
|
+
/** 安全读取数字字段(非正值回退到 0) */
|
|
10
|
+
function int(value) {
|
|
11
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
12
|
+
return Math.trunc(value);
|
|
13
|
+
}
|
|
14
|
+
return 0;
|
|
15
|
+
}
|
|
16
|
+
function readSize(meta) {
|
|
17
|
+
if (!meta)
|
|
18
|
+
return 0;
|
|
19
|
+
const v = meta.size ??
|
|
20
|
+
meta.fileSize ??
|
|
21
|
+
meta.file_size ??
|
|
22
|
+
meta.contentLength ??
|
|
23
|
+
0;
|
|
24
|
+
return int(v);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 展示层 path 统一带前导 `/`(对齐 PRD / SKILL 里的示例)。
|
|
28
|
+
* 后端存储的 path 实际是无前导 `/` 的,这里补齐。
|
|
29
|
+
*/
|
|
30
|
+
function toDisplayPath(p) {
|
|
31
|
+
if (!p)
|
|
32
|
+
return p;
|
|
33
|
+
return p.startsWith("/") ? p : `/${p}`;
|
|
34
|
+
}
|
|
35
|
+
/** 将后端 attachment 结构映射为 CLI FileInfo(用于 ls) */
|
|
36
|
+
function parseAttachment(att) {
|
|
37
|
+
const rawPath = str(att.filePath, str(att.name));
|
|
38
|
+
const info = {
|
|
39
|
+
file_name: str(att.name),
|
|
40
|
+
path: toDisplayPath(rawPath),
|
|
41
|
+
size_bytes: readSize(att.metadata),
|
|
42
|
+
type: str(att.metadata?.mimeType),
|
|
43
|
+
uploaded_at: str(att.createdAt),
|
|
44
|
+
};
|
|
45
|
+
const downloadUrl = str(att.downloadURL);
|
|
46
|
+
if (downloadUrl)
|
|
47
|
+
info.download_url = downloadUrl;
|
|
48
|
+
// uploaded_by 从 createdBy.name 映射(后端返 {userID, name, email, ...},空代表匿名)
|
|
49
|
+
const uploader = str(att.createdBy?.name);
|
|
50
|
+
if (uploader)
|
|
51
|
+
info.uploaded_by = uploader;
|
|
52
|
+
return info;
|
|
53
|
+
}
|
|
54
|
+
/** 将后端 head 响应映射为 CLI FileInfo(用于 stat) */
|
|
55
|
+
function parseHead(data, filePath) {
|
|
56
|
+
const outer = data?.metadata ?? {};
|
|
57
|
+
const inner = outer.metadata ?? {};
|
|
58
|
+
const info = {
|
|
59
|
+
file_name: str(outer.name),
|
|
60
|
+
path: toDisplayPath(filePath || str(outer.name)),
|
|
61
|
+
size_bytes: readSize(inner),
|
|
62
|
+
type: str(inner.mimeType),
|
|
63
|
+
uploaded_at: str(inner.lastModified),
|
|
64
|
+
};
|
|
65
|
+
const downloadUrl = str(outer.downloadURL);
|
|
66
|
+
if (downloadUrl)
|
|
67
|
+
info.download_url = downloadUrl;
|
|
68
|
+
const uploader = str(outer.createdBy?.name);
|
|
69
|
+
if (uploader)
|
|
70
|
+
info.uploaded_by = uploader;
|
|
71
|
+
return info;
|
|
72
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.db = exports.file = exports.plugin = void 0;
|
|
37
|
+
const _plugin = __importStar(require("../api/plugin/index"));
|
|
38
|
+
const _file = __importStar(require("../api/file/index"));
|
|
39
|
+
const _db = __importStar(require("../api/db/index"));
|
|
40
|
+
exports.plugin = { ..._plugin };
|
|
41
|
+
exports.file = { ..._file };
|
|
42
|
+
exports.db = { ..._db };
|
|
@@ -0,0 +1,243 @@
|
|
|
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.getPluginVersions = getPluginVersions;
|
|
7
|
+
exports.getPluginVersion = getPluginVersion;
|
|
8
|
+
exports.downloadPlugin = downloadPlugin;
|
|
9
|
+
exports.getCachePath = getCachePath;
|
|
10
|
+
exports.hasCachedPlugin = hasCachedPlugin;
|
|
11
|
+
exports.listCachedPlugins = listCachedPlugins;
|
|
12
|
+
exports.cleanAllCache = cleanAllCache;
|
|
13
|
+
exports.cleanPluginCache = cleanPluginCache;
|
|
14
|
+
exports.reportEvents = reportEvents;
|
|
15
|
+
exports.reportInstallEvent = reportInstallEvent;
|
|
16
|
+
exports.reportCreateInstanceEvent = reportCreateInstanceEvent;
|
|
17
|
+
const http_client_1 = require("@lark-apaas/http-client");
|
|
18
|
+
const http_1 = require("../../utils/http");
|
|
19
|
+
const error_1 = require("../../utils/error");
|
|
20
|
+
const logger_1 = require("../../utils/logger");
|
|
21
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
22
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
23
|
+
// ── Plugin Version API ──
|
|
24
|
+
async function getPluginVersions(keys, latestOnly = true) {
|
|
25
|
+
const client = (0, http_1.getHttpClient)();
|
|
26
|
+
const response = await client.post(`/api/v1/studio/innerapi/plugins/-/versions/batch_get?keys=${keys.join(",")}&latest_only=${String(latestOnly)}`);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new error_1.HttpError(response.status, response.url, `Failed to get plugin versions: ${String(response.status)} ${response.statusText}`);
|
|
29
|
+
}
|
|
30
|
+
const result = (await response.json());
|
|
31
|
+
if (result.status_code !== "0") {
|
|
32
|
+
throw new error_1.AppError("INTERNAL_API_ERROR", `API error: ${result.message ?? "unknown"}`);
|
|
33
|
+
}
|
|
34
|
+
return result.data.pluginVersions;
|
|
35
|
+
}
|
|
36
|
+
async function getPluginVersion(pluginKey, requestedVersion) {
|
|
37
|
+
const isLatest = requestedVersion === "latest";
|
|
38
|
+
const versions = await getPluginVersions([pluginKey], isLatest);
|
|
39
|
+
const pluginVersions = versions[pluginKey];
|
|
40
|
+
if (!pluginVersions || pluginVersions.length === 0) {
|
|
41
|
+
throw new error_1.AppError("PLUGIN_NOT_FOUND", `Plugin not found: ${pluginKey}`, { next_actions: ["检查包名拼写,或确认该插件已在插件市场发布"] });
|
|
42
|
+
}
|
|
43
|
+
if (isLatest) {
|
|
44
|
+
return pluginVersions[0];
|
|
45
|
+
}
|
|
46
|
+
const targetVersion = pluginVersions.find((v) => v.version === requestedVersion);
|
|
47
|
+
if (!targetVersion) {
|
|
48
|
+
throw new error_1.AppError("VERSION_NOT_FOUND", `Version ${requestedVersion} not found for plugin ${pluginKey}`, { next_actions: [`可用版本:${pluginVersions.map((v) => v.version).join(", ")}`] });
|
|
49
|
+
}
|
|
50
|
+
return targetVersion;
|
|
51
|
+
}
|
|
52
|
+
// ── Plugin Download ──
|
|
53
|
+
function parsePluginKey(key) {
|
|
54
|
+
const match = /^(@[^/]+)\/(.+)$/.exec(key);
|
|
55
|
+
if (!match) {
|
|
56
|
+
throw new error_1.AppError("INVALID_PLUGIN_KEY", `Invalid plugin key format: ${key}`, { next_actions: ["插件 key 必须形如 @scope/name"] });
|
|
57
|
+
}
|
|
58
|
+
return { scope: match[1], name: match[2] };
|
|
59
|
+
}
|
|
60
|
+
async function downloadFromInner(pluginKey, version) {
|
|
61
|
+
const client = (0, http_1.getHttpClient)();
|
|
62
|
+
const { scope, name } = parsePluginKey(pluginKey);
|
|
63
|
+
const url = `/api/v1/studio/innerapi/plugins/${scope}/${name}/versions/${version}/package`;
|
|
64
|
+
const response = await client.get(url);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
throw new error_1.HttpError(response.status, url, `Failed to download plugin: ${String(response.status)} ${response.statusText}`);
|
|
67
|
+
}
|
|
68
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
69
|
+
return Buffer.from(arrayBuffer);
|
|
70
|
+
}
|
|
71
|
+
async function downloadFromPublic(downloadURL) {
|
|
72
|
+
const client = new http_client_1.HttpClient({ timeout: 60000 });
|
|
73
|
+
const response = await client.get(downloadURL);
|
|
74
|
+
if (!response.ok) {
|
|
75
|
+
throw new error_1.HttpError(response.status, downloadURL, `Failed to download from public URL: ${String(response.status)} ${response.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
78
|
+
return Buffer.from(arrayBuffer);
|
|
79
|
+
}
|
|
80
|
+
const MAX_RETRIES = 2;
|
|
81
|
+
async function withRetry(operation, description, maxRetries = MAX_RETRIES) {
|
|
82
|
+
let lastError;
|
|
83
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
84
|
+
try {
|
|
85
|
+
return await operation();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
89
|
+
if (attempt < maxRetries) {
|
|
90
|
+
(0, logger_1.log)("plugin", `${description} failed, retrying (${String(attempt + 1)}/${String(maxRetries)})...`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw lastError ?? new error_1.AppError("INTERNAL_RETRY_EXHAUSTED", `${description} failed after ${String(maxRetries)} retries`, { retryable: true, next_actions: ["检查网络后重试,--verbose 可查看重试日志"] });
|
|
95
|
+
}
|
|
96
|
+
/** 插件缓存目录 */
|
|
97
|
+
const PLUGIN_CACHE_DIR = "node_modules/.cache/miaoda-cli/plugins";
|
|
98
|
+
function getPluginCacheDir() {
|
|
99
|
+
return node_path_1.default.join(process.cwd(), PLUGIN_CACHE_DIR);
|
|
100
|
+
}
|
|
101
|
+
function ensureCacheDir() {
|
|
102
|
+
const cacheDir = getPluginCacheDir();
|
|
103
|
+
if (!node_fs_1.default.existsSync(cacheDir)) {
|
|
104
|
+
node_fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function getTempFilePath(pluginKey, version) {
|
|
108
|
+
ensureCacheDir();
|
|
109
|
+
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
110
|
+
const filename = `${safeKey}@${version}.tgz`;
|
|
111
|
+
return node_path_1.default.join(getPluginCacheDir(), filename);
|
|
112
|
+
}
|
|
113
|
+
async function downloadPlugin(pluginKey, requestedVersion) {
|
|
114
|
+
const pluginInfo = await getPluginVersion(pluginKey, requestedVersion);
|
|
115
|
+
let tgzBuffer;
|
|
116
|
+
if (pluginInfo.downloadApproach === "inner") {
|
|
117
|
+
tgzBuffer = await withRetry(() => downloadFromInner(pluginKey, pluginInfo.version), "Download");
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
tgzBuffer = await withRetry(() => downloadFromPublic(pluginInfo.downloadURL), "Download");
|
|
121
|
+
}
|
|
122
|
+
const tgzPath = getTempFilePath(pluginKey, pluginInfo.version);
|
|
123
|
+
node_fs_1.default.writeFileSync(tgzPath, tgzBuffer);
|
|
124
|
+
return {
|
|
125
|
+
tgzPath,
|
|
126
|
+
version: pluginInfo.version,
|
|
127
|
+
pluginInfo,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// ── Cache ──
|
|
131
|
+
function getCachePath(pluginKey, version) {
|
|
132
|
+
ensureCacheDir();
|
|
133
|
+
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
134
|
+
const filename = `${safeKey}@${version}.tgz`;
|
|
135
|
+
return node_path_1.default.join(getPluginCacheDir(), filename);
|
|
136
|
+
}
|
|
137
|
+
function hasCachedPlugin(pluginKey, version) {
|
|
138
|
+
const cachePath = getCachePath(pluginKey, version);
|
|
139
|
+
return node_fs_1.default.existsSync(cachePath);
|
|
140
|
+
}
|
|
141
|
+
function listCachedPlugins() {
|
|
142
|
+
const cacheDir = getPluginCacheDir();
|
|
143
|
+
if (!node_fs_1.default.existsSync(cacheDir)) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
const files = node_fs_1.default.readdirSync(cacheDir);
|
|
147
|
+
const result = [];
|
|
148
|
+
for (const file of files) {
|
|
149
|
+
if (!file.endsWith(".tgz"))
|
|
150
|
+
continue;
|
|
151
|
+
const match = /^(.+)@(.+)\.tgz$/.exec(file);
|
|
152
|
+
if (!match)
|
|
153
|
+
continue;
|
|
154
|
+
const [, rawName, version] = match;
|
|
155
|
+
const name = rawName.replace(/^_/, "@").replace(/_/, "/");
|
|
156
|
+
const filePath = node_path_1.default.join(cacheDir, file);
|
|
157
|
+
const stat = node_fs_1.default.statSync(filePath);
|
|
158
|
+
result.push({ name, version, filePath, size: stat.size, mtime: stat.mtime });
|
|
159
|
+
}
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
function cleanAllCache() {
|
|
163
|
+
const cacheDir = getPluginCacheDir();
|
|
164
|
+
if (!node_fs_1.default.existsSync(cacheDir)) {
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
const files = node_fs_1.default.readdirSync(cacheDir);
|
|
168
|
+
let count = 0;
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
if (file.endsWith(".tgz")) {
|
|
171
|
+
node_fs_1.default.unlinkSync(node_path_1.default.join(cacheDir, file));
|
|
172
|
+
count++;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return count;
|
|
176
|
+
}
|
|
177
|
+
function cleanPluginCache(pluginKey, version) {
|
|
178
|
+
const cacheDir = getPluginCacheDir();
|
|
179
|
+
if (!node_fs_1.default.existsSync(cacheDir)) {
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
183
|
+
const files = node_fs_1.default.readdirSync(cacheDir);
|
|
184
|
+
let count = 0;
|
|
185
|
+
for (const file of files) {
|
|
186
|
+
if (version) {
|
|
187
|
+
if (file === `${safeKey}@${version}.tgz`) {
|
|
188
|
+
node_fs_1.default.unlinkSync(node_path_1.default.join(cacheDir, file));
|
|
189
|
+
count++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
if (file.startsWith(`${safeKey}@`) && file.endsWith(".tgz")) {
|
|
194
|
+
node_fs_1.default.unlinkSync(node_path_1.default.join(cacheDir, file));
|
|
195
|
+
count++;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return count;
|
|
200
|
+
}
|
|
201
|
+
// ── Telemetry ──
|
|
202
|
+
async function reportEvents(events) {
|
|
203
|
+
if (events.length === 0)
|
|
204
|
+
return true;
|
|
205
|
+
try {
|
|
206
|
+
const client = (0, http_1.getHttpClient)();
|
|
207
|
+
const response = await client.post("/api/v1/studio/innerapi/resource_events", { events });
|
|
208
|
+
if (!response.ok) {
|
|
209
|
+
(0, logger_1.log)("telemetry", `Failed to report events: ${String(response.status)} ${response.statusText}`);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
const result = (await response.json());
|
|
213
|
+
if (result.status_code !== "0") {
|
|
214
|
+
(0, logger_1.log)("telemetry", `API error: ${result.message ?? "unknown"}`);
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
(0, logger_1.log)("telemetry", `Failed to report events: ${error instanceof Error ? error.message : String(error)}`);
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function reportInstallEvent(pluginKey, version) {
|
|
225
|
+
await reportEvents([
|
|
226
|
+
{
|
|
227
|
+
resourceType: "plugin",
|
|
228
|
+
resourceKey: pluginKey,
|
|
229
|
+
eventType: "install",
|
|
230
|
+
details: { version },
|
|
231
|
+
},
|
|
232
|
+
]);
|
|
233
|
+
}
|
|
234
|
+
async function reportCreateInstanceEvent(pluginKey, version) {
|
|
235
|
+
await reportEvents([
|
|
236
|
+
{
|
|
237
|
+
resourceType: "plugin",
|
|
238
|
+
resourceKey: pluginKey,
|
|
239
|
+
eventType: "create_instance",
|
|
240
|
+
details: { version },
|
|
241
|
+
},
|
|
242
|
+
]);
|
|
243
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reportCreateInstanceEvent = exports.reportInstallEvent = exports.reportEvents = exports.hasCachedPlugin = exports.getCachePath = exports.downloadPlugin = exports.getPluginVersion = exports.getPluginVersions = void 0;
|
|
4
|
+
var api_1 = require("./api");
|
|
5
|
+
Object.defineProperty(exports, "getPluginVersions", { enumerable: true, get: function () { return api_1.getPluginVersions; } });
|
|
6
|
+
Object.defineProperty(exports, "getPluginVersion", { enumerable: true, get: function () { return api_1.getPluginVersion; } });
|
|
7
|
+
Object.defineProperty(exports, "downloadPlugin", { enumerable: true, get: function () { return api_1.downloadPlugin; } });
|
|
8
|
+
Object.defineProperty(exports, "getCachePath", { enumerable: true, get: function () { return api_1.getCachePath; } });
|
|
9
|
+
Object.defineProperty(exports, "hasCachedPlugin", { enumerable: true, get: function () { return api_1.hasCachedPlugin; } });
|
|
10
|
+
Object.defineProperty(exports, "reportEvents", { enumerable: true, get: function () { return api_1.reportEvents; } });
|
|
11
|
+
Object.defineProperty(exports, "reportInstallEvent", { enumerable: true, get: function () { return api_1.reportInstallEvent; } });
|
|
12
|
+
Object.defineProperty(exports, "reportCreateInstanceEvent", { enumerable: true, get: function () { return api_1.reportCreateInstanceEvent; } });
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerDbCommands = registerDbCommands;
|
|
4
|
+
const index_1 = require("../../../cli/handlers/db/index");
|
|
5
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
6
|
+
function registerDbCommands(program) {
|
|
7
|
+
const dbCmd = program
|
|
8
|
+
.command("db")
|
|
9
|
+
.description("数据操作:SQL 执行、表结构查询、数据导入导出");
|
|
10
|
+
dbCmd.action(() => {
|
|
11
|
+
dbCmd.outputHelp();
|
|
12
|
+
});
|
|
13
|
+
dbCmd
|
|
14
|
+
.command("sql")
|
|
15
|
+
.description("执行任意 SQL(SELECT / DML / DDL / TCL / EXPLAIN);query 省略时读 stdin")
|
|
16
|
+
.argument("[query]", "要执行的 SQL 语句;省略时从 stdin 读取")
|
|
17
|
+
.addOption((0, shared_1.appIdOption)())
|
|
18
|
+
.option("--env <env>", "目标环境(P0 未启用多环境)")
|
|
19
|
+
.action(async (query, opts) => {
|
|
20
|
+
await (0, index_1.handleDbSql)(query, opts);
|
|
21
|
+
});
|
|
22
|
+
// schema 二级资源分组
|
|
23
|
+
const schemaCmd = dbCmd
|
|
24
|
+
.command("schema")
|
|
25
|
+
.description("表结构查询");
|
|
26
|
+
schemaCmd.action(() => {
|
|
27
|
+
schemaCmd.outputHelp();
|
|
28
|
+
});
|
|
29
|
+
schemaCmd
|
|
30
|
+
.command("list")
|
|
31
|
+
.description("列出应用所有表(rows / size / columns / updated_at)")
|
|
32
|
+
.addOption((0, shared_1.appIdOption)())
|
|
33
|
+
.action(async (opts) => {
|
|
34
|
+
await (0, index_1.handleDbSchemaList)(opts);
|
|
35
|
+
});
|
|
36
|
+
schemaCmd
|
|
37
|
+
.command("get")
|
|
38
|
+
.description("查看单表结构(字段 / 索引 / DDL)")
|
|
39
|
+
.argument("<table>", "表名")
|
|
40
|
+
.addOption((0, shared_1.appIdOption)())
|
|
41
|
+
.option("--ddl", "TTY 下强制输出完整 DDL 而非结构化概览")
|
|
42
|
+
.action(async (table, opts) => {
|
|
43
|
+
await (0, index_1.handleDbSchemaGet)(table, opts);
|
|
44
|
+
});
|
|
45
|
+
// data 二级资源分组
|
|
46
|
+
const dataCmd = dbCmd
|
|
47
|
+
.command("data")
|
|
48
|
+
.description("数据导入 / 导出");
|
|
49
|
+
dataCmd.action(() => {
|
|
50
|
+
dataCmd.outputHelp();
|
|
51
|
+
});
|
|
52
|
+
dataCmd
|
|
53
|
+
.command("import")
|
|
54
|
+
.description("从 CSV / JSON 文件导入数据(P0:≤ 1 MB / ≤ 5000 行,单事务原子)")
|
|
55
|
+
.argument("<file>", "本地文件路径")
|
|
56
|
+
.addOption((0, shared_1.appIdOption)())
|
|
57
|
+
.option("--table <name>", "目标表名;省略时按文件名推断")
|
|
58
|
+
.option("--format <fmt>", "csv | json;省略时按文件扩展名推断")
|
|
59
|
+
.action(async (file, opts) => {
|
|
60
|
+
await (0, index_1.handleDbDataImport)(file, opts);
|
|
61
|
+
});
|
|
62
|
+
dataCmd
|
|
63
|
+
.command("export")
|
|
64
|
+
.description("导出整表到 CSV / JSON(P0:≤ 1 MB / ≤ 5000 行)")
|
|
65
|
+
.argument("<table>", "表名")
|
|
66
|
+
.addOption((0, shared_1.appIdOption)())
|
|
67
|
+
.option("--format <fmt>", "csv | json;默认 csv")
|
|
68
|
+
.option("-f, --file <path>", "输出文件路径;默认 <table>.<format>")
|
|
69
|
+
.option("--limit <n>", "最多导出行数(≤ 5000)")
|
|
70
|
+
.action(async (table, opts) => {
|
|
71
|
+
await (0, index_1.handleDbDataExport)(table, opts);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerFileCommands = registerFileCommands;
|
|
4
|
+
const index_1 = require("../../../cli/handlers/file/index");
|
|
5
|
+
const shared_1 = require("../../../cli/commands/shared");
|
|
6
|
+
function registerFileCommands(program) {
|
|
7
|
+
const fileCmd = program
|
|
8
|
+
.command("file")
|
|
9
|
+
.description("文件操作:上传、下载、删除、查询");
|
|
10
|
+
fileCmd.action(() => {
|
|
11
|
+
fileCmd.outputHelp();
|
|
12
|
+
});
|
|
13
|
+
fileCmd
|
|
14
|
+
.command("ls")
|
|
15
|
+
.description("列出应用下的文件")
|
|
16
|
+
.argument("[query]", "可选筛选值:形似 /path、包含 / 或 16+位 fileKey 时按 path 精确匹配;否则按 file_name 精确匹配")
|
|
17
|
+
.addOption((0, shared_1.appIdOption)())
|
|
18
|
+
.option("--path <path>", "按 path 精确匹配(跳过自动识别)")
|
|
19
|
+
.option("--name <name>", "按 file_name 精确匹配(跳过自动识别)")
|
|
20
|
+
.option("--type <mime>", "按 MIME 类型过滤(精确匹配)")
|
|
21
|
+
.option("--size-gt <size>", "大小大于,支持 B/KB/MB/GB")
|
|
22
|
+
.option("--size-lt <size>", "大小小于")
|
|
23
|
+
.option("--uploaded-since <time>", "上传时间晚于(ISO 8601)")
|
|
24
|
+
.option("--limit <n>", "返回条数上限", "50")
|
|
25
|
+
.option("--cursor <token>", "分页游标")
|
|
26
|
+
.option("--all", "自动翻页聚合全部结果")
|
|
27
|
+
.action(async (query, opts) => {
|
|
28
|
+
await (0, index_1.handleFileLs)({ ...opts, query });
|
|
29
|
+
});
|
|
30
|
+
fileCmd
|
|
31
|
+
.command("stat")
|
|
32
|
+
.description("查看指定文件的元数据")
|
|
33
|
+
.argument("<file>", "path 或 file_name:自动识别(见 ls 命令说明)")
|
|
34
|
+
.addOption((0, shared_1.appIdOption)())
|
|
35
|
+
.action(async (file, opts) => {
|
|
36
|
+
await (0, index_1.handleFileStat)(file, opts);
|
|
37
|
+
});
|
|
38
|
+
fileCmd
|
|
39
|
+
.command("cp")
|
|
40
|
+
.description("上传或下载文件(方向由 src/dst 自动判断)")
|
|
41
|
+
.argument("<src>", "源:本地路径 或 远程 /path / file_name")
|
|
42
|
+
.argument("<dst>", "目标:本地路径 或 远程路径")
|
|
43
|
+
.addOption((0, shared_1.appIdOption)())
|
|
44
|
+
.option("--rename <name>", "上传后使用的新文件名")
|
|
45
|
+
.action(async (src, dst, opts) => {
|
|
46
|
+
await (0, index_1.handleFileCp)(src, dst, opts);
|
|
47
|
+
});
|
|
48
|
+
fileCmd
|
|
49
|
+
.command("rm")
|
|
50
|
+
.description("删除一个或多个文件(best-effort)")
|
|
51
|
+
.argument("[paths...]", "path 或 file_name:形似 /path、含 / 或 16+位 fileKey 时按 path 精确删除,其余按 file_name 查找后删除")
|
|
52
|
+
.addOption((0, shared_1.appIdOption)())
|
|
53
|
+
.option("-n, --name <name>", "强制按 file_name 查找后删除(跳过自动识别);可重复指定;多匹配报 AMBIGUOUS_FILE_NAME", (value, prev) => [...(prev ?? []), value])
|
|
54
|
+
.option("-y, --yes", "跳过交互确认")
|
|
55
|
+
.action(async (paths, opts) => {
|
|
56
|
+
await (0, index_1.handleFileRm)(paths, opts);
|
|
57
|
+
});
|
|
58
|
+
fileCmd
|
|
59
|
+
.command("sign")
|
|
60
|
+
.description("生成文件临时下载链接")
|
|
61
|
+
.argument("<file>", "path 或 file_name:自动识别(见 ls 命令说明)")
|
|
62
|
+
.addOption((0, shared_1.appIdOption)())
|
|
63
|
+
.option("--expires <duration>", "过期时长(默认 7d,最长 30d)")
|
|
64
|
+
.action(async (file, opts) => {
|
|
65
|
+
await (0, index_1.handleFileSign)(file, opts);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerCommands = registerCommands;
|
|
4
|
+
const index_1 = require("../../cli/commands/plugin/index");
|
|
5
|
+
const index_2 = require("../../cli/commands/file/index");
|
|
6
|
+
const index_3 = require("../../cli/commands/db/index");
|
|
7
|
+
function registerCommands(program) {
|
|
8
|
+
(0, index_1.registerPluginCommands)(program);
|
|
9
|
+
(0, index_2.registerFileCommands)(program);
|
|
10
|
+
(0, index_3.registerDbCommands)(program);
|
|
11
|
+
}
|