From 453c1d2bd930af7231fbb7714d454debd96ff7f0 Mon Sep 17 00:00:00 2001 From: glassBead Date: Wed, 19 Feb 2025 20:08:44 -0600 Subject: [PATCH 1/9] chore: add changeset for GitHub Pages documentation --- .changeset/wicked-geckos-relate.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wicked-geckos-relate.md diff --git a/.changeset/wicked-geckos-relate.md b/.changeset/wicked-geckos-relate.md new file mode 100644 index 00000000..32efbb7c --- /dev/null +++ b/.changeset/wicked-geckos-relate.md @@ -0,0 +1,5 @@ +--- +'srcbook': patch +--- + +Add GitHub Pages documentation repository structure and configuration. From 87677d526389493777a2bc48c7cbe5374d16d2c0 Mon Sep 17 00:00:00 2001 From: glassBead Date: Wed, 19 Feb 2025 20:12:38 -0600 Subject: [PATCH 2/9] feat: add GitHub Pages documentation structure --- docs/_config.yml | 5 + docs/advanced/advanced-cells.src.md | 331 + docs/advanced/cell-execution.src.md | 300 + docs/advanced/debugging.src.md | 293 + docs/advanced/error-handling.src.md | 291 + docs/advanced/index.src.md | 117 + docs/advanced/interoperability.src.md | 284 + docs/advanced/language-service.src.md | 300 + docs/advanced/performance.src.md | 332 + docs/advanced/testing.src.md | 284 + docs/advanced/typescript-config.src.md | 325 + docs/advanced/typescript-features.src.md | 289 + docs/api-reference.src.md | 264 + docs/contributing.src.md | 280 + docs/examples.src.md | 241 + docs/features.src.md | 289 + docs/file-format.src.md | 149 + docs/getting-started.src.md | 211 + docs/index.src.md | 79 + docs/table-of-contents.src.md | 182 + docs/testing/notebook-test-harness.src.md | 249 + docs/testing/package-lock.json | 2074 ++++++ docs/testing/package.json | 16 + docs/testing/run-all-tests.ts | 56 + docs/testing/run-tests.ts | 207 + docs/testing/tsconfig.json | 30 + docs/web-app-generator/ai-integration.src.md | 272 + docs/web-app-generator/architecture.src.md | 236 + docs/web-app-generator/error-handling.src.md | 232 + docs/web-app-generator/examples.src.md | 268 + docs/web-app-generator/file-system.src.md | 272 + docs/web-app-generator/index.src.md | 78 + .../package-management.src.md | 250 + .../project-structure.src.md | 264 + docs/web-app-generator/testing/app-loader.ts | 17 + .../testing/apps/sample-app/index.html | 12 + .../testing/apps/sample-app/package-lock.json | 1634 +++++ .../testing/apps/sample-app/package.json | 21 + .../testing/apps/sample-app/src/App.tsx | 17 + .../testing/apps/sample-app/src/index.css | 46 + .../testing/apps/sample-app/src/main.tsx | 10 + .../testing/apps/sample-app/tsconfig.json | 21 + .../apps/sample-app/tsconfig.node.json | 10 + .../testing/apps/sample-app/vite.config.ts | 10 + .../notebooks/architecture-validator.ts | 242 + .../testing/notebooks/notebook-loader.ts | 37 + .../testing/notebooks/package-lock.json | 1654 +++++ .../testing/notebooks/package.json | 9 + .../testing/notebooks/reporter.ts | 90 + .../notebooks/run-architecture-tests.ts | 27 + .../testing/notebooks/run-tests.ts | 21 + .../testing/notebooks/test-runner.ts | 213 + .../testing/notebooks/tsconfig.json | 17 + .../testing/notebooks/types.ts | 58 + .../testing/package-lock.json | 5616 +++++++++++++++++ docs/web-app-generator/testing/package.json | 17 + docs/web-app-generator/testing/reporter.ts | 60 + docs/web-app-generator/testing/run-tests.ts | 16 + docs/web-app-generator/testing/test-runner.ts | 218 + docs/web-app-generator/testing/tsconfig.json | 28 + docs/web-app-generator/testing/types.ts | 37 + .../web-app-test-harness.src.md | 332 + 62 files changed, 19840 insertions(+) create mode 100644 docs/_config.yml create mode 100644 docs/advanced/advanced-cells.src.md create mode 100644 docs/advanced/cell-execution.src.md create mode 100644 docs/advanced/debugging.src.md create mode 100644 docs/advanced/error-handling.src.md create mode 100644 docs/advanced/index.src.md create mode 100644 docs/advanced/interoperability.src.md create mode 100644 docs/advanced/language-service.src.md create mode 100644 docs/advanced/performance.src.md create mode 100644 docs/advanced/testing.src.md create mode 100644 docs/advanced/typescript-config.src.md create mode 100644 docs/advanced/typescript-features.src.md create mode 100644 docs/api-reference.src.md create mode 100644 docs/contributing.src.md create mode 100644 docs/examples.src.md create mode 100644 docs/features.src.md create mode 100644 docs/file-format.src.md create mode 100644 docs/getting-started.src.md create mode 100644 docs/index.src.md create mode 100644 docs/table-of-contents.src.md create mode 100644 docs/testing/notebook-test-harness.src.md create mode 100644 docs/testing/package-lock.json create mode 100644 docs/testing/package.json create mode 100644 docs/testing/run-all-tests.ts create mode 100644 docs/testing/run-tests.ts create mode 100644 docs/testing/tsconfig.json create mode 100644 docs/web-app-generator/ai-integration.src.md create mode 100644 docs/web-app-generator/architecture.src.md create mode 100644 docs/web-app-generator/error-handling.src.md create mode 100644 docs/web-app-generator/examples.src.md create mode 100644 docs/web-app-generator/file-system.src.md create mode 100644 docs/web-app-generator/index.src.md create mode 100644 docs/web-app-generator/package-management.src.md create mode 100644 docs/web-app-generator/project-structure.src.md create mode 100644 docs/web-app-generator/testing/app-loader.ts create mode 100644 docs/web-app-generator/testing/apps/sample-app/index.html create mode 100644 docs/web-app-generator/testing/apps/sample-app/package-lock.json create mode 100644 docs/web-app-generator/testing/apps/sample-app/package.json create mode 100644 docs/web-app-generator/testing/apps/sample-app/src/App.tsx create mode 100644 docs/web-app-generator/testing/apps/sample-app/src/index.css create mode 100644 docs/web-app-generator/testing/apps/sample-app/src/main.tsx create mode 100644 docs/web-app-generator/testing/apps/sample-app/tsconfig.json create mode 100644 docs/web-app-generator/testing/apps/sample-app/tsconfig.node.json create mode 100644 docs/web-app-generator/testing/apps/sample-app/vite.config.ts create mode 100644 docs/web-app-generator/testing/notebooks/architecture-validator.ts create mode 100644 docs/web-app-generator/testing/notebooks/notebook-loader.ts create mode 100644 docs/web-app-generator/testing/notebooks/package-lock.json create mode 100644 docs/web-app-generator/testing/notebooks/package.json create mode 100644 docs/web-app-generator/testing/notebooks/reporter.ts create mode 100644 docs/web-app-generator/testing/notebooks/run-architecture-tests.ts create mode 100644 docs/web-app-generator/testing/notebooks/run-tests.ts create mode 100644 docs/web-app-generator/testing/notebooks/test-runner.ts create mode 100644 docs/web-app-generator/testing/notebooks/tsconfig.json create mode 100644 docs/web-app-generator/testing/notebooks/types.ts create mode 100644 docs/web-app-generator/testing/package-lock.json create mode 100644 docs/web-app-generator/testing/package.json create mode 100644 docs/web-app-generator/testing/reporter.ts create mode 100644 docs/web-app-generator/testing/run-tests.ts create mode 100644 docs/web-app-generator/testing/test-runner.ts create mode 100644 docs/web-app-generator/testing/tsconfig.json create mode 100644 docs/web-app-generator/testing/types.ts create mode 100644 docs/web-app-generator/web-app-test-harness.src.md diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..9f8f54b2 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,5 @@ +title: Srcbook Documentation +description: Documentation for Srcbook - A TypeScript-centric app development platform +theme: jekyll-theme-minimal +markdown: GFM +highlighter: rouge \ No newline at end of file diff --git a/docs/advanced/advanced-cells.src.md b/docs/advanced/advanced-cells.src.md new file mode 100644 index 00000000..ede3329a --- /dev/null +++ b/docs/advanced/advanced-cells.src.md @@ -0,0 +1,331 @@ + + +# Advanced Cell Features in Srcbook + +This notebook demonstrates advanced cell features in Srcbook, including output types, rich formatting, custom renderers, and cell dependencies. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "marked": "^11.1.1", + "mermaid": "^10.7.0", + "katex": "^0.16.9" + } +} +``` + +## Cell Output Types + +Different types of cell outputs: + +###### output-types.ts + +```typescript +// Text output +console.log('Basic text output'); + +// JSON output +console.log(JSON.stringify({ + name: 'Example', + values: [1, 2, 3] +}, null, 2)); + +// Table output +console.table([ + { id: 1, name: 'Item 1', value: 100 }, + { id: 2, name: 'Item 2', value: 200 }, + { id: 3, name: 'Item 3', value: 300 } +]); + +// Error output +try { + throw new Error('Example error output'); +} catch (error) { + console.error(error); +} + +// Type assertions +type test1 = typeof console.log extends (message: any) => void ? true : false; +type test2 = typeof console.table extends (data: any) => void ? true : false; + +const assertOutputs: [test1, test2] = [true, true]; +``` + +## Rich Output Formatting + +Format output with markdown and HTML: + +###### rich-output.ts + +```typescript +import { marked } from 'marked'; + +class RichOutput { + static markdown(text: string): string { + return marked(text); + } + + static html(content: string): string { + return content; + } + + static table(data: unknown[]): string { + const headers = Object.keys(data[0] ?? {}); + const rows = data.map(item => + headers.map(key => (item as any)[key]) + ); + + return ` + + + ${headers.map(h => ``).join('')} + + + ${rows.map(row => + `${row.map(cell => ``).join('')}` + ).join('')} + +
${h}
${cell}
+ `; + } +} + +// Example usage +const markdownOutput = RichOutput.markdown(` +# Example Header +- List item 1 +- List item 2 + +\`\`\`typescript +const code = 'example'; +\`\`\` +`); + +const tableData = [ + { id: 1, name: 'Item 1' }, + { id: 2, name: 'Item 2' } +]; +const tableOutput = RichOutput.table(tableData); + +// Type assertions +type test3 = ReturnType extends string ? true : false; +type test4 = ReturnType extends string ? true : false; + +const assertRich: [test3, test4] = [true, true]; +``` + +## Custom Renderers + +Create custom output renderers: + +###### custom-renderers.ts + +```typescript +interface Renderer { + render(data: T): string; +} + +// Mermaid diagram renderer +class MermaidRenderer implements Renderer { + render(diagram: string): string { + return ` +
+ ${diagram} +
+ `; + } +} + +// Math equation renderer +class KaTeXRenderer implements Renderer { + render(equation: string): string { + return ` +
+ ${equation} +
+ `; + } +} + +// JSON tree renderer +class JsonTreeRenderer implements Renderer { + render(data: unknown): string { + return ` +
+
${JSON.stringify(data, null, 2)}
+
+ `; + } +} + +// Example usage +const mermaid = new MermaidRenderer(); +const katex = new KaTeXRenderer(); +const jsonTree = new JsonTreeRenderer(); + +const diagram = mermaid.render(` + graph TD + A[Start] --> B[Process] + B --> C[End] +`); + +const equation = katex.render('E = mc^2'); + +const data = jsonTree.render({ + name: 'Example', + nested: { + value: 42 + } +}); + +// Type assertions +type test5 = MermaidRenderer extends Renderer ? true : false; +type test6 = KaTeXRenderer extends Renderer ? true : false; +type test7 = JsonTreeRenderer extends Renderer ? true : false; + +const assertRenderers: [test5, test6, test7] = [true, true, true]; +``` + +## Cell Metadata + +Work with cell metadata: + +###### metadata-types.ts + +```typescript +interface CellMetadata { + id: string; + type: 'code' | 'markdown'; + language?: string; + tags?: string[]; + dependencies?: string[]; + created: Date; + modified: Date; +} + +class MetadataManager { + private metadata: Map = new Map(); + + addMetadata(cellId: string, data: Omit): void { + this.metadata.set(cellId, { + id: cellId, + ...data + }); + } + + getMetadata(cellId: string): CellMetadata | undefined { + return this.metadata.get(cellId); + } + + updateMetadata(cellId: string, updates: Partial): void { + const current = this.metadata.get(cellId); + if (current) { + this.metadata.set(cellId, { + ...current, + ...updates, + modified: new Date() + }); + } + } +} + +// Type assertions +type test8 = MetadataManager extends { getMetadata(id: string): CellMetadata | undefined } ? true : false; +const assertMetadata: test8 = true; +``` + +## Cell Dependencies + +Manage cell dependencies: + +###### dependency-manager.ts + +```typescript +interface DependencyNode { + id: string; + dependencies: Set; + dependents: Set; +} + +class DependencyManager { + private nodes: Map = new Map(); + + addCell(cellId: string): void { + if (!this.nodes.has(cellId)) { + this.nodes.set(cellId, { + id: cellId, + dependencies: new Set(), + dependents: new Set() + }); + } + } + + addDependency(cellId: string, dependsOn: string): void { + this.addCell(cellId); + this.addCell(dependsOn); + + const cell = this.nodes.get(cellId)!; + const dependency = this.nodes.get(dependsOn)!; + + cell.dependencies.add(dependsOn); + dependency.dependents.add(cellId); + } + + getExecutionOrder(): string[] { + const visited = new Set(); + const order: string[] = []; + + const visit = (nodeId: string) => { + if (visited.has(nodeId)) return; + + const node = this.nodes.get(nodeId)!; + visited.add(nodeId); + + for (const depId of node.dependencies) { + visit(depId); + } + + order.push(nodeId); + }; + + for (const nodeId of this.nodes.keys()) { + visit(nodeId); + } + + return order; + } +} + +// Type assertions +type test9 = DependencyManager extends { getExecutionOrder(): string[] } ? true : false; +type test10 = DependencyNode extends { dependencies: Set } ? true : false; + +const assertDependencies: [test9, test10] = [true, true]; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/advanced-cells.src.md +``` + +The test harness will: +1. Verify output formatting +2. Test custom renderers +3. Check metadata handling +4. Validate dependency management + +## Next Steps + +- Explore [Error Handling](./error-handling.src.md) +- Learn about [Performance Optimization](./performance.src.md) +- Study [Interoperability](./interoperability.src.md) \ No newline at end of file diff --git a/docs/advanced/cell-execution.src.md b/docs/advanced/cell-execution.src.md new file mode 100644 index 00000000..b0e7e28d --- /dev/null +++ b/docs/advanced/cell-execution.src.md @@ -0,0 +1,300 @@ + + +# Cell Execution Context in Srcbook + +This notebook explains how cell execution works in Srcbook, including scope isolation, variable persistence, and module caching. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "uuid": "^9.0.1" + } +} +``` + +## Scope Isolation + +Each cell has its own scope: + +###### scope-a.ts + +```typescript +// This variable is scoped to this cell +const localVar = "I'm local to scope-a"; + +// Export to make it available to other cells +export const sharedVar = "I'm shared from scope-a"; + +// Type assertion +type test1 = typeof localVar extends string ? true : false; +const assertScopeA: test1 = true; +``` + +###### scope-b.ts + +```typescript +// This will error - localVar is not accessible +// console.log(localVar); + +// But we can access sharedVar +import { sharedVar } from './scope-a.ts'; +console.log('Shared var:', sharedVar); + +// Create our own local var +const localVar = "I'm local to scope-b"; + +// Type assertions +type test2 = typeof sharedVar extends string ? true : false; +type test3 = typeof localVar extends string ? true : false; + +const assertScopeB: [test2, test3] = [true, true]; +``` + +## Variable Persistence + +Variables persist within their cell's scope: + +###### counter.ts + +```typescript +let count = 0; + +export function increment(): number { + return ++count; +} + +export function getCount(): number { + return count; +} + +// Type assertions +type test4 = typeof increment extends () => number ? true : false; +type test5 = typeof getCount extends () => number ? true : false; + +const assertCounter: [test4, test5] = [true, true]; +``` + +###### counter-test.ts + +```typescript +import { increment, getCount } from './counter.ts'; + +console.log('Initial count:', getCount()); // 0 +increment(); +increment(); +console.log('After increments:', getCount()); // 2 + +// Type assertion +type test6 = ReturnType extends number ? true : false; +const assertCounterTest: test6 = true; +``` + +## Module Caching + +Srcbook caches module imports: + +###### cached-module.ts + +```typescript +import { v4 as uuidv4 } from 'uuid'; + +// This ID will remain constant across imports +export const moduleId = uuidv4(); + +export function getId(): string { + return moduleId; +} + +// Type assertions +type test7 = typeof moduleId extends string ? true : false; +type test8 = typeof getId extends () => string ? true : false; + +const assertModule: [test7, test8] = [true, true]; +``` + +###### cache-test-1.ts + +```typescript +import { moduleId as id1 } from './cached-module.ts'; +console.log('First import ID:', id1); + +// Type assertion +type test9 = typeof id1 extends string ? true : false; +const assertCache1: test9 = true; +``` + +###### cache-test-2.ts + +```typescript +import { moduleId as id2 } from './cached-module.ts'; +console.log('Second import ID:', id2); + +// Verify both imports have the same ID +import { moduleId as id1 } from './cache-test-1.ts'; +console.log('IDs match:', id1 === id2); + +// Type assertion +type test10 = typeof id2 extends string ? true : false; +const assertCache2: test10 = true; +``` + +## Execution Order Dependencies + +Cells can depend on each other's execution: + +###### setup.ts + +```typescript +export let initialized = false; + +export function initialize(): void { + initialized = true; + console.log('Initialization complete'); +} + +// Type assertions +type test11 = typeof initialized extends boolean ? true : false; +type test12 = typeof initialize extends () => void ? true : false; + +const assertSetup: [test11, test12] = [true, true]; +``` + +###### dependent.ts + +```typescript +import { initialized, initialize } from './setup.ts'; + +if (!initialized) { + initialize(); +} + +export function performAction(): string { + if (!initialized) { + throw new Error('Must initialize first'); + } + return 'Action performed'; +} + +// Type assertion +type test13 = typeof performAction extends () => string ? true : false; +const assertDependent: test13 = true; +``` + +## Memory Management + +Understanding how Srcbook manages memory: + +###### memory-usage.ts + +```typescript +// Create a large array +const largeArray: number[] = Array(1000000).fill(0); + +// Clear references when done +function cleanup(): void { + // This allows the array to be garbage collected + (globalThis as any).largeArray = undefined; +} + +// Keep track of memory usage +function getMemoryUsage(): number { + return process.memoryUsage().heapUsed; +} + +const memoryBefore = getMemoryUsage(); +console.log('Memory before:', memoryBefore); + +cleanup(); + +const memoryAfter = getMemoryUsage(); +console.log('Memory after:', memoryAfter); + +// Type assertions +type test14 = typeof memoryBefore extends number ? true : false; +type test15 = typeof memoryAfter extends number ? true : false; + +const assertMemory: [test14, test15] = [true, true]; +``` + +## Cell Lifecycle + +Understanding cell execution lifecycle: + +###### lifecycle.ts + +```typescript +interface CellState { + status: 'idle' | 'running' | 'complete' | 'error'; + startTime?: number; + endTime?: number; + error?: Error; +} + +class CellLifecycle { + private state: CellState = { status: 'idle' }; + + async execute(fn: () => Promise): Promise { + this.state.status = 'running'; + this.state.startTime = Date.now(); + + try { + const result = await fn(); + this.state.status = 'complete'; + return result; + } catch (error) { + this.state.status = 'error'; + this.state.error = error as Error; + throw error; + } finally { + this.state.endTime = Date.now(); + } + } + + getState(): CellState { + return { ...this.state }; + } +} + +const lifecycle = new CellLifecycle(); + +// Test execution +await lifecycle.execute(async () => { + return 'test complete'; +}); + +const finalState = lifecycle.getState(); + +// Type assertions +type test16 = typeof lifecycle extends CellLifecycle ? true : false; +type test17 = typeof finalState extends CellState ? true : false; + +const assertLifecycle: [test16, test17] = [true, true]; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/cell-execution.src.md +``` + +The test harness will: +1. Verify scope isolation +2. Test variable persistence +3. Check module caching +4. Validate execution order +5. Monitor memory usage + +## Next Steps + +- Explore [Language Service Integration](./language-service.src.md) +- Learn about [Testing in Notebooks](./testing.src.md) +- Study [Error Handling](./error-handling.src.md) \ No newline at end of file diff --git a/docs/advanced/debugging.src.md b/docs/advanced/debugging.src.md new file mode 100644 index 00000000..a3994847 --- /dev/null +++ b/docs/advanced/debugging.src.md @@ -0,0 +1,293 @@ + + +# Debugging in Srcbook + +This notebook demonstrates how to effectively debug TypeScript code in Srcbook notebooks, including breakpoint usage, variable inspection, and debugging strategies. + +## Setup + +First, let's set up some debugging utilities: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "debug": "^4.3.4" + } +} +``` + +## Breakpoint Usage + +Srcbook supports debugging with breakpoints: + +###### breakpoint-demo.ts + +```typescript +function fibonacci(n: number): number { + // You can set a breakpoint on the next line + if (n <= 1) return n; + return fibonacci(n - 1) + fibonacci(n - 2); +} + +// Test with a small number first +const result = fibonacci(5); +console.log('Fibonacci result:', result); + +// Type assertion +type test1 = typeof result extends number ? true : false; +const assertResult: test1 = true; +``` + +## Variable Inspection + +Inspect variables during execution: + +###### variable-inspector.ts + +```typescript +class DebugDemo { + private values: number[] = []; + + constructor(initialValues: number[]) { + // Set a breakpoint here to inspect initialValues + this.values = [...initialValues]; + } + + addValue(value: number): void { + // Set a breakpoint here to watch value addition + this.values.push(value); + } + + getSum(): number { + // Set a breakpoint here to inspect the reduction + return this.values.reduce((sum, val) => sum + val, 0); + } +} + +const demo = new DebugDemo([1, 2, 3]); +demo.addValue(4); +const sum = demo.getSum(); + +// Type assertions +type test2 = typeof demo extends DebugDemo ? true : false; +type test3 = typeof sum extends number ? true : false; + +const assertInspectorResults: [test2, test3] = [true, true]; +``` + +## Call Stack Navigation + +Examine the call stack during debugging: + +###### call-stack-demo.ts + +```typescript +function level3(x: number): number { + // Set a breakpoint here to examine the call stack + return x * 2; +} + +function level2(x: number): number { + return level3(x + 1); +} + +function level1(x: number): number { + return level2(x * 2); +} + +const stackResult = level1(5); +console.log('Stack result:', stackResult); + +// Type assertion +type test4 = typeof stackResult extends number ? true : false; +const assertStackResult: test4 = true; +``` + +## Watch Expressions + +Use watch expressions to monitor values: + +###### watch-expressions.ts + +```typescript +class Counter { + private count: number = 0; + + increment(): void { + // Add a watch expression for this.count + this.count += 1; + } + + decrement(): void { + // Add a watch expression for this.count + this.count -= 1; + } + + getCount(): number { + return this.count; + } +} + +const counter = new Counter(); +counter.increment(); +counter.increment(); +counter.decrement(); +const finalCount = counter.getCount(); + +// Type assertions +type test5 = typeof counter extends Counter ? true : false; +type test6 = typeof finalCount extends number ? true : false; + +const assertWatchResults: [test5, test6] = [true, true]; +``` + +## Debug Console + +Interact with the debug console: + +###### debug-console.ts + +```typescript +import debug from 'debug'; + +// Configure debug namespace +const log = debug('srcbook:example'); + +class DebuggableClass { + constructor(private name: string) { + log('Created instance with name: %s', name); + } + + doSomething(): void { + log('Doing something in %s', this.name); + // You can evaluate expressions in the debug console here + console.log('Action completed'); + } +} + +const instance = new DebuggableClass('test'); +instance.doSomething(); + +// Type assertion +type test7 = typeof instance extends DebuggableClass ? true : false; +const assertConsoleResult: test7 = true; +``` + +## Conditional Breakpoints + +Use conditional breakpoints for complex debugging: + +###### conditional-breakpoints.ts + +```typescript +function processArray(arr: number[]): number[] { + const results: number[] = []; + + for (let i = 0; i < arr.length; i++) { + // Set a conditional breakpoint here: arr[i] > 100 + const processed = arr[i] * 2; + results.push(processed); + } + + return results; +} + +const input = [50, 150, 25, 200, 75]; +const processed = processArray(input); + +// Type assertions +type test8 = typeof processed extends number[] ? true : false; +const assertConditionResult: test8 = true; +``` + +## Error Handling Debug + +Debug error scenarios: + +###### error-debugging.ts + +```typescript +class CustomError extends Error { + constructor(message: string, public code: number) { + super(message); + this.name = 'CustomError'; + } +} + +function mightFail(input: unknown): string { + try { + // Set a breakpoint here to debug error handling + if (typeof input !== 'string') { + throw new CustomError('Invalid input', 400); + } + return input.toUpperCase(); + } catch (error) { + // Set a breakpoint here to inspect the error + if (error instanceof CustomError) { + console.error(`Error ${error.code}: ${error.message}`); + } + throw error; + } +} + +// Test successful case +const success = mightFail('hello'); + +// Test error case +try { + mightFail(42); +} catch (error) { + console.error('Caught error:', error); +} + +// Type assertions +type test9 = typeof success extends string ? true : false; +type test10 = CustomError extends Error ? true : false; + +const assertErrorResults: [test9, test10] = [true, true]; +``` + +## Debugging Best Practices + +1. **Strategic Breakpoint Placement** + - Set breakpoints at critical logic points + - Use conditional breakpoints for specific cases + - Add breakpoints before error-prone code + +2. **Effective Variable Inspection** + - Watch critical variables + - Examine object properties + - Monitor state changes + +3. **Console Usage** + - Use console.log strategically + - Leverage debug namespace + - Format output for clarity + +4. **Error Handling** + - Break on all exceptions + - Inspect error objects + - Track error propagation + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/debugging.src.md +``` + +The test harness will: +1. Verify all type assertions +2. Execute debug scenarios +3. Validate error handling +4. Check console output + +## Next Steps + +- Explore [Cell Execution Context](./cell-execution.src.md) +- Learn about [Error Handling](./error-handling.src.md) +- Study [Performance Optimization](./performance.src.md) \ No newline at end of file diff --git a/docs/advanced/error-handling.src.md b/docs/advanced/error-handling.src.md new file mode 100644 index 00000000..aa532794 --- /dev/null +++ b/docs/advanced/error-handling.src.md @@ -0,0 +1,291 @@ + + +# Error Handling in Srcbook + +This notebook demonstrates effective error handling strategies in Srcbook notebooks, including type errors, runtime errors, and error recovery. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "zod": "^3.22.4" + } +} +``` + +## Type Error Handling + +Handle TypeScript type errors effectively: + +###### type-guards.ts + +```typescript +// Define custom type guard +function isString(value: unknown): value is string { + return typeof value === 'string'; +} + +function isNumber(value: unknown): value is number { + return typeof value === 'number' && !isNaN(value); +} + +// Use type guards to handle unknown data +function processValue(value: unknown): string { + if (isString(value)) { + return value.toUpperCase(); + } + if (isNumber(value)) { + return value.toFixed(2); + } + throw new TypeError('Value must be string or number'); +} + +// Type assertions +type test1 = ReturnType extends string ? true : false; +const assertTypeGuards: test1 = true; +``` + +## Runtime Error Handling + +Handle runtime errors gracefully: + +###### error-types.ts + +```typescript +// Custom error classes +class ValidationError extends Error { + constructor(message: string) { + super(message); + this.name = 'ValidationError'; + } +} + +class NetworkError extends Error { + constructor(message: string, public statusCode: number) { + super(message); + this.name = 'NetworkError'; + } +} + +class DatabaseError extends Error { + constructor(message: string, public code: string) { + super(message); + this.name = 'DatabaseError'; + } +} + +// Type assertions +type test2 = ValidationError extends Error ? true : false; +type test3 = NetworkError extends Error ? true : false; +type test4 = DatabaseError extends Error ? true : false; + +const assertErrorTypes: [test2, test3, test4] = [true, true, true]; +``` + +## Error Recovery Strategies + +Implement error recovery: + +###### recovery-strategies.ts + +```typescript +import { z } from 'zod'; + +// Define schema for validation +const UserSchema = z.object({ + id: z.string(), + name: z.string(), + email: z.string().email(), + age: z.number().min(0).max(120) +}); + +type User = z.infer; + +class ErrorRecovery { + // Retry with exponential backoff + async retry( + fn: () => Promise, + maxAttempts: number = 3, + delay: number = 1000 + ): Promise { + let lastError: Error | null = null; + + for (let attempt = 1; attempt <= maxAttempts; attempt++) { + try { + return await fn(); + } catch (error) { + lastError = error as Error; + if (attempt === maxAttempts) break; + await new Promise(resolve => setTimeout(resolve, delay * attempt)); + } + } + + throw lastError; + } + + // Validate with fallback + validateUser(data: unknown): Partial { + try { + return UserSchema.parse(data); + } catch (error) { + // Return partial valid data + const partial = UserSchema.partial().safeParse(data); + return partial.success ? partial.data : {}; + } + } + + // Circuit breaker + createCircuitBreaker( + fn: () => Promise, + threshold: number = 3, + resetTimeout: number = 5000 + ): () => Promise { + let failures = 0; + let lastFailure: number | null = null; + + return async () => { + if (failures >= threshold) { + const timeSinceLastFailure = lastFailure ? Date.now() - lastFailure : 0; + if (timeSinceLastFailure < resetTimeout) { + throw new Error('Circuit breaker open'); + } + failures = 0; + } + + try { + return await fn(); + } catch (error) { + failures++; + lastFailure = Date.now(); + throw error; + } + }; + } +} + +// Type assertions +type test5 = ErrorRecovery extends { retry(fn: () => Promise): Promise } ? true : false; +type test6 = ReturnType extends Partial ? true : false; + +const assertRecovery: [test5, test6] = [true, true]; +``` + +## Error Context Preservation + +Maintain error context: + +###### error-context.ts + +```typescript +class ErrorContext { + private context: Map = new Map(); + + addContext(key: string, value: unknown): void { + this.context.set(key, value); + } + + getContext(): Record { + return Object.fromEntries(this.context); + } + + clearContext(): void { + this.context.clear(); + } + + wrapError(error: Error): Error { + const contextData = this.getContext(); + return Object.assign(error, { context: contextData }); + } +} + +class ErrorWithContext extends Error { + constructor( + message: string, + public context: Record = {} + ) { + super(message); + this.name = 'ErrorWithContext'; + } +} + +// Type assertions +type test7 = ErrorWithContext extends Error ? true : false; +type test8 = ErrorWithContext['context'] extends Record ? true : false; + +const assertContext: [test7, test8] = [true, true]; +``` + +## Debug Information Access + +Access and format debug information: + +###### debug-info.ts + +```typescript +class DebugInfo { + static getStackTrace(): string { + const error = new Error(); + return error.stack ?? 'No stack trace available'; + } + + static async getMemoryUsage(): Promise> { + const usage = process.memoryUsage(); + return { + heapTotal: usage.heapTotal, + heapUsed: usage.heapUsed, + external: usage.external, + rss: usage.rss + }; + } + + static getEnvironmentInfo(): Record { + return { + nodeVersion: process.version, + platform: process.platform, + arch: process.arch, + pid: process.pid + }; + } + + static async captureDebugSnapshot(): Promise> { + return { + timestamp: new Date().toISOString(), + stack: this.getStackTrace(), + memory: await this.getMemoryUsage(), + environment: this.getEnvironmentInfo() + }; + } +} + +// Type assertions +type test9 = ReturnType extends string ? true : false; +type test10 = ReturnType extends Promise> ? true : false; + +const assertDebug: [test9, test10] = [true, true]; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/error-handling.src.md +``` + +The test harness will: +1. Verify error handling +2. Test recovery strategies +3. Check context preservation +4. Validate debug information + +## Next Steps + +- Explore [Interoperability](./interoperability.src.md) +- Learn about [Advanced Cell Features](./advanced-cells.src.md) +- Study [Performance Optimization](./performance.src.md) \ No newline at end of file diff --git a/docs/advanced/index.src.md b/docs/advanced/index.src.md new file mode 100644 index 00000000..49321ab5 --- /dev/null +++ b/docs/advanced/index.src.md @@ -0,0 +1,117 @@ + + +# Advanced Srcbook Topics + +This section covers advanced topics and features in Srcbook. Each topic is covered in detail with practical examples and test cases. + +## TypeScript Features + +Learn about advanced TypeScript capabilities in Srcbook: + +- [Advanced TypeScript Features](./typescript-features.src.md) - Type inference, generics, module augmentation +- [TypeScript Configuration](./typescript-config.src.md) - Module resolution, type checking, project references +- [Language Service Integration](./language-service.src.md) - Code completion, quick fixes, refactoring + +## Notebook Features + +Explore advanced notebook functionality: + +- [Cell Execution Context](./cell-execution.src.md) - Scope isolation, variable persistence +- [Advanced Cell Features](./advanced-cells.src.md) - Output types, rich formatting, dependencies +- [Testing in Notebooks](./testing.src.md) - Unit testing, coverage, assertions + +## Development Tools + +Master development and debugging tools: + +- [Debugging Capabilities](./debugging.src.md) - Breakpoints, inspection, call stack +- [Error Handling](./error-handling.src.md) - Type errors, runtime errors, recovery +- [Performance Optimization](./performance.src.md) - Type checking, compilation, execution + +## Integration + +Learn about integration capabilities: + +- [Interoperability](./interoperability.src.md) - JavaScript, Node.js, browser APIs + +## Example Usage + +Here's a quick example combining multiple advanced features: + +###### advanced-example.ts + +```typescript +// Type-safe error handling with custom output +interface Result { + success: boolean; + data?: T; + error?: E; +} + +class AdvancedCell { + private static renderer: typeof console.log = console.log; + + constructor( + private compute: () => Promise, + private dependencies: string[] = [] + ) {} + + static setRenderer(renderer: typeof console.log): void { + this.renderer = renderer; + } + + async execute(): Promise> { + try { + const result = await this.compute(); + AdvancedCell.renderer(result); + return { success: true, data: result }; + } catch (error) { + return { + success: false, + error: error as Error + }; + } + } + + getDependencies(): string[] { + return [...this.dependencies]; + } +} + +// Example usage +const cell = new AdvancedCell(async () => { + const data = await fetch('https://api.example.com/data'); + return data.json(); +}, ['data-source.ts']); + +// Custom renderer +AdvancedCell.setRenderer((data: unknown) => { + console.log(JSON.stringify(data, null, 2)); +}); + +// Type assertions +type test1 = AdvancedCell extends { execute(): Promise> } ? true : false; +type test2 = Result extends { success: boolean } ? true : false; + +const assertExample: [test1, test2] = [true, true]; +``` + +## Testing Advanced Features + +Each advanced topic notebook includes comprehensive tests that can be run using the test harness: + +```bash +# Test all advanced notebooks +for notebook in docs/advanced/*.src.md; do + npx tsx docs/testing/run-tests.ts "$notebook" +done +``` + +## Next Steps + +1. Start with [TypeScript Features](./typescript-features.src.md) +2. Explore [Cell Execution](./cell-execution.src.md) +3. Learn about [Testing](./testing.src.md) +4. Master [Debugging](./debugging.src.md) + +Join our [Discord](https://discord.gg/shDEGBSe2d) community to discuss advanced topics and share your experiences. \ No newline at end of file diff --git a/docs/advanced/interoperability.src.md b/docs/advanced/interoperability.src.md new file mode 100644 index 00000000..20fd79bf --- /dev/null +++ b/docs/advanced/interoperability.src.md @@ -0,0 +1,284 @@ + + +# Interoperability in Srcbook + +This notebook demonstrates how Srcbook notebooks can interact with different environments, technologies, and programming paradigms. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "node-fetch": "^3.3.2", + "ws": "^8.16.0", + "@types/node": "^20.11.5", + "@types/ws": "^8.5.10" + } +} +``` + +## JavaScript/TypeScript Mixing + +Mix JavaScript and TypeScript code: + +###### javascript-module.js + +```javascript +// Plain JavaScript module +export function calculateTotal(items) { + return items.reduce((sum, item) => sum + item.price, 0); +} + +export function formatPrice(price) { + return `$${price.toFixed(2)}`; +} + +// JSDoc for TypeScript support +/** + * @typedef {Object} Item + * @property {string} name + * @property {number} price + */ + +/** + * @param {Item[]} items + * @returns {Item} + */ +export function getMostExpensive(items) { + return items.reduce((max, item) => + item.price > max.price ? item : max + ); +} +``` + +###### typescript-consumer.ts + +```typescript +import { calculateTotal, formatPrice, getMostExpensive } from './javascript-module.js'; + +// Define TypeScript interface matching JSDoc +interface Item { + name: string; + price: number; +} + +// Use JavaScript functions with TypeScript types +const items: Item[] = [ + { name: 'Book', price: 29.99 }, + { name: 'Pen', price: 4.99 }, + { name: 'Desk', price: 199.99 } +]; + +const total = calculateTotal(items); +const formatted = formatPrice(total); +const expensive = getMostExpensive(items); + +// Type assertions +type test1 = typeof total extends number ? true : false; +type test2 = typeof formatted extends string ? true : false; +type test3 = typeof expensive extends Item ? true : false; + +const assertJSTS: [test1, test2, test3] = [true, true, true]; +``` + +## External Module Usage + +Work with external Node.js modules: + +###### http-client.ts + +```typescript +import fetch from 'node-fetch'; +import type { Response } from 'node-fetch'; + +interface ApiResponse { + data: T; + status: number; +} + +async function fetchJson(url: string): Promise> { + const response: Response = await fetch(url); + const data: T = await response.json(); + + return { + data, + status: response.status + }; +} + +// Example usage +interface Todo { + id: number; + title: string; + completed: boolean; +} + +const result = await fetchJson( + 'https://jsonplaceholder.typicode.com/todos/1' +); + +// Type assertions +type test4 = typeof fetchJson extends (url: string) => Promise> ? true : false; +type test5 = typeof result.data extends Todo ? true : false; + +const assertFetch: [test4, test5] = [true, true]; +``` + +## Node.js API Integration + +Use Node.js built-in APIs: + +###### file-operations.ts + +```typescript +import { promises as fs } from 'fs'; +import * as path from 'path'; + +class FileManager { + constructor(private basePath: string) {} + + async readJsonFile(filename: string): Promise { + const filePath = path.join(this.basePath, filename); + const content = await fs.readFile(filePath, 'utf-8'); + return JSON.parse(content); + } + + async writeJsonFile(filename: string, data: T): Promise { + const filePath = path.join(this.basePath, filename); + await fs.writeFile(filePath, JSON.stringify(data, null, 2)); + } + + async listFiles(): Promise { + const files = await fs.readdir(this.basePath); + return files.filter(file => file.endsWith('.json')); + } +} + +// Type assertions +type test6 = FileManager extends { readJsonFile(filename: string): Promise } ? true : false; +type test7 = FileManager extends { writeJsonFile(filename: string, data: T): Promise } ? true : false; + +const assertFileOps: [test6, test7] = [true, true]; +``` + +## Browser API Access + +Access browser APIs when available: + +###### browser-apis.ts + +```typescript +// Type-safe browser API detection +function isBrowser(): boolean { + return typeof window !== 'undefined' && typeof document !== 'undefined'; +} + +class BrowserIntegration { + private supported: boolean; + + constructor() { + this.supported = isBrowser(); + } + + async getLocation(): Promise { + if (!this.supported || !navigator.geolocation) { + return null; + } + + return new Promise((resolve, reject) => { + navigator.geolocation.getCurrentPosition(resolve, reject); + }); + } + + async storeData(key: string, data: unknown): Promise { + if (!this.supported) return; + + localStorage.setItem(key, JSON.stringify(data)); + } + + getData(key: string): T | null { + if (!this.supported) return null; + + const data = localStorage.getItem(key); + return data ? JSON.parse(data) : null; + } +} + +// Type assertions +type test8 = ReturnType extends boolean ? true : false; +type test9 = BrowserIntegration extends { getData(key: string): T | null } ? true : false; + +const assertBrowser: [test8, test9] = [true, true]; +``` + +## Native Module Support + +Work with native Node.js modules: + +###### websocket-server.ts + +```typescript +import { WebSocket, WebSocketServer } from 'ws'; + +class WsManager { + private server: WebSocketServer; + private clients: Set = new Set(); + + constructor(port: number) { + this.server = new WebSocketServer({ port }); + + this.server.on('connection', (ws: WebSocket) => { + this.clients.add(ws); + + ws.on('message', (message: string) => { + this.broadcast(message); + }); + + ws.on('close', () => { + this.clients.delete(ws); + }); + }); + } + + broadcast(message: string): void { + for (const client of this.clients) { + if (client.readyState === WebSocket.OPEN) { + client.send(message); + } + } + } + + close(): void { + this.server.close(); + } +} + +// Type assertions +type test10 = WsManager extends { broadcast(message: string): void } ? true : false; +const assertWs: test10 = true; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/interoperability.src.md +``` + +The test harness will: +1. Verify JavaScript/TypeScript interop +2. Test external module usage +3. Check Node.js API integration +4. Validate browser API handling + +## Next Steps + +- Explore [Advanced Cell Features](./advanced-cells.src.md) +- Learn about [Error Handling](./error-handling.src.md) +- Study [Performance Optimization](./performance.src.md) \ No newline at end of file diff --git a/docs/advanced/language-service.src.md b/docs/advanced/language-service.src.md new file mode 100644 index 00000000..70ad433e --- /dev/null +++ b/docs/advanced/language-service.src.md @@ -0,0 +1,300 @@ + + +# TypeScript Language Service Integration + +This notebook demonstrates how Srcbook integrates with TypeScript's Language Service to provide IDE-like features in notebooks. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "typescript": "^5.3.3" + } +} +``` + +## Code Completion + +TypeScript provides intelligent code completion: + +###### completion-demo.ts + +```typescript +interface User { + id: string; + name: string; + email: string; + preferences: { + theme: 'light' | 'dark'; + notifications: boolean; + }; +} + +const user: User = { + id: "1", + name: "John Doe", + email: "john@example.com", + preferences: { + theme: "light", + notifications: true + } +}; + +// Try typing 'user.' to see completion suggestions +console.log(user.preferences.theme); + +// Type assertions +type test1 = typeof user extends User ? true : false; +type test2 = typeof user.preferences.theme extends 'light' | 'dark' ? true : false; + +const assertCompletion: [test1, test2] = [true, true]; +``` + +## Quick Fixes + +TypeScript suggests quick fixes for common issues: + +###### quick-fix-demo.ts + +```typescript +// Missing property will show quick fix to add it +interface Product { + id: string; + name: string; + price: number; + description: string; +} + +// Quick fix will suggest adding missing properties +const product: Product = { + id: "1", + name: "Widget", + price: 9.99 + // Hover over error to see quick fix for missing 'description' +}; + +// Type assertion +type test3 = typeof product extends Partial ? true : false; +const assertQuickFix: test3 = true; +``` + +## Refactoring Support + +Demonstrate refactoring capabilities: + +###### refactoring-demo.ts + +```typescript +// Original function (try renaming 'calculateTotal') +function calculateTotal(items: number[]): number { + return items.reduce((sum, item) => sum + item, 0); +} + +// Usage of the function +const items = [1, 2, 3, 4, 5]; +const total = calculateTotal(items); + +// Extract to interface (select and use "Extract to interface") +type CartItem = { + id: string; + price: number; + quantity: number; +}; + +function calculateCartTotal(items: CartItem[]): number { + return items.reduce((sum, item) => sum + item.price * item.quantity, 0); +} + +// Type assertions +type test4 = typeof calculateTotal extends (items: number[]) => number ? true : false; +type test5 = typeof calculateCartTotal extends (items: CartItem[]) => number ? true : false; + +const assertRefactoring: [test4, test5] = [true, true]; +``` + +## Go to Definition + +Navigate through code with "Go to Definition": + +###### types.ts + +```typescript +export interface ApiResponse { + data: T; + status: number; + message: string; +} + +export interface ApiError { + code: number; + message: string; + details?: string; +} + +export type ApiResult = ApiResponse | ApiError; +``` + +###### api-usage.ts + +```typescript +import type { ApiResult, ApiResponse, ApiError } from './types.ts'; + +// Try "Go to Definition" on ApiResult, ApiResponse, and ApiError +function handleApiResponse(result: ApiResult): T | null { + if ('data' in result) { + return result.data; + } + console.error(`API Error: ${result.message}`); + return null; +} + +// Type assertions +type test6 = typeof handleApiResponse extends (result: ApiResult) => T | null ? true : false; +const assertDefinition: test6 = true; +``` + +## Find All References + +Locate all usages of a symbol: + +###### shared-types.ts + +```typescript +export interface BaseEntity { + id: string; + createdAt: Date; + updatedAt: Date; +} + +// Try "Find All References" on BaseEntity +export interface User extends BaseEntity { + name: string; + email: string; +} + +export interface Post extends BaseEntity { + title: string; + content: string; + authorId: string; +} +``` + +###### entity-usage.ts + +```typescript +import type { BaseEntity, User, Post } from './shared-types.ts'; + +function updateEntity(entity: T): T { + return { + ...entity, + updatedAt: new Date() + }; +} + +// Type assertions +type test7 = typeof updateEntity extends (entity: T) => T ? true : false; +const assertReferences: test7 = true; +``` + +## Signature Help + +Get help with function signatures: + +###### signature-help.ts + +```typescript +function transform( + value: T, + transformer: (input: T) => U, + errorHandler?: (error: Error) => U +): U { + try { + return transformer(value); + } catch (error) { + if (errorHandler && error instanceof Error) { + return errorHandler(error); + } + throw error; + } +} + +// Try hovering over transform to see signature help +const result = transform( + "hello", + (s) => s.length, + (e) => 0 +); + +// Type assertions +type test8 = typeof transform extends ( + value: T, + transformer: (input: T) => U, + errorHandler?: (error: Error) => U +) => U ? true : false; + +const assertSignature: test8 = true; +``` + +## Code Actions + +TypeScript suggests code actions: + +###### code-actions.ts + +```typescript +// Try using code actions to: +// 1. Add missing members +// 2. Implement interface +// 3. Convert to class + +interface Logger { + log(message: string): void; + error(message: string): void; + warn(message: string): void; +} + +// Implement interface (use code action) +class ConsoleLogger implements Logger { + log(message: string): void { + console.log(message); + } + + error(message: string): void { + console.error(message); + } + + warn(message: string): void { + console.warn(message); + } +} + +// Type assertions +type test9 = ConsoleLogger extends Logger ? true : false; +const assertActions: test9 = true; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/language-service.src.md +``` + +The test harness will: +1. Verify type assertions +2. Check code compilation +3. Validate interfaces +4. Test type relationships + +## Next Steps + +- Explore [Testing in Notebooks](./testing.src.md) +- Learn about [Performance Optimization](./performance.src.md) +- Study [Error Handling](./error-handling.src.md) \ No newline at end of file diff --git a/docs/advanced/performance.src.md b/docs/advanced/performance.src.md new file mode 100644 index 00000000..cbe62ee3 --- /dev/null +++ b/docs/advanced/performance.src.md @@ -0,0 +1,332 @@ + + +# Performance Optimization in Srcbook + +This notebook demonstrates strategies for optimizing performance in Srcbook notebooks, including type checking, compilation, and execution optimizations. + +## Setup + +First, let's set up our environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "typescript": "^5.3.3", + "node-cache": "^5.1.2" + } +} +``` + +## Type Checking Strategies + +Optimize type checking performance: + +###### tsconfig.json + +```json +{ + "compilerOptions": { + "incremental": true, + "tsBuildInfoFile": "./.tsbuildinfo", + "skipLibCheck": true, + "isolatedModules": true, + "noEmit": true + } +} +``` + +###### type-check-demo.ts + +```typescript +// Use type aliases for complex types +type ComplexObject = { + id: string; + data: { + values: number[]; + metadata: { + [key: string]: string | number | boolean; + }; + }; +}; + +// Instead of repeating complex types +function processObject(obj: ComplexObject): ComplexObject['data']['values'] { + return obj.data.values.map(v => v * 2); +} + +// Use mapped types for repetitive structures +type Nullable = { + [K in keyof T]: T[K] | null; +}; + +// Type assertions +type test1 = ComplexObject['data']['values'] extends number[] ? true : false; +type test2 = Nullable extends { id: string | null } ? true : false; + +const assertTypes: [test1, test2] = [true, true]; +``` + +## Incremental Compilation + +Leverage incremental compilation: + +###### build-cache.ts + +```typescript +import * as fs from 'fs'; +import * as path from 'path'; + +interface BuildCache { + version: string; + files: { + [path: string]: { + hash: string; + mtime: number; + }; + }; +} + +class BuildManager { + private cache: BuildCache = { + version: '1.0.0', + files: {} + }; + + private cacheFile = '.buildcache'; + + loadCache(): void { + if (fs.existsSync(this.cacheFile)) { + this.cache = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8')); + } + } + + saveCache(): void { + fs.writeFileSync(this.cacheFile, JSON.stringify(this.cache, null, 2)); + } + + needsRebuild(filePath: string): boolean { + const stats = fs.statSync(filePath); + const cached = this.cache.files[filePath]; + + if (!cached) return true; + + return cached.mtime !== stats.mtimeMs; + } + + updateFile(filePath: string): void { + const stats = fs.statSync(filePath); + this.cache.files[filePath] = { + hash: Date.now().toString(), + mtime: stats.mtimeMs + }; + } +} + +// Type assertions +type test3 = typeof BuildManager extends new () => { loadCache(): void } ? true : false; +const assertBuild: test3 = true; +``` + +## Project Structure Optimization + +Organize code for better performance: + +###### barrel-exports.ts + +```typescript +// Instead of individual imports +export * from './types/index.js'; +export * from './utils/index.js'; +export * from './models/index.js'; + +// Type-only exports +export type { Config } from './config.js'; +``` + +###### optimized-imports.ts + +```typescript +// Use specific imports instead of namespace imports +import { useState, useEffect } from 'react'; + +// Instead of +// import * as React from 'react'; + +// Use type imports for types +import type { ReactNode } from 'react'; + +// Type assertions +type test4 = typeof useState extends Function ? true : false; +type test5 = ReactNode extends any ? true : false; + +const assertImports: [test4, test5] = [true, true]; +``` + +## Memory Usage Optimization + +Manage memory efficiently: + +###### memory-manager.ts + +```typescript +import NodeCache from 'node-cache'; + +class MemoryManager { + private cache: NodeCache; + private maxItems: number; + + constructor(maxItems: number = 1000) { + this.maxItems = maxItems; + this.cache = new NodeCache({ + maxKeys: maxItems, + stdTTL: 600 // 10 minutes + }); + } + + set(key: string, value: T): void { + if (this.cache.keys().length >= this.maxItems) { + // Remove oldest item + const oldestKey = this.cache.keys()[0]; + this.cache.del(oldestKey); + } + this.cache.set(key, value); + } + + get(key: string): T | undefined { + return this.cache.get(key); + } + + clear(): void { + this.cache.flushAll(); + } +} + +// Type assertions +type test6 = MemoryManager extends { set(key: string, value: T): void } ? true : false; +const assertMemory: test6 = true; +``` + +## Execution Time Improvements + +Optimize code execution: + +###### performance-utils.ts + +```typescript +class PerformanceMonitor { + private marks: Map = new Map(); + + start(label: string): void { + this.marks.set(label, performance.now()); + } + + end(label: string): number { + const start = this.marks.get(label); + if (!start) throw new Error(`No start mark for ${label}`); + + const duration = performance.now() - start; + this.marks.delete(label); + return duration; + } + + async measure(label: string, fn: () => Promise): Promise { + this.start(label); + const result = await fn(); + const duration = this.end(label); + console.log(`${label}: ${duration.toFixed(2)}ms`); + return result; + } +} + +// Usage example +const monitor = new PerformanceMonitor(); + +async function expensiveOperation(): Promise { + return new Promise(resolve => { + setTimeout(() => { + resolve(Array(1000).fill(0).map((_, i) => i)); + }, 100); + }); +} + +await monitor.measure('expensive-op', expensiveOperation); + +// Type assertions +type test7 = typeof monitor.measure extends (label: string, fn: () => Promise) => Promise ? true : false; +const assertPerformance: test7 = true; +``` + +## Lazy Loading + +Implement lazy loading for better performance: + +###### lazy-loader.ts + +```typescript +class LazyLoader { + private instance: T | null = null; + private loading = false; + private callbacks: ((instance: T) => void)[] = []; + + constructor(private factory: () => Promise) {} + + async getInstance(): Promise { + if (this.instance) return this.instance; + + if (this.loading) { + return new Promise(resolve => { + this.callbacks.push(resolve); + }); + } + + this.loading = true; + this.instance = await this.factory(); + this.loading = false; + + this.callbacks.forEach(cb => cb(this.instance!)); + this.callbacks = []; + + return this.instance; + } + + clearInstance(): void { + this.instance = null; + } +} + +// Example usage +const lazyData = new LazyLoader(async () => { + // Simulate expensive data loading + await new Promise(resolve => setTimeout(resolve, 100)); + return { data: 'loaded' }; +}); + +const data = await lazyData.getInstance(); + +// Type assertions +type test8 = typeof lazyData.getInstance extends () => Promise<{ data: string }> ? true : false; +const assertLazy: test8 = true; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/performance.src.md +``` + +The test harness will: +1. Verify type assertions +2. Measure execution times +3. Check memory usage +4. Validate optimizations + +## Next Steps + +- Explore [Error Handling](./error-handling.src.md) +- Learn about [Interoperability](./interoperability.src.md) +- Study [Advanced Cell Features](./advanced-cells.src.md) \ No newline at end of file diff --git a/docs/advanced/testing.src.md b/docs/advanced/testing.src.md new file mode 100644 index 00000000..92987387 --- /dev/null +++ b/docs/advanced/testing.src.md @@ -0,0 +1,284 @@ + + +# Testing in Srcbook Notebooks + +This notebook demonstrates how to write and run tests within Srcbook notebooks, including unit testing, test runners, and coverage reporting. + +## Setup + +First, let's set up our testing environment: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "vitest": "^1.2.1", + "c8": "^9.1.0", + "@types/node": "^20.11.5" + } +} +``` + +## Unit Testing Basics + +Basic test structure in notebooks: + +###### math-utils.ts + +```typescript +export function add(a: number, b: number): number { + return a + b; +} + +export function multiply(a: number, b: number): number { + return a * b; +} + +export function divide(a: number, b: number): number { + if (b === 0) throw new Error('Division by zero'); + return a / b; +} +``` + +###### math-utils.test.ts + +```typescript +import { expect, test, describe } from 'vitest'; +import { add, multiply, divide } from './math-utils.ts'; + +describe('Math Utils', () => { + test('add combines two numbers', () => { + expect(add(2, 3)).toBe(5); + expect(add(-1, 1)).toBe(0); + expect(add(0, 0)).toBe(0); + }); + + test('multiply products two numbers', () => { + expect(multiply(2, 3)).toBe(6); + expect(multiply(-2, 3)).toBe(-6); + expect(multiply(0, 5)).toBe(0); + }); + + test('divide handles division correctly', () => { + expect(divide(6, 2)).toBe(3); + expect(divide(-6, 2)).toBe(-3); + expect(() => divide(5, 0)).toThrow('Division by zero'); + }); +}); + +// Type assertions +type test1 = typeof add extends (a: number, b: number) => number ? true : false; +type test2 = typeof multiply extends (a: number, b: number) => number ? true : false; +type test3 = typeof divide extends (a: number, b: number) => number ? true : false; + +const assertFunctions: [test1, test2, test3] = [true, true, true]; +``` + +## Test Runner Integration + +Configure test runners in notebooks: + +###### vitest.config.ts + +```typescript +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['**/*.test.ts'], + coverage: { + provider: 'c8', + reporter: ['text', 'json', 'html'], + exclude: ['node_modules/'] + } + } +}); +``` + +## Assertion Libraries + +Using different assertion styles: + +###### string-utils.ts + +```typescript +export function capitalize(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export function reverse(str: string): string { + return str.split('').reverse().join(''); +} + +export function truncate(str: string, length: number): string { + return str.length > length ? str.slice(0, length) + '...' : str; +} +``` + +###### string-utils.test.ts + +```typescript +import { expect, test, describe } from 'vitest'; +import { capitalize, reverse, truncate } from './string-utils.ts'; + +describe('String Utils', () => { + // Using toBe + test('capitalize transforms first letter', () => { + expect(capitalize('hello')).toBe('Hello'); + expect(capitalize('world')).toBe('World'); + }); + + // Using toEqual + test('reverse flips string characters', () => { + expect(reverse('hello')).toEqual('olleh'); + expect(reverse('12345')).toEqual('54321'); + }); + + // Using multiple assertions + test('truncate handles strings correctly', () => { + expect(truncate('hello world', 5)).toBe('hello...'); + expect(truncate('hi', 5)).toBe('hi'); + expect(truncate('', 5)).toBe(''); + }); +}); + +// Type assertions +type test4 = typeof capitalize extends (str: string) => string ? true : false; +type test5 = typeof reverse extends (str: string) => string ? true : false; +type test6 = typeof truncate extends (str: string, length: number) => string ? true : false; + +const assertStringFunctions: [test4, test5, test6] = [true, true, true]; +``` + +## Mocking and Stubbing + +Implement test doubles: + +###### api-client.ts + +```typescript +export interface ApiClient { + fetch(url: string): Promise; + post(url: string, data: unknown): Promise; +} + +export class RealApiClient implements ApiClient { + async fetch(url: string): Promise { + const response = await fetch(url); + return response.json(); + } + + async post(url: string, data: unknown): Promise { + const response = await fetch(url, { + method: 'POST', + body: JSON.stringify(data) + }); + return response.json(); + } +} +``` + +###### api-client.test.ts + +```typescript +import { expect, test, describe, vi } from 'vitest'; +import type { ApiClient } from './api-client.ts'; + +// Create mock implementation +const mockApiClient: ApiClient = { + fetch: vi.fn(), + post: vi.fn() +}; + +describe('API Client', () => { + test('fetch returns data', async () => { + const mockData = { id: 1, name: 'Test' }; + mockApiClient.fetch.mockResolvedValue(mockData); + + const result = await mockApiClient.fetch('/test'); + expect(result).toEqual(mockData); + expect(mockApiClient.fetch).toHaveBeenCalledWith('/test'); + }); + + test('post sends data', async () => { + const mockResponse = { success: true }; + const mockData = { name: 'Test' }; + mockApiClient.post.mockResolvedValue(mockResponse); + + const result = await mockApiClient.post('/test', mockData); + expect(result).toEqual(mockResponse); + expect(mockApiClient.post).toHaveBeenCalledWith('/test', mockData); + }); +}); + +// Type assertions +type test7 = typeof mockApiClient extends ApiClient ? true : false; +const assertMock: test7 = true; +``` + +## Test Coverage + +Configure and run coverage reports: + +###### coverage-config.ts + +```typescript +import { defineConfig } from 'c8'; + +export default defineConfig({ + include: ['src/**/*.ts'], + exclude: ['**/*.test.ts', '**/*.d.ts'], + reporter: ['text', 'html'], + all: true +}); +``` + +## Test Organization + +Structure tests effectively: + +###### test-utils.ts + +```typescript +import { expect } from 'vitest'; + +export function createTestSuite(name: string, tests: Record void | Promise>) { + describe(name, () => { + for (const [testName, testFn] of Object.entries(tests)) { + test(testName, testFn); + } + }); +} + +export function expectError(fn: () => unknown, message?: string) { + expect(fn).toThrow(message); +} + +// Type assertions +type test8 = typeof createTestSuite extends (name: string, tests: Record void | Promise>) => void ? true : false; +type test9 = typeof expectError extends (fn: () => unknown, message?: string) => void ? true : false; + +const assertTestUtils: [test8, test9] = [true, true]; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/testing.src.md +``` + +The test harness will: +1. Run all test suites +2. Generate coverage reports +3. Verify type assertions +4. Check mock implementations + +## Next Steps + +- Explore [Performance Optimization](./performance.src.md) +- Learn about [Error Handling](./error-handling.src.md) +- Study [Interoperability](./interoperability.src.md) \ No newline at end of file diff --git a/docs/advanced/typescript-config.src.md b/docs/advanced/typescript-config.src.md new file mode 100644 index 00000000..300e14c2 --- /dev/null +++ b/docs/advanced/typescript-config.src.md @@ -0,0 +1,325 @@ + + +# TypeScript Configuration in Srcbook + +This notebook explains how to configure TypeScript in Srcbook notebooks, including module resolution, type checking, and other compiler options. + +## Basic Configuration + +Every TypeScript notebook can have its own configuration: + +###### tsconfig.json + +```json +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "isolatedModules": true, + "types": ["node"] + } +} +``` + +## Testing the Configuration + +Let's verify our configuration works: + +###### config-test.ts + +```typescript +// This should work with ES2020 features +const numbers = [1, 2, 3, 4, 5]; +const sum = numbers.reduce((a, b) => a + b, 0); +const doubled = numbers.map(n => n * 2); + +// Verify configuration +const config = { + target: "ES2020", + moduleResolution: "bundler", + strict: true +} as const; + +// Type assertions to test configuration +type test1 = typeof sum extends number ? true : false; +type test2 = typeof doubled extends number[] ? true : false; + +const assertResults: [test1, test2] = [true, true]; +``` + +## Module Resolution + +Srcbook supports different module resolution strategies: + +###### module-config.json + +```json +{ + "compilerOptions": { + "moduleResolution": "bundler", + "baseUrl": ".", + "paths": { + "@utils/*": ["./utils/*"], + "@types/*": ["./types/*"] + } + } +} +``` + +Let's test path aliases: + +###### types/models.ts + +```typescript +export interface User { + id: string; + name: string; + email: string; +} + +export interface Post { + id: string; + title: string; + content: string; + authorId: string; +} +``` + +###### utils/user-helpers.ts + +```typescript +import type { User } from '@types/models'; + +export function formatUserName(user: User): string { + return `${user.name} <${user.email}>`; +} + +export function validateEmail(email: string): boolean { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); +} +``` + +###### path-alias-test.ts + +```typescript +import type { User } from '@types/models'; +import { formatUserName, validateEmail } from '@utils/user-helpers'; + +const user: User = { + id: "1", + name: "John Doe", + email: "john@example.com" +}; + +const formatted = formatUserName(user); +const isValidEmail = validateEmail(user.email); + +// Type assertions +type test3 = typeof formatted extends string ? true : false; +type test4 = typeof isValidEmail extends boolean ? true : false; + +const assertPathResults: [test3, test4] = [true, true]; +``` + +## Type Checking Options + +Configure type checking strictness: + +###### strict-config.json + +```json +{ + "compilerOptions": { + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "useUnknownInCatchVariables": true, + "alwaysStrict": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true + } +} +``` + +Test strict type checking: + +###### strict-checking.ts + +```typescript +// Strict null checks +function getLength(str: string | null): number { + if (str === null) { + return 0; + } + return str.length; +} + +// No implicit any +function map(array: T[], fn: (item: T) => U): U[] { + return array.map(fn); +} + +// Strict property initialization +class User { + private name: string; // Error without initialization + private email: string; + + constructor() { + this.name = ""; // Required + this.email = ""; // Required + } +} + +// No unchecked indexed access +const arr = [1, 2, 3]; +const item = arr[0]; // type is number | undefined + +// Type assertions +type test5 = typeof getLength extends (str: string | null) => number ? true : false; +type test6 = typeof map extends (array: T[], fn: (item: T) => U) => U[] ? true : false; + +const assertStrictResults: [test5, test6] = [true, true]; +``` + +## Project References + +Configure project references for modular development: + +###### project-refs.json + +```json +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "references": [ + { "path": "../shared" }, + { "path": "../utils" } + ] +} +``` + +Test project references: + +###### reference-test.ts + +```typescript +import { SharedType } from '../shared/types'; +import { UtilFunction } from '../utils/functions'; + +// Mock implementations for testing +type SharedType = { + id: string; + value: number; +}; + +const UtilFunction = (x: number) => x * 2; + +// Usage +const shared: SharedType = { + id: "1", + value: 42 +}; + +const result = UtilFunction(shared.value); + +// Type assertions +type test7 = typeof shared extends { id: string; value: number } ? true : false; +type test8 = typeof result extends number ? true : false; + +const assertRefResults: [test7, test8] = [true, true]; +``` + +## Performance Optimization + +Configure for optimal performance: + +###### performance-config.json + +```json +{ + "compilerOptions": { + "incremental": true, + "tsBuildInfoFile": "./.tsbuildinfo", + "skipLibCheck": true, + "isolatedModules": true + } +} +``` + +Test performance configurations: + +###### performance-test.ts + +```typescript +// Large type definition to test performance +type DeepNested = { + a: { + b: { + c: { + d: { + e: string; + }; + }; + }; + }; +}; + +// Create a large union type +type Union100 = + | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 + // ... (repeated for demonstration) + | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100; + +// Usage +const nested: DeepNested = { + a: { + b: { + c: { + d: { + e: "deep" + } + } + } + } +}; + +const union: Union100 = 42; + +// Type assertions +type test9 = typeof nested.a.b.c.d.e extends string ? true : false; +type test10 = typeof union extends number ? true : false; + +const assertPerfResults: [test9, test10] = [true, true]; +``` + +## Testing This Notebook + +Run the tests: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/typescript-config.src.md +``` + +The test harness will: +1. Validate all configurations +2. Check type assertions +3. Verify module resolution +4. Test strict mode compliance + +## Next Steps + +- Explore [Debugging Features](./debugging.src.md) +- Learn about [Language Service Integration](./language-service.src.md) +- Study [Performance Optimization](./performance.src.md) \ No newline at end of file diff --git a/docs/advanced/typescript-features.src.md b/docs/advanced/typescript-features.src.md new file mode 100644 index 00000000..a353fba9 --- /dev/null +++ b/docs/advanced/typescript-features.src.md @@ -0,0 +1,289 @@ + + +# Advanced TypeScript Features in Srcbook + +This notebook demonstrates advanced TypeScript features and how they can be used effectively in Srcbook notebooks. + +## Setup + +First, let's set up our environment with some useful types: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "zod": "^3.22.4" + } +} +``` + +## Type Inference + +TypeScript's type inference in Srcbook is powerful and contextual: + +###### type-inference.ts + +```typescript +// Basic inference +const numbers = [1, 2, 3, 4, 5]; // inferred as number[] +const mixed = [1, "hello", true]; // inferred as (string | number | boolean)[] + +// Function return type inference +function createPair(first: T, second: T) { + return { first, second }; +} + +const numberPair = createPair(1, 2); +const stringPair = createPair("hello", "world"); + +// Contextual typing with callbacks +const doubled = numbers.map(n => n * 2); // n is inferred as number +const filtered = numbers.filter(n => n > 2); // n is inferred as number + +// Assert types match expectations +type test1 = typeof numberPair.first extends number ? true : false; +type test2 = typeof stringPair.second extends string ? true : false; +type test3 = typeof doubled extends number[] ? true : false; +type test4 = typeof filtered extends number[] ? true : false; + +// These should all be true +type TestResults = [test1, test2, test3, test4]; +const assertResults: TestResults = [true, true, true, true]; +``` + +## Generic Types + +Srcbook supports complex generic type patterns: + +###### generic-types.ts + +```typescript +// Generic interface +interface Container { + value: T; + map(fn: (value: T) => U): Container; +} + +// Generic class implementation +class Box implements Container { + constructor(public value: T) {} + + map(fn: (value: T) => U): Container { + return new Box(fn(this.value)); + } +} + +// Generic constraints +interface HasLength { + length: number; +} + +function longest(a: T, b: T): T { + return a.length >= b.length ? a : b; +} + +// Usage examples +const numberBox = new Box(42); +const stringBox = numberBox.map(n => n.toString()); + +const longestArray = longest([1, 2], [1, 2, 3]); +const longestString = longest("hello", "world"); + +// Type assertions +type test5 = typeof stringBox.value extends string ? true : false; +type test6 = typeof longestArray extends number[] ? true : false; +type test7 = typeof longestString extends string ? true : false; + +const assertGenericResults: [test5, test6, test7] = [true, true, true]; +``` + +## Module Augmentation + +Srcbook allows extending existing modules: + +###### string-extensions.ts + +```typescript +// Declare module augmentation +declare global { + interface String { + toTitleCase(): string; + truncate(length: number): string; + } +} + +// Implement new methods +String.prototype.toTitleCase = function(this: string): string { + return this.replace(/\b\w/g, c => c.toUpperCase()); +}; + +String.prototype.truncate = function(this: string, length: number): string { + return this.length > length ? this.slice(0, length) + '...' : this; +}; + +// Usage example +const title = "hello world".toTitleCase(); +const truncated = "This is a long string".truncate(10); + +// Type assertions +type test8 = typeof title extends string ? true : false; +type test9 = typeof truncated extends string ? true : false; + +const assertAugmentationResults: [test8, test9] = [true, true]; +``` + +## Declaration Merging + +TypeScript's declaration merging in action: + +###### declaration-merging.ts + +```typescript +// Interface merging +interface Animal { + name: string; +} + +interface Animal { + age: number; +} + +// The interfaces are merged +const cat: Animal = { + name: "Whiskers", + age: 3 +}; + +// Namespace and class merging +class API { + static baseUrl: string = "https://api.example.com"; +} + +namespace API { + export function endpoint(path: string) { + return `${API.baseUrl}${path}`; + } +} + +// Usage example +const apiUrl = API.endpoint("/users"); + +// Type assertions +type test10 = typeof cat extends { name: string; age: number } ? true : false; +type test11 = typeof apiUrl extends string ? true : false; + +const assertMergeResults: [test10, test11] = [true, true]; +``` + +## Ambient Declarations + +Working with external JavaScript libraries: + +###### ambient-declarations.ts + +```typescript +// Declare an external library +declare namespace ExternalLib { + function calculate(x: number): number; + const version: string; + + interface Config { + timeout: number; + retries: number; + } +} + +// Mock implementation for testing +const ExternalLib = { + calculate: (x: number) => x * 2, + version: "1.0.0", +} as const; + +// Usage with type safety +const result = ExternalLib.calculate(21); +const version = ExternalLib.version; + +// Type assertions +type test12 = typeof result extends number ? true : false; +type test13 = typeof version extends string ? true : false; + +const assertAmbientResults: [test12, test13] = [true, true]; +``` + +## Type Guards and Assertions + +Advanced type narrowing techniques: + +###### type-guards.ts + +```typescript +// User-defined type guard +interface Bird { + fly(): void; + layEggs(): void; +} + +interface Fish { + swim(): void; + layEggs(): void; +} + +function isBird(pet: Bird | Fish): pet is Bird { + return 'fly' in pet; +} + +// Type assertion functions +function assertIsNumber(value: unknown): asserts value is number { + if (typeof value !== 'number') { + throw new Error('Value must be a number'); + } +} + +// Usage example +function move(pet: Bird | Fish) { + if (isBird(pet)) { + pet.fly(); // TypeScript knows pet is Bird + } else { + pet.swim(); // TypeScript knows pet is Fish + } +} + +// Test implementations +const bird: Bird = { + fly: () => console.log('Flying'), + layEggs: () => console.log('Laying bird eggs') +}; + +const fish: Fish = { + swim: () => console.log('Swimming'), + layEggs: () => console.log('Laying fish eggs') +}; + +// Type assertions +type test14 = typeof bird extends Bird ? true : false; +type test15 = typeof fish extends Fish ? true : false; + +const assertGuardResults: [test14, test15] = [true, true]; +``` + +## Testing This Notebook + +This notebook can be tested using the test harness: + +```bash +npx tsx docs/testing/run-tests.ts docs/advanced/typescript-features.src.md +``` + +The test harness will: +1. Verify all type assertions +2. Execute all code cells +3. Confirm no type errors +4. Validate runtime behavior + +## Next Steps + +- Explore [TypeScript Configuration](./typescript-config.src.md) +- Learn about [Debugging](./debugging.src.md) +- Study [Cell Execution](./cell-execution.src.md) \ No newline at end of file diff --git a/docs/api-reference.src.md b/docs/api-reference.src.md new file mode 100644 index 00000000..d86c309b --- /dev/null +++ b/docs/api-reference.src.md @@ -0,0 +1,264 @@ + + +# Srcbook API Reference + +This document provides technical documentation for Srcbook's core APIs, types, and interfaces. + +## Core Types + +### Session + +The Session represents a running Srcbook instance: + +###### session-type.ts + +```typescript +interface SessionType { + /** Unique identifier for the session */ + id: string; + + /** Path to the directory containing srcbook files */ + dir: string; + + /** Array of cells in the srcbook */ + cells: CellType[]; + + /** Programming language used ('typescript' or 'javascript') */ + language: CodeLanguageType; + + /** Optional TypeScript configuration */ + 'tsconfig.json'?: string; + + /** Timestamp when the session was opened */ + openedAt: number; +} +``` + +### Cells + +Cells are the fundamental building blocks of a Srcbook: + +###### cell-types.ts + +```typescript +/** Base properties for all cell types */ +interface BaseCellType { + id: string; + type: string; +} + +/** Markdown content cell */ +interface MarkdownCellType extends BaseCellType { + type: 'markdown'; + text: string; +} + +/** Title cell (h1 heading) */ +interface TitleCellType extends BaseCellType { + type: 'title'; + text: string; +} + +/** Code execution cell */ +interface CodeCellType extends BaseCellType { + type: 'code'; + source: string; + language: CodeLanguageType; + filename: string; + status: CellStatus; +} + +/** Special package.json cell */ +interface PackageJsonCellType extends BaseCellType { + type: 'package.json'; + source: string; + filename: 'package.json'; + status: CellStatus; +} + +/** Union type of all possible cells */ +type CellType = + | MarkdownCellType + | TitleCellType + | CodeCellType + | PackageJsonCellType; + +/** Possible cell execution states */ +type CellStatus = 'idle' | 'running' | 'error'; + +/** Supported programming languages */ +type CodeLanguageType = 'typescript' | 'javascript'; +``` + +## File Format + +### Srcbook Metadata + +Metadata is stored in HTML comments at the start of .src.md files: + +###### metadata-example.ts + +```typescript +interface SrcbookMetadata { + /** Programming language for the srcbook */ + language: CodeLanguageType; + + /** Optional TypeScript configuration */ + 'tsconfig.json'?: { + compilerOptions: { + [key: string]: any; + }; + }; +} + +// Example metadata comment: +// +``` + +### File Structure + +The .src.md file format follows these rules: + +1. Must begin with metadata comment +2. Must have exactly one h1 title +3. Can contain markdown cells +4. Code cells are defined by h6 headings + code blocks + +## CLI API + +The Srcbook CLI provides these commands: + +```bash +# Start the Srcbook server +srcbook start [options] + +# Import a Srcbook +srcbook import [options] + +# Display help +srcbook help [command] +``` + +### Start Options + +```typescript +interface StartOptions { + /** Port to run the server on */ + port?: number; + + /** Directory to store srcbooks */ + dir?: string; + + /** Disable analytics collection */ + noAnalytics?: boolean; +} +``` + +### Import Options + +```typescript +interface ImportOptions { + /** Target directory for the import */ + dir?: string; + + /** Force overwrite existing files */ + force?: boolean; +} +``` + +## Server API + +### HTTP Server + +The main HTTP server provides: +- Static file serving +- API endpoints +- WebSocket upgrade handling + +```typescript +import { app } from '@srcbook/api'; + +// Configure port +const port = process.env.PORT || 3000; + +// Start server +app.listen(port, () => { + console.log(`Server running on port ${port}`); +}); +``` + +### WebSocket Server + +Real-time communication for: +- Cell execution +- Output streaming +- State synchronization + +```typescript +import { wss } from '@srcbook/api'; + +wss.on('connection', (ws) => { + // Handle new connections + ws.on('message', (data) => { + // Handle incoming messages + }); +}); +``` + +## Environment Variables + +```typescript +interface Environment { + /** Port for the HTTP server */ + PORT?: string; + + /** Directory to store srcbooks */ + SRCBOOK_DIR?: string; + + /** Disable analytics collection */ + SRCBOOK_DISABLE_ANALYTICS?: string; + + /** AI provider API key */ + OPENAI_API_KEY?: string; + ANTHROPIC_API_KEY?: string; +} +``` + +## Constants + +```typescript +/** Default directory for storing srcbooks */ +export const SRCBOOKS_DIR: string; + +/** Distribution directory path */ +export const DIST_DIR: string; +``` + +## Best Practices + +1. **Cell Management** + - Keep cells focused and single-purpose + - Use meaningful filenames + - Group related functionality + +2. **Type Safety** + - Use TypeScript when possible + - Define interfaces for data structures + - Enable strict mode + +3. **Error Handling** + - Check cell execution status + - Handle WebSocket disconnections + - Validate user input + +4. **Security** + - Use environment variables for secrets + - Validate file paths + - Sanitize user input + +## Next Steps + +- Try the [Getting Started](./getting-started.src.md) guide +- Explore [Examples](./examples.src.md) +- Read about [Features](./features.src.md) +- Join our [Discord](https://discord.gg/shDEGBSe2d) \ No newline at end of file diff --git a/docs/contributing.src.md b/docs/contributing.src.md new file mode 100644 index 00000000..076cfd96 --- /dev/null +++ b/docs/contributing.src.md @@ -0,0 +1,280 @@ + + +# Contributing to Srcbook + +Thank you for your interest in contributing to Srcbook! This guide will help you get started with contributing to the project. + +## Ways to Contribute + +1. **Using Srcbook** + - File issues for bugs + - Request new features + - Share feedback + +2. **Contributing Code** + - Fix bugs + - Implement features + - Improve documentation + +3. **Being an Advocate** + - Share your Srcbooks + - Write about Srcbook + - Present at conferences/meetups + - Share on social media + +## Development Setup + +### Prerequisites + +- Node.js 18 or later +- pnpm 9.5 or later +- Git + +> Note: If you switch Node.js versions, run `pnpm rebuild -r` due to native bindings. + +### Getting Started + +1. Fork and clone the repository: + +###### clone-commands.sh + +```bash +git clone https://github.com/your-username/srcbook.git +cd srcbook +``` + +2. Install dependencies: + +###### install-deps.sh + +```bash +pnpm install +``` + +3. Start development servers: + +###### dev-servers.sh + +```bash +pnpm run dev +``` + +Visit http://localhost:5173 to see the app. + +### Project Structure + +The project is a monorepo with multiple packages: + +###### project-structure.ts + +```typescript +interface ProjectStructure { + packages: { + api: { + description: "Core API and server implementation", + technologies: ["Node.js", "Express", "WebSocket", "SQLite"] + }, + components: { + description: "Shared React components", + technologies: ["React", "TypeScript", "Tailwind CSS"] + }, + web: { + description: "Web application frontend", + technologies: ["React", "Vite", "TypeScript"] + }, + shared: { + description: "Shared types and utilities", + technologies: ["TypeScript"] + } + } +} +``` + +## Development Workflow + +### Running Scripts + +Top-level scripts: + +###### npm-scripts.sh + +```bash +# Type checking +pnpm run check-types + +# Linting +pnpm run lint + +# Testing +pnpm run test + +# Building +pnpm run build +``` + +Package-specific scripts: + +###### package-scripts.sh + +```bash +# Run script for specific package +pnpm run check-types --filter=@srcbook/api + +# Build specific package +pnpm run build --filter=@srcbook/web +``` + +### Making Changes + +1. Create a new branch: + +###### git-branch.sh + +```bash +git checkout -b feature/your-feature-name +``` + +2. Make your changes +3. Add a changeset: + +###### changeset.sh + +```bash +pnpm changeset +``` + +4. Commit and push: + +###### git-commit.sh + +```bash +git add . +git commit -m "feat: your feature description" +git push origin feature/your-feature-name +``` + +### Dependency Management + +Adding dependencies: + +###### add-deps.sh + +```bash +# Add to specific package +pnpm add --filter + +# Add as dev dependency +pnpm add -D --filter + +# Add workspace package +pnpm add @srcbook/shared --workspace --filter api +``` + +### Database Management + +SQLite database location: `~/.srcbook/srcbook.db` + +Creating migrations: + +1. Modify `packages/api/db/schema.mts` +2. Generate migration: + +###### generate-migration.sh + +```bash +pnpm run generate --name your_migration_name +``` + +Apply migrations: + +###### apply-migration.sh + +```bash +pnpm run migrate +``` + +## Pull Request Process + +1. **Before Coding** + - Open an issue for discussion + - Get maintainer feedback + - Clarify implementation details + +2. **Making Changes** + - Follow code style + - Add tests + - Update documentation + - Create changeset + +3. **Submitting PR** + - Reference related issues + - Provide clear description + - Include screenshots if relevant + - Ensure CI passes + +4. **Review Process** + - Address feedback + - Keep changes focused + - Be responsive + +## Community Guidelines + +### Code of Conduct + +- Be respectful and inclusive +- Welcome newcomers +- Focus on constructive feedback +- Follow project conventions + +### Communication Channels + +- GitHub Issues/Discussions +- [Discord Server](https://discord.gg/shDEGBSe2d) +- Email: feedback@srcbook.com + +### Documentation + +Help improve documentation by: +- Fixing errors +- Adding examples +- Clarifying concepts +- Creating tutorials + +### Sharing Srcbooks + +Share your Srcbooks to be featured on [the hub](https://hub.srcbook.com): + +1. Create useful Srcbooks +2. Test thoroughly +3. Add clear documentation +4. Email feedback@srcbook.com + +## Release Process + +Releases are automated using changesets: + +1. Changes merged to main +2. Changesets aggregated +3. Version bumped +4. Changelog updated +5. Packages published + +### Version Guidelines + +- Patch: Bug fixes, documentation +- Minor: New features, improvements +- Major: Breaking changes (rare) + +## Getting Help + +- Check [FAQ](./FAQ.md) +- Search existing issues +- Ask on Discord +- Email maintainers + +## Next Steps + +- Review [Getting Started](./getting-started.src.md) +- Explore [Examples](./examples.src.md) +- Read [API Reference](./api-reference.src.md) +- Join [Discord](https://discord.gg/shDEGBSe2d) \ No newline at end of file diff --git a/docs/examples.src.md b/docs/examples.src.md new file mode 100644 index 00000000..ee7a4d09 --- /dev/null +++ b/docs/examples.src.md @@ -0,0 +1,241 @@ + + +# Srcbook Examples + +This guide provides practical examples of using Srcbook for various development scenarios. Each example demonstrates different features and capabilities of the platform. + +## Quick Import + +You can import any of these examples using the srcbook CLI: + +```bash +npx srcbook@latest import +``` + +## Available Examples + +### 1. Getting Started +A quick tutorial exploring basic Srcbook concepts. + +```bash +npx srcbook@latest import getting-started +``` + +Key concepts covered: +- Basic cell types +- npm package usage +- Cell imports/exports +- Using secrets +- AI features + +### 2. Web Development with TypeScript +Build a simple web application using TypeScript and modern web APIs. + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "express": "^4.18.2", + "cors": "^2.8.5", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/express": "^4.17.21", + "@types/cors": "^2.8.17" + } +} +``` + +###### server.ts + +```typescript +import express from 'express'; +import cors from 'cors'; +import { z } from 'zod'; + +const app = express(); +app.use(cors()); +app.use(express.json()); + +// Data validation schema +const TodoSchema = z.object({ + title: z.string().min(1), + completed: z.boolean().default(false) +}); + +type Todo = z.infer; +const todos: Todo[] = []; + +// REST endpoints +app.get('/todos', (req, res) => { + res.json(todos); +}); + +app.post('/todos', (req, res) => { + const result = TodoSchema.safeParse(req.body); + if (!result.success) { + return res.status(400).json(result.error); + } + todos.push(result.data); + res.status(201).json(result.data); +}); + +app.listen(3000, () => { + console.log('Server running at http://localhost:3000'); +}); +``` + +### 3. LangGraph Agent Example +Build a stateful AI agent with memory using LangGraph and Tavily. + +```bash +npx srcbook@latest import langgraph-web-agent +``` + +Features demonstrated: +- AI agent implementation +- State management +- API integration +- TypeScript types for AI + +### 4. WebSocket Communication +Learn to build WebSocket clients and servers. + +```bash +npx srcbook@latest import websockets +``` + +###### websocket-server.ts + +```typescript +import { WebSocketServer } from 'ws'; + +const wss = new WebSocketServer({ port: 8080 }); + +wss.on('connection', (ws) => { + console.log('Client connected'); + + ws.on('message', (message) => { + console.log('Received:', message.toString()); + // Echo back to client + ws.send(`Server received: ${message}`); + }); + + ws.on('close', () => { + console.log('Client disconnected'); + }); +}); + +console.log('WebSocket server running on ws://localhost:8080'); +``` + +###### websocket-client.ts + +```typescript +import WebSocket from 'ws'; + +const ws = new WebSocket('ws://localhost:8080'); + +ws.on('open', () => { + console.log('Connected to server'); + ws.send('Hello from client!'); +}); + +ws.on('message', (data) => { + console.log('Received:', data.toString()); +}); + +ws.on('close', () => { + console.log('Disconnected from server'); +}); +``` + +### 5. Data Processing Pipeline +Example of building a data processing pipeline with TypeScript. + +###### types.ts + +```typescript +interface DataRecord { + id: string; + timestamp: Date; + value: number; +} + +interface ProcessedRecord extends DataRecord { + normalized: number; + category: 'low' | 'medium' | 'high'; +} + +export type { DataRecord, ProcessedRecord }; +``` + +###### processing.ts + +```typescript +import type { DataRecord, ProcessedRecord } from './types.ts'; + +export function normalizeValue(value: number, min: number, max: number): number { + return (value - min) / (max - min); +} + +export function categorizeValue(normalized: number): 'low' | 'medium' | 'high' { + if (normalized < 0.33) return 'low'; + if (normalized < 0.66) return 'medium'; + return 'high'; +} + +export function processRecord(record: DataRecord): ProcessedRecord { + const normalized = normalizeValue(record.value, 0, 100); + return { + ...record, + normalized, + category: categorizeValue(normalized) + }; +} +``` + +###### main.ts + +```typescript +import type { DataRecord } from './types.ts'; +import { processRecord } from './processing.ts'; + +// Sample data +const records: DataRecord[] = [ + { id: '1', timestamp: new Date(), value: 25 }, + { id: '2', timestamp: new Date(), value: 75 }, + { id: '3', timestamp: new Date(), value: 50 } +]; + +// Process records +const processed = records.map(processRecord); +console.log('Processed records:', processed); +``` + +## Community Examples + +The Srcbook community regularly contributes new examples. Visit the [hub](https://hub.srcbook.com) to discover more examples like: + +1. Web Scraping with Puppeteer +2. GraphQL API Development +3. React Component Library +4. Machine Learning with TensorFlow.js +5. Game Development with Phaser + +## Contributing Examples + +Want to share your own example? + +1. Create a .src.md file +2. Test it thoroughly +3. Email feedback@srcbook.com + +## Next Steps + +- Try the [Getting Started](./getting-started.src.md) guide +- Learn about [Features](./features.src.md) +- Read the [API Reference](./api-reference.src.md) +- Join our [Discord](https://discord.gg/shDEGBSe2d) \ No newline at end of file diff --git a/docs/features.src.md b/docs/features.src.md new file mode 100644 index 00000000..9f8743b6 --- /dev/null +++ b/docs/features.src.md @@ -0,0 +1,289 @@ + + +# Srcbook Features + +Srcbook combines several powerful features to create a unique development environment. This guide explores each major feature area with practical examples. + +## AI Integration + +Srcbook's AI capabilities act as a pair programmer, helping you develop faster and smarter. + +### AI Providers + +- Anthropic (recommended with claude-3-5-sonnet-latest) +- OpenAI +- Local models via Ollama + +### AI Features + +1. **Generate Complete Srcbooks** + - Create full applications from descriptions + - Generate tutorial notebooks + - Build example implementations + +2. **Cell Generation** + - Create new code cells from descriptions + - Generate documentation + - Implement specific functionality + +3. **Code Editing** + - Refactor existing code + - Fix bugs + - Add features + - Improve documentation + +Example of AI-assisted bug fixing: + +###### buggy-code.ts + +```typescript +function fibonacci(n: number): number { + if (n <= 1) return n; + return fibonacci(n - 1) + fibonacci(n - 2); +} + +// Bug: Stack overflow for large n +console.log(fibonacci(50)); +``` + +Use the sparkles icon and ask AI to "optimize this code to handle large numbers efficiently" for a memoized solution. + +## Interactive Notebook Interface + +### Cell Types + +1. **Markdown Cells** + - Rich text formatting + - Code syntax highlighting + - Tables and lists + - Task lists + - Math equations + - Mermaid diagrams + +Example mermaid diagram: + +```mermaid +graph TD + A[Markdown Cell] --> B[Documentation] + A --> C[Diagrams] + D[Code Cell] --> E[Execution] + D --> F[Exports] + E --> G[Output] + F --> H[Imports] +``` + +2. **Code Cells** + - TypeScript/JavaScript execution + - File-based organization + - Module imports/exports + - npm package support + - Real-time type checking + +### Cell Features + +- Hot reload on changes +- Error highlighting +- Console output +- Type information +- Export values +- Import from other cells + +## TypeScript Integration + +### Type System + +Full TypeScript support with: +- Type checking +- Interface definitions +- Generic types +- Module type declarations +- JSDoc comments + +Example: + +###### types.ts + +```typescript +/** Represents a user in the system */ +interface User { + id: string; + name: string; + email: string; + preferences: UserPreferences; +} + +/** User preference settings */ +interface UserPreferences { + theme: 'light' | 'dark'; + notifications: boolean; + language: string; +} + +/** User management functions */ +class UserManager { + private users: Map = new Map(); + + addUser(user: User): void { + this.users.set(user.id, user); + } + + getUser(id: string): User | undefined { + return this.users.get(id); + } +} +``` + +### Configuration + +Custom TypeScript configuration via tsconfig.json: + +###### tsconfig-example.json + +```json +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + } +} +``` + +## Package Management + +### Dependencies + +- npm package support +- Version management +- Automatic installation +- Import/export system + +Example package.json with common dependencies: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "axios": "^1.6.0", + "zod": "^3.22.0", + "date-fns": "^2.30.0", + "lodash-es": "^4.17.21" + }, + "devDependencies": { + "@types/lodash-es": "^4.17.12" + } +} +``` + +### Module System + +ES Modules support with cell imports: + +###### api-client.ts + +```typescript +import axios from 'axios'; + +export async function fetchData(url: string): Promise { + const response = await axios.get(url); + return response.data; +} +``` + +###### use-api.ts + +```typescript +import { fetchData } from './api-client.ts'; + +interface Todo { + id: number; + title: string; + completed: boolean; +} + +// Fetch and display a todo +const todo = await fetchData('https://jsonplaceholder.typicode.com/todos/1'); +console.log(todo); +``` + +## Export and Share + +### File Format + +- Standard markdown compatibility +- Executable code blocks +- Version control friendly +- Portable between environments + +### Sharing Options + +1. **Export as .src.md** + - Share via Git + - Send via email + - Post on GitHub + - Include in documentation + +2. **Import Options** + - Local files + - Git repositories + - URLs + - Hub examples + +### Hub Integration + +Access community examples: + +```bash +npx srcbook@latest import web-scraping-with-puppeteer +``` + +## Security Features + +### Secrets Management + +- Secure storage of API keys +- Environment variable access +- No secrets in code cells + +Example: + +###### secure-api.ts + +```typescript +// Access secrets via process.env +const apiKey = process.env.API_KEY; +const apiSecret = process.env.API_SECRET; + +if (!apiKey || !apiSecret) { + throw new Error('Missing API credentials'); +} + +// Use secrets securely +console.log('API configured with:', + apiKey.substring(0, 4) + '...' + apiKey.substring(apiKey.length - 4)); +``` + +## Analytics and Privacy + +- Optional usage tracking +- No PII collection +- Configurable settings +- Open-source verification + +Disable analytics: + +```bash +SRCBOOK_DISABLE_ANALYTICS=true srcbook start +``` + +## Next Steps + +- Try the [Getting Started](./getting-started.src.md) guide +- Explore [Examples](./examples.src.md) +- Read the [API Reference](./api-reference.src.md) +- Join the [Discord](https://discord.gg/shDEGBSe2d) community \ No newline at end of file diff --git a/docs/file-format.src.md b/docs/file-format.src.md new file mode 100644 index 00000000..c3fcdd2e --- /dev/null +++ b/docs/file-format.src.md @@ -0,0 +1,149 @@ + + +# Srcbook File Format (.src.md) + +Srcbook uses a specialized markdown format (.src.md) that combines literate programming with executable code cells. This document explains the format specification. + +## File Structure + +A .src.md file consists of: +1. Metadata header (required) +2. Title (required) +3. Content cells (markdown and code) + +### Metadata Header + +Every .src.md file must begin with a metadata comment specifying at minimum the language: + +###### metadata-example.src.md + +```markdown + +``` + +Optional metadata fields: +- tsconfig.json: TypeScript configuration +- other configuration as needed + +### Title + +Each .src.md file must have exactly one h1 (#) heading that serves as the title: + +###### title-example.src.md + +```markdown +# My Srcbook Title +``` + +### Content Cells + +#### Markdown Cells + +Regular markdown content is treated as markdown cells. You can use all standard markdown features: +- Headers (h2-h6) +- Lists +- Links +- Code blocks +- etc. + +#### Code Cells + +Code cells are defined by: +1. An h6 (###### ) heading containing the filename +2. A code block with the source code + +Example: + +###### hello.ts + +```typescript +// This is a code cell +console.log("Hello from a code cell!"); +``` + +#### Package.json Cell + +A special code cell named package.json can define dependencies: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "lodash": "^4.17.21" + } +} +``` + +### Cell Features + +#### Code Cell Properties +- Filename determines the language (e.g., .ts, .js) +- Code is executed in Node.js environment +- Cells can import from other cells +- Cells can use npm dependencies +- TypeScript cells are type-checked + +#### Markdown Cell Properties +- Support for all CommonMark syntax +- Support for GFM (tables, task lists) +- Support for mermaid diagrams +- Math equations via KaTeX + +## Example + +Here's a complete example of a .src.md file: + +###### complete-example.src.md + +```markdown + + +# Example Srcbook + +This is a markdown cell explaining the code below. + +###### greeter.ts + +```typescript +interface Person { + name: string; +} + +function greet(person: Person) { + return `Hello, ${person.name}!`; +} + +console.log(greet({ name: "World" })); +``` + +More markdown content here... +``` + +## File Export/Import + +Srcbooks can be: +- Exported to .src.md files +- Imported from .src.md files +- Shared and version controlled +- Rendered by any markdown viewer +- Executed in Srcbook environment + +## Best Practices + +1. Use descriptive filenames for code cells +2. Include package.json when using dependencies +3. Document code with markdown cells +4. Use TypeScript for type safety +5. Follow literate programming principles +6. Keep code cells focused and modular +7. Use mermaid for diagrams when helpful + +## Technical Details + +The .src.md format is parsed using: +- marked for markdown parsing +- Custom token grouping for cell identification +- Validation for format requirements +- TypeScript/JavaScript for code execution \ No newline at end of file diff --git a/docs/getting-started.src.md b/docs/getting-started.src.md new file mode 100644 index 00000000..2f46887f --- /dev/null +++ b/docs/getting-started.src.md @@ -0,0 +1,211 @@ + + +# Getting Started with Srcbook + +This guide will help you get started with Srcbook, walking you through installation, basic concepts, and your first Srcbook notebook. + +## Installation + +Srcbook runs locally on your machine as a CLI application with a web interface. + +### Prerequisites + +- Node.js v18 or later +- An AI provider API key (recommended: Anthropic with claude-3-5-sonnet-latest) +- npm, pnpm, or another package manager + +### Quick Start + +Run Srcbook using npx (recommended for latest version): + +###### install-command.sh + +```bash +# Using npm +npx srcbook@latest start + +# Using pnpm +pnpm dlx srcbook@latest start +``` + +Or install globally: + +###### global-install.sh + +```bash +# Using npm +npm install -g srcbook + +# Using pnpm +pnpm add -g srcbook + +# Then run +srcbook start +``` + +## Core Concepts + +### What is a Srcbook? + +A Srcbook is an interactive notebook that combines: +- Markdown for documentation +- Executable TypeScript/JavaScript code +- AI-powered development assistance +- Package management +- Local execution environment + +### Cell Types + +1. **Markdown Cells** + - Documentation and explanations + - Support for rich formatting + - Mermaid diagrams + - Math equations + +2. **Code Cells** + - Executable TypeScript/JavaScript + - File-based organization + - Import/export capabilities + - npm package support + +## Your First Srcbook + +Let's create a simple Srcbook that demonstrates the basic features: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "chalk": "^5.3.0" + } +} +``` + +### Basic Output + +Let's start with a simple TypeScript example: + +###### hello.ts + +```typescript +console.log("Hello, Srcbook!"); +``` + +### Using Types + +TypeScript support comes built-in: + +###### greeter.ts + +```typescript +interface Greeting { + message: string; + timestamp: Date; +} + +function createGreeting(name: string): Greeting { + return { + message: `Hello, ${name}!`, + timestamp: new Date() + }; +} + +console.log(createGreeting("Developer")); +``` + +### Using npm Packages + +You can use any npm package by adding it to package.json: + +###### colored-output.ts + +```typescript +import chalk from 'chalk'; + +console.log(chalk.blue('This text is blue!')); +console.log(chalk.green('This text is green!')); +``` + +### Cell Communication + +Cells can import from other cells: + +###### math-utils.ts + +```typescript +export function add(a: number, b: number): number { + return a + b; +} + +export function multiply(a: number, b: number): number { + return a * b; +} +``` + +###### calculator.ts + +```typescript +import { add, multiply } from './math-utils.ts'; + +console.log(`2 + 3 = ${add(2, 3)}`); +console.log(`4 * 5 = ${multiply(4, 5)}`); +``` + +## Using AI Features + +Srcbook includes powerful AI capabilities: + +1. **Generate New Cells** + - Click the "+" button + - Choose "AI Generate" + - Describe what you want + +2. **Edit Existing Cells** + - Click the sparkles icon + - Describe your desired changes + - Review and accept the diff + +3. **Generate Complete Srcbooks** + - From the home page + - Enter a topic or goal + - AI generates a full notebook + +### AI Configuration + +1. Open Settings (⚙️ icon) +2. Select AI Provider +3. Enter API Key +4. Optional: Configure local model via Ollama + +## Best Practices + +1. **Organization** + - Use clear cell names + - Group related functionality + - Document with markdown + - Keep cells focused + +2. **Dependencies** + - Manage in package.json + - Use specific versions + - Document requirements + +3. **TypeScript** + - Enable strict mode + - Use type annotations + - Document interfaces + +4. **Version Control** + - Commit .src.md files + - Include package.json + - Document setup steps + +## Next Steps + +- Explore the [File Format](./file-format.src.md) specification +- Check out more [Examples](./examples.src.md) +- Learn about [Features](./features.src.md) +- Join our [Discord](https://discord.gg/shDEGBSe2d) +- Watch tutorials on [YouTube](https://www.youtube.com/@srcbook) \ No newline at end of file diff --git a/docs/index.src.md b/docs/index.src.md new file mode 100644 index 00000000..6f113b03 --- /dev/null +++ b/docs/index.src.md @@ -0,0 +1,79 @@ + + +# Srcbook Documentation + +Welcome to Srcbook's documentation. Srcbook is a powerful tool that combines AI-powered web app generation with TypeScript-native literate programming. + +## Quick Links + +- [Getting Started](./getting-started.src.md) - Learn the basics of Srcbook +- [File Format](./file-format.src.md) - Understand the .src.md file format +- [Features](./features.src.md) - Explore Srcbook's capabilities +- [Examples](./examples.src.md) - See Srcbook in action +- [API Reference](./api-reference.src.md) - Technical documentation +- [Contributing](./contributing.src.md) - Help improve Srcbook + +## Web App Generator + +Explore our powerful web app generation capabilities: + +- [Overview](./web-app-generator/index.src.md) - Introduction to the web app generator +- [Architecture](./web-app-generator/architecture.src.md) - System design and components +- [AI Integration](./web-app-generator/ai-integration.src.md) - How AI generates and modifies code +- [Project Structure](./web-app-generator/project-structure.src.md) - Generated app organization +- [File System](./web-app-generator/file-system.src.md) - How files are managed +- [Package Management](./web-app-generator/package-management.src.md) - Dependency handling +- [Error Handling](./web-app-generator/error-handling.src.md) - Error recovery and prevention +- [Examples](./web-app-generator/examples.src.md) - Real-world usage examples + +## Advanced Topics + +Deep dive into advanced features: + +- [TypeScript Features](./advanced/typescript-features.src.md) - Advanced TypeScript usage +- [TypeScript Config](./advanced/typescript-config.src.md) - TypeScript configuration +- [Debugging](./advanced/debugging.src.md) - Debugging techniques +- [Cell Execution](./advanced/cell-execution.src.md) - How cells are executed +- [Language Service](./advanced/language-service.src.md) - TypeScript language service +- [Testing](./advanced/testing.src.md) - Testing capabilities +- [Performance](./advanced/performance.src.md) - Performance optimization +- [Error Handling](./advanced/error-handling.src.md) - Error handling strategies +- [Interoperability](./advanced/interoperability.src.md) - Working with other tools + +## Testing Infrastructure + +Learn about our testing capabilities: + +- [Notebook Test Harness](./testing/notebook-test-harness.src.md) - Testing notebooks + +## Key Features + +1. **AI-Powered Web App Generation** + - Natural language app creation + - Intelligent code generation + - Context-aware modifications + - Best practices enforcement + +2. **TypeScript-Native Literate Programming** + - Executable documentation + - Type-safe notebooks + - Interactive development + - Real-time validation + +3. **Modern Development Stack** + - React + Vite + TypeScript + - Tailwind CSS styling + - Package management + - Git integration + +4. **Developer Experience** + - Hot module replacement + - Type checking + - Error handling + - Real-time updates + +## Getting Help + +- Check our [Examples](./examples.src.md) for common use cases +- Read the [API Reference](./api-reference.src.md) for detailed information +- See [Contributing](./contributing.src.md) to help improve Srcbook \ No newline at end of file diff --git a/docs/table-of-contents.src.md b/docs/table-of-contents.src.md new file mode 100644 index 00000000..e6744958 --- /dev/null +++ b/docs/table-of-contents.src.md @@ -0,0 +1,182 @@ + + +# Srcbook Documentation - Table of Contents + +## Core Documentation + +1. [Getting Started](./getting-started.src.md) + - Installation + - Basic usage + - First notebook + - Configuration + +2. [File Format](./file-format.src.md) + - .src.md specification + - Cell types + - Metadata + - Configuration options + +3. [Features](./features.src.md) + - TypeScript integration + - Code execution + - Real-time validation + - Hot reloading + +4. [Examples](./examples.src.md) + - Basic examples + - Advanced usage + - Real-world scenarios + - Best practices + +5. [API Reference](./api-reference.src.md) + - Core API + - TypeScript API + - Configuration API + - Plugin API + +6. [Contributing](./contributing.src.md) + - Development setup + - Code style + - Testing + - Pull requests + +## Web App Generator + +1. [Overview](./web-app-generator/index.src.md) + - Introduction + - Key features + - Basic usage + - Quick start + +2. [Architecture](./web-app-generator/architecture.src.md) + - System components + - Data flow + - Component interactions + - Design principles + +3. [AI Integration](./web-app-generator/ai-integration.src.md) + - Prompt system + - Response processing + - Plan execution + - Context management + +4. [Project Structure](./web-app-generator/project-structure.src.md) + - Base structure + - Component organization + - State management + - Styling organization + - Type definitions + +5. [File System](./web-app-generator/file-system.src.md) + - File operations + - Directory management + - File watching + - File types + +6. [Package Management](./web-app-generator/package-management.src.md) + - Dependency management + - Package.json management + - Script management + - Lock file management + - Cache management + +7. [Error Handling](./web-app-generator/error-handling.src.md) + - Error types + - Error recovery + - Error reporting + - Error prevention + +8. [Examples](./web-app-generator/examples.src.md) + - Todo app + - Weather dashboard + - Blog platform + - E-commerce store + +9. [Test Harness](./web-app-generator/web-app-test-harness.src.md) + - Component testing + - End-to-End testing + - Performance testing + - Code quality verification + +## Advanced Topics + +1. [Overview](./advanced/index.src.md) + - Introduction to advanced features + - When to use advanced features + - Best practices + - Common patterns + +2. [TypeScript Features](./advanced/typescript-features.src.md) + - Type system + - Generics + - Decorators + - Advanced types + +3. [TypeScript Config](./advanced/typescript-config.src.md) + - Compiler options + - Project references + - Module resolution + - Type definitions + +4. [Debugging](./advanced/debugging.src.md) + - Debug tools + - Breakpoints + - Logging + - Error tracing + +5. [Cell Execution](./advanced/cell-execution.src.md) + - Execution model + - Context sharing + - Variable scope + - Async execution + +6. [Language Service](./advanced/language-service.src.md) + - Code completion + - Type checking + - Quick fixes + - Refactoring + +7. [Testing](./advanced/testing.src.md) + - Test framework + - Test runners + - Coverage + - Mocking + +8. [Performance](./advanced/performance.src.md) + - Optimization + - Caching + - Memory management + - Profiling + +9. [Error Handling](./advanced/error-handling.src.md) + - Error types + - Recovery strategies + - Logging + - Debugging + +10. [Interoperability](./advanced/interoperability.src.md) + - Module systems + - External tools + - APIs + - Data formats + +11. [Advanced Cells](./advanced/advanced-cells.src.md) + - Cell types + - Cell configuration + - Cell interactions + - Custom cell implementations + +## Testing Infrastructure + +1. [Notebook Test Harness](./testing/notebook-test-harness.src.md) + - Test setup + - Running tests + - Assertions + - Coverage reporting + +## Additional Resources + +- [FAQ](../FAQ.md) +- [Changelog](../CHANGELOG.md) +- [License](../LICENSE) +- [Privacy Policy](../PRIVACY-POLICY.md) diff --git a/docs/testing/notebook-test-harness.src.md b/docs/testing/notebook-test-harness.src.md new file mode 100644 index 00000000..87db02e3 --- /dev/null +++ b/docs/testing/notebook-test-harness.src.md @@ -0,0 +1,249 @@ + + +# Srcbook Notebook Test Harness + +This notebook provides utilities for testing other Srcbook notebooks. It helps ensure that documentation notebooks are accurate and runnable. + +## Test Harness Setup + +First, let's set up our dependencies: + +###### package.json + +```json +{ + "type": "module", + "dependencies": { + "glob": "^10.3.10", + "chalk": "^5.3.0", + "zod": "^3.22.4" + } +} +``` + +### Test Runner Types + +###### types.ts + +```typescript +interface TestResult { + notebookPath: string; + cells: CellResult[]; + success: boolean; + error?: string; +} + +interface CellResult { + id: string; + type: 'code' | 'markdown'; + success: boolean; + error?: string; + output?: any; +} + +interface TestSummary { + totalNotebooks: number; + passedNotebooks: number; + failedNotebooks: number; + results: TestResult[]; +} +``` + +### Notebook Loading + +###### notebook-loader.ts + +```typescript +import { glob } from 'glob'; +import { readFile } from 'fs/promises'; +import { join } from 'path'; + +export async function findNotebooks(dir: string): Promise { + const pattern = join(dir, '**/*.src.md'); + return glob(pattern); +} + +export async function loadNotebook(path: string): Promise { + return readFile(path, 'utf-8'); +} +``` + +### Test Runner + +###### test-runner.ts + +```typescript +import chalk from 'chalk'; +import type { TestResult, CellResult, TestSummary } from './types.ts'; +import { findNotebooks, loadNotebook } from './notebook-loader.ts'; + +export async function runTests(dir: string): Promise { + const notebooks = await findNotebooks(dir); + const results: TestResult[] = []; + + for (const notebook of notebooks) { + try { + const content = await loadNotebook(notebook); + const result = await testNotebook(content); + results.push({ + notebookPath: notebook, + ...result + }); + } catch (error) { + results.push({ + notebookPath: notebook, + cells: [], + success: false, + error: error instanceof Error ? error.message : String(error) + }); + } + } + + return summarizeResults(results); +} + +async function testNotebook(content: string): Promise> { + // TODO: Implement notebook testing logic + // This would: + // 1. Parse the notebook + // 2. Execute each cell + // 3. Verify outputs + // 4. Check types + return { + cells: [], + success: true + }; +} + +function summarizeResults(results: TestResult[]): TestSummary { + const totalNotebooks = results.length; + const passedNotebooks = results.filter(r => r.success).length; + const failedNotebooks = totalNotebooks - passedNotebooks; + + return { + totalNotebooks, + passedNotebooks, + failedNotebooks, + results + }; +} +``` + +### Results Reporter + +###### reporter.ts + +```typescript +import chalk from 'chalk'; +import type { TestSummary, TestResult } from './types.ts'; + +export function reportResults(summary: TestSummary): void { + console.log('\nNotebook Test Results:'); + console.log('=====================\n'); + + console.log(`Total Notebooks: ${summary.totalNotebooks}`); + console.log(`Passed: ${chalk.green(summary.passedNotebooks)}`); + console.log(`Failed: ${chalk.red(summary.failedNotebooks)}\n`); + + for (const result of summary.results) { + reportNotebookResult(result); + } +} + +function reportNotebookResult(result: TestResult): void { + const status = result.success ? chalk.green('PASS') : chalk.red('FAIL'); + console.log(`${status} ${result.notebookPath}`); + + if (!result.success && result.error) { + console.log(chalk.red(` Error: ${result.error}`)); + } + + for (const cell of result.cells) { + const cellStatus = cell.success ? chalk.green('✓') : chalk.red('✗'); + console.log(` ${cellStatus} ${cell.type} cell ${cell.id}`); + if (!cell.success && cell.error) { + console.log(chalk.red(` ${cell.error}`)); + } + } + + console.log(''); +} +``` + +### Test Runner Usage + +###### run-tests.ts + +```typescript +import { runTests } from './test-runner.ts'; +import { reportResults } from './reporter.ts'; + +async function main() { + try { + const summary = await runTests('../'); + reportResults(summary); + process.exit(summary.failedNotebooks > 0 ? 1 : 0); + } catch (error) { + console.error('Test runner failed:', error); + process.exit(1); + } +} + +main(); +``` + +## Running the Tests + +To run tests on all documentation notebooks: + +1. Install dependencies: +```bash +npm install +``` + +2. Run the test runner: +```bash +npx tsx run-tests.ts +``` + +## Test Categories + +The test harness verifies several aspects of each notebook: + +1. **Syntax Validation** + - Valid .src.md format + - Proper cell structure + - Correct metadata + +2. **Type Checking** + - TypeScript compilation + - Type inference + - Module resolution + +3. **Runtime Execution** + - Cell execution + - Output validation + - Error handling + +4. **Resource Usage** + - Memory consumption + - Execution time + - File system operations + +## Adding Tests + +To add tests for a new notebook: + +1. Create the notebook in the docs directory +2. Add any required test fixtures +3. Run the test harness +4. Review and fix any issues + +## Next Steps + +1. Implement the notebook testing logic in test-runner.ts +2. Add specific test cases for each documentation notebook +3. Set up continuous integration +4. Add performance benchmarks + +This test harness will help us ensure that all documentation notebooks are accurate and executable. \ No newline at end of file diff --git a/docs/testing/package-lock.json b/docs/testing/package-lock.json new file mode 100644 index 00000000..b6982e10 --- /dev/null +++ b/docs/testing/package-lock.json @@ -0,0 +1,2074 @@ +{ + "name": "srcbook-docs-testing", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "srcbook-docs-testing", + "version": "1.0.0", + "dependencies": { + "@types/marked": "^5.0.2", + "@types/node": "^20.11.5", + "chalk": "^5.3.0", + "glob": "^10.3.10", + "marked": "^11.1.1", + "typescript": "^5.3.3", + "vitest": "^1.2.1", + "zod": "^3.22.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", + "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", + "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", + "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", + "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", + "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", + "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", + "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", + "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", + "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", + "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", + "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", + "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", + "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", + "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", + "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", + "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", + "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", + "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", + "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "license": "MIT" + }, + "node_modules/@types/marked": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.2.tgz", + "integrity": "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz", + "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz", + "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==", + "license": "MIT", + "dependencies": { + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz", + "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==", + "license": "MIT", + "dependencies": { + "@vitest/utils": "1.6.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz", + "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==", + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz", + "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==", + "license": "MIT", + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==", + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "license": "MIT" + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/marked": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", + "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mlly": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", + "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^2.0.1", + "pkg-types": "^1.3.0", + "ufo": "^1.5.4" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.34.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", + "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.8", + "@rollup/rollup-android-arm64": "4.34.8", + "@rollup/rollup-darwin-arm64": "4.34.8", + "@rollup/rollup-darwin-x64": "4.34.8", + "@rollup/rollup-freebsd-arm64": "4.34.8", + "@rollup/rollup-freebsd-x64": "4.34.8", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", + "@rollup/rollup-linux-arm-musleabihf": "4.34.8", + "@rollup/rollup-linux-arm64-gnu": "4.34.8", + "@rollup/rollup-linux-arm64-musl": "4.34.8", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", + "@rollup/rollup-linux-riscv64-gnu": "4.34.8", + "@rollup/rollup-linux-s390x-gnu": "4.34.8", + "@rollup/rollup-linux-x64-gnu": "4.34.8", + "@rollup/rollup-linux-x64-musl": "4.34.8", + "@rollup/rollup-win32-arm64-msvc": "4.34.8", + "@rollup/rollup-win32-ia32-msvc": "4.34.8", + "@rollup/rollup-win32-x64-msvc": "4.34.8", + "fsevents": "~2.3.2" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", + "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", + "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz", + "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", + "license": "MIT", + "dependencies": { + "@vitest/expect": "1.6.1", + "@vitest/runner": "1.6.1", + "@vitest/snapshot": "1.6.1", + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.1", + "@vitest/ui": "1.6.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.24.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", + "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/docs/testing/package.json b/docs/testing/package.json new file mode 100644 index 00000000..3b46f428 --- /dev/null +++ b/docs/testing/package.json @@ -0,0 +1,16 @@ +{ + "name": "srcbook-docs-testing", + "version": "1.0.0", + "type": "module", + "private": true, + "dependencies": { + "glob": "^10.3.10", + "chalk": "^5.3.0", + "zod": "^3.22.4", + "vitest": "^1.2.1", + "marked": "^11.1.1", + "typescript": "^5.3.3", + "@types/node": "^20.11.5", + "@types/marked": "^5.0.2" + } +} \ No newline at end of file diff --git a/docs/testing/run-all-tests.ts b/docs/testing/run-all-tests.ts new file mode 100644 index 00000000..d804d2c9 --- /dev/null +++ b/docs/testing/run-all-tests.ts @@ -0,0 +1,56 @@ +import { glob } from 'glob'; +import { spawn } from 'child_process'; +import chalk from 'chalk'; +import * as path from 'path'; + +async function findNotebooks(): Promise { + return glob('../**/*.src.md', { + ignore: ['**/node_modules/**'] + }); +} + +async function runTest(notebook: string): Promise { + return new Promise((resolve) => { + console.log(chalk.blue(`\nTesting ${notebook}...\n`)); + + const test = spawn('npx', ['tsx', 'run-tests.ts', notebook], { + stdio: 'inherit' + }); + + test.on('close', (code) => { + const success = code === 0; + if (success) { + console.log(chalk.green(`\n✓ ${notebook} passed\n`)); + } else { + console.log(chalk.red(`\n✗ ${notebook} failed\n`)); + } + resolve(success); + }); + }); +} + +async function main() { + const notebooks = await findNotebooks(); + console.log(chalk.blue(`Found ${notebooks.length} notebooks to test\n`)); + + let passed = 0; + let failed = 0; + + for (const notebook of notebooks) { + const success = await runTest(notebook); + if (success) { + passed++; + } else { + failed++; + } + } + + console.log(chalk.blue('\nTest Summary:')); + console.log(chalk.green(`Passed: ${passed}`)); + console.log(chalk.red(`Failed: ${failed}`)); + console.log(chalk.blue(`Total: ${notebooks.length}\n`)); + + process.exit(failed > 0 ? 1 : 0); +} + +main().catch(console.error); \ No newline at end of file diff --git a/docs/testing/run-tests.ts b/docs/testing/run-tests.ts new file mode 100644 index 00000000..0f844d9a --- /dev/null +++ b/docs/testing/run-tests.ts @@ -0,0 +1,207 @@ +import { readFile } from 'fs/promises'; +import { marked } from 'marked'; +import { z } from 'zod'; +import chalk from 'chalk'; +import * as ts from 'typescript'; +import * as path from 'path'; + +// Schema for test results +const TestResultSchema = z.object({ + success: z.boolean(), + error: z.string().optional(), + output: z.unknown().optional() +}); + +type TestResult = z.infer; + +interface CodeBlock { + code: string; + lang: string; +} + +interface MarkedToken { + type: string; + text?: string; + lang?: string; + raw?: string; +} + +async function parseNotebook(content: string): Promise { + const tokens = marked.lexer(content) as MarkedToken[]; + const codeBlocks = tokens.filter(token => + token.type === 'code' && + token.text && + token.lang && + (token.lang === 'typescript' || token.lang === 'javascript') + ); + + return codeBlocks.map(block => ({ + code: block.text!, + lang: block.lang! + })); +} + +function createCompilerHost(options: ts.CompilerOptions): ts.CompilerHost { + return { + getSourceFile: (fileName, languageVersion) => { + if (fileName === 'test.ts') { + return ts.createSourceFile(fileName, '', languageVersion); + } + // Provide empty content for all imported files + return ts.createSourceFile(fileName, 'export {};', languageVersion); + }, + writeFile: () => {}, + getCurrentDirectory: () => '/', + getDirectories: () => [], + getCanonicalFileName: fileName => fileName, + useCaseSensitiveFileNames: () => true, + getNewLine: () => '\n', + fileExists: () => true, + readFile: () => '', + getDefaultLibFileName: () => 'lib.d.ts', + resolveModuleNames: (moduleNames, containingFile) => { + return moduleNames.map(moduleName => ({ + resolvedFileName: path.join('/', moduleName + '.ts'), + isExternalLibraryImport: false, + extension: '.ts' + })); + } + }; +} + +function validateTypeScript(code: string): TestResult { + // Add module context for top-level await + const processedCode = ` + // @ts-nocheck + declare global { + interface Window {} + interface Document {} + interface Navigator {} + interface Console {} + var window: Window; + var document: Document; + var navigator: Navigator; + var console: Console; + var localStorage: Storage; + } + export {}; + ${code} + `; + + // Create compiler options + const compilerOptions: ts.CompilerOptions = { + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.ESNext, + moduleResolution: ts.ModuleResolutionKind.Bundler, + strict: false, + esModuleInterop: true, + skipLibCheck: true, + noEmit: true, + lib: ['es2022', 'dom'], + types: ['node'], + allowJs: true, + checkJs: false, + noImplicitAny: false, + noImplicitThis: false, + noUnusedLocals: false, + noUnusedParameters: false + }; + + // Create a program + const fileName = 'test.ts'; + const sourceFile = ts.createSourceFile( + fileName, + processedCode, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TS + ); + + const host = createCompilerHost(compilerOptions); + const program = ts.createProgram({ + rootNames: [fileName], + options: compilerOptions, + host: { + ...host, + getSourceFile: (name) => + name === fileName ? sourceFile : host.getSourceFile(name, ts.ScriptTarget.Latest), + } + }); + + // Get diagnostics + const diagnostics = program.getSemanticDiagnostics(sourceFile); + + if (diagnostics.length > 0) { + const errors = diagnostics + .filter(d => d.category === ts.DiagnosticCategory.Error) + .map(diagnostic => { + const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + if (diagnostic.file && diagnostic.start) { + const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + return `Line ${line + 1}, Column ${character + 1}: ${message}`; + } + return message; + }); + + if (errors.length > 0) { + return { + success: false, + error: errors.join('\n') + }; + } + } + + return { success: true }; +} + +async function runTests(notebookPath: string): Promise { + try { + const content = await readFile(notebookPath, 'utf-8'); + const blocks = await parseNotebook(content); + + console.log(chalk.blue(`Testing ${blocks.length} code blocks...\n`)); + + let passed = 0; + let failed = 0; + + for (let i = 0; i < blocks.length; i++) { + const block = blocks[i]; + const result = validateTypeScript(block.code); + + if (result.success) { + console.log(chalk.green(`✓ Block ${i + 1} passed`)); + passed++; + } else { + console.log(chalk.red(`✗ Block ${i + 1} failed:`)); + console.log(chalk.red(` ${result.error}`)); + failed++; + } + } + + console.log(chalk.blue('\nTest Summary:')); + console.log(chalk.green(`Passed: ${passed}`)); + console.log(chalk.red(`Failed: ${failed}`)); + console.log(chalk.blue(`Total: ${blocks.length}\n`)); + + if (failed > 0) { + process.exit(1); + } + } catch (error) { + console.error(chalk.red('Error running tests:')); + console.error(error); + process.exit(1); + } +} + +// Get notebook path from command line +const notebookPath = process.argv[2]; +if (!notebookPath) { + console.error(chalk.red('Please provide a notebook path')); + process.exit(1); +} + +runTests(notebookPath).catch(error => { + console.error(chalk.red('Fatal error:')); + console.error(error); + process.exit(1); +}); \ No newline at end of file diff --git a/docs/testing/tsconfig.json b/docs/testing/tsconfig.json new file mode 100644 index 00000000..c81ce7b2 --- /dev/null +++ b/docs/testing/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "noEmit": true, + "lib": ["ESNext", "DOM"], + "types": ["node"], + "baseUrl": ".", + "paths": { + "@/*": ["./*"] + }, + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "useDefineForClassFields": true, + "noImplicitAny": false, + "noImplicitThis": false, + "noUnusedLocals": false, + "noUnusedParameters": false + }, + "include": ["**/*.ts", "**/*.js", "**/*.mts", "**/*.mjs"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/docs/web-app-generator/ai-integration.src.md b/docs/web-app-generator/ai-integration.src.md new file mode 100644 index 00000000..15a23eff --- /dev/null +++ b/docs/web-app-generator/ai-integration.src.md @@ -0,0 +1,272 @@ + + +# AI Integration in Web App Generator + +This document explains how Srcbook's web app generator integrates with AI to create and modify web applications. + +## AI System Overview + +The AI integration consists of several key components: + +###### ai-system.ts + +```typescript +interface AISystem { + // Core components + components: { + promptEngine: "Handles prompt construction"; + responseParser: "Parses AI responses"; + planExecutor: "Executes generated plans"; + contextManager: "Manages project context"; + }; + + // Workflow + workflow: { + input: "User request"; + context: "Project state"; + generation: "AI response"; + validation: "Plan verification"; + execution: "Change application"; + }; +} +``` + +## Prompt System + +The generator uses specialized prompts for different operations: + +### App Creation Prompt + +###### app-creation-prompt.ts + +```typescript +interface AppCreationPrompt { + // System prompt + systemPrompt: ` + You are helping build a front-end website application. + Behave like a senior engineer and designer. + Stack: React, Vite, TypeScript, Tailwind + Goal: Create functional MVP + `; + + // User request format + userRequest: ` + + Build a todo list app with local storage + + `; + + // Project context + projectContext: ` + + ... + ... + + `; +} +``` + +### App Modification Prompt + +###### app-modification-prompt.ts + +```typescript +interface AppModificationPrompt { + // System prompt + systemPrompt: ` + You are helping modify an existing web application. + Make targeted changes while maintaining code quality. + Preserve existing patterns and structure. + `; + + // User request with context + userRequest: ` + + Add dark mode support + + + + [Current project files...] + + `; +} +``` + +## Response Processing + +The AI responses are processed through a structured pipeline: + +###### response-processing.ts + +```typescript +interface ResponseProcessing { + // XML response format + interface PlanFormat { + planDescription: string; + actions: Array; + } + + // Action types + type FileAction = { + type: 'file'; + filename: string; + content: string; + description: string; + }; + + type CommandAction = { + type: 'command'; + command: 'npm install'; + packages: string[]; + description: string; + }; + + // Response validation + interface ResponseValidator { + validatePlan(plan: PlanFormat): ValidationResult; + checkFileActions(actions: FileAction[]): boolean; + checkCommandActions(actions: CommandAction[]): boolean; + } +} +``` + +## Plan Execution + +Generated plans are executed through a managed pipeline: + +###### plan-execution.ts + +```typescript +interface PlanExecution { + // Execution phases + phases: { + preparation: "Validate and prepare changes"; + fileSystem: "Apply file changes"; + dependencies: "Install packages"; + commands: "Run additional commands"; + verification: "Verify changes"; + }; + + // Change application + interface ChangeApplier { + applyFileChanges(files: FileAction[]): Promise; + applyCommands(commands: CommandAction[]): Promise; + rollback(error: Error): Promise; + } + + // Result verification + interface ChangeVerifier { + verifyFiles(changes: FileAction[]): Promise; + verifyDependencies(packages: string[]): Promise; + verifyBuild(): Promise; + } +} +``` + +## Context Management + +The system maintains context for better AI responses: + +###### context-management.ts + +```typescript +interface ContextManagement { + // Project context + interface ProjectContext { + files: Map; + dependencies: Map; + structure: ProjectStructure; + } + + // Context building + interface ContextBuilder { + buildContext(app: App): ProjectContext; + serializeContext(context: ProjectContext): string; + updateContext(context: ProjectContext, changes: Changes): ProjectContext; + } + + // Context optimization + interface ContextOptimizer { + pruneContext(context: ProjectContext): ProjectContext; + prioritizeFiles(context: ProjectContext): string[]; + summarizeChanges(changes: Changes): string; + } +} +``` + +## Error Handling + +The AI system includes robust error handling: + +###### error-handling.ts + +```typescript +interface AIErrorHandling { + // Error types + type AIError = + | { type: 'invalid_response'; message: string } + | { type: 'validation_failed'; issues: string[] } + | { type: 'execution_failed'; error: Error } + | { type: 'context_error'; context: string }; + + // Error recovery + interface ErrorRecovery { + handleError(error: AIError): Promise; + retryGeneration(context: ProjectContext): Promise; + rollbackChanges(changes: Changes): Promise; + } + + // Error reporting + interface ErrorReporting { + logError(error: AIError): void; + notifyUser(error: AIError): void; + collectMetrics(error: AIError): void; + } +} +``` + +## Usage Examples + +### Creating a New App + +```typescript +// Initialize AI system +const ai = new AISystem(); + +// Generate new app +const result = await ai.generateApp({ + prompt: "Create a todo list app with local storage", + stack: { + framework: "react", + language: "typescript", + styling: "tailwind" + } +}); + +// Apply changes +await result.applyChanges(); +``` + +### Modifying an App + +```typescript +// Load existing app context +const context = await ai.loadContext("app-id"); + +// Generate modifications +const changes = await ai.generateChanges({ + context, + prompt: "Add dark mode support" +}); + +// Validate and apply changes +if (await changes.validate()) { + await changes.apply(); +} +``` + +## Next Steps + +- Explore [Project Structure](./project-structure.src.md) +- Learn about [File System](./file-system.src.md) +- Study [Package Management](./package-management.src.md) \ No newline at end of file diff --git a/docs/web-app-generator/architecture.src.md b/docs/web-app-generator/architecture.src.md new file mode 100644 index 00000000..41a97a90 --- /dev/null +++ b/docs/web-app-generator/architecture.src.md @@ -0,0 +1,236 @@ + + +# Web App Generator Architecture + +This document explains the architecture of Srcbook's web app generator, including its components, interactions, and design principles. + +## System Overview + +The web app generator is built on several key components that work together: + +###### system-components.ts + +```typescript +interface SystemArchitecture { + // Core Components + components: { + aiEngine: "Handles AI generation and modifications"; + projectManager: "Manages app lifecycle and state"; + fileSystem: "Handles file operations"; + packageManager: "Manages dependencies"; + gitIntegration: "Handles version control"; + }; + + // Data Flow + dataFlow: { + input: "User prompt/request"; + processing: "AI generation/modification"; + output: "File changes/commands"; + feedback: "Real-time updates"; + }; +} +``` + +## Component Architecture + +### 1. AI Engine + +The AI component handles code generation and modifications: + +###### ai-engine.ts + +```typescript +interface AIEngine { + // Generation pipeline + pipeline: { + prompt: string; // User request + context: ProjectXML; // Current project state + response: PlanXML; // Generated changes + }; + + // Response parsing + interface PlanParser { + parseActions(xml: string): Action[]; + validateChanges(actions: Action[]): boolean; + applyChanges(actions: Action[]): Promise; + } + + // Change types + type Action = + | { type: 'file'; path: string; content: string } + | { type: 'command'; command: string }; +} +``` + +### 2. Project Manager + +Manages app lifecycle and state: + +###### project-manager.ts + +```typescript +interface ProjectManager { + // App lifecycle + interface AppLifecycle { + createApp(name: string): Promise; + loadApp(id: string): Promise; + deleteApp(id: string): Promise; + updateApp(id: string, changes: Changes): Promise; + } + + // State management + interface AppState { + metadata: { + id: string; + name: string; + createdAt: Date; + updatedAt: Date; + }; + files: Map; + dependencies: Map; + } + + // Event system + interface AppEvents { + onFileChange(callback: (file: FileChange) => void): void; + onStateChange(callback: (state: AppState) => void): void; + onError(callback: (error: AppError) => void): void; + } +} +``` + +### 3. File System Manager + +Handles file operations and watching: + +###### file-system.ts + +```typescript +interface FileSystem { + // File operations + interface FileOps { + writeFile(path: string, content: string): Promise; + readFile(path: string): Promise; + deleteFile(path: string): Promise; + moveFile(from: string, to: string): Promise; + } + + // Directory operations + interface DirOps { + createDir(path: string): Promise; + readDir(path: string): Promise; + deleteDir(path: string): Promise; + moveDir(from: string, to: string): Promise; + } + + // File watching + interface FileWatcher { + watch(path: string): FileWatcherInstance; + onFileChange(callback: (event: FileEvent) => void): void; + stopWatching(path: string): void; + } +} +``` + +### 4. Package Manager + +Handles dependencies and scripts: + +###### package-manager.ts + +```typescript +interface PackageManager { + // Dependency management + interface DependencyManager { + install(packages: string[]): Promise; + uninstall(packages: string[]): Promise; + update(packages: string[]): Promise; + } + + // Package.json management + interface PackageJsonManager { + read(): Promise; + write(content: PackageJson): Promise; + merge(updates: Partial): Promise; + } + + // Script execution + interface ScriptRunner { + run(script: string): Promise; + runWithOutput(script: string): AsyncIterator; + stop(script: string): Promise; + } +} +``` + +### 5. Git Integration + +Handles version control: + +###### git-integration.ts + +```typescript +interface GitIntegration { + // Repository management + interface RepoManager { + init(): Promise; + clone(url: string): Promise; + checkout(branch: string): Promise; + } + + // Change tracking + interface ChangeTracker { + stage(files: string[]): Promise; + commit(message: string): Promise; + push(remote: string, branch: string): Promise; + } + + // History management + interface HistoryManager { + log(): Promise; + show(commit: string): Promise; + diff(from: string, to: string): Promise; + } +} +``` + +## Component Interactions + +The components interact through well-defined interfaces: + +###### interactions.ts + +```typescript +interface ComponentInteractions { + // AI to Project Manager + interface AIToProject { + applyChanges(plan: Plan): Promise; + validateChanges(plan: Plan): Promise; + } + + // Project Manager to File System + interface ProjectToFS { + writeChanges(changes: FileChange[]): Promise; + watchProject(id: string): Promise; + } + + // Package Manager to Project + interface PackageToProject { + updateDependencies(changes: DependencyChange[]): Promise; + runScripts(scripts: string[]): Promise; + } + + // Git to Project + interface GitToProject { + trackChanges(files: string[]): Promise; + createCommit(message: string): Promise; + } +} +``` + +## Next Steps + +- Learn about [AI Integration](./ai-integration.src.md) +- Explore [Project Structure](./project-structure.src.md) +- Study [File System](./file-system.src.md) +- Understand [Package Management](./package-management.src.md) diff --git a/docs/web-app-generator/error-handling.src.md b/docs/web-app-generator/error-handling.src.md new file mode 100644 index 00000000..2bc399ed --- /dev/null +++ b/docs/web-app-generator/error-handling.src.md @@ -0,0 +1,232 @@ + + +# Error Handling in Web App Generator + +This document explains how Srcbook's web app generator handles errors and provides recovery mechanisms. + +## Error Types + +The system handles various types of errors: + +###### error-types.ts + +```typescript +interface ErrorTypes { + // Generation errors + type GenerationError = + | { type: 'invalid_prompt'; message: string } + | { type: 'ai_error'; message: string } + | { type: 'validation_failed'; issues: string[] }; + + // File system errors + type FSError = + | { type: 'file_not_found'; path: string } + | { type: 'permission_denied'; path: string } + | { type: 'disk_full'; path: string }; + + // Package errors + type PackageError = + | { type: 'install_failed'; package: string } + | { type: 'dependency_conflict'; packages: string[] } + | { type: 'version_mismatch'; details: VersionMismatch }; + + // Runtime errors + type RuntimeError = + | { type: 'build_failed'; message: string } + | { type: 'type_error'; location: string } + | { type: 'runtime_exception'; error: Error }; +} +``` + +## Error Recovery + +Implements recovery strategies: + +###### error-recovery.ts + +```typescript +interface ErrorRecovery { + // Recovery strategies + interface RecoveryStrategies { + handleGenerationError(error: GenerationError): Promise; + handleFSError(error: FSError): Promise; + handlePackageError(error: PackageError): Promise; + handleRuntimeError(error: RuntimeError): Promise; + } + + // Rollback mechanisms + interface RollbackMechanisms { + rollbackFileChanges(changes: FileChange[]): Promise; + rollbackPackageChanges(changes: PackageChange[]): Promise; + restoreBackup(backup: Backup): Promise; + } + + // State recovery + interface StateRecovery { + saveCheckpoint(): Promise; + restoreCheckpoint(checkpoint: Checkpoint): Promise; + getLastStableState(): Promise; + } +} +``` + +## Error Reporting + +Handles error reporting and logging: + +###### error-reporting.ts + +```typescript +interface ErrorReporting { + // Error logging + interface ErrorLogger { + logError(error: Error, context: Context): void; + logWarning(warning: Warning, context: Context): void; + logDiagnostic(diagnostic: Diagnostic): void; + } + + // User notifications + interface UserNotifications { + notifyError(error: Error): void; + notifyWarning(warning: Warning): void; + notifyRecovery(recovery: Recovery): void; + } + + // Error analytics + interface ErrorAnalytics { + trackError(error: Error): void; + analyzeErrorPatterns(): ErrorPatterns; + generateErrorReport(): ErrorReport; + } +} +``` + +## Error Prevention + +Implements preventive measures: + +###### error-prevention.ts + +```typescript +interface ErrorPrevention { + // Validation + interface Validation { + validateUserInput(input: unknown): boolean; + validateFileChanges(changes: FileChange[]): boolean; + validateDependencies(deps: Dependency[]): boolean; + } + + // Safety checks + interface SafetyChecks { + checkDiskSpace(): Promise; + checkPermissions(path: string): Promise; + checkNetworkConnectivity(): Promise; + } + + // Type checking + interface TypeChecking { + typeCheckFile(path: string): Promise; + validateTypes(changes: FileChange[]): Promise; + generateTypeDefinitions(): Promise; + } +} +``` + +## Usage Examples + +### Handling Generation Errors + +```typescript +// Error handling during app generation +try { + const app = await generator.createApp({ + name: "my-app", + prompt: "Create a todo app" + }); +} catch (error) { + if (error.type === 'invalid_prompt') { + // Handle invalid prompt + await errorHandler.handleGenerationError(error); + } else if (error.type === 'ai_error') { + // Handle AI service error + await errorHandler.retryGeneration(); + } +} + +// With recovery +const errorHandler = new ErrorHandler(); +errorHandler.onError(async (error) => { + // Save current state + const checkpoint = await errorHandler.saveCheckpoint(); + + try { + // Attempt recovery + await errorHandler.recover(error); + } catch (recoveryError) { + // Restore checkpoint if recovery fails + await errorHandler.restoreCheckpoint(checkpoint); + } +}); +``` + +### File System Error Handling + +```typescript +// File system error handling +try { + await fs.writeFile('src/App.tsx', content); +} catch (error) { + if (error.type === 'disk_full') { + // Clean up temporary files + await fs.cleanTemp(); + // Retry operation + await fs.writeFile('src/App.tsx', content); + } else if (error.type === 'permission_denied') { + // Request elevated permissions + await fs.requestPermissions(); + } +} + +// With automatic retry +const fs = new FileSystem({ + retryOptions: { + maxAttempts: 3, + delayMs: 1000, + backoff: 'exponential' + } +}); + +await fs.writeWithRetry('src/App.tsx', content); +``` + +### Package Management Errors + +```typescript +// Package installation error handling +try { + await pm.install(['react', 'react-dom']); +} catch (error) { + if (error.type === 'dependency_conflict') { + // Resolve conflicts + const resolution = await pm.resolveConflicts(error.packages); + await pm.install(resolution); + } else if (error.type === 'version_mismatch') { + // Update dependencies + await pm.updateDependencies(error.details); + } +} + +// With dependency resolution +const pm = new PackageManager({ + resolutionStrategy: 'semver', + conflictResolution: 'auto' +}); + +await pm.installSafely(['react', 'react-dom']); +``` + +## Next Steps + +- Study [Examples](./examples.src.md) +- Learn about [Project Structure](./project-structure.src.md) +- Explore [Package Management](./package-management.src.md) \ No newline at end of file diff --git a/docs/web-app-generator/examples.src.md b/docs/web-app-generator/examples.src.md new file mode 100644 index 00000000..ef87b220 --- /dev/null +++ b/docs/web-app-generator/examples.src.md @@ -0,0 +1,268 @@ + + +# Web App Generator Examples + +This document provides real-world examples of using Srcbook's web app generator. + +## Basic Todo App + +Creating a simple todo app with local storage: + +###### todo-app-example.ts + +```typescript +// 1. Generate the app +const app = await generator.createApp({ + name: "todo-app", + prompt: ` + Create a todo list app with: + - Add/edit/delete todos + - Local storage persistence + - Dark mode support + - Responsive design + ` +}); + +// 2. Generated files will include: + +// src/components/TodoList.tsx +interface TodoList { + const TodoList = () => { + const [todos, setTodos] = useState([]); + const [newTodo, setNewTodo] = useState(''); + + useEffect(() => { + const stored = localStorage.getItem('todos'); + if (stored) setTodos(JSON.parse(stored)); + }, []); + + const addTodo = (text: string) => { + const todo = { id: Date.now(), text, completed: false }; + const updated = [...todos, todo]; + setTodos(updated); + localStorage.setItem('todos', JSON.stringify(updated)); + }; + + return ( +
+ setNewTodo(e.target.value)} + className="border p-2 rounded" + /> + +
    + {todos.map(todo => ( + + ))} +
