@ibm/ibmi-mcp-server 0.3.2 → 0.4.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 +36 -24
- package/dist/cli/commands/columns.d.ts +7 -0
- package/dist/cli/commands/columns.d.ts.map +1 -0
- package/dist/cli/commands/columns.js +29 -0
- package/dist/cli/commands/columns.js.map +1 -0
- package/dist/cli/commands/completion.d.ts +10 -0
- package/dist/cli/commands/completion.d.ts.map +1 -0
- package/dist/cli/commands/completion.js +225 -0
- package/dist/cli/commands/completion.js.map +1 -0
- package/dist/cli/commands/related.d.ts +7 -0
- package/dist/cli/commands/related.d.ts.map +1 -0
- package/dist/cli/commands/related.js +32 -0
- package/dist/cli/commands/related.js.map +1 -0
- package/dist/cli/commands/schemas.d.ts +7 -0
- package/dist/cli/commands/schemas.d.ts.map +1 -0
- package/dist/cli/commands/schemas.js +49 -0
- package/dist/cli/commands/schemas.js.map +1 -0
- package/dist/cli/commands/sql.d.ts +8 -0
- package/dist/cli/commands/sql.d.ts.map +1 -0
- package/dist/cli/commands/sql.js +106 -0
- package/dist/cli/commands/sql.js.map +1 -0
- package/dist/cli/commands/system.d.ts +11 -0
- package/dist/cli/commands/system.d.ts.map +1 -0
- package/dist/cli/commands/system.js +263 -0
- package/dist/cli/commands/system.js.map +1 -0
- package/dist/cli/commands/tables.d.ts +7 -0
- package/dist/cli/commands/tables.d.ts.map +1 -0
- package/dist/cli/commands/tables.js +48 -0
- package/dist/cli/commands/tables.js.map +1 -0
- package/dist/cli/commands/tool.d.ts +18 -0
- package/dist/cli/commands/tool.d.ts.map +1 -0
- package/dist/cli/commands/tool.js +194 -0
- package/dist/cli/commands/tool.js.map +1 -0
- package/dist/cli/commands/tools-list.d.ts +20 -0
- package/dist/cli/commands/tools-list.d.ts.map +1 -0
- package/dist/cli/commands/tools-list.js +209 -0
- package/dist/cli/commands/tools-list.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +7 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +77 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/config/credentials.d.ts +21 -0
- package/dist/cli/config/credentials.d.ts.map +1 -0
- package/dist/cli/config/credentials.js +96 -0
- package/dist/cli/config/credentials.js.map +1 -0
- package/dist/cli/config/index.d.ts +10 -0
- package/dist/cli/config/index.d.ts.map +1 -0
- package/dist/cli/config/index.js +9 -0
- package/dist/cli/config/index.js.map +1 -0
- package/dist/cli/config/loader.d.ts +36 -0
- package/dist/cli/config/loader.d.ts.map +1 -0
- package/dist/cli/config/loader.js +206 -0
- package/dist/cli/config/loader.js.map +1 -0
- package/dist/cli/config/resolver.d.ts +26 -0
- package/dist/cli/config/resolver.d.ts.map +1 -0
- package/dist/cli/config/resolver.js +102 -0
- package/dist/cli/config/resolver.js.map +1 -0
- package/dist/cli/config/schema.d.ts +128 -0
- package/dist/cli/config/schema.d.ts.map +1 -0
- package/dist/cli/config/schema.js +37 -0
- package/dist/cli/config/schema.js.map +1 -0
- package/dist/cli/config/types.d.ts +59 -0
- package/dist/cli/config/types.d.ts.map +1 -0
- package/dist/cli/config/types.js +6 -0
- package/dist/cli/config/types.js.map +1 -0
- package/dist/cli/formatters/output.d.ts +60 -0
- package/dist/cli/formatters/output.d.ts.map +1 -0
- package/dist/cli/formatters/output.js +190 -0
- package/dist/cli/formatters/output.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +98 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/command-helpers.d.ts +47 -0
- package/dist/cli/utils/command-helpers.d.ts.map +1 -0
- package/dist/cli/utils/command-helpers.js +211 -0
- package/dist/cli/utils/command-helpers.js.map +1 -0
- package/dist/cli/utils/connection.d.ts +20 -0
- package/dist/cli/utils/connection.d.ts.map +1 -0
- package/dist/cli/utils/connection.js +37 -0
- package/dist/cli/utils/connection.js.map +1 -0
- package/dist/cli/utils/exit-codes.d.ts +48 -0
- package/dist/cli/utils/exit-codes.d.ts.map +1 -0
- package/dist/cli/utils/exit-codes.js +111 -0
- package/dist/cli/utils/exit-codes.js.map +1 -0
- package/dist/cli/utils/yaml-loader.d.ts +69 -0
- package/dist/cli/utils/yaml-loader.d.ts.map +1 -0
- package/dist/cli/utils/yaml-loader.js +135 -0
- package/dist/cli/utils/yaml-loader.js.map +1 -0
- package/dist/cli/utils/yaml-to-commander.d.ts +26 -0
- package/dist/cli/utils/yaml-to-commander.d.ts.map +1 -0
- package/dist/cli/utils/yaml-to-commander.js +156 -0
- package/dist/cli/utils/yaml-to-commander.js.map +1 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +9 -10
- package/dist/config/index.js.map +1 -1
- package/dist/config/resolver.d.ts.map +1 -1
- package/dist/config/resolver.js +6 -0
- package/dist/config/resolver.js.map +1 -1
- package/dist/ibmi-mcp-server/tools/executeSql.tool.d.ts.map +1 -1
- package/dist/ibmi-mcp-server/tools/executeSql.tool.js +6 -2
- package/dist/ibmi-mcp-server/tools/executeSql.tool.js.map +1 -1
- package/dist/ibmi-mcp-server/tools/generateSql.tool.js +1 -1
- package/dist/ibmi-mcp-server/tools/generateSql.tool.js.map +1 -1
- package/dist/ibmi-mcp-server/tools/getRelatedObjects.tool.d.ts +93 -0
- package/dist/ibmi-mcp-server/tools/getRelatedObjects.tool.d.ts.map +1 -0
- package/dist/ibmi-mcp-server/tools/getRelatedObjects.tool.js +198 -0
- package/dist/ibmi-mcp-server/tools/getRelatedObjects.tool.js.map +1 -0
- package/dist/ibmi-mcp-server/tools/getTableColumns.tool.d.ts +87 -0
- package/dist/ibmi-mcp-server/tools/getTableColumns.tool.d.ts.map +1 -0
- package/dist/ibmi-mcp-server/tools/getTableColumns.tool.js +163 -0
- package/dist/ibmi-mcp-server/tools/getTableColumns.tool.js.map +1 -0
- package/dist/ibmi-mcp-server/tools/index.d.ts +175 -0
- package/dist/ibmi-mcp-server/tools/index.d.ts.map +1 -1
- package/dist/ibmi-mcp-server/tools/index.js +27 -1
- package/dist/ibmi-mcp-server/tools/index.js.map +1 -1
- package/dist/ibmi-mcp-server/tools/listSchemas.tool.d.ts +107 -0
- package/dist/ibmi-mcp-server/tools/listSchemas.tool.d.ts.map +1 -0
- package/dist/ibmi-mcp-server/tools/listSchemas.tool.js +195 -0
- package/dist/ibmi-mcp-server/tools/listSchemas.tool.js.map +1 -0
- package/dist/ibmi-mcp-server/tools/listTablesInSchema.tool.d.ts +107 -0
- package/dist/ibmi-mcp-server/tools/listTablesInSchema.tool.d.ts.map +1 -0
- package/dist/ibmi-mcp-server/tools/listTablesInSchema.tool.js +198 -0
- package/dist/ibmi-mcp-server/tools/listTablesInSchema.tool.js.map +1 -0
- package/dist/ibmi-mcp-server/tools/validateQuery.tool.d.ts +229 -0
- package/dist/ibmi-mcp-server/tools/validateQuery.tool.d.ts.map +1 -0
- package/dist/ibmi-mcp-server/tools/validateQuery.tool.js +401 -0
- package/dist/ibmi-mcp-server/tools/validateQuery.tool.js.map +1 -0
- package/dist/ibmi-mcp-server/utils/cli/argumentParser.d.ts +2 -0
- package/dist/ibmi-mcp-server/utils/cli/argumentParser.d.ts.map +1 -1
- package/dist/ibmi-mcp-server/utils/cli/argumentParser.js +21 -7
- package/dist/ibmi-mcp-server/utils/cli/argumentParser.js.map +1 -1
- package/dist/ibmi-mcp-server/utils/security/sqlSecurityValidator.js +1 -1
- package/dist/ibmi-mcp-server/utils/security/sqlSecurityValidator.js.map +1 -1
- package/dist/mcp-server/tools/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/index.js +5 -3
- package/dist/mcp-server/tools/index.js.map +1 -1
- package/package.json +6 -4
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Credential management for the IBM i CLI.
|
|
3
|
+
* Handles environment variable expansion in config values and interactive password prompting.
|
|
4
|
+
* @module cli/config/credentials
|
|
5
|
+
*/
|
|
6
|
+
import * as readline from "readline";
|
|
7
|
+
/**
|
|
8
|
+
* Expand ${ENV_VAR} references in a string value.
|
|
9
|
+
* Returns the original string if no env var pattern is found or the var is not set.
|
|
10
|
+
*/
|
|
11
|
+
export function expandEnvVars(value) {
|
|
12
|
+
return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
13
|
+
const envValue = process.env[varName];
|
|
14
|
+
if (envValue === undefined) {
|
|
15
|
+
return _match; // Leave unexpanded if not set
|
|
16
|
+
}
|
|
17
|
+
return envValue;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Prompt the user for a password interactively (hidden input).
|
|
22
|
+
* Returns the entered password string.
|
|
23
|
+
*/
|
|
24
|
+
export async function promptPassword(prompt) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const rl = readline.createInterface({
|
|
27
|
+
input: process.stdin,
|
|
28
|
+
output: process.stderr, // Use stderr so it doesn't interfere with piped output
|
|
29
|
+
terminal: true,
|
|
30
|
+
});
|
|
31
|
+
// Disable echoing for password entry
|
|
32
|
+
if (process.stdin.isTTY) {
|
|
33
|
+
process.stderr.write(prompt);
|
|
34
|
+
const stdin = process.stdin;
|
|
35
|
+
const wasRaw = stdin.isRaw;
|
|
36
|
+
stdin.setRawMode(true);
|
|
37
|
+
let password = "";
|
|
38
|
+
const onData = (char) => {
|
|
39
|
+
const c = char.toString("utf8");
|
|
40
|
+
if (c === "\n" || c === "\r") {
|
|
41
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
42
|
+
stdin.removeListener("data", onData);
|
|
43
|
+
process.stderr.write("\n");
|
|
44
|
+
rl.close();
|
|
45
|
+
resolve(password);
|
|
46
|
+
}
|
|
47
|
+
else if (c === "\u0003") {
|
|
48
|
+
// Ctrl+C — throw to let withConnection's finally block run cleanup
|
|
49
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
50
|
+
stdin.removeListener("data", onData);
|
|
51
|
+
process.stderr.write("\n");
|
|
52
|
+
rl.close();
|
|
53
|
+
reject(new Error("Cancelled"));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
else if (c === "\u007f" || c === "\b") {
|
|
57
|
+
// Backspace
|
|
58
|
+
if (password.length > 0) {
|
|
59
|
+
password = password.slice(0, -1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
password += c;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
stdin.on("data", onData);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Non-interactive: read a line
|
|
70
|
+
rl.question(prompt, (answer) => {
|
|
71
|
+
rl.close();
|
|
72
|
+
resolve(answer);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolve the password for a system config.
|
|
79
|
+
* Priority: config password (with env expansion) → interactive prompt.
|
|
80
|
+
*/
|
|
81
|
+
export async function resolvePassword(systemName, configPassword, user, host) {
|
|
82
|
+
if (configPassword) {
|
|
83
|
+
const expanded = expandEnvVars(configPassword);
|
|
84
|
+
// If expansion resolved to a non-empty value, use it
|
|
85
|
+
if (expanded && !expanded.includes("${")) {
|
|
86
|
+
return expanded;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Fall back to interactive prompt
|
|
90
|
+
if (!process.stdin.isTTY) {
|
|
91
|
+
throw new Error(`No password configured for system "${systemName}" and stdin is not a terminal. ` +
|
|
92
|
+
`Set the password in config or via environment variable.`);
|
|
93
|
+
}
|
|
94
|
+
return promptPassword(`Password for ${user}@${host} [${systemName}]: `);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/cli/config/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel export for CLI configuration modules.
|
|
3
|
+
* @module cli/config
|
|
4
|
+
*/
|
|
5
|
+
export { CliConfigSchema, SystemConfigSchema, validateConfig } from "./schema.js";
|
|
6
|
+
export { loadConfig, saveUserConfig, upsertSystem, removeSystem, setDefaultSystem, getProjectConfigPath, getUserConfigPath, } from "./loader.js";
|
|
7
|
+
export { resolveSystem } from "./resolver.js";
|
|
8
|
+
export { expandEnvVars, promptPassword, resolvePassword, } from "./credentials.js";
|
|
9
|
+
export type { CliConfig, SystemConfig, ResolvedSystem, OutputFormat, GlobalOptions, } from "./types.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Barrel export for CLI configuration modules.
|
|
3
|
+
* @module cli/config
|
|
4
|
+
*/
|
|
5
|
+
export { CliConfigSchema, SystemConfigSchema, validateConfig } from "./schema.js";
|
|
6
|
+
export { loadConfig, saveUserConfig, upsertSystem, removeSystem, setDefaultSystem, getProjectConfigPath, getUserConfigPath, } from "./loader.js";
|
|
7
|
+
export { resolveSystem } from "./resolver.js";
|
|
8
|
+
export { expandEnvVars, promptPassword, resolvePassword, } from "./credentials.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/config/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EACL,UAAU,EACV,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Configuration file loader for the IBM i CLI.
|
|
3
|
+
* Finds and parses .ibmi/config.yaml from project and user directories,
|
|
4
|
+
* merging them with project-level taking precedence.
|
|
5
|
+
* @module cli/config/loader
|
|
6
|
+
*/
|
|
7
|
+
import type { CliConfig, SystemConfig } from "./types.js";
|
|
8
|
+
/** Get the project-level config file path (nearest .ibmi/config.yaml walking up from cwd). */
|
|
9
|
+
export declare function getProjectConfigPath(): string;
|
|
10
|
+
/** Get the user-level config file path. */
|
|
11
|
+
export declare function getUserConfigPath(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Load the full CLI configuration by merging user-level and project-level configs.
|
|
14
|
+
* Project-level config takes precedence over user-level.
|
|
15
|
+
*
|
|
16
|
+
* @returns The merged, validated, and env-expanded configuration.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadConfig(): CliConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Save a config to the user-level config file.
|
|
21
|
+
*/
|
|
22
|
+
export declare function saveUserConfig(config: CliConfig): void;
|
|
23
|
+
/**
|
|
24
|
+
* Add or update a system in the user config.
|
|
25
|
+
*/
|
|
26
|
+
export declare function upsertSystem(name: string, system: SystemConfig): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove a system from the user config.
|
|
29
|
+
* @returns true if the system existed and was removed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function removeSystem(name: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Set the default system in the user config.
|
|
34
|
+
*/
|
|
35
|
+
export declare function setDefaultSystem(name: string): void;
|
|
36
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/cli/config/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAgC1D,8FAA8F;AAC9F,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAkED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,SAAS,CAsBtC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAatD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,GACnB,IAAI,CAgBN;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBlD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkBnD"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Configuration file loader for the IBM i CLI.
|
|
3
|
+
* Finds and parses .ibmi/config.yaml from project and user directories,
|
|
4
|
+
* merging them with project-level taking precedence.
|
|
5
|
+
* @module cli/config/loader
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import yaml from "js-yaml";
|
|
11
|
+
import { CliConfigSchema, validateConfig } from "./schema.js";
|
|
12
|
+
import { expandEnvVars } from "./credentials.js";
|
|
13
|
+
/** Default config file name. */
|
|
14
|
+
const CONFIG_FILE = "config.yaml";
|
|
15
|
+
/** Project-level config directory. */
|
|
16
|
+
const PROJECT_CONFIG_DIR = ".ibmi";
|
|
17
|
+
/** User-level config directory. */
|
|
18
|
+
const USER_CONFIG_DIR = path.join(homedir(), ".ibmi");
|
|
19
|
+
/**
|
|
20
|
+
* Walk up from cwd to find the nearest .ibmi/config.yaml.
|
|
21
|
+
* Stops at the filesystem root. Returns null if not found.
|
|
22
|
+
*/
|
|
23
|
+
function findProjectConfigPath() {
|
|
24
|
+
let dir = process.cwd();
|
|
25
|
+
const root = path.parse(dir).root;
|
|
26
|
+
while (true) {
|
|
27
|
+
const candidate = path.join(dir, PROJECT_CONFIG_DIR, CONFIG_FILE);
|
|
28
|
+
if (existsSync(candidate)) {
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
const parent = path.dirname(dir);
|
|
32
|
+
if (parent === dir || dir === root) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
dir = parent;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Get the project-level config file path (nearest .ibmi/config.yaml walking up from cwd). */
|
|
39
|
+
export function getProjectConfigPath() {
|
|
40
|
+
return findProjectConfigPath() ?? path.join(process.cwd(), PROJECT_CONFIG_DIR, CONFIG_FILE);
|
|
41
|
+
}
|
|
42
|
+
/** Get the user-level config file path. */
|
|
43
|
+
export function getUserConfigPath() {
|
|
44
|
+
return path.join(USER_CONFIG_DIR, CONFIG_FILE);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Load and parse a single YAML config file.
|
|
48
|
+
* Returns null if file doesn't exist.
|
|
49
|
+
*/
|
|
50
|
+
function loadConfigFile(filePath) {
|
|
51
|
+
if (!existsSync(filePath)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
55
|
+
const parsed = yaml.load(raw);
|
|
56
|
+
if (!parsed || typeof parsed !== "object") {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const result = CliConfigSchema.safeParse(parsed);
|
|
60
|
+
if (!result.success) {
|
|
61
|
+
const errors = result.error.issues
|
|
62
|
+
.map((i) => ` ${i.path.join(".")}: ${i.message}`)
|
|
63
|
+
.join("\n");
|
|
64
|
+
throw new Error(`Invalid config at ${filePath}:\n${errors}`);
|
|
65
|
+
}
|
|
66
|
+
return result.data;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Expand environment variables in all system configs.
|
|
70
|
+
*/
|
|
71
|
+
function expandSystemEnvVars(config) {
|
|
72
|
+
const expanded = {
|
|
73
|
+
default: config.default,
|
|
74
|
+
format: config.format,
|
|
75
|
+
systems: {},
|
|
76
|
+
};
|
|
77
|
+
for (const [name, system] of Object.entries(config.systems)) {
|
|
78
|
+
expanded.systems[name] = {
|
|
79
|
+
...system,
|
|
80
|
+
host: expandEnvVars(system.host),
|
|
81
|
+
user: expandEnvVars(system.user),
|
|
82
|
+
password: system.password ? expandEnvVars(system.password) : undefined,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return expanded;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Merge two configs. Source overrides target on a per-system basis.
|
|
89
|
+
* Systems in source completely replace same-named systems in target.
|
|
90
|
+
*/
|
|
91
|
+
function mergeConfigs(target, source) {
|
|
92
|
+
return {
|
|
93
|
+
default: source.default ?? target.default,
|
|
94
|
+
format: source.format ?? target.format,
|
|
95
|
+
systems: {
|
|
96
|
+
...target.systems,
|
|
97
|
+
...source.systems,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load the full CLI configuration by merging user-level and project-level configs.
|
|
103
|
+
* Project-level config takes precedence over user-level.
|
|
104
|
+
*
|
|
105
|
+
* @returns The merged, validated, and env-expanded configuration.
|
|
106
|
+
*/
|
|
107
|
+
export function loadConfig() {
|
|
108
|
+
const userConfig = loadConfigFile(getUserConfigPath());
|
|
109
|
+
const projectConfig = loadConfigFile(getProjectConfigPath());
|
|
110
|
+
let config;
|
|
111
|
+
if (userConfig && projectConfig) {
|
|
112
|
+
config = mergeConfigs(userConfig, projectConfig);
|
|
113
|
+
}
|
|
114
|
+
else if (projectConfig) {
|
|
115
|
+
config = projectConfig;
|
|
116
|
+
}
|
|
117
|
+
else if (userConfig) {
|
|
118
|
+
config = userConfig;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
config = { systems: {} };
|
|
122
|
+
}
|
|
123
|
+
// Validate cross-references
|
|
124
|
+
const errors = validateConfig(config);
|
|
125
|
+
if (errors.length > 0) {
|
|
126
|
+
throw new Error(`Configuration errors:\n${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
127
|
+
}
|
|
128
|
+
return expandSystemEnvVars(config);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Save a config to the user-level config file.
|
|
132
|
+
*/
|
|
133
|
+
export function saveUserConfig(config) {
|
|
134
|
+
const configDir = USER_CONFIG_DIR;
|
|
135
|
+
if (!existsSync(configDir)) {
|
|
136
|
+
mkdirSync(configDir, { recursive: true });
|
|
137
|
+
}
|
|
138
|
+
const yamlStr = yaml.dump(config, {
|
|
139
|
+
indent: 2,
|
|
140
|
+
lineWidth: 120,
|
|
141
|
+
noRefs: true,
|
|
142
|
+
});
|
|
143
|
+
writeFileSync(getUserConfigPath(), yamlStr, "utf-8");
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Add or update a system in the user config.
|
|
147
|
+
*/
|
|
148
|
+
export function upsertSystem(name, system) {
|
|
149
|
+
let config;
|
|
150
|
+
try {
|
|
151
|
+
config = loadConfigFile(getUserConfigPath()) ?? { systems: {} };
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
config = { systems: {} };
|
|
155
|
+
}
|
|
156
|
+
config.systems[name] = system;
|
|
157
|
+
// If this is the first system, make it the default
|
|
158
|
+
if (!config.default && Object.keys(config.systems).length === 1) {
|
|
159
|
+
config.default = name;
|
|
160
|
+
}
|
|
161
|
+
saveUserConfig(config);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Remove a system from the user config.
|
|
165
|
+
* @returns true if the system existed and was removed.
|
|
166
|
+
*/
|
|
167
|
+
export function removeSystem(name) {
|
|
168
|
+
let config;
|
|
169
|
+
try {
|
|
170
|
+
config = loadConfigFile(getUserConfigPath()) ?? { systems: {} };
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if (!(name in config.systems)) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
delete config.systems[name];
|
|
179
|
+
// Clear default if it pointed to the removed system
|
|
180
|
+
if (config.default === name) {
|
|
181
|
+
const remaining = Object.keys(config.systems);
|
|
182
|
+
config.default = remaining.length > 0 ? remaining[0] : undefined;
|
|
183
|
+
}
|
|
184
|
+
saveUserConfig(config);
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Set the default system in the user config.
|
|
189
|
+
*/
|
|
190
|
+
export function setDefaultSystem(name) {
|
|
191
|
+
let config;
|
|
192
|
+
try {
|
|
193
|
+
config = loadConfigFile(getUserConfigPath()) ?? { systems: {} };
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
config = { systems: {} };
|
|
197
|
+
}
|
|
198
|
+
// Load project config to check if system exists there
|
|
199
|
+
const fullConfig = loadConfig();
|
|
200
|
+
if (!(name in fullConfig.systems)) {
|
|
201
|
+
throw new Error(`System "${name}" not found. Available systems: ${Object.keys(fullConfig.systems).join(", ") || "(none)"}`);
|
|
202
|
+
}
|
|
203
|
+
config.default = name;
|
|
204
|
+
saveUserConfig(config);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/cli/config/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview System resolution for the IBM i CLI.
|
|
3
|
+
* Resolves which IBM i system to connect to based on:
|
|
4
|
+
* 1. --system flag (highest priority)
|
|
5
|
+
* 2. IBMI_SYSTEM environment variable
|
|
6
|
+
* 3. Config file default
|
|
7
|
+
* 4. DB2i_* environment variables (legacy fallback)
|
|
8
|
+
* @module cli/config/resolver
|
|
9
|
+
*/
|
|
10
|
+
import type { CliConfig, ResolvedSystem } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Resolve which system to use for a CLI command.
|
|
13
|
+
*
|
|
14
|
+
* Resolution priority:
|
|
15
|
+
* 1. --system <name> flag
|
|
16
|
+
* 2. IBMI_SYSTEM environment variable
|
|
17
|
+
* 3. Config file `default:` setting
|
|
18
|
+
* 4. DB2i_* environment variables (creates implicit "env" system)
|
|
19
|
+
*
|
|
20
|
+
* @param systemFlag - The --system flag value, if provided.
|
|
21
|
+
* @param config - Pre-loaded config (optional, will load if not provided).
|
|
22
|
+
* @returns The resolved system context.
|
|
23
|
+
* @throws If no system can be resolved.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveSystem(systemFlag?: string, config?: CliConfig): ResolvedSystem;
|
|
26
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/cli/config/resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAgB,MAAM,YAAY,CAAC;AA6B1E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,SAAS,GACjB,cAAc,CAiEhB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview System resolution for the IBM i CLI.
|
|
3
|
+
* Resolves which IBM i system to connect to based on:
|
|
4
|
+
* 1. --system flag (highest priority)
|
|
5
|
+
* 2. IBMI_SYSTEM environment variable
|
|
6
|
+
* 3. Config file default
|
|
7
|
+
* 4. DB2i_* environment variables (legacy fallback)
|
|
8
|
+
* @module cli/config/resolver
|
|
9
|
+
*/
|
|
10
|
+
import { loadConfig } from "./loader.js";
|
|
11
|
+
/**
|
|
12
|
+
* Build a SystemConfig from legacy DB2i_* environment variables.
|
|
13
|
+
* Returns null if the required env vars are not set.
|
|
14
|
+
*/
|
|
15
|
+
function buildLegacySystemConfig() {
|
|
16
|
+
const host = process.env["DB2i_HOST"];
|
|
17
|
+
const user = process.env["DB2i_USER"];
|
|
18
|
+
const password = process.env["DB2i_PASS"];
|
|
19
|
+
if (!host || !user) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
host,
|
|
24
|
+
user,
|
|
25
|
+
password,
|
|
26
|
+
port: 8076,
|
|
27
|
+
readOnly: false,
|
|
28
|
+
confirm: false,
|
|
29
|
+
timeout: 60,
|
|
30
|
+
maxRows: 5000,
|
|
31
|
+
ignoreUnauthorized: process.env["DB2i_IGNORE_UNAUTHORIZED"] !== "false",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve which system to use for a CLI command.
|
|
36
|
+
*
|
|
37
|
+
* Resolution priority:
|
|
38
|
+
* 1. --system <name> flag
|
|
39
|
+
* 2. IBMI_SYSTEM environment variable
|
|
40
|
+
* 3. Config file `default:` setting
|
|
41
|
+
* 4. DB2i_* environment variables (creates implicit "env" system)
|
|
42
|
+
*
|
|
43
|
+
* @param systemFlag - The --system flag value, if provided.
|
|
44
|
+
* @param config - Pre-loaded config (optional, will load if not provided).
|
|
45
|
+
* @returns The resolved system context.
|
|
46
|
+
* @throws If no system can be resolved.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveSystem(systemFlag, config) {
|
|
49
|
+
const cfg = config ?? loadConfig();
|
|
50
|
+
// 1. --system flag
|
|
51
|
+
if (systemFlag) {
|
|
52
|
+
const system = cfg.systems[systemFlag];
|
|
53
|
+
if (!system) {
|
|
54
|
+
const available = Object.keys(cfg.systems);
|
|
55
|
+
throw new Error(`System "${systemFlag}" not found in configuration. ` +
|
|
56
|
+
(available.length > 0
|
|
57
|
+
? `Available systems: ${available.join(", ")}`
|
|
58
|
+
: `No systems configured. Run "ibmi system add" to add one.`));
|
|
59
|
+
}
|
|
60
|
+
return { name: systemFlag, config: system, source: "flag" };
|
|
61
|
+
}
|
|
62
|
+
// 2. IBMI_SYSTEM env var
|
|
63
|
+
const envSystem = process.env["IBMI_SYSTEM"];
|
|
64
|
+
if (envSystem) {
|
|
65
|
+
const system = cfg.systems[envSystem];
|
|
66
|
+
if (!system) {
|
|
67
|
+
const available = Object.keys(cfg.systems);
|
|
68
|
+
throw new Error(`System "${envSystem}" (from IBMI_SYSTEM env var) not found. ` +
|
|
69
|
+
(available.length > 0
|
|
70
|
+
? `Available systems: ${available.join(", ")}`
|
|
71
|
+
: `No systems configured.`));
|
|
72
|
+
}
|
|
73
|
+
return { name: envSystem, config: system, source: "env" };
|
|
74
|
+
}
|
|
75
|
+
// 3. Config default
|
|
76
|
+
if (cfg.default) {
|
|
77
|
+
const system = cfg.systems[cfg.default];
|
|
78
|
+
if (system) {
|
|
79
|
+
return { name: cfg.default, config: system, source: "config-default" };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 4. If there's only one system, use it
|
|
83
|
+
const systemNames = Object.keys(cfg.systems);
|
|
84
|
+
if (systemNames.length === 1 && systemNames[0]) {
|
|
85
|
+
return {
|
|
86
|
+
name: systemNames[0],
|
|
87
|
+
config: cfg.systems[systemNames[0]],
|
|
88
|
+
source: "config-default",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// 5. Legacy DB2i_* env vars
|
|
92
|
+
const legacyConfig = buildLegacySystemConfig();
|
|
93
|
+
if (legacyConfig) {
|
|
94
|
+
return { name: "env", config: legacyConfig, source: "legacy-env" };
|
|
95
|
+
}
|
|
96
|
+
// Nothing found
|
|
97
|
+
throw new Error("No IBM i system configured. Options:\n" +
|
|
98
|
+
" 1. Run: ibmi system add <name>\n" +
|
|
99
|
+
" 2. Set IBMI_SYSTEM environment variable\n" +
|
|
100
|
+
" 3. Set DB2i_HOST, DB2i_USER, DB2i_PASS environment variables");
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/cli/config/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Zod schemas for validating CLI configuration files.
|
|
3
|
+
* @module cli/config/schema
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
/** Schema for a single system configuration entry. */
|
|
7
|
+
export declare const SystemConfigSchema: z.ZodObject<{
|
|
8
|
+
description: z.ZodOptional<z.ZodString>;
|
|
9
|
+
host: z.ZodString;
|
|
10
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
user: z.ZodString;
|
|
12
|
+
password: z.ZodOptional<z.ZodString>;
|
|
13
|
+
defaultSchema: z.ZodOptional<z.ZodString>;
|
|
14
|
+
readOnly: z.ZodDefault<z.ZodBoolean>;
|
|
15
|
+
confirm: z.ZodDefault<z.ZodBoolean>;
|
|
16
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
maxRows: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
ignoreUnauthorized: z.ZodDefault<z.ZodBoolean>;
|
|
19
|
+
tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
user: string;
|
|
22
|
+
host: string;
|
|
23
|
+
port: number;
|
|
24
|
+
readOnly: boolean;
|
|
25
|
+
ignoreUnauthorized: boolean;
|
|
26
|
+
timeout: number;
|
|
27
|
+
confirm: boolean;
|
|
28
|
+
maxRows: number;
|
|
29
|
+
password?: string | undefined;
|
|
30
|
+
description?: string | undefined;
|
|
31
|
+
tools?: string[] | undefined;
|
|
32
|
+
defaultSchema?: string | undefined;
|
|
33
|
+
}, {
|
|
34
|
+
user: string;
|
|
35
|
+
host: string;
|
|
36
|
+
password?: string | undefined;
|
|
37
|
+
description?: string | undefined;
|
|
38
|
+
port?: number | undefined;
|
|
39
|
+
readOnly?: boolean | undefined;
|
|
40
|
+
tools?: string[] | undefined;
|
|
41
|
+
ignoreUnauthorized?: boolean | undefined;
|
|
42
|
+
timeout?: number | undefined;
|
|
43
|
+
defaultSchema?: string | undefined;
|
|
44
|
+
confirm?: boolean | undefined;
|
|
45
|
+
maxRows?: number | undefined;
|
|
46
|
+
}>;
|
|
47
|
+
/** Schema for the full CLI config file. */
|
|
48
|
+
export declare const CliConfigSchema: z.ZodObject<{
|
|
49
|
+
default: z.ZodOptional<z.ZodString>;
|
|
50
|
+
format: z.ZodOptional<z.ZodEnum<["table", "json", "csv", "markdown"]>>;
|
|
51
|
+
systems: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
52
|
+
description: z.ZodOptional<z.ZodString>;
|
|
53
|
+
host: z.ZodString;
|
|
54
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
55
|
+
user: z.ZodString;
|
|
56
|
+
password: z.ZodOptional<z.ZodString>;
|
|
57
|
+
defaultSchema: z.ZodOptional<z.ZodString>;
|
|
58
|
+
readOnly: z.ZodDefault<z.ZodBoolean>;
|
|
59
|
+
confirm: z.ZodDefault<z.ZodBoolean>;
|
|
60
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
61
|
+
maxRows: z.ZodDefault<z.ZodNumber>;
|
|
62
|
+
ignoreUnauthorized: z.ZodDefault<z.ZodBoolean>;
|
|
63
|
+
tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
user: string;
|
|
66
|
+
host: string;
|
|
67
|
+
port: number;
|
|
68
|
+
readOnly: boolean;
|
|
69
|
+
ignoreUnauthorized: boolean;
|
|
70
|
+
timeout: number;
|
|
71
|
+
confirm: boolean;
|
|
72
|
+
maxRows: number;
|
|
73
|
+
password?: string | undefined;
|
|
74
|
+
description?: string | undefined;
|
|
75
|
+
tools?: string[] | undefined;
|
|
76
|
+
defaultSchema?: string | undefined;
|
|
77
|
+
}, {
|
|
78
|
+
user: string;
|
|
79
|
+
host: string;
|
|
80
|
+
password?: string | undefined;
|
|
81
|
+
description?: string | undefined;
|
|
82
|
+
port?: number | undefined;
|
|
83
|
+
readOnly?: boolean | undefined;
|
|
84
|
+
tools?: string[] | undefined;
|
|
85
|
+
ignoreUnauthorized?: boolean | undefined;
|
|
86
|
+
timeout?: number | undefined;
|
|
87
|
+
defaultSchema?: string | undefined;
|
|
88
|
+
confirm?: boolean | undefined;
|
|
89
|
+
maxRows?: number | undefined;
|
|
90
|
+
}>>>;
|
|
91
|
+
}, "strip", z.ZodTypeAny, {
|
|
92
|
+
systems: Record<string, {
|
|
93
|
+
user: string;
|
|
94
|
+
host: string;
|
|
95
|
+
port: number;
|
|
96
|
+
readOnly: boolean;
|
|
97
|
+
ignoreUnauthorized: boolean;
|
|
98
|
+
timeout: number;
|
|
99
|
+
confirm: boolean;
|
|
100
|
+
maxRows: number;
|
|
101
|
+
password?: string | undefined;
|
|
102
|
+
description?: string | undefined;
|
|
103
|
+
tools?: string[] | undefined;
|
|
104
|
+
defaultSchema?: string | undefined;
|
|
105
|
+
}>;
|
|
106
|
+
default?: string | undefined;
|
|
107
|
+
format?: "table" | "json" | "markdown" | "csv" | undefined;
|
|
108
|
+
}, {
|
|
109
|
+
default?: string | undefined;
|
|
110
|
+
format?: "table" | "json" | "markdown" | "csv" | undefined;
|
|
111
|
+
systems?: Record<string, {
|
|
112
|
+
user: string;
|
|
113
|
+
host: string;
|
|
114
|
+
password?: string | undefined;
|
|
115
|
+
description?: string | undefined;
|
|
116
|
+
port?: number | undefined;
|
|
117
|
+
readOnly?: boolean | undefined;
|
|
118
|
+
tools?: string[] | undefined;
|
|
119
|
+
ignoreUnauthorized?: boolean | undefined;
|
|
120
|
+
timeout?: number | undefined;
|
|
121
|
+
defaultSchema?: string | undefined;
|
|
122
|
+
confirm?: boolean | undefined;
|
|
123
|
+
maxRows?: number | undefined;
|
|
124
|
+
}> | undefined;
|
|
125
|
+
}>;
|
|
126
|
+
/** Validate that the default system references an existing system. */
|
|
127
|
+
export declare function validateConfig(config: z.infer<typeof CliConfigSchema>): string[];
|
|
128
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/cli/config/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sDAAsD;AACtD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa7B,CAAC;AAKH,2CAA2C;AAC3C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI1B,CAAC;AAEH,sEAAsE;AACtE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,GACtC,MAAM,EAAE,CAUV"}
|