quidproquo-webserver 0.1.19 → 0.1.21
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 +1 -2
- package/lib/commonjs/actionProcessor/api/getHttpApiEventAutoRespondActionProcessor.js +7 -5
- package/lib/commonjs/actionProcessor/api/getHttpApiEventAutoRespondActionProcessor.js.map +1 -1
- package/lib/commonjs/actions/dns/DnsActionType.d.ts +3 -1
- package/lib/commonjs/actions/dns/DnsActionType.js +2 -0
- package/lib/commonjs/actions/dns/DnsActionType.js.map +1 -1
- package/lib/commonjs/actions/dns/askDnsList.d.ts +2 -1
- package/lib/commonjs/actions/dns/askDnsList.js +1 -0
- package/lib/commonjs/actions/dns/askDnsList.js.map +1 -1
- package/lib/commonjs/actions/dns/askDnsResolveHosts.d.ts +9 -0
- package/lib/commonjs/actions/dns/askDnsResolveHosts.js +11 -0
- package/lib/commonjs/actions/dns/askDnsResolveHosts.js.map +1 -0
- package/lib/commonjs/actions/dns/index.d.ts +1 -0
- package/lib/commonjs/actions/dns/index.js +1 -0
- package/lib/commonjs/actions/dns/index.js.map +1 -1
- package/lib/commonjs/actions/index.d.ts +1 -1
- package/lib/commonjs/actions/index.js +1 -1
- package/lib/commonjs/actions/index.js.map +1 -1
- package/lib/commonjs/actions/openApi/OpenApiActionType.d.ts +3 -0
- package/lib/commonjs/actions/openApi/OpenApiActionType.js +8 -0
- package/lib/commonjs/actions/openApi/OpenApiActionType.js.map +1 -0
- package/lib/commonjs/actions/openApi/askOpenApiGetDocument.d.ts +9 -0
- package/lib/commonjs/actions/openApi/askOpenApiGetDocument.js +12 -0
- package/lib/commonjs/actions/openApi/askOpenApiGetDocument.js.map +1 -0
- package/lib/commonjs/actions/openApi/index.d.ts +2 -0
- package/lib/commonjs/actions/{openApiSpec → openApi}/index.js +2 -2
- package/lib/commonjs/actions/openApi/index.js.map +1 -0
- package/lib/commonjs/config/QPQConfig.d.ts +0 -1
- package/lib/commonjs/config/QPQConfig.js +0 -1
- package/lib/commonjs/config/QPQConfig.js.map +1 -1
- package/lib/commonjs/config/settings/api.d.ts +1 -2
- package/lib/commonjs/config/settings/api.js +1 -2
- package/lib/commonjs/config/settings/api.js.map +1 -1
- package/lib/commonjs/config/settings/dns.d.ts +15 -5
- package/lib/commonjs/config/settings/dns.js +10 -5
- package/lib/commonjs/config/settings/dns.js.map +1 -1
- package/lib/commonjs/config/settings/domainProxy.d.ts +0 -1
- package/lib/commonjs/config/settings/domainProxy.js.map +1 -1
- package/lib/commonjs/config/settings/emailSender.d.ts +3 -4
- package/lib/commonjs/config/settings/emailSender.js +5 -7
- package/lib/commonjs/config/settings/emailSender.js.map +1 -1
- package/lib/commonjs/config/settings/index.d.ts +0 -1
- package/lib/commonjs/config/settings/index.js +0 -1
- package/lib/commonjs/config/settings/index.js.map +1 -1
- package/lib/commonjs/config/settings/route.d.ts +2 -0
- package/lib/commonjs/config/settings/route.js.map +1 -1
- package/lib/commonjs/config/settings/webEntry.d.ts +0 -1
- package/lib/commonjs/config/settings/webEntry.js.map +1 -1
- package/lib/commonjs/config/settings/websocket.d.ts +1 -2
- package/lib/commonjs/config/settings/websocket.js +3 -12
- package/lib/commonjs/config/settings/websocket.js.map +1 -1
- package/lib/commonjs/config/types/JsonSchema.d.ts +1 -0
- package/lib/commonjs/config/types/JsonSchema.js +3 -0
- package/lib/commonjs/config/types/JsonSchema.js.map +1 -0
- package/lib/commonjs/config/types/RouteSchema.d.ts +10 -0
- package/lib/commonjs/config/types/RouteSchema.js +3 -0
- package/lib/commonjs/config/types/RouteSchema.js.map +1 -0
- package/lib/commonjs/config/types/index.d.ts +2 -0
- package/lib/commonjs/config/types/index.js +2 -0
- package/lib/commonjs/config/types/index.js.map +1 -1
- package/lib/commonjs/configUtils/dns/getDnsConfig.d.ts +4 -0
- package/lib/commonjs/configUtils/dns/getDnsConfig.js +16 -0
- package/lib/commonjs/configUtils/dns/getDnsConfig.js.map +1 -0
- package/lib/commonjs/configUtils/dns/getPrimaryRootDomain.d.ts +3 -0
- package/lib/commonjs/configUtils/dns/getPrimaryRootDomain.js +8 -0
- package/lib/commonjs/configUtils/dns/getPrimaryRootDomain.js.map +1 -0
- package/lib/commonjs/configUtils/dns/getRootDomains.d.ts +3 -0
- package/lib/commonjs/configUtils/dns/getRootDomains.js +8 -0
- package/lib/commonjs/configUtils/dns/getRootDomains.js.map +1 -0
- package/lib/commonjs/configUtils/dns/index.d.ts +3 -0
- package/lib/commonjs/configUtils/dns/index.js +20 -0
- package/lib/commonjs/configUtils/dns/index.js.map +1 -0
- package/lib/commonjs/configUtils/index.d.ts +2 -0
- package/lib/commonjs/configUtils/index.js +19 -0
- package/lib/commonjs/configUtils/index.js.map +1 -0
- package/lib/commonjs/configUtils/storageDrive/getStorageDriveCorsSettingsByName.d.ts +4 -0
- package/lib/commonjs/configUtils/storageDrive/getStorageDriveCorsSettingsByName.js +14 -0
- package/lib/commonjs/configUtils/storageDrive/getStorageDriveCorsSettingsByName.js.map +1 -0
- package/lib/commonjs/configUtils/storageDrive/index.d.ts +1 -0
- package/lib/commonjs/configUtils/storageDrive/index.js +18 -0
- package/lib/commonjs/configUtils/storageDrive/index.js.map +1 -0
- package/lib/commonjs/domain/index.d.ts +2 -0
- package/lib/commonjs/domain/index.js +19 -0
- package/lib/commonjs/domain/index.js.map +1 -0
- package/lib/commonjs/domain/logic/host/findRootDomainForHost.d.ts +6 -0
- package/lib/commonjs/domain/logic/host/findRootDomainForHost.js +19 -0
- package/lib/commonjs/domain/logic/host/findRootDomainForHost.js.map +1 -0
- package/lib/commonjs/domain/logic/host/getDomainTargetKey.d.ts +3 -0
- package/lib/commonjs/domain/logic/host/getDomainTargetKey.js +7 -0
- package/lib/commonjs/domain/logic/host/getDomainTargetKey.js.map +1 -0
- package/lib/commonjs/domain/logic/host/index.d.ts +6 -0
- package/lib/commonjs/domain/logic/host/index.js +23 -0
- package/lib/commonjs/domain/logic/host/index.js.map +1 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRequestHost.d.ts +9 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRequestHost.js +21 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRequestHost.js.map +1 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRoot.d.ts +5 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRoot.js +15 -0
- package/lib/commonjs/domain/logic/host/resolveHostForRoot.js.map +1 -0
- package/lib/commonjs/domain/logic/host/resolveHosts.d.ts +9 -0
- package/lib/commonjs/domain/logic/host/resolveHosts.js +27 -0
- package/lib/commonjs/domain/logic/host/resolveHosts.js.map +1 -0
- package/lib/commonjs/domain/logic/host/resolvePrimaryHost.d.ts +5 -0
- package/lib/commonjs/domain/logic/host/resolvePrimaryHost.js +14 -0
- package/lib/commonjs/domain/logic/host/resolvePrimaryHost.js.map +1 -0
- package/lib/commonjs/domain/logic/index.d.ts +3 -0
- package/lib/commonjs/domain/logic/index.js +20 -0
- package/lib/commonjs/domain/logic/index.js.map +1 -0
- package/lib/commonjs/domain/logic/origin/getStorageDriveCorsAllowedOrigins.d.ts +4 -0
- package/lib/commonjs/domain/logic/origin/getStorageDriveCorsAllowedOrigins.js +9 -0
- package/lib/commonjs/domain/logic/origin/getStorageDriveCorsAllowedOrigins.js.map +1 -0
- package/lib/commonjs/domain/logic/origin/index.d.ts +4 -0
- package/lib/commonjs/domain/logic/origin/index.js +21 -0
- package/lib/commonjs/domain/logic/origin/index.js.map +1 -0
- package/lib/commonjs/domain/logic/origin/resolveContentSecurityPolicyEntry.d.ts +9 -0
- package/lib/commonjs/domain/logic/origin/resolveContentSecurityPolicyEntry.js +20 -0
- package/lib/commonjs/domain/logic/origin/resolveContentSecurityPolicyEntry.js.map +1 -0
- package/lib/commonjs/domain/logic/origin/resolveOrigins.d.ts +8 -0
- package/lib/commonjs/domain/logic/origin/resolveOrigins.js +20 -0
- package/lib/commonjs/domain/logic/origin/resolveOrigins.js.map +1 -0
- package/lib/commonjs/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.d.ts +8 -0
- package/lib/commonjs/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.js +21 -0
- package/lib/commonjs/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.js.map +1 -0
- package/lib/commonjs/domain/logic/resolver/getDomainResolver.d.ts +4 -0
- package/lib/commonjs/domain/logic/resolver/getDomainResolver.js +20 -0
- package/lib/commonjs/domain/logic/resolver/getDomainResolver.js.map +1 -0
- package/lib/commonjs/domain/logic/resolver/index.d.ts +4 -0
- package/lib/commonjs/domain/logic/resolver/index.js +21 -0
- package/lib/commonjs/domain/logic/resolver/index.js.map +1 -0
- package/lib/commonjs/domain/logic/resolver/isLocalhostRootDomain.d.ts +2 -0
- package/lib/commonjs/domain/logic/resolver/isLocalhostRootDomain.js +7 -0
- package/lib/commonjs/domain/logic/resolver/isLocalhostRootDomain.js.map +1 -0
- package/lib/commonjs/domain/logic/resolver/loadDomainResolver.d.ts +8 -0
- package/lib/commonjs/domain/logic/resolver/loadDomainResolver.js +33 -0
- package/lib/commonjs/domain/logic/resolver/loadDomainResolver.js.map +1 -0
- package/lib/commonjs/domain/logic/resolver/validateResolvedHost.d.ts +3 -0
- package/lib/commonjs/domain/logic/resolver/validateResolvedHost.js +13 -0
- package/lib/commonjs/domain/logic/resolver/validateResolvedHost.js.map +1 -0
- package/lib/commonjs/domain/resolvers/defaultDomainResolver.d.ts +3 -0
- package/lib/commonjs/domain/resolvers/defaultDomainResolver.js +11 -0
- package/lib/commonjs/domain/resolvers/defaultDomainResolver.js.map +1 -0
- package/lib/commonjs/domain/resolvers/index.d.ts +2 -0
- package/lib/commonjs/domain/resolvers/index.js +19 -0
- package/lib/commonjs/domain/resolvers/index.js.map +1 -0
- package/lib/commonjs/domain/resolvers/localhostDomainResolver.d.ts +3 -0
- package/lib/commonjs/domain/resolvers/localhostDomainResolver.js +8 -0
- package/lib/commonjs/domain/resolvers/localhostDomainResolver.js.map +1 -0
- package/lib/commonjs/domain/types/DomainResolver.d.ts +10 -0
- package/lib/commonjs/domain/types/DomainResolver.js +3 -0
- package/lib/commonjs/domain/types/DomainResolver.js.map +1 -0
- package/lib/commonjs/domain/types/DomainScope.d.ts +13 -0
- package/lib/commonjs/domain/types/DomainScope.js +3 -0
- package/lib/commonjs/domain/types/DomainScope.js.map +1 -0
- package/lib/commonjs/domain/types/DomainTarget.d.ts +5 -0
- package/lib/commonjs/domain/types/DomainTarget.js +3 -0
- package/lib/commonjs/domain/types/DomainTarget.js.map +1 -0
- package/lib/commonjs/domain/types/index.d.ts +3 -0
- package/lib/commonjs/domain/types/index.js +20 -0
- package/lib/commonjs/domain/types/index.js.map +1 -0
- package/lib/commonjs/index.d.ts +1 -0
- package/lib/commonjs/index.js +1 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/stories/index.d.ts +0 -1
- package/lib/commonjs/stories/index.js +0 -1
- package/lib/commonjs/stories/index.js.map +1 -1
- package/lib/commonjs/types/OpenApiDocument.d.ts +60 -0
- package/lib/commonjs/types/OpenApiDocument.js +3 -0
- package/lib/commonjs/types/OpenApiDocument.js.map +1 -0
- package/lib/commonjs/types/index.d.ts +1 -0
- package/lib/commonjs/types/index.js +1 -0
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/commonjs/utils/headerUtils.d.ts +5 -4
- package/lib/commonjs/utils/headerUtils.js +16 -29
- package/lib/commonjs/utils/headerUtils.js.map +1 -1
- package/lib/commonjs/utils/index.d.ts +3 -0
- package/lib/commonjs/utils/index.js +3 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/mergeRouteUtils.js +3 -0
- package/lib/commonjs/utils/mergeRouteUtils.js.map +1 -1
- package/lib/commonjs/utils/openApi/OpenApiDocumentOptions.d.ts +2 -0
- package/lib/commonjs/utils/openApi/OpenApiDocumentOptions.js +3 -0
- package/lib/commonjs/utils/openApi/OpenApiDocumentOptions.js.map +1 -0
- package/lib/commonjs/utils/openApi/buildOpenApiDocument.d.ts +5 -0
- package/lib/commonjs/utils/openApi/buildOpenApiDocument.js +55 -0
- package/lib/commonjs/utils/openApi/buildOpenApiDocument.js.map +1 -0
- package/lib/commonjs/utils/openApi/buildOpenApiOperation.d.ts +4 -0
- package/lib/commonjs/utils/openApi/buildOpenApiOperation.js +45 -0
- package/lib/commonjs/utils/openApi/buildOpenApiOperation.js.map +1 -0
- package/lib/commonjs/utils/openApi/buildOpenApiPathParameters.d.ts +2 -0
- package/lib/commonjs/utils/openApi/buildOpenApiPathParameters.js +13 -0
- package/lib/commonjs/utils/openApi/buildOpenApiPathParameters.js.map +1 -0
- package/lib/commonjs/utils/openApi/buildOpenApiQueryParameters.d.ts +3 -0
- package/lib/commonjs/utils/openApi/buildOpenApiQueryParameters.js +25 -0
- package/lib/commonjs/utils/openApi/buildOpenApiQueryParameters.js.map +1 -0
- package/lib/commonjs/utils/openApi/buildOpenApiSecurity.d.ts +4 -0
- package/lib/commonjs/utils/openApi/buildOpenApiSecurity.js +24 -0
- package/lib/commonjs/utils/openApi/buildOpenApiSecurity.js.map +1 -0
- package/lib/commonjs/utils/openApi/index.d.ts +7 -0
- package/lib/commonjs/utils/openApi/index.js +24 -0
- package/lib/commonjs/utils/openApi/index.js.map +1 -0
- package/lib/commonjs/utils/openApi/openApiSecuritySchemeNames.d.ts +2 -0
- package/lib/commonjs/utils/openApi/openApiSecuritySchemeNames.js +7 -0
- package/lib/commonjs/utils/openApi/openApiSecuritySchemeNames.js.map +1 -0
- package/lib/commonjs/utils/qpqConfigAccessorsUtils.d.ts +1 -34
- package/lib/commonjs/utils/qpqConfigAccessorsUtils.js +7 -114
- package/lib/commonjs/utils/qpqConfigAccessorsUtils.js.map +1 -1
- package/lib/esm/actionProcessor/api/getHttpApiEventAutoRespondActionProcessor.js +6 -4
- package/lib/esm/actionProcessor/api/getHttpApiEventAutoRespondActionProcessor.js.map +1 -1
- package/lib/esm/actions/dns/DnsActionType.d.ts +3 -1
- package/lib/esm/actions/dns/DnsActionType.js +2 -0
- package/lib/esm/actions/dns/DnsActionType.js.map +1 -1
- package/lib/esm/actions/dns/askDnsList.d.ts +2 -1
- package/lib/esm/actions/dns/askDnsList.js +1 -0
- package/lib/esm/actions/dns/askDnsList.js.map +1 -1
- package/lib/esm/actions/dns/askDnsResolveHosts.d.ts +9 -0
- package/lib/esm/actions/dns/askDnsResolveHosts.js +8 -0
- package/lib/esm/actions/dns/askDnsResolveHosts.js.map +1 -0
- package/lib/esm/actions/dns/index.d.ts +1 -0
- package/lib/esm/actions/dns/index.js +1 -0
- package/lib/esm/actions/dns/index.js.map +1 -1
- package/lib/esm/actions/index.d.ts +1 -1
- package/lib/esm/actions/index.js +1 -1
- package/lib/esm/actions/index.js.map +1 -1
- package/lib/esm/actions/openApi/OpenApiActionType.d.ts +3 -0
- package/lib/esm/actions/openApi/OpenApiActionType.js +5 -0
- package/lib/esm/actions/openApi/OpenApiActionType.js.map +1 -0
- package/lib/esm/actions/openApi/askOpenApiGetDocument.d.ts +9 -0
- package/lib/esm/actions/openApi/askOpenApiGetDocument.js +9 -0
- package/lib/esm/actions/openApi/askOpenApiGetDocument.js.map +1 -0
- package/lib/esm/actions/openApi/index.d.ts +2 -0
- package/lib/esm/actions/openApi/index.js +3 -0
- package/lib/esm/actions/openApi/index.js.map +1 -0
- package/lib/esm/config/QPQConfig.d.ts +0 -1
- package/lib/esm/config/QPQConfig.js +0 -1
- package/lib/esm/config/QPQConfig.js.map +1 -1
- package/lib/esm/config/settings/api.d.ts +1 -2
- package/lib/esm/config/settings/api.js +1 -2
- package/lib/esm/config/settings/api.js.map +1 -1
- package/lib/esm/config/settings/dns.d.ts +15 -5
- package/lib/esm/config/settings/dns.js +10 -5
- package/lib/esm/config/settings/dns.js.map +1 -1
- package/lib/esm/config/settings/domainProxy.d.ts +0 -1
- package/lib/esm/config/settings/domainProxy.js.map +1 -1
- package/lib/esm/config/settings/emailSender.d.ts +3 -4
- package/lib/esm/config/settings/emailSender.js +5 -7
- package/lib/esm/config/settings/emailSender.js.map +1 -1
- package/lib/esm/config/settings/index.d.ts +0 -1
- package/lib/esm/config/settings/index.js +0 -1
- package/lib/esm/config/settings/index.js.map +1 -1
- package/lib/esm/config/settings/route.d.ts +2 -0
- package/lib/esm/config/settings/route.js.map +1 -1
- package/lib/esm/config/settings/webEntry.d.ts +0 -1
- package/lib/esm/config/settings/webEntry.js.map +1 -1
- package/lib/esm/config/settings/websocket.d.ts +1 -2
- package/lib/esm/config/settings/websocket.js +3 -12
- package/lib/esm/config/settings/websocket.js.map +1 -1
- package/lib/esm/config/types/JsonSchema.d.ts +1 -0
- package/lib/esm/config/types/JsonSchema.js +2 -0
- package/lib/esm/config/types/JsonSchema.js.map +1 -0
- package/lib/esm/config/types/RouteSchema.d.ts +10 -0
- package/lib/esm/config/types/RouteSchema.js +2 -0
- package/lib/esm/config/types/RouteSchema.js.map +1 -0
- package/lib/esm/config/types/index.d.ts +2 -0
- package/lib/esm/config/types/index.js +2 -0
- package/lib/esm/config/types/index.js.map +1 -1
- package/lib/esm/configUtils/dns/getDnsConfig.d.ts +4 -0
- package/lib/esm/configUtils/dns/getDnsConfig.js +11 -0
- package/lib/esm/configUtils/dns/getDnsConfig.js.map +1 -0
- package/lib/esm/configUtils/dns/getPrimaryRootDomain.d.ts +3 -0
- package/lib/esm/configUtils/dns/getPrimaryRootDomain.js +4 -0
- package/lib/esm/configUtils/dns/getPrimaryRootDomain.js.map +1 -0
- package/lib/esm/configUtils/dns/getRootDomains.d.ts +3 -0
- package/lib/esm/configUtils/dns/getRootDomains.js +4 -0
- package/lib/esm/configUtils/dns/getRootDomains.js.map +1 -0
- package/lib/esm/configUtils/dns/index.d.ts +3 -0
- package/lib/esm/configUtils/dns/index.js +4 -0
- package/lib/esm/configUtils/dns/index.js.map +1 -0
- package/lib/esm/configUtils/index.d.ts +2 -0
- package/lib/esm/configUtils/index.js +3 -0
- package/lib/esm/configUtils/index.js.map +1 -0
- package/lib/esm/configUtils/storageDrive/getStorageDriveCorsSettingsByName.d.ts +4 -0
- package/lib/esm/configUtils/storageDrive/getStorageDriveCorsSettingsByName.js +7 -0
- package/lib/esm/configUtils/storageDrive/getStorageDriveCorsSettingsByName.js.map +1 -0
- package/lib/esm/configUtils/storageDrive/index.d.ts +1 -0
- package/lib/esm/configUtils/storageDrive/index.js +2 -0
- package/lib/esm/configUtils/storageDrive/index.js.map +1 -0
- package/lib/esm/domain/index.d.ts +2 -0
- package/lib/esm/domain/index.js +3 -0
- package/lib/esm/domain/index.js.map +1 -0
- package/lib/esm/domain/logic/host/findRootDomainForHost.d.ts +6 -0
- package/lib/esm/domain/logic/host/findRootDomainForHost.js +14 -0
- package/lib/esm/domain/logic/host/findRootDomainForHost.js.map +1 -0
- package/lib/esm/domain/logic/host/getDomainTargetKey.d.ts +3 -0
- package/lib/esm/domain/logic/host/getDomainTargetKey.js +3 -0
- package/lib/esm/domain/logic/host/getDomainTargetKey.js.map +1 -0
- package/lib/esm/domain/logic/host/index.d.ts +6 -0
- package/lib/esm/domain/logic/host/index.js +7 -0
- package/lib/esm/domain/logic/host/index.js.map +1 -0
- package/lib/esm/domain/logic/host/resolveHostForRequestHost.d.ts +9 -0
- package/lib/esm/domain/logic/host/resolveHostForRequestHost.js +16 -0
- package/lib/esm/domain/logic/host/resolveHostForRequestHost.js.map +1 -0
- package/lib/esm/domain/logic/host/resolveHostForRoot.d.ts +5 -0
- package/lib/esm/domain/logic/host/resolveHostForRoot.js +11 -0
- package/lib/esm/domain/logic/host/resolveHostForRoot.js.map +1 -0
- package/lib/esm/domain/logic/host/resolveHosts.d.ts +9 -0
- package/lib/esm/domain/logic/host/resolveHosts.js +23 -0
- package/lib/esm/domain/logic/host/resolveHosts.js.map +1 -0
- package/lib/esm/domain/logic/host/resolvePrimaryHost.d.ts +5 -0
- package/lib/esm/domain/logic/host/resolvePrimaryHost.js +10 -0
- package/lib/esm/domain/logic/host/resolvePrimaryHost.js.map +1 -0
- package/lib/esm/domain/logic/index.d.ts +3 -0
- package/lib/esm/domain/logic/index.js +4 -0
- package/lib/esm/domain/logic/index.js.map +1 -0
- package/lib/esm/domain/logic/origin/getStorageDriveCorsAllowedOrigins.d.ts +4 -0
- package/lib/esm/domain/logic/origin/getStorageDriveCorsAllowedOrigins.js +5 -0
- package/lib/esm/domain/logic/origin/getStorageDriveCorsAllowedOrigins.js.map +1 -0
- package/lib/esm/domain/logic/origin/index.d.ts +4 -0
- package/lib/esm/domain/logic/origin/index.js +5 -0
- package/lib/esm/domain/logic/origin/index.js.map +1 -0
- package/lib/esm/domain/logic/origin/resolveContentSecurityPolicyEntry.d.ts +9 -0
- package/lib/esm/domain/logic/origin/resolveContentSecurityPolicyEntry.js +16 -0
- package/lib/esm/domain/logic/origin/resolveContentSecurityPolicyEntry.js.map +1 -0
- package/lib/esm/domain/logic/origin/resolveOrigins.d.ts +8 -0
- package/lib/esm/domain/logic/origin/resolveOrigins.js +16 -0
- package/lib/esm/domain/logic/origin/resolveOrigins.js.map +1 -0
- package/lib/esm/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.d.ts +8 -0
- package/lib/esm/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.js +17 -0
- package/lib/esm/domain/logic/origin/resolveServiceScopedCorsAllowedOrigins.js.map +1 -0
- package/lib/esm/domain/logic/resolver/getDomainResolver.d.ts +4 -0
- package/lib/esm/domain/logic/resolver/getDomainResolver.js +16 -0
- package/lib/esm/domain/logic/resolver/getDomainResolver.js.map +1 -0
- package/lib/esm/domain/logic/resolver/index.d.ts +4 -0
- package/lib/esm/domain/logic/resolver/index.js +5 -0
- package/lib/esm/domain/logic/resolver/index.js.map +1 -0
- package/lib/esm/domain/logic/resolver/isLocalhostRootDomain.d.ts +2 -0
- package/lib/esm/domain/logic/resolver/isLocalhostRootDomain.js +3 -0
- package/lib/esm/domain/logic/resolver/isLocalhostRootDomain.js.map +1 -0
- package/lib/esm/domain/logic/resolver/loadDomainResolver.d.ts +8 -0
- package/lib/esm/domain/logic/resolver/loadDomainResolver.js +19 -0
- package/lib/esm/domain/logic/resolver/loadDomainResolver.js.map +1 -0
- package/lib/esm/domain/logic/resolver/validateResolvedHost.d.ts +3 -0
- package/lib/esm/domain/logic/resolver/validateResolvedHost.js +9 -0
- package/lib/esm/domain/logic/resolver/validateResolvedHost.js.map +1 -0
- package/lib/esm/domain/resolvers/defaultDomainResolver.d.ts +3 -0
- package/lib/esm/domain/resolvers/defaultDomainResolver.js +8 -0
- package/lib/esm/domain/resolvers/defaultDomainResolver.js.map +1 -0
- package/lib/esm/domain/resolvers/index.d.ts +2 -0
- package/lib/esm/domain/resolvers/index.js +3 -0
- package/lib/esm/domain/resolvers/index.js.map +1 -0
- package/lib/esm/domain/resolvers/localhostDomainResolver.d.ts +3 -0
- package/lib/esm/domain/resolvers/localhostDomainResolver.js +5 -0
- package/lib/esm/domain/resolvers/localhostDomainResolver.js.map +1 -0
- package/lib/esm/domain/types/DomainResolver.d.ts +10 -0
- package/lib/esm/domain/types/DomainResolver.js +2 -0
- package/lib/esm/domain/types/DomainResolver.js.map +1 -0
- package/lib/esm/domain/types/DomainScope.d.ts +13 -0
- package/lib/esm/domain/types/DomainScope.js +2 -0
- package/lib/esm/domain/types/DomainScope.js.map +1 -0
- package/lib/esm/domain/types/DomainTarget.d.ts +5 -0
- package/lib/esm/domain/types/DomainTarget.js +2 -0
- package/lib/esm/domain/types/DomainTarget.js.map +1 -0
- package/lib/esm/domain/types/index.d.ts +3 -0
- package/lib/esm/domain/types/index.js +4 -0
- package/lib/esm/domain/types/index.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/stories/index.d.ts +0 -1
- package/lib/esm/stories/index.js +0 -1
- package/lib/esm/stories/index.js.map +1 -1
- package/lib/esm/types/OpenApiDocument.d.ts +60 -0
- package/lib/esm/types/OpenApiDocument.js +2 -0
- package/lib/esm/types/OpenApiDocument.js.map +1 -0
- package/lib/esm/types/index.d.ts +1 -0
- package/lib/esm/types/index.js +1 -0
- package/lib/esm/types/index.js.map +1 -1
- package/lib/esm/utils/headerUtils.d.ts +5 -4
- package/lib/esm/utils/headerUtils.js +16 -28
- package/lib/esm/utils/headerUtils.js.map +1 -1
- package/lib/esm/utils/index.d.ts +3 -0
- package/lib/esm/utils/index.js +3 -0
- package/lib/esm/utils/index.js.map +1 -1
- package/lib/esm/utils/mergeRouteUtils.js +2 -0
- package/lib/esm/utils/mergeRouteUtils.js.map +1 -1
- package/lib/esm/utils/openApi/OpenApiDocumentOptions.d.ts +2 -0
- package/lib/esm/utils/openApi/OpenApiDocumentOptions.js +2 -0
- package/lib/esm/utils/openApi/OpenApiDocumentOptions.js.map +1 -0
- package/lib/esm/utils/openApi/buildOpenApiDocument.d.ts +5 -0
- package/lib/esm/utils/openApi/buildOpenApiDocument.js +50 -0
- package/lib/esm/utils/openApi/buildOpenApiDocument.js.map +1 -0
- package/lib/esm/utils/openApi/buildOpenApiOperation.d.ts +4 -0
- package/lib/esm/utils/openApi/buildOpenApiOperation.js +40 -0
- package/lib/esm/utils/openApi/buildOpenApiOperation.js.map +1 -0
- package/lib/esm/utils/openApi/buildOpenApiPathParameters.d.ts +2 -0
- package/lib/esm/utils/openApi/buildOpenApiPathParameters.js +9 -0
- package/lib/esm/utils/openApi/buildOpenApiPathParameters.js.map +1 -0
- package/lib/esm/utils/openApi/buildOpenApiQueryParameters.d.ts +3 -0
- package/lib/esm/utils/openApi/buildOpenApiQueryParameters.js +21 -0
- package/lib/esm/utils/openApi/buildOpenApiQueryParameters.js.map +1 -0
- package/lib/esm/utils/openApi/buildOpenApiSecurity.d.ts +4 -0
- package/lib/esm/utils/openApi/buildOpenApiSecurity.js +19 -0
- package/lib/esm/utils/openApi/buildOpenApiSecurity.js.map +1 -0
- package/lib/esm/utils/openApi/index.d.ts +7 -0
- package/lib/esm/utils/openApi/index.js +8 -0
- package/lib/esm/utils/openApi/index.js.map +1 -0
- package/lib/esm/utils/openApi/openApiSecuritySchemeNames.d.ts +2 -0
- package/lib/esm/utils/openApi/openApiSecuritySchemeNames.js +4 -0
- package/lib/esm/utils/openApi/openApiSecuritySchemeNames.js.map +1 -0
- package/lib/esm/utils/qpqConfigAccessorsUtils.d.ts +1 -34
- package/lib/esm/utils/qpqConfigAccessorsUtils.js +5 -100
- package/lib/esm/utils/qpqConfigAccessorsUtils.js.map +1 -1
- package/package.json +3 -3
- package/lib/commonjs/actions/openApiSpec/OpenApiSpecActionType.d.ts +0 -3
- package/lib/commonjs/actions/openApiSpec/OpenApiSpecActionType.js +0 -8
- package/lib/commonjs/actions/openApiSpec/OpenApiSpecActionType.js.map +0 -1
- package/lib/commonjs/actions/openApiSpec/askGetOpenApiSpec.d.ts +0 -2
- package/lib/commonjs/actions/openApiSpec/askGetOpenApiSpec.js +0 -9
- package/lib/commonjs/actions/openApiSpec/askGetOpenApiSpec.js.map +0 -1
- package/lib/commonjs/actions/openApiSpec/index.d.ts +0 -2
- package/lib/commonjs/actions/openApiSpec/index.js.map +0 -1
- package/lib/commonjs/config/settings/openApi.d.ts +0 -5
- package/lib/commonjs/config/settings/openApi.js +0 -13
- package/lib/commonjs/config/settings/openApi.js.map +0 -1
- package/lib/commonjs/stories/askGetDomainRoot.d.ts +0 -2
- package/lib/commonjs/stories/askGetDomainRoot.js +0 -22
- package/lib/commonjs/stories/askGetDomainRoot.js.map +0 -1
- package/lib/esm/actions/openApiSpec/OpenApiSpecActionType.d.ts +0 -3
- package/lib/esm/actions/openApiSpec/OpenApiSpecActionType.js +0 -5
- package/lib/esm/actions/openApiSpec/OpenApiSpecActionType.js.map +0 -1
- package/lib/esm/actions/openApiSpec/askGetOpenApiSpec.d.ts +0 -2
- package/lib/esm/actions/openApiSpec/askGetOpenApiSpec.js +0 -6
- package/lib/esm/actions/openApiSpec/askGetOpenApiSpec.js.map +0 -1
- package/lib/esm/actions/openApiSpec/index.d.ts +0 -2
- package/lib/esm/actions/openApiSpec/index.js +0 -3
- package/lib/esm/actions/openApiSpec/index.js.map +0 -1
- package/lib/esm/config/settings/openApi.d.ts +0 -5
- package/lib/esm/config/settings/openApi.js +0 -9
- package/lib/esm/config/settings/openApi.js.map +0 -1
- package/lib/esm/stories/askGetDomainRoot.d.ts +0 -2
- package/lib/esm/stories/askGetDomainRoot.js +0 -18
- package/lib/esm/stories/askGetDomainRoot.js.map +0 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { JsonSchema } from '../config/types/JsonSchema';
|
|
2
|
+
export type OpenApiParameter = {
|
|
3
|
+
name: string;
|
|
4
|
+
in: 'path' | 'query';
|
|
5
|
+
required: boolean;
|
|
6
|
+
schema: JsonSchema;
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
export type OpenApiMediaType = {
|
|
10
|
+
schema: JsonSchema;
|
|
11
|
+
};
|
|
12
|
+
export type OpenApiRequestBody = {
|
|
13
|
+
required: boolean;
|
|
14
|
+
content: {
|
|
15
|
+
'application/json': OpenApiMediaType;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export type OpenApiResponse = {
|
|
19
|
+
description: string;
|
|
20
|
+
content?: {
|
|
21
|
+
'application/json': OpenApiMediaType;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type OpenApiSecurityRequirement = Record<string, string[]>;
|
|
25
|
+
export type OpenApiOperation = {
|
|
26
|
+
operationId: string;
|
|
27
|
+
summary?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
parameters?: OpenApiParameter[];
|
|
31
|
+
requestBody?: OpenApiRequestBody;
|
|
32
|
+
responses: Record<string, OpenApiResponse>;
|
|
33
|
+
security?: OpenApiSecurityRequirement[];
|
|
34
|
+
};
|
|
35
|
+
export type OpenApiPathItem = Partial<Record<'get' | 'post' | 'put' | 'patch' | 'delete' | 'options' | 'head', OpenApiOperation>>;
|
|
36
|
+
export type OpenApiSecurityScheme = {
|
|
37
|
+
type: 'http';
|
|
38
|
+
scheme: 'bearer';
|
|
39
|
+
bearerFormat: 'JWT';
|
|
40
|
+
} | {
|
|
41
|
+
type: 'apiKey';
|
|
42
|
+
in: 'header';
|
|
43
|
+
name: string;
|
|
44
|
+
};
|
|
45
|
+
export type OpenApiInfo = {
|
|
46
|
+
title: string;
|
|
47
|
+
version: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
};
|
|
50
|
+
export type OpenApiDocument = {
|
|
51
|
+
openapi: '3.1.0';
|
|
52
|
+
info: OpenApiInfo;
|
|
53
|
+
servers: {
|
|
54
|
+
url: string;
|
|
55
|
+
}[];
|
|
56
|
+
paths: Record<string, OpenApiPathItem>;
|
|
57
|
+
components: {
|
|
58
|
+
securitySchemes: Record<string, OpenApiSecurityScheme>;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiDocument.js","sourceRoot":"","sources":["../../../src/types/OpenApiDocument.ts"],"names":[],"mappings":"","sourcesContent":["import { JsonSchema } from '../config/types/JsonSchema';\n\n// The slice of OpenAPI 3.1 this framework emits. Anything the generator does not\n// produce (callbacks, links, examples) is deliberately absent rather than typed loosely.\nexport type OpenApiParameter = {\n name: string;\n in: 'path' | 'query';\n required: boolean;\n schema: JsonSchema;\n description?: string;\n};\n\nexport type OpenApiMediaType = { schema: JsonSchema };\n\nexport type OpenApiRequestBody = {\n required: boolean;\n content: { 'application/json': OpenApiMediaType };\n};\n\nexport type OpenApiResponse = {\n description: string;\n content?: { 'application/json': OpenApiMediaType };\n};\n\nexport type OpenApiSecurityRequirement = Record<string, string[]>;\n\nexport type OpenApiOperation = {\n operationId: string;\n summary?: string;\n description?: string;\n tags?: string[];\n parameters?: OpenApiParameter[];\n requestBody?: OpenApiRequestBody;\n responses: Record<string, OpenApiResponse>;\n security?: OpenApiSecurityRequirement[];\n};\n\nexport type OpenApiPathItem = Partial<Record<'get' | 'post' | 'put' | 'patch' | 'delete' | 'options' | 'head', OpenApiOperation>>;\n\nexport type OpenApiSecurityScheme = { type: 'http'; scheme: 'bearer'; bearerFormat: 'JWT' } | { type: 'apiKey'; in: 'header'; name: string };\n\nexport type OpenApiInfo = {\n title: string;\n version: string;\n description?: string;\n};\n\nexport type OpenApiDocument = {\n openapi: '3.1.0';\n info: OpenApiInfo;\n servers: { url: string }[];\n paths: Record<string, OpenApiPathItem>;\n components: {\n securitySchemes: Record<string, OpenApiSecurityScheme>;\n };\n};\n"]}
|
package/lib/esm/types/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './constants';
|
|
|
3
3
|
export * from './EmailSendEvent';
|
|
4
4
|
export * from './ExecuteServiceFunctionEvent';
|
|
5
5
|
export * from './HTTPEvent';
|
|
6
|
+
export * from './OpenApiDocument';
|
|
6
7
|
export * from './SEOEvent';
|
|
7
8
|
export * from './StorageDriveEvent';
|
|
8
9
|
export * from './WebsocketEvent';
|
package/lib/esm/types/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from './constants';
|
|
|
3
3
|
export * from './EmailSendEvent';
|
|
4
4
|
export * from './ExecuteServiceFunctionEvent';
|
|
5
5
|
export * from './HTTPEvent';
|
|
6
|
+
export * from './OpenApiDocument';
|
|
6
7
|
export * from './SEOEvent';
|
|
7
8
|
export * from './StorageDriveEvent';
|
|
8
9
|
export * from './WebsocketEvent';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC","sourcesContent":["export * from './CloudflareDnsDeployEvent';\nexport * from './constants';\nexport * from './EmailSendEvent';\nexport * from './ExecuteServiceFunctionEvent';\nexport * from './HTTPEvent';\nexport * from './SEOEvent';\nexport * from './StorageDriveEvent';\nexport * from './WebsocketEvent';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC","sourcesContent":["export * from './CloudflareDnsDeployEvent';\nexport * from './constants';\nexport * from './EmailSendEvent';\nexport * from './ExecuteServiceFunctionEvent';\nexport * from './HTTPEvent';\nexport * from './OpenApiDocument';\nexport * from './SEOEvent';\nexport * from './StorageDriveEvent';\nexport * from './WebsocketEvent';\n"]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { AskResponse, QPQConfig } from 'quidproquo-core';
|
|
2
|
-
import { RouteOptions
|
|
2
|
+
import { RouteOptions } from '../config/settings/route';
|
|
3
|
+
import { DomainResolver } from '../domain/types/DomainResolver';
|
|
3
4
|
import { SeoEvent } from '../types';
|
|
4
5
|
import { HTTPEvent, HttpEventHeaders } from '../types/HTTPEvent';
|
|
5
6
|
export declare const getHeaderValue: (header: string, headers: HttpEventHeaders) => string | null;
|
|
6
7
|
export declare function askReadRequiredHeader(event: HTTPEvent, requiredHeader: string): AskResponse<string>;
|
|
7
8
|
export declare function askReadRequiredHeaders(event: HTTPEvent, requiredHeaders: string[]): AskResponse<string[]>;
|
|
8
9
|
export declare const getAccessTokenFromHeaders: (headers: HttpEventHeaders) => string | undefined;
|
|
9
|
-
|
|
10
|
-
export declare const getAllowedOrigins: (qpqConfig: QPQConfig, route: RouteOptions) => string[];
|
|
11
|
-
export declare const getCorsHeaders: (qpqConfig: QPQConfig, route: RouteOptions, reqHeaders: HttpEventHeaders) => HttpEventHeaders;
|
|
10
|
+
/** Site roots first (primary leads, so it is the fallback origin), then default and route entries, all lowercased. */
|
|
11
|
+
export declare const getAllowedOrigins: (qpqConfig: QPQConfig, route: RouteOptions, resolver?: DomainResolver) => string[];
|
|
12
|
+
export declare const getCorsHeaders: (qpqConfig: QPQConfig, route: RouteOptions, reqHeaders: HttpEventHeaders, resolver?: DomainResolver) => HttpEventHeaders;
|
|
12
13
|
export declare const isBot: (event: HTTPEvent | SeoEvent<any>) => boolean;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { askMap, askThrowError, ErrorTypeEnum } from 'quidproquo-core';
|
|
2
|
+
import { resolveHosts } from '../domain/logic/host/resolveHosts';
|
|
3
|
+
import { resolveOrigins } from '../domain/logic/origin/resolveOrigins';
|
|
2
4
|
import { qpqHeaderIsBot } from '../types';
|
|
3
|
-
import {
|
|
5
|
+
import { getDefaultRouteSettings } from './qpqConfigAccessorsUtils';
|
|
4
6
|
export const getHeaderValue = (header, headers) => {
|
|
5
7
|
const headerAsLower = header.toLowerCase();
|
|
6
8
|
const realHeaderKey = Object.keys(headers).find((k) => k.toLowerCase() === headerAsLower);
|
|
@@ -26,37 +28,23 @@ export const getAccessTokenFromHeaders = (headers) => {
|
|
|
26
28
|
const [authType, authToken] = authorizationHeader.split(' ');
|
|
27
29
|
return authToken;
|
|
28
30
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const protocol = allowedOrigin.protocol || 'https';
|
|
36
|
-
if (allowedOrigin.service) {
|
|
37
|
-
return `${protocol}://${allowedOrigin.api}.${allowedOrigin.service}.${domain}`;
|
|
38
|
-
}
|
|
39
|
-
return `${protocol}://${allowedOrigin.api}.${domain}`;
|
|
40
|
-
};
|
|
41
|
-
export const getAllowedOrigins = (qpqConfig, route) => {
|
|
42
|
-
const baseDomain = getBaseDomainName(qpqConfig);
|
|
43
|
-
// Root domain
|
|
44
|
-
const rootDomain = `https://${baseDomain}`;
|
|
45
|
-
// generic settings
|
|
46
|
-
const defaultRouteSettings = getDefaultRouteSettings(qpqConfig);
|
|
47
|
-
const defaultAllowedOrigins = defaultRouteSettings.reduce((acc, cur) => [...acc, ...(cur.routeOptions.allowedOrigins || []).map((ao) => convertContentSecurityPolicyEntryToString(baseDomain, ao))], []);
|
|
48
|
-
// Route specific
|
|
49
|
-
const routeAllowedOrigins = (route.allowedOrigins || []).map((ao) => convertContentSecurityPolicyEntryToString(baseDomain, ao));
|
|
50
|
-
// Return the allowed origins
|
|
51
|
-
const allAllowedOrigins = [rootDomain, ...defaultAllowedOrigins, ...routeAllowedOrigins].map((o) => o.toLowerCase());
|
|
52
|
-
return allAllowedOrigins;
|
|
31
|
+
/** Site roots first (primary leads, so it is the fallback origin), then default and route entries, all lowercased. */
|
|
32
|
+
export const getAllowedOrigins = (qpqConfig, route, resolver) => {
|
|
33
|
+
const rootOrigins = resolveHosts(qpqConfig, {}, resolver).map((host) => `https://${host}`);
|
|
34
|
+
const defaultAllowedOrigins = getDefaultRouteSettings(qpqConfig).flatMap((setting) => (setting.routeOptions.allowedOrigins || []).flatMap((entry) => resolveOrigins(qpqConfig, entry, resolver)));
|
|
35
|
+
const routeAllowedOrigins = (route.allowedOrigins || []).flatMap((entry) => resolveOrigins(qpqConfig, entry, resolver));
|
|
36
|
+
return [...rootOrigins, ...defaultAllowedOrigins, ...routeAllowedOrigins].map((origin) => origin.toLowerCase());
|
|
53
37
|
};
|
|
54
|
-
export const getCorsHeaders = (qpqConfig, route, reqHeaders) => {
|
|
38
|
+
export const getCorsHeaders = (qpqConfig, route, reqHeaders, resolver) => {
|
|
55
39
|
const origin = getHeaderValue('origin', reqHeaders) || '';
|
|
56
|
-
const allowedOrigins = getAllowedOrigins(qpqConfig, route);
|
|
40
|
+
const allowedOrigins = getAllowedOrigins(qpqConfig, route, resolver);
|
|
57
41
|
const allowCredentials = !!route.routeAuthSettings?.userDirectoryName;
|
|
58
42
|
// If we have an auth endpoint, then we don't let wildcard origins access the API for security reasons
|
|
59
|
-
|
|
43
|
+
// A service with no domain declares nothing browser-facing, so an open origin is the
|
|
44
|
+
// only sensible fallback (the storage-drive cors default makes the same call).
|
|
45
|
+
const allowOrigin = (!allowCredentials ? allowedOrigins.find((ao) => origin === ao || ao === '*') : allowedOrigins.find((ao) => origin === ao)) ||
|
|
46
|
+
allowedOrigins[0] ||
|
|
47
|
+
'*';
|
|
60
48
|
// Reflect exactly what the preflight asks for instead of a blanket '*'. A
|
|
61
49
|
// literal '*' is invalid once credentials are allowed (browsers reject it),
|
|
62
50
|
// so echoing the requested headers/method keeps authenticated routes working
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headerUtils.js","sourceRoot":"","sources":["../../../src/utils/headerUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAe,aAAa,EAAE,aAAa,EAAa,MAAM,iBAAiB,CAAC;AAG/F,OAAO,EAAE,cAAc,EAAY,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"headerUtils.js","sourceRoot":"","sources":["../../../src/utils/headerUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import { askMap, AskResponse, askThrowError, ErrorTypeEnum, QPQConfig } from 'quidproquo-core';\n\nimport { RouteOptions } from '../config/settings/route';\nimport { resolveHosts } from '../domain/logic/host/resolveHosts';\nimport { resolveOrigins } from '../domain/logic/origin/resolveOrigins';\nimport { DomainResolver } from '../domain/types/DomainResolver';\nimport { qpqHeaderIsBot, SeoEvent } from '../types';\nimport { HTTPEvent, HttpEventHeaders } from '../types/HTTPEvent';\nimport { getDefaultRouteSettings } from './qpqConfigAccessorsUtils';\n\nexport const getHeaderValue = (header: string, headers: HttpEventHeaders): string | null => {\n const headerAsLower = header.toLowerCase();\n const realHeaderKey = Object.keys(headers).find((k) => k.toLowerCase() === headerAsLower);\n\n if (!realHeaderKey) {\n return null;\n }\n\n return headers[realHeaderKey] || null;\n};\n\nexport function* askReadRequiredHeader(event: HTTPEvent, requiredHeader: string): AskResponse<string> {\n const header = getHeaderValue(requiredHeader, event.headers);\n if (!header) {\n return yield* askThrowError(ErrorTypeEnum.NotFound, `Header ${requiredHeader} not found`);\n }\n\n return header;\n}\n\nexport function* askReadRequiredHeaders(event: HTTPEvent, requiredHeaders: string[]): AskResponse<string[]> {\n return yield* askMap(requiredHeaders, function* (header: string) {\n return yield* askReadRequiredHeader(event, header);\n });\n}\n\nexport const getAccessTokenFromHeaders = (headers: HttpEventHeaders): string | undefined => {\n const authorizationHeader = getHeaderValue('authorization', headers) || '';\n const [authType, authToken] = authorizationHeader.split(' ');\n\n return authToken;\n};\n\n/** Site roots first (primary leads, so it is the fallback origin), then default and route entries, all lowercased. */\nexport const getAllowedOrigins = (qpqConfig: QPQConfig, route: RouteOptions, resolver?: DomainResolver): string[] => {\n const rootOrigins = resolveHosts(qpqConfig, {}, resolver).map((host) => `https://${host}`);\n\n const defaultAllowedOrigins = getDefaultRouteSettings(qpqConfig).flatMap((setting) =>\n (setting.routeOptions.allowedOrigins || []).flatMap((entry) => resolveOrigins(qpqConfig, entry, resolver)),\n );\n\n const routeAllowedOrigins = (route.allowedOrigins || []).flatMap((entry) => resolveOrigins(qpqConfig, entry, resolver));\n\n return [...rootOrigins, ...defaultAllowedOrigins, ...routeAllowedOrigins].map((origin) => origin.toLowerCase());\n};\n\nexport const getCorsHeaders = (\n qpqConfig: QPQConfig,\n route: RouteOptions,\n reqHeaders: HttpEventHeaders,\n resolver?: DomainResolver,\n): HttpEventHeaders => {\n const origin = getHeaderValue('origin', reqHeaders) || '';\n\n const allowedOrigins = getAllowedOrigins(qpqConfig, route, resolver);\n\n const allowCredentials = !!route.routeAuthSettings?.userDirectoryName;\n\n // If we have an auth endpoint, then we don't let wildcard origins access the API for security reasons\n // A service with no domain declares nothing browser-facing, so an open origin is the\n // only sensible fallback (the storage-drive cors default makes the same call).\n const allowOrigin =\n (!allowCredentials ? allowedOrigins.find((ao) => origin === ao || ao === '*') : allowedOrigins.find((ao) => origin === ao)) ||\n allowedOrigins[0] ||\n '*';\n\n // Reflect exactly what the preflight asks for instead of a blanket '*'. A\n // literal '*' is invalid once credentials are allowed (browsers reject it),\n // so echoing the requested headers/method keeps authenticated routes working\n // while staying scoped to the real request. The security boundary is the\n // origin check above; these two just describe what that trusted origin may send.\n const requestedHeaders = getHeaderValue('access-control-request-headers', reqHeaders);\n const requestedMethod = getHeaderValue('access-control-request-method', reqHeaders);\n\n return {\n 'Access-Control-Allow-Headers': requestedHeaders || 'Authorization, Content-Type',\n 'Access-Control-Allow-Methods': requestedMethod || 'GET, POST, PUT, PATCH, DELETE, OPTIONS',\n 'Access-Control-Allow-Origin': allowOrigin,\n 'Access-Control-Allow-Credentials': `${allowCredentials}`,\n Vary: 'Origin, Access-Control-Request-Headers, Access-Control-Request-Method',\n };\n};\n\nexport const isBot = (event: HTTPEvent | SeoEvent<any>): boolean => {\n return event.headers[qpqHeaderIsBot] === 'true';\n};\n"]}
|
package/lib/esm/utils/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
export * from '../configUtils';
|
|
2
|
+
export * from '../domain/logic';
|
|
1
3
|
export * from './headerUtils';
|
|
2
4
|
export * from './httpEventUtils';
|
|
3
5
|
export * from './jwtUtils';
|
|
4
6
|
export * from './mergeRouteUtils';
|
|
5
7
|
export * from './networkRequestUtils';
|
|
8
|
+
export * from './openApi';
|
|
6
9
|
export * from './pathUtils';
|
|
7
10
|
export * from './preformNetworkRequest';
|
|
8
11
|
export * from './qpqConfigAccessorsUtils';
|
package/lib/esm/utils/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
export * from '../configUtils';
|
|
2
|
+
export * from '../domain/logic';
|
|
1
3
|
export * from './headerUtils';
|
|
2
4
|
export * from './httpEventUtils';
|
|
3
5
|
export * from './jwtUtils';
|
|
4
6
|
export * from './mergeRouteUtils';
|
|
5
7
|
export * from './networkRequestUtils';
|
|
8
|
+
export * from './openApi';
|
|
6
9
|
export * from './pathUtils';
|
|
7
10
|
export * from './preformNetworkRequest';
|
|
8
11
|
export * from './qpqConfigAccessorsUtils';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC","sourcesContent":["export * from './headerUtils';\nexport * from './httpEventUtils';\nexport * from './jwtUtils';\nexport * from './mergeRouteUtils';\nexport * from './networkRequestUtils';\nexport * from './pathUtils';\nexport * from './preformNetworkRequest';\nexport * from './qpqConfigAccessorsUtils';\nexport * from './urlUtils';\nexport * from './websocketEventUtils';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC","sourcesContent":["export * from '../configUtils';\nexport * from '../domain/logic';\nexport * from './headerUtils';\nexport * from './httpEventUtils';\nexport * from './jwtUtils';\nexport * from './mergeRouteUtils';\nexport * from './networkRequestUtils';\nexport * from './openApi';\nexport * from './pathUtils';\nexport * from './preformNetworkRequest';\nexport * from './qpqConfigAccessorsUtils';\nexport * from './urlUtils';\nexport * from './websocketEventUtils';\n"]}
|
|
@@ -10,6 +10,8 @@ export const mergeRouteOptions = (routeOptionsA, routeOptionsB) => {
|
|
|
10
10
|
return {
|
|
11
11
|
allowedOrigins: [...new Set([...(routeOptionsB.allowedOrigins || []), ...(routeOptionsA.allowedOrigins || [])])],
|
|
12
12
|
routeAuthSettings: mergeRouteAuthSettings(routeOptionsA.routeAuthSettings, routeOptionsB.routeAuthSettings),
|
|
13
|
+
// Schemas describe one route, they are never shared defaults, so the more specific side wins outright
|
|
14
|
+
schema: routeOptionsB.schema ?? routeOptionsA.schema,
|
|
13
15
|
};
|
|
14
16
|
};
|
|
15
17
|
export const mergeAllRouteOptions = (activeApi, routeConfig, qpqConfig) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeRouteUtils.js","sourceRoot":"","sources":["../../../src/utils/mergeRouteUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,kBAAsC,EAAE,kBAAsC,EAAqB,EAAE;IAC1I,OAAO;QACL,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,IAAI,kBAAkB,EAAE,iBAAiB;QACjG,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,kBAAkB,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpG,OAAO,EAAE,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,kBAAkB,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAC9F,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CACxB,GAAG,CAAC,SAAS,CACX,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC,eAAe,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW,CAC3I,KAAK,KAAK,CACd;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,aAA2B,EAAE,aAA2B,EAAgB,EAAE;IAC1G,OAAO;QACL,cAAc,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChH,iBAAiB,EAAE,sBAAsB,CAAC,aAAa,CAAC,iBAAiB,EAAE,aAAa,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"mergeRouteUtils.js","sourceRoot":"","sources":["../../../src/utils/mergeRouteUtils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,kBAAsC,EAAE,kBAAsC,EAAqB,EAAE;IAC1I,OAAO;QACL,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,IAAI,kBAAkB,EAAE,iBAAiB;QACjG,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,kBAAkB,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpG,OAAO,EAAE,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,kBAAkB,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAC9F,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CACxB,GAAG,CAAC,SAAS,CACX,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC,eAAe,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW,CAC3I,KAAK,KAAK,CACd;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,aAA2B,EAAE,aAA2B,EAAgB,EAAE;IAC1G,OAAO;QACL,cAAc,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,cAAc,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAChH,iBAAiB,EAAE,sBAAsB,CAAC,aAAa,CAAC,iBAAiB,EAAE,aAAa,CAAC,iBAAiB,CAAC;QAE3G,sGAAsG;QACtG,MAAM,EAAE,aAAa,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM;KACrD,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAiB,EAAE,WAA2C,EAAE,SAAoB,EAAgB,EAAE;IACzI,sEAAsE;IACtE,YAAY;IACZ,MAAM,cAAc,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACrF,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC;IAEzC,OAAO,CAAC,GAAG,cAAc,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAkB,CAAC,CAAC;AACjH,CAAC,CAAC","sourcesContent":["import { QPQConfig } from 'quidproquo-core';\n\nimport { RouteAuthSettings, RouteQPQWebServerConfigSetting } from '../config/settings/route';\nimport { RouteOptions } from '../config/settings/route';\nimport { getDefaultRouteSettings } from './qpqConfigAccessorsUtils';\n\nexport const mergeRouteAuthSettings = (routeAuthSettingsA?: RouteAuthSettings, routeAuthSettingsB?: RouteAuthSettings): RouteAuthSettings => {\n return {\n userDirectoryName: routeAuthSettingsB?.userDirectoryName || routeAuthSettingsA?.userDirectoryName,\n scopes: [...new Set([...(routeAuthSettingsB?.scopes || []), ...(routeAuthSettingsA?.scopes || [])])],\n\n apiKeys: [...(routeAuthSettingsB?.apiKeys || []), ...(routeAuthSettingsA?.apiKeys || [])].filter(\n (apiKeyRef, index, arr) =>\n arr.findIndex(\n (item) => item.name === apiKeyRef.name && item.applicationName === apiKeyRef.applicationName && item.serviceName === apiKeyRef.serviceName,\n ) === index,\n ),\n };\n};\n\nexport const mergeRouteOptions = (routeOptionsA: RouteOptions, routeOptionsB: RouteOptions): RouteOptions => {\n return {\n allowedOrigins: [...new Set([...(routeOptionsB.allowedOrigins || []), ...(routeOptionsA.allowedOrigins || [])])],\n routeAuthSettings: mergeRouteAuthSettings(routeOptionsA.routeAuthSettings, routeOptionsB.routeAuthSettings),\n\n // Schemas describe one route, they are never shared defaults, so the more specific side wins outright\n schema: routeOptionsB.schema ?? routeOptionsA.schema,\n };\n};\n\nexport const mergeAllRouteOptions = (activeApi: string, routeConfig: RouteQPQWebServerConfigSetting, qpqConfig: QPQConfig): RouteOptions => {\n // TODO: This needs to filter active route on the current route Config\n // activeApi\n const defaultOptions = getDefaultRouteSettings(qpqConfig).map((o) => o.routeOptions);\n const routeOptions = routeConfig.options;\n\n return [...defaultOptions, routeOptions].reduce((acc, opt) => mergeRouteOptions(acc, opt), {} as RouteOptions);\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiDocumentOptions.js","sourceRoot":"","sources":["../../../../src/utils/openApi/OpenApiDocumentOptions.ts"],"names":[],"mappings":"","sourcesContent":["import { OpenApiInfo } from '../../types/OpenApiDocument';\n\n// The parts of the document that are prose rather than derived from the routes.\n// Every field falls back to something sensible taken from the service config.\nexport type OpenApiDocumentOptions = Partial<OpenApiInfo>;\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { QPQConfig } from 'quidproquo-core';
|
|
2
|
+
import { DomainResolver } from '../../domain/types/DomainResolver';
|
|
3
|
+
import { OpenApiDocument } from '../../types/OpenApiDocument';
|
|
4
|
+
import { OpenApiDocumentOptions } from './OpenApiDocumentOptions';
|
|
5
|
+
export declare const buildOpenApiDocument: (qpqConfig: QPQConfig, options?: OpenApiDocumentOptions, resolver?: DomainResolver) => OpenApiDocument;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { qpqCoreUtils } from 'quidproquo-core';
|
|
2
|
+
import { resolveHosts } from '../../domain/logic/host/resolveHosts';
|
|
3
|
+
import { mergeAllRouteOptions } from '../mergeRouteUtils';
|
|
4
|
+
import { getAllRoutes, getApiConfigs } from '../qpqConfigAccessorsUtils';
|
|
5
|
+
import { buildOpenApiOperation } from './buildOpenApiOperation';
|
|
6
|
+
import { openApiSecuritySchemes } from './buildOpenApiSecurity';
|
|
7
|
+
// Every live api on every root is a server the operations can be called on. Deployed, an
|
|
8
|
+
// api domain is shared by every service in the application and each service is mounted
|
|
9
|
+
// under its module name (the api gateway base path mapping), so the url carries that path.
|
|
10
|
+
// A service with no domain (nothing browser-facing, local only) lists none.
|
|
11
|
+
const buildServers = (qpqConfig, resolver) => {
|
|
12
|
+
const serviceName = qpqCoreUtils.getApplicationModuleName(qpqConfig);
|
|
13
|
+
return getApiConfigs(qpqConfig)
|
|
14
|
+
.filter((api) => !api.deprecated)
|
|
15
|
+
.flatMap((api) => resolveHosts(qpqConfig, { subdomain: api.apiSubdomain }, resolver).map((host) => ({ url: `https://${host}/${serviceName}` })));
|
|
16
|
+
};
|
|
17
|
+
// Only schemes some operation actually references make it into components, so a
|
|
18
|
+
// service with no auth publishes no dangling security definitions.
|
|
19
|
+
const buildSecuritySchemes = (paths) => {
|
|
20
|
+
const used = new Set(Object.values(paths)
|
|
21
|
+
.flatMap((pathItem) => Object.values(pathItem))
|
|
22
|
+
.flatMap((operation) => operation.security ?? [])
|
|
23
|
+
.flatMap((requirement) => Object.keys(requirement)));
|
|
24
|
+
return Object.fromEntries(Object.entries(openApiSecuritySchemes).filter(([name]) => used.has(name)));
|
|
25
|
+
};
|
|
26
|
+
// Walk every route in the config and describe it. Routes are plain data, so this
|
|
27
|
+
// runs anywhere the config does: at deploy time, in a processor, or in a test.
|
|
28
|
+
export const buildOpenApiDocument = (qpqConfig, options = {}, resolver) => {
|
|
29
|
+
const paths = {};
|
|
30
|
+
for (const route of getAllRoutes(qpqConfig)) {
|
|
31
|
+
const routeOptions = mergeAllRouteOptions('', route, qpqConfig);
|
|
32
|
+
if (routeOptions.schema?.hidden) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const verb = route.method.toLowerCase();
|
|
36
|
+
paths[route.path] = { ...paths[route.path], [verb]: buildOpenApiOperation(route, routeOptions) };
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
openapi: '3.1.0',
|
|
40
|
+
info: {
|
|
41
|
+
title: options.title ?? `${qpqCoreUtils.getApplicationName(qpqConfig)} ${qpqCoreUtils.getApplicationModuleName(qpqConfig)}`,
|
|
42
|
+
version: options.version ?? '1.0.0',
|
|
43
|
+
description: options.description,
|
|
44
|
+
},
|
|
45
|
+
servers: buildServers(qpqConfig, resolver),
|
|
46
|
+
paths,
|
|
47
|
+
components: { securitySchemes: buildSecuritySchemes(paths) },
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=buildOpenApiDocument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOpenApiDocument.js","sourceRoot":"","sources":["../../../../src/utils/openApi/buildOpenApiDocument.ts"],"names":[],"mappings":"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","sourcesContent":["import { QPQConfig, qpqCoreUtils } from 'quidproquo-core';\n\nimport { resolveHosts } from '../../domain/logic/host/resolveHosts';\nimport { DomainResolver } from '../../domain/types/DomainResolver';\nimport { OpenApiDocument, OpenApiPathItem, OpenApiSecurityScheme } from '../../types/OpenApiDocument';\nimport { mergeAllRouteOptions } from '../mergeRouteUtils';\nimport { getAllRoutes, getApiConfigs } from '../qpqConfigAccessorsUtils';\nimport { buildOpenApiOperation } from './buildOpenApiOperation';\nimport { openApiSecuritySchemes } from './buildOpenApiSecurity';\nimport { OpenApiDocumentOptions } from './OpenApiDocumentOptions';\n\ntype HttpVerb = keyof OpenApiPathItem;\n\n// Every live api on every root is a server the operations can be called on. Deployed, an\n// api domain is shared by every service in the application and each service is mounted\n// under its module name (the api gateway base path mapping), so the url carries that path.\n// A service with no domain (nothing browser-facing, local only) lists none.\nconst buildServers = (qpqConfig: QPQConfig, resolver?: DomainResolver): { url: string }[] => {\n const serviceName = qpqCoreUtils.getApplicationModuleName(qpqConfig);\n\n return getApiConfigs(qpqConfig)\n .filter((api) => !api.deprecated)\n .flatMap((api) => resolveHosts(qpqConfig, { subdomain: api.apiSubdomain }, resolver).map((host) => ({ url: `https://${host}/${serviceName}` })));\n};\n\n// Only schemes some operation actually references make it into components, so a\n// service with no auth publishes no dangling security definitions.\nconst buildSecuritySchemes = (paths: Record<string, OpenApiPathItem>): Record<string, OpenApiSecurityScheme> => {\n const used = new Set(\n Object.values(paths)\n .flatMap((pathItem) => Object.values(pathItem))\n .flatMap((operation) => operation.security ?? [])\n .flatMap((requirement) => Object.keys(requirement)),\n );\n\n return Object.fromEntries(Object.entries(openApiSecuritySchemes).filter(([name]) => used.has(name)));\n};\n\n// Walk every route in the config and describe it. Routes are plain data, so this\n// runs anywhere the config does: at deploy time, in a processor, or in a test.\nexport const buildOpenApiDocument = (qpqConfig: QPQConfig, options: OpenApiDocumentOptions = {}, resolver?: DomainResolver): OpenApiDocument => {\n const paths: Record<string, OpenApiPathItem> = {};\n\n for (const route of getAllRoutes(qpqConfig)) {\n const routeOptions = mergeAllRouteOptions('', route, qpqConfig);\n if (routeOptions.schema?.hidden) {\n continue;\n }\n\n const verb = route.method.toLowerCase() as HttpVerb;\n paths[route.path] = { ...paths[route.path], [verb]: buildOpenApiOperation(route, routeOptions) };\n }\n\n return {\n openapi: '3.1.0',\n info: {\n title: options.title ?? `${qpqCoreUtils.getApplicationName(qpqConfig)} ${qpqCoreUtils.getApplicationModuleName(qpqConfig)}`,\n version: options.version ?? '1.0.0',\n description: options.description,\n },\n servers: buildServers(qpqConfig, resolver),\n paths,\n components: { securitySchemes: buildSecuritySchemes(paths) },\n };\n};\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { RouteOptions } from '../../config/settings/route';
|
|
2
|
+
import { RouteQPQWebServerConfigSetting } from '../../config/settings/route';
|
|
3
|
+
import { OpenApiOperation } from '../../types/OpenApiDocument';
|
|
4
|
+
export declare const buildOpenApiOperation: (route: RouteQPQWebServerConfigSetting, options: RouteOptions) => OpenApiOperation;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { buildOpenApiPathParameters } from './buildOpenApiPathParameters';
|
|
2
|
+
import { buildOpenApiQueryParameters } from './buildOpenApiQueryParameters';
|
|
3
|
+
import { buildOpenApiSecurity } from './buildOpenApiSecurity';
|
|
4
|
+
// `get_v1_widgets_id` style: stable across deploys and unique per method+path,
|
|
5
|
+
// which is all client generators need from it.
|
|
6
|
+
const toOperationId = (method, path) => [method.toLowerCase(), ...path.replace(/[{}]/g, '').split('/').filter(Boolean)].join('_');
|
|
7
|
+
const buildResponses = (options) => {
|
|
8
|
+
const { schema, routeAuthSettings } = options;
|
|
9
|
+
const responses = {
|
|
10
|
+
'200': schema?.responseJsonSchema
|
|
11
|
+
? { description: 'Success', content: { 'application/json': { schema: schema.responseJsonSchema } } }
|
|
12
|
+
: { description: 'Success' },
|
|
13
|
+
};
|
|
14
|
+
if (routeAuthSettings?.userDirectoryName || routeAuthSettings?.apiKeys?.length) {
|
|
15
|
+
responses['401'] = { description: 'Missing or invalid credentials' };
|
|
16
|
+
}
|
|
17
|
+
// Only routes that validate input can reject it; a plain route has no 422 path
|
|
18
|
+
if (schema?.bodyJsonSchema || schema?.queryJsonSchema) {
|
|
19
|
+
responses['422'] = { description: 'Request failed validation' };
|
|
20
|
+
}
|
|
21
|
+
return responses;
|
|
22
|
+
};
|
|
23
|
+
// One route becomes one operation. `options` is the route's options after the
|
|
24
|
+
// service defaults have been merged in, so auth requirements are the real ones.
|
|
25
|
+
export const buildOpenApiOperation = (route, options) => {
|
|
26
|
+
const { schema } = options;
|
|
27
|
+
const parameters = [...buildOpenApiPathParameters(route.path), ...buildOpenApiQueryParameters(schema?.queryJsonSchema)];
|
|
28
|
+
const security = buildOpenApiSecurity(options.routeAuthSettings);
|
|
29
|
+
return {
|
|
30
|
+
operationId: toOperationId(route.method, route.path),
|
|
31
|
+
summary: schema?.summary,
|
|
32
|
+
description: schema?.description,
|
|
33
|
+
tags: schema?.tags,
|
|
34
|
+
parameters: parameters.length ? parameters : undefined,
|
|
35
|
+
requestBody: schema?.bodyJsonSchema ? { required: true, content: { 'application/json': { schema: schema.bodyJsonSchema } } } : undefined,
|
|
36
|
+
responses: buildResponses(options),
|
|
37
|
+
security: security.length ? security : undefined,
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=buildOpenApiOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOpenApiOperation.js","sourceRoot":"","sources":["../../../../src/utils/openApi/buildOpenApiOperation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,+EAA+E;AAC/E,+CAA+C;AAC/C,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,IAAY,EAAU,EAAE,CAC7D,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE5F,MAAM,cAAc,GAAG,CAAC,OAAqB,EAAmC,EAAE;IAChF,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;IAE9C,MAAM,SAAS,GAAoC;QACjD,KAAK,EAAE,MAAM,EAAE,kBAAkB;YAC/B,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,kBAAkB,EAAE,EAAE,EAAE;YACpG,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE;KAC/B,CAAC;IAEF,IAAI,iBAAiB,EAAE,iBAAiB,IAAI,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAC/E,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;IACvE,CAAC;IAED,+EAA+E;IAC/E,IAAI,MAAM,EAAE,cAAc,IAAI,MAAM,EAAE,eAAe,EAAE,CAAC;QACtD,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;IAClE,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,8EAA8E;AAC9E,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAqC,EAAE,OAAqB,EAAoB,EAAE;IACtH,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,UAAU,GAAG,CAAC,GAAG,0BAA0B,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,2BAA2B,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;IACxH,MAAM,QAAQ,GAAG,oBAAoB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAEjE,OAAO;QACL,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;QACpD,OAAO,EAAE,MAAM,EAAE,OAAO;QACxB,WAAW,EAAE,MAAM,EAAE,WAAW;QAChC,IAAI,EAAE,MAAM,EAAE,IAAI;QAClB,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QACtD,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS;QACxI,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC;QAClC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;KACjD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { RouteOptions } from '../../config/settings/route';\nimport { RouteQPQWebServerConfigSetting } from '../../config/settings/route';\nimport { OpenApiOperation, OpenApiResponse } from '../../types/OpenApiDocument';\nimport { buildOpenApiPathParameters } from './buildOpenApiPathParameters';\nimport { buildOpenApiQueryParameters } from './buildOpenApiQueryParameters';\nimport { buildOpenApiSecurity } from './buildOpenApiSecurity';\n\n// `get_v1_widgets_id` style: stable across deploys and unique per method+path,\n// which is all client generators need from it.\nconst toOperationId = (method: string, path: string): string =>\n [method.toLowerCase(), ...path.replace(/[{}]/g, '').split('/').filter(Boolean)].join('_');\n\nconst buildResponses = (options: RouteOptions): Record<string, OpenApiResponse> => {\n const { schema, routeAuthSettings } = options;\n\n const responses: Record<string, OpenApiResponse> = {\n '200': schema?.responseJsonSchema\n ? { description: 'Success', content: { 'application/json': { schema: schema.responseJsonSchema } } }\n : { description: 'Success' },\n };\n\n if (routeAuthSettings?.userDirectoryName || routeAuthSettings?.apiKeys?.length) {\n responses['401'] = { description: 'Missing or invalid credentials' };\n }\n\n // Only routes that validate input can reject it; a plain route has no 422 path\n if (schema?.bodyJsonSchema || schema?.queryJsonSchema) {\n responses['422'] = { description: 'Request failed validation' };\n }\n\n return responses;\n};\n\n// One route becomes one operation. `options` is the route's options after the\n// service defaults have been merged in, so auth requirements are the real ones.\nexport const buildOpenApiOperation = (route: RouteQPQWebServerConfigSetting, options: RouteOptions): OpenApiOperation => {\n const { schema } = options;\n const parameters = [...buildOpenApiPathParameters(route.path), ...buildOpenApiQueryParameters(schema?.queryJsonSchema)];\n const security = buildOpenApiSecurity(options.routeAuthSettings);\n\n return {\n operationId: toOperationId(route.method, route.path),\n summary: schema?.summary,\n description: schema?.description,\n tags: schema?.tags,\n parameters: parameters.length ? parameters : undefined,\n requestBody: schema?.bodyJsonSchema ? { required: true, content: { 'application/json': { schema: schema.bodyJsonSchema } } } : undefined,\n responses: buildResponses(options),\n security: security.length ? security : undefined,\n };\n};\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Route paths already use OpenAPI's `{param}` template syntax, so the path itself
|
|
2
|
+
// is the source of truth for path parameters. They are always strings on the wire.
|
|
3
|
+
export const buildOpenApiPathParameters = (path) => [...path.matchAll(/\{([^}]+)\}/g)].map(([, name]) => ({
|
|
4
|
+
name,
|
|
5
|
+
in: 'path',
|
|
6
|
+
required: true,
|
|
7
|
+
schema: { type: 'string' },
|
|
8
|
+
}));
|
|
9
|
+
//# sourceMappingURL=buildOpenApiPathParameters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOpenApiPathParameters.js","sourceRoot":"","sources":["../../../../src/utils/openApi/buildOpenApiPathParameters.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,mFAAmF;AACnF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,IAAY,EAAsB,EAAE,CAC7E,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI;IACJ,EAAE,EAAE,MAAM;IACV,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;CAC3B,CAAC,CAAC,CAAC","sourcesContent":["import { OpenApiParameter } from '../../types/OpenApiDocument';\n\n// Route paths already use OpenAPI's `{param}` template syntax, so the path itself\n// is the source of truth for path parameters. They are always strings on the wire.\nexport const buildOpenApiPathParameters = (path: string): OpenApiParameter[] =>\n [...path.matchAll(/\\{([^}]+)\\}/g)].map(([, name]) => ({\n name,\n in: 'path',\n required: true,\n schema: { type: 'string' },\n }));\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const isJsonSchema = (value) => typeof value === 'object' && value !== null;
|
|
2
|
+
// A query schema is declared as one object schema, but OpenAPI wants one parameter
|
|
3
|
+
// per key. Only the top-level properties can be unpacked; a query schema that is
|
|
4
|
+
// not an object (or has none) contributes nothing rather than something wrong.
|
|
5
|
+
export const buildOpenApiQueryParameters = (querySchema) => {
|
|
6
|
+
const properties = querySchema?.properties;
|
|
7
|
+
if (!isJsonSchema(properties)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const required = Array.isArray(querySchema?.required) ? querySchema.required : [];
|
|
11
|
+
return Object.entries(properties)
|
|
12
|
+
.filter((entry) => isJsonSchema(entry[1]))
|
|
13
|
+
.map(([name, schema]) => ({
|
|
14
|
+
name,
|
|
15
|
+
in: 'query',
|
|
16
|
+
required: required.includes(name),
|
|
17
|
+
schema,
|
|
18
|
+
description: typeof schema.description === 'string' ? schema.description : undefined,
|
|
19
|
+
}));
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=buildOpenApiQueryParameters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOpenApiQueryParameters.js","sourceRoot":"","sources":["../../../../src/utils/openApi/buildOpenApiQueryParameters.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,CAAC,KAAc,EAAuB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE1G,mFAAmF;AACnF,iFAAiF;AACjF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,WAAwB,EAAsB,EAAE;IAC1F,MAAM,UAAU,GAAG,WAAW,EAAE,UAAU,CAAC;IAC3C,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAE,WAAW,CAAC,QAAqB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhG,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;SAC9B,MAAM,CAAC,CAAC,KAAK,EAAiC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;SACxE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,IAAI;QACJ,EAAE,EAAE,OAAO;QACX,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QACjC,MAAM;QACN,WAAW,EAAE,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;KACrF,CAAC,CAAC,CAAC;AACR,CAAC,CAAC","sourcesContent":["import { JsonSchema } from '../../config/types/JsonSchema';\nimport { OpenApiParameter } from '../../types/OpenApiDocument';\n\nconst isJsonSchema = (value: unknown): value is JsonSchema => typeof value === 'object' && value !== null;\n\n// A query schema is declared as one object schema, but OpenAPI wants one parameter\n// per key. Only the top-level properties can be unpacked; a query schema that is\n// not an object (or has none) contributes nothing rather than something wrong.\nexport const buildOpenApiQueryParameters = (querySchema?: JsonSchema): OpenApiParameter[] => {\n const properties = querySchema?.properties;\n if (!isJsonSchema(properties)) {\n return [];\n }\n\n const required = Array.isArray(querySchema?.required) ? (querySchema.required as string[]) : [];\n\n return Object.entries(properties)\n .filter((entry): entry is [string, JsonSchema] => isJsonSchema(entry[1]))\n .map(([name, schema]) => ({\n name,\n in: 'query',\n required: required.includes(name),\n schema,\n description: typeof schema.description === 'string' ? schema.description : undefined,\n }));\n};\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { RouteAuthSettings } from '../../config/settings/route';
|
|
2
|
+
import { OpenApiSecurityRequirement, OpenApiSecurityScheme } from '../../types/OpenApiDocument';
|
|
3
|
+
export declare const buildOpenApiSecurity: (routeAuthSettings?: RouteAuthSettings) => OpenApiSecurityRequirement[];
|
|
4
|
+
export declare const openApiSecuritySchemes: Record<string, OpenApiSecurityScheme>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OPEN_API_API_KEY_AUTH, OPEN_API_BEARER_AUTH } from './openApiSecuritySchemeNames';
|
|
2
|
+
// Mirrors what askValidateRouteAuth actually checks: a user directory means a JWT in
|
|
3
|
+
// the Authorization header, api keys mean the x-api-key header. Either satisfies the
|
|
4
|
+
// route, so they are listed as alternatives rather than both required.
|
|
5
|
+
export const buildOpenApiSecurity = (routeAuthSettings) => {
|
|
6
|
+
const requirements = [];
|
|
7
|
+
if (routeAuthSettings?.userDirectoryName) {
|
|
8
|
+
requirements.push({ [OPEN_API_BEARER_AUTH]: routeAuthSettings.scopes ?? [] });
|
|
9
|
+
}
|
|
10
|
+
if (routeAuthSettings?.apiKeys?.length) {
|
|
11
|
+
requirements.push({ [OPEN_API_API_KEY_AUTH]: [] });
|
|
12
|
+
}
|
|
13
|
+
return requirements;
|
|
14
|
+
};
|
|
15
|
+
export const openApiSecuritySchemes = {
|
|
16
|
+
[OPEN_API_BEARER_AUTH]: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },
|
|
17
|
+
[OPEN_API_API_KEY_AUTH]: { type: 'apiKey', in: 'header', name: 'x-api-key' },
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=buildOpenApiSecurity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildOpenApiSecurity.js","sourceRoot":"","sources":["../../../../src/utils/openApi/buildOpenApiSecurity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAE3F,qFAAqF;AACrF,qFAAqF;AACrF,uEAAuE;AACvE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,iBAAqC,EAAgC,EAAE;IAC1G,MAAM,YAAY,GAAiC,EAAE,CAAC;IAEtD,IAAI,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;QACzC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACvC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAA0C;IAC3E,CAAC,oBAAoB,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE;IAC/E,CAAC,qBAAqB,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE;CAC7E,CAAC","sourcesContent":["import { RouteAuthSettings } from '../../config/settings/route';\nimport { OpenApiSecurityRequirement, OpenApiSecurityScheme } from '../../types/OpenApiDocument';\nimport { OPEN_API_API_KEY_AUTH, OPEN_API_BEARER_AUTH } from './openApiSecuritySchemeNames';\n\n// Mirrors what askValidateRouteAuth actually checks: a user directory means a JWT in\n// the Authorization header, api keys mean the x-api-key header. Either satisfies the\n// route, so they are listed as alternatives rather than both required.\nexport const buildOpenApiSecurity = (routeAuthSettings?: RouteAuthSettings): OpenApiSecurityRequirement[] => {\n const requirements: OpenApiSecurityRequirement[] = [];\n\n if (routeAuthSettings?.userDirectoryName) {\n requirements.push({ [OPEN_API_BEARER_AUTH]: routeAuthSettings.scopes ?? [] });\n }\n\n if (routeAuthSettings?.apiKeys?.length) {\n requirements.push({ [OPEN_API_API_KEY_AUTH]: [] });\n }\n\n return requirements;\n};\n\nexport const openApiSecuritySchemes: Record<string, OpenApiSecurityScheme> = {\n [OPEN_API_BEARER_AUTH]: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' },\n [OPEN_API_API_KEY_AUTH]: { type: 'apiKey', in: 'header', name: 'x-api-key' },\n};\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './buildOpenApiDocument';
|
|
2
|
+
export * from './buildOpenApiOperation';
|
|
3
|
+
export * from './buildOpenApiPathParameters';
|
|
4
|
+
export * from './buildOpenApiQueryParameters';
|
|
5
|
+
export * from './buildOpenApiSecurity';
|
|
6
|
+
export * from './OpenApiDocumentOptions';
|
|
7
|
+
export * from './openApiSecuritySchemeNames';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './buildOpenApiDocument';
|
|
2
|
+
export * from './buildOpenApiOperation';
|
|
3
|
+
export * from './buildOpenApiPathParameters';
|
|
4
|
+
export * from './buildOpenApiQueryParameters';
|
|
5
|
+
export * from './buildOpenApiSecurity';
|
|
6
|
+
export * from './OpenApiDocumentOptions';
|
|
7
|
+
export * from './openApiSecuritySchemeNames';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/openApi/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC","sourcesContent":["export * from './buildOpenApiDocument';\nexport * from './buildOpenApiOperation';\nexport * from './buildOpenApiPathParameters';\nexport * from './buildOpenApiQueryParameters';\nexport * from './buildOpenApiSecurity';\nexport * from './OpenApiDocumentOptions';\nexport * from './openApiSecuritySchemeNames';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openApiSecuritySchemeNames.js","sourceRoot":"","sources":["../../../../src/utils/openApi/openApiSecuritySchemeNames.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AACjD,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC","sourcesContent":["// Keys under components.securitySchemes; operations reference them by name.\nexport const OPEN_API_BEARER_AUTH = 'bearerAuth';\nexport const OPEN_API_API_KEY_AUTH = 'apiKeyAuth';\n"]}
|