kitstore-cli 1.0.0 → 1.0.2
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/default-config.json +1 -0
- package/dist/config.js +20 -4
- package/package.json +5 -1
- package/.env.test +0 -4
- package/.eslintrc.js +0 -29
- package/e2e/install.e2e.test.ts +0 -237
- package/e2e/integration.e2e.test.ts +0 -346
- package/e2e/login.e2e.test.ts +0 -188
- package/jest.config.js +0 -24
- package/openapitools.json +0 -7
- package/src/__tests__/commands/init.test.ts +0 -52
- package/src/__tests__/commands/install.test.ts +0 -449
- package/src/__tests__/commands/list.test.ts +0 -164
- package/src/__tests__/commands/login.test.ts +0 -293
- package/src/__tests__/commands/rule-check.test.ts +0 -52
- package/src/__tests__/commands/search.test.ts +0 -168
- package/src/__tests__/commands/upload.test.ts +0 -404
- package/src/__tests__/config.test.ts +0 -181
- package/src/__tests__/setup.ts +0 -11
- package/src/api/client.ts +0 -20
- package/src/api/generated/.openapi-generator/FILES +0 -17
- package/src/api/generated/.openapi-generator/VERSION +0 -1
- package/src/api/generated/.openapi-generator-ignore +0 -23
- package/src/api/generated/api.ts +0 -1171
- package/src/api/generated/base.ts +0 -62
- package/src/api/generated/common.ts +0 -113
- package/src/api/generated/configuration.ts +0 -121
- package/src/api/generated/docs/AuthApi.md +0 -158
- package/src/api/generated/docs/AuthResponseDto.md +0 -22
- package/src/api/generated/docs/AuthUserDto.md +0 -24
- package/src/api/generated/docs/HealthApi.md +0 -183
- package/src/api/generated/docs/LoginDto.md +0 -22
- package/src/api/generated/docs/RegisterDto.md +0 -24
- package/src/api/generated/docs/RuleAuthorDto.md +0 -22
- package/src/api/generated/docs/RuleResponseDto.md +0 -36
- package/src/api/generated/docs/RulesApi.md +0 -289
- package/src/api/generated/git_push.sh +0 -57
- package/src/api/generated/index.ts +0 -18
- package/src/commands/init.ts +0 -46
- package/src/commands/install.ts +0 -129
- package/src/commands/list.ts +0 -71
- package/src/commands/login.ts +0 -65
- package/src/commands/rule-check.ts +0 -49
- package/src/commands/search.ts +0 -66
- package/src/commands/upload.ts +0 -117
- package/src/config.ts +0 -66
- package/src/index.ts +0 -79
- package/test-cli-config.js +0 -118
- package/tsconfig.json +0 -24
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"server": "https://test-backend.example.com"}
|
package/dist/config.js
CHANGED
|
@@ -44,21 +44,37 @@ const path = __importStar(require("path"));
|
|
|
44
44
|
const os = __importStar(require("os"));
|
|
45
45
|
const CONFIG_DIR = process.env.KITSTORE_CONFIG_DIR || path.join(os.homedir(), '.kitstore');
|
|
46
46
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
47
|
+
async function loadBundledDefaultConfig() {
|
|
48
|
+
try {
|
|
49
|
+
// Try to load the bundled default config file
|
|
50
|
+
const defaultConfigPath = path.join(__dirname, '..', 'default-config.json');
|
|
51
|
+
if (await fs.pathExists(defaultConfigPath)) {
|
|
52
|
+
const defaultConfig = await fs.readJson(defaultConfigPath);
|
|
53
|
+
return defaultConfig;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
// Ignore errors - bundled config may not exist
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
47
61
|
async function getConfig() {
|
|
48
62
|
try {
|
|
49
63
|
await fs.ensureDir(CONFIG_DIR);
|
|
50
64
|
if (await fs.pathExists(CONFIG_FILE)) {
|
|
51
65
|
const content = await fs.readJson(CONFIG_FILE);
|
|
52
|
-
// Environment variable takes precedence over config file,
|
|
53
|
-
const
|
|
66
|
+
// Environment variable takes precedence over config file, bundled default, then localhost
|
|
67
|
+
const defaultConfig = await loadBundledDefaultConfig();
|
|
68
|
+
const server = process.env.AGENTKIT_BACKEND_URL || content.server || defaultConfig?.server || 'http://localhost:3000';
|
|
54
69
|
return { ...content, server };
|
|
55
70
|
}
|
|
56
71
|
}
|
|
57
72
|
catch (err) {
|
|
58
73
|
// Ignore errors
|
|
59
74
|
}
|
|
60
|
-
//
|
|
61
|
-
const
|
|
75
|
+
// No local config file - try bundled default config
|
|
76
|
+
const defaultConfig = await loadBundledDefaultConfig();
|
|
77
|
+
const server = process.env.AGENTKIT_BACKEND_URL || defaultConfig?.server || 'http://localhost:3000';
|
|
62
78
|
return { server };
|
|
63
79
|
}
|
|
64
80
|
async function saveConfig(config) {
|
package/package.json
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kitstore-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "CLI tool for Cursor Kit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"kitstore": "./dist/index.js"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/",
|
|
11
|
+
"default-config.json"
|
|
12
|
+
],
|
|
9
13
|
"scripts": {
|
|
10
14
|
"build": "tsc",
|
|
11
15
|
"dev": "tsx src/index.ts",
|
package/.env.test
DELETED
package/.eslintrc.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
parser: '@typescript-eslint/parser',
|
|
3
|
-
parserOptions: {
|
|
4
|
-
project: 'tsconfig.json',
|
|
5
|
-
tsconfigRootDir: __dirname,
|
|
6
|
-
sourceType: 'module',
|
|
7
|
-
},
|
|
8
|
-
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
9
|
-
extends: [
|
|
10
|
-
'eslint:recommended',
|
|
11
|
-
'@typescript-eslint/recommended',
|
|
12
|
-
],
|
|
13
|
-
root: true,
|
|
14
|
-
env: {
|
|
15
|
-
node: true,
|
|
16
|
-
jest: true,
|
|
17
|
-
},
|
|
18
|
-
ignorePatterns: ['.eslintrc.js', 'dist'],
|
|
19
|
-
rules: {
|
|
20
|
-
'@typescript-eslint/interface-name-prefix': 'off',
|
|
21
|
-
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
22
|
-
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
23
|
-
'@typescript-eslint/no-explicit-any': 'off',
|
|
24
|
-
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
|
25
|
-
},
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
package/e2e/install.e2e.test.ts
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { existsSync, unlinkSync, readFileSync, mkdirSync, rmSync } from 'fs';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
|
|
5
|
-
// TC-E2E-CLI-002: Install rule flow
|
|
6
|
-
// TC-E2E-CLI-005: List rules
|
|
7
|
-
// TC-E2E-CLI-011: Search rules
|
|
8
|
-
describe('CLI Install E2E Tests', () => {
|
|
9
|
-
const tempHome = path.join(process.cwd(), 'temp-home-install');
|
|
10
|
-
const configDir = path.join(tempHome, '.kitstore');
|
|
11
|
-
const configPath = path.join(configDir, 'config.json');
|
|
12
|
-
const installDir = path.join(tempHome, '.cursor');
|
|
13
|
-
const rulesDir = path.join(installDir, 'rules');
|
|
14
|
-
const cliPath = path.join(process.cwd(), 'dist', 'index.js');
|
|
15
|
-
|
|
16
|
-
beforeAll(() => {
|
|
17
|
-
if (!existsSync(tempHome)) {
|
|
18
|
-
mkdirSync(tempHome, { recursive: true });
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
// Setup mock config for authenticated user
|
|
24
|
-
const config = {
|
|
25
|
-
server: 'http://localhost:3000',
|
|
26
|
-
token: 'test-token',
|
|
27
|
-
user: { id: 'test-user-id', username: 'testuser' },
|
|
28
|
-
lastLogin: new Date().toISOString(),
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Ensure config directory exists
|
|
32
|
-
if (!existsSync(configDir)) {
|
|
33
|
-
mkdirSync(configDir, { recursive: true });
|
|
34
|
-
}
|
|
35
|
-
require('fs').writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
afterAll(() => {
|
|
39
|
-
// Clean up temp home
|
|
40
|
-
if (existsSync(tempHome)) {
|
|
41
|
-
rmSync(tempHome, { recursive: true, force: true });
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
afterEach(() => {
|
|
46
|
-
// Clean up config and installed rules
|
|
47
|
-
if (existsSync(configPath)) {
|
|
48
|
-
unlinkSync(configPath);
|
|
49
|
-
}
|
|
50
|
-
if (existsSync(rulesDir)) {
|
|
51
|
-
rmSync(rulesDir, { recursive: true, force: true });
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// TC-E2E-CLI-005: List rules
|
|
56
|
-
test('should list rules successfully', () => {
|
|
57
|
-
// Skip if CLI is not built
|
|
58
|
-
if (!existsSync(cliPath)) {
|
|
59
|
-
console.warn('Skipping test: CLI not built');
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
try {
|
|
64
|
-
// Run list command
|
|
65
|
-
const result = execSync(`node ${cliPath} list`, {
|
|
66
|
-
encoding: 'utf8',
|
|
67
|
-
timeout: 10000,
|
|
68
|
-
env: {
|
|
69
|
-
...process.env,
|
|
70
|
-
NODE_ENV: 'test',
|
|
71
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
72
|
-
HOME: tempHome,
|
|
73
|
-
USERPROFILE: tempHome,
|
|
74
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
75
|
-
HOMEPATH: tempHome.substring(2)
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Should show found rules or empty message
|
|
80
|
-
expect(result).toMatch(/📋 Found \d+ rules\/commands|📭 No rules or commands found/);
|
|
81
|
-
|
|
82
|
-
} catch (error: any) {
|
|
83
|
-
// If backend not running, skip test
|
|
84
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
85
|
-
if (
|
|
86
|
-
output.includes('ECONNREFUSED') ||
|
|
87
|
-
output.includes('ENOTFOUND') ||
|
|
88
|
-
output.includes('Not logged in') ||
|
|
89
|
-
output.includes('Failed to list rules') ||
|
|
90
|
-
output.includes('failed: Error')
|
|
91
|
-
) {
|
|
92
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
93
|
-
return;
|
|
94
|
-
} else {
|
|
95
|
-
throw error;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// TC-E2E-CLI-011: Search rules
|
|
101
|
-
test('should search rules successfully', () => {
|
|
102
|
-
// Skip if CLI is not built
|
|
103
|
-
if (!existsSync(cliPath)) {
|
|
104
|
-
console.warn('Skipping test: CLI not built');
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
// Run search command
|
|
110
|
-
const result = execSync(`node ${cliPath} search "test"`, {
|
|
111
|
-
encoding: 'utf8',
|
|
112
|
-
timeout: 10000,
|
|
113
|
-
env: {
|
|
114
|
-
...process.env,
|
|
115
|
-
NODE_ENV: 'test',
|
|
116
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
117
|
-
HOME: tempHome,
|
|
118
|
-
USERPROFILE: tempHome,
|
|
119
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
120
|
-
HOMEPATH: tempHome.substring(2)
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Should show search results
|
|
125
|
-
expect(result).toMatch(/🔍 Search results for "test"|🔍 No rules or commands found matching "test"/);
|
|
126
|
-
|
|
127
|
-
} catch (error: any) {
|
|
128
|
-
// If backend not running, skip test
|
|
129
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
130
|
-
if (
|
|
131
|
-
output.includes('ECONNREFUSED') ||
|
|
132
|
-
output.includes('ENOTFOUND') ||
|
|
133
|
-
output.includes('Not logged in') ||
|
|
134
|
-
output.includes('Failed to list rules') ||
|
|
135
|
-
output.includes('failed: Error')
|
|
136
|
-
) {
|
|
137
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
138
|
-
return;
|
|
139
|
-
} else {
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
// TC-E2E-CLI-012: List with filters
|
|
146
|
-
test('should list rules with tag filter', () => {
|
|
147
|
-
// Skip if CLI is not built
|
|
148
|
-
if (!existsSync(cliPath)) {
|
|
149
|
-
console.warn('Skipping test: CLI not built');
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
// Run list command with tag filter
|
|
155
|
-
const result = execSync(`node ${cliPath} list --tag test`, {
|
|
156
|
-
encoding: 'utf8',
|
|
157
|
-
timeout: 10000,
|
|
158
|
-
env: {
|
|
159
|
-
...process.env,
|
|
160
|
-
NODE_ENV: 'test',
|
|
161
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
162
|
-
HOME: tempHome,
|
|
163
|
-
USERPROFILE: tempHome,
|
|
164
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
165
|
-
HOMEPATH: tempHome.substring(2)
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Should show filtered results
|
|
170
|
-
expect(result).toMatch(/📋 Found \d+ rules\/commands|📭 No rules or commands found/);
|
|
171
|
-
|
|
172
|
-
} catch (error: any) {
|
|
173
|
-
// If backend not running, skip test
|
|
174
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
175
|
-
if (
|
|
176
|
-
output.includes('ECONNREFUSED') ||
|
|
177
|
-
output.includes('ENOTFOUND') ||
|
|
178
|
-
output.includes('Not logged in') ||
|
|
179
|
-
output.includes('Failed to list rules') ||
|
|
180
|
-
output.includes('failed: Error')
|
|
181
|
-
) {
|
|
182
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
183
|
-
return;
|
|
184
|
-
} else {
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// TC-E2E-CLI-013: List with type filter
|
|
191
|
-
test('should list rules with type filter', () => {
|
|
192
|
-
// Skip if CLI is not built
|
|
193
|
-
if (!existsSync(cliPath)) {
|
|
194
|
-
console.warn('Skipping test: CLI not built');
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
try {
|
|
199
|
-
// Run list command with type filter
|
|
200
|
-
const result = execSync(`node ${cliPath} list --type rule`, {
|
|
201
|
-
encoding: 'utf8',
|
|
202
|
-
timeout: 10000,
|
|
203
|
-
env: {
|
|
204
|
-
...process.env,
|
|
205
|
-
NODE_ENV: 'test',
|
|
206
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
207
|
-
HOME: tempHome,
|
|
208
|
-
USERPROFILE: tempHome,
|
|
209
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
210
|
-
HOMEPATH: tempHome.substring(2)
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// Should show filtered results
|
|
215
|
-
expect(result).toMatch(/📋 Found \d+ rules\/commands|📭 No rules or commands found/);
|
|
216
|
-
|
|
217
|
-
} catch (error: any) {
|
|
218
|
-
// If backend not running, skip test
|
|
219
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
220
|
-
if (
|
|
221
|
-
output.includes('ECONNREFUSED') ||
|
|
222
|
-
output.includes('ENOTFOUND') ||
|
|
223
|
-
output.includes('Not logged in') ||
|
|
224
|
-
output.includes('Failed to list rules') ||
|
|
225
|
-
output.includes('failed: Error')
|
|
226
|
-
) {
|
|
227
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
228
|
-
return;
|
|
229
|
-
} else {
|
|
230
|
-
throw error;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { existsSync, readFileSync, unlinkSync } from 'fs';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
|
|
5
|
-
// TC-E2E-CLI-026 to TC-E2E-CLI-030
|
|
6
|
-
describe('CLI Integration E2E Tests', () => {
|
|
7
|
-
const tempHome = path.join(process.cwd(), 'temp-home-integration');
|
|
8
|
-
const configDir = path.join(tempHome, '.kitstore');
|
|
9
|
-
const configPath = path.join(configDir, 'config.json');
|
|
10
|
-
const cliPath = path.join(process.cwd(), 'dist', 'index.js');
|
|
11
|
-
|
|
12
|
-
beforeAll(() => {
|
|
13
|
-
if (!existsSync(tempHome)) {
|
|
14
|
-
require('fs').mkdirSync(tempHome, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
// Setup authenticated config for integration tests
|
|
20
|
-
const config = {
|
|
21
|
-
server: 'http://localhost:3000',
|
|
22
|
-
token: 'test-token',
|
|
23
|
-
user: { id: 'test-user-id', username: 'testuser' },
|
|
24
|
-
lastLogin: new Date().toISOString(),
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// Ensure config directory exists
|
|
28
|
-
if (!existsSync(configDir)) {
|
|
29
|
-
require('fs').mkdirSync(configDir, { recursive: true });
|
|
30
|
-
}
|
|
31
|
-
require('fs').writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterAll(() => {
|
|
35
|
-
// Clean up temp home
|
|
36
|
-
if (existsSync(tempHome)) {
|
|
37
|
-
require('fs-extra').removeSync(tempHome);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
// Clean up config
|
|
43
|
-
if (existsSync(configPath)) {
|
|
44
|
-
unlinkSync(configPath);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// TC-E2E-CLI-026: CLI ↔ Backend ↔ Database integration (list command)
|
|
49
|
-
test('should integrate CLI list with backend API and database', () => {
|
|
50
|
-
if (!existsSync(cliPath)) {
|
|
51
|
-
console.warn('Skipping test: CLI not built');
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const result = execSync(`node ${cliPath} list`, {
|
|
57
|
-
encoding: 'utf8',
|
|
58
|
-
timeout: 15000,
|
|
59
|
-
env: {
|
|
60
|
-
...process.env,
|
|
61
|
-
NODE_ENV: 'test',
|
|
62
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
63
|
-
HOME: tempHome,
|
|
64
|
-
USERPROFILE: tempHome,
|
|
65
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
66
|
-
HOMEPATH: tempHome.substring(2)
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Should successfully query database through backend API
|
|
71
|
-
expect(result).toMatch(/📋 Found \d+ rules\/commands|📭 No rules or commands found/);
|
|
72
|
-
|
|
73
|
-
// Verify the command completed without errors
|
|
74
|
-
expect(result).not.toContain('❌');
|
|
75
|
-
|
|
76
|
-
} catch (error: any) {
|
|
77
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
78
|
-
if (
|
|
79
|
-
output.includes('ECONNREFUSED') ||
|
|
80
|
-
output.includes('ENOTFOUND') ||
|
|
81
|
-
output.includes('Not logged in') ||
|
|
82
|
-
output.includes('failed: Error') ||
|
|
83
|
-
output.includes('AggregateError')
|
|
84
|
-
) {
|
|
85
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
86
|
-
return;
|
|
87
|
-
} else {
|
|
88
|
-
throw error;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// TC-E2E-CLI-027: CLI ↔ Backend ↔ Database integration (search command)
|
|
94
|
-
test('should integrate CLI search with backend API and database filtering', () => {
|
|
95
|
-
if (!existsSync(cliPath)) {
|
|
96
|
-
console.warn('Skipping test: CLI not built');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const result = execSync(`node ${cliPath} search "test"`, {
|
|
102
|
-
encoding: 'utf8',
|
|
103
|
-
timeout: 15000,
|
|
104
|
-
env: {
|
|
105
|
-
...process.env,
|
|
106
|
-
NODE_ENV: 'test',
|
|
107
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
108
|
-
HOME: tempHome,
|
|
109
|
-
USERPROFILE: tempHome,
|
|
110
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
111
|
-
HOMEPATH: tempHome.substring(2)
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Should successfully query and filter database through backend API
|
|
116
|
-
expect(result).toMatch(/🔍 Search results for "test"|🔍 No rules or commands found matching "test"/);
|
|
117
|
-
|
|
118
|
-
// Verify search functionality works
|
|
119
|
-
expect(result).not.toContain('❌');
|
|
120
|
-
|
|
121
|
-
} catch (error: any) {
|
|
122
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
123
|
-
if (
|
|
124
|
-
output.includes('ECONNREFUSED') ||
|
|
125
|
-
output.includes('ENOTFOUND') ||
|
|
126
|
-
output.includes('Not logged in') ||
|
|
127
|
-
output.includes('failed: Error') ||
|
|
128
|
-
output.includes('AggregateError')
|
|
129
|
-
) {
|
|
130
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
131
|
-
return;
|
|
132
|
-
} else {
|
|
133
|
-
throw error;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// TC-E2E-CLI-028: File upload → storage → download cycle
|
|
139
|
-
test('should complete full file upload-storage-download cycle', () => {
|
|
140
|
-
if (!existsSync(cliPath)) {
|
|
141
|
-
console.warn('Skipping test: CLI not built');
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
// Create a test file to upload
|
|
147
|
-
const testFilePath = path.join(process.cwd(), 'test-upload.md');
|
|
148
|
-
const testContent = '# Test Rule for Integration\nThis is a test rule for CLI integration testing.';
|
|
149
|
-
require('fs').writeFileSync(testFilePath, testContent);
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
// Upload the file
|
|
153
|
-
const uploadResult = execSync(
|
|
154
|
-
`node ${cliPath} upload "${testFilePath}" --name "Integration Test Rule" --tag "integration" --type "rule" --description "Test rule for integration"`,
|
|
155
|
-
{
|
|
156
|
-
encoding: 'utf8',
|
|
157
|
-
timeout: 30000,
|
|
158
|
-
env: {
|
|
159
|
-
...process.env,
|
|
160
|
-
NODE_ENV: 'test',
|
|
161
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
162
|
-
HOME: tempHome,
|
|
163
|
-
USERPROFILE: tempHome,
|
|
164
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
165
|
-
HOMEPATH: tempHome.substring(2)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
// Verify upload succeeded
|
|
171
|
-
expect(uploadResult).toContain('✅ Successfully uploaded rule');
|
|
172
|
-
|
|
173
|
-
// Extract rule ID from output for download test
|
|
174
|
-
const ruleIdMatch = uploadResult.match(/📋 Rule ID: ([^\s]+)/);
|
|
175
|
-
if (ruleIdMatch) {
|
|
176
|
-
const ruleId = ruleIdMatch[1];
|
|
177
|
-
|
|
178
|
-
// Test download functionality if rule was created
|
|
179
|
-
// Note: Download would require install command and actual file storage
|
|
180
|
-
// This tests the upload portion of the cycle
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
} finally {
|
|
184
|
-
// Clean up test file
|
|
185
|
-
if (existsSync(testFilePath)) {
|
|
186
|
-
unlinkSync(testFilePath);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
} catch (error: any) {
|
|
191
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
192
|
-
if (
|
|
193
|
-
output.includes('ECONNREFUSED') ||
|
|
194
|
-
output.includes('ENOTFOUND') ||
|
|
195
|
-
output.includes('Not logged in') ||
|
|
196
|
-
output.includes('failed: Error') ||
|
|
197
|
-
output.includes('AggregateError')
|
|
198
|
-
) {
|
|
199
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
200
|
-
return;
|
|
201
|
-
} else {
|
|
202
|
-
throw error;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// TC-E2E-CLI-029: Authentication token lifecycle
|
|
208
|
-
test('should handle authentication token lifecycle correctly', () => {
|
|
209
|
-
if (!existsSync(cliPath)) {
|
|
210
|
-
console.warn('Skipping test: CLI not built');
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
// Clear existing config to test login flow
|
|
216
|
-
if (existsSync(configPath)) {
|
|
217
|
-
unlinkSync(configPath);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Attempt to run authenticated command without login
|
|
221
|
-
try {
|
|
222
|
-
execSync(`node ${cliPath} list`, {
|
|
223
|
-
encoding: 'utf8',
|
|
224
|
-
timeout: 10000,
|
|
225
|
-
env: {
|
|
226
|
-
...process.env,
|
|
227
|
-
NODE_ENV: 'test',
|
|
228
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
229
|
-
HOME: tempHome,
|
|
230
|
-
USERPROFILE: tempHome,
|
|
231
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
232
|
-
HOMEPATH: tempHome.substring(2)
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
fail('Expected command to fail without authentication');
|
|
236
|
-
} catch (error: any) {
|
|
237
|
-
expect(error.status).toBe(1);
|
|
238
|
-
expect(error.stderr || error.stdout).toContain('Not logged in');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Now test login (mock successful login)
|
|
242
|
-
// Note: Actual login requires backend, so we'll test the error handling
|
|
243
|
-
|
|
244
|
-
} catch (error: any) {
|
|
245
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
246
|
-
if (
|
|
247
|
-
output.includes('ECONNREFUSED') ||
|
|
248
|
-
output.includes('ENOTFOUND') ||
|
|
249
|
-
output.includes('Not logged in') ||
|
|
250
|
-
output.includes('failed: Error') ||
|
|
251
|
-
output.includes('AggregateError')
|
|
252
|
-
) {
|
|
253
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
254
|
-
return;
|
|
255
|
-
} else {
|
|
256
|
-
throw error;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
// TC-E2E-CLI-030: Configuration persistence across sessions
|
|
262
|
-
test('should persist configuration across multiple CLI sessions', () => {
|
|
263
|
-
if (!existsSync(cliPath)) {
|
|
264
|
-
console.warn('Skipping test: CLI not built');
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
try {
|
|
269
|
-
// First session - list command
|
|
270
|
-
const result1 = execSync(`node ${cliPath} list`, {
|
|
271
|
-
encoding: 'utf8',
|
|
272
|
-
timeout: 10000,
|
|
273
|
-
env: {
|
|
274
|
-
...process.env,
|
|
275
|
-
NODE_ENV: 'test',
|
|
276
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
277
|
-
HOME: tempHome,
|
|
278
|
-
USERPROFILE: tempHome,
|
|
279
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
280
|
-
HOMEPATH: tempHome.substring(2)
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
expect(result1).not.toContain('❌');
|
|
285
|
-
|
|
286
|
-
// Verify config still exists
|
|
287
|
-
expect(existsSync(configPath)).toBe(true);
|
|
288
|
-
|
|
289
|
-
// Second session - search command
|
|
290
|
-
const result2 = execSync(`node ${cliPath} search "test"`, {
|
|
291
|
-
encoding: 'utf8',
|
|
292
|
-
timeout: 10000,
|
|
293
|
-
env: {
|
|
294
|
-
...process.env,
|
|
295
|
-
NODE_ENV: 'test',
|
|
296
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
297
|
-
HOME: tempHome,
|
|
298
|
-
USERPROFILE: tempHome,
|
|
299
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
300
|
-
HOMEPATH: tempHome.substring(2)
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
expect(result2).not.toContain('❌');
|
|
305
|
-
|
|
306
|
-
// Verify config persists
|
|
307
|
-
expect(existsSync(configPath)).toBe(true);
|
|
308
|
-
const config = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
309
|
-
expect(config.token).toBe('test-token');
|
|
310
|
-
expect(config.user.username).toBe('testuser');
|
|
311
|
-
|
|
312
|
-
// Third session - help command
|
|
313
|
-
const result3 = execSync(`node ${cliPath} --help`, {
|
|
314
|
-
encoding: 'utf8',
|
|
315
|
-
timeout: 5000,
|
|
316
|
-
env: {
|
|
317
|
-
...process.env,
|
|
318
|
-
NODE_ENV: 'test',
|
|
319
|
-
AGENTKIT_CONFIG_DIR: configDir,
|
|
320
|
-
HOME: tempHome,
|
|
321
|
-
USERPROFILE: tempHome,
|
|
322
|
-
HOMEDRIVE: tempHome.substring(0, 2),
|
|
323
|
-
HOMEPATH: tempHome.substring(2)
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
expect(result3).toContain('kitstore');
|
|
328
|
-
expect(result3).toContain('login');
|
|
329
|
-
|
|
330
|
-
} catch (error: any) {
|
|
331
|
-
const output = (error.stdout || '') + (error.stderr || '');
|
|
332
|
-
if (
|
|
333
|
-
output.includes('ECONNREFUSED') ||
|
|
334
|
-
output.includes('ENOTFOUND') ||
|
|
335
|
-
output.includes('Not logged in') ||
|
|
336
|
-
output.includes('failed: Error') ||
|
|
337
|
-
output.includes('AggregateError')
|
|
338
|
-
) {
|
|
339
|
-
console.warn('Skipping test: Backend server not running or unauthorized');
|
|
340
|
-
return;
|
|
341
|
-
} else {
|
|
342
|
-
throw error;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
});
|