rkb-cli 0.3.0-beta.1
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 +18 -0
- package/bin/run.js +5 -0
- package/edition.json +20 -0
- package/lib/adapters/aliyun/official-cli.js +338 -0
- package/lib/adapters/pop/context.js +34 -0
- package/lib/adapters/pop/doc-publish.js +7 -0
- package/lib/adapters/pop/identity.js +31 -0
- package/lib/adapters/pop/pipeline.js +50 -0
- package/lib/adapters/pop/sandbox-sts.js +19 -0
- package/lib/adapters/pop/space-read.js +67 -0
- package/lib/adapters/pop/transport.js +120 -0
- package/lib/command-registry.js +19 -0
- package/lib/commands/doc/index.js +2 -0
- package/lib/commands/doc/publish.js +31 -0
- package/lib/commands/space/index.js +2 -0
- package/lib/commands/space/list.js +40 -0
- package/lib/commands/space/use.js +29 -0
- package/lib/commands/whoami.js +34 -0
- package/lib/config/index.js +157 -0
- package/lib/core/context.js +12 -0
- package/lib/core/result.js +17 -0
- package/lib/features/auth/aliyun/command.js +78 -0
- package/lib/features/auth/aliyun/factory.js +3 -0
- package/lib/features/auth/aliyun/logout-command.js +69 -0
- package/lib/features/doc/pipeline/service.js +65 -0
- package/lib/features/space/read/service.js +65 -0
- package/lib/lib/command-flags.js +12 -0
- package/lib/lib/git-project.js +47 -0
- package/lib/lib/log-paths.js +30 -0
- package/lib/lib/logger.js +146 -0
- package/lib/runtime/bootstrap.js +7 -0
- package/lib/runtime/container.js +13 -0
- package/lib/runtime/profile.js +89 -0
- package/package.json +42 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { CapabilityError } from "../../../core/result.js";
|
|
2
|
+
export class PipelineService {
|
|
3
|
+
api;
|
|
4
|
+
context;
|
|
5
|
+
constructor(api, context) {
|
|
6
|
+
this.api = api;
|
|
7
|
+
this.context = context;
|
|
8
|
+
}
|
|
9
|
+
async startPipeline() {
|
|
10
|
+
if (this.context.requireSpace && !this.context.getSpace())
|
|
11
|
+
return {
|
|
12
|
+
success: false,
|
|
13
|
+
code: "SPACE_NOT_SELECTED",
|
|
14
|
+
error: `No current space. Run '${this.context.bin} space use <spaceCode>' first.`,
|
|
15
|
+
};
|
|
16
|
+
const project = this.context.getProject();
|
|
17
|
+
if (!project)
|
|
18
|
+
return {
|
|
19
|
+
success: false,
|
|
20
|
+
code: "GIT_CONTEXT_MISSING",
|
|
21
|
+
error: "Not a supported Git repository. Run this command in a documentation repository with an origin remote.",
|
|
22
|
+
};
|
|
23
|
+
const space = this.context.getSpace();
|
|
24
|
+
if (space && space !== project.spaceCode)
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
code: "SPACE_MISMATCH",
|
|
28
|
+
error: `Current space '${space}' does not match Git remote space '${project.spaceCode}'.`,
|
|
29
|
+
};
|
|
30
|
+
const issues = this.context.getGitIssues();
|
|
31
|
+
if (issues.length)
|
|
32
|
+
return { success: false, code: "GIT_NOT_READY", error: issues.join(" ") };
|
|
33
|
+
const input = { ...project };
|
|
34
|
+
if (this.context.workflowInstanceId) {
|
|
35
|
+
const id = Number(this.context.workflowInstanceId);
|
|
36
|
+
if (!Number.isSafeInteger(id))
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
code: "INVALID_WORKFLOW_INSTANCE_ID",
|
|
40
|
+
error: "WORKFLOW_INSTANCE_ID must be an integer.",
|
|
41
|
+
};
|
|
42
|
+
input.workflowInstanceId = id;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const run = await this.api.start(input);
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
data: {
|
|
49
|
+
...run,
|
|
50
|
+
spaceCode: project.spaceCode,
|
|
51
|
+
branchName: project.branchName,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
success: false,
|
|
58
|
+
code: error instanceof CapabilityError
|
|
59
|
+
? error.code
|
|
60
|
+
: "PIPELINE_START_FAILED",
|
|
61
|
+
error: error instanceof Error ? error.message : String(error),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { failure } from "../../../core/result.js";
|
|
2
|
+
export class SpaceReadService {
|
|
3
|
+
api;
|
|
4
|
+
context;
|
|
5
|
+
constructor(api, context) {
|
|
6
|
+
this.api = api;
|
|
7
|
+
this.context = context;
|
|
8
|
+
}
|
|
9
|
+
async list() {
|
|
10
|
+
try {
|
|
11
|
+
return {
|
|
12
|
+
success: true,
|
|
13
|
+
data: {
|
|
14
|
+
spaces: await this.api.listSpaces(),
|
|
15
|
+
currentSpaceCode: this.context.getSpace(),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
return failure("Failed to list spaces", error);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async use(code) {
|
|
24
|
+
if (this.context.isSpaceFromEnv())
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
code: "SPACE_FROM_ENV",
|
|
28
|
+
error: `Current space is controlled by ${this.context.spaceEnvKey}. Unset it before switching spaces.`,
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
const spaces = await this.api.listSpaces();
|
|
32
|
+
const space = spaces.find((item) => item.code === code.trim());
|
|
33
|
+
if (!space)
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
code: "SPACE_NOT_FOUND",
|
|
37
|
+
error: `Space is not accessible with the current ${this.context.credentialLabel}: ${code.trim()}`,
|
|
38
|
+
};
|
|
39
|
+
this.context.setSpace(space.code);
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
message: `Switched to space: ${space.code}`,
|
|
43
|
+
data: { space },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return failure("Failed to switch space", error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async get() {
|
|
51
|
+
const code = this.context.getSpace();
|
|
52
|
+
if (!code)
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
code: "SPACE_NOT_SELECTED",
|
|
56
|
+
error: `No current space. Run '${this.context.bin} space use <spaceCode>' first.`,
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
return { success: true, data: { space: await this.api.getSpace(code) } };
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return failure(`Failed to get space ${code}`, error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
export const baseFlags = {
|
|
3
|
+
json: Flags.boolean({
|
|
4
|
+
description: "Output as JSON",
|
|
5
|
+
default: false,
|
|
6
|
+
}),
|
|
7
|
+
verbose: Flags.boolean({
|
|
8
|
+
char: "v",
|
|
9
|
+
description: "Enable verbose output",
|
|
10
|
+
default: false,
|
|
11
|
+
}),
|
|
12
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
function git(args, cwd = process.cwd()) {
|
|
3
|
+
try {
|
|
4
|
+
return execFileSync("git", args, {
|
|
5
|
+
cwd,
|
|
6
|
+
encoding: "utf8",
|
|
7
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
8
|
+
}).trim();
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function parseGitRemote(remoteUrl) {
|
|
15
|
+
const ssh = remoteUrl.match(/^git@[^:]+:([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
16
|
+
const https = remoteUrl.match(/^https?:\/\/[^/]+\/([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
17
|
+
const match = ssh ?? https;
|
|
18
|
+
if (!match)
|
|
19
|
+
return null;
|
|
20
|
+
return { tenantCode: match[1], spaceCode: match[2] };
|
|
21
|
+
}
|
|
22
|
+
export function getGitProjectContext(cwd = process.cwd()) {
|
|
23
|
+
const remote = parseGitRemote(git(["remote", "get-url", "origin"], cwd));
|
|
24
|
+
const branchName = git(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
25
|
+
if (!remote || !branchName)
|
|
26
|
+
return null;
|
|
27
|
+
return { ...remote, branchName };
|
|
28
|
+
}
|
|
29
|
+
export function getPipelineGitIssues(cwd = process.cwd()) {
|
|
30
|
+
const issues = [];
|
|
31
|
+
if (git(["status", "--porcelain"], cwd)) {
|
|
32
|
+
issues.push("The Git working tree contains uncommitted changes.");
|
|
33
|
+
}
|
|
34
|
+
const unpushedText = git(["rev-list", "--count", "@{upstream}..HEAD"], cwd);
|
|
35
|
+
const unpushedCount = Number.parseInt(unpushedText, 10);
|
|
36
|
+
if (Number.isFinite(unpushedCount) && unpushedCount > 0) {
|
|
37
|
+
issues.push(`The current branch contains ${unpushedCount} unpushed commit(s).`);
|
|
38
|
+
}
|
|
39
|
+
return issues;
|
|
40
|
+
}
|
|
41
|
+
/** External spaces are selected explicitly; Git organization names are not tenant codes. */
|
|
42
|
+
export function getGitBranch(cwd = process.cwd()) {
|
|
43
|
+
if (!git(["remote", "get-url", "origin"], cwd))
|
|
44
|
+
return null;
|
|
45
|
+
const branch = git(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
|
|
46
|
+
return branch && branch !== "HEAD" ? branch : null;
|
|
47
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { runtimeProfile } from "../runtime/profile.js";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { getConfigValue } from "../config/index.js";
|
|
5
|
+
export function getLogDir() {
|
|
6
|
+
const configured = getConfigValue("log.file.path").trim();
|
|
7
|
+
const value = configured || `~/${runtimeProfile.configDirName}/logs`;
|
|
8
|
+
if (value === "~")
|
|
9
|
+
return homedir();
|
|
10
|
+
if (value.startsWith("~/"))
|
|
11
|
+
return join(homedir(), value.slice(2));
|
|
12
|
+
return isAbsolute(value) ? resolve(value) : resolve(process.cwd(), value);
|
|
13
|
+
}
|
|
14
|
+
export function getLogFilename() {
|
|
15
|
+
const configured = getConfigValue("log.file.filename").trim();
|
|
16
|
+
const filename = configured || runtimeProfile.bin;
|
|
17
|
+
if (basename(filename) !== filename ||
|
|
18
|
+
!/^[A-Za-z0-9._-]+$/.test(filename) ||
|
|
19
|
+
filename === "." ||
|
|
20
|
+
filename === "..") {
|
|
21
|
+
throw new Error("log.file.filename must contain only letters, numbers, dots, underscores, or hyphens");
|
|
22
|
+
}
|
|
23
|
+
return filename;
|
|
24
|
+
}
|
|
25
|
+
export function getTodayLogName(date = new Date()) {
|
|
26
|
+
return `${getLogFilename()}-${date.toISOString().slice(0, 10)}.log`;
|
|
27
|
+
}
|
|
28
|
+
export function isManagedLogName(name) {
|
|
29
|
+
return name.startsWith(`${getLogFilename()}-`) && name.endsWith(".log");
|
|
30
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { appendFileSync, chmodSync, mkdirSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { getConfigValue } from "../config/index.js";
|
|
7
|
+
import { getLogDir, getTodayLogName } from "./log-paths.js";
|
|
8
|
+
export const LogLevel = {
|
|
9
|
+
DEBUG: 0,
|
|
10
|
+
INFO: 1,
|
|
11
|
+
WARN: 2,
|
|
12
|
+
ERROR: 3,
|
|
13
|
+
};
|
|
14
|
+
const asyncStorage = new AsyncLocalStorage();
|
|
15
|
+
export async function runWithTrace(command, operation) {
|
|
16
|
+
return asyncStorage.run({ traceId: randomUUID().slice(0, 8), command }, operation);
|
|
17
|
+
}
|
|
18
|
+
export function getTraceId() {
|
|
19
|
+
return asyncStorage.getStore()?.traceId ?? "no-trace";
|
|
20
|
+
}
|
|
21
|
+
function loadConfig() {
|
|
22
|
+
try {
|
|
23
|
+
return {
|
|
24
|
+
level: normalizeLevel(getConfigValue("log.level"), "INFO"),
|
|
25
|
+
fileEnabled: getConfigValue("log.file.enabled") !== false,
|
|
26
|
+
fileLevel: normalizeLevel(getConfigValue("log.file.level"), "DEBUG"),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return { level: "INFO", fileEnabled: true, fileLevel: "DEBUG" };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function normalizeLevel(value, fallback) {
|
|
34
|
+
const normalized = String(value).toUpperCase();
|
|
35
|
+
return normalized in LogLevel ? normalized : fallback;
|
|
36
|
+
}
|
|
37
|
+
function shouldLog(level, minimum) {
|
|
38
|
+
return LogLevel[level] >= LogLevel[minimum];
|
|
39
|
+
}
|
|
40
|
+
function stringifyData(data) {
|
|
41
|
+
if (data === undefined)
|
|
42
|
+
return "";
|
|
43
|
+
if (typeof data === "string")
|
|
44
|
+
return ` ${data}`;
|
|
45
|
+
try {
|
|
46
|
+
return ` ${JSON.stringify(data)}`;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return " [Unserializable data]";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function terminalLabel(level) {
|
|
53
|
+
switch (level) {
|
|
54
|
+
case "DEBUG":
|
|
55
|
+
return chalk.gray("debug");
|
|
56
|
+
case "INFO":
|
|
57
|
+
return chalk.blue("info");
|
|
58
|
+
case "WARN":
|
|
59
|
+
return chalk.yellow.bold("warn");
|
|
60
|
+
case "ERROR":
|
|
61
|
+
return chalk.red.bold("error");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function writeTerminal(level, message) {
|
|
65
|
+
process.stderr.write(`${terminalLabel(level)}: ${message}\n`);
|
|
66
|
+
}
|
|
67
|
+
function writeFile(level, message) {
|
|
68
|
+
try {
|
|
69
|
+
const logDir = getLogDir();
|
|
70
|
+
mkdirSync(logDir, { recursive: true, mode: 0o700 });
|
|
71
|
+
const logFile = join(logDir, getTodayLogName());
|
|
72
|
+
const context = asyncStorage.getStore();
|
|
73
|
+
const timestamp = new Date().toISOString();
|
|
74
|
+
const traceId = context?.traceId ?? "no-trace";
|
|
75
|
+
const command = context?.command ?? "rkb";
|
|
76
|
+
appendFileSync(logFile, `[${timestamp}] [${level}] [${traceId}] [${command}] ${message}\n`, { encoding: "utf8", mode: 0o600 });
|
|
77
|
+
try {
|
|
78
|
+
chmodSync(logFile, 0o600);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Some filesystems do not support POSIX permissions.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Logging must never make a command fail.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function log(level, message, data) {
|
|
89
|
+
const config = loadConfig();
|
|
90
|
+
const completeMessage = message + stringifyData(data);
|
|
91
|
+
if (shouldLog(level, config.level))
|
|
92
|
+
writeTerminal(level, completeMessage);
|
|
93
|
+
if (config.fileEnabled && shouldLog(level, config.fileLevel)) {
|
|
94
|
+
writeFile(level, completeMessage);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function terminalOnly(level, message, data) {
|
|
98
|
+
const config = loadConfig();
|
|
99
|
+
if (shouldLog(level, config.level)) {
|
|
100
|
+
writeTerminal(level, message + stringifyData(data));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export const logger = {
|
|
104
|
+
debug(message, data) {
|
|
105
|
+
log("DEBUG", message, data);
|
|
106
|
+
},
|
|
107
|
+
info(message, data) {
|
|
108
|
+
log("INFO", message, data);
|
|
109
|
+
},
|
|
110
|
+
warn(message, data) {
|
|
111
|
+
log("WARN", message, data);
|
|
112
|
+
},
|
|
113
|
+
error(message, data) {
|
|
114
|
+
log("ERROR", message, data);
|
|
115
|
+
},
|
|
116
|
+
success(message, data) {
|
|
117
|
+
const config = loadConfig();
|
|
118
|
+
const completeMessage = message + stringifyData(data);
|
|
119
|
+
if (shouldLog("INFO", config.level)) {
|
|
120
|
+
process.stderr.write(`${chalk.green.bold("SUCCESS")}: ${completeMessage}\n`);
|
|
121
|
+
}
|
|
122
|
+
if (config.fileEnabled && shouldLog("INFO", config.fileLevel)) {
|
|
123
|
+
writeFile("INFO", `[SUCCESS] ${completeMessage}`);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
export const terminalLogger = {
|
|
128
|
+
debug(message, data) {
|
|
129
|
+
terminalOnly("DEBUG", message, data);
|
|
130
|
+
},
|
|
131
|
+
info(message, data) {
|
|
132
|
+
terminalOnly("INFO", message, data);
|
|
133
|
+
},
|
|
134
|
+
warn(message, data) {
|
|
135
|
+
terminalOnly("WARN", message, data);
|
|
136
|
+
},
|
|
137
|
+
error(message, data) {
|
|
138
|
+
terminalOnly("ERROR", message, data);
|
|
139
|
+
},
|
|
140
|
+
success(message, data) {
|
|
141
|
+
const config = loadConfig();
|
|
142
|
+
if (shouldLog("INFO", config.level)) {
|
|
143
|
+
process.stderr.write(`${chalk.green.bold("SUCCESS")}: ${message + stringifyData(data)}\n`);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerService } from './container.js';
|
|
2
|
+
import { createService as factory0 } from "../adapters/pop/identity.js";
|
|
3
|
+
registerService("identity", factory0);
|
|
4
|
+
import { createService as factory1 } from "../adapters/pop/space-read.js";
|
|
5
|
+
registerService("spaceRead", factory1);
|
|
6
|
+
import { createService as factory2 } from "../adapters/pop/doc-publish.js";
|
|
7
|
+
registerService("docPublish", factory2);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const factories = new Map();
|
|
2
|
+
// Only the build-generated composition root registers concrete implementations.
|
|
3
|
+
export function registerService(key, factory) {
|
|
4
|
+
if (factories.has(key))
|
|
5
|
+
throw new Error(`Duplicate service registration: ${key}`);
|
|
6
|
+
factories.set(key, factory);
|
|
7
|
+
}
|
|
8
|
+
export function getService(key) {
|
|
9
|
+
const factory = factories.get(key);
|
|
10
|
+
if (!factory)
|
|
11
|
+
throw new Error(`Capability is unavailable in this edition: ${key}`);
|
|
12
|
+
return factory();
|
|
13
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const runtimeProfile = {
|
|
2
|
+
"edition": "external",
|
|
3
|
+
"bin": "rkb",
|
|
4
|
+
"configDirName": ".rkb-external",
|
|
5
|
+
"configDirEnv": "RKB_EXTERNAL_CONFIG_DIR",
|
|
6
|
+
"envPrefix": "RKB_EXTERNAL_ENV_",
|
|
7
|
+
"spaceKey": "context.spaceCode",
|
|
8
|
+
"tenantKey": "context.tenantCode",
|
|
9
|
+
"schema": [
|
|
10
|
+
{
|
|
11
|
+
"key": "log.level",
|
|
12
|
+
"category": "log",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"default": "INFO",
|
|
15
|
+
"description": "Console log level",
|
|
16
|
+
"enum": [
|
|
17
|
+
"DEBUG",
|
|
18
|
+
"INFO",
|
|
19
|
+
"WARN",
|
|
20
|
+
"ERROR"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"key": "log.file.enabled",
|
|
25
|
+
"category": "log",
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": true,
|
|
28
|
+
"description": "Enable file logging"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"key": "log.file.path",
|
|
32
|
+
"category": "log",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"default": "~/.rkb-external/logs",
|
|
35
|
+
"description": "Log file directory"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"key": "log.file.filename",
|
|
39
|
+
"category": "log",
|
|
40
|
+
"type": "string",
|
|
41
|
+
"default": "rkb-external",
|
|
42
|
+
"description": "Log file name prefix"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"key": "log.file.level",
|
|
46
|
+
"category": "log",
|
|
47
|
+
"type": "string",
|
|
48
|
+
"default": "DEBUG",
|
|
49
|
+
"description": "File log level",
|
|
50
|
+
"enum": [
|
|
51
|
+
"DEBUG",
|
|
52
|
+
"INFO",
|
|
53
|
+
"WARN",
|
|
54
|
+
"ERROR"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"key": "request.timeout",
|
|
59
|
+
"category": "request",
|
|
60
|
+
"type": "number",
|
|
61
|
+
"default": 30000,
|
|
62
|
+
"description": "POP request timeout in milliseconds"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"key": "context.spaceCode",
|
|
66
|
+
"category": "context",
|
|
67
|
+
"type": "string",
|
|
68
|
+
"default": "",
|
|
69
|
+
"description": "Selected space code"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"key": "context.tenantCode",
|
|
73
|
+
"category": "context",
|
|
74
|
+
"type": "string",
|
|
75
|
+
"default": "",
|
|
76
|
+
"description": "Tenant code; empty uses the account tenant"
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"preview": {
|
|
80
|
+
"mode": "maas",
|
|
81
|
+
"cacheWithinConfig": true
|
|
82
|
+
},
|
|
83
|
+
"pop": {
|
|
84
|
+
"endpoint": "raasknowledgebuddy-pre.aliyuncs.com",
|
|
85
|
+
"apiVersion": "2026-09-02",
|
|
86
|
+
"requestBodyType": "formData"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
;
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rkb-cli",
|
|
3
|
+
"version": "0.3.0-beta.1",
|
|
4
|
+
"description": "RaaS Knowledge Buddy command-line interface",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"rkb": "./bin/run.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"lib",
|
|
12
|
+
"edition.json"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20.0.0"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@alicloud/openapi-client": "^0.4.15",
|
|
20
|
+
"@alicloud/tea-util": "^1.4.11",
|
|
21
|
+
"@oclif/core": "^4.3.0",
|
|
22
|
+
"chalk": "^4.1.2",
|
|
23
|
+
"open": "^11.0.0",
|
|
24
|
+
"yaml": "^2.9.0"
|
|
25
|
+
},
|
|
26
|
+
"oclif": {
|
|
27
|
+
"bin": "rkb",
|
|
28
|
+
"dirname": "rkb-external",
|
|
29
|
+
"commands": {
|
|
30
|
+
"strategy": "explicit",
|
|
31
|
+
"target": "./lib/command-registry.js"
|
|
32
|
+
},
|
|
33
|
+
"topicSeparator": " ",
|
|
34
|
+
"additionalHelpFlags": [
|
|
35
|
+
"-h"
|
|
36
|
+
],
|
|
37
|
+
"additionalVersionFlags": [
|
|
38
|
+
"-V"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"private": false
|
|
42
|
+
}
|