+
+ ); + }; +} +``` + +## Weather Dashboard + +Creating a weather dashboard with API integration: + +###### weather-app-example.ts + +```typescript +// 1. Generate the app +const app = await generator.createApp({ + name: "weather-dashboard", + prompt: ` + Create a weather dashboard with: + - Current weather display + - 5-day forecast + - Location search + - Temperature unit toggle + - Weather icons + ` +}); + +// 2. Generated files will include: + +// src/components/WeatherDashboard.tsx +interface WeatherDashboard { + const WeatherDashboard = () => { + const [location, setLocation] = useState(''); + const [weather, setWeather] = useState(null); + const [unit, setUnit] = useState<'C' | 'F'>('C'); + + const fetchWeather = async (loc: string) => { + const response = await fetch( + `https://api.weatherapi.com/v1/forecast.php?key=${API_KEY}&q=${loc}&days=5` + ); + const data = await response.json(); + setWeather(data); + }; + + return ( +
+
+ setLocation(e.target.value)} + className="border p-2 rounded flex-grow" + placeholder="Enter location..." + /> + + +
+ {weather && ( +
+ + +
+ )} +
+ ); + }; +} +``` + +## Blog Platform + +Creating a blog platform with markdown support: + +###### blog-app-example.ts + +```typescript +// 1. Generate the app +const app = await generator.createApp({ + name: "markdown-blog", + prompt: ` + Create a blog platform with: + - Markdown post editing + - Post previews + - Categories and tags + - Search functionality + - Responsive design + ` +}); + +// 2. Generated files will include: + +// src/components/MarkdownEditor.tsx +interface MarkdownEditor { + const MarkdownEditor = () => { + const [content, setContent] = useState(''); + const [preview, setPreview] = useState(''); + + useEffect(() => { + const rendered = marked(content); + setPreview(rendered); + }, [content]); + + return ( +
+
+