skrypt-ai 0.3.3 → 0.4.0

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 (97) 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 +3 -1
  25. package/dist/template/package.json +17 -14
  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 +141 -14
  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 +57 -7
  63. package/dist/template/src/app/not-found.tsx +35 -0
  64. package/dist/template/src/app/page.tsx +95 -11
  65. package/dist/template/src/components/ai-chat.tsx +26 -21
  66. package/dist/template/src/components/breadcrumbs.tsx +56 -12
  67. package/dist/template/src/components/copy-button.tsx +17 -3
  68. package/dist/template/src/components/docs-layout.tsx +202 -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 +56 -20
  72. package/dist/template/src/components/mdx/accordion.tsx +17 -13
  73. package/dist/template/src/components/mdx/callout.tsx +50 -37
  74. package/dist/template/src/components/mdx/card.tsx +24 -12
  75. package/dist/template/src/components/mdx/code-block.tsx +17 -3
  76. package/dist/template/src/components/mdx/code-group.tsx +78 -18
  77. package/dist/template/src/components/mdx/code-playground.tsx +3 -0
  78. package/dist/template/src/components/mdx/go-playground.tsx +3 -0
  79. package/dist/template/src/components/mdx/highlighted-code.tsx +178 -38
  80. package/dist/template/src/components/mdx/python-playground.tsx +2 -0
  81. package/dist/template/src/components/mdx/steps.tsx +6 -6
  82. package/dist/template/src/components/mdx/tabs.tsx +76 -8
  83. package/dist/template/src/components/page-header.tsx +19 -0
  84. package/dist/template/src/components/scroll-to-top.tsx +33 -0
  85. package/dist/template/src/components/search-dialog.tsx +251 -57
  86. package/dist/template/src/components/sidebar.tsx +137 -77
  87. package/dist/template/src/components/table-of-contents.tsx +29 -13
  88. package/dist/template/src/lib/highlight.ts +90 -31
  89. package/dist/template/src/lib/search.ts +14 -4
  90. package/dist/template/src/lib/theme-utils.ts +140 -0
  91. package/dist/template/src/styles/globals.css +397 -84
  92. package/dist/template/src/types/remark-gfm.d.ts +2 -0
  93. package/dist/utils/files.d.ts +9 -0
  94. package/dist/utils/files.js +33 -0
  95. package/dist/utils/validation.d.ts +4 -0
  96. package/dist/utils/validation.js +38 -0
  97. package/package.json +1 -4
