@rekog/mcp-nest 1.9.10 → 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -29
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/decorators/constants.d.ts +1 -0
- package/dist/mcp/decorators/constants.d.ts.map +1 -1
- package/dist/mcp/decorators/constants.js +2 -1
- package/dist/mcp/decorators/constants.js.map +1 -1
- package/dist/mcp/decorators/index.d.ts +3 -1
- package/dist/mcp/decorators/index.d.ts.map +1 -1
- package/dist/mcp/decorators/index.js +3 -1
- package/dist/mcp/decorators/index.js.map +1 -1
- package/dist/mcp/decorators/mcp-controller.decorator.d.ts +6 -0
- package/dist/mcp/decorators/mcp-controller.decorator.d.ts.map +1 -0
- package/dist/mcp/decorators/mcp-controller.decorator.js +43 -0
- package/dist/mcp/decorators/mcp-controller.decorator.js.map +1 -0
- package/dist/mcp/decorators/mcp-message-pattern.d.ts +3 -0
- package/dist/mcp/decorators/mcp-message-pattern.d.ts.map +1 -0
- package/dist/mcp/decorators/mcp-message-pattern.js +13 -0
- package/dist/mcp/decorators/mcp-message-pattern.js.map +1 -0
- package/dist/mcp/decorators/prompt.decorator.d.ts +4 -1
- package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/prompt.decorator.js +2 -1
- package/dist/mcp/decorators/prompt.decorator.js.map +1 -1
- package/dist/mcp/decorators/public.decorator.js.map +1 -1
- package/dist/mcp/decorators/raw-request.decorator.d.ts +2 -0
- package/dist/mcp/decorators/raw-request.decorator.d.ts.map +1 -0
- package/dist/mcp/decorators/raw-request.decorator.js +6 -0
- package/dist/mcp/decorators/raw-request.decorator.js.map +1 -0
- package/dist/mcp/decorators/resource-template.decorator.d.ts +1 -1
- package/dist/mcp/decorators/resource-template.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/resource-template.decorator.js +2 -1
- package/dist/mcp/decorators/resource-template.decorator.js.map +1 -1
- package/dist/mcp/decorators/resource.decorator.d.ts +1 -1
- package/dist/mcp/decorators/resource.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/resource.decorator.js +2 -1
- package/dist/mcp/decorators/resource.decorator.js.map +1 -1
- package/dist/mcp/decorators/tool.decorator.d.ts +1 -3
- package/dist/mcp/decorators/tool.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/tool.decorator.js +2 -1
- package/dist/mcp/decorators/tool.decorator.js.map +1 -1
- package/dist/mcp/filters/mcp-exception.filter.d.ts +6 -0
- package/dist/mcp/filters/mcp-exception.filter.d.ts.map +1 -0
- package/dist/mcp/filters/mcp-exception.filter.js +26 -0
- package/dist/mcp/filters/mcp-exception.filter.js.map +1 -0
- package/dist/mcp/index.d.ts +11 -7
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +11 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/interfaces/authenticated-user.interface.d.ts +9 -0
- package/dist/mcp/interfaces/authenticated-user.interface.d.ts.map +1 -0
- package/dist/{authz/interfaces/request-with-user.js → mcp/interfaces/authenticated-user.interface.js} +1 -1
- package/dist/mcp/interfaces/authenticated-user.interface.js.map +1 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts +1 -1
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts.map +1 -1
- package/dist/mcp/interfaces/dynamic-prompt.interface.js.map +1 -1
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts +1 -1
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts.map +1 -1
- package/dist/mcp/interfaces/dynamic-resource.interface.js.map +1 -1
- package/dist/mcp/interfaces/dynamic-tool.interface.d.ts +1 -1
- package/dist/mcp/interfaces/dynamic-tool.interface.d.ts.map +1 -1
- package/dist/mcp/interfaces/dynamic-tool.interface.js.map +1 -1
- package/dist/mcp/interfaces/index.d.ts +2 -2
- package/dist/mcp/interfaces/index.d.ts.map +1 -1
- package/dist/mcp/interfaces/index.js +0 -3
- package/dist/mcp/interfaces/index.js.map +1 -1
- package/dist/mcp/services/tool-authorization.service.d.ts +7 -5
- package/dist/mcp/services/tool-authorization.service.d.ts.map +1 -1
- package/dist/mcp/services/tool-authorization.service.js +9 -6
- package/dist/mcp/services/tool-authorization.service.js.map +1 -1
- package/dist/mcp/transport/mcp-context.d.ts +34 -0
- package/dist/mcp/transport/mcp-context.d.ts.map +1 -0
- package/dist/mcp/transport/mcp-context.js +74 -0
- package/dist/mcp/transport/mcp-context.js.map +1 -0
- package/dist/mcp/transport/mcp-http-handler.d.ts +7 -0
- package/dist/mcp/transport/mcp-http-handler.d.ts.map +1 -0
- package/dist/mcp/transport/mcp-http-handler.js +5 -0
- package/dist/mcp/transport/mcp-http-handler.js.map +1 -0
- package/dist/mcp/transport/mcp-server-options.interface.d.ts +23 -0
- package/dist/mcp/transport/mcp-server-options.interface.d.ts.map +1 -0
- package/dist/{authz/providers/oauth-provider.interface.js → mcp/transport/mcp-server-options.interface.js} +1 -1
- package/dist/mcp/transport/mcp-server-options.interface.js.map +1 -0
- package/dist/mcp/transport/mcp-transport.constants.d.ts +19 -0
- package/dist/mcp/transport/mcp-transport.constants.d.ts.map +1 -0
- package/dist/mcp/transport/mcp-transport.constants.js +21 -0
- package/dist/mcp/transport/mcp-transport.constants.js.map +1 -0
- package/dist/mcp/transport/mcp-transport.interface.d.ts +17 -0
- package/dist/mcp/transport/mcp-transport.interface.d.ts.map +1 -0
- package/dist/{authz/interfaces/oauth-common.interface.js → mcp/transport/mcp-transport.interface.js} +1 -1
- package/dist/mcp/transport/mcp-transport.interface.js.map +1 -0
- package/dist/mcp/transport/mcp.strategy.d.ts +56 -0
- package/dist/mcp/transport/mcp.strategy.d.ts.map +1 -0
- package/dist/mcp/transport/mcp.strategy.js +446 -0
- package/dist/mcp/transport/mcp.strategy.js.map +1 -0
- package/dist/mcp/transport/resource-matcher.d.ts +13 -0
- package/dist/mcp/transport/resource-matcher.d.ts.map +1 -0
- package/dist/mcp/transport/resource-matcher.js +83 -0
- package/dist/mcp/transport/resource-matcher.js.map +1 -0
- package/dist/mcp/transport/streamable-http.controller.d.ts +16 -0
- package/dist/mcp/transport/streamable-http.controller.d.ts.map +1 -0
- package/dist/mcp/transport/streamable-http.controller.js +98 -0
- package/dist/mcp/transport/streamable-http.controller.js.map +1 -0
- package/dist/mcp/transport/transports/index.d.ts +3 -0
- package/dist/mcp/transport/transports/index.d.ts.map +1 -0
- package/dist/{authz → mcp/transport/transports}/index.js +2 -10
- package/dist/mcp/transport/transports/index.js.map +1 -0
- package/dist/mcp/transport/transports/read-body.d.ts +3 -0
- package/dist/mcp/transport/transports/read-body.d.ts.map +1 -0
- package/dist/mcp/transport/transports/read-body.js +32 -0
- package/dist/mcp/transport/transports/read-body.js.map +1 -0
- package/dist/mcp/transport/transports/stdio.transport.d.ts +9 -0
- package/dist/mcp/transport/transports/stdio.transport.d.ts.map +1 -0
- package/dist/mcp/transport/transports/stdio.transport.js +27 -0
- package/dist/mcp/transport/transports/stdio.transport.js.map +1 -0
- package/dist/mcp/transport/transports/streamable-http.transport.d.ts +33 -0
- package/dist/mcp/transport/transports/streamable-http.transport.d.ts.map +1 -0
- package/dist/mcp/transport/transports/streamable-http.transport.js +216 -0
- package/dist/mcp/transport/transports/streamable-http.transport.js.map +1 -0
- package/dist/mcp/utils/mcp-logger.factory.d.ts +6 -2
- package/dist/mcp/utils/mcp-logger.factory.d.ts.map +1 -1
- package/dist/mcp/utils/mcp-logger.factory.js.map +1 -1
- package/package.json +3 -66
- package/src/index.ts +0 -1
- package/src/mcp/decorators/constants.ts +1 -0
- package/src/mcp/decorators/index.ts +3 -1
- package/src/mcp/decorators/mcp-controller.decorator.ts +126 -0
- package/src/mcp/decorators/mcp-message-pattern.ts +38 -0
- package/src/mcp/decorators/prompt.decorator.ts +32 -2
- package/src/mcp/decorators/public.decorator.ts +3 -3
- package/src/mcp/decorators/raw-request.decorator.ts +32 -0
- package/src/mcp/decorators/resource-template.decorator.ts +6 -2
- package/src/mcp/decorators/resource.decorator.ts +6 -2
- package/src/mcp/decorators/tool.decorator.ts +6 -3
- package/src/mcp/filters/mcp-exception.filter.ts +47 -0
- package/src/mcp/index.ts +13 -7
- package/src/mcp/interfaces/authenticated-user.interface.ts +22 -0
- package/src/mcp/interfaces/dynamic-prompt.interface.ts +1 -1
- package/src/mcp/interfaces/dynamic-resource.interface.ts +1 -1
- package/src/mcp/interfaces/dynamic-tool.interface.ts +2 -2
- package/src/mcp/interfaces/index.ts +3 -7
- package/src/mcp/services/tool-authorization.service.ts +52 -72
- package/src/mcp/transport/mcp-context.ts +138 -0
- package/src/mcp/transport/mcp-http-handler.ts +32 -0
- package/src/mcp/transport/mcp-server-options.interface.ts +75 -0
- package/src/mcp/transport/mcp-transport.constants.ts +99 -0
- package/src/mcp/transport/mcp-transport.interface.ts +50 -0
- package/src/mcp/transport/mcp.strategy.ts +752 -0
- package/src/mcp/transport/resource-matcher.ts +107 -0
- package/src/mcp/transport/streamable-http.controller.ts +114 -0
- package/src/mcp/transport/transports/index.ts +2 -0
- package/src/mcp/transport/transports/read-body.ts +39 -0
- package/src/mcp/transport/transports/stdio.transport.ts +35 -0
- package/src/mcp/transport/transports/streamable-http.transport.ts +384 -0
- package/src/mcp/utils/mcp-logger.factory.spec.ts +8 -22
- package/src/mcp/utils/mcp-logger.factory.ts +13 -2
- package/dist/authz/guards/jwt-auth.guard.d.ts +0 -19
- package/dist/authz/guards/jwt-auth.guard.d.ts.map +0 -1
- package/dist/authz/guards/jwt-auth.guard.js +0 -108
- package/dist/authz/guards/jwt-auth.guard.js.map +0 -1
- package/dist/authz/index.d.ts +0 -11
- package/dist/authz/index.d.ts.map +0 -1
- package/dist/authz/index.js.map +0 -1
- package/dist/authz/interfaces/oauth-common.interface.d.ts +0 -21
- package/dist/authz/interfaces/oauth-common.interface.d.ts.map +0 -1
- package/dist/authz/interfaces/oauth-common.interface.js.map +0 -1
- package/dist/authz/interfaces/request-with-user.d.ts +0 -13
- package/dist/authz/interfaces/request-with-user.d.ts.map +0 -1
- package/dist/authz/interfaces/request-with-user.js.map +0 -1
- package/dist/authz/mcp-oauth.controller.d.ts +0 -81
- package/dist/authz/mcp-oauth.controller.d.ts.map +0 -1
- package/dist/authz/mcp-oauth.controller.js +0 -540
- package/dist/authz/mcp-oauth.controller.js.map +0 -1
- package/dist/authz/mcp-oauth.module.d.ts +0 -12
- package/dist/authz/mcp-oauth.module.d.ts.map +0 -1
- package/dist/authz/mcp-oauth.module.js +0 -271
- package/dist/authz/mcp-oauth.module.js.map +0 -1
- package/dist/authz/providers/azure-ad.provider.d.ts +0 -3
- package/dist/authz/providers/azure-ad.provider.d.ts.map +0 -1
- package/dist/authz/providers/azure-ad.provider.js +0 -37
- package/dist/authz/providers/azure-ad.provider.js.map +0 -1
- package/dist/authz/providers/github.provider.d.ts +0 -3
- package/dist/authz/providers/github.provider.d.ts.map +0 -1
- package/dist/authz/providers/github.provider.js +0 -24
- package/dist/authz/providers/github.provider.js.map +0 -1
- package/dist/authz/providers/google.provider.d.ts +0 -3
- package/dist/authz/providers/google.provider.d.ts.map +0 -1
- package/dist/authz/providers/google.provider.js +0 -25
- package/dist/authz/providers/google.provider.js.map +0 -1
- package/dist/authz/providers/oauth-provider.interface.d.ts +0 -107
- package/dist/authz/providers/oauth-provider.interface.d.ts.map +0 -1
- package/dist/authz/providers/oauth-provider.interface.js.map +0 -1
- package/dist/authz/services/client.service.d.ts +0 -12
- package/dist/authz/services/client.service.d.ts.map +0 -1
- package/dist/authz/services/client.service.js +0 -81
- package/dist/authz/services/client.service.js.map +0 -1
- package/dist/authz/services/jwt-token.service.d.ts +0 -37
- package/dist/authz/services/jwt-token.service.d.ts.map +0 -1
- package/dist/authz/services/jwt-token.service.js +0 -182
- package/dist/authz/services/jwt-token.service.js.map +0 -1
- package/dist/authz/services/oauth-strategy.service.d.ts +0 -13
- package/dist/authz/services/oauth-strategy.service.d.ts.map +0 -1
- package/dist/authz/services/oauth-strategy.service.js +0 -71
- package/dist/authz/services/oauth-strategy.service.js.map +0 -1
- package/dist/authz/stores/memory-store.service.d.ts +0 -27
- package/dist/authz/stores/memory-store.service.d.ts.map +0 -1
- package/dist/authz/stores/memory-store.service.js +0 -107
- package/dist/authz/stores/memory-store.service.js.map +0 -1
- package/dist/authz/stores/oauth-store.interface.d.ts +0 -61
- package/dist/authz/stores/oauth-store.interface.d.ts.map +0 -1
- package/dist/authz/stores/oauth-store.interface.js +0 -5
- package/dist/authz/stores/oauth-store.interface.js.map +0 -1
- package/dist/authz/stores/typeorm/constants.d.ts +0 -3
- package/dist/authz/stores/typeorm/constants.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/constants.js +0 -6
- package/dist/authz/stores/typeorm/constants.js.map +0 -1
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +0 -15
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +0 -69
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +0 -1
- package/dist/authz/stores/typeorm/entities/index.d.ts +0 -5
- package/dist/authz/stores/typeorm/entities/index.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/entities/index.js +0 -12
- package/dist/authz/stores/typeorm/entities/index.js.map +0 -1
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +0 -17
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +0 -77
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +0 -1
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts +0 -14
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.js +0 -65
- package/dist/authz/stores/typeorm/entities/oauth-session.entity.js.map +0 -1
- package/dist/authz/stores/typeorm/entities/user-profile.entity.d.ts +0 -13
- package/dist/authz/stores/typeorm/entities/user-profile.entity.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/entities/user-profile.entity.js +0 -62
- package/dist/authz/stores/typeorm/entities/user-profile.entity.js.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.d.ts +0 -28
- package/dist/authz/stores/typeorm/typeorm-store.service.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.js +0 -138
- package/dist/authz/stores/typeorm/typeorm-store.service.js.map +0 -1
- package/dist/mcp/constants/feature-registration.constants.d.ts +0 -7
- package/dist/mcp/constants/feature-registration.constants.d.ts.map +0 -1
- package/dist/mcp/constants/feature-registration.constants.js +0 -5
- package/dist/mcp/constants/feature-registration.constants.js.map +0 -1
- package/dist/mcp/decorators/tool-guards.decorator.d.ts +0 -12
- package/dist/mcp/decorators/tool-guards.decorator.d.ts.map +0 -1
- package/dist/mcp/decorators/tool-guards.decorator.js +0 -13
- package/dist/mcp/decorators/tool-guards.decorator.js.map +0 -1
- package/dist/mcp/interfaces/mcp-options.interface.d.ts +0 -53
- package/dist/mcp/interfaces/mcp-options.interface.d.ts.map +0 -1
- package/dist/mcp/interfaces/mcp-options.interface.js +0 -10
- package/dist/mcp/interfaces/mcp-options.interface.js.map +0 -1
- package/dist/mcp/mcp.module.d.ts +0 -15
- package/dist/mcp/mcp.module.d.ts.map +0 -1
- package/dist/mcp/mcp.module.js +0 -248
- package/dist/mcp/mcp.module.js.map +0 -1
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts +0 -117
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts.map +0 -1
- package/dist/mcp/services/handlers/mcp-handler.base.js +0 -125
- package/dist/mcp/services/handlers/mcp-handler.base.js.map +0 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts +0 -12
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts.map +0 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.js +0 -98
- package/dist/mcp/services/handlers/mcp-prompts.handler.js.map +0 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts +0 -13
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts.map +0 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.js +0 -117
- package/dist/mcp/services/handlers/mcp-resources.handler.js.map +0 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts +0 -22
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +0 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.js +0 -258
- package/dist/mcp/services/handlers/mcp-tools.handler.js.map +0 -1
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts +0 -26
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-dynamic-registry.service.js +0 -133
- package/dist/mcp/services/mcp-dynamic-registry.service.js.map +0 -1
- package/dist/mcp/services/mcp-executor.service.d.ts +0 -15
- package/dist/mcp/services/mcp-executor.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-executor.service.js +0 -47
- package/dist/mcp/services/mcp-executor.service.js.map +0 -1
- package/dist/mcp/services/mcp-registry-discovery.service.d.ts +0 -63
- package/dist/mcp/services/mcp-registry-discovery.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-registry-discovery.service.js +0 -397
- package/dist/mcp/services/mcp-registry-discovery.service.js.map +0 -1
- package/dist/mcp/services/mcp-sse.service.d.ts +0 -20
- package/dist/mcp/services/mcp-sse.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-sse.service.js +0 -91
- package/dist/mcp/services/mcp-sse.service.js.map +0 -1
- package/dist/mcp/services/mcp-streamable-http.service.d.ts +0 -32
- package/dist/mcp/services/mcp-streamable-http.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-streamable-http.service.js +0 -327
- package/dist/mcp/services/mcp-streamable-http.service.js.map +0 -1
- package/dist/mcp/services/sse-ping.service.d.ts +0 -23
- package/dist/mcp/services/sse-ping.service.d.ts.map +0 -1
- package/dist/mcp/services/sse-ping.service.js +0 -99
- package/dist/mcp/services/sse-ping.service.js.map +0 -1
- package/dist/mcp/transport/sse.controller.factory.d.ts +0 -14
- package/dist/mcp/transport/sse.controller.factory.d.ts.map +0 -1
- package/dist/mcp/transport/sse.controller.factory.js +0 -67
- package/dist/mcp/transport/sse.controller.factory.js.map +0 -1
- package/dist/mcp/transport/stdio.service.d.ts +0 -14
- package/dist/mcp/transport/stdio.service.d.ts.map +0 -1
- package/dist/mcp/transport/stdio.service.js +0 -66
- package/dist/mcp/transport/stdio.service.js.map +0 -1
- package/dist/mcp/transport/streamable-http.controller.factory.d.ts +0 -14
- package/dist/mcp/transport/streamable-http.controller.factory.d.ts.map +0 -1
- package/dist/mcp/transport/streamable-http.controller.factory.js +0 -74
- package/dist/mcp/transport/streamable-http.controller.factory.js.map +0 -1
- package/dist/mcp/utils/capabilities-builder.d.ts +0 -5
- package/dist/mcp/utils/capabilities-builder.d.ts.map +0 -1
- package/dist/mcp/utils/capabilities-builder.js +0 -25
- package/dist/mcp/utils/capabilities-builder.js.map +0 -1
- package/dist/mcp/utils/mcp-server.factory.d.ts +0 -6
- package/dist/mcp/utils/mcp-server.factory.d.ts.map +0 -1
- package/dist/mcp/utils/mcp-server.factory.js +0 -22
- package/dist/mcp/utils/mcp-server.factory.js.map +0 -1
- package/src/authz/guards/jwt-auth.guard.ts +0 -127
- package/src/authz/index.ts +0 -10
- package/src/authz/interfaces/oauth-common.interface.ts +0 -21
- package/src/authz/interfaces/request-with-user.ts +0 -16
- package/src/authz/mcp-oauth.controller.ts +0 -860
- package/src/authz/mcp-oauth.module.ts +0 -384
- package/src/authz/providers/azure-ad.provider.ts +0 -40
- package/src/authz/providers/github.provider.ts +0 -22
- package/src/authz/providers/google.provider.ts +0 -23
- package/src/authz/providers/oauth-provider.interface.ts +0 -147
- package/src/authz/services/client.service.ts +0 -125
- package/src/authz/services/jwt-token.service.spec.ts +0 -67
- package/src/authz/services/jwt-token.service.ts +0 -188
- package/src/authz/services/oauth-strategy.service.ts +0 -64
- package/src/authz/stores/memory-store.service.spec.ts +0 -475
- package/src/authz/stores/memory-store.service.ts +0 -141
- package/src/authz/stores/oauth-store.interface.ts +0 -131
- package/src/authz/stores/typeorm/README.md +0 -140
- package/src/authz/stores/typeorm/constants.ts +0 -6
- package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +0 -41
- package/src/authz/stores/typeorm/entities/index.ts +0 -4
- package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +0 -53
- package/src/authz/stores/typeorm/entities/oauth-session.entity.ts +0 -38
- package/src/authz/stores/typeorm/entities/user-profile.entity.ts +0 -46
- package/src/authz/stores/typeorm/typeorm-store.service.spec.ts +0 -494
- package/src/authz/stores/typeorm/typeorm-store.service.ts +0 -165
- package/src/mcp/constants/feature-registration.constants.ts +0 -24
- package/src/mcp/decorators/tool-guards.decorator.ts +0 -82
- package/src/mcp/interfaces/mcp-options.interface.ts +0 -95
- package/src/mcp/mcp.module.ts +0 -349
- package/src/mcp/services/handlers/mcp-handler.base.ts +0 -203
- package/src/mcp/services/handlers/mcp-prompts.handler.ts +0 -143
- package/src/mcp/services/handlers/mcp-resources.handler.ts +0 -183
- package/src/mcp/services/handlers/mcp-tools.handler.spec.ts +0 -41
- package/src/mcp/services/handlers/mcp-tools.handler.ts +0 -436
- package/src/mcp/services/mcp-dynamic-registry.service.ts +0 -236
- package/src/mcp/services/mcp-executor.service.ts +0 -64
- package/src/mcp/services/mcp-registry-discovery.service.spec.ts +0 -306
- package/src/mcp/services/mcp-registry-discovery.service.ts +0 -849
- package/src/mcp/services/mcp-sse.service.ts +0 -124
- package/src/mcp/services/mcp-streamable-http.service.ts +0 -472
- package/src/mcp/services/sse-ping.service.ts +0 -144
- package/src/mcp/transport/custom-decorator.spec.ts +0 -75
- package/src/mcp/transport/sse.controller.factory.ts +0 -84
- package/src/mcp/transport/stdio.service.ts +0 -75
- package/src/mcp/transport/streamable-http.controller.factory.ts +0 -80
- package/src/mcp/utils/capabilities-builder.ts +0 -43
- package/src/mcp/utils/mcp-server.factory.ts +0 -33
|
@@ -1,494 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
|
-
import { Test, TestingModule } from '@nestjs/testing';
|
|
3
|
-
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
4
|
-
import { Repository, DeleteResult } from 'typeorm';
|
|
5
|
-
import { TypeOrmStore } from './typeorm-store.service';
|
|
6
|
-
import {
|
|
7
|
-
OAuthClientEntity,
|
|
8
|
-
AuthorizationCodeEntity,
|
|
9
|
-
OAuthSessionEntity,
|
|
10
|
-
OAuthUserProfileEntity,
|
|
11
|
-
} from './entities';
|
|
12
|
-
import { OAuthClient, AuthorizationCode } from '../oauth-store.interface';
|
|
13
|
-
import { OAuthSession } from '../../providers/oauth-provider.interface';
|
|
14
|
-
import { OAUTH_TYPEORM_CONNECTION_NAME } from './constants';
|
|
15
|
-
|
|
16
|
-
describe('TypeOrmStore', () => {
|
|
17
|
-
let service: TypeOrmStore;
|
|
18
|
-
let clientRepository: jest.Mocked<Repository<OAuthClientEntity>>;
|
|
19
|
-
let authCodeRepository: jest.Mocked<Repository<AuthorizationCodeEntity>>;
|
|
20
|
-
let sessionRepository: jest.Mocked<Repository<OAuthSessionEntity>>;
|
|
21
|
-
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
// Create mocked repositories
|
|
24
|
-
const mockClientRepository = {
|
|
25
|
-
save: jest.fn(),
|
|
26
|
-
findOne: jest.fn(),
|
|
27
|
-
delete: jest.fn(),
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const mockAuthCodeRepository = {
|
|
31
|
-
save: jest.fn(),
|
|
32
|
-
findOne: jest.fn(),
|
|
33
|
-
delete: jest.fn(),
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const mockSessionRepository = {
|
|
37
|
-
save: jest.fn(),
|
|
38
|
-
findOne: jest.fn(),
|
|
39
|
-
delete: jest.fn(),
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const mockUserProfileRepository = {
|
|
43
|
-
save: jest.fn(),
|
|
44
|
-
findOne: jest.fn(),
|
|
45
|
-
delete: jest.fn(),
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const module: TestingModule = await Test.createTestingModule({
|
|
49
|
-
providers: [
|
|
50
|
-
TypeOrmStore,
|
|
51
|
-
{
|
|
52
|
-
provide: getRepositoryToken(
|
|
53
|
-
OAuthClientEntity,
|
|
54
|
-
OAUTH_TYPEORM_CONNECTION_NAME,
|
|
55
|
-
),
|
|
56
|
-
useValue: mockClientRepository,
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
provide: getRepositoryToken(
|
|
60
|
-
AuthorizationCodeEntity,
|
|
61
|
-
OAUTH_TYPEORM_CONNECTION_NAME,
|
|
62
|
-
),
|
|
63
|
-
useValue: mockAuthCodeRepository,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
provide: getRepositoryToken(
|
|
67
|
-
OAuthSessionEntity,
|
|
68
|
-
OAUTH_TYPEORM_CONNECTION_NAME,
|
|
69
|
-
),
|
|
70
|
-
useValue: mockSessionRepository,
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
provide: getRepositoryToken(
|
|
74
|
-
OAuthUserProfileEntity,
|
|
75
|
-
OAUTH_TYPEORM_CONNECTION_NAME,
|
|
76
|
-
),
|
|
77
|
-
useValue: mockUserProfileRepository,
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
}).compile();
|
|
81
|
-
|
|
82
|
-
service = module.get<TypeOrmStore>(TypeOrmStore);
|
|
83
|
-
clientRepository = module.get(
|
|
84
|
-
getRepositoryToken(OAuthClientEntity, OAUTH_TYPEORM_CONNECTION_NAME),
|
|
85
|
-
);
|
|
86
|
-
authCodeRepository = module.get(
|
|
87
|
-
getRepositoryToken(
|
|
88
|
-
AuthorizationCodeEntity,
|
|
89
|
-
OAUTH_TYPEORM_CONNECTION_NAME,
|
|
90
|
-
),
|
|
91
|
-
);
|
|
92
|
-
sessionRepository = module.get(
|
|
93
|
-
getRepositoryToken(OAuthSessionEntity, OAUTH_TYPEORM_CONNECTION_NAME),
|
|
94
|
-
);
|
|
95
|
-
// Note: userProfileRepository is not directly used in tests below; it's provided for completeness
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
afterEach(() => {
|
|
99
|
-
jest.clearAllMocks();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should be defined', () => {
|
|
103
|
-
expect(service).toBeDefined();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('generateClientId', () => {
|
|
107
|
-
const mockClient: OAuthClient = {
|
|
108
|
-
client_id: '',
|
|
109
|
-
client_name: 'Test Client',
|
|
110
|
-
client_description: 'A test OAuth client',
|
|
111
|
-
logo_uri: 'https://example.com/logo.png',
|
|
112
|
-
client_uri: 'https://example.com',
|
|
113
|
-
developer_name: 'Test Developer',
|
|
114
|
-
developer_email: 'test@example.com',
|
|
115
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
116
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
117
|
-
response_types: ['code'],
|
|
118
|
-
token_endpoint_auth_method: 'none',
|
|
119
|
-
created_at: new Date(),
|
|
120
|
-
updated_at: new Date(),
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
it('should generate client IDs with correct format', () => {
|
|
124
|
-
const clientId = service.generateClientId(mockClient);
|
|
125
|
-
|
|
126
|
-
// Should match pattern: normalizedname_8hexchars
|
|
127
|
-
expect(clientId).toMatch(/^[a-z0-9]+_[a-f0-9]{8}$/);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should include normalized client name in the generated ID', () => {
|
|
131
|
-
const clientWithSpecialChars = {
|
|
132
|
-
...mockClient,
|
|
133
|
-
client_name: 'Test Client!@#',
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const clientId = service.generateClientId(clientWithSpecialChars);
|
|
137
|
-
expect(clientId).toMatch(/^testclient_[a-f0-9]{8}$/);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should generate different IDs for different clients', () => {
|
|
141
|
-
const client1 = { ...mockClient, client_name: 'Client One' };
|
|
142
|
-
const client2 = { ...mockClient, client_name: 'Client Two' };
|
|
143
|
-
|
|
144
|
-
const id1 = service.generateClientId(client1);
|
|
145
|
-
const id2 = service.generateClientId(client2);
|
|
146
|
-
|
|
147
|
-
expect(id1).not.toBe(id2);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should generate different IDs on each call (non-deterministic)', () => {
|
|
151
|
-
const id1 = service.generateClientId(mockClient);
|
|
152
|
-
const id2 = service.generateClientId(mockClient);
|
|
153
|
-
|
|
154
|
-
// TypeORM store uses random bytes, so IDs should be different
|
|
155
|
-
expect(id1).not.toBe(id2);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe('Client Management', () => {
|
|
160
|
-
const mockClient: OAuthClient = {
|
|
161
|
-
client_id: 'test-client-id',
|
|
162
|
-
client_name: 'Test Client',
|
|
163
|
-
client_description: 'A test OAuth client',
|
|
164
|
-
logo_uri: 'https://example.com/logo.png',
|
|
165
|
-
client_uri: 'https://example.com',
|
|
166
|
-
developer_name: 'Test Developer',
|
|
167
|
-
developer_email: 'test@example.com',
|
|
168
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
169
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
170
|
-
response_types: ['code'],
|
|
171
|
-
token_endpoint_auth_method: 'none',
|
|
172
|
-
created_at: new Date(),
|
|
173
|
-
updated_at: new Date(),
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
describe('storeClient', () => {
|
|
177
|
-
it('should store a client and return the saved result', async () => {
|
|
178
|
-
clientRepository.save.mockResolvedValue(
|
|
179
|
-
mockClient as OAuthClientEntity,
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const result = await service.storeClient(mockClient);
|
|
183
|
-
|
|
184
|
-
expect(clientRepository.save).toHaveBeenCalledWith(mockClient);
|
|
185
|
-
expect(result).toEqual(mockClient);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('should handle database errors', async () => {
|
|
189
|
-
const error = new Error('Database error');
|
|
190
|
-
clientRepository.save.mockRejectedValue(error);
|
|
191
|
-
|
|
192
|
-
await expect(service.storeClient(mockClient)).rejects.toThrow(
|
|
193
|
-
'Database error',
|
|
194
|
-
);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
describe('getClient', () => {
|
|
199
|
-
it('should return client when found', async () => {
|
|
200
|
-
clientRepository.findOne.mockResolvedValue(
|
|
201
|
-
mockClient as OAuthClientEntity,
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const result = await service.getClient('test-client-id');
|
|
205
|
-
|
|
206
|
-
expect(clientRepository.findOne).toHaveBeenCalledWith({
|
|
207
|
-
where: { client_id: 'test-client-id' },
|
|
208
|
-
});
|
|
209
|
-
expect(result).toEqual(mockClient);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('should return undefined when client not found', async () => {
|
|
213
|
-
clientRepository.findOne.mockResolvedValue(null);
|
|
214
|
-
|
|
215
|
-
const result = await service.getClient('non-existent-id');
|
|
216
|
-
|
|
217
|
-
expect(result).toBeUndefined();
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should handle database errors', async () => {
|
|
221
|
-
const error = new Error('Database error');
|
|
222
|
-
clientRepository.findOne.mockRejectedValue(error);
|
|
223
|
-
|
|
224
|
-
await expect(service.getClient('test-client-id')).rejects.toThrow(
|
|
225
|
-
'Database error',
|
|
226
|
-
);
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
describe('findClient', () => {
|
|
231
|
-
it('should find client by name when found', async () => {
|
|
232
|
-
clientRepository.findOne.mockResolvedValue(
|
|
233
|
-
mockClient as OAuthClientEntity,
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
const result = await service.findClient('Test Client');
|
|
237
|
-
|
|
238
|
-
expect(clientRepository.findOne).toHaveBeenCalledWith({
|
|
239
|
-
where: { client_name: 'Test Client' },
|
|
240
|
-
});
|
|
241
|
-
expect(result).toEqual(mockClient);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it('should return undefined when client name not found', async () => {
|
|
245
|
-
clientRepository.findOne.mockResolvedValue(null);
|
|
246
|
-
|
|
247
|
-
const result = await service.findClient('Non-existent Client');
|
|
248
|
-
|
|
249
|
-
expect(result).toBeUndefined();
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('should handle database errors', async () => {
|
|
253
|
-
const error = new Error('Database error');
|
|
254
|
-
clientRepository.findOne.mockRejectedValue(error);
|
|
255
|
-
|
|
256
|
-
await expect(service.findClient('Test Client')).rejects.toThrow(
|
|
257
|
-
'Database error',
|
|
258
|
-
);
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
describe('Authorization Code Management', () => {
|
|
264
|
-
const mockAuthCode: AuthorizationCode = {
|
|
265
|
-
code: 'test-auth-code',
|
|
266
|
-
user_id: 'user-123',
|
|
267
|
-
client_id: 'client-123',
|
|
268
|
-
redirect_uri: 'http://localhost:3000/callback',
|
|
269
|
-
code_challenge: 'test-challenge',
|
|
270
|
-
code_challenge_method: 'S256',
|
|
271
|
-
expires_at: Date.now() + 600000, // 10 minutes from now
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const expiredAuthCode: AuthorizationCode = {
|
|
275
|
-
...mockAuthCode,
|
|
276
|
-
expires_at: Date.now() - 1000, // 1 second ago
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
describe('storeAuthCode', () => {
|
|
280
|
-
it('should store an authorization code', async () => {
|
|
281
|
-
authCodeRepository.save.mockResolvedValue(
|
|
282
|
-
mockAuthCode as AuthorizationCodeEntity,
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
await service.storeAuthCode(mockAuthCode);
|
|
286
|
-
|
|
287
|
-
expect(authCodeRepository.save).toHaveBeenCalledWith(mockAuthCode);
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it('should handle database errors', async () => {
|
|
291
|
-
const error = new Error('Database error');
|
|
292
|
-
authCodeRepository.save.mockRejectedValue(error);
|
|
293
|
-
|
|
294
|
-
await expect(service.storeAuthCode(mockAuthCode)).rejects.toThrow(
|
|
295
|
-
'Database error',
|
|
296
|
-
);
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
describe('getAuthCode', () => {
|
|
301
|
-
it('should return authorization code when found and not expired', async () => {
|
|
302
|
-
authCodeRepository.findOne.mockResolvedValue(
|
|
303
|
-
mockAuthCode as AuthorizationCodeEntity,
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
const result = await service.getAuthCode('test-auth-code');
|
|
307
|
-
|
|
308
|
-
expect(authCodeRepository.findOne).toHaveBeenCalledWith({
|
|
309
|
-
where: { code: 'test-auth-code' },
|
|
310
|
-
});
|
|
311
|
-
expect(result).toEqual(mockAuthCode);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
it('should return undefined and delete expired authorization code', async () => {
|
|
315
|
-
authCodeRepository.findOne.mockResolvedValue(
|
|
316
|
-
expiredAuthCode as AuthorizationCodeEntity,
|
|
317
|
-
);
|
|
318
|
-
authCodeRepository.delete.mockResolvedValue({
|
|
319
|
-
raw: {},
|
|
320
|
-
affected: 1,
|
|
321
|
-
} as DeleteResult);
|
|
322
|
-
|
|
323
|
-
const result = await service.getAuthCode('expired-code');
|
|
324
|
-
|
|
325
|
-
expect(authCodeRepository.findOne).toHaveBeenCalledWith({
|
|
326
|
-
where: { code: 'expired-code' },
|
|
327
|
-
});
|
|
328
|
-
expect(authCodeRepository.delete).toHaveBeenCalledWith({
|
|
329
|
-
code: 'expired-code',
|
|
330
|
-
});
|
|
331
|
-
expect(result).toBeUndefined();
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
it('should return undefined when authorization code not found', async () => {
|
|
335
|
-
authCodeRepository.findOne.mockResolvedValue(null);
|
|
336
|
-
|
|
337
|
-
const result = await service.getAuthCode('non-existent-code');
|
|
338
|
-
|
|
339
|
-
expect(result).toBeUndefined();
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('should handle database errors', async () => {
|
|
343
|
-
const error = new Error('Database error');
|
|
344
|
-
authCodeRepository.findOne.mockRejectedValue(error);
|
|
345
|
-
|
|
346
|
-
await expect(service.getAuthCode('test-auth-code')).rejects.toThrow(
|
|
347
|
-
'Database error',
|
|
348
|
-
);
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
describe('removeAuthCode', () => {
|
|
353
|
-
it('should remove an authorization code', async () => {
|
|
354
|
-
authCodeRepository.delete.mockResolvedValue({
|
|
355
|
-
raw: {},
|
|
356
|
-
affected: 1,
|
|
357
|
-
} as DeleteResult);
|
|
358
|
-
|
|
359
|
-
await service.removeAuthCode('test-auth-code');
|
|
360
|
-
|
|
361
|
-
expect(authCodeRepository.delete).toHaveBeenCalledWith({
|
|
362
|
-
code: 'test-auth-code',
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
it('should handle database errors', async () => {
|
|
367
|
-
const error = new Error('Database error');
|
|
368
|
-
authCodeRepository.delete.mockRejectedValue(error);
|
|
369
|
-
|
|
370
|
-
await expect(service.removeAuthCode('test-auth-code')).rejects.toThrow(
|
|
371
|
-
'Database error',
|
|
372
|
-
);
|
|
373
|
-
});
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
describe('OAuth Session Management', () => {
|
|
378
|
-
const mockSession: OAuthSession = {
|
|
379
|
-
sessionId: 'session-123',
|
|
380
|
-
state: 'test-state',
|
|
381
|
-
clientId: 'client-123',
|
|
382
|
-
redirectUri: 'http://localhost:3000/callback',
|
|
383
|
-
codeChallenge: 'test-challenge',
|
|
384
|
-
codeChallengeMethod: 'S256',
|
|
385
|
-
oauthState: 'oauth-state-123',
|
|
386
|
-
resource: 'test-resource',
|
|
387
|
-
expiresAt: Date.now() + 3600000, // 1 hour from now
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
const expiredSession: OAuthSession = {
|
|
391
|
-
...mockSession,
|
|
392
|
-
sessionId: 'expired-session',
|
|
393
|
-
expiresAt: Date.now() - 1000, // 1 second ago
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
describe('storeOAuthSession', () => {
|
|
397
|
-
it('should store an OAuth session', async () => {
|
|
398
|
-
const expectedEntity = { ...mockSession, sessionId: 'session-123' };
|
|
399
|
-
sessionRepository.save.mockResolvedValue(
|
|
400
|
-
expectedEntity as OAuthSessionEntity,
|
|
401
|
-
);
|
|
402
|
-
|
|
403
|
-
await service.storeOAuthSession('session-123', mockSession);
|
|
404
|
-
|
|
405
|
-
expect(sessionRepository.save).toHaveBeenCalledWith(expectedEntity);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
it('should handle database errors', async () => {
|
|
409
|
-
const error = new Error('Database error');
|
|
410
|
-
sessionRepository.save.mockRejectedValue(error);
|
|
411
|
-
|
|
412
|
-
await expect(
|
|
413
|
-
service.storeOAuthSession('session-123', mockSession),
|
|
414
|
-
).rejects.toThrow('Database error');
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
describe('getOAuthSession', () => {
|
|
419
|
-
it('should return OAuth session when found and not expired', async () => {
|
|
420
|
-
sessionRepository.findOne.mockResolvedValue(
|
|
421
|
-
mockSession as OAuthSessionEntity,
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
const result = await service.getOAuthSession('session-123');
|
|
425
|
-
|
|
426
|
-
expect(sessionRepository.findOne).toHaveBeenCalledWith({
|
|
427
|
-
where: { sessionId: 'session-123' },
|
|
428
|
-
});
|
|
429
|
-
expect(result).toEqual(mockSession);
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
it('should return undefined and delete expired OAuth session', async () => {
|
|
433
|
-
sessionRepository.findOne.mockResolvedValue(
|
|
434
|
-
expiredSession as OAuthSessionEntity,
|
|
435
|
-
);
|
|
436
|
-
sessionRepository.delete.mockResolvedValue({
|
|
437
|
-
raw: {},
|
|
438
|
-
affected: 1,
|
|
439
|
-
} as DeleteResult);
|
|
440
|
-
|
|
441
|
-
const result = await service.getOAuthSession('expired-session');
|
|
442
|
-
|
|
443
|
-
expect(sessionRepository.findOne).toHaveBeenCalledWith({
|
|
444
|
-
where: { sessionId: 'expired-session' },
|
|
445
|
-
});
|
|
446
|
-
expect(sessionRepository.delete).toHaveBeenCalledWith({
|
|
447
|
-
sessionId: 'expired-session',
|
|
448
|
-
});
|
|
449
|
-
expect(result).toBeUndefined();
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
it('should return undefined when OAuth session not found', async () => {
|
|
453
|
-
sessionRepository.findOne.mockResolvedValue(null);
|
|
454
|
-
|
|
455
|
-
const result = await service.getOAuthSession('non-existent-session');
|
|
456
|
-
|
|
457
|
-
expect(result).toBeUndefined();
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
it('should handle database errors', async () => {
|
|
461
|
-
const error = new Error('Database error');
|
|
462
|
-
sessionRepository.findOne.mockRejectedValue(error);
|
|
463
|
-
|
|
464
|
-
await expect(service.getOAuthSession('session-123')).rejects.toThrow(
|
|
465
|
-
'Database error',
|
|
466
|
-
);
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
|
|
470
|
-
describe('removeOAuthSession', () => {
|
|
471
|
-
it('should remove an OAuth session', async () => {
|
|
472
|
-
sessionRepository.delete.mockResolvedValue({
|
|
473
|
-
raw: {},
|
|
474
|
-
affected: 1,
|
|
475
|
-
} as DeleteResult);
|
|
476
|
-
|
|
477
|
-
await service.removeOAuthSession('session-123');
|
|
478
|
-
|
|
479
|
-
expect(sessionRepository.delete).toHaveBeenCalledWith({
|
|
480
|
-
sessionId: 'session-123',
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
it('should handle database errors', async () => {
|
|
485
|
-
const error = new Error('Database error');
|
|
486
|
-
sessionRepository.delete.mockRejectedValue(error);
|
|
487
|
-
|
|
488
|
-
await expect(service.removeOAuthSession('session-123')).rejects.toThrow(
|
|
489
|
-
'Database error',
|
|
490
|
-
);
|
|
491
|
-
});
|
|
492
|
-
});
|
|
493
|
-
});
|
|
494
|
-
});
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
2
|
-
import { InjectRepository } from '@nestjs/typeorm';
|
|
3
|
-
import { Repository } from 'typeorm';
|
|
4
|
-
import { randomBytes, createHash } from 'crypto';
|
|
5
|
-
import {
|
|
6
|
-
OAuthClientEntity,
|
|
7
|
-
AuthorizationCodeEntity,
|
|
8
|
-
OAuthSessionEntity,
|
|
9
|
-
OAuthUserProfileEntity,
|
|
10
|
-
} from './entities';
|
|
11
|
-
import { OAUTH_TYPEORM_CONNECTION_NAME } from './constants';
|
|
12
|
-
import type {
|
|
13
|
-
OAuthSession,
|
|
14
|
-
OAuthUserProfile,
|
|
15
|
-
} from '../../interfaces/oauth-common.interface';
|
|
16
|
-
import type {
|
|
17
|
-
AuthorizationCode,
|
|
18
|
-
IOAuthStore,
|
|
19
|
-
OAuthClient,
|
|
20
|
-
} from '../oauth-store.interface';
|
|
21
|
-
|
|
22
|
-
@Injectable()
|
|
23
|
-
export class TypeOrmStore implements IOAuthStore {
|
|
24
|
-
constructor(
|
|
25
|
-
@InjectRepository(OAuthClientEntity, OAUTH_TYPEORM_CONNECTION_NAME)
|
|
26
|
-
private readonly clientRepository: Repository<OAuthClientEntity>,
|
|
27
|
-
@InjectRepository(AuthorizationCodeEntity, OAUTH_TYPEORM_CONNECTION_NAME)
|
|
28
|
-
private readonly authCodeRepository: Repository<AuthorizationCodeEntity>,
|
|
29
|
-
@InjectRepository(OAuthSessionEntity, OAUTH_TYPEORM_CONNECTION_NAME)
|
|
30
|
-
private readonly sessionRepository: Repository<OAuthSessionEntity>,
|
|
31
|
-
@InjectRepository(OAuthUserProfileEntity, OAUTH_TYPEORM_CONNECTION_NAME)
|
|
32
|
-
private readonly userProfileRepository: Repository<OAuthUserProfileEntity>,
|
|
33
|
-
) {}
|
|
34
|
-
|
|
35
|
-
// Client management
|
|
36
|
-
async storeClient(client: OAuthClient): Promise<OAuthClient> {
|
|
37
|
-
const savedClient = await this.clientRepository.save(client);
|
|
38
|
-
return savedClient;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async getClient(client_id: string): Promise<OAuthClient | undefined> {
|
|
42
|
-
return (
|
|
43
|
-
(await this.clientRepository.findOne({ where: { client_id } })) ??
|
|
44
|
-
undefined
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async findClient(client_name: string): Promise<OAuthClient | undefined> {
|
|
49
|
-
return (
|
|
50
|
-
(await this.clientRepository.findOne({ where: { client_name } })) ??
|
|
51
|
-
undefined
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Authorization code management
|
|
56
|
-
async storeAuthCode(code: AuthorizationCode): Promise<void> {
|
|
57
|
-
await this.authCodeRepository.save(code);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async getAuthCode(code: string): Promise<AuthorizationCode | undefined> {
|
|
61
|
-
const authCode = await this.authCodeRepository.findOne({ where: { code } });
|
|
62
|
-
// Check if expired
|
|
63
|
-
if (authCode && authCode.expires_at < Date.now()) {
|
|
64
|
-
await this.authCodeRepository.delete({ code });
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
return authCode ?? undefined;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async removeAuthCode(code: string): Promise<void> {
|
|
71
|
-
await this.authCodeRepository.delete({ code });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// OAuth session management
|
|
75
|
-
async storeOAuthSession(
|
|
76
|
-
sessionId: string,
|
|
77
|
-
session: OAuthSession,
|
|
78
|
-
): Promise<void> {
|
|
79
|
-
await this.sessionRepository.save({ ...session, sessionId });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async getOAuthSession(sessionId: string): Promise<OAuthSession | undefined> {
|
|
83
|
-
const session = await this.sessionRepository.findOne({
|
|
84
|
-
where: { sessionId },
|
|
85
|
-
});
|
|
86
|
-
if (session && session.expiresAt < Date.now()) {
|
|
87
|
-
await this.sessionRepository.delete({ sessionId });
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
return session ?? undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async removeOAuthSession(sessionId: string): Promise<void> {
|
|
94
|
-
await this.sessionRepository.delete({ sessionId });
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
generateClientId(client: OAuthClient): string {
|
|
98
|
-
// Create deterministic client ID based on name + random salt
|
|
99
|
-
const normalizedName = client.client_name
|
|
100
|
-
.toLowerCase()
|
|
101
|
-
.replace(/[^a-z0-9]/g, '');
|
|
102
|
-
const salt = randomBytes(4).toString('hex');
|
|
103
|
-
return `${normalizedName}_${salt}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// User profile management
|
|
107
|
-
async upsertUserProfile(
|
|
108
|
-
profile: OAuthUserProfile,
|
|
109
|
-
provider: string,
|
|
110
|
-
): Promise<string> {
|
|
111
|
-
// Try find by provider+provider_user_id
|
|
112
|
-
const existing = await this.userProfileRepository.findOne({
|
|
113
|
-
where: { provider, provider_user_id: profile.id },
|
|
114
|
-
});
|
|
115
|
-
if (existing) {
|
|
116
|
-
// Update fields that may change
|
|
117
|
-
existing.username = profile.username;
|
|
118
|
-
existing.email = profile.email;
|
|
119
|
-
existing.displayName = profile.displayName;
|
|
120
|
-
existing.avatarUrl = profile.avatarUrl;
|
|
121
|
-
existing.raw = profile.raw ? JSON.stringify(profile.raw) : existing.raw;
|
|
122
|
-
await this.userProfileRepository.save(existing);
|
|
123
|
-
return existing.profile_id;
|
|
124
|
-
}
|
|
125
|
-
// Create new
|
|
126
|
-
const entity = this.userProfileRepository.create({
|
|
127
|
-
profile_id: this.generateProfileId(provider, profile.id),
|
|
128
|
-
provider_user_id: profile.id,
|
|
129
|
-
provider,
|
|
130
|
-
username: profile.username,
|
|
131
|
-
email: profile.email,
|
|
132
|
-
displayName: profile.displayName,
|
|
133
|
-
avatarUrl: profile.avatarUrl,
|
|
134
|
-
raw: profile.raw ? JSON.stringify(profile.raw) : undefined,
|
|
135
|
-
});
|
|
136
|
-
const saved = await this.userProfileRepository.save(entity);
|
|
137
|
-
return saved.profile_id;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async getUserProfileById(
|
|
141
|
-
profileId: string,
|
|
142
|
-
): Promise<
|
|
143
|
-
(OAuthUserProfile & { profile_id: string; provider: string }) | undefined
|
|
144
|
-
> {
|
|
145
|
-
const entity = await this.userProfileRepository.findOne({
|
|
146
|
-
where: { profile_id: profileId },
|
|
147
|
-
});
|
|
148
|
-
if (!entity) return undefined;
|
|
149
|
-
return {
|
|
150
|
-
profile_id: entity.profile_id,
|
|
151
|
-
provider: entity.provider,
|
|
152
|
-
id: entity.provider_user_id,
|
|
153
|
-
username: entity.username,
|
|
154
|
-
email: entity.email,
|
|
155
|
-
displayName: entity.displayName,
|
|
156
|
-
avatarUrl: entity.avatarUrl,
|
|
157
|
-
raw: entity.raw ? JSON.parse(entity.raw) : undefined,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
private generateProfileId(provider: string, providerUserId: string): string {
|
|
162
|
-
const input = `${provider}:${providerUserId}`;
|
|
163
|
-
return createHash('sha256').update(input).digest('hex').slice(0, 24);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { InjectionToken } from '@nestjs/common';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Token prefix for feature registrations.
|
|
5
|
-
* Each McpModule.forFeature() call creates a unique provider with this prefix.
|
|
6
|
-
*/
|
|
7
|
-
export const MCP_FEATURE_REGISTRATION = 'MCP_FEATURE_REGISTRATION';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Interface for feature registration metadata.
|
|
11
|
-
* Used to map provider tokens to specific MCP server names.
|
|
12
|
-
*/
|
|
13
|
-
export interface McpFeatureRegistration {
|
|
14
|
-
/**
|
|
15
|
-
* The name of the MCP server this feature should register to.
|
|
16
|
-
* Must match the `name` in a McpModule.forRoot() configuration.
|
|
17
|
-
*/
|
|
18
|
-
serverName: string;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Provider tokens (class constructors or injection tokens) to scan for tools/resources/prompts.
|
|
22
|
-
*/
|
|
23
|
-
providerTokens: InjectionToken[];
|
|
24
|
-
}
|