@cvtoolman/huawei-lts-cli 1.0.0

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # huawei-lts-cli
2
+
3
+ Command-line tool for querying [Huawei Cloud Log Tank Service (LTS)](https://www.huaweicloud.com/intl/en-us/product/lts.html) logs from the terminal.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/huawei-lts-cli.svg)](https://www.npmjs.com/package/huawei-lts-cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ ## Features
9
+
10
+ - ๐Ÿ” Query LTS logs by time range, keyword, and more
11
+ - ๐Ÿ“‹ Multiple output formats: pretty (colored), JSON, table
12
+ - ๐Ÿš€ Auto-pagination โ€” fetches all matching logs in one command
13
+ - โš™๏ธ Persistent configuration โ€” set credentials once, use forever
14
+ - ๐Ÿง™ Interactive setup wizard โ€” `lts-cli init` guides you step by step
15
+ - ๐Ÿ” Environment variable support โ€” CI/CD friendly
16
+ - ๐Ÿš Shell completion for bash, zsh, and PowerShell
17
+
18
+ ## Quick Start
19
+
20
+ ### 1. Install
21
+
22
+ ```bash
23
+ npm install -g huawei-lts-cli
24
+ ```
25
+
26
+ ### 2. Configure
27
+
28
+ ```bash
29
+ lts-cli init
30
+ ```
31
+
32
+ The wizard will ask for your AK, SK, Project ID, and Region. You can find your credentials in the Huawei Cloud console under **My Credentials > Access Keys**.
33
+
34
+ Or set manually:
35
+
36
+ ```bash
37
+ lts-cli config --set ak=YOUR_ACCESS_KEY
38
+ lts-cli config --set sk=YOUR_SECRET_KEY
39
+ lts-cli config --set projectId=YOUR_PROJECT_ID
40
+ lts-cli config --set region=cn-south-1
41
+ lts-cli config --set endpoint=https://lts.cn-south-1.myhuaweicloud.com
42
+ lts-cli config --set groupId=YOUR_LOG_GROUP_ID # optional โ€” default
43
+ lts-cli config --set streamId=YOUR_LOG_STREAM_ID # optional โ€” default
44
+ ```
45
+
46
+ ### 3. Query
47
+
48
+ ```bash
49
+ # Basic query
50
+ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
51
+
52
+ # With keyword filter
53
+ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z -k "ERROR"
54
+
55
+ # With explicit group/stream (overrides config defaults)
56
+ lts-cli query -g <group-id> -s <stream-id> --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
57
+
58
+ # JSON output (useful for piping to jq)
59
+ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z -f json
60
+
61
+ # Table output
62
+ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z -f table
63
+ ```
64
+
65
+ ## Command Reference
66
+
67
+ ### `lts-cli query` โ€” Query Logs
68
+
69
+ ```
70
+ Usage: lts-cli query [options]
71
+
72
+ Options:
73
+ -g, --group-id <groupId> Log group ID (can be set in config)
74
+ -s, --stream-id <streamId> Log stream ID (can be set in config)
75
+ --start-time, --st <time> Start time in ISO 8601 (required)
76
+ --end-time, --et <time> End time in ISO 8601 (required)
77
+ -k, --keyword <keyword> Search keyword
78
+ -l, --limit <limit> Results per page (default: 100)
79
+ -o, --offset <offset> Pagination offset (default: 0)
80
+ -r, --reverse Show newest logs first
81
+ -f, --format <format> Output format: pretty, json, table (default: pretty)
82
+ --no-paginate Disable auto-pagination (single page only)
83
+ ```
84
+
85
+ ### `lts-cli config` โ€” Manage Configuration
86
+
87
+ ```
88
+ Usage: lts-cli config [options]
89
+
90
+ Options:
91
+ --set <key=value> Set a configuration value
92
+ --get <key> Get a configuration value
93
+ --list List all configuration values
94
+ --unset <key> Remove a configuration value
95
+ ```
96
+
97
+ ### `lts-cli init` โ€” Setup Wizard
98
+
99
+ ```
100
+ Usage: lts-cli init
101
+
102
+ Interactive wizard that guides you through setting up AK, SK, Project ID,
103
+ region, endpoint, and optional default log group/stream.
104
+ ```
105
+
106
+ ### `lts-cli completion` โ€” Shell Completion
107
+
108
+ ```
109
+ Usage: lts-cli completion <shell>
110
+
111
+ Generate completion script for bash, zsh, or powershell.
112
+
113
+ Examples:
114
+ lts-cli completion bash >> ~/.bashrc
115
+ lts-cli completion zsh >> ~/.zshrc
116
+ lts-cli completion powershell >> $PROFILE
117
+ ```
118
+
119
+ ## Configuration
120
+
121
+ Configuration is stored in `~/.lts-cli/config.json` (Linux/macOS) or `%USERPROFILE%\.lts-cli\config.json` (Windows).
122
+
123
+ ### Available Keys
124
+
125
+ | Key | Required | Description |
126
+ |---|---|---|
127
+ | `ak` | Yes | Huawei Cloud Access Key |
128
+ | `sk` | Yes | Huawei Cloud Secret Key |
129
+ | `projectId` | Yes | Huawei Cloud Project ID |
130
+ | `region` | No | Region (e.g. `cn-south-1`) |
131
+ | `endpoint` | No | LTS service endpoint. Must include `https://` |
132
+ | `groupId` | No | Default log group ID |
133
+ | `streamId` | No | Default log stream ID |
134
+
135
+ ### Environment Variables
136
+
137
+ All config keys can also be set via environment variables (useful for CI/CD):
138
+
139
+ | Config Key | Environment Variable |
140
+ |---|---|
141
+ | `ak` | `LTS_AK` |
142
+ | `sk` | `LTS_SK` |
143
+ | `projectId` | `LTS_PROJECT_ID` |
144
+ | `region` | `LTS_REGION` |
145
+ | `endpoint` | `LTS_ENDPOINT` |
146
+ | `groupId` | `LTS_GROUP_ID` |
147
+ | `streamId` | `LTS_STREAM_ID` |
148
+
149
+ Environment variables take precedence over config file values.
150
+
151
+ ## Supported Regions
152
+
153
+ | Region ID | Region Name | Endpoint |
154
+ |---|---|---|
155
+ | `cn-north-1` | CN North-Beijing1 | `lts.cn-north-1.myhuaweicloud.com` |
156
+ | `cn-north-4` | CN North-Beijing4 | `lts.cn-north-4.myhuaweicloud.com` |
157
+ | `cn-east-2` | CN East-Shanghai2 | `lts.cn-east-2.myhuaweicloud.com` |
158
+ | `cn-east-3` | CN East-Shanghai3 | `lts.cn-east-3.myhuaweicloud.com` |
159
+ | `cn-south-1` | CN South-Guangzhou | `lts.cn-south-1.myhuaweicloud.com` |
160
+ | `cn-south-4` | CN South-Shenzhen | `lts.cn-south-4.myhuaweicloud.com` |
161
+ | `cn-southwest-2` | CN Southwest-Guiyang | `lts.cn-southwest-2.myhuaweicloud.com` |
162
+ | `ap-southeast-1` | AP-Singapore | `lts.ap-southeast-1.myhuaweicloud.com` |
163
+ | `ap-southeast-2` | AP-Bangkok | `lts.ap-southeast-2.myhuaweicloud.com` |
164
+ | `ap-southeast-3` | AP-Jakarta | `lts.ap-southeast-3.myhuaweicloud.com` |
165
+ | `af-south-1` | AF-Johannesburg | `lts.af-south-1.myhuaweicloud.com` |
166
+
167
+ > For a complete list, see [Huawei Cloud LTS Endpoints](https://support.huaweicloud.com/intl/en-us/api-lts/lts_api_0011.html).
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ # Clone and install
173
+ git clone <repo-url>
174
+ cd huawei-lts-cli
175
+ npm install
176
+
177
+ # Build
178
+ npm run build
179
+
180
+ # Run during development (no build step needed)
181
+ npm run dev -- query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
182
+
183
+ # Run compiled version
184
+ npm start -- query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
185
+
186
+ # Link for local testing
187
+ npm link
188
+ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
189
+ ```
190
+
191
+ ## License
192
+
193
+ [MIT](LICENSE)
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createConfigCommand = createConfigCommand;
4
+ const commander_1 = require("commander");
5
+ const config_1 = require("../../config");
6
+ function createConfigCommand() {
7
+ const cmd = new commander_1.Command('config');
8
+ cmd.description('Manage LTS CLI configuration')
9
+ .option('--set <key=value>', 'Set a configuration value')
10
+ .option('--get <key>', 'Get a configuration value')
11
+ .option('--list', 'List all configuration values')
12
+ .option('--unset <key>', 'Remove a configuration value')
13
+ .action((options) => {
14
+ if (options.set) {
15
+ const parts = options.set.split('=');
16
+ if (parts.length !== 2) {
17
+ console.error('Usage: config --set key=value');
18
+ process.exit(1);
19
+ }
20
+ const [key, value] = parts;
21
+ (0, config_1.setConfig)(key, value);
22
+ console.log(`Set ${key}=${value}`);
23
+ }
24
+ else if (options.get) {
25
+ const value = (0, config_1.getConfig)(options.get);
26
+ if (value !== undefined) {
27
+ console.log(value);
28
+ }
29
+ else {
30
+ console.error(`Config key '${options.get}' not found`);
31
+ process.exit(1);
32
+ }
33
+ }
34
+ else if (options.list) {
35
+ const config = (0, config_1.listConfig)();
36
+ const entries = Object.entries(config);
37
+ if (entries.length === 0) {
38
+ console.log('No configuration values set');
39
+ }
40
+ else {
41
+ for (const [key, value] of entries) {
42
+ console.log(`${key}=${value}`);
43
+ }
44
+ }
45
+ }
46
+ else if (options.unset) {
47
+ (0, config_1.unsetConfig)(options.unset);
48
+ console.log(`Removed ${options.unset}`);
49
+ }
50
+ else {
51
+ console.error('Usage: lts-cli config [--set key=value | --get key | --list | --unset key]');
52
+ process.exit(1);
53
+ }
54
+ });
55
+ return cmd;
56
+ }
@@ -0,0 +1,156 @@
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.createInitCommand = createInitCommand;
37
+ const commander_1 = require("commander");
38
+ const readline = __importStar(require("readline"));
39
+ const config_1 = require("../../config");
40
+ function ask(rl, question) {
41
+ return new Promise((resolve) => {
42
+ rl.question(question, (answer) => resolve(answer.trim()));
43
+ });
44
+ }
45
+ const ENDPOINT_MAP = {
46
+ 'cn-north-1': 'lts.cn-north-1.myhuaweicloud.com',
47
+ 'cn-north-2': 'lts.cn-north-2.myhuaweicloud.com',
48
+ 'cn-north-4': 'lts.cn-north-4.myhuaweicloud.com',
49
+ 'cn-north-5': 'lts.cn-north-5.myhuaweicloud.com',
50
+ 'cn-north-9': 'lts.cn-north-9.myhuaweicloud.com',
51
+ 'cn-east-2': 'lts.cn-east-2.myhuaweicloud.com',
52
+ 'cn-east-3': 'lts.cn-east-3.myhuaweicloud.com',
53
+ 'cn-east-4': 'lts.cn-east-4.myhuaweicloud.com',
54
+ 'cn-south-1': 'lts.cn-south-1.myhuaweicloud.com',
55
+ 'cn-south-2': 'lts.cn-south-2.myhuaweicloud.com',
56
+ 'cn-south-4': 'lts.cn-south-4.myhuaweicloud.com',
57
+ 'cn-southwest-2': 'lts.cn-southwest-2.myhuaweicloud.com',
58
+ 'ap-southeast-1': 'lts.ap-southeast-1.myhuaweicloud.com',
59
+ 'ap-southeast-2': 'lts.ap-southeast-2.myhuaweicloud.com',
60
+ 'ap-southeast-3': 'lts.ap-southeast-3.myhuaweicloud.com',
61
+ 'af-south-1': 'lts.af-south-1.myhuaweicloud.com',
62
+ 'la-south-2': 'lts.la-south-2.myhuaweicloud.com',
63
+ 'sa-brazil-1': 'lts.sa-brazil-1.myhuaweicloud.com',
64
+ 'na-mexico-1': 'lts.na-mexico-1.myhuaweicloud.com',
65
+ 'la-north-2': 'lts.la-north-2.myhuaweicloud.com',
66
+ };
67
+ function createInitCommand() {
68
+ const cmd = new commander_1.Command('init');
69
+ cmd.description('Interactive setup wizard โ€” configure credentials step by step')
70
+ .action(async () => {
71
+ const rl = readline.createInterface({
72
+ input: process.stdin,
73
+ output: process.stdout,
74
+ });
75
+ console.log('');
76
+ console.log('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—');
77
+ console.log('โ•‘ Huawei Cloud LTS CLI โ€” Setup Wizard โ•‘');
78
+ console.log('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•');
79
+ console.log('');
80
+ console.log('This wizard will guide you through setting up your credentials.');
81
+ console.log('You can find AK/SK in the Huawei Cloud console under:');
82
+ console.log(' My Credentials > Access Keys');
83
+ console.log('');
84
+ console.log('Press Enter to skip any optional field.');
85
+ console.log('');
86
+ try {
87
+ // Required: AK
88
+ const ak = await ask(rl, 'Access Key (AK): ');
89
+ if (ak) {
90
+ (0, config_1.setConfig)('ak', ak);
91
+ }
92
+ // Required: SK
93
+ const sk = await ask(rl, 'Secret Key (SK): ');
94
+ if (sk) {
95
+ (0, config_1.setConfig)('sk', sk);
96
+ }
97
+ // Required: Project ID
98
+ const projectId = await ask(rl, 'Project ID: ');
99
+ if (projectId) {
100
+ (0, config_1.setConfig)('projectId', projectId);
101
+ }
102
+ // Required: Region
103
+ console.log('');
104
+ console.log('Common regions: cn-north-1, cn-north-4, cn-east-2, cn-east-3, cn-south-1');
105
+ const region = await ask(rl, 'Region (e.g. cn-south-1): ');
106
+ if (region) {
107
+ (0, config_1.setConfig)('region', region);
108
+ // Auto-suggest endpoint based on region
109
+ const autoEndpoint = ENDPOINT_MAP[region];
110
+ if (autoEndpoint) {
111
+ const useDefault = await ask(rl, `Endpoint [https://${autoEndpoint}]: `);
112
+ if (!useDefault) {
113
+ (0, config_1.setConfig)('endpoint', `https://${autoEndpoint}`);
114
+ }
115
+ else {
116
+ const customEndpoint = useDefault.startsWith('http') ? useDefault : `https://${useDefault}`;
117
+ (0, config_1.setConfig)('endpoint', customEndpoint);
118
+ }
119
+ }
120
+ else {
121
+ const endpoint = await ask(rl, 'Endpoint (e.g. https://lts.cn-south-1.myhuaweicloud.com): ');
122
+ if (endpoint) {
123
+ const normalized = endpoint.startsWith('http') ? endpoint : `https://${endpoint}`;
124
+ (0, config_1.setConfig)('endpoint', normalized);
125
+ }
126
+ }
127
+ }
128
+ // Optional: default groupId & streamId
129
+ console.log('');
130
+ console.log('Optional โ€” set default log group & stream so you can query without -g / -s:');
131
+ const groupId = await ask(rl, 'Default Log Group ID (optional): ');
132
+ if (groupId) {
133
+ (0, config_1.setConfig)('groupId', groupId);
134
+ }
135
+ const streamId = await ask(rl, 'Default Log Stream ID (optional): ');
136
+ if (streamId) {
137
+ (0, config_1.setConfig)('streamId', streamId);
138
+ }
139
+ console.log('');
140
+ console.log('โœ… Configuration saved!');
141
+ console.log('');
142
+ console.log('Try it out:');
143
+ if (groupId && streamId) {
144
+ console.log(' lts-cli query --start-time 2024-01-01T00:00:00Z --end-time 2024-01-02T00:00:00Z');
145
+ }
146
+ else {
147
+ console.log(' lts-cli query -g <group-id> -s <stream-id> --start-time 2024-01-01T00:00:00Z --end-time 2024-01-02T00:00:00Z');
148
+ }
149
+ console.log('');
150
+ }
151
+ finally {
152
+ rl.close();
153
+ }
154
+ });
155
+ return cmd;
156
+ }
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createQueryCommand = createQueryCommand;
4
+ const commander_1 = require("commander");
5
+ const client_1 = require("../../lts/client");
6
+ const config_1 = require("../../config");
7
+ const output_1 = require("../../output");
8
+ function createQueryCommand() {
9
+ const cmd = new commander_1.Command('query');
10
+ cmd.description('Query LTS logs')
11
+ .option('-g, --group-id <groupId>', 'Log group ID (can also be set via config)')
12
+ .option('-s, --stream-id <streamId>', 'Log stream ID (can also be set via config)')
13
+ .requiredOption('--start-time <startTime>', 'Start time (ISO 8601, e.g. 2024-01-01T00:00:00Z)')
14
+ .requiredOption('--end-time <endTime>', 'End time (ISO 8601, e.g. 2024-01-02T00:00:00Z)')
15
+ .option('--st <startTime>', 'Alias for --start-time')
16
+ .option('--et <endTime>', 'Alias for --end-time')
17
+ .option('-k, --keyword <keyword>', 'Search keyword')
18
+ .option('-l, --limit <limit>', 'Limit number of results', parseInt, 100)
19
+ .option('-o, --offset <offset>', 'Offset for pagination', parseInt, 0)
20
+ .option('-r, --reverse', 'Reverse order (newest first)')
21
+ .option('-f, --format <format>', 'Output format: json, table, pretty', 'pretty')
22
+ .option('--no-paginate', 'Disable auto-pagination (single page only)')
23
+ .action(async (options) => {
24
+ const config = (0, config_1.loadConfig)();
25
+ // Validate required credentials
26
+ if (!config.ak || !config.sk || !config.projectId) {
27
+ console.error('Error: Missing required credentials. Please configure them first:');
28
+ console.error('');
29
+ console.error(' Quick setup (recommended):');
30
+ console.error(' lts-cli init');
31
+ console.error('');
32
+ console.error(' Or set individually:');
33
+ console.error(' lts-cli config --set ak=<your-access-key>');
34
+ console.error(' lts-cli config --set sk=<your-secret-key>');
35
+ console.error(' lts-cli config --set projectId=<your-project-id>');
36
+ process.exit(1);
37
+ }
38
+ // groupId & streamId: CLI args take priority over config
39
+ const groupId = options.groupId || config.groupId;
40
+ const streamId = options.streamId || config.streamId;
41
+ if (!groupId || !streamId) {
42
+ console.error('Error: groupId and streamId are required. Provide them via:');
43
+ console.error(' lts-cli config --set groupId=<your-group-id>');
44
+ console.error(' lts-cli config --set streamId=<your-stream-id>');
45
+ console.error(' or use -g <groupId> -s <streamId> flags');
46
+ process.exit(1);
47
+ }
48
+ // --st / --et are aliases for --start-time / --end-time
49
+ const startTime = options.startTime || options.st;
50
+ const endTime = options.endTime || options.et;
51
+ if (!startTime || !endTime) {
52
+ console.error('Error: --start-time and --end-time are required.');
53
+ process.exit(1);
54
+ }
55
+ const format = ['json', 'table', 'pretty'].includes(options.format)
56
+ ? options.format
57
+ : 'pretty';
58
+ const client = new client_1.LTSClient(config);
59
+ const params = {
60
+ groupId,
61
+ streamId,
62
+ startTime,
63
+ endTime,
64
+ keyword: options.keyword,
65
+ limit: options.limit,
66
+ offset: options.offset,
67
+ reverse: options.reverse,
68
+ };
69
+ try {
70
+ if (options.paginate) {
71
+ const result = await client.queryLogs(params);
72
+ console.log((0, output_1.formatOutput)(result, format));
73
+ }
74
+ else {
75
+ // Auto-pagination: fetch all logs
76
+ const allLogs = [];
77
+ let offset = options.offset || 0;
78
+ const limit = options.limit || 100;
79
+ let hasMore = true;
80
+ while (hasMore) {
81
+ const pageParams = {
82
+ ...params,
83
+ offset,
84
+ limit,
85
+ };
86
+ const result = await client.queryLogs(pageParams);
87
+ allLogs.push(...result.logs);
88
+ if (result.logs.length < limit) {
89
+ hasMore = false;
90
+ }
91
+ else {
92
+ offset += limit;
93
+ }
94
+ }
95
+ const result = {
96
+ logs: allLogs,
97
+ total: allLogs.length,
98
+ };
99
+ console.log((0, output_1.formatOutput)(result, format));
100
+ }
101
+ }
102
+ catch (error) {
103
+ const msg = error.message || String(error);
104
+ // Friendlier error messages for common issues
105
+ if (msg.includes('Invalid URL')) {
106
+ console.error('Error: Invalid endpoint URL. Make sure it starts with https://');
107
+ console.error(' Example: https://lts.cn-south-1.myhuaweicloud.com');
108
+ }
109
+ else if (msg.includes('Authentication failed') || msg.includes('401') || msg.includes('403')) {
110
+ console.error('Error: Authentication failed. Please check your AK/SK credentials:');
111
+ console.error(' lts-cli config --list');
112
+ }
113
+ else if (msg.includes('ENOTFOUND') || msg.includes('ECONNREFUSED')) {
114
+ console.error('Error: Cannot reach the LTS service. Please check your endpoint and network connection.');
115
+ }
116
+ else if (msg.includes('Request failed after retries')) {
117
+ console.error('Error: The service is temporarily unavailable. Please try again later.');
118
+ }
119
+ else {
120
+ console.error('Error querying logs:', msg);
121
+ }
122
+ process.exit(1);
123
+ }
124
+ });
125
+ return cmd;
126
+ }
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const query_1 = require("./commands/query");
6
+ const config_1 = require("./commands/config");
7
+ const init_1 = require("./commands/init");
8
+ const program = new commander_1.Command();
9
+ program
10
+ .name('lts-cli')
11
+ .description('Huawei Cloud LTS (Log Tank Service) CLI โ€” query logs from the terminal')
12
+ .version('1.0.0')
13
+ .addHelpText('after', `
14
+ Examples:
15
+ $ lts-cli init Setup credentials interactively
16
+ $ lts-cli config --list Show current configuration
17
+ $ lts-cli query --st 2024-01-01T00:00:00Z --et 2024-01-02T00:00:00Z
18
+
19
+ Environment variables:
20
+ LTS_AK Access Key
21
+ LTS_SK Secret Key
22
+ LTS_PROJECT_ID Project ID
23
+ LTS_REGION Region
24
+ LTS_ENDPOINT Service endpoint
25
+ LTS_GROUP_ID Default log group ID
26
+ LTS_STREAM_ID Default log stream ID
27
+ `);
28
+ program.addCommand((0, init_1.createInitCommand)());
29
+ program.addCommand((0, query_1.createQueryCommand)());
30
+ program.addCommand((0, config_1.createConfigCommand)());
31
+ // Shell completion support
32
+ const completionCmd = new commander_1.Command('completion')
33
+ .description('Generate shell completion script')
34
+ .argument('<shell>', 'Shell type: bash, zsh, or powershell')
35
+ .action((shell) => {
36
+ switch (shell) {
37
+ case 'bash':
38
+ console.log(`# lts-cli bash completion โ€” add to ~/.bashrc or ~/.bash_profile
39
+ _lts_cli_completion() {
40
+ local words cword
41
+ _get_comp_words_by_ref -n : words cword
42
+ local cur="\${words[cword]}"
43
+
44
+ if (( cword == 1 )); then
45
+ COMPREPLY=( $(compgen -W "query config init completion" -- "\$cur") )
46
+ return
47
+ fi
48
+
49
+ local cmd="\${words[1]}"
50
+ case "\$cmd" in
51
+ query)
52
+ case "\$prev" in
53
+ -g|--group-id|-s|--stream-id|-k|--keyword|-l|--limit|-o|--offset|-f|--format)
54
+ COMPREPLY=()
55
+ return
56
+ ;;
57
+ *)
58
+ COMPREPLY=( $(compgen -W "-g --group-id -s --stream-id --start-time --end-time --st --et -k --keyword -l --limit -o --offset -r --reverse -f --format --no-paginate" -- "\$cur") )
59
+ return
60
+ ;;
61
+ esac
62
+ ;;
63
+ config)
64
+ COMPREPLY=( $(compgen -W "--set --get --list --unset" -- "\$cur") )
65
+ return
66
+ ;;
67
+ completion)
68
+ COMPREPLY=( $(compgen -W "bash zsh powershell" -- "\$cur") )
69
+ return
70
+ ;;
71
+ *)
72
+ COMPREPLY=()
73
+ return
74
+ ;;
75
+ esac
76
+ }
77
+ complete -F _lts_cli_completion lts-cli`);
78
+ break;
79
+ case 'zsh':
80
+ console.log(`# lts-cli zsh completion โ€” add to ~/.zshrc
81
+ #compdef lts-cli
82
+ _lts_cli() {
83
+ local -a commands
84
+ commands=(
85
+ 'query:Query LTS logs'
86
+ 'config:Manage configuration'
87
+ 'init:Interactive setup wizard'
88
+ 'completion:Generate shell completion script'
89
+ )
90
+
91
+ local context state state_descr line
92
+ typeset -A opt_args
93
+
94
+ _arguments -C \\
95
+ '1: :->command' \\
96
+ '*:: :->args'
97
+
98
+ case "\$state" in
99
+ command)
100
+ _describe 'command' commands
101
+ ;;
102
+ args)
103
+ case "\$line[1]" in
104
+ query)
105
+ _arguments \\
106
+ '-g[Log group ID]:group ID:' \\
107
+ '-s[Log stream ID]:stream ID:' \\
108
+ '--start-time[Start time (ISO 8601)]:time:' \\
109
+ '--end-time[End time (ISO 8601)]:time:' \\
110
+ '--st[Alias for --start-time]:time:' \\
111
+ '--et[Alias for --end-time]:time:' \\
112
+ '-k[Search keyword]:keyword:' \\
113
+ '-l[Limit]:number:' \\
114
+ '-o[Offset]:number:' \\
115
+ '-r[Reverse order]' \\
116
+ '-f[Output format]:format:(json table pretty)' \\
117
+ '--no-paginate[Disable pagination]'
118
+ ;;
119
+ config)
120
+ _arguments \\
121
+ '--set[Set config value]:key=value:' \\
122
+ '--get[Get config value]:key:' \\
123
+ '--list[List all config]' \\
124
+ '--unset[Remove config value]:key:'
125
+ ;;
126
+ completion)
127
+ _values 'shell' bash zsh powershell
128
+ ;;
129
+ esac
130
+ ;;
131
+ esac
132
+ }
133
+ compdef _lts_cli lts-cli`);
134
+ break;
135
+ case 'powershell':
136
+ console.log(`# lts-cli PowerShell completion โ€” add to $PROFILE
137
+ Register-ArgumentCompleter -CommandName lts-cli -ScriptBlock {
138
+ param(\$wordToComplete, \$commandAst, \$cursorPosition)
139
+
140
+ \$commands = @('query', 'config', 'init', 'completion')
141
+
142
+ \$args = \$commandAst.ToString() -split '\\s+'
143
+ if (\$args.Count -le 1) {
144
+ return \$commands | Where-Object { \$_ -like "\$wordToComplete*" }
145
+ }
146
+
147
+ switch (\$args[1]) {
148
+ 'query' {
149
+ \$opts = @('-g', '-s', '--start-time', '--end-time', '--st', '--et', '-k', '-l', '-o', '-r', '-f', '--no-paginate')
150
+ return \$opts | Where-Object { \$_ -like "\$wordToComplete*" }
151
+ }
152
+ 'config' {
153
+ \$opts = @('--set', '--get', '--list', '--unset')
154
+ return \$opts | Where-Object { \$_ -like "\$wordToComplete*" }
155
+ }
156
+ 'completion' {
157
+ return @('bash', 'zsh', 'powershell') | Where-Object { \$_ -like "\$wordToComplete*" }
158
+ }
159
+ }
160
+ }`);
161
+ break;
162
+ default:
163
+ console.error(`Unknown shell: ${shell}. Supported: bash, zsh, powershell`);
164
+ process.exit(1);
165
+ }
166
+ });
167
+ program.addCommand(completionCmd);
168
+ program.parse();
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.queryOptions = void 0;
4
+ exports.queryOptions = {
5
+ groupId: { short: '-g', long: '--group-id <groupId>', description: 'Log group ID', required: true },
6
+ streamId: { short: '-s', long: '--stream-id <streamId>', description: 'Log stream ID', required: true },
7
+ startTime: { short: '--start-time <startTime>', long: '--start-time <startTime>', description: 'Start time (ISO 8601)', required: true },
8
+ endTime: { short: '--end-time <endTime>', long: '--end-time <endTime>', description: 'End time (ISO 8601)', required: true },
9
+ keyword: { short: '-k', long: '--keyword <keyword>', description: 'Search keyword', required: false },
10
+ limit: { short: '-l', long: '--limit <limit>', description: 'Limit number of results', required: false },
11
+ offset: { short: '-o', long: '--offset <offset>', description: 'Offset for pagination', required: false },
12
+ reverse: { short: '-r', long: '--reverse', description: 'Reverse order', required: false },
13
+ format: { short: '-f', long: '--format <format>', description: 'Output format: json, table, pretty', required: false },
14
+ noPaginate: { short: '', long: '--no-paginate', description: 'Disable pagination', required: false },
15
+ };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadConfig = loadConfig;
4
+ exports.getConfig = getConfig;
5
+ exports.setConfig = setConfig;
6
+ exports.listConfig = listConfig;
7
+ exports.unsetConfig = unsetConfig;
8
+ const store_1 = require("./store");
9
+ const ENV_MAP = {
10
+ ak: 'LTS_AK',
11
+ sk: 'LTS_SK',
12
+ projectId: 'LTS_PROJECT_ID',
13
+ region: 'LTS_REGION',
14
+ endpoint: 'LTS_ENDPOINT',
15
+ groupId: 'LTS_GROUP_ID',
16
+ streamId: 'LTS_STREAM_ID',
17
+ };
18
+ function getEnvValue(key) {
19
+ const envKey = ENV_MAP[key];
20
+ if (envKey) {
21
+ return process.env[envKey];
22
+ }
23
+ return undefined;
24
+ }
25
+ function loadConfig() {
26
+ const config = (0, store_1.readConfigFile)();
27
+ return {
28
+ ak: getEnvValue('ak') ?? config.ak ?? '',
29
+ sk: getEnvValue('sk') ?? config.sk ?? '',
30
+ projectId: getEnvValue('projectId') ?? config.projectId ?? '',
31
+ region: getEnvValue('region') ?? config.region ?? '',
32
+ endpoint: getEnvValue('endpoint') ?? config.endpoint ?? '',
33
+ groupId: getEnvValue('groupId') ?? config.groupId,
34
+ streamId: getEnvValue('streamId') ?? config.streamId,
35
+ };
36
+ }
37
+ function getConfig(key) {
38
+ const envValue = getEnvValue(key);
39
+ if (envValue !== undefined) {
40
+ return envValue;
41
+ }
42
+ const config = (0, store_1.readConfigFile)();
43
+ return config[key];
44
+ }
45
+ function setConfig(key, value) {
46
+ const config = (0, store_1.readConfigFile)();
47
+ config[key] = value;
48
+ (0, store_1.writeConfigFile)(config);
49
+ }
50
+ function listConfig() {
51
+ return (0, store_1.readConfigFile)();
52
+ }
53
+ function unsetConfig(key) {
54
+ const config = (0, store_1.readConfigFile)();
55
+ delete config[key];
56
+ (0, store_1.writeConfigFile)(config);
57
+ }
@@ -0,0 +1,67 @@
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.readConfigFile = readConfigFile;
37
+ exports.writeConfigFile = writeConfigFile;
38
+ exports.getConfigFilePath = getConfigFilePath;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const os = __importStar(require("os"));
42
+ const CONFIG_DIR = path.join(os.homedir(), '.lts-cli');
43
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
44
+ function ensureDir(dir) {
45
+ if (!fs.existsSync(dir)) {
46
+ fs.mkdirSync(dir, { recursive: true });
47
+ }
48
+ }
49
+ function readConfigFile() {
50
+ try {
51
+ if (!fs.existsSync(CONFIG_FILE)) {
52
+ return {};
53
+ }
54
+ const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
55
+ return JSON.parse(data);
56
+ }
57
+ catch {
58
+ return {};
59
+ }
60
+ }
61
+ function writeConfigFile(config) {
62
+ ensureDir(CONFIG_DIR);
63
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
64
+ }
65
+ function getConfigFilePath() {
66
+ return CONFIG_FILE;
67
+ }
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LTSClient = void 0;
4
+ const LtsClient_1 = require("@huaweicloud/huaweicloud-sdk-lts/v2/LtsClient");
5
+ const ClientBuilder_1 = require("@huaweicloud/huaweicloud-sdk-core/ClientBuilder");
6
+ const BasicCredentials_1 = require("@huaweicloud/huaweicloud-sdk-core/auth/BasicCredentials");
7
+ const region_1 = require("@huaweicloud/huaweicloud-sdk-core/region/region");
8
+ const ListLogsRequest_1 = require("@huaweicloud/huaweicloud-sdk-lts/v2/model/ListLogsRequest");
9
+ const QueryLtsLogParams_1 = require("@huaweicloud/huaweicloud-sdk-lts/v2/model/QueryLtsLogParams");
10
+ function sleep(ms) {
11
+ return new Promise((resolve) => setTimeout(resolve, ms));
12
+ }
13
+ class LTSClient {
14
+ client;
15
+ config;
16
+ constructor(config) {
17
+ this.config = config;
18
+ const credentials = new BasicCredentials_1.BasicCredentials()
19
+ .withAk(config.ak)
20
+ .withSk(config.sk)
21
+ .withProjectId(config.projectId);
22
+ const builder = new ClientBuilder_1.ClientBuilder((hcClient) => new LtsClient_1.LtsClient(hcClient));
23
+ if (config.endpoint) {
24
+ builder.withEndpoint(config.endpoint);
25
+ }
26
+ if (config.region) {
27
+ builder.withRegion(new region_1.Region(config.region, config.endpoint || ''));
28
+ }
29
+ builder.withCredential(credentials);
30
+ this.client = builder.build();
31
+ }
32
+ async queryLogs(params) {
33
+ const queryParams = new QueryLtsLogParams_1.QueryLtsLogParams()
34
+ .withStartTime(new Date(params.startTime).getTime().toString())
35
+ .withEndTime(new Date(params.endTime).getTime().toString())
36
+ .withLimit(params.limit ?? 100);
37
+ if (params.keyword) {
38
+ queryParams.withKeywords(params.keyword);
39
+ }
40
+ if (params.reverse !== undefined) {
41
+ queryParams.withIsDesc(params.reverse);
42
+ }
43
+ const request = new ListLogsRequest_1.ListLogsRequest(params.groupId, params.streamId, 'application/json')
44
+ .withBody(queryParams);
45
+ const response = await this.retryRequest(() => this.client.listLogs(request));
46
+ const logs = (response.logs || []).map((log) => ({
47
+ logTime: log.lineNum ?? '',
48
+ content: log.content ?? '',
49
+ labels: log.labels ?? {},
50
+ }));
51
+ return {
52
+ logs,
53
+ total: response.count ?? logs.length,
54
+ };
55
+ }
56
+ async retryRequest(fn, maxRetries = 3) {
57
+ let lastError;
58
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
59
+ try {
60
+ return await fn();
61
+ }
62
+ catch (error) {
63
+ lastError = error;
64
+ const statusCode = error.statusCode || error.httpStatusCode || 0;
65
+ if (statusCode === 401 || statusCode === 403) {
66
+ throw new Error(`Authentication failed (HTTP ${statusCode}). Please check your AK/SK credentials.`);
67
+ }
68
+ if (statusCode === 429) {
69
+ if (attempt < maxRetries) {
70
+ const delay = Math.pow(2, attempt) * 1000;
71
+ await sleep(delay);
72
+ continue;
73
+ }
74
+ }
75
+ if (statusCode >= 500) {
76
+ if (attempt < maxRetries) {
77
+ const delay = Math.pow(2, attempt) * 1000;
78
+ await sleep(delay);
79
+ continue;
80
+ }
81
+ }
82
+ throw error;
83
+ }
84
+ }
85
+ throw lastError ?? new Error('Request failed after retries');
86
+ }
87
+ }
88
+ exports.LTSClient = LTSClient;
@@ -0,0 +1,20 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.LTSClient = void 0;
18
+ var client_1 = require("./client");
19
+ Object.defineProperty(exports, "LTSClient", { enumerable: true, get: function () { return client_1.LTSClient; } });
20
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * ๅŽไธบไบ‘LTS API ่ฏทๆฑ‚ๅ’Œๅ“ๅบ”็ฑปๅž‹ๅฎšไน‰
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,41 @@
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.formatOutput = formatOutput;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const json_1 = require("./json");
9
+ const table_1 = require("./table");
10
+ function formatOutput(data, format) {
11
+ switch (format) {
12
+ case 'json':
13
+ return (0, json_1.formatJson)(data);
14
+ case 'table':
15
+ return (0, table_1.formatTable)(data);
16
+ case 'pretty':
17
+ return formatPretty(data);
18
+ default:
19
+ return (0, json_1.formatJson)(data);
20
+ }
21
+ }
22
+ function formatPretty(data) {
23
+ if (data.logs.length === 0) {
24
+ return chalk_1.default.yellow('No logs found.');
25
+ }
26
+ const lines = [];
27
+ lines.push(chalk_1.default.bold.green(`Found ${data.total} logs:`));
28
+ lines.push('');
29
+ for (const log of data.logs) {
30
+ lines.push(chalk_1.default.cyan(`[${log.logTime}]`));
31
+ lines.push(chalk_1.default.white(log.content));
32
+ if (Object.keys(log.labels).length > 0) {
33
+ const labels = Object.entries(log.labels)
34
+ .map(([k, v]) => `${k}=${v}`)
35
+ .join(', ');
36
+ lines.push(chalk_1.default.gray(` labels: ${labels}`));
37
+ }
38
+ lines.push('');
39
+ }
40
+ return lines.join('\n');
41
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatJson = formatJson;
4
+ function formatJson(data) {
5
+ return JSON.stringify(data, null, 2);
6
+ }
@@ -0,0 +1,24 @@
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.formatTable = formatTable;
7
+ const cli_table3_1 = __importDefault(require("cli-table3"));
8
+ function formatTable(data) {
9
+ if (data.logs.length === 0) {
10
+ return 'No logs found.';
11
+ }
12
+ const table = new cli_table3_1.default({
13
+ head: ['Time', 'Content', 'Labels'],
14
+ colWidths: [25, 50, 30],
15
+ wordWrap: true,
16
+ });
17
+ for (const log of data.logs) {
18
+ const labelsStr = Object.entries(log.labels)
19
+ .map(([k, v]) => `${k}=${v}`)
20
+ .join(', ');
21
+ table.push([log.logTime, log.content, labelsStr]);
22
+ }
23
+ return table.toString();
24
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@cvtoolman/huawei-lts-cli",
3
+ "version": "1.0.0",
4
+ "description": "Command-line tool for querying Huawei Cloud Log Tank Service (LTS) logs",
5
+ "main": "dist/cli/index.js",
6
+ "bin": {
7
+ "lts-cli": "./dist/cli/index.js"
8
+ },
9
+ "files": [
10
+ "dist/"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsx src/cli/index.ts",
15
+ "start": "node dist/cli/index.js",
16
+ "clean": "node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"",
17
+ "prepublishOnly": "npm run clean && npm run build"
18
+ },
19
+ "keywords": [
20
+ "huawei-cloud",
21
+ "huawei",
22
+ "lts",
23
+ "log-tank-service",
24
+ "logs",
25
+ "cli",
26
+ "log-query",
27
+ "cloud-logging"
28
+ ],
29
+ "author": "cvtoolman",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/jcxy/huawei-lts-cli.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/jcxy/huawei-lts-cli/issues"
37
+ },
38
+ "homepage": "https://github.com/jcxy/huawei-lts-cli#readme",
39
+ "engines": {
40
+ "node": ">=16.0.0"
41
+ },
42
+ "dependencies": {
43
+ "@huaweicloud/huaweicloud-sdk-core": "latest",
44
+ "@huaweicloud/huaweicloud-sdk-lts": "latest",
45
+ "chalk": "^4.1.2",
46
+ "cli-table3": "latest",
47
+ "commander": "latest",
48
+ "uuid": "^9.0.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "latest",
52
+ "tsx": "latest",
53
+ "typescript": "latest"
54
+ }
55
+ }