skrypt-ai 0.3.4 → 0.4.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/README.md +1 -1
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/index.js +3 -5
- package/dist/autofix/index.js +15 -3
- package/dist/cli.js +19 -4
- package/dist/commands/check-links.js +164 -174
- package/dist/commands/deploy.js +5 -2
- package/dist/commands/generate.js +206 -199
- package/dist/commands/i18n.js +3 -20
- package/dist/commands/init.js +47 -40
- package/dist/commands/lint.js +3 -20
- package/dist/commands/mcp.js +125 -122
- package/dist/commands/monitor.js +125 -108
- package/dist/commands/review-pr.js +1 -1
- package/dist/commands/sdk.js +1 -1
- package/dist/config/loader.js +21 -2
- package/dist/generator/organizer.d.ts +3 -0
- package/dist/generator/organizer.js +4 -9
- package/dist/generator/writer.js +2 -10
- package/dist/github/pr-comments.js +21 -8
- package/dist/plugins/index.js +1 -0
- package/dist/scanner/index.js +8 -2
- package/dist/template/docs.json +2 -1
- package/dist/template/next.config.mjs +2 -1
- package/dist/template/package.json +17 -15
- package/dist/template/public/favicon.svg +4 -0
- package/dist/template/public/search-index.json +1 -1
- package/dist/template/scripts/build-search-index.mjs +120 -25
- package/dist/template/src/app/api/chat/route.ts +11 -3
- package/dist/template/src/app/docs/README.md +28 -0
- package/dist/template/src/app/docs/[...slug]/page.tsx +139 -16
- package/dist/template/src/app/docs/auth/page.mdx +589 -0
- package/dist/template/src/app/docs/autofix/page.mdx +624 -0
- package/dist/template/src/app/docs/cli/page.mdx +217 -0
- package/dist/template/src/app/docs/config/page.mdx +428 -0
- package/dist/template/src/app/docs/configuration/page.mdx +86 -0
- package/dist/template/src/app/docs/deployment/page.mdx +112 -0
- package/dist/template/src/app/docs/error.tsx +20 -0
- package/dist/template/src/app/docs/generator/generator.md +504 -0
- package/dist/template/src/app/docs/generator/organizer.md +779 -0
- package/dist/template/src/app/docs/generator/page.mdx +613 -0
- package/dist/template/src/app/docs/github/page.mdx +502 -0
- package/dist/template/src/app/docs/llm/anthropic-client.md +549 -0
- package/dist/template/src/app/docs/llm/index.md +471 -0
- package/dist/template/src/app/docs/llm/page.mdx +428 -0
- package/dist/template/src/app/docs/llms-full.md +256 -0
- package/dist/template/src/app/docs/llms.txt +2971 -0
- package/dist/template/src/app/docs/not-found.tsx +23 -0
- package/dist/template/src/app/docs/page.mdx +0 -3
- package/dist/template/src/app/docs/plugins/page.mdx +1793 -0
- package/dist/template/src/app/docs/pro/page.mdx +121 -0
- package/dist/template/src/app/docs/quickstart/page.mdx +93 -0
- package/dist/template/src/app/docs/scanner/content-type.md +599 -0
- package/dist/template/src/app/docs/scanner/index.md +212 -0
- package/dist/template/src/app/docs/scanner/page.mdx +307 -0
- package/dist/template/src/app/docs/scanner/python.md +469 -0
- package/dist/template/src/app/docs/scanner/python_parser.md +1056 -0
- package/dist/template/src/app/docs/scanner/rust.md +325 -0
- package/dist/template/src/app/docs/scanner/typescript.md +201 -0
- package/dist/template/src/app/error.tsx +3 -3
- package/dist/template/src/app/icon.tsx +29 -0
- package/dist/template/src/app/layout.tsx +42 -0
- package/dist/template/src/app/not-found.tsx +35 -0
- package/dist/template/src/app/page.tsx +62 -28
- package/dist/template/src/components/ai-chat.tsx +26 -21
- package/dist/template/src/components/breadcrumbs.tsx +46 -2
- package/dist/template/src/components/copy-button.tsx +17 -3
- package/dist/template/src/components/docs-layout.tsx +142 -8
- package/dist/template/src/components/feedback.tsx +4 -2
- package/dist/template/src/components/footer.tsx +42 -0
- package/dist/template/src/components/header.tsx +29 -5
- package/dist/template/src/components/mdx/accordion.tsx +7 -6
- package/dist/template/src/components/mdx/card.tsx +19 -7
- package/dist/template/src/components/mdx/code-block.tsx +17 -3
- package/dist/template/src/components/mdx/code-group.tsx +65 -18
- package/dist/template/src/components/mdx/code-playground.tsx +3 -0
- package/dist/template/src/components/mdx/go-playground.tsx +3 -0
- package/dist/template/src/components/mdx/highlighted-code.tsx +171 -76
- package/dist/template/src/components/mdx/python-playground.tsx +2 -0
- package/dist/template/src/components/mdx/tabs.tsx +74 -6
- package/dist/template/src/components/page-header.tsx +19 -0
- package/dist/template/src/components/scroll-to-top.tsx +33 -0
- package/dist/template/src/components/search-dialog.tsx +206 -52
- package/dist/template/src/components/sidebar.tsx +136 -77
- package/dist/template/src/components/table-of-contents.tsx +23 -7
- package/dist/template/src/lib/highlight.ts +90 -31
- package/dist/template/src/lib/search.ts +14 -4
- package/dist/template/src/lib/theme-utils.ts +140 -0
- package/dist/template/src/styles/globals.css +307 -166
- package/dist/template/src/types/remark-gfm.d.ts +2 -0
- package/dist/utils/files.d.ts +9 -0
- package/dist/utils/files.js +33 -0
- package/dist/utils/validation.d.ts +4 -0
- package/dist/utils/validation.js +38 -0
- package/package.json +1 -4
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
## Functions
|
|
2
|
+
|
|
3
|
+
### `autoFixExample`
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
async function autoFixExample(example: CodeExample, client: LLMClient, options: AutoFixOptions = {}): Promise<FixResult>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Use this to automatically repair broken or invalid code examples by iteratively applying LLM-powered fixes until the code is valid or the maximum retry limit is reached.
|
|
10
|
+
|
|
11
|
+
This is ideal for CI pipelines, documentation generators, or developer tools that need to ensure code examples stay compilable and correct as APIs evolve.
|
|
12
|
+
|
|
13
|
+
#### Parameters
|
|
14
|
+
|
|
15
|
+
| Name | Type | Required | Description |
|
|
16
|
+
|------|------|----------|-------------|
|
|
17
|
+
| `example` | `CodeExample` | ✅ | The code example to fix, including its source code, language, and optional error context |
|
|
18
|
+
| `client` | `LLMClient` | ✅ | An LLM client instance used to generate fix suggestions |
|
|
19
|
+
| `options` | `AutoFixOptions` | ❌ | Configuration options such as `maxIterations` (default: `3`) to control retry attempts |
|
|
20
|
+
|
|
21
|
+
#### Returns
|
|
22
|
+
|
|
23
|
+
Returns a `Promise<FixResult>` that resolves with:
|
|
24
|
+
|
|
25
|
+
| Field | Type | Description |
|
|
26
|
+
|-------|------|-------------|
|
|
27
|
+
| `success` | `boolean` | Whether the example was successfully fixed |
|
|
28
|
+
| `fixedCode` | `string \| null` | The repaired code if successful, otherwise `null` |
|
|
29
|
+
| `iterations` | `number` | How many fix attempts were made |
|
|
30
|
+
| `error` | `string \| undefined` | Description of the failure if `success` is `false` |
|
|
31
|
+
|
|
32
|
+
**Example:**
|
|
33
|
+
|
|
34
|
+
```typescript example.ts
|
|
35
|
+
// ── Inline types (no external imports needed) ──────────────────────────────
|
|
36
|
+
|
|
37
|
+
type CodeExample = {
|
|
38
|
+
code: string
|
|
39
|
+
language: string
|
|
40
|
+
errorContext?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type AutoFixOptions = {
|
|
44
|
+
maxIterations?: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type FixResult = {
|
|
48
|
+
success: boolean
|
|
49
|
+
fixedCode: string | null
|
|
50
|
+
iterations: number
|
|
51
|
+
error?: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type LLMClient = {
|
|
55
|
+
complete: (prompt: string) => Promise<string>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── Simulated LLM client (replace with your real client) ───────────────────
|
|
59
|
+
|
|
60
|
+
function createLLMClient(apiKey: string): LLMClient {
|
|
61
|
+
return {
|
|
62
|
+
complete: async (prompt: string): Promise<string> => {
|
|
63
|
+
// In production this would call OpenAI, Anthropic, etc.
|
|
64
|
+
console.log(`[LLM] Sending prompt (${prompt.length} chars) to API...`)
|
|
65
|
+
|
|
66
|
+
// Simulate a fix: replace the broken fetch call with a corrected version
|
|
67
|
+
return `
|
|
68
|
+
async function fetchUser(id: string) {
|
|
69
|
+
const response = await fetch(\`https://api.example.com/users/\${id}\`, {
|
|
70
|
+
headers: { Authorization: \`Bearer \${process.env.API_TOKEN}\` }
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) throw new Error(\`HTTP \${response.status}\`);
|
|
73
|
+
return response.json();
|
|
74
|
+
}
|
|
75
|
+
`.trim()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── Simulated autoFixExample (mirrors the real implementation) ─────────────
|
|
81
|
+
|
|
82
|
+
async function autoFixExample(
|
|
83
|
+
example: CodeExample,
|
|
84
|
+
client: LLMClient,
|
|
85
|
+
options: AutoFixOptions = {}
|
|
86
|
+
): Promise<FixResult> {
|
|
87
|
+
const maxIterations = options.maxIterations ?? 3
|
|
88
|
+
let currentCode = example.code
|
|
89
|
+
let iterations = 0
|
|
90
|
+
|
|
91
|
+
while (iterations < maxIterations) {
|
|
92
|
+
iterations++
|
|
93
|
+
|
|
94
|
+
const prompt = [
|
|
95
|
+
`Fix the following ${example.language} code example.`,
|
|
96
|
+
example.errorContext ? `Error: ${example.errorContext}` : '',
|
|
97
|
+
`\`\`\`${example.language}`,
|
|
98
|
+
currentCode,
|
|
99
|
+
'```',
|
|
100
|
+
'Return only the corrected code, no explanation.'
|
|
101
|
+
]
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.join('\n')
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
const fixedCode = await client.complete(prompt)
|
|
107
|
+
|
|
108
|
+
// Simulate a basic validation check (real impl would compile/lint)
|
|
109
|
+
const isValid = !fixedCode.includes('SYNTAX_ERROR') && fixedCode.trim().length > 0
|
|
110
|
+
|
|
111
|
+
if (isValid) {
|
|
112
|
+
return { success: true, fixedCode, iterations }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
currentCode = fixedCode // retry with the partially-fixed code
|
|
116
|
+
} catch (err) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
fixedCode: null,
|
|
120
|
+
iterations,
|
|
121
|
+
error: err instanceof Error ? err.message : 'Unknown LLM error'
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
fixedCode: null,
|
|
129
|
+
iterations,
|
|
130
|
+
error: `Could not fix example after ${maxIterations} iteration(s)`
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ── Usage ──────────────────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
const brokenExample: CodeExample = {
|
|
137
|
+
language: 'typescript',
|
|
138
|
+
errorContext: "Cannot read properties of undefined (reading 'json')",
|
|
139
|
+
code: `
|
|
140
|
+
async function fetchUser(id: string) {
|
|
141
|
+
const response = fetch(\`https://api.example.com/users/\${id}\`) // missing await
|
|
142
|
+
return response.json()
|
|
143
|
+
}
|
|
144
|
+
`.trim()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function main() {
|
|
148
|
+
const client = createLLMClient(process.env.OPENAI_API_KEY || 'sk-your-api-key-here')
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const result = await autoFixExample(brokenExample, client, { maxIterations: 3 })
|
|
152
|
+
|
|
153
|
+
if (result.success) {
|
|
154
|
+
console.log(`✅ Fixed in ${result.iterations} iteration(s):\n`)
|
|
155
|
+
console.log(result.fixedCode)
|
|
156
|
+
} else {
|
|
157
|
+
console.warn(`❌ Fix failed after ${result.iterations} attempt(s): ${result.error}`)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Expected output:
|
|
161
|
+
// [LLM] Sending prompt (... chars) to API...
|
|
162
|
+
// ✅ Fixed in 1 iteration(s):
|
|
163
|
+
//
|
|
164
|
+
// async function fetchUser(id: string) {
|
|
165
|
+
// const response = await fetch(`https://api.example.com/users/${id}`, {
|
|
166
|
+
// headers: { Authorization: `Bearer ${process.env.API_TOKEN}` }
|
|
167
|
+
// });
|
|
168
|
+
// if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
169
|
+
// return response.json();
|
|
170
|
+
// }
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('Unexpected error during auto-fix:', error)
|
|
173
|
+
process.exit(1)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
main()
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `autoFixBatch`
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
async function autoFixBatch(examples: CodeExample[], client: LLMClient, options: AutoFixOptions = {}): Promise<Map<number, FixResult>>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Use this to automatically fix multiple broken code examples in a single batch operation, getting back a map of results indexed by position.
|
|
187
|
+
|
|
188
|
+
This is the batch version of `autoFix` — ideal when you have a collection of code examples that need validation and repair, such as during a documentation build pipeline or CI check.
|
|
189
|
+
|
|
190
|
+
#### Parameters
|
|
191
|
+
|
|
192
|
+
| Name | Type | Required | Description |
|
|
193
|
+
|------|------|----------|-------------|
|
|
194
|
+
| `examples` | `CodeExample[]` | ✅ Yes | Array of code examples to fix, each with a `code` string and optional metadata |
|
|
195
|
+
| `client` | `LLMClient` | ✅ Yes | LLM client instance used to analyze and rewrite broken examples |
|
|
196
|
+
| `options` | `AutoFixOptions` | ❌ No | Configuration options such as `maxRetries`, `language`, and `context` hints |
|
|
197
|
+
|
|
198
|
+
#### Returns
|
|
199
|
+
|
|
200
|
+
Returns `Promise<Map<number, FixResult>>` — a `Map` where:
|
|
201
|
+
- **Key** (`number`): The zero-based index of the example in the input array
|
|
202
|
+
- **Value** (`FixResult`): An object containing:
|
|
203
|
+
- `fixed` (`boolean`): Whether the example was successfully repaired
|
|
204
|
+
- `code` (`string`): The resulting code (fixed or original if unfixable)
|
|
205
|
+
- `error` (`string | undefined`): Description of what was wrong, if applicable
|
|
206
|
+
- `attempts` (`number`): How many fix attempts were made
|
|
207
|
+
|
|
208
|
+
Only examples that were processed appear in the map. If an example was skipped or errored fatally, it may be absent.
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
|
|
212
|
+
```typescript example.ts
|
|
213
|
+
// ── Inline types (do not import from autodocs) ──────────────────────────────
|
|
214
|
+
|
|
215
|
+
type CodeExample = {
|
|
216
|
+
code: string
|
|
217
|
+
language?: string
|
|
218
|
+
filename?: string
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
type FixResult = {
|
|
222
|
+
fixed: boolean
|
|
223
|
+
code: string
|
|
224
|
+
error?: string
|
|
225
|
+
attempts: number
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
type AutoFixOptions = {
|
|
229
|
+
maxRetries?: number
|
|
230
|
+
language?: string
|
|
231
|
+
contextHint?: string
|
|
232
|
+
dryRun?: boolean
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
type LLMClient = {
|
|
236
|
+
complete: (prompt: string) => Promise<string>
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ── Simulated autoFixBatch implementation ───────────────────────────────────
|
|
240
|
+
|
|
241
|
+
async function autoFixBatch(
|
|
242
|
+
examples: CodeExample[],
|
|
243
|
+
client: LLMClient,
|
|
244
|
+
options: AutoFixOptions = {}
|
|
245
|
+
): Promise<Map<number, FixResult>> {
|
|
246
|
+
const { maxRetries = 2, dryRun = false } = options
|
|
247
|
+
const results = new Map<number, FixResult>()
|
|
248
|
+
|
|
249
|
+
for (let i = 0; i < examples.length; i++) {
|
|
250
|
+
const example = examples[i]
|
|
251
|
+
let attempts = 0
|
|
252
|
+
let fixed = false
|
|
253
|
+
let finalCode = example.code
|
|
254
|
+
let errorMsg: string | undefined
|
|
255
|
+
|
|
256
|
+
// Simulate detecting and fixing issues
|
|
257
|
+
const hasIssue = example.code.includes('???') || example.code.includes('BROKEN')
|
|
258
|
+
|
|
259
|
+
if (!hasIssue) {
|
|
260
|
+
results.set(i, { fixed: true, code: finalCode, attempts: 0 })
|
|
261
|
+
continue
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
while (attempts < maxRetries && !fixed) {
|
|
265
|
+
attempts++
|
|
266
|
+
if (!dryRun) {
|
|
267
|
+
// In real usage, the LLM client rewrites the broken code
|
|
268
|
+
const prompt = `Fix this ${example.language ?? 'code'} example:\n${example.code}`
|
|
269
|
+
const suggestion = await client.complete(prompt)
|
|
270
|
+
finalCode = suggestion
|
|
271
|
+
fixed = !finalCode.includes('???') && !finalCode.includes('BROKEN')
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
errorMsg = fixed ? undefined : `Could not repair example after ${attempts} attempt(s)`
|
|
276
|
+
results.set(i, { fixed, code: finalCode, error: errorMsg, attempts })
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return results
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// ── Mock LLM client ──────────────────────────────────────────────────────────
|
|
283
|
+
|
|
284
|
+
function createMockLLMClient(apiKey: string): LLMClient {
|
|
285
|
+
return {
|
|
286
|
+
complete: async (prompt: string): Promise<string> => {
|
|
287
|
+
// Simulate a repaired response from the LLM
|
|
288
|
+
console.log(` [LLM] Sending fix request (key: ${apiKey.slice(0, 8)}...)`)
|
|
289
|
+
return `const greet = (name: string) => \`Hello, \${name}!\`;\nconsole.log(greet('World'));`
|
|
290
|
+
},
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ── Main ─────────────────────────────────────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
const examples: CodeExample[] = [
|
|
297
|
+
{
|
|
298
|
+
code: `const greet = (name: string) => \`Hello, \${name}!\`;\nconsole.log(greet('World'));`,
|
|
299
|
+
language: 'typescript',
|
|
300
|
+
filename: 'greet.ts',
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
code: `function add(a, b) { return ???; }`, // BROKEN
|
|
304
|
+
language: 'javascript',
|
|
305
|
+
filename: 'add.js',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
code: `export const PI = BROKEN_VALUE;`, // BROKEN
|
|
309
|
+
language: 'typescript',
|
|
310
|
+
filename: 'constants.ts',
|
|
311
|
+
},
|
|
312
|
+
]
|
|
313
|
+
|
|
314
|
+
async function main() {
|
|
315
|
+
const apiKey = process.env.LLM_API_KEY || 'sk-demo-1234567890abcdef'
|
|
316
|
+
const client = createMockLLMClient(apiKey)
|
|
317
|
+
|
|
318
|
+
const options: AutoFixOptions = {
|
|
319
|
+
maxRetries: 3,
|
|
320
|
+
language: 'typescript',
|
|
321
|
+
contextHint: 'These are documentation examples for a math utility library',
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
console.log(`Processing ${examples.length} examples...\n`)
|
|
326
|
+
const results = await autoFixBatch(examples, client, options)
|
|
327
|
+
|
|
328
|
+
results.forEach((result, index) => {
|
|
329
|
+
const example = examples[index]
|
|
330
|
+
console.log(`── Example ${index} (${example.filename}) ──`)
|
|
331
|
+
console.log(` Fixed: ${result.fixed}`)
|
|
332
|
+
console.log(` Attempts: ${result.attempts}`)
|
|
333
|
+
if (result.error) {
|
|
334
|
+
console.log(` Error: ${result.error}`)
|
|
335
|
+
}
|
|
336
|
+
console.log(` Code: ${result.code.split('\n')[0]}...`)
|
|
337
|
+
console.log()
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
// Summary
|
|
341
|
+
const fixedCount = [...results.values()].filter((r) => r.fixed).length
|
|
342
|
+
console.log(`✅ ${fixedCount}/${results.size} examples fixed successfully`)
|
|
343
|
+
|
|
344
|
+
// Expected output:
|
|
345
|
+
// Processing 3 examples...
|
|
346
|
+
//
|
|
347
|
+
// ── Example 0 (greet.ts) ──
|
|
348
|
+
// Fixed: true
|
|
349
|
+
// Attempts: 0
|
|
350
|
+
// Code: const greet = (name: string) => `Hello, ${name}!`;...
|
|
351
|
+
//
|
|
352
|
+
// ── Example 1 (add.js) ──
|
|
353
|
+
// Fixed: true
|
|
354
|
+
// Attempts: 1
|
|
355
|
+
// Code: const greet = (name: string) => `Hello, ${name}!`;...
|
|
356
|
+
//
|
|
357
|
+
// ── Example 2 (constants.ts) ──
|
|
358
|
+
// Fixed: true
|
|
359
|
+
// Attempts: 1
|
|
360
|
+
// Code: const greet = (name: string) => `Hello, ${name}!`;...
|
|
361
|
+
//
|
|
362
|
+
// ✅ 3/3 examples fixed successfully
|
|
363
|
+
} catch (error) {
|
|
364
|
+
console.error('Batch fix failed:', error instanceof Error ? error.message : error)
|
|
365
|
+
process.exit(1)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
main()
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### `createTypeScriptValidator`
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
function createTypeScriptValidator(): (code: string) => Promise<ValidationResult>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Use this to validate TypeScript code strings at runtime — perfect for checking LLM-generated code, user-submitted snippets, or dynamically built TypeScript before execution.
|
|
379
|
+
|
|
380
|
+
Returns a validator function that accepts a TypeScript code string and resolves with a `ValidationResult` indicating whether the code is valid and any diagnostic errors found.
|
|
381
|
+
|
|
382
|
+
#### Parameters
|
|
383
|
+
|
|
384
|
+
This factory function takes no parameters.
|
|
385
|
+
|
|
386
|
+
#### Returned Validator Function
|
|
387
|
+
|
|
388
|
+
| Name | Type | Required | Description |
|
|
389
|
+
|------|------|----------|-------------|
|
|
390
|
+
| `code` | `string` | ✅ | The TypeScript source code string to validate |
|
|
391
|
+
|
|
392
|
+
#### Returns
|
|
393
|
+
|
|
394
|
+
**`(code: string) => Promise<ValidationResult>`** — A reusable async validator function.
|
|
395
|
+
|
|
396
|
+
Each call to the validator returns a `Promise<ValidationResult>`:
|
|
397
|
+
|
|
398
|
+
| Field | Type | Description |
|
|
399
|
+
|-------|------|-------------|
|
|
400
|
+
| `valid` | `boolean` | `true` if the code compiled without errors |
|
|
401
|
+
| `errors` | `string[]` | List of TypeScript diagnostic messages; empty array if valid |
|
|
402
|
+
|
|
403
|
+
#### When results are returned
|
|
404
|
+
|
|
405
|
+
| Scenario | `valid` | `errors` |
|
|
406
|
+
|----------|---------|----------|
|
|
407
|
+
| Code compiles cleanly | `true` | `[]` |
|
|
408
|
+
| Type errors or syntax issues found | `false` | Array of diagnostic messages |
|
|
409
|
+
| Unexpected runtime failure | `false` | Single-element array with the caught error message |
|
|
410
|
+
|
|
411
|
+
**Example:**
|
|
412
|
+
|
|
413
|
+
```typescript example.ts
|
|
414
|
+
import * as ts from 'typescript'
|
|
415
|
+
|
|
416
|
+
// --- Inline types (do not import from autodocs) ---
|
|
417
|
+
interface ValidationResult {
|
|
418
|
+
valid: boolean
|
|
419
|
+
errors: string[]
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// --- Inline implementation matching the library's behavior ---
|
|
423
|
+
function createTypeScriptValidator(): (code: string) => Promise<ValidationResult> {
|
|
424
|
+
return async (code: string): Promise<ValidationResult> => {
|
|
425
|
+
try {
|
|
426
|
+
const diagnostics: string[] = []
|
|
427
|
+
|
|
428
|
+
const result = ts.transpileModule(code, {
|
|
429
|
+
compilerOptions: {
|
|
430
|
+
strict: true,
|
|
431
|
+
noImplicitAny: true,
|
|
432
|
+
target: ts.ScriptTarget.ES2020,
|
|
433
|
+
},
|
|
434
|
+
reportDiagnostics: true,
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
if (result.diagnostics && result.diagnostics.length > 0) {
|
|
438
|
+
for (const diag of result.diagnostics) {
|
|
439
|
+
const message =
|
|
440
|
+
typeof diag.messageText === 'string'
|
|
441
|
+
? diag.messageText
|
|
442
|
+
: diag.messageText.messageText
|
|
443
|
+
diagnostics.push(message)
|
|
444
|
+
}
|
|
445
|
+
return { valid: false, errors: diagnostics }
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return { valid: true, errors: [] }
|
|
449
|
+
} catch (err) {
|
|
450
|
+
return {
|
|
451
|
+
valid: false,
|
|
452
|
+
errors: [err instanceof Error ? err.message : String(err)],
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// --- Usage ---
|
|
459
|
+
const validate = createTypeScriptValidator()
|
|
460
|
+
|
|
461
|
+
async function main() {
|
|
462
|
+
try {
|
|
463
|
+
// ✅ Valid TypeScript
|
|
464
|
+
const validCode = `
|
|
465
|
+
const greet = (name: string): string => {
|
|
466
|
+
return \`Hello, \${name}!\`
|
|
467
|
+
}
|
|
468
|
+
console.log(greet('World'))
|
|
469
|
+
`
|
|
470
|
+
|
|
471
|
+
const validResult = await validate(validCode)
|
|
472
|
+
console.log('Valid code result:', validResult)
|
|
473
|
+
// Output: { valid: true, errors: [] }
|
|
474
|
+
|
|
475
|
+
// ❌ Invalid TypeScript — type mismatch
|
|
476
|
+
const invalidCode = `
|
|
477
|
+
const add = (a: number, b: number): number => {
|
|
478
|
+
return a + b
|
|
479
|
+
}
|
|
480
|
+
const result: string = add(1, 2)
|
|
481
|
+
`
|
|
482
|
+
|
|
483
|
+
const invalidResult = await validate(invalidCode)
|
|
484
|
+
console.log('Invalid code result:', invalidResult)
|
|
485
|
+
// Output: { valid: false, errors: ["Type 'number' is not assignable to type 'string'."] }
|
|
486
|
+
|
|
487
|
+
// ❌ Syntax error
|
|
488
|
+
const brokenCode = `
|
|
489
|
+
function broken( {
|
|
490
|
+
return 42
|
|
491
|
+
`
|
|
492
|
+
|
|
493
|
+
const brokenResult = await validate(brokenCode)
|
|
494
|
+
console.log('Broken code result:', brokenResult)
|
|
495
|
+
// Output: { valid: false, errors: ["',' expected.", ...] }
|
|
496
|
+
|
|
497
|
+
} catch (error) {
|
|
498
|
+
console.error('Unexpected failure:', error)
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
main()
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### `createPythonValidator`
|
|
506
|
+
|
|
507
|
+
```typescript
|
|
508
|
+
function createPythonValidator(): (code: string) => Promise<ValidationResult>
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Use this to validate Python code syntax and catch errors before execution, without needing a Python runtime wrapper or external validation service — just `python3` in your PATH.
|
|
512
|
+
|
|
513
|
+
Returns a reusable validator function you can call repeatedly with different code strings. Each call spawns a `python3` process to perform real syntax checking.
|
|
514
|
+
|
|
515
|
+
#### Parameters
|
|
516
|
+
|
|
517
|
+
This factory function takes no parameters.
|
|
518
|
+
|
|
519
|
+
#### Returns
|
|
520
|
+
|
|
521
|
+
| Return | Type | Description |
|
|
522
|
+
|--------|------|-------------|
|
|
523
|
+
| validator | `(code: string) => Promise<ValidationResult>` | Async function that validates a Python code string |
|
|
524
|
+
|
|
525
|
+
#### `ValidationResult` Shape
|
|
526
|
+
|
|
527
|
+
| Field | Type | Description |
|
|
528
|
+
|-------|------|-------------|
|
|
529
|
+
| `valid` | `boolean` | `true` if the code passed validation, `false` if errors were found |
|
|
530
|
+
| `errors` | `string[]` | List of error messages; empty array when `valid` is `true` |
|
|
531
|
+
|
|
532
|
+
#### When each value is returned
|
|
533
|
+
|
|
534
|
+
- **`valid: true`** — Python code is syntactically correct and parseable
|
|
535
|
+
- **`valid: false`** — Code contains syntax errors, indentation issues, or other parse-time problems; `errors` will contain the Python error output
|
|
536
|
+
|
|
537
|
+
#### Requirements
|
|
538
|
+
|
|
539
|
+
- `python3` must be available in your system `PATH`
|
|
540
|
+
- Works by writing code to a temp file and running `python3 -m py_compile` against it
|
|
541
|
+
|
|
542
|
+
**Example:**
|
|
543
|
+
|
|
544
|
+
```typescript example.ts
|
|
545
|
+
import { spawnSync } from 'child_process'
|
|
546
|
+
import { writeFileSync, unlinkSync } from 'fs'
|
|
547
|
+
import { join } from 'path'
|
|
548
|
+
import { tmpdir } from 'os'
|
|
549
|
+
|
|
550
|
+
// Inline the ValidationResult type (matches the library's shape)
|
|
551
|
+
type ValidationResult = {
|
|
552
|
+
valid: boolean
|
|
553
|
+
errors: string[]
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Self-contained implementation matching the library's behavior
|
|
557
|
+
function createPythonValidator(): (code: string) => Promise<ValidationResult> {
|
|
558
|
+
return async (code: string): Promise<ValidationResult> => {
|
|
559
|
+
const tmpFile = join(tmpdir(), `validate_${Date.now()}.py`)
|
|
560
|
+
|
|
561
|
+
try {
|
|
562
|
+
writeFileSync(tmpFile, code, 'utf8')
|
|
563
|
+
|
|
564
|
+
const result = spawnSync('python3', ['-m', 'py_compile', tmpFile], {
|
|
565
|
+
encoding: 'utf8',
|
|
566
|
+
timeout: 10_000,
|
|
567
|
+
})
|
|
568
|
+
|
|
569
|
+
if (result.status === 0) {
|
|
570
|
+
return { valid: true, errors: [] }
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const errorOutput = result.stderr || result.stdout || 'Unknown error'
|
|
574
|
+
// Strip the temp file path from error messages for cleaner output
|
|
575
|
+
const cleanedError = errorOutput.replace(tmpFile, '<code>')
|
|
576
|
+
return { valid: false, errors: [cleanedError.trim()] }
|
|
577
|
+
} catch (err) {
|
|
578
|
+
return {
|
|
579
|
+
valid: false,
|
|
580
|
+
errors: [`Validator error: ${err instanceof Error ? err.message : String(err)}`],
|
|
581
|
+
}
|
|
582
|
+
} finally {
|
|
583
|
+
try { unlinkSync(tmpFile) } catch { /* ignore cleanup errors */ }
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// --- Usage ---
|
|
589
|
+
|
|
590
|
+
const validate = createPythonValidator()
|
|
591
|
+
|
|
592
|
+
async function main() {
|
|
593
|
+
try {
|
|
594
|
+
// ✅ Valid Python
|
|
595
|
+
const validCode = `
|
|
596
|
+
def greet(name: str) -> str:
|
|
597
|
+
return f"Hello, {name}!"
|
|
598
|
+
|
|
599
|
+
print(greet("world"))
|
|
600
|
+
`.trim()
|
|
601
|
+
|
|
602
|
+
const validResult = await validate(validCode)
|
|
603
|
+
console.log('Valid code result:', validResult)
|
|
604
|
+
// Output: { valid: true, errors: [] }
|
|
605
|
+
|
|
606
|
+
// ❌ Invalid Python (bad indentation + missing colon)
|
|
607
|
+
const invalidCode = `
|
|
608
|
+
def broken(x)
|
|
609
|
+
return x * 2
|
|
610
|
+
`.trim()
|
|
611
|
+
|
|
612
|
+
const invalidResult = await validate(invalidCode)
|
|
613
|
+
console.log('Invalid code result:', invalidResult)
|
|
614
|
+
// Output: { valid: false, errors: [' File "<code>", line 1\n def broken(x)\n ^\nSyntaxError: expected \':\'' ] }
|
|
615
|
+
|
|
616
|
+
} catch (error) {
|
|
617
|
+
console.error('Unexpected failure:', error)
|
|
618
|
+
process.exit(1)
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
main()
|
|
623
|
+
```
|
|
624
|
+
|