@guilhermefsousa/open-spec-kit 0.0.3 → 0.0.5
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/package.json +1 -1
- package/src/commands/doctor.js +16 -1
- package/src/commands/init.js +20 -21
- package/src/utils/http.js +19 -2
package/package.json
CHANGED
package/src/commands/doctor.js
CHANGED
|
@@ -4,7 +4,7 @@ import { join } from 'path';
|
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import yaml from 'yaml';
|
|
6
6
|
import { detectMcpRunner, getInstallInstructions } from '../utils/mcp-detect.js';
|
|
7
|
-
import { confluenceRequest, figmaRequest } from '../utils/http.js';
|
|
7
|
+
import { confluenceRequest, figmaRequest, isSslError } from '../utils/http.js';
|
|
8
8
|
|
|
9
9
|
export async function doctorCommand() {
|
|
10
10
|
console.log(chalk.bold('\n open-spec-kit doctor\n'));
|
|
@@ -319,6 +319,21 @@ export async function doctorCommand() {
|
|
|
319
319
|
console.log(chalk.dim(' Renove em: Figma > Account Settings > Personal Access Tokens'));
|
|
320
320
|
console.log(chalk.dim(' Atualize FIGMA_API_KEY no .env'));
|
|
321
321
|
fail++;
|
|
322
|
+
} else if (isSslError(err)) {
|
|
323
|
+
try {
|
|
324
|
+
const result = await figmaRequest(figmaKey, 10000, true);
|
|
325
|
+
console.log(chalk.green(` ✓ Token Figma válido — SSL corporativo ignorado (usuário: ${result.data.handle || result.data.email || 'OK'})`));
|
|
326
|
+
pass++;
|
|
327
|
+
} catch (retryErr) {
|
|
328
|
+
if (retryErr.status === 401 || retryErr.status === 403) {
|
|
329
|
+
console.log(chalk.red(` ✗ Token Figma inválido ou expirado (HTTP ${retryErr.status})`));
|
|
330
|
+
console.log(chalk.dim(' Renove em: Figma > Account Settings > Personal Access Tokens'));
|
|
331
|
+
console.log(chalk.dim(' Atualize FIGMA_API_KEY no .env'));
|
|
332
|
+
} else {
|
|
333
|
+
console.log(chalk.yellow(` ⚠ Não foi possível verificar token Figma: ${retryErr.message}`));
|
|
334
|
+
}
|
|
335
|
+
fail++;
|
|
336
|
+
}
|
|
322
337
|
} else {
|
|
323
338
|
console.log(chalk.yellow(` ⚠ Não foi possível verificar token Figma: ${err.message}`));
|
|
324
339
|
fail++;
|
package/src/commands/init.js
CHANGED
|
@@ -6,7 +6,7 @@ import { join, dirname } from 'path';
|
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
8
|
import { detectMcpRunner, detectNpxRunner, tryInstallMcpAtlassian, getInstallInstructions } from '../utils/mcp-detect.js';
|
|
9
|
-
import { confluenceRequest, figmaRequest } from '../utils/http.js';
|
|
9
|
+
import { confluenceRequest, figmaRequest, isSslError } from '../utils/http.js';
|
|
10
10
|
|
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
const TEMPLATES_DIR = join(__dirname, '..', '..', 'templates');
|
|
@@ -47,26 +47,6 @@ const KNOWN_TECH_KEYWORDS = [
|
|
|
47
47
|
'SQS', 'SNS', 'DynamoDB', 'Cassandra', 'Nginx', 'Apache',
|
|
48
48
|
];
|
|
49
49
|
|
|
50
|
-
// ──────────────────────────────────────────────────────
|
|
51
|
-
// SSL error detection (corporate proxy workaround)
|
|
52
|
-
// ──────────────────────────────────────────────────────
|
|
53
|
-
const SSL_ERROR_CODES = new Set([
|
|
54
|
-
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
|
55
|
-
'SELF_SIGNED_CERT_IN_CHAIN',
|
|
56
|
-
'DEPTH_ZERO_SELF_SIGNED_CERT',
|
|
57
|
-
'CERT_HAS_EXPIRED',
|
|
58
|
-
'ERR_TLS_CERT_ALTNAME_INVALID',
|
|
59
|
-
'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
function isSslError(err) {
|
|
63
|
-
return err.status === 0 && (
|
|
64
|
-
SSL_ERROR_CODES.has(err.code) ||
|
|
65
|
-
SSL_ERROR_CODES.has(err.message) ||
|
|
66
|
-
(err.message && SSL_ERROR_CODES.has(err.message.split(':').pop()?.trim()))
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
50
|
function stripHtml(html) {
|
|
71
51
|
if (!html) return '';
|
|
72
52
|
return html
|
|
@@ -785,6 +765,25 @@ export async function initCommand() {
|
|
|
785
765
|
phase3.hasFigma = false;
|
|
786
766
|
phase3.figmaFileUrl = '';
|
|
787
767
|
phase3.figmaToken = '';
|
|
768
|
+
} else if (isSslError(err)) {
|
|
769
|
+
figmaSpinner.text = 'Certificado SSL corporativo detectado — tentando sem verificação...';
|
|
770
|
+
try {
|
|
771
|
+
const result = await figmaRequest(phase3.figmaToken.trim(), 15000, true);
|
|
772
|
+
figmaSpinner.succeed(`Token Figma validado (SSL corporativo ignorado) — usuário: ${result.data.handle || result.data.email || 'OK'}`);
|
|
773
|
+
figmaTokenValidated = true;
|
|
774
|
+
} catch (retryErr) {
|
|
775
|
+
if (retryErr.status === 401 || retryErr.status === 403) {
|
|
776
|
+
figmaSpinner.fail(`Token Figma inválido (HTTP ${retryErr.status}). Verifique o Personal Access Token.`);
|
|
777
|
+
console.log(chalk.dim(' Gere em: Figma > Account Settings > Personal Access Tokens'));
|
|
778
|
+
console.log(chalk.yellow(' Continuando sem Figma...\n'));
|
|
779
|
+
phase3.hasFigma = false;
|
|
780
|
+
phase3.figmaFileUrl = '';
|
|
781
|
+
phase3.figmaToken = '';
|
|
782
|
+
} else {
|
|
783
|
+
figmaSpinner.warn(`Não foi possível validar o token Figma: ${retryErr.message}`);
|
|
784
|
+
console.log(chalk.yellow(' Token será salvo, mas verifique com "open-spec-kit doctor".\n'));
|
|
785
|
+
}
|
|
786
|
+
}
|
|
788
787
|
} else {
|
|
789
788
|
figmaSpinner.warn(`Não foi possível validar o token Figma: ${err.message}`);
|
|
790
789
|
console.log(chalk.yellow(' Token será salvo, mas verifique com "open-spec-kit doctor".\n'));
|
package/src/utils/http.js
CHANGED
|
@@ -49,6 +49,23 @@ export function confluenceRequest(baseUrl, path, user, token, timeoutMs = 15000,
|
|
|
49
49
|
return httpGetJson(url, { 'Authorization': `Basic ${auth}` }, { timeoutMs, allowInsecure });
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export function figmaRequest(token, timeoutMs = 15000) {
|
|
53
|
-
return httpGetJson('https://api.figma.com/v1/me', { 'X-Figma-Token': token }, { timeoutMs });
|
|
52
|
+
export function figmaRequest(token, timeoutMs = 15000, allowInsecure = false) {
|
|
53
|
+
return httpGetJson('https://api.figma.com/v1/me', { 'X-Figma-Token': token }, { timeoutMs, allowInsecure });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const SSL_ERROR_CODES = new Set([
|
|
57
|
+
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
|
58
|
+
'SELF_SIGNED_CERT_IN_CHAIN',
|
|
59
|
+
'DEPTH_ZERO_SELF_SIGNED_CERT',
|
|
60
|
+
'CERT_HAS_EXPIRED',
|
|
61
|
+
'ERR_TLS_CERT_ALTNAME_INVALID',
|
|
62
|
+
'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
export function isSslError(err) {
|
|
66
|
+
return err.status === 0 && (
|
|
67
|
+
SSL_ERROR_CODES.has(err.code) ||
|
|
68
|
+
SSL_ERROR_CODES.has(err.message) ||
|
|
69
|
+
(err.message && SSL_ERROR_CODES.has(err.message.split(':').pop()?.trim()))
|
|
70
|
+
);
|
|
54
71
|
}
|