workos 0.7.0 → 0.7.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/dist/doctor/agent-prompt.d.ts +2 -1
- package/dist/doctor/agent-prompt.js +146 -23
- package/dist/doctor/agent-prompt.js.map +1 -1
- package/dist/doctor/checks/ai-analysis.js +1 -1
- package/dist/doctor/checks/ai-analysis.js.map +1 -1
- package/dist/doctor/index.js +1 -1
- package/dist/doctor/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { LanguageInfo, FrameworkInfo, SdkInfo, EnvironmentInfo, Issue } from './types.js';
|
|
2
2
|
export interface AnalysisContext {
|
|
3
|
+
installDir: string;
|
|
3
4
|
language: LanguageInfo;
|
|
4
5
|
framework: FrameworkInfo;
|
|
5
6
|
sdk: SdkInfo;
|
|
6
7
|
environment: EnvironmentInfo;
|
|
7
8
|
existingIssues: Issue[];
|
|
8
9
|
}
|
|
9
|
-
export declare function buildDoctorPrompt(context: AnalysisContext): string
|
|
10
|
+
export declare function buildDoctorPrompt(context: AnalysisContext): Promise<string>;
|
|
@@ -1,5 +1,124 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const MAX_FILE_SIZE = 2000;
|
|
4
|
+
const README_TIMEOUT_MS = 5000;
|
|
5
|
+
const MAX_README_SIZE = 15000;
|
|
6
|
+
// Map SDK package names to their GitHub repo README URLs
|
|
7
|
+
const SDK_README_URLS = {
|
|
8
|
+
'@workos/authkit-nextjs': 'https://raw.githubusercontent.com/workos/authkit-nextjs/main/README.md',
|
|
9
|
+
'@workos-inc/authkit-nextjs': 'https://raw.githubusercontent.com/workos/authkit-nextjs/main/README.md',
|
|
10
|
+
'@workos/authkit-react-router': 'https://raw.githubusercontent.com/workos/authkit-react-router/main/README.md',
|
|
11
|
+
'@workos-inc/authkit-react-router': 'https://raw.githubusercontent.com/workos/authkit-react-router/main/README.md',
|
|
12
|
+
'@workos/authkit-react': 'https://raw.githubusercontent.com/workos/authkit-react/main/README.md',
|
|
13
|
+
'@workos-inc/authkit-react': 'https://raw.githubusercontent.com/workos/authkit-react/main/README.md',
|
|
14
|
+
'@workos/authkit-tanstack-react-start': 'https://raw.githubusercontent.com/workos/authkit-tanstack-react-start/main/README.md',
|
|
15
|
+
'@workos/authkit-remix': 'https://raw.githubusercontent.com/workos/authkit-remix/main/README.md',
|
|
16
|
+
'@workos-inc/authkit-remix': 'https://raw.githubusercontent.com/workos/authkit-remix/main/README.md',
|
|
17
|
+
'@workos/authkit-sveltekit': 'https://raw.githubusercontent.com/workos/authkit-sveltekit/main/README.md',
|
|
18
|
+
'@workos/authkit-js': 'https://raw.githubusercontent.com/workos/authkit-js/main/README.md',
|
|
19
|
+
'@workos-inc/authkit-js': 'https://raw.githubusercontent.com/workos/authkit-js/main/README.md',
|
|
20
|
+
'@workos-inc/node': 'https://raw.githubusercontent.com/workos/workos-node/main/README.md',
|
|
21
|
+
};
|
|
22
|
+
async function fetchSdkReadme(sdkName) {
|
|
23
|
+
if (!sdkName)
|
|
24
|
+
return null;
|
|
25
|
+
const url = SDK_README_URLS[sdkName];
|
|
26
|
+
if (!url)
|
|
27
|
+
return null;
|
|
28
|
+
try {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const timeoutId = setTimeout(() => controller.abort(), README_TIMEOUT_MS);
|
|
31
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
32
|
+
clearTimeout(timeoutId);
|
|
33
|
+
if (!response.ok)
|
|
34
|
+
return null;
|
|
35
|
+
const text = await response.text();
|
|
36
|
+
return text.length > MAX_README_SIZE ? text.slice(0, MAX_README_SIZE) + '\n... (truncated)' : text;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function readFileSafe(path) {
|
|
43
|
+
try {
|
|
44
|
+
const content = readFileSync(path, 'utf-8');
|
|
45
|
+
return content.length > MAX_FILE_SIZE ? content.slice(0, MAX_FILE_SIZE) + '\n... (truncated)' : content;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function readEnvFileRedacted(path) {
|
|
52
|
+
const content = readFileSafe(path);
|
|
53
|
+
if (!content)
|
|
54
|
+
return null;
|
|
55
|
+
return content.replace(/^([A-Z_]+)=(.+)$/gm, (_match, key, value) => {
|
|
56
|
+
if (key.includes('SECRET') || key.includes('PASSWORD') || key.includes('API_KEY')) {
|
|
57
|
+
return `${key}=${value.slice(0, 3)}...(redacted)`;
|
|
58
|
+
}
|
|
59
|
+
return `${key}=${value}`;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function collectProjectFiles(installDir) {
|
|
63
|
+
const candidates = [
|
|
64
|
+
'middleware.ts',
|
|
65
|
+
'middleware.js',
|
|
66
|
+
'proxy.ts',
|
|
67
|
+
'proxy.js',
|
|
68
|
+
'src/middleware.ts',
|
|
69
|
+
'src/middleware.js',
|
|
70
|
+
'src/proxy.ts',
|
|
71
|
+
'src/proxy.js',
|
|
72
|
+
'app/layout.tsx',
|
|
73
|
+
'app/layout.jsx',
|
|
74
|
+
'src/app/layout.tsx',
|
|
75
|
+
'src/app/layout.jsx',
|
|
76
|
+
'app/page.tsx',
|
|
77
|
+
'app/page.jsx',
|
|
78
|
+
'src/app/page.tsx',
|
|
79
|
+
'src/app/page.jsx',
|
|
80
|
+
'src/start.ts',
|
|
81
|
+
'src/start.tsx',
|
|
82
|
+
'app/start.ts',
|
|
83
|
+
'app/root.tsx',
|
|
84
|
+
'app/root.jsx',
|
|
85
|
+
'config/initializers/workos.rb',
|
|
86
|
+
'config/routes.rb',
|
|
87
|
+
'app/settings.py',
|
|
88
|
+
'settings.py',
|
|
89
|
+
'main.go',
|
|
90
|
+
'cmd/main.go',
|
|
91
|
+
];
|
|
92
|
+
// Callback routes
|
|
93
|
+
for (const prefix of ['app', 'src/app']) {
|
|
94
|
+
for (const path of ['auth/callback', 'callback', 'api/auth/callback']) {
|
|
95
|
+
for (const ext of ['ts', 'tsx', 'js', 'jsx']) {
|
|
96
|
+
candidates.push(`${prefix}/${path}/route.${ext}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const files = [];
|
|
101
|
+
for (const candidate of candidates) {
|
|
102
|
+
const fullPath = join(installDir, candidate);
|
|
103
|
+
if (existsSync(fullPath)) {
|
|
104
|
+
const content = readFileSafe(fullPath);
|
|
105
|
+
if (content) {
|
|
106
|
+
files.push(`### ${candidate}\n\`\`\`\n${content}\n\`\`\``);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Include env files with redacted secrets
|
|
111
|
+
for (const envFile of ['.env.local', '.env']) {
|
|
112
|
+
const fullPath = join(installDir, envFile);
|
|
113
|
+
const content = readEnvFileRedacted(fullPath);
|
|
114
|
+
if (content) {
|
|
115
|
+
files.push(`### ${envFile} (secrets redacted)\n\`\`\`\n${content}\n\`\`\``);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return files.length > 0 ? files.join('\n\n') : 'No key files found.';
|
|
119
|
+
}
|
|
120
|
+
export async function buildDoctorPrompt(context) {
|
|
121
|
+
const { installDir, language, framework, sdk, environment, existingIssues } = context;
|
|
3
122
|
const projectContext = [
|
|
4
123
|
`- Language: ${language.name}`,
|
|
5
124
|
framework.name
|
|
@@ -14,27 +133,29 @@ export function buildDoctorPrompt(context) {
|
|
|
14
133
|
const existingIssuesList = existingIssues.length > 0
|
|
15
134
|
? existingIssues.map((i) => `- [${i.severity}] ${i.code}: ${i.message}`).join('\n')
|
|
16
135
|
: 'None detected.';
|
|
17
|
-
|
|
136
|
+
const readme = await fetchSdkReadme(sdk.name);
|
|
137
|
+
const readmeSection = readme
|
|
138
|
+
? `## SDK Documentation (source of truth)\nThis is the official README for ${sdk.name}. Use it to determine correct patterns, imports, and configuration.\n\n${readme}`
|
|
139
|
+
: '## SDK Documentation\nUnable to fetch SDK README. Be conservative — only report issues you are certain about.';
|
|
140
|
+
return `You are a WorkOS integration analyst. Compare this project's code against the SDK documentation and identify real issues.
|
|
18
141
|
|
|
19
142
|
## Project Context
|
|
20
143
|
${projectContext}
|
|
21
144
|
|
|
22
|
-
##
|
|
23
|
-
- \`@workos-inc/node\`
|
|
24
|
-
- \`@workos-inc
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
145
|
+
## General SDK Knowledge
|
|
146
|
+
- \`@workos-inc/node\` works in ANY JavaScript runtime (Node.js, browsers, React Native, Expo, etc.). Despite the name, it has no Node.js-specific dependencies.
|
|
147
|
+
- Some packages are under \`@workos-inc/*\` and some under \`@workos/*\`. Both are official. Do NOT flag package scope as an issue.
|
|
148
|
+
|
|
149
|
+
${readmeSection}
|
|
150
|
+
|
|
151
|
+
## Project Files
|
|
152
|
+
${collectProjectFiles(installDir)}
|
|
29
153
|
|
|
30
154
|
## Already Detected Issues
|
|
31
155
|
${existingIssuesList}
|
|
32
156
|
|
|
33
157
|
## Your Task
|
|
34
|
-
|
|
35
|
-
2. Check for framework-specific anti-patterns
|
|
36
|
-
3. Verify the integration follows WorkOS best practices
|
|
37
|
-
4. Identify potential runtime issues
|
|
158
|
+
Compare the project files against the SDK documentation above. Report issues where the code DEVIATES from what the documentation says to do. If the code follows the documented patterns, it is correct.
|
|
38
159
|
|
|
39
160
|
## Output Format
|
|
40
161
|
Return your analysis as a JSON object wrapped in a markdown code block:
|
|
@@ -45,6 +166,8 @@ Return your analysis as a JSON object wrapped in a markdown code block:
|
|
|
45
166
|
"severity": "error | warning | info",
|
|
46
167
|
"title": "Short description",
|
|
47
168
|
"detail": "What's wrong and why it matters",
|
|
169
|
+
"docSays": "Direct quote or paraphrase from the SDK documentation above",
|
|
170
|
+
"codeDoes": "What the project code actually does that contradicts the docs",
|
|
48
171
|
"remediation": "How to fix it",
|
|
49
172
|
"filePath": "path/to/relevant/file"
|
|
50
173
|
}
|
|
@@ -54,14 +177,14 @@ Return your analysis as a JSON object wrapped in a markdown code block:
|
|
|
54
177
|
\`\`\`
|
|
55
178
|
|
|
56
179
|
## Rules
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
180
|
+
- Every finding MUST have both "docSays" and "codeDoes" filled in. If you cannot cite what the documentation requires AND how the code deviates, it is not a valid finding — drop it.
|
|
181
|
+
- "docSays" must reference something the documentation REQUIRES, not something optional or a suggestion.
|
|
182
|
+
- "codeDoes" must show an actual contradiction, not "the code doesn't use an optional feature."
|
|
183
|
+
- If the code matches the documented patterns, it is CORRECT. Do not suggest alternatives, improvements, or optional features.
|
|
184
|
+
- Do NOT report issues about optional configuration, missing optional callbacks, or "consider adding" suggestions.
|
|
185
|
+
- Do NOT repeat issues already detected (listed above).
|
|
186
|
+
- Do NOT invent SDK options, config properties, or API methods not in the documentation.
|
|
187
|
+
- Do NOT flag package scope (@workos-inc/* vs @workos/*) as an issue.
|
|
188
|
+
- A well-configured project should have ZERO findings — return an empty findings array and a positive summary.`;
|
|
66
189
|
}
|
|
67
190
|
//# sourceMappingURL=agent-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-prompt.js","sourceRoot":"","sources":["../../src/doctor/agent-prompt.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,iBAAiB,CAAC,OAAwB;IACxD,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAE1E,MAAM,cAAc,GAAG;QACrB,eAAe,QAAQ,CAAC,IAAI,EAAE;QAC9B,SAAS,CAAC,IAAI;YACZ,CAAC,CAAC,gBAAgB,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,OAAO,IAAI,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAClH,CAAC,CAAC,IAAI;QACR,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;QAChG,kBAAkB,WAAW,CAAC,UAAU,IAAI,SAAS,EAAE;QACvD,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI;KAClE;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,kBAAkB,GACtB,cAAc,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnF,CAAC,CAAC,gBAAgB,CAAC;IAEvB,OAAO;;;EAGP,cAAc;;;;;;;;;;;EAWd,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAkC4D,CAAC;AACjF,CAAC","sourcesContent":["import type { LanguageInfo, FrameworkInfo, SdkInfo, EnvironmentInfo, Issue } from './types.js';\n\nexport interface AnalysisContext {\n language: LanguageInfo;\n framework: FrameworkInfo;\n sdk: SdkInfo;\n environment: EnvironmentInfo;\n existingIssues: Issue[];\n}\n\nexport function buildDoctorPrompt(context: AnalysisContext): string {\n const { language, framework, sdk, environment, existingIssues } = context;\n\n const projectContext = [\n `- Language: ${language.name}`,\n framework.name\n ? `- Framework: ${framework.name} ${framework.version ?? ''}${framework.variant ? ` (${framework.variant})` : ''}`\n : null,\n sdk.name ? `- SDK: ${sdk.name}${sdk.version ? ` v${sdk.version}` : ''}` : '- SDK: Not installed',\n `- Environment: ${environment.apiKeyType ?? 'Unknown'}`,\n environment.baseUrl ? `- Base URL: ${environment.baseUrl}` : null,\n ]\n .filter(Boolean)\n .join('\\n');\n\n const existingIssuesList =\n existingIssues.length > 0\n ? existingIssues.map((i) => `- [${i.severity}] ${i.code}: ${i.message}`).join('\\n')\n : 'None detected.';\n\n return `You are a WorkOS integration analyst. Analyze this project and identify potential issues with the WorkOS integration.\n\n## Project Context\n${projectContext}\n\n## WorkOS SDK Knowledge (IMPORTANT — do not contradict this)\n- \\`@workos-inc/node\\` and \\`@workos/node\\` work in ANY JavaScript runtime (Node.js, browsers, React Native, Expo, Cloudflare Workers, Deno, Bun). Despite the name, they have NO Node.js-specific API dependencies (no \\`node:crypto\\`, no \\`node:fs\\`, etc.).\n- \\`@workos-inc/node\\` supports PKCE (Proof Key for Code Exchange) for client-side authentication flows. Using it in Expo, React Native, or browser SPAs is the CORRECT and recommended approach.\n- AuthKit SDKs (\\`@workos/authkit-nextjs\\`, \\`@workos/authkit-react-router\\`, \\`@workos/authkit-react\\`, \\`@workos/authkit-tanstack-react-start\\`, etc.) are framework-specific wrappers around the core SDK that add session management, middleware, and auth providers.\n- Legacy scope \\`@workos-inc/*\\` and new scope \\`@workos/*\\` are the same SDKs — the org is migrating package names.\n- For non-JS languages: \\`workos-python\\`, \\`workos-ruby\\`, \\`workos-go\\`, \\`workos-java\\`, \\`workos-php\\`, \\`WorkOS.net\\` are server-side SDKs.\n- Do NOT flag \\`@workos-inc/node\\` as incompatible with client-side, mobile, or non-Node environments. It is designed for universal JavaScript use.\n\n## Already Detected Issues\n${existingIssuesList}\n\n## Your Task\n1. Analyze the project's WorkOS integration based on the context above\n2. Check for framework-specific anti-patterns\n3. Verify the integration follows WorkOS best practices\n4. Identify potential runtime issues\n\n## Output Format\nReturn your analysis as a JSON object wrapped in a markdown code block:\n\\`\\`\\`json\n{\n \"findings\": [\n {\n \"severity\": \"error | warning | info\",\n \"title\": \"Short description\",\n \"detail\": \"What's wrong and why it matters\",\n \"remediation\": \"How to fix it\",\n \"filePath\": \"path/to/relevant/file\"\n }\n ],\n \"summary\": \"One paragraph summary of the integration health\"\n}\n\\`\\`\\`\n\n## Rules\n- Do NOT repeat issues already detected (listed above)\n- Do NOT contradict the SDK Knowledge section above. If you think an SDK is incompatible with a runtime, re-read that section first.\n- Only report issues you are confident about. Do NOT speculate about potential problems that might exist — report problems that DO exist based on the project context.\n- Focus on framework-specific patterns the static checks can't catch\n- Be specific — reference actual file paths and line patterns\n- Keep findings actionable — every finding must have a remediation\n- Limit to 3-5 most important findings. Fewer high-quality findings beat many speculative ones.\n- If the integration looks good, return an empty findings array and say so in the summary. Do NOT invent problems.\n- The filePath field is optional — only include it if you found a specific file`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agent-prompt.js","sourceRoot":"","sources":["../../src/doctor/agent-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYjC,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAC/B,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B,yDAAyD;AACzD,MAAM,eAAe,GAA2B;IAC9C,wBAAwB,EAAE,wEAAwE;IAClG,4BAA4B,EAAE,wEAAwE;IACtG,8BAA8B,EAAE,8EAA8E;IAC9G,kCAAkC,EAAE,8EAA8E;IAClH,uBAAuB,EAAE,uEAAuE;IAChG,2BAA2B,EAAE,uEAAuE;IACpG,sCAAsC,EACpC,sFAAsF;IACxF,uBAAuB,EAAE,uEAAuE;IAChG,2BAA2B,EAAE,uEAAuE;IACpG,2BAA2B,EAAE,2EAA2E;IACxG,oBAAoB,EAAE,oEAAoE;IAC1F,wBAAwB,EAAE,oEAAoE;IAC9F,kBAAkB,EAAE,qEAAqE;CAC1F,CAAC;AAEF,KAAK,UAAU,cAAc,CAAC,OAAsB;IAClD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;IACrG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,OAAO,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,GAAW,EAAE,KAAa,EAAE,EAAE;QAClF,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAClF,OAAO,GAAG,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC;QACpD,CAAC;QACD,OAAO,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAkB;IAC7C,MAAM,UAAU,GAAa;QAC3B,eAAe;QACf,eAAe;QACf,UAAU;QACV,UAAU;QACV,mBAAmB;QACnB,mBAAmB;QACnB,cAAc;QACd,cAAc;QACd,gBAAgB;QAChB,gBAAgB;QAChB,oBAAoB;QACpB,oBAAoB;QACpB,cAAc;QACd,cAAc;QACd,kBAAkB;QAClB,kBAAkB;QAClB,cAAc;QACd,eAAe;QACf,cAAc;QACd,cAAc;QACd,cAAc;QACd,+BAA+B;QAC/B,kBAAkB;QAClB,iBAAiB;QACjB,aAAa;QACb,SAAS;QACT,aAAa;KACd,CAAC;IAEF,kBAAkB;IAClB,KAAK,MAAM,MAAM,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,mBAAmB,CAAC,EAAE,CAAC;YACtE,KAAK,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,UAAU,GAAG,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC7C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,aAAa,OAAO,UAAU,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,KAAK,MAAM,OAAO,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,gCAAgC,OAAO,UAAU,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAwB;IAC9D,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAEtF,MAAM,cAAc,GAAG;QACrB,eAAe,QAAQ,CAAC,IAAI,EAAE;QAC9B,SAAS,CAAC,IAAI;YACZ,CAAC,CAAC,gBAAgB,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,OAAO,IAAI,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAClH,CAAC,CAAC,IAAI;QACR,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB;QAChG,kBAAkB,WAAW,CAAC,UAAU,IAAI,SAAS,EAAE;QACvD,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI;KAClE;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,kBAAkB,GACtB,cAAc,CAAC,MAAM,GAAG,CAAC;QACvB,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnF,CAAC,CAAC,gBAAgB,CAAC;IAEvB,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,MAAM;QAC1B,CAAC,CAAC,2EAA2E,GAAG,CAAC,IAAI,0EAA0E,MAAM,EAAE;QACvK,CAAC,CAAC,+GAA+G,CAAC;IAEpH,OAAO;;;EAGP,cAAc;;;;;;EAMd,aAAa;;;EAGb,mBAAmB,CAAC,UAAU,CAAC;;;EAG/B,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+GAiC2F,CAAC;AAChH,CAAC","sourcesContent":["import { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { LanguageInfo, FrameworkInfo, SdkInfo, EnvironmentInfo, Issue } from './types.js';\n\nexport interface AnalysisContext {\n installDir: string;\n language: LanguageInfo;\n framework: FrameworkInfo;\n sdk: SdkInfo;\n environment: EnvironmentInfo;\n existingIssues: Issue[];\n}\n\nconst MAX_FILE_SIZE = 2000;\nconst README_TIMEOUT_MS = 5000;\nconst MAX_README_SIZE = 15000;\n\n// Map SDK package names to their GitHub repo README URLs\nconst SDK_README_URLS: Record<string, string> = {\n '@workos/authkit-nextjs': 'https://raw.githubusercontent.com/workos/authkit-nextjs/main/README.md',\n '@workos-inc/authkit-nextjs': 'https://raw.githubusercontent.com/workos/authkit-nextjs/main/README.md',\n '@workos/authkit-react-router': 'https://raw.githubusercontent.com/workos/authkit-react-router/main/README.md',\n '@workos-inc/authkit-react-router': 'https://raw.githubusercontent.com/workos/authkit-react-router/main/README.md',\n '@workos/authkit-react': 'https://raw.githubusercontent.com/workos/authkit-react/main/README.md',\n '@workos-inc/authkit-react': 'https://raw.githubusercontent.com/workos/authkit-react/main/README.md',\n '@workos/authkit-tanstack-react-start':\n 'https://raw.githubusercontent.com/workos/authkit-tanstack-react-start/main/README.md',\n '@workos/authkit-remix': 'https://raw.githubusercontent.com/workos/authkit-remix/main/README.md',\n '@workos-inc/authkit-remix': 'https://raw.githubusercontent.com/workos/authkit-remix/main/README.md',\n '@workos/authkit-sveltekit': 'https://raw.githubusercontent.com/workos/authkit-sveltekit/main/README.md',\n '@workos/authkit-js': 'https://raw.githubusercontent.com/workos/authkit-js/main/README.md',\n '@workos-inc/authkit-js': 'https://raw.githubusercontent.com/workos/authkit-js/main/README.md',\n '@workos-inc/node': 'https://raw.githubusercontent.com/workos/workos-node/main/README.md',\n};\n\nasync function fetchSdkReadme(sdkName: string | null): Promise<string | null> {\n if (!sdkName) return null;\n const url = SDK_README_URLS[sdkName];\n if (!url) return null;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), README_TIMEOUT_MS);\n const response = await fetch(url, { signal: controller.signal });\n clearTimeout(timeoutId);\n\n if (!response.ok) return null;\n const text = await response.text();\n return text.length > MAX_README_SIZE ? text.slice(0, MAX_README_SIZE) + '\\n... (truncated)' : text;\n } catch {\n return null;\n }\n}\n\nfunction readFileSafe(path: string): string | null {\n try {\n const content = readFileSync(path, 'utf-8');\n return content.length > MAX_FILE_SIZE ? content.slice(0, MAX_FILE_SIZE) + '\\n... (truncated)' : content;\n } catch {\n return null;\n }\n}\n\nfunction readEnvFileRedacted(path: string): string | null {\n const content = readFileSafe(path);\n if (!content) return null;\n return content.replace(/^([A-Z_]+)=(.+)$/gm, (_match, key: string, value: string) => {\n if (key.includes('SECRET') || key.includes('PASSWORD') || key.includes('API_KEY')) {\n return `${key}=${value.slice(0, 3)}...(redacted)`;\n }\n return `${key}=${value}`;\n });\n}\n\nfunction collectProjectFiles(installDir: string): string {\n const candidates: string[] = [\n 'middleware.ts',\n 'middleware.js',\n 'proxy.ts',\n 'proxy.js',\n 'src/middleware.ts',\n 'src/middleware.js',\n 'src/proxy.ts',\n 'src/proxy.js',\n 'app/layout.tsx',\n 'app/layout.jsx',\n 'src/app/layout.tsx',\n 'src/app/layout.jsx',\n 'app/page.tsx',\n 'app/page.jsx',\n 'src/app/page.tsx',\n 'src/app/page.jsx',\n 'src/start.ts',\n 'src/start.tsx',\n 'app/start.ts',\n 'app/root.tsx',\n 'app/root.jsx',\n 'config/initializers/workos.rb',\n 'config/routes.rb',\n 'app/settings.py',\n 'settings.py',\n 'main.go',\n 'cmd/main.go',\n ];\n\n // Callback routes\n for (const prefix of ['app', 'src/app']) {\n for (const path of ['auth/callback', 'callback', 'api/auth/callback']) {\n for (const ext of ['ts', 'tsx', 'js', 'jsx']) {\n candidates.push(`${prefix}/${path}/route.${ext}`);\n }\n }\n }\n\n const files: string[] = [];\n for (const candidate of candidates) {\n const fullPath = join(installDir, candidate);\n if (existsSync(fullPath)) {\n const content = readFileSafe(fullPath);\n if (content) {\n files.push(`### ${candidate}\\n\\`\\`\\`\\n${content}\\n\\`\\`\\``);\n }\n }\n }\n\n // Include env files with redacted secrets\n for (const envFile of ['.env.local', '.env']) {\n const fullPath = join(installDir, envFile);\n const content = readEnvFileRedacted(fullPath);\n if (content) {\n files.push(`### ${envFile} (secrets redacted)\\n\\`\\`\\`\\n${content}\\n\\`\\`\\``);\n }\n }\n\n return files.length > 0 ? files.join('\\n\\n') : 'No key files found.';\n}\n\nexport async function buildDoctorPrompt(context: AnalysisContext): Promise<string> {\n const { installDir, language, framework, sdk, environment, existingIssues } = context;\n\n const projectContext = [\n `- Language: ${language.name}`,\n framework.name\n ? `- Framework: ${framework.name} ${framework.version ?? ''}${framework.variant ? ` (${framework.variant})` : ''}`\n : null,\n sdk.name ? `- SDK: ${sdk.name}${sdk.version ? ` v${sdk.version}` : ''}` : '- SDK: Not installed',\n `- Environment: ${environment.apiKeyType ?? 'Unknown'}`,\n environment.baseUrl ? `- Base URL: ${environment.baseUrl}` : null,\n ]\n .filter(Boolean)\n .join('\\n');\n\n const existingIssuesList =\n existingIssues.length > 0\n ? existingIssues.map((i) => `- [${i.severity}] ${i.code}: ${i.message}`).join('\\n')\n : 'None detected.';\n\n const readme = await fetchSdkReadme(sdk.name);\n const readmeSection = readme\n ? `## SDK Documentation (source of truth)\\nThis is the official README for ${sdk.name}. Use it to determine correct patterns, imports, and configuration.\\n\\n${readme}`\n : '## SDK Documentation\\nUnable to fetch SDK README. Be conservative — only report issues you are certain about.';\n\n return `You are a WorkOS integration analyst. Compare this project's code against the SDK documentation and identify real issues.\n\n## Project Context\n${projectContext}\n\n## General SDK Knowledge\n- \\`@workos-inc/node\\` works in ANY JavaScript runtime (Node.js, browsers, React Native, Expo, etc.). Despite the name, it has no Node.js-specific dependencies.\n- Some packages are under \\`@workos-inc/*\\` and some under \\`@workos/*\\`. Both are official. Do NOT flag package scope as an issue.\n\n${readmeSection}\n\n## Project Files\n${collectProjectFiles(installDir)}\n\n## Already Detected Issues\n${existingIssuesList}\n\n## Your Task\nCompare the project files against the SDK documentation above. Report issues where the code DEVIATES from what the documentation says to do. If the code follows the documented patterns, it is correct.\n\n## Output Format\nReturn your analysis as a JSON object wrapped in a markdown code block:\n\\`\\`\\`json\n{\n \"findings\": [\n {\n \"severity\": \"error | warning | info\",\n \"title\": \"Short description\",\n \"detail\": \"What's wrong and why it matters\",\n \"docSays\": \"Direct quote or paraphrase from the SDK documentation above\",\n \"codeDoes\": \"What the project code actually does that contradicts the docs\",\n \"remediation\": \"How to fix it\",\n \"filePath\": \"path/to/relevant/file\"\n }\n ],\n \"summary\": \"One paragraph summary of the integration health\"\n}\n\\`\\`\\`\n\n## Rules\n- Every finding MUST have both \"docSays\" and \"codeDoes\" filled in. If you cannot cite what the documentation requires AND how the code deviates, it is not a valid finding — drop it.\n- \"docSays\" must reference something the documentation REQUIRES, not something optional or a suggestion.\n- \"codeDoes\" must show an actual contradiction, not \"the code doesn't use an optional feature.\"\n- If the code matches the documented patterns, it is CORRECT. Do not suggest alternatives, improvements, or optional features.\n- Do NOT report issues about optional configuration, missing optional callbacks, or \"consider adding\" suggestions.\n- Do NOT repeat issues already detected (listed above).\n- Do NOT invent SDK options, config properties, or API methods not in the documentation.\n- Do NOT flag package scope (@workos-inc/* vs @workos/*) as an issue.\n- A well-configured project should have ZERO findings — return an empty findings array and a positive summary.`;\n}\n"]}
|
|
@@ -104,7 +104,7 @@ export async function checkAiAnalysis(context, options) {
|
|
|
104
104
|
const startTime = Date.now();
|
|
105
105
|
const spinner = startSpinner('Analyzing project with AI...');
|
|
106
106
|
try {
|
|
107
|
-
const prompt = buildDoctorPrompt(context);
|
|
107
|
+
const prompt = await buildDoctorPrompt(context);
|
|
108
108
|
const responseText = await callModel(prompt, model);
|
|
109
109
|
const durationMs = Date.now() - startTime;
|
|
110
110
|
const { findings, summary } = parseAiResponse(responseText);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-analysis.js","sourceRoot":"","sources":["../../../src/doctor/checks/ai-analysis.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ai-analysis.js","sourceRoot":"","sources":["../../../src/doctor/checks/ai-analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import Anthropic from '@anthropic-ai/sdk';\nimport { getLlmGatewayUrl, getAuthkitDomain, getCliAuthClientId, getConfig } from '../../lib/settings.js';\nimport { getCredentials, isTokenExpired, updateTokens, diagnoseCredentials } from '../../lib/credentials.js';\nimport { refreshAccessToken } from '../../lib/token-refresh-client.js';\nimport { buildDoctorPrompt, type AnalysisContext } from '../agent-prompt.js';\nimport type { AiAnalysis, AiFinding } from '../types.js';\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nfunction startSpinner(message: string): { stop: () => void } {\n let i = 0;\n const interval = setInterval(() => {\n process.stderr.write(`\\r ${SPINNER_FRAMES[i++ % SPINNER_FRAMES.length]} ${message}`);\n }, 80);\n return {\n stop: () => {\n clearInterval(interval);\n process.stderr.write(`\\r${' '.repeat(message.length + 6)}\\r`);\n },\n };\n}\n\nexport function parseAiResponse(text: string): { findings: AiFinding[]; summary: string } {\n const codeBlockMatch = text.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?\\s*```/);\n const jsonStr = codeBlockMatch ? codeBlockMatch[1] : text;\n\n try {\n const parsed = JSON.parse(jsonStr.trim());\n const findings = Array.isArray(parsed.findings)\n ? parsed.findings.map((f: Record<string, unknown>) => ({\n severity: (['error', 'warning', 'info'].includes(f.severity as string) ? f.severity : 'info') as\n | 'error'\n | 'warning'\n | 'info',\n title: String(f.title ?? ''),\n detail: String(f.detail ?? ''),\n remediation: String(f.remediation ?? ''),\n filePath: f.filePath ? String(f.filePath) : undefined,\n }))\n : [];\n return { findings, summary: String(parsed.summary ?? '') };\n } catch {\n const jsonMatch = text.match(/\\{[\\s\\S]*\"findings\"[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const parsed = JSON.parse(jsonMatch[0]);\n return {\n findings: Array.isArray(parsed.findings) ? parsed.findings : [],\n summary: String(parsed.summary ?? ''),\n };\n } catch {\n // give up\n }\n }\n return { findings: [], summary: text.slice(0, 500) };\n }\n}\n\nasync function callModel(prompt: string, model: string): Promise<string> {\n let creds = getCredentials();\n if (!creds) throw new Error('Not authenticated');\n\n if (isTokenExpired(creds)) {\n if (!creds.refreshToken) throw new Error('Session expired — run `workos login` to re-authenticate');\n const result = await refreshAccessToken(getAuthkitDomain(), getCliAuthClientId());\n if (!result.success || !result.accessToken || !result.expiresAt) {\n throw new Error('Session expired — run `workos login` to re-authenticate');\n }\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n creds = getCredentials()!;\n }\n\n const client = new Anthropic({\n baseURL: getLlmGatewayUrl(),\n apiKey: 'gateway',\n defaultHeaders: { Authorization: `Bearer ${creds.accessToken}` },\n });\n\n const response = await client.messages.create({\n model,\n max_tokens: 2048,\n messages: [{ role: 'user', content: prompt }],\n });\n\n const text = response.content[0];\n if (text.type === 'text') return text.text;\n throw new Error('Unexpected response format');\n}\n\nexport async function checkAiAnalysis(context: AnalysisContext, options: { skipAi?: boolean }): Promise<AiAnalysis> {\n const model = getConfig().doctorModel;\n\n const skippedResult = (reason: string): AiAnalysis => ({\n findings: [],\n summary: '',\n model,\n durationMs: 0,\n skipped: true,\n skipReason: reason,\n });\n\n if (options.skipAi) {\n return skippedResult('Skipped (--skip-ai flag)');\n }\n\n const creds = getCredentials();\n if (!creds) {\n const diag = diagnoseCredentials();\n process.stderr.write('\\n [credential-debug]\\n');\n for (const line of diag) {\n process.stderr.write(` ${line}\\n`);\n }\n process.stderr.write('\\n');\n return skippedResult('Not authenticated — run `workos login` for AI-powered analysis');\n }\n\n const startTime = Date.now();\n const spinner = startSpinner('Analyzing project with AI...');\n\n try {\n const prompt = await buildDoctorPrompt(context);\n const responseText = await callModel(prompt, model);\n const durationMs = Date.now() - startTime;\n const { findings, summary } = parseAiResponse(responseText);\n return { findings, summary, model, durationMs };\n } catch (error) {\n const durationMs = Date.now() - startTime;\n const errMsg = error instanceof Error ? error.message : 'Unknown error';\n return { ...skippedResult(`Analysis failed: ${errMsg}`), durationMs };\n } finally {\n spinner.stop();\n }\n}\n"]}
|
package/dist/doctor/index.js
CHANGED
|
@@ -41,7 +41,7 @@ export async function runDoctor(options) {
|
|
|
41
41
|
const [dashboardResult, authPatterns, aiAnalysis] = await Promise.all([
|
|
42
42
|
checkDashboardSettings(options, environment.apiKeyType, envRaw),
|
|
43
43
|
checkAuthPatterns(options, framework, environment, sdk),
|
|
44
|
-
checkAiAnalysis({ language, framework, sdk, environment, existingIssues: earlyIssues }, { skipAi: options.skipAi }),
|
|
44
|
+
checkAiAnalysis({ installDir: options.installDir, language, framework, sdk, environment, existingIssues: earlyIssues }, { skipAi: options.skipAi }),
|
|
45
45
|
]);
|
|
46
46
|
// Compute expected redirect URI from framework detection if not set in env
|
|
47
47
|
const redirectUriSource = environment.redirectUri ? 'env' : 'inferred';
|
package/dist/doctor/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAsB;IACpD,kEAAkE;IAClE,qEAAqE;IACrE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAErE,oCAAoC;IACpC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1E,QAAQ,CAAC,OAAO,CAAC;QACjB,cAAc,CAAC,OAAO,CAAC;QACvB,YAAY,CAAC,OAAO,CAAC;QACrB,iBAAiB,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,IAAI,wBAAwB,CAAC;QAC3E,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC;KAClC,CAAC,CAAC;IAEH,8FAA8F;IAC9F,yEAAyE;IACzE,MAAM,WAAW,GAAG,YAAY,CAAC;QAC/B,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,cAAc,EAAE;QAC7E,GAAG;QACH,QAAQ;QACR,OAAO;QACP,SAAS;QACT,WAAW;QACX,YAAY;KACb,CAAC,CAAC;IAEH,MAAM,CAAC,eAAe,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACpE,sBAAsB,CAAC,OAAO,EAAE,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC;QAC/D,iBAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,CAAC;QACvD,eAAe,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkSdk } from './checks/sdk.js';\nimport { checkFramework } from './checks/framework.js';\nimport { checkRuntime } from './checks/runtime.js';\nimport { checkLanguage } from './checks/language.js';\nimport { checkEnvironment } from './checks/environment.js';\nimport { checkConnectivity } from './checks/connectivity.js';\nimport { checkDashboardSettings, compareRedirectUris } from './checks/dashboard.js';\nimport { checkAuthPatterns } from './checks/auth-patterns.js';\nimport { checkAiAnalysis } from './checks/ai-analysis.js';\nimport { detectIssues } from './issues.js';\nimport { formatReport } from './output.js';\nimport { formatReportAsJson } from './json-output.js';\nimport { copyToClipboard } from './clipboard.js';\nimport Chalk from 'chalk';\nimport type { DoctorOptions, DoctorReport } from './types.js';\n\nconst DOCTOR_VERSION = '1.0.0';\n\nexport async function runDoctor(options: DoctorOptions): Promise<DoctorReport> {\n // Environment check first - loads project's .env/.env.local files\n // Must run before connectivity so the resolved base URL is available\n const { info: environment, raw: envRaw } = checkEnvironment(options);\n\n // Run remaining checks concurrently\n const [sdk, framework, runtime, connectivity, language] = await Promise.all([\n checkSdk(options),\n checkFramework(options),\n checkRuntime(options),\n checkConnectivity(options, environment.baseUrl ?? 'https://api.workos.com'),\n checkLanguage(options.installDir),\n ]);\n\n // Dashboard settings + auth patterns + AI analysis (parallel, all need sdk/framework results)\n // AI analysis also receives early issues as context to avoid duplication\n const earlyIssues = detectIssues({\n version: DOCTOR_VERSION,\n timestamp: '',\n project: { path: options.installDir, packageManager: runtime.packageManager },\n sdk,\n language,\n runtime,\n framework,\n environment,\n connectivity,\n });\n\n const [dashboardResult, authPatterns, aiAnalysis] = await Promise.all([\n checkDashboardSettings(options, environment.apiKeyType, envRaw),\n checkAuthPatterns(options, framework, environment, sdk),\n checkAiAnalysis(\n { installDir: options.installDir, language, framework, sdk, environment, existingIssues: earlyIssues },\n { skipAi: options.skipAi },\n ),\n ]);\n\n // Compute expected redirect URI from framework detection if not set in env\n const redirectUriSource: 'env' | 'inferred' = environment.redirectUri ? 'env' : 'inferred';\n const expectedRedirectUri =\n environment.redirectUri ??\n (framework.expectedCallbackPath && framework.detectedPort\n ? `http://localhost:${framework.detectedPort}${framework.expectedCallbackPath}`\n : null);\n\n // Compare redirect URIs if we have dashboard data\n const redirectUris = dashboardResult.settings\n ? compareRedirectUris(expectedRedirectUri, dashboardResult.settings.redirectUris, redirectUriSource)\n : undefined;\n\n // Build partial report\n const partialReport = {\n version: DOCTOR_VERSION,\n timestamp: new Date().toISOString(),\n project: {\n path: options.installDir,\n packageManager: runtime.packageManager,\n },\n sdk,\n language,\n runtime,\n framework,\n environment,\n connectivity,\n credentialValidation: dashboardResult.credentialValidation,\n dashboardSettings: dashboardResult.settings ?? undefined,\n dashboardError: dashboardResult.settings ? undefined : dashboardResult.error,\n redirectUris,\n authPatterns,\n aiAnalysis,\n };\n\n // Detect issues based on collected data\n const issues = detectIssues(partialReport);\n\n // Calculate summary\n const errors = issues.filter((i) => i.severity === 'error').length;\n const warnings = issues.filter((i) => i.severity === 'warning').length;\n\n const report: DoctorReport = {\n ...partialReport,\n issues,\n summary: {\n errors,\n warnings,\n healthy: errors === 0,\n },\n };\n\n return report;\n}\n\nexport async function outputReport(report: DoctorReport, options: DoctorOptions): Promise<void> {\n if (options.json) {\n const json = formatReportAsJson(report);\n console.log(json);\n\n if (options.copy) {\n const success = await copyToClipboard(json);\n if (success) {\n console.error('(Copied to clipboard)');\n }\n }\n } else {\n formatReport(report, { verbose: options.verbose });\n\n if (options.copy) {\n const json = formatReportAsJson(report);\n const success = await copyToClipboard(json);\n if (success) {\n console.log(Chalk.dim('Report copied to clipboard'));\n }\n }\n }\n}\n\nexport { formatReport } from './output.js';\nexport { formatReportAsJson } from './json-output.js';\nexport type { DoctorReport, DoctorOptions } from './types.js';\n"]}
|