fullcourtdefense-cli 1.3.2 → 1.3.3
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/dist/api.js +17 -1
- package/dist/commands/configure.js +51 -38
- package/dist/version.json +1 -1
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -19,7 +19,23 @@ class BotGuardApi {
|
|
|
19
19
|
},
|
|
20
20
|
body: body ? JSON.stringify(body) : undefined,
|
|
21
21
|
});
|
|
22
|
-
const
|
|
22
|
+
const contentType = resp.headers.get('content-type') || '';
|
|
23
|
+
const raw = await resp.text();
|
|
24
|
+
let data;
|
|
25
|
+
try {
|
|
26
|
+
data = raw ? JSON.parse(raw) : {};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
if (raw.trimStart().startsWith('<!DOCTYPE') || raw.trimStart().startsWith('<html')) {
|
|
30
|
+
throw new Error(`API returned HTML instead of JSON (${resp.status} ${path}). `
|
|
31
|
+
+ 'The endpoint may not be deployed yet — retry with `fullcourtdefense setup --skip-validate true` '
|
|
32
|
+
+ 'or confirm https://api.fullcourtdefense.ai is reachable.');
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Invalid API response (${resp.status} ${path}): ${raw.slice(0, 200)}`);
|
|
35
|
+
}
|
|
36
|
+
if (!contentType.includes('json') && !data?.success && !resp.ok) {
|
|
37
|
+
// Some gateways omit content-type; JSON parse already succeeded.
|
|
38
|
+
}
|
|
23
39
|
if (!resp.ok || data.success === false) {
|
|
24
40
|
const err = data;
|
|
25
41
|
const msg = err.code ? `${err.error} (${err.code})` : (err.error || `API error (${resp.status})`);
|
|
@@ -47,46 +47,59 @@ function resolveApiKey(args, config) {
|
|
|
47
47
|
return args.apiKey || config.apiKey || process.env.FULLCOURTDEFENSE_API_KEY || '';
|
|
48
48
|
}
|
|
49
49
|
async function configureCommand(args, config) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
const apiUrl = args.apiUrl || config.apiUrl || 'https://api.fullcourtdefense.ai';
|
|
51
|
+
const apiKey = resolveApiKey(args, config);
|
|
52
|
+
const organizationId = args.organizationId || config.organizationId;
|
|
53
|
+
const shieldId = args.shieldId || config.shieldId;
|
|
54
|
+
const shieldKey = args.shieldKey ?? config.shieldKey;
|
|
55
|
+
const hasAllRequired = Boolean(apiKey && organizationId && shieldId);
|
|
56
|
+
let finalApiUrl = apiUrl;
|
|
57
|
+
let finalApiKey = apiKey;
|
|
58
|
+
let finalOrgId = organizationId;
|
|
59
|
+
let finalShieldId = shieldId;
|
|
60
|
+
let finalShieldKey = shieldKey;
|
|
61
|
+
if (!hasAllRequired) {
|
|
62
|
+
const rl = readline.createInterface({ input: process_1.stdin, output: process_1.stdout });
|
|
63
|
+
try {
|
|
64
|
+
finalApiUrl = args.apiUrl || await ask(rl, 'FullCourtDefense API URL', config.apiUrl || 'https://api.fullcourtdefense.ai');
|
|
65
|
+
finalApiKey = resolveApiKey(args, config) || await ask(rl, 'Organization API key (from Settings → API Keys)', '');
|
|
66
|
+
finalOrgId = args.organizationId || await ask(rl, 'Organization ID (from Settings → Organization)', config.organizationId || '');
|
|
67
|
+
finalShieldId = args.shieldId || await ask(rl, 'Shield ID', config.shieldId || 'sh_...');
|
|
68
|
+
finalShieldKey = args.shieldKey ?? await ask(rl, 'Shield key if locked, blank if not required', config.shieldKey || '');
|
|
56
69
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error('Organization ID is required.');
|
|
70
|
+
finally {
|
|
71
|
+
rl.close();
|
|
60
72
|
}
|
|
61
|
-
const shieldId = args.shieldId || await ask(rl, 'Shield ID', config.shieldId || 'sh_...');
|
|
62
|
-
if (!shieldId || shieldId === 'sh_...') {
|
|
63
|
-
throw new Error('Shield ID is required.');
|
|
64
|
-
}
|
|
65
|
-
const shieldKey = args.shieldKey ?? await ask(rl, 'Shield key if locked, blank if not required', config.shieldKey || '');
|
|
66
|
-
if (args.skipValidate !== true) {
|
|
67
|
-
console.log('Validating organization, Shield ID, and Shield key against FullCourtDefense...');
|
|
68
|
-
const api = new api_1.BotGuardApi(apiKey, apiUrl);
|
|
69
|
-
const validated = await api.validateSetup({
|
|
70
|
-
organizationId,
|
|
71
|
-
shieldId,
|
|
72
|
-
shieldKey: shieldKey || undefined,
|
|
73
|
-
});
|
|
74
|
-
if (validated.organizationId !== organizationId) {
|
|
75
|
-
throw new Error(`Organization mismatch: API key belongs to "${validated.organizationName}" (${validated.organizationId}), not "${organizationId}".`);
|
|
76
|
-
}
|
|
77
|
-
console.log(`Verified: ${validated.organizationName} → Shield "${validated.shieldName}" (${validated.shieldId})`);
|
|
78
|
-
}
|
|
79
|
-
const savedPath = (0, config_1.saveSetupConfig)({
|
|
80
|
-
apiKey,
|
|
81
|
-
organizationId,
|
|
82
|
-
shieldId,
|
|
83
|
-
shieldKey: shieldKey || undefined,
|
|
84
|
-
apiUrl,
|
|
85
|
-
});
|
|
86
|
-
console.log(`Saved setup to ${savedPath}`);
|
|
87
|
-
console.log('All other CLI commands (install, discover --upload, scan, hooks) will use these credentials automatically.');
|
|
88
73
|
}
|
|
89
|
-
|
|
90
|
-
|
|
74
|
+
if (!finalApiKey) {
|
|
75
|
+
throw new Error('Organization API key is required to validate your setup.');
|
|
76
|
+
}
|
|
77
|
+
if (!finalOrgId) {
|
|
78
|
+
throw new Error('Organization ID is required.');
|
|
79
|
+
}
|
|
80
|
+
if (!finalShieldId || finalShieldId === 'sh_...') {
|
|
81
|
+
throw new Error('Shield ID is required.');
|
|
82
|
+
}
|
|
83
|
+
if (args.skipValidate !== true) {
|
|
84
|
+
console.log('Validating organization, Shield ID, and Shield key against FullCourtDefense...');
|
|
85
|
+
const api = new api_1.BotGuardApi(finalApiKey, finalApiUrl);
|
|
86
|
+
const validated = await api.validateSetup({
|
|
87
|
+
organizationId: finalOrgId,
|
|
88
|
+
shieldId: finalShieldId,
|
|
89
|
+
shieldKey: finalShieldKey || undefined,
|
|
90
|
+
});
|
|
91
|
+
if (validated.organizationId !== finalOrgId) {
|
|
92
|
+
throw new Error(`Organization mismatch: API key belongs to "${validated.organizationName}" (${validated.organizationId}), not "${finalOrgId}".`);
|
|
93
|
+
}
|
|
94
|
+
console.log(`Verified: ${validated.organizationName} → Shield "${validated.shieldName}" (${validated.shieldId})`);
|
|
91
95
|
}
|
|
96
|
+
const savedPath = (0, config_1.saveSetupConfig)({
|
|
97
|
+
apiKey: finalApiKey,
|
|
98
|
+
organizationId: finalOrgId,
|
|
99
|
+
shieldId: finalShieldId,
|
|
100
|
+
shieldKey: finalShieldKey || undefined,
|
|
101
|
+
apiUrl: finalApiUrl,
|
|
102
|
+
});
|
|
103
|
+
console.log(`Saved setup to ${savedPath}`);
|
|
104
|
+
console.log('All other CLI commands (install, discover --upload, scan, hooks) will use these credentials automatically.');
|
|
92
105
|
}
|
package/dist/version.json
CHANGED