@cyanheads/mcp-ts-core 0.1.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +583 -0
- package/LICENSE +201 -0
- package/README.md +287 -0
- package/biome.json +103 -0
- package/dist/app.d.ts +82 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +222 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/init.d.ts +8 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +161 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/config/index.d.ts +349 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +464 -0
- package/dist/config/index.js.map +1 -0
- package/dist/context.d.ts +119 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +144 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/prompts/prompt-registration.d.ts +33 -0
- package/dist/mcp-server/prompts/prompt-registration.d.ts.map +1 -0
- package/dist/mcp-server/prompts/prompt-registration.js +91 -0
- package/dist/mcp-server/prompts/prompt-registration.js.map +1 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.d.ts +49 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.d.ts.map +1 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.js +39 -0
- package/dist/mcp-server/prompts/utils/newPromptDefinition.js.map +1 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.d.ts +37 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.d.ts.map +1 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.js +2 -0
- package/dist/mcp-server/prompts/utils/promptDefinition.js.map +1 -0
- package/dist/mcp-server/resources/resource-registration.d.ts +27 -0
- package/dist/mcp-server/resources/resource-registration.d.ts.map +1 -0
- package/dist/mcp-server/resources/resource-registration.js +85 -0
- package/dist/mcp-server/resources/resource-registration.js.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.d.ts +84 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.js +40 -0
- package/dist/mcp-server/resources/utils/newResourceDefinition.js.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.d.ts +32 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.js +103 -0
- package/dist/mcp-server/resources/utils/newResourceHandlerFactory.js.map +1 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts +94 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.js +2 -0
- package/dist/mcp-server/resources/utils/resourceDefinition.js.map +1 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts +14 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +111 -0
- package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -0
- package/dist/mcp-server/roots/roots-registration.d.ts +22 -0
- package/dist/mcp-server/roots/roots-registration.d.ts.map +1 -0
- package/dist/mcp-server/roots/roots-registration.js +25 -0
- package/dist/mcp-server/roots/roots-registration.js.map +1 -0
- package/dist/mcp-server/server.d.ts +34 -0
- package/dist/mcp-server/server.d.ts.map +1 -0
- package/dist/mcp-server/server.js +62 -0
- package/dist/mcp-server/server.js.map +1 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.d.ts +42 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.js +70 -0
- package/dist/mcp-server/tasks/core/sessionAwareTaskStore.js.map +1 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.d.ts +109 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.js +209 -0
- package/dist/mcp-server/tasks/core/storageBackedTaskStore.js.map +1 -0
- package/dist/mcp-server/tasks/core/taskManager.d.ts +103 -0
- package/dist/mcp-server/tasks/core/taskManager.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/taskManager.js +144 -0
- package/dist/mcp-server/tasks/core/taskManager.js.map +1 -0
- package/dist/mcp-server/tasks/core/taskTypes.d.ts +11 -0
- package/dist/mcp-server/tasks/core/taskTypes.d.ts.map +1 -0
- package/dist/mcp-server/tasks/core/taskTypes.js +13 -0
- package/dist/mcp-server/tasks/core/taskTypes.js.map +1 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.d.ts +108 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.js +14 -0
- package/dist/mcp-server/tasks/utils/taskToolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/tool-registration.d.ts +49 -0
- package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -0
- package/dist/mcp-server/tools/tool-registration.js +269 -0
- package/dist/mcp-server/tools/tool-registration.js.map +1 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.d.ts +73 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.js +45 -0
- package/dist/mcp-server/tools/utils/newToolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.d.ts +33 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.js +107 -0
- package/dist/mcp-server/tools/utils/newToolHandlerFactory.js.map +1 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts +118 -0
- package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/toolDefinition.js +2 -0
- package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +34 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js +68 -0
- package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -0
- package/dist/mcp-server/transports/ITransport.d.ts +15 -0
- package/dist/mcp-server/transports/ITransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/ITransport.js +2 -0
- package/dist/mcp-server/transports/ITransport.js.map +1 -0
- package/dist/mcp-server/transports/auth/authFactory.d.ts +11 -0
- package/dist/mcp-server/transports/auth/authFactory.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/authFactory.js +43 -0
- package/dist/mcp-server/transports/auth/authFactory.js.map +1 -0
- package/dist/mcp-server/transports/auth/authMiddleware.d.ts +24 -0
- package/dist/mcp-server/transports/auth/authMiddleware.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/authMiddleware.js +69 -0
- package/dist/mcp-server/transports/auth/authMiddleware.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authContext.d.ts +34 -0
- package/dist/mcp-server/transports/auth/lib/authContext.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authContext.js +25 -0
- package/dist/mcp-server/transports/auth/lib/authContext.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.d.ts +19 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.js +2 -0
- package/dist/mcp-server/transports/auth/lib/authTypes.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.d.ts +18 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.js +64 -0
- package/dist/mcp-server/transports/auth/lib/authUtils.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.d.ts +25 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.js +34 -0
- package/dist/mcp-server/transports/auth/lib/checkScopes.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.d.ts +34 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.js +58 -0
- package/dist/mcp-server/transports/auth/lib/claimParser.js.map +1 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.d.ts +25 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.js +30 -0
- package/dist/mcp-server/transports/auth/lib/withAuth.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts +18 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.js +2 -0
- package/dist/mcp-server/transports/auth/strategies/authStrategy.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts +14 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js +86 -0
- package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts +14 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.d.ts.map +1 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js +113 -0
- package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js.map +1 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.d.ts +25 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.js +112 -0
- package/dist/mcp-server/transports/http/httpErrorHandler.js.map +1 -0
- package/dist/mcp-server/transports/http/httpTransport.d.ts +47 -0
- package/dist/mcp-server/transports/http/httpTransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpTransport.js +396 -0
- package/dist/mcp-server/transports/http/httpTransport.js.map +1 -0
- package/dist/mcp-server/transports/http/httpTypes.d.ts +17 -0
- package/dist/mcp-server/transports/http/httpTypes.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/httpTypes.js +2 -0
- package/dist/mcp-server/transports/http/httpTypes.js.map +1 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.d.ts +21 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.js +44 -0
- package/dist/mcp-server/transports/http/protectedResourceMetadata.js.map +1 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.d.ts +33 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.js +54 -0
- package/dist/mcp-server/transports/http/sessionIdUtils.js.map +1 -0
- package/dist/mcp-server/transports/http/sessionStore.d.ts +87 -0
- package/dist/mcp-server/transports/http/sessionStore.d.ts.map +1 -0
- package/dist/mcp-server/transports/http/sessionStore.js +209 -0
- package/dist/mcp-server/transports/http/sessionStore.js.map +1 -0
- package/dist/mcp-server/transports/manager.d.ts +22 -0
- package/dist/mcp-server/transports/manager.d.ts.map +1 -0
- package/dist/mcp-server/transports/manager.js +62 -0
- package/dist/mcp-server/transports/manager.js.map +1 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.d.ts +44 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.d.ts.map +1 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.js +63 -0
- package/dist/mcp-server/transports/stdio/stdioTransport.js.map +1 -0
- package/dist/services/graph/core/GraphService.d.ts +205 -0
- package/dist/services/graph/core/GraphService.d.ts.map +1 -0
- package/dist/services/graph/core/GraphService.js +231 -0
- package/dist/services/graph/core/GraphService.js.map +1 -0
- package/dist/services/graph/core/IGraphProvider.d.ts +295 -0
- package/dist/services/graph/core/IGraphProvider.d.ts.map +1 -0
- package/dist/services/graph/core/IGraphProvider.js +8 -0
- package/dist/services/graph/core/IGraphProvider.js.map +1 -0
- package/dist/services/graph/types.d.ts +107 -0
- package/dist/services/graph/types.d.ts.map +1 -0
- package/dist/services/graph/types.js +8 -0
- package/dist/services/graph/types.js.map +1 -0
- package/dist/services/llm/core/ILlmProvider.d.ts +86 -0
- package/dist/services/llm/core/ILlmProvider.d.ts.map +1 -0
- package/dist/services/llm/core/ILlmProvider.js +2 -0
- package/dist/services/llm/core/ILlmProvider.js.map +1 -0
- package/dist/services/llm/providers/openrouter.provider.d.ts +187 -0
- package/dist/services/llm/providers/openrouter.provider.d.ts.map +1 -0
- package/dist/services/llm/providers/openrouter.provider.js +302 -0
- package/dist/services/llm/providers/openrouter.provider.js.map +1 -0
- package/dist/services/llm/types.d.ts +16 -0
- package/dist/services/llm/types.d.ts.map +1 -0
- package/dist/services/llm/types.js +9 -0
- package/dist/services/llm/types.js.map +1 -0
- package/dist/services/speech/core/ISpeechProvider.d.ts +92 -0
- package/dist/services/speech/core/ISpeechProvider.d.ts.map +1 -0
- package/dist/services/speech/core/ISpeechProvider.js +34 -0
- package/dist/services/speech/core/ISpeechProvider.js.map +1 -0
- package/dist/services/speech/core/SpeechService.d.ts +87 -0
- package/dist/services/speech/core/SpeechService.d.ts.map +1 -0
- package/dist/services/speech/core/SpeechService.js +135 -0
- package/dist/services/speech/core/SpeechService.js.map +1 -0
- package/dist/services/speech/providers/elevenlabs.provider.d.ts +77 -0
- package/dist/services/speech/providers/elevenlabs.provider.d.ts.map +1 -0
- package/dist/services/speech/providers/elevenlabs.provider.js +199 -0
- package/dist/services/speech/providers/elevenlabs.provider.js.map +1 -0
- package/dist/services/speech/providers/whisper.provider.d.ts +94 -0
- package/dist/services/speech/providers/whisper.provider.d.ts.map +1 -0
- package/dist/services/speech/providers/whisper.provider.js +240 -0
- package/dist/services/speech/providers/whisper.provider.js.map +1 -0
- package/dist/services/speech/types.d.ts +173 -0
- package/dist/services/speech/types.d.ts.map +1 -0
- package/dist/services/speech/types.js +8 -0
- package/dist/services/speech/types.js.map +1 -0
- package/dist/storage/core/IStorageProvider.d.ts +159 -0
- package/dist/storage/core/IStorageProvider.d.ts.map +1 -0
- package/dist/storage/core/IStorageProvider.js +2 -0
- package/dist/storage/core/IStorageProvider.js.map +1 -0
- package/dist/storage/core/StorageService.d.ts +22 -0
- package/dist/storage/core/StorageService.d.ts.map +1 -0
- package/dist/storage/core/StorageService.js +151 -0
- package/dist/storage/core/StorageService.js.map +1 -0
- package/dist/storage/core/storageFactory.d.ts +66 -0
- package/dist/storage/core/storageFactory.d.ts.map +1 -0
- package/dist/storage/core/storageFactory.js +122 -0
- package/dist/storage/core/storageFactory.js.map +1 -0
- package/dist/storage/core/storageValidation.d.ts +77 -0
- package/dist/storage/core/storageValidation.d.ts.map +1 -0
- package/dist/storage/core/storageValidation.js +303 -0
- package/dist/storage/core/storageValidation.js.map +1 -0
- package/dist/storage/providers/cloudflare/d1Provider.d.ts +94 -0
- package/dist/storage/providers/cloudflare/d1Provider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/d1Provider.js +347 -0
- package/dist/storage/providers/cloudflare/d1Provider.js.map +1 -0
- package/dist/storage/providers/cloudflare/kvProvider.d.ts +21 -0
- package/dist/storage/providers/cloudflare/kvProvider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/kvProvider.js +183 -0
- package/dist/storage/providers/cloudflare/kvProvider.js.map +1 -0
- package/dist/storage/providers/cloudflare/r2Provider.d.ts +28 -0
- package/dist/storage/providers/cloudflare/r2Provider.d.ts.map +1 -0
- package/dist/storage/providers/cloudflare/r2Provider.js +222 -0
- package/dist/storage/providers/cloudflare/r2Provider.js.map +1 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.d.ts +20 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.d.ts.map +1 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.js +282 -0
- package/dist/storage/providers/fileSystem/fileSystemProvider.js.map +1 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.d.ts +21 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.d.ts.map +1 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.js +139 -0
- package/dist/storage/providers/inMemory/inMemoryProvider.js.map +1 -0
- package/dist/storage/providers/supabase/supabase.types.d.ts +49 -0
- package/dist/storage/providers/supabase/supabase.types.d.ts.map +1 -0
- package/dist/storage/providers/supabase/supabase.types.js +8 -0
- package/dist/storage/providers/supabase/supabase.types.js.map +1 -0
- package/dist/storage/providers/supabase/supabaseProvider.d.ts +24 -0
- package/dist/storage/providers/supabase/supabaseProvider.d.ts.map +1 -0
- package/dist/storage/providers/supabase/supabaseProvider.js +209 -0
- package/dist/storage/providers/supabase/supabaseProvider.js.map +1 -0
- package/dist/testing/index.d.ts +53 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +132 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-global/errors.d.ts +83 -0
- package/dist/types-global/errors.d.ts.map +1 -0
- package/dist/types-global/errors.js +113 -0
- package/dist/types-global/errors.js.map +1 -0
- package/dist/utils/formatting/diffFormatter.d.ts +227 -0
- package/dist/utils/formatting/diffFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/diffFormatter.js +369 -0
- package/dist/utils/formatting/diffFormatter.js.map +1 -0
- package/dist/utils/formatting/index.d.ts +9 -0
- package/dist/utils/formatting/index.d.ts.map +1 -0
- package/dist/utils/formatting/index.js +9 -0
- package/dist/utils/formatting/index.js.map +1 -0
- package/dist/utils/formatting/markdownBuilder.d.ts +543 -0
- package/dist/utils/formatting/markdownBuilder.d.ts.map +1 -0
- package/dist/utils/formatting/markdownBuilder.js +674 -0
- package/dist/utils/formatting/markdownBuilder.js.map +1 -0
- package/dist/utils/formatting/tableFormatter.d.ts +261 -0
- package/dist/utils/formatting/tableFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/tableFormatter.js +456 -0
- package/dist/utils/formatting/tableFormatter.js.map +1 -0
- package/dist/utils/formatting/treeFormatter.d.ts +344 -0
- package/dist/utils/formatting/treeFormatter.d.ts.map +1 -0
- package/dist/utils/formatting/treeFormatter.js +400 -0
- package/dist/utils/formatting/treeFormatter.js.map +1 -0
- package/dist/utils/internal/encoding.d.ts +42 -0
- package/dist/utils/internal/encoding.d.ts.map +1 -0
- package/dist/utils/internal/encoding.js +87 -0
- package/dist/utils/internal/encoding.js.map +1 -0
- package/dist/utils/internal/error-handler/errorHandler.d.ts +140 -0
- package/dist/utils/internal/error-handler/errorHandler.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/errorHandler.js +318 -0
- package/dist/utils/internal/error-handler/errorHandler.js.map +1 -0
- package/dist/utils/internal/error-handler/helpers.d.ts +98 -0
- package/dist/utils/internal/error-handler/helpers.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/helpers.js +214 -0
- package/dist/utils/internal/error-handler/helpers.js.map +1 -0
- package/dist/utils/internal/error-handler/mappings.d.ts +85 -0
- package/dist/utils/internal/error-handler/mappings.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/mappings.js +234 -0
- package/dist/utils/internal/error-handler/mappings.js.map +1 -0
- package/dist/utils/internal/error-handler/types.d.ts +160 -0
- package/dist/utils/internal/error-handler/types.d.ts.map +1 -0
- package/dist/utils/internal/error-handler/types.js +6 -0
- package/dist/utils/internal/error-handler/types.js.map +1 -0
- package/dist/utils/internal/health.d.ts +60 -0
- package/dist/utils/internal/health.d.ts.map +1 -0
- package/dist/utils/internal/health.js +46 -0
- package/dist/utils/internal/health.js.map +1 -0
- package/dist/utils/internal/logger.d.ts +300 -0
- package/dist/utils/internal/logger.d.ts.map +1 -0
- package/dist/utils/internal/logger.js +573 -0
- package/dist/utils/internal/logger.js.map +1 -0
- package/dist/utils/internal/performance.d.ts +78 -0
- package/dist/utils/internal/performance.d.ts.map +1 -0
- package/dist/utils/internal/performance.js +227 -0
- package/dist/utils/internal/performance.js.map +1 -0
- package/dist/utils/internal/requestContext.d.ts +200 -0
- package/dist/utils/internal/requestContext.d.ts.map +1 -0
- package/dist/utils/internal/requestContext.js +163 -0
- package/dist/utils/internal/requestContext.js.map +1 -0
- package/dist/utils/internal/runtime.d.ts +49 -0
- package/dist/utils/internal/runtime.d.ts.map +1 -0
- package/dist/utils/internal/runtime.js +90 -0
- package/dist/utils/internal/runtime.js.map +1 -0
- package/dist/utils/internal/startupBanner.d.ts +23 -0
- package/dist/utils/internal/startupBanner.d.ts.map +1 -0
- package/dist/utils/internal/startupBanner.js +34 -0
- package/dist/utils/internal/startupBanner.js.map +1 -0
- package/dist/utils/metrics/tokenCounter.d.ts +97 -0
- package/dist/utils/metrics/tokenCounter.d.ts.map +1 -0
- package/dist/utils/metrics/tokenCounter.js +162 -0
- package/dist/utils/metrics/tokenCounter.js.map +1 -0
- package/dist/utils/network/fetchWithTimeout.d.ts +91 -0
- package/dist/utils/network/fetchWithTimeout.d.ts.map +1 -0
- package/dist/utils/network/fetchWithTimeout.js +305 -0
- package/dist/utils/network/fetchWithTimeout.js.map +1 -0
- package/dist/utils/pagination/pagination.d.ts +157 -0
- package/dist/utils/pagination/pagination.d.ts.map +1 -0
- package/dist/utils/pagination/pagination.js +191 -0
- package/dist/utils/pagination/pagination.js.map +1 -0
- package/dist/utils/parsing/csvParser.d.ts +84 -0
- package/dist/utils/parsing/csvParser.d.ts.map +1 -0
- package/dist/utils/parsing/csvParser.js +132 -0
- package/dist/utils/parsing/csvParser.js.map +1 -0
- package/dist/utils/parsing/dateParser.d.ts +103 -0
- package/dist/utils/parsing/dateParser.d.ts.map +1 -0
- package/dist/utils/parsing/dateParser.js +142 -0
- package/dist/utils/parsing/dateParser.js.map +1 -0
- package/dist/utils/parsing/frontmatterParser.d.ts +91 -0
- package/dist/utils/parsing/frontmatterParser.d.ts.map +1 -0
- package/dist/utils/parsing/frontmatterParser.js +163 -0
- package/dist/utils/parsing/frontmatterParser.js.map +1 -0
- package/dist/utils/parsing/index.d.ts +15 -0
- package/dist/utils/parsing/index.d.ts.map +1 -0
- package/dist/utils/parsing/index.js +15 -0
- package/dist/utils/parsing/index.js.map +1 -0
- package/dist/utils/parsing/jsonParser.d.ts +115 -0
- package/dist/utils/parsing/jsonParser.d.ts.map +1 -0
- package/dist/utils/parsing/jsonParser.js +177 -0
- package/dist/utils/parsing/jsonParser.js.map +1 -0
- package/dist/utils/parsing/pdfParser.d.ts +563 -0
- package/dist/utils/parsing/pdfParser.d.ts.map +1 -0
- package/dist/utils/parsing/pdfParser.js +775 -0
- package/dist/utils/parsing/pdfParser.js.map +1 -0
- package/dist/utils/parsing/thinkBlock.d.ts +31 -0
- package/dist/utils/parsing/thinkBlock.d.ts.map +1 -0
- package/dist/utils/parsing/thinkBlock.js +31 -0
- package/dist/utils/parsing/thinkBlock.js.map +1 -0
- package/dist/utils/parsing/xmlParser.d.ts +69 -0
- package/dist/utils/parsing/xmlParser.d.ts.map +1 -0
- package/dist/utils/parsing/xmlParser.js +140 -0
- package/dist/utils/parsing/xmlParser.js.map +1 -0
- package/dist/utils/parsing/yamlParser.d.ts +64 -0
- package/dist/utils/parsing/yamlParser.d.ts.map +1 -0
- package/dist/utils/parsing/yamlParser.js +129 -0
- package/dist/utils/parsing/yamlParser.js.map +1 -0
- package/dist/utils/scheduling/scheduler.d.ts +174 -0
- package/dist/utils/scheduling/scheduler.d.ts.map +1 -0
- package/dist/utils/scheduling/scheduler.js +248 -0
- package/dist/utils/scheduling/scheduler.js.map +1 -0
- package/dist/utils/security/idGenerator.d.ts +189 -0
- package/dist/utils/security/idGenerator.d.ts.map +1 -0
- package/dist/utils/security/idGenerator.js +301 -0
- package/dist/utils/security/idGenerator.js.map +1 -0
- package/dist/utils/security/index.d.ts +8 -0
- package/dist/utils/security/index.d.ts.map +1 -0
- package/dist/utils/security/index.js +8 -0
- package/dist/utils/security/index.js.map +1 -0
- package/dist/utils/security/rateLimiter.d.ts +171 -0
- package/dist/utils/security/rateLimiter.d.ts.map +1 -0
- package/dist/utils/security/rateLimiter.js +294 -0
- package/dist/utils/security/rateLimiter.js.map +1 -0
- package/dist/utils/security/sanitization.d.ts +430 -0
- package/dist/utils/security/sanitization.d.ts.map +1 -0
- package/dist/utils/security/sanitization.js +759 -0
- package/dist/utils/security/sanitization.js.map +1 -0
- package/dist/utils/telemetry/index.d.ts +12 -0
- package/dist/utils/telemetry/index.d.ts.map +1 -0
- package/dist/utils/telemetry/index.js +12 -0
- package/dist/utils/telemetry/index.js.map +1 -0
- package/dist/utils/telemetry/instrumentation.d.ts +62 -0
- package/dist/utils/telemetry/instrumentation.d.ts.map +1 -0
- package/dist/utils/telemetry/instrumentation.js +223 -0
- package/dist/utils/telemetry/instrumentation.js.map +1 -0
- package/dist/utils/telemetry/metrics.d.ts +170 -0
- package/dist/utils/telemetry/metrics.d.ts.map +1 -0
- package/dist/utils/telemetry/metrics.js +205 -0
- package/dist/utils/telemetry/metrics.js.map +1 -0
- package/dist/utils/telemetry/semconv.d.ts +147 -0
- package/dist/utils/telemetry/semconv.d.ts.map +1 -0
- package/dist/utils/telemetry/semconv.js +159 -0
- package/dist/utils/telemetry/semconv.js.map +1 -0
- package/dist/utils/telemetry/trace.d.ts +141 -0
- package/dist/utils/telemetry/trace.d.ts.map +1 -0
- package/dist/utils/telemetry/trace.js +193 -0
- package/dist/utils/telemetry/trace.js.map +1 -0
- package/dist/utils/types/guards.d.ts +209 -0
- package/dist/utils/types/guards.d.ts.map +1 -0
- package/dist/utils/types/guards.js +229 -0
- package/dist/utils/types/guards.js.map +1 -0
- package/dist/utils/types/index.d.ts +6 -0
- package/dist/utils/types/index.d.ts.map +1 -0
- package/dist/utils/types/index.js +6 -0
- package/dist/utils/types/index.js.map +1 -0
- package/dist/worker.d.ts +59 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +216 -0
- package/dist/worker.js.map +1 -0
- package/package.json +377 -0
- package/skills/README.md +38 -0
- package/skills/add-export/SKILL.md +49 -0
- package/skills/add-prompt/SKILL.md +97 -0
- package/skills/add-provider/SKILL.md +53 -0
- package/skills/add-resource/SKILL.md +107 -0
- package/skills/add-service/SKILL.md +113 -0
- package/skills/add-tool/SKILL.md +110 -0
- package/skills/api-auth/SKILL.md +173 -0
- package/skills/api-config/SKILL.md +68 -0
- package/skills/api-context/SKILL.md +321 -0
- package/skills/api-errors/SKILL.md +146 -0
- package/skills/api-services/SKILL.md +24 -0
- package/skills/api-services/references/graph.md +124 -0
- package/skills/api-services/references/llm.md +46 -0
- package/skills/api-services/references/speech.md +72 -0
- package/skills/api-testing/SKILL.md +263 -0
- package/skills/api-utils/SKILL.md +106 -0
- package/skills/api-utils/references/formatting.md +237 -0
- package/skills/api-utils/references/parsing.md +263 -0
- package/skills/api-utils/references/security.md +226 -0
- package/skills/api-workers/SKILL.md +165 -0
- package/skills/devcheck/SKILL.md +31 -0
- package/skills/maintenance/SKILL.md +52 -0
- package/skills/migrate-mcp-ts-template/SKILL.md +131 -0
- package/skills/release/SKILL.md +67 -0
- package/skills/setup/SKILL.md +89 -0
- package/skills/walkthrough-init/SKILL.md +50 -0
- package/templates/.env.example +17 -0
- package/templates/AGENTS.md +113 -0
- package/templates/CLAUDE.md +113 -0
- package/templates/_tsconfig.json +33 -0
- package/templates/biome.template.json +43 -0
- package/templates/package.json +26 -0
- package/templates/src/index.ts +16 -0
- package/templates/src/mcp-server/prompts/definitions/echo.prompt.ts +19 -0
- package/templates/src/mcp-server/resources/definitions/echo.resource.ts +30 -0
- package/templates/src/mcp-server/tools/definitions/echo.tool.ts +24 -0
- package/templates/vitest.config.ts +12 -0
- package/tsconfig.base.json +44 -0
- package/vitest.config.base.ts +38 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Speech Service (`services/speech`)
|
|
2
|
+
|
|
3
|
+
## `ISpeechProvider` interface
|
|
4
|
+
|
|
5
|
+
The provider interface — implemented by ElevenLabs (TTS) and Whisper (STT):
|
|
6
|
+
|
|
7
|
+
| Member | Type | Notes |
|
|
8
|
+
|:-------|:-----|:------|
|
|
9
|
+
| `.textToSpeech(opts)` | `Promise<TextToSpeechResult>` | Synthesize speech from text |
|
|
10
|
+
| `.speechToText(opts)` | `Promise<SpeechToTextResult>` | Transcribe audio to text |
|
|
11
|
+
| `.getVoices()` | `Promise<Voice[]>` | List available voices (TTS providers only) |
|
|
12
|
+
| `.healthCheck()` | `Promise<boolean>` | Liveness check |
|
|
13
|
+
| `.supportsTTS` | `boolean` | Check before calling `textToSpeech` |
|
|
14
|
+
| `.supportsSTT` | `boolean` | Check before calling `speechToText` |
|
|
15
|
+
| `.name` | `string` | Provider identifier (e.g., `'elevenlabs'`) |
|
|
16
|
+
|
|
17
|
+
## `SpeechService` orchestrator
|
|
18
|
+
|
|
19
|
+
`SpeechService` does **not** expose `textToSpeech`/`speechToText` directly. It manages independent TTS and STT provider instances. Access the underlying providers via accessors:
|
|
20
|
+
|
|
21
|
+
| Method | Return | Notes |
|
|
22
|
+
|:-------|:-------|:------|
|
|
23
|
+
| `.getTTSProvider()` | `ISpeechProvider` | Throws `McpError(InvalidRequest)` if no TTS provider configured |
|
|
24
|
+
| `.getSTTProvider()` | `ISpeechProvider` | Throws `McpError(InvalidRequest)` if no STT provider configured |
|
|
25
|
+
| `.hasTTS()` | `boolean` | Check if TTS is available |
|
|
26
|
+
| `.hasSTT()` | `boolean` | Check if STT is available |
|
|
27
|
+
| `.healthCheck()` | `Promise<{ tts: boolean; stt: boolean }>` | Checks both providers in parallel |
|
|
28
|
+
|
|
29
|
+
## Providers
|
|
30
|
+
|
|
31
|
+
| Provider | Capability | Tier 3 peer |
|
|
32
|
+
|:---------|:-----------|:------------|
|
|
33
|
+
| `ElevenLabsProvider` | TTS only (`supportsTTS: true`, `supportsSTT: false`) | ElevenLabs API (direct HTTP) |
|
|
34
|
+
| `WhisperProvider` | STT only (`supportsTTS: false`, `supportsSTT: true`) | `openai` (Whisper API). 25MB file size limit. |
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
| Env Var | Purpose |
|
|
39
|
+
|:--------|:--------|
|
|
40
|
+
| `SPEECH_TTS_ENABLED` | Enable TTS (`true`/`false`) |
|
|
41
|
+
| `SPEECH_TTS_API_KEY` | TTS provider API key (e.g., ElevenLabs) |
|
|
42
|
+
| `SPEECH_TTS_DEFAULT_MODEL_ID` | Default TTS model ID |
|
|
43
|
+
| `SPEECH_TTS_DEFAULT_VOICE_ID` | Default TTS voice ID |
|
|
44
|
+
| `SPEECH_STT_ENABLED` | Enable STT (`true`/`false`) |
|
|
45
|
+
| `SPEECH_STT_API_KEY` | STT provider API key (e.g., OpenAI) |
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// Text-to-Speech — access the provider, then call methods on it
|
|
51
|
+
const ttsProvider = speechService.getTTSProvider();
|
|
52
|
+
const ttsResult = await ttsProvider.textToSpeech({
|
|
53
|
+
text: 'Hello, world!',
|
|
54
|
+
voice: 'some-voice-id',
|
|
55
|
+
outputFormat: 'mp3_44100_128',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Speech-to-Text
|
|
59
|
+
const sttProvider = speechService.getSTTProvider();
|
|
60
|
+
const sttResult = await sttProvider.speechToText({
|
|
61
|
+
audioData: buffer,
|
|
62
|
+
mimeType: 'audio/mp3',
|
|
63
|
+
language: 'en',
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// List available voices
|
|
67
|
+
const voices = await ttsProvider.getVoices();
|
|
68
|
+
|
|
69
|
+
// Health check
|
|
70
|
+
const health = await speechService.healthCheck();
|
|
71
|
+
// health: { tts: boolean, stt: boolean }
|
|
72
|
+
```
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-testing
|
|
3
|
+
description: >
|
|
4
|
+
Testing patterns for MCP tool/resource handlers using `createMockContext` and Vitest. Covers mock context options, handler testing, McpError assertions, format testing, Vitest config setup, and test isolation conventions.
|
|
5
|
+
metadata:
|
|
6
|
+
author: cyanheads
|
|
7
|
+
version: "1.0"
|
|
8
|
+
audience: external
|
|
9
|
+
type: reference
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Tests target handler behavior directly — call `handler(input, ctx)`, assert on the return value or thrown error. The framework's handler factory (try/catch, formatting, telemetry) is not involved. Use `createMockContext` from `@cyanheads/mcp-ts-core/testing` to construct the `ctx` argument.
|
|
15
|
+
|
|
16
|
+
**Philosophy:** Test behavior, not implementation. Refactors should not break tests. Colocate test files with source (`foo.tool.ts` → `foo.tool.test.ts`). Integration tests at I/O boundaries over unit tests of internals.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## `createMockContext` options
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { createMockContext } from '@cyanheads/mcp-ts-core/testing';
|
|
24
|
+
|
|
25
|
+
createMockContext() // minimal — ctx.state operations throw without tenantId
|
|
26
|
+
createMockContext({ tenantId: 'test-tenant' }) // enables ctx.state (tenant-scoped in-memory storage)
|
|
27
|
+
createMockContext({ sample: vi.fn().mockResolvedValue(...) }) // with MCP sampling
|
|
28
|
+
createMockContext({ elicit: vi.fn().mockResolvedValue(...) }) // with elicitation
|
|
29
|
+
createMockContext({ progress: true }) // with task progress (ctx.progress populated)
|
|
30
|
+
createMockContext({ requestId: 'my-id' }) // override request ID (default: 'test-request-id')
|
|
31
|
+
createMockContext({ signal: controller.signal }) // custom AbortSignal
|
|
32
|
+
createMockContext({ auth: { clientId: 'test', scopes: [] } }) // with auth context
|
|
33
|
+
createMockContext({ uri: new URL('myscheme://item/123') }) // for resource handler testing
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`MockContextOptions` interface:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
interface MockContextOptions {
|
|
40
|
+
auth?: AuthContext;
|
|
41
|
+
elicit?: (message: string, schema: z.ZodObject<z.ZodRawShape>) => Promise<ElicitResult>;
|
|
42
|
+
progress?: boolean;
|
|
43
|
+
requestId?: string;
|
|
44
|
+
sample?: (messages: SamplingMessage[], opts?: SamplingOpts) => Promise<CreateMessageResult>;
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
tenantId?: string;
|
|
47
|
+
uri?: URL;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Option | Effect |
|
|
52
|
+
|:-------|:-------|
|
|
53
|
+
| _(none)_ | Minimal context — `ctx.state` operations throw without `tenantId`; `ctx.elicit`/`ctx.sample`/`ctx.progress` are `undefined` |
|
|
54
|
+
| `auth` | Sets `ctx.auth` for scope-checking tests |
|
|
55
|
+
| `elicit` | Assigns a function to `ctx.elicit` for testing elicitation calls |
|
|
56
|
+
| `progress` | Populates `ctx.progress` with real state-tracking implementation (see below) |
|
|
57
|
+
| `requestId` | Overrides `ctx.requestId` (default: `'test-request-id'`) |
|
|
58
|
+
| `sample` | Assigns a function to `ctx.sample` for testing sampling calls |
|
|
59
|
+
| `signal` | Overrides `ctx.signal` — useful for cancellation testing |
|
|
60
|
+
| `tenantId` | Sets `ctx.tenantId` and enables `ctx.state` operations with in-memory storage |
|
|
61
|
+
| `uri` | Sets `ctx.uri` for resource handler testing |
|
|
62
|
+
|
|
63
|
+
### Mock progress
|
|
64
|
+
|
|
65
|
+
When `progress: true`, `ctx.progress` is a real state-tracking object — not `vi.fn()` spies. It maintains internal state accessible via inspection properties:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const ctx = createMockContext({ progress: true });
|
|
69
|
+
// ctx.progress is typed as ContextProgress, but the mock exposes internal state:
|
|
70
|
+
const progress = ctx.progress as ContextProgress & {
|
|
71
|
+
_total: number;
|
|
72
|
+
_completed: number;
|
|
73
|
+
_messages: string[];
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
await ctx.progress!.setTotal(10);
|
|
77
|
+
await ctx.progress!.increment(3);
|
|
78
|
+
await ctx.progress!.update('step message');
|
|
79
|
+
|
|
80
|
+
expect(progress._total).toBe(10);
|
|
81
|
+
expect(progress._completed).toBe(3);
|
|
82
|
+
expect(progress._messages).toContain('step message');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Mock logger
|
|
86
|
+
|
|
87
|
+
`ctx.log` captures all log calls for inspection:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
const ctx = createMockContext();
|
|
91
|
+
const log = ctx.log as ContextLogger & {
|
|
92
|
+
calls: Array<{ level: string; msg: string; data?: unknown }>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
await myTool.handler(input, ctx);
|
|
96
|
+
expect(log.calls.some(c => c.level === 'info' && c.msg.includes('Processing'))).toBe(true);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Full test example
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// src/mcp-server/tools/definitions/my-tool.tool.test.ts
|
|
105
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
106
|
+
import { createMockContext } from '@cyanheads/mcp-ts-core/testing';
|
|
107
|
+
import { McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
108
|
+
import { myTool } from '@/mcp-server/tools/definitions/my-tool.tool.js';
|
|
109
|
+
|
|
110
|
+
describe('myTool', () => {
|
|
111
|
+
it('returns expected output', async () => {
|
|
112
|
+
const ctx = createMockContext();
|
|
113
|
+
const input = myTool.input.parse({ query: 'hello' });
|
|
114
|
+
const result = await myTool.handler(input, ctx);
|
|
115
|
+
expect(result.result).toBe('Found: hello');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('throws McpError on invalid state', async () => {
|
|
119
|
+
const ctx = createMockContext();
|
|
120
|
+
const input = myTool.input.parse({ query: 'TRIGGER_ERROR' });
|
|
121
|
+
await expect(myTool.handler(input, ctx)).rejects.toThrow(McpError);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('formats response correctly', () => {
|
|
125
|
+
const result = { result: 'test' };
|
|
126
|
+
const blocks = myTool.format!(result);
|
|
127
|
+
expect(blocks[0].type).toBe('text');
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Key points:
|
|
133
|
+
|
|
134
|
+
- Parse input through `myTool.input.parse(...)` — validates against the Zod schema and produces the typed input the handler expects.
|
|
135
|
+
- Call `myTool.handler(input, ctx)` directly — not through the MCP SDK or any framework wrapper.
|
|
136
|
+
- Assert on the return value for happy paths; use `.rejects.toThrow(McpError)` for error paths.
|
|
137
|
+
- Test `format` separately if the tool defines one — it is a pure function and needs no `ctx`.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Testing with optional capabilities
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
it('uses elicitation when available', async () => {
|
|
145
|
+
const elicit = vi.fn().mockResolvedValue({
|
|
146
|
+
action: 'accept',
|
|
147
|
+
data: { format: 'json' },
|
|
148
|
+
});
|
|
149
|
+
const ctx = createMockContext({ elicit });
|
|
150
|
+
const input = myTool.input.parse({ query: 'hello' });
|
|
151
|
+
await myTool.handler(input, ctx);
|
|
152
|
+
expect(elicit).toHaveBeenCalledOnce();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('uses sampling when available', async () => {
|
|
156
|
+
const sample = vi.fn().mockResolvedValue({
|
|
157
|
+
role: 'assistant',
|
|
158
|
+
content: { type: 'text', text: 'Summary text' },
|
|
159
|
+
});
|
|
160
|
+
const ctx = createMockContext({ sample });
|
|
161
|
+
const input = myTool.input.parse({ query: 'summarize this' });
|
|
162
|
+
const result = await myTool.handler(input, ctx);
|
|
163
|
+
expect(result.summary).toBeDefined();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('handles missing elicitation gracefully', async () => {
|
|
167
|
+
// ctx.elicit is undefined — handler must check before calling
|
|
168
|
+
const ctx = createMockContext();
|
|
169
|
+
const input = myTool.input.parse({ query: 'hello' });
|
|
170
|
+
// Should not throw even when ctx.elicit is absent
|
|
171
|
+
await expect(myTool.handler(input, ctx)).resolves.toBeDefined();
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Vitest config
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
// vitest.config.ts
|
|
181
|
+
import { defineConfig } from 'vitest/config';
|
|
182
|
+
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
183
|
+
|
|
184
|
+
export default defineConfig({
|
|
185
|
+
plugins: [tsconfigPaths()],
|
|
186
|
+
ssr: {
|
|
187
|
+
noExternal: ['zod'],
|
|
188
|
+
},
|
|
189
|
+
test: {
|
|
190
|
+
globals: true,
|
|
191
|
+
environment: 'node',
|
|
192
|
+
setupFiles: ['./tests/setup.ts'],
|
|
193
|
+
exclude: ['tests/integration/**', 'node_modules/**'],
|
|
194
|
+
pool: 'forks',
|
|
195
|
+
maxWorkers: 4,
|
|
196
|
+
isolate: true,
|
|
197
|
+
coverage: {
|
|
198
|
+
provider: 'istanbul',
|
|
199
|
+
reporter: ['text', 'json', 'html'],
|
|
200
|
+
include: ['src/**/*.ts'],
|
|
201
|
+
exclude: ['src/**/*.d.ts'],
|
|
202
|
+
thresholds: {
|
|
203
|
+
lines: 80,
|
|
204
|
+
functions: 75,
|
|
205
|
+
branches: 70,
|
|
206
|
+
statements: 80,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Key points:
|
|
214
|
+
- `tsconfigPaths()` resolves the `@/` path alias from `tsconfig.json` — no manual `resolve.alias` needed.
|
|
215
|
+
- `ssr: { noExternal: ['zod'] }` fixes Vite SSR transform issues with Zod 4.
|
|
216
|
+
- Integration tests (in `tests/integration/`) are excluded from the default run; they have their own config.
|
|
217
|
+
- `pool: 'forks'` with `isolate: true` prevents mock pollution between test files.
|
|
218
|
+
- `setupFiles` points to `tests/setup.ts` for any global test setup (e.g., env vars).
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Test isolation
|
|
223
|
+
|
|
224
|
+
**Construct dependencies fresh in `beforeEach`.** Never share mutable state across tests.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
228
|
+
import { initMyService } from '@/services/my-domain/my-service.js';
|
|
229
|
+
|
|
230
|
+
describe('myTool with service', () => {
|
|
231
|
+
beforeEach(() => {
|
|
232
|
+
// Re-initialize with a fresh instance before each test
|
|
233
|
+
initMyService(mockConfig, mockStorage);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('calls service correctly', async () => {
|
|
237
|
+
const ctx = createMockContext({ tenantId: 'test-tenant' });
|
|
238
|
+
// ...
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
- Re-init services with `initMyService()` (or equivalent) per test suite — the module-level singleton must be reset so tests don't share state.
|
|
244
|
+
- Vitest runs test files in separate worker threads — parallel file execution is safe by default.
|
|
245
|
+
- Use `createMockContext({ tenantId })` whenever the handler accesses `ctx.state` — omitting `tenantId` causes `ctx.state` to throw.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## McpError assertions
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import { McpError, JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
253
|
+
|
|
254
|
+
it('throws NotFound for missing resource', async () => {
|
|
255
|
+
const ctx = createMockContext();
|
|
256
|
+
const input = myTool.input.parse({ id: 'nonexistent' });
|
|
257
|
+
await expect(myTool.handler(input, ctx)).rejects.toMatchObject({
|
|
258
|
+
code: JsonRpcErrorCode.NotFound,
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Use `.rejects.toThrow(McpError)` to assert type only. Use `.rejects.toMatchObject({ code: ... })` when the specific error code matters.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-utils
|
|
3
|
+
description: >
|
|
4
|
+
API reference for all `@cyanheads/mcp-ts-core/utils/*` subpath exports. Use when looking up utility method signatures, options, peer dependencies, or usage patterns.
|
|
5
|
+
metadata:
|
|
6
|
+
author: cyanheads
|
|
7
|
+
version: "2.0"
|
|
8
|
+
audience: external
|
|
9
|
+
type: reference
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Utility subpath exports from `@cyanheads/mcp-ts-core/utils/*`. Complex utilities with rich APIs have dedicated reference files; simpler utilities are documented inline below.
|
|
15
|
+
|
|
16
|
+
**Tier 3** = optional peer dependency. Install as needed (e.g., `bun add js-yaml`). All Tier 3 methods are **async** (lazy-load deps on first call).
|
|
17
|
+
|
|
18
|
+
## References
|
|
19
|
+
|
|
20
|
+
| Reference | Path | Subpath | Covers |
|
|
21
|
+
|:----------|:-----|:--------|:-------|
|
|
22
|
+
| Formatting | `references/formatting.md` | `utils/formatting` | `markdown()`, `MarkdownBuilder`, `diffFormatter`, `tableFormatter`, `treeFormatter` — builder patterns, option types, style variants, usage examples |
|
|
23
|
+
| Parsing | `references/parsing.md` | `utils/parsing` | `yamlParser`, `xmlParser`, `csvParser`, `jsonParser`, `pdfParser`, `dateParser`, `frontmatterParser` — method signatures, option types, peer deps, `Allow` flags, PDF workflows |
|
|
24
|
+
| Security | `references/security.md` | `utils/security` | `sanitization`, `RateLimiter`, `IdGenerator` — config types, method details, sensitive fields, usage examples |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## `@cyanheads/mcp-ts-core/utils/network`
|
|
29
|
+
|
|
30
|
+
| Export | API | Notes |
|
|
31
|
+
|:-------|:----|:------|
|
|
32
|
+
| `fetchWithTimeout` | `(url, timeoutMs, context: RequestContext, options?: FetchWithTimeoutOptions) -> Promise<Response>` | Wraps `fetch` with `AbortController` timeout. `FetchWithTimeoutOptions` extends `RequestInit` (minus `signal`) and adds `rejectPrivateIPs?: boolean` and `signal?: AbortSignal` (external cancellation). SSRF protection: blocks RFC 1918, loopback, link-local, CGNAT, cloud metadata. DNS validation on Node; hostname-only on Workers. Manual redirect following (max 5) with per-hop SSRF check. |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## `@cyanheads/mcp-ts-core/utils/pagination`
|
|
37
|
+
|
|
38
|
+
| Export | API | Notes |
|
|
39
|
+
|:-------|:----|:------|
|
|
40
|
+
| `extractCursor` | `(params?) -> string \| undefined` | Extracts opaque cursor string from MCP request params. Checks `params.cursor` then `params._meta.cursor`. Returns `undefined` when no cursor is present. Does not decode. |
|
|
41
|
+
| `paginateArray` | `<T>(items, cursorStr, defaultPageSize, maxPageSize, context: RequestContext) -> PaginatedResult<T>` | Decodes cursor, slices array, returns `{ items, nextCursor?, totalCount }`. `nextCursor` omitted on last page. Throws `McpError(InvalidParams)` on invalid cursor. |
|
|
42
|
+
| `encodeCursor` | `(state: PaginationState) -> string` | Encodes `{ offset, limit, ...extra }` to opaque base64url string. |
|
|
43
|
+
| `decodeCursor` | `(cursor, context: RequestContext) -> PaginationState` | Decodes opaque base64url cursor. Throws `McpError(InvalidParams)` if malformed. |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## `@cyanheads/mcp-ts-core/utils/runtime`
|
|
48
|
+
|
|
49
|
+
| Export | API | Notes |
|
|
50
|
+
|:-------|:----|:------|
|
|
51
|
+
| `runtimeCaps` | `RuntimeCapabilities` object | Snapshot at import time. Fields: `isNode`, `isBun`, `isWorkerLike`, `isBrowserLike`, `hasProcess`, `hasBuffer`, `hasTextEncoder`, `hasPerformanceNow`. All booleans, never throw. |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## `@cyanheads/mcp-ts-core/utils/scheduling`
|
|
56
|
+
|
|
57
|
+
| Export | API | Notes |
|
|
58
|
+
|:-------|:----|:------|
|
|
59
|
+
| `schedulerService` | `.schedule(id, schedule, taskFunction, description) -> Promise<Job>` `.start(id) -> void` `.stop(id) -> void` `.remove(id) -> void` `.listJobs() -> Job[]` | **Async** `schedule()` — Tier 3 peer: `node-cron`. **Node-only** (throws `ConfigurationError` in Workers). Jobs start in stopped state; call `start(id)` to activate. Skips overlapping executions. Each tick gets fresh `RequestContext`. `Job: { id, schedule, description, isRunning, task }`. `taskFunction: (context: RequestContext) => void | Promise<void>`. |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## `@cyanheads/mcp-ts-core/utils/types`
|
|
64
|
+
|
|
65
|
+
The `utils/types` subpath exports only two guards. The full set of guards lives in the internal module and is not part of the public API.
|
|
66
|
+
|
|
67
|
+
| Export | Signature | Notes |
|
|
68
|
+
|:-------|:----------|:------|
|
|
69
|
+
| `isErrorWithCode` | `(error: unknown) -> error is Error & { code: unknown }` | Type guard — `true` when value is an `Error` instance with a `code` property |
|
|
70
|
+
| `isRecord` | `(value: unknown) -> value is Record<string, unknown>` | Type guard for plain objects (non-null, non-array) |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## `@cyanheads/mcp-ts-core/utils/logger`
|
|
75
|
+
|
|
76
|
+
| Export | API | Notes |
|
|
77
|
+
|:-------|:----|:------|
|
|
78
|
+
| `logger` | Pino instance. `.debug()` `.info()` `.notice()` `.warning()` `.error()` `.fatal()` | Global structured logger. Use `ctx.log` in handlers instead. `logger` is for lifecycle/background contexts (startup, shutdown, `setup()`). Auto-redacts sensitive fields. |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## `@cyanheads/mcp-ts-core/utils/requestContext`
|
|
83
|
+
|
|
84
|
+
| Export | API | Notes |
|
|
85
|
+
|:-------|:----|:------|
|
|
86
|
+
| `requestContextService` | `.createRequestContext(opts?) -> RequestContext` `.createFromHeaders(headers, fallback?) -> RequestContext` | Creates tracing context with `requestId`, `timestamp`, `traceId`, `spanId`, `tenantId`, `auth`. Internal — most consumers use `ctx` from handlers. |
|
|
87
|
+
| `RequestContext` | Type: `{ requestId, timestamp, operation?, traceId?, spanId?, tenantId?, auth? }` | Request tracing metadata. |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## `@cyanheads/mcp-ts-core/utils/errorHandler`
|
|
92
|
+
|
|
93
|
+
| Export | API | Notes |
|
|
94
|
+
|:-------|:----|:------|
|
|
95
|
+
| `ErrorHandler` | `.tryCatch<T>(fn, opts) -> Promise<T>` `.handleError(error, opts) -> Error` `.determineErrorCode(error) -> JsonRpcErrorCode` `.mapError(error, mappings, defaultFactory?) -> T \| Error` `.formatError(error) -> Record<string, unknown>` | Service-level error handling. `tryCatch` wraps async or sync `fn`, logs via `handleError`, and always rethrows. No `.tryCatchSync()`. Use in services, NOT in tool handlers (those throw raw `McpError`). Options: `operation`, `context`, `errorCode`, `input`, `rethrow`, `includeStack`, `critical`, `errorMapper`. |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## `@cyanheads/mcp-ts-core/utils/telemetry`
|
|
100
|
+
|
|
101
|
+
| Export | Subpath | API | Notes |
|
|
102
|
+
|:-------|:--------|:----|:------|
|
|
103
|
+
| `initInstrumentation` | `telemetry/instrumentation` | `(config) -> void` | Initializes OpenTelemetry SDK with OTLP exporter. Call once at startup. |
|
|
104
|
+
| `metrics` | `telemetry/metrics` | `.recordToolExecution(name, duration, success)` `.recordResourceAccess(uri, duration)` `.getMetrics()` | In-process metrics collection with OTEL integration. |
|
|
105
|
+
| `trace` | `telemetry/trace` | `.startSpan(name, opts?)` `.runInSpan(name, fn)` `.runInContext(fn)` | Tracing helpers wrapping OTEL `@opentelemetry/api`. |
|
|
106
|
+
| `SEMCONV_*` | `telemetry/semconv` | 38 semantic convention constants | Attribute keys following OpenTelemetry semantic conventions. |
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Formatting Utilities (`utils/formatting`)
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { markdown, MarkdownBuilder, diffFormatter, tableFormatter, treeFormatter } from '@cyanheads/mcp-ts-core/utils/formatting';
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## `markdown()` / `MarkdownBuilder`
|
|
10
|
+
|
|
11
|
+
`markdown()` is a factory shorthand for `new MarkdownBuilder()`. Fluent builder — all methods return `this` except `build()`.
|
|
12
|
+
|
|
13
|
+
### Methods
|
|
14
|
+
|
|
15
|
+
| Method | Signature | Notes |
|
|
16
|
+
|:-------|:----------|:------|
|
|
17
|
+
| `h1` | `(text, emoji?) -> this` | `# [emoji ]text` |
|
|
18
|
+
| `h2` | `(text, emoji?) -> this` | `## [emoji ]text` |
|
|
19
|
+
| `h3` | `(text, emoji?) -> this` | `### [emoji ]text` |
|
|
20
|
+
| `h4` | `(text, emoji?) -> this` | `#### [emoji ]text` |
|
|
21
|
+
| `keyValue` | `(key, value) -> this` | `**key:** value` |
|
|
22
|
+
| `keyValuePlain` | `(key, value) -> this` | `key: value` (no bold) |
|
|
23
|
+
| `list` | `(items, ordered?) -> this` | `ordered` defaults to `false`; empty arrays silently ignored |
|
|
24
|
+
| `codeBlock` | `(content, language?) -> this` | Fenced block; `language` defaults to `''` |
|
|
25
|
+
| `inlineCode` | `(code) -> this` | Backtick-wrapped; no trailing newline |
|
|
26
|
+
| `paragraph` | `(text) -> this` | Text + `\n\n` |
|
|
27
|
+
| `blockquote` | `(text) -> this` | Each line prefixed with `> ` |
|
|
28
|
+
| `hr` | `() -> this` | `---` |
|
|
29
|
+
| `link` | `(text, url) -> this` | `[text](url)`; no trailing newline |
|
|
30
|
+
| `table` | `(headers, rows) -> this` | GFM table; no-ops if headers or rows empty |
|
|
31
|
+
| `section` | `(title, content) -> this` | H2 heading + callback |
|
|
32
|
+
| `section` | `(title, level, content) -> this` | Heading at level 2/3/4 + callback |
|
|
33
|
+
| `details` | `(summary, details) -> this` | HTML `<details>`/`<summary>` collapsible block |
|
|
34
|
+
| `alert` | `(type, content) -> this` | GFM `[!TYPE]` alert blockquote |
|
|
35
|
+
| `taskList` | `(items) -> this` | GFM checkbox list; `items: Array<{ checked: boolean; text: string }>` |
|
|
36
|
+
| `image` | `(altText, url, title?) -> this` | `` |
|
|
37
|
+
| `strikethrough` | `(text) -> this` | `~~text~~`; no trailing newline |
|
|
38
|
+
| `diff` | `(changes) -> this` | ` ```diff ` block; `changes: { additions?: string[]; deletions?: string[]; context?: string[] }` |
|
|
39
|
+
| `badge` | `(label, message, color?) -> this` | shields.io badge image; `color` defaults to `'blue'` |
|
|
40
|
+
| `bold` | `(text) -> this` | `**text**`; no trailing newline |
|
|
41
|
+
| `italic` | `(text) -> this` | `*text*`; no trailing newline |
|
|
42
|
+
| `boldItalic` | `(text) -> this` | `***text***`; no trailing newline |
|
|
43
|
+
| `raw` | `(markdown) -> this` | Appends verbatim |
|
|
44
|
+
| `blankLine` | `() -> this` | Single `\n` |
|
|
45
|
+
| `text` | `(text) -> this` | Plain text, no formatting, no implicit newlines |
|
|
46
|
+
| `when` | `(condition, content) -> this` | Conditional append; `content: () => void` |
|
|
47
|
+
| `reset` | `() -> this` | Clears buffer |
|
|
48
|
+
| `build` | `() -> string` | Returns trimmed joined buffer; does NOT reset |
|
|
49
|
+
|
|
50
|
+
### Usage
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const md = markdown()
|
|
54
|
+
.h1('Report', '📊')
|
|
55
|
+
.paragraph('Generated automatically.')
|
|
56
|
+
.section('Results', 3, () => {
|
|
57
|
+
md.table(['Name', 'Score'], [['Alice', '95'], ['Bob', '87']]);
|
|
58
|
+
})
|
|
59
|
+
.when(hasWarnings, () => {
|
|
60
|
+
md.alert('warning', 'Some items need attention.');
|
|
61
|
+
})
|
|
62
|
+
.build();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Inline methods (`bold`, `italic`, `inlineCode`, `link`, `strikethrough`) do not append newlines — combine them with `text()` or `paragraph()` for inline composition.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## `diffFormatter`
|
|
70
|
+
|
|
71
|
+
**Tier 3 peer:** `diff` (`bun add diff`). All methods are **async**.
|
|
72
|
+
|
|
73
|
+
### Types
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
type DiffFormat = 'unified' | 'patch' | 'inline';
|
|
77
|
+
|
|
78
|
+
interface DiffFormatterOptions {
|
|
79
|
+
context?: number; // unchanged lines around changes; default 3
|
|
80
|
+
format?: DiffFormat; // default 'unified'
|
|
81
|
+
includeHeaders?: boolean; // ---/+++ headers (patch only); default true
|
|
82
|
+
oldPath?: string; // file path for old version (headers)
|
|
83
|
+
newPath?: string; // file path for new version (headers)
|
|
84
|
+
showLineNumbers?: boolean; // default true
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Methods
|
|
89
|
+
|
|
90
|
+
| Method | Signature | Returns |
|
|
91
|
+
|:-------|:----------|:--------|
|
|
92
|
+
| `diff` | `(oldText, newText, options?, context?) -> Promise<string>` | Formatted diff string |
|
|
93
|
+
| `diffLines` | `(oldLines, newLines, options?, context?) -> Promise<string>` | Same as `diff` but accepts pre-split `string[]` arrays |
|
|
94
|
+
| `diffWords` | `(oldText, newText, context?) -> Promise<string>` | Word-level inline diff: `[+added+]` / `[-removed-]` |
|
|
95
|
+
| `getStats` | `(oldText, newText, context?) -> Promise<{ additions, deletions, changes }>` | Line-count stats; `changes = additions + deletions` |
|
|
96
|
+
|
|
97
|
+
### Format behavior
|
|
98
|
+
|
|
99
|
+
| Format | Output |
|
|
100
|
+
|:-------|:-------|
|
|
101
|
+
| `'unified'` | Hunk headers (`@@`) only — strips `---`/`+++` file headers. Default. |
|
|
102
|
+
| `'patch'` | Full patch with file headers. `includeHeaders: false` strips them. |
|
|
103
|
+
| `'inline'` | No headers or hunk markers. Additions as `[+text+]`, removals as `[-text-]`. |
|
|
104
|
+
|
|
105
|
+
### Usage
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
const diff = await diffFormatter.diff(oldCode, newCode, {
|
|
109
|
+
format: 'unified',
|
|
110
|
+
context: 5,
|
|
111
|
+
showLineNumbers: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const stats = await diffFormatter.getStats(oldCode, newCode);
|
|
115
|
+
// { additions: 12, deletions: 3, changes: 15 }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## `tableFormatter`
|
|
121
|
+
|
|
122
|
+
Synchronous — no peer dependency.
|
|
123
|
+
|
|
124
|
+
### Types
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
type TableStyle = 'markdown' | 'ascii' | 'grid' | 'compact';
|
|
128
|
+
type Alignment = 'left' | 'center' | 'right';
|
|
129
|
+
|
|
130
|
+
interface TableFormatterOptions {
|
|
131
|
+
style?: TableStyle; // default 'markdown'
|
|
132
|
+
alignment?: Record<string, Alignment>; // key = column name or numeric index string
|
|
133
|
+
maxWidth?: number; // truncates at this width; default 50
|
|
134
|
+
minWidth?: number; // default 3
|
|
135
|
+
truncate?: boolean; // truncate with '...' when exceeding maxWidth; default true
|
|
136
|
+
headerStyle?: 'bold' | 'uppercase' | 'none';
|
|
137
|
+
padding?: number; // spaces around cell content; default 1
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Methods
|
|
142
|
+
|
|
143
|
+
| Method | Signature | Notes |
|
|
144
|
+
|:-------|:----------|:------|
|
|
145
|
+
| `format` | `<T extends Record<string, unknown>>(data, options?, context?) -> string` | Extracts headers from first object's keys; stringifies values. Returns `''` if empty. |
|
|
146
|
+
| `formatRaw` | `(headers, rows, options?, context?) -> string` | Pre-serialized `string[][]`; every row must match `headers.length`. Returns `''` if empty. |
|
|
147
|
+
|
|
148
|
+
### Styles
|
|
149
|
+
|
|
150
|
+
| Style | Description |
|
|
151
|
+
|:------|:------------|
|
|
152
|
+
| `markdown` | GFM pipes with alignment indicators in separator row |
|
|
153
|
+
| `ascii` | `+`/`-`/`|` box drawing |
|
|
154
|
+
| `grid` | Unicode box drawing (`┌─┬─┐` / `│` / `├─┼─┤` / `└─┴─┘`) |
|
|
155
|
+
| `compact` | Space-separated, no borders |
|
|
156
|
+
|
|
157
|
+
### Usage
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
// From objects — headers auto-extracted from keys
|
|
161
|
+
const table = tableFormatter.format(
|
|
162
|
+
[{ name: 'Alice', score: 95 }, { name: 'Bob', score: 87 }],
|
|
163
|
+
{ style: 'grid', alignment: { score: 'right' } },
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// From raw arrays
|
|
167
|
+
const raw = tableFormatter.formatRaw(
|
|
168
|
+
['Name', 'Score'],
|
|
169
|
+
[['Alice', '95'], ['Bob', '87']],
|
|
170
|
+
{ style: 'markdown', headerStyle: 'bold' },
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## `treeFormatter`
|
|
177
|
+
|
|
178
|
+
Synchronous — no peer dependency.
|
|
179
|
+
|
|
180
|
+
### Types
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
type TreeStyle = 'unicode' | 'ascii' | 'compact';
|
|
184
|
+
|
|
185
|
+
interface TreeNode {
|
|
186
|
+
name: string; // required, must be non-empty
|
|
187
|
+
children?: TreeNode[]; // presence determines folder vs leaf icon
|
|
188
|
+
metadata?: Record<string, unknown>; // rendered as key=value when showMetadata enabled
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
interface TreeFormatterOptions {
|
|
192
|
+
style?: TreeStyle; // default 'unicode'
|
|
193
|
+
maxDepth?: number; // 0-based cutoff; undefined = no limit
|
|
194
|
+
showMetadata?: boolean; // append metadata after node name; default false
|
|
195
|
+
icons?: boolean; // prefix nodes with icons; default false
|
|
196
|
+
indent?: string; // per-level indent; default ' ' (two spaces)
|
|
197
|
+
folderIcon?: string; // icon for branch nodes; default folder emoji
|
|
198
|
+
fileIcon?: string; // icon for leaf nodes; default page emoji
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Methods
|
|
203
|
+
|
|
204
|
+
| Method | Signature | Notes |
|
|
205
|
+
|:-------|:----------|:------|
|
|
206
|
+
| `format` | `(root, options?, context?) -> string` | Single tree. Detects and marks circular references as `[Circular Reference]`. |
|
|
207
|
+
| `formatMultiple` | `(roots, options?, context?) -> string` | Forest of trees joined by `\n\n`. `roots` must be non-empty. |
|
|
208
|
+
|
|
209
|
+
### Styles
|
|
210
|
+
|
|
211
|
+
| Style | Connectors |
|
|
212
|
+
|:------|:-----------|
|
|
213
|
+
| `unicode` | `├──` / `└──` / `│` |
|
|
214
|
+
| `ascii` | `+--` / `\--` / `|` |
|
|
215
|
+
| `compact` | Indented list, no connectors |
|
|
216
|
+
|
|
217
|
+
### Usage
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
const tree: TreeNode = {
|
|
221
|
+
name: 'src',
|
|
222
|
+
children: [
|
|
223
|
+
{ name: 'index.ts' },
|
|
224
|
+
{
|
|
225
|
+
name: 'utils',
|
|
226
|
+
children: [{ name: 'helpers.ts', metadata: { lines: 42 } }],
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const output = treeFormatter.format(tree, {
|
|
232
|
+
style: 'unicode',
|
|
233
|
+
icons: true,
|
|
234
|
+
showMetadata: true,
|
|
235
|
+
maxDepth: 3,
|
|
236
|
+
});
|
|
237
|
+
```
|