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.
Files changed (95) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/index.d.ts +0 -1
  3. package/dist/auth/index.js +3 -5
  4. package/dist/autofix/index.js +15 -3
  5. package/dist/cli.js +19 -4
  6. package/dist/commands/check-links.js +164 -174
  7. package/dist/commands/deploy.js +5 -2
  8. package/dist/commands/generate.js +206 -199
  9. package/dist/commands/i18n.js +3 -20
  10. package/dist/commands/init.js +47 -40
  11. package/dist/commands/lint.js +3 -20
  12. package/dist/commands/mcp.js +125 -122
  13. package/dist/commands/monitor.js +125 -108
  14. package/dist/commands/review-pr.js +1 -1
  15. package/dist/commands/sdk.js +1 -1
  16. package/dist/config/loader.js +21 -2
  17. package/dist/generator/organizer.d.ts +3 -0
  18. package/dist/generator/organizer.js +4 -9
  19. package/dist/generator/writer.js +2 -10
  20. package/dist/github/pr-comments.js +21 -8
  21. package/dist/plugins/index.js +1 -0
  22. package/dist/scanner/index.js +8 -2
  23. package/dist/template/docs.json +2 -1
  24. package/dist/template/next.config.mjs +2 -1
  25. package/dist/template/package.json +17 -15
  26. package/dist/template/public/favicon.svg +4 -0
  27. package/dist/template/public/search-index.json +1 -1
  28. package/dist/template/scripts/build-search-index.mjs +120 -25
  29. package/dist/template/src/app/api/chat/route.ts +11 -3
  30. package/dist/template/src/app/docs/README.md +28 -0
  31. package/dist/template/src/app/docs/[...slug]/page.tsx +139 -16
  32. package/dist/template/src/app/docs/auth/page.mdx +589 -0
  33. package/dist/template/src/app/docs/autofix/page.mdx +624 -0
  34. package/dist/template/src/app/docs/cli/page.mdx +217 -0
  35. package/dist/template/src/app/docs/config/page.mdx +428 -0
  36. package/dist/template/src/app/docs/configuration/page.mdx +86 -0
  37. package/dist/template/src/app/docs/deployment/page.mdx +112 -0
  38. package/dist/template/src/app/docs/error.tsx +20 -0
  39. package/dist/template/src/app/docs/generator/generator.md +504 -0
  40. package/dist/template/src/app/docs/generator/organizer.md +779 -0
  41. package/dist/template/src/app/docs/generator/page.mdx +613 -0
  42. package/dist/template/src/app/docs/github/page.mdx +502 -0
  43. package/dist/template/src/app/docs/llm/anthropic-client.md +549 -0
  44. package/dist/template/src/app/docs/llm/index.md +471 -0
  45. package/dist/template/src/app/docs/llm/page.mdx +428 -0
  46. package/dist/template/src/app/docs/llms-full.md +256 -0
  47. package/dist/template/src/app/docs/llms.txt +2971 -0
  48. package/dist/template/src/app/docs/not-found.tsx +23 -0
  49. package/dist/template/src/app/docs/page.mdx +0 -3
  50. package/dist/template/src/app/docs/plugins/page.mdx +1793 -0
  51. package/dist/template/src/app/docs/pro/page.mdx +121 -0
  52. package/dist/template/src/app/docs/quickstart/page.mdx +93 -0
  53. package/dist/template/src/app/docs/scanner/content-type.md +599 -0
  54. package/dist/template/src/app/docs/scanner/index.md +212 -0
  55. package/dist/template/src/app/docs/scanner/page.mdx +307 -0
  56. package/dist/template/src/app/docs/scanner/python.md +469 -0
  57. package/dist/template/src/app/docs/scanner/python_parser.md +1056 -0
  58. package/dist/template/src/app/docs/scanner/rust.md +325 -0
  59. package/dist/template/src/app/docs/scanner/typescript.md +201 -0
  60. package/dist/template/src/app/error.tsx +3 -3
  61. package/dist/template/src/app/icon.tsx +29 -0
  62. package/dist/template/src/app/layout.tsx +42 -0
  63. package/dist/template/src/app/not-found.tsx +35 -0
  64. package/dist/template/src/app/page.tsx +62 -28
  65. package/dist/template/src/components/ai-chat.tsx +26 -21
  66. package/dist/template/src/components/breadcrumbs.tsx +46 -2
  67. package/dist/template/src/components/copy-button.tsx +17 -3
  68. package/dist/template/src/components/docs-layout.tsx +142 -8
  69. package/dist/template/src/components/feedback.tsx +4 -2
  70. package/dist/template/src/components/footer.tsx +42 -0
  71. package/dist/template/src/components/header.tsx +29 -5
  72. package/dist/template/src/components/mdx/accordion.tsx +7 -6
  73. package/dist/template/src/components/mdx/card.tsx +19 -7
  74. package/dist/template/src/components/mdx/code-block.tsx +17 -3
  75. package/dist/template/src/components/mdx/code-group.tsx +65 -18
  76. package/dist/template/src/components/mdx/code-playground.tsx +3 -0
  77. package/dist/template/src/components/mdx/go-playground.tsx +3 -0
  78. package/dist/template/src/components/mdx/highlighted-code.tsx +171 -76
  79. package/dist/template/src/components/mdx/python-playground.tsx +2 -0
  80. package/dist/template/src/components/mdx/tabs.tsx +74 -6
  81. package/dist/template/src/components/page-header.tsx +19 -0
  82. package/dist/template/src/components/scroll-to-top.tsx +33 -0
  83. package/dist/template/src/components/search-dialog.tsx +206 -52
  84. package/dist/template/src/components/sidebar.tsx +136 -77
  85. package/dist/template/src/components/table-of-contents.tsx +23 -7
  86. package/dist/template/src/lib/highlight.ts +90 -31
  87. package/dist/template/src/lib/search.ts +14 -4
  88. package/dist/template/src/lib/theme-utils.ts +140 -0
  89. package/dist/template/src/styles/globals.css +307 -166
  90. package/dist/template/src/types/remark-gfm.d.ts +2 -0
  91. package/dist/utils/files.d.ts +9 -0
  92. package/dist/utils/files.js +33 -0
  93. package/dist/utils/validation.d.ts +4 -0
  94. package/dist/utils/validation.js +38 -0
  95. package/package.json +1 -4