@@ -0,0 +1,504 @@
1
+ # Generator.ts
2
+
3
+ ## Functions
4
+
5
+ ### `generateForElement`
6
+
7
+ ```typescript
8
+ async function generateForElement(element: APIElement, client: LLMClient, options: GenerationOptions, onProgress?: (progress: GenerationProgress) => void): Promise<GeneratedDoc>
9
+ ```
10
+
11
+ Use this to generate documentation for a single API element using an LLM client, without running any test validation on the output.
12
+
13
+ This is the core documentation generation function — pass it a parsed API element (function, class, type, etc.), an LLM client, and generation options to receive structured documentation. Optionally track progress in real time via the `onProgress` callback.
14
+
15
+ ## Parameters
16
+
17
+ | Name | Type | Required | Description |
18
+ |------|------|----------|-------------|
19
+ | `element` | `APIElement` | ✅ | The parsed API element to document (function, class, interface, etc.) |
20
+ | `client` | `LLMClient` | ✅ | Configured LLM client used to generate the documentation |
21
+ | `options` | `GenerationOptions` | ✅ | Controls generation behavior: model, style, language, max tokens, etc. |
22
+ | `onProgress` | `(progress: GenerationProgress) => void` | ❌ | Optional callback invoked during generation to report progress stages |
23
+
24
+ ## Returns
25
+
26
+ Returns a `Promise<GeneratedDoc>` that resolves to a structured documentation object containing:
27
+
28
+ | Field | Description |
29
+ |-------|-------------|
30
+ | `markdown` | The generated documentation as a markdown string |
31
+ | `element` | Reference back to the source `APIElement` |
32
+ | `metadata` | Generation metadata (model used, token counts, timestamp) |
33
+
34
+ Rejects with an error if the LLM client fails or the element cannot be processed.
35
+
36
+ **Example:**
37
+
38
+ ```typescript example.ts
39
+ // ─── Inline type definitions (no external imports needed) ───────────────────
40
+
41
+ type APIElement = {
42
+ name: string
43
+ kind: 'function' | 'class' | 'interface' | 'type'
44
+ signature: string
45
+ docstring?: string
46
+ filePath: string
47
+ }
48
+
49
+ type GenerationOptions = {
50
+ model: string
51
+ style: 'concise' | 'detailed'
52
+ language: 'typescript' | 'javascript'
53
+ maxTokens?: number
54
+ }
55
+
56
+ type GenerationProgress = {
57
+ stage: 'preparing' | 'generating' | 'formatting' | 'complete'
58
+ percentComplete: number
59
+ message: string
60
+ }
61
+
62
+ type GeneratedDoc = {
63
+ markdown: string
64
+ element: APIElement
65
+ metadata: {
66
+ model: string
67
+ tokensUsed: number
68
+ generatedAt: string
69
+ }
70
+ }
71
+
72
+ type LLMClient = {
73
+ apiKey: string
74
+ baseUrl: string
75
+ complete: (prompt: string, maxTokens: number) => Promise<string>
76
+ }
77
+
78
+ // ─── Simulated implementations ───────────────────────────────────────────────
79
+
80
+ function createLLMClient(apiKey: string): LLMClient {
81
+ return {
82
+ apiKey,
83
+ baseUrl: 'https://api.openai.com/v1',
84
+ complete: async (prompt: string, maxTokens: number): Promise<string> => {
85
+ // Simulates an LLM response for demonstration
86
+ return `Use this to calculate the total price including tax.\n\n**Parameters:**\n- \`price\`: number — base price\n- \`taxRate\`: number — tax rate as a decimal\n\n**Returns:** \`number\` — final price with tax applied`
87
+ }
88
+ }
89
+ }
90
+
91
+ async function generateForElement(
92
+ element: APIElement,
93
+ client: LLMClient,
94
+ options: GenerationOptions,
95
+ onProgress?: (progress: GenerationProgress) => void
96
+ ): Promise<GeneratedDoc> {
97
+ const reportProgress = (stage: GenerationProgress['stage'], percent: number, message: string) => {
98
+ onProgress?.({ stage, percentComplete: percent, message })
99
+ }
100
+
101
+ reportProgress('preparing', 10, `Preparing context for "${element.name}"`)
102
+ await new Promise(r => setTimeout(r, 50)) // simulate async work
103
+
104
+ reportProgress('generating', 40, `Sending "${element.name}" to ${options.model}`)
105
+ const prompt = `Generate ${options.style} documentation for:\n${element.signature}`
106
+ const rawDoc = await client.complete(prompt, options.maxTokens ?? 1024)
107
+
108
+ reportProgress('formatting', 80, 'Formatting output')
109
+ await new Promise(r => setTimeout(r, 30))
110
+
111
+ reportProgress('complete', 100, 'Documentation generated successfully')
112
+
113
+ return {
114
+ markdown: rawDoc,
115
+ element,
116
+ metadata: {
117
+ model: options.model,
118
+ tokensUsed: rawDoc.split(' ').length * 2, // rough estimate for demo
119
+ generatedAt: new Date().toISOString()
120
+ }
121
+ }
122
+ }
123
+
124
+ // ─── Usage example ────────────────────────────────────────────────────────────
125
+
126
+ const apiElement: APIElement = {
127
+ name: 'calculateTotalPrice',
128
+ kind: 'function',
129
+ signature: 'function calculateTotalPrice(price: number, taxRate: number): number',
130
+ docstring: 'Calculates the total price including tax.',
131
+ filePath: 'src/pricing/utils.ts'
132
+ }
133
+
134
+ const client = createLLMClient(process.env.OPENAI_API_KEY || 'sk-your-api-key-here')
135
+
136
+ const options: GenerationOptions = {
137
+ model: 'gpt-4o',
138
+ style: 'detailed',
139
+ language: 'typescript',
140
+ maxTokens: 512
141
+ }
142
+
143
+ async function main() {
144
+ try {
145
+ console.log(`Generating docs for: ${apiElement.name}\n`)
146
+
147
+ const doc = await generateForElement(
148
+ apiElement,
149
+ client,
150
+ options,
151
+ (progress: GenerationProgress) => {
152
+ console.log(`[${progress.percentComplete}%] ${progress.stage}: ${progress.message}`)
153
+ }
154
+ )
155
+
156
+ console.log('\n─── Generated Documentation ───────────────────────────')
157
+ console.log(doc.markdown)
158
+ console.log('\n─── Metadata ──────────────────────────────────────────')
159
+ console.log(`Model: ${doc.metadata.model}`)
160
+ console.log(`Tokens used: ${doc.metadata.tokensUsed}`)
161
+ console.log(`Generated at: ${doc.metadata.generatedAt}`)
162
+
163
+ // Expected output:
164
+ // [10%] preparing: Preparing context for "calculateTotalPrice"
165
+ // [40%] generating: Sending "calculateTotalPrice" to gpt-4o
166
+ // [80%] formatting: Formatting output
167
+ // [100%] complete: Documentation generated successfully
168
+ //
169
+ // ─── Generated Documentation ───
170
+ // Use this to calculate the total price including tax.
171
+ // ...
172
+ } catch (error) {
173
+ console.error('Documentation generation failed:', error)
174
+ process.exit(1)
175
+ }
176
+ }
177
+
178
+ main()
179
+ ```
180
+
181
+ ### `generateForElements`
182
+
183
+ ```typescript
184
+ async function generateForElements(elements: APIElement[], client: LLMClient, options: GenerationOptions): Promise<GeneratedDoc[]>
185
+ ```
186
+
187
+ Use this to batch-generate documentation for multiple API elements in a single call, processing an entire scanned API surface and returning structured docs for each element.
188
+
189
+ This is the primary entry point for bulk documentation generation — pass in your parsed API elements, an LLM client, and generation options to get back a full array of generated documentation objects.
190
+
191
+ ## Parameters
192
+
193
+ | Name | Type | Required | Description |
194
+ |------|------|----------|-------------|
195
+ | `elements` | `APIElement[]` | Yes | Array of parsed API elements (functions, classes, types, etc.) to generate docs for |
196
+ | `client` | `LLMClient` | Yes | Configured LLM client used to generate the documentation content |
197
+ | `options` | `GenerationOptions` | Yes | Controls generation behavior: model selection, output format, concurrency, etc. |
198
+
199
+ ## Returns
200
+
201
+ Returns `Promise<GeneratedDoc[]>` — resolves to an array of generated documentation objects, one per input element, in the same order as the input `elements` array.
202
+
203
+ | Scenario | Result |
204
+ |----------|--------|
205
+ | All elements processed successfully | Array of `GeneratedDoc` objects with markdown/content for each element |
206
+ | Empty `elements` array | Resolves to `[]` |
207
+ | LLM client error on an element | Rejects or returns partial results depending on `options.onError` strategy |
208
+
209
+ **Example:**
210
+
211
+ ```typescript example.ts
212
+ // ─── Inline type definitions (no external imports needed) ───────────────────
213
+
214
+ type APIElement = {
215
+ name: string
216
+ kind: 'function' | 'class' | 'type' | 'interface' | 'variable'
217
+ signature: string
218
+ docstring?: string
219
+ filePath: string
220
+ }
221
+
222
+ type GeneratedDoc = {
223
+ elementName: string
224
+ kind: APIElement['kind']
225
+ markdown: string
226
+ generatedAt: Date
227
+ }
228
+
229
+ type GenerationOptions = {
230
+ model?: string
231
+ maxConcurrency?: number
232
+ outputFormat?: 'markdown' | 'html'
233
+ onError?: 'skip' | 'throw'
234
+ }
235
+
236
+ type LLMClient = {
237
+ apiKey: string
238
+ baseUrl: string
239
+ complete: (prompt: string) => Promise<string>
240
+ }
241
+
242
+ // ─── Simulated implementation of generateForElements ────────────────────────
243
+
244
+ async function generateForElements(
245
+ elements: APIElement[],
246
+ client: LLMClient,
247
+ options: GenerationOptions
248
+ ): Promise<GeneratedDoc[]> {
249
+ const {
250
+ maxConcurrency = 3,
251
+ outputFormat = 'markdown',
252
+ onError = 'skip',
253
+ } = options
254
+
255
+ const results: GeneratedDoc[] = []
256
+
257
+ // Process in batches to respect maxConcurrency
258
+ for (let i = 0; i < elements.length; i += maxConcurrency) {
259
+ const batch = elements.slice(i, i + maxConcurrency)
260
+
261
+ const batchResults = await Promise.allSettled(
262
+ batch.map(async (element) => {
263
+ const prompt = `Generate ${outputFormat} documentation for: ${element.signature}`
264
+
265
+ try {
266
+ const content = await client.complete(prompt)
267
+ return {
268
+ elementName: element.name,
269
+ kind: element.kind,
270
+ markdown: content,
271
+ generatedAt: new Date(),
272
+ } satisfies GeneratedDoc
273
+ } catch (err) {
274
+ if (onError === 'throw') throw err
275
+ console.warn(`Skipping ${element.name} due to error:`, err)
276
+ return null
277
+ }
278
+ })
279
+ )
280
+
281
+ for (const result of batchResults) {
282
+ if (result.status === 'fulfilled' && result.value !== null) {
283
+ results.push(result.value)
284
+ }
285
+ }
286
+ }
287
+
288
+ return results
289
+ }
290
+
291
+ // ─── Simulated LLM client (replace complete() with real API call) ────────────
292
+
293
+ function createLLMClient(apiKey: string): LLMClient {
294
+ return {
295
+ apiKey,
296
+ baseUrl: 'https://api.openai.com/v1',
297
+ complete: async (prompt: string): Promise<string> => {
298
+ // Simulate LLM latency
299
+ await new Promise((r) => setTimeout(r, 50))
300
+ return `**Auto-generated doc**\n\nPrompt received: "${prompt.slice(0, 60)}..."`
301
+ },
302
+ }
303
+ }
304
+
305
+ // ─── Example usage ───────────────────────────────────────────────────────────
306
+
307
+ const elements: APIElement[] = [
308
+ {
309
+ name: 'fetchUser',
310
+ kind: 'function',
311
+ signature: 'async function fetchUser(id: string): Promise<User>',
312
+ docstring: 'Fetches a user by ID',
313
+ filePath: 'src/api/users.ts',
314
+ },
315
+ {
316
+ name: 'UserService',
317
+ kind: 'class',
318
+ signature: 'class UserService { constructor(db: Database) }',
319
+ filePath: 'src/services/UserService.ts',
320
+ },
321
+ {
322
+ name: 'UserRole',
323
+ kind: 'type',
324
+ signature: "type UserRole = 'admin' | 'editor' | 'viewer'",
325
+ filePath: 'src/types/roles.ts',
326
+ },
327
+ ]
328
+
329
+ const client = createLLMClient(process.env.LLM_API_KEY || 'sk-your-api-key-here')
330
+
331
+ const options: GenerationOptions = {
332
+ model: 'gpt-4o',
333
+ maxConcurrency: 2,
334
+ outputFormat: 'markdown',
335
+ onError: 'skip',
336
+ }
337
+
338
+ async function main() {
339
+ try {
340
+ console.log(`Generating docs for ${elements.length} elements...\n`)
341
+
342
+ const docs = await generateForElements(elements, client, options)
343
+
344
+ console.log(`✅ Generated ${docs.length} documentation entries:\n`)
345
+
346
+ for (const doc of docs) {
347
+ console.log(`─── ${doc.elementName} (${doc.kind}) ───`)
348
+ console.log(doc.markdown)
349
+ console.log(`Generated at: ${doc.generatedAt.toISOString()}\n`)
350
+ }
351
+
352
+ // Expected output:
353
+ // ✅ Generated 3 documentation entries:
354
+ // ─── fetchUser (function) ───
355
+ // **Auto-generated doc**
356
+ // Prompt received: "Generate markdown documentation for: async function fe..."
357
+ // Generated at: 2024-11-15T10:23:45.123Z
358
+ // ... (one entry per element)
359
+ } catch (error) {
360
+ console.error('Documentation generation failed:', error)
361
+ process.exit(1)
362
+ }
363
+ }
364
+
365
+ main()
366
+ ```
367
+
368
+ ### `formatAsMarkdown`
369
+
370
+ ```typescript
371
+ function formatAsMarkdown(docs: GeneratedDoc[], title: string): string
372
+ ```
373
+
374
+ Use this to convert an array of generated documentation objects into a formatted Markdown string, ready to write to a `.md` file or display in a docs site.
375
+
376
+ Takes structured doc data (functions, classes, methods) and a page title, and returns a complete Markdown document with sections organized by element type.
377
+
378
+ ## Parameters
379
+
380
+ | Name | Type | Required | Description |
381
+ |------|------|----------|-------------|
382
+ | `docs` | `GeneratedDoc[]` | ✅ | Array of generated documentation objects, each containing an element descriptor and its rendered doc content |
383
+ | `title` | `string` | ✅ | The top-level heading for the Markdown document (rendered as `# title`) |
384
+
385
+ ## Returns
386
+
387
+ A `string` containing the full Markdown file content, with:
388
+ - A `# Title` heading at the top
389
+ - Sections grouped by element kind: **Functions**, **Classes**, and **Methods**
390
+ - Each doc entry rendered under its appropriate section
391
+
392
+ ---MARKDOWN---
393
+
394
+ **Example:**
395
+
396
+ ```typescript example.ts
397
+ // ---- Inline types (mirrors the real GeneratedDoc / APIElement shape) ----
398
+ type ElementKind = 'function' | 'class' | 'method'
399
+
400
+ interface APIElement {
401
+ name: string
402
+ kind: ElementKind
403
+ signature?: string
404
+ }
405
+
406
+ interface GeneratedDoc {
407
+ element: APIElement
408
+ documentation: string
409
+ }
410
+
411
+ // ---- Inline implementation of formatAsMarkdown ----
412
+ function formatAsMarkdown(docs: GeneratedDoc[], title: string): string {
413
+ let content = `# ${title}\n\n`
414
+
415
+ const functions = docs.filter(d => d.element.kind === 'function')
416
+ const classes = docs.filter(d => d.element.kind === 'class')
417
+ const methods = docs.filter(d => d.element.kind === 'method')
418
+
419
+ function renderSection(heading: string, items: GeneratedDoc[]): string {
420
+ if (items.length === 0) return ''
421
+ let section = `## ${heading}\n\n`
422
+ for (const doc of items) {
423
+ section += `### \`${doc.element.name}\`\n\n`
424
+ if (doc.element.signature) {
425
+ section += `\`\`\`ts\n${doc.element.signature}\n\`\`\`\n\n`
426
+ }
427
+ section += `${doc.documentation}\n\n`
428
+ }
429
+ return section
430
+ }
431
+
432
+ content += renderSection('Functions', functions)
433
+ content += renderSection('Classes', classes)
434
+ content += renderSection('Methods', methods)
435
+
436
+ return content.trimEnd() + '\n'
437
+ }
438
+
439
+ // ---- Realistic sample data ----
440
+ const sampleDocs: GeneratedDoc[] = [
441
+ {
442
+ element: {
443
+ name: 'fetchUser',
444
+ kind: 'function',
445
+ signature: 'function fetchUser(id: string): Promise<User>',
446
+ },
447
+ documentation:
448
+ 'Fetches a user record by ID from the remote API. Throws `NotFoundError` if the user does not exist.',
449
+ },
450
+ {
451
+ element: {
452
+ name: 'UserService',
453
+ kind: 'class',
454
+ signature: 'class UserService',
455
+ },
456
+ documentation:
457
+ 'Provides high-level methods for managing user accounts, including creation, updates, and deletion.',
458
+ },
459
+ {
460
+ element: {
461
+ name: 'UserService.update',
462
+ kind: 'method',
463
+ signature: 'update(id: string, patch: Partial<User>): Promise<User>',
464
+ },
465
+ documentation:
466
+ 'Applies a partial update to an existing user. Returns the updated user object.',
467
+ },
468
+ ]
469
+
470
+ // ---- Run the example ----
471
+ try {
472
+ const markdown = formatAsMarkdown(sampleDocs, 'API Reference')
473
+ console.log(markdown)
474
+ /*
475
+ Expected output:
476
+ ─────────────────────────────────────────
477
+ # API Reference
478
+
479
+ ## Functions
480
+
481
+ ### `fetchUser`
482
+
483
+ ```ts
484
+ function fetchUser(id: string): Promise<User>
485
+ ```
486
+
487
+ Fetches a user record by ID from the remote API. Throws `NotFoundError` if the user does not exist.
488
+
489
+ ## Classes
490
+
491
+ ### `UserService`
492
+ ...
493
+
494
+ ## Methods
495
+
496
+ ### `UserService.update`
497
+ ...
498
+ ─────────────────────────────────────────
499
+ */
500
+ } catch (error) {
501
+ console.error('formatAsMarkdown failed:', error)
502
+ }
503
+ ```
504
+