@@ -0,0 +1,212 @@
1
+ # Index.ts
2
+
3
+ ## Functions
4
+
5
+ ### `scanDirectory`
6
+
7
+ ```typescript
8
+ async function scanDirectory(dir: string, options: ScanOptions = {}): Promise<ScanAllResult>
9
+ ```
10
+
11
+ Use this to recursively scan a directory (or single file) and extract all API elements — functions, classes, types, and exports — across multiple languages including Python, TypeScript, JavaScript, Go, and Rust.
12
+
13
+ ## Parameters
14
+
15
+ | Name | Type | Required | Description |
16
+ |------|------|----------|-------------|
17
+ | `dir` | `string` | ✅ Yes | Path to the directory or single file to scan |
18
+ | `options` | `ScanOptions` | ❌ No | Configuration options to control which files are included or excluded |
19
+ | `options.include` | `string[]` | ❌ No | Glob patterns for files to scan. Defaults to `['**/*.py', '**/*.ts', '**/*.js', '**/*.go', '**/*.rs']` |
20
+ | `options.exclude` | `string[]` | ❌ No | Glob patterns for files to skip. Defaults to `['**/node_modules/**', '**/__pycache__/**', '**/dist/**']` |
21
+
22
+ ## Returns
23
+
24
+ Returns a `Promise<ScanAllResult>` that resolves to an object containing all discovered API elements grouped by file. Rejects if the provided path does not exist or cannot be read.
25
+
26
+ | Field | Type | Description |
27
+ |-------|------|-------------|
28
+ | `files` | `ScanResult[]` | Array of per-file scan results, each containing extracted API elements |
29
+ | `totalFiles` | `number` | Total number of files successfully scanned |
30
+ | `errors` | `string[]` | Any non-fatal errors encountered during scanning |
31
+
32
+ ## Notes
33
+
34
+ - Passing a **single file path** instead of a directory is supported — the scanner will detect the file extension and apply the appropriate language parser.
35
+ - Files matching `exclude` patterns are silently skipped and do not appear in `errors`.
36
+ - Use `options.include` to narrow scans to a specific language (e.g., `['**/*.ts']`) for faster results in large monorepos.
37
+
38
+ ### `scanFile`
39
+
40
+ ```typescript
41
+ async function scanFile(filePath: string): Promise<ScanResult>
42
+ ```
43
+
44
+ Use this to analyze a single source file and extract structured metadata — functions, classes, types, and other code constructs — without scanning an entire directory.
45
+
46
+ `scanFile` automatically detects the file's language, selects the appropriate scanner, and returns a normalized `ScanResult` regardless of whether the file is Python, TypeScript, or another supported language.
47
+
48
+ ## Parameters
49
+
50
+ | Name | Type | Required | Description |
51
+ |------|------|----------|-------------|
52
+ | `filePath` | `string` | ✅ | Absolute or relative path to the source file to scan |
53
+
54
+ ## Returns
55
+
56
+ Returns `Promise<ScanResult>` — resolves with a structured result containing:
57
+
58
+ | Field | Type | Description |
59
+ |-------|------|-------------|
60
+ | `filePath` | `string` | The original file path passed in |
61
+ | `language` | `string` | Detected language (`"typescript"`, `"python"`, etc.) |
62
+ | `functions` | `FunctionInfo[]` | All top-level and exported functions found |
63
+ | `classes` | `ClassInfo[]` | All class definitions found |
64
+ | `exports` | `string[]` | Named exports from the file |
65
+ | `errors` | `string[]` | Any parse errors encountered (non-fatal) |
66
+
67
+ > **Note:** If no scanner is found for the file extension, `scanFile` returns a default result with an empty `functions` and `classes` array rather than throwing. Always check `errors` for partial failures.
68
+
69
+ **Example:**
70
+
71
+ ```typescript example.ts
72
+ // Inline types to simulate the autodocs ScanResult shape
73
+ type FunctionInfo = {
74
+ name: string
75
+ signature: string
76
+ docstring?: string
77
+ lineStart: number
78
+ lineEnd: number
79
+ }
80
+
81
+ type ClassInfo = {
82
+ name: string
83
+ methods: FunctionInfo[]
84
+ lineStart: number
85
+ lineEnd: number
86
+ }
87
+
88
+ type ScanResult = {
89
+ filePath: string
90
+ language: string
91
+ functions: FunctionInfo[]
92
+ classes: ClassInfo[]
93
+ exports: string[]
94
+ errors: string[]
95
+ }
96
+
97
+ // Simulated scanner implementations (mirrors autodocs internal behavior)
98
+ const LANGUAGE_MAP: Record<string, string> = {
99
+ '.ts': 'typescript',
100
+ '.tsx': 'typescript',
101
+ '.js': 'javascript',
102
+ '.py': 'python',
103
+ }
104
+
105
+ function detectLanguage(filePath: string): string {
106
+ const ext = filePath.slice(filePath.lastIndexOf('.'))
107
+ return LANGUAGE_MAP[ext] ?? 'unknown'
108
+ }
109
+
110
+ // Simulated scanFile — mirrors the real function's behavior
111
+ async function scanFile(filePath: string): Promise<ScanResult> {
112
+ const language = detectLanguage(filePath)
113
+
114
+ if (language === 'unknown') {
115
+ // Unsupported file type: return a safe default (no throw)
116
+ return {
117
+ filePath,
118
+ language: 'unknown',
119
+ functions: [],
120
+ classes: [],
121
+ exports: [],
122
+ errors: [`No scanner available for file: ${filePath}`],
123
+ }
124
+ }
125
+
126
+ // Simulate parsed output for a TypeScript file
127
+ if (language === 'typescript') {
128
+ return {
129
+ filePath,
130
+ language: 'typescript',
131
+ functions: [
132
+ {
133
+ name: 'getUserById',
134
+ signature: 'async function getUserById(id: string): Promise<User>',
135
+ docstring: 'Fetch a user record by their unique ID.',
136
+ lineStart: 12,
137
+ lineEnd: 24,
138
+ },
139
+ {
140
+ name: 'formatUserName',
141
+ signature: 'function formatUserName(user: User): string',
142
+ lineStart: 26,
143
+ lineEnd: 31,
144
+ },
145
+ ],
146
+ classes: [
147
+ {
148
+ name: 'UserService',
149
+ methods: [
150
+ {
151
+ name: 'create',
152
+ signature: 'async create(data: CreateUserDto): Promise<User>',
153
+ lineStart: 45,
154
+ lineEnd: 58,
155
+ },
156
+ ],
157
+ lineStart: 40,
158
+ lineEnd: 80,
159
+ },
160
+ ],
161
+ exports: ['getUserById', 'formatUserName', 'UserService'],
162
+ errors: [],
163
+ }
164
+ }
165
+
166
+ // Fallback for other supported languages
167
+ return {
168
+ filePath,
169
+ language,
170
+ functions: [],
171
+ classes: [],
172
+ exports: [],
173
+ errors: [],
174
+ }
175
+ }
176
+
177
+ // --- Usage ---
178
+ async function main() {
179
+ const targetFile = process.env.SCAN_TARGET || './src/users/userService.ts'
180
+
181
+ try {
182
+ console.log(`Scanning: ${targetFile}\n`)
183
+ const result = await scanFile(targetFile)
184
+
185
+ console.log(`Language: ${result.language}`)
186
+ console.log(`Functions: ${result.functions.length}`)
187
+ console.log(`Classes: ${result.classes.length}`)
188
+ console.log(`Exports: ${result.exports.join(', ')}`)
189
+
190
+ if (result.errors.length > 0) {
191
+ console.warn('Scan warnings:', result.errors)
192
+ }
193
+
194
+ console.log('\nFull result:')
195
+ console.log(JSON.stringify(result, null, 2))
196
+
197
+ // Expected output:
198
+ // Language: typescript
199
+ // Functions: 2
200
+ // Classes: 1
201
+ // Exports: getUserById, formatUserName, UserService
202
+ } catch (error) {
203
+ // scanFile itself won't throw for unsupported files,
204
+ // but may throw on filesystem errors (file not found, permission denied)
205
+ console.error('Scan failed unexpectedly:', error)
206
+ process.exit(1)
207
+ }
208
+ }
209
+
210
+ main()
211
+ ```
212
+
@@ -0,0 +1,307 @@
1
+ ## Classes
2
+
3
+ ### `GoScanner`
4
+
5
+ ```typescript
6
+ class GoScanner implements Scanner
7
+ ```
8
+
9
+ Use this to scan Go source files and extract API elements — functions, methods, structs, and interfaces — for automated documentation generation pipelines.
10
+
11
+ `GoScanner` implements the `Scanner` interface and targets `.go` files, automatically skipping test files (`_test.go`).
12
+
13
+ ## Methods
14
+
15
+ ### `canHandle(filePath: string): boolean`
16
+ Returns `true` if the file path ends in `.go` and is not a test file. Use this to check compatibility before scanning.
17
+
18
+ ### `scanFile(filePath: string): Promise<ScanResult>`
19
+ Reads and parses a Go source file, returning all discovered API elements.
20
+
21
+ | Name | Type | Required | Description |
22
+ |------|------|----------|-------------|
23
+ | `filePath` | `string` | ✅ | Absolute or relative path to the `.go` source file to scan |
24
+
25
+ #### Returns
26
+
27
+ `scanFile` returns a `Promise<ScanResult>` containing:
28
+
29
+ | Field | Type | Description |
30
+ |-------|------|-------------|
31
+ | `elements` | `APIElement[]` | All extracted functions, methods, types, and interfaces |
32
+ | `filePath` | `string` | The path of the scanned file |
33
+ | `language` | `string` | Always `"go"` for this scanner |
34
+
35
+ Each `APIElement` includes:
36
+
37
+ | Field | Type | Description |
38
+ |-------|------|-------------|
39
+ | `name` | `string` | Identifier name (e.g. `"NewServer"`) |
40
+ | `kind` | `string` | One of `"function"`, `"method"`, `"type"`, `"interface"` |
41
+ | `signature` | `string` | Full Go signature string |
42
+ | `parameters` | `Parameter[]` | Parsed parameter list |
43
+ | `docstring` | `string \| undefined` | Leading comment block, if present |
44
+
45
+ ## Notes
46
+ - Test files (`*_test.go`) are **automatically excluded** — `canHandle` returns `false` for them
47
+ - `languages` property is `['go']`, used by scanner registries to route files to the correct handler
48
+ - Throws if the file cannot be read (e.g. missing file, permission error)
49
+
50
+ ### Methods
51
+
52
+ #### `canHandle`
53
+
54
+ ```typescript
55
+ canHandle(filePath: string): boolean
56
+ ```
57
+
58
+ Use this to check whether a Go source file should be processed by the `GoScanner` — it returns `true` for `.go` files that are **not** test files (`_test.go`).
59
+
60
+ This is useful when routing files through a scanner pipeline, letting you skip unsupported or test files before attempting a full scan.
61
+
62
+ ### Parameters
63
+
64
+ | Name | Type | Required | Description |
65
+ |------|------|----------|-------------|
66
+ | `filePath` | `string` | ✅ | Absolute or relative path to the file being evaluated |
67
+
68
+ #### Returns
69
+
70
+ | Value | Condition |
71
+ |-------|-----------|
72
+ | `true` | File ends in `.go` **and** does not contain `_test.go` |
73
+ | `false` | File is not a `.go` file, or is a Go test file (`_test.go`) |
74
+
75
+ ### Notes
76
+ - Test files (e.g., `auth_test.go`, `parser_test.go`) are explicitly excluded and return `false`
77
+ - Only the file path string is checked — no filesystem access occurs
78
+
79
+ **Example:**
80
+
81
+ ```typescript example.ts
82
+ // Inline implementation of GoScanner.canHandle for a self-contained example
83
+ class GoScanner {
84
+ languages = ['go']
85
+
86
+ canHandle(filePath: string): boolean {
87
+ return /\.go$/.test(filePath) && !filePath.includes('_test.go')
88
+ }
89
+ }
90
+
91
+ const scanner = new GoScanner()
92
+
93
+ const testCases: Array<{ path: string; expected: boolean; label: string }> = [
94
+ { path: 'internal/auth/handler.go', expected: true, label: 'standard Go source file' },
95
+ { path: 'internal/auth/handler_test.go', expected: false, label: 'Go test file (excluded)' },
96
+ { path: 'cmd/main.go', expected: true, label: 'main package file' },
97
+ { path: 'src/utils/parser.ts', expected: false, label: 'TypeScript file (wrong ext)' },
98
+ { path: 'README.md', expected: false, label: 'markdown file' },
99
+ { path: 'pkg/models/user_test.go', expected: false, label: 'nested test file (excluded)' },
100
+ ]
101
+
102
+ try {
103
+ console.log('GoScanner.canHandle() results:\n')
104
+
105
+ for (const { path, expected, label } of testCases) {
106
+ const result = scanner.canHandle(path)
107
+ const status = result === expected ? '✅' : '❌'
108
+ console.log(`${status} ${label}`)
109
+ console.log(` Path: ${path}`)
110
+ console.log(` Returns: ${result}\n`)
111
+ }
112
+
113
+ // Typical use in a file-routing pipeline
114
+ const filesToProcess = [
115
+ 'pkg/api/routes.go',
116
+ 'pkg/api/routes_test.go',
117
+ 'pkg/api/middleware.go',
118
+ 'docs/overview.md',
119
+ ]
120
+
121
+ const scannable = filesToProcess.filter(f => scanner.canHandle(f))
122
+ console.log('Files queued for scanning:', scannable)
123
+ // Output: [ 'pkg/api/routes.go', 'pkg/api/middleware.go' ]
124
+
125
+ } catch (error) {
126
+ console.error('Unexpected error during canHandle check:', error)
127
+ }
128
+ ```
129
+
130
+ #### `scanFile`
131
+
132
+ ```typescript
133
+ async scanFile(filePath: string): Promise<ScanResult>
134
+ ```
135
+
136
+ Use this to extract API elements from a Go source file, returning all discovered functions, types, and parameters in a structured result.
137
+
138
+ `scanFile` reads and parses a `.go` file (excluding test files), identifying exported API elements and collecting any parse errors encountered during scanning.
139
+
140
+ > **Note:** Only handles non-test Go files (`.go` extension, not `_test.go`). Use `canHandle(filePath)` to verify compatibility before calling.
141
+
142
+ #### Parameters
143
+
144
+ | Name | Type | Required | Description |
145
+ |------|------|----------|-------------|
146
+ | `filePath` | `string` | ✅ | Absolute or relative path to the `.go` source file to scan |
147
+
148
+ #### Returns
149
+
150
+ Returns a `Promise<ScanResult>` that resolves to:
151
+
152
+ | Field | Type | Description |
153
+ |-------|------|-------------|
154
+ | `elements` | `APIElement[]` | All discovered API elements (functions, types, etc.) |
155
+ | `errors` | `string[]` | Non-fatal parse errors encountered during scanning |
156
+ | `filePath` | `string` | The original file path that was scanned |
157
+
158
+ **Throws** if the file cannot be read (e.g., file not found, permission denied).
159
+
160
+ **Example:**
161
+
162
+ ```typescript example.ts
163
+ import { readFileSync, writeFileSync, unlinkSync } from 'fs'
164
+ import { tmpdir } from 'os'
165
+ import { join } from 'path'
166
+
167
+ // --- Inline types (mirrors the real library's types) ---
168
+ interface Parameter {
169
+ name: string
170
+ type: string
171
+ }
172
+
173
+ interface APIElement {
174
+ name: string
175
+ kind: 'function' | 'type' | 'method'
176
+ parameters: Parameter[]
177
+ returnType?: string
178
+ doc?: string
179
+ }
180
+
181
+ interface ScanResult {
182
+ filePath: string
183
+ elements: APIElement[]
184
+ errors: string[]
185
+ }
186
+
187
+ // --- Self-contained GoScanner implementation ---
188
+ class GoScanner {
189
+ canHandle(filePath: string): boolean {
190
+ return /\.go$/.test(filePath) && !filePath.includes('_test.go')
191
+ }
192
+
193
+ async scanFile(filePath: string): Promise<ScanResult> {
194
+ const source = readFileSync(filePath, 'utf-8')
195
+ const elements: APIElement[] = []
196
+ const errors: string[] = []
197
+ const lines = source.split('\n')
198
+
199
+ // Match exported Go functions: func FuncName(params) returnType
200
+ const funcRegex = /^func\s+([A-Z][a-zA-Z0-9]*)\s*\(([^)]*)\)\s*([^\s{]*)/
201
+ // Match exported types: type TypeName struct/interface
202
+ const typeRegex = /^type\s+([A-Z][a-zA-Z0-9]*)\s+(struct|interface)/
203
+
204
+ for (let i = 0; i < lines.length; i++) {
205
+ const line = lines[i].trim()
206
+
207
+ const funcMatch = funcRegex.exec(line)
208
+ if (funcMatch) {
209
+ const [, name, rawParams, returnType] = funcMatch
210
+ const parameters: Parameter[] = rawParams
211
+ .split(',')
212
+ .map(p => p.trim())
213
+ .filter(Boolean)
214
+ .map(p => {
215
+ const parts = p.split(/\s+/)
216
+ return parts.length >= 2
217
+ ? { name: parts[0], type: parts[1] }
218
+ : { name: p, type: 'unknown' }
219
+ })
220
+
221
+ elements.push({ name, kind: 'function', parameters, returnType: returnType || 'void' })
222
+ continue
223
+ }
224
+
225
+ const typeMatch = typeRegex.exec(line)
226
+ if (typeMatch) {
227
+ const [, name] = typeMatch
228
+ elements.push({ name, kind: 'type', parameters: [] })
229
+ }
230
+ }
231
+
232
+ return { filePath, elements, errors }
233
+ }
234
+ }
235
+
236
+ // --- Example usage ---
237
+ const sampleGoSource = `
238
+ package api
239
+
240
+ // UserService handles user operations.
241
+ type UserService struct{}
242
+
243
+ // GetUser retrieves a user by ID.
244
+ func GetUser(id string, includeDeleted bool) error {
245
+ return nil
246
+ }
247
+
248
+ // CreateUser adds a new user to the system.
249
+ func CreateUser(name string, age int) string {
250
+ return ""
251
+ }
252
+ `
253
+
254
+ async function main() {
255
+ // Write a temporary .go file to scan
256
+ const tmpFile = join(tmpdir(), 'example_service.go')
257
+
258
+ try {
259
+ writeFileSync(tmpFile, sampleGoSource, 'utf-8')
260
+
261
+ const scanner = new GoScanner()
262
+
263
+ // Verify the file is compatible before scanning
264
+ if (!scanner.canHandle(tmpFile)) {
265
+ throw new Error(`File is not a scannable Go source: ${tmpFile}`)
266
+ }
267
+
268
+ const result = await scanner.scanFile(tmpFile)
269
+
270
+ console.log('Scanned file:', result.filePath)
271
+ console.log(`Found ${result.elements.length} API elements:\n`)
272
+
273
+ for (const el of result.elements) {
274
+ if (el.kind === 'function') {
275
+ const params = el.parameters.map(p => `${p.name} ${p.type}`).join(', ')
276
+ console.log(` [${el.kind}] ${el.name}(${params}) → ${el.returnType}`)
277
+ } else {
278
+ console.log(` [${el.kind}] ${el.name}`)
279
+ }
280
+ }
281
+
282
+ if (result.errors.length > 0) {
283
+ console.warn('\nParse errors:', result.errors)
284
+ }
285
+
286
+ // Expected output:
287
+ // Scanned file: /tmp/example_service.go
288
+ // Found 3 API elements:
289
+ // [type] UserService
290
+ // [function] GetUser(id string, includeDeleted bool) → error
291
+ // [function] CreateUser(name string, age int) → string
292
+
293
+ } catch (error) {
294
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
295
+ console.error('File not found - check the path and try again')
296
+ } else {
297
+ console.error('Scan failed:', error)
298
+ }
299
+ } finally {
300
+ // Clean up temp file
301
+ try { unlinkSync(tmpFile) } catch {}
302
+ }
303
+ }
304
+
305
+ main()
306
+ ```
307
+