@webpieces/http-routing 0.3.293 → 0.3.298
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/package.json +3 -4
- package/src/ApiClient.d.ts +19 -0
- package/src/ApiClient.js +26 -0
- package/src/ApiClient.js.map +1 -0
- package/src/ApiFactory.d.ts +25 -0
- package/src/ApiFactory.js +3 -0
- package/src/ApiFactory.js.map +1 -0
- package/src/ApiRoutingFactory.js +1 -1
- package/src/ApiRoutingFactory.js.map +1 -1
- package/src/AuthConfig.d.ts +30 -0
- package/src/AuthConfig.js +35 -0
- package/src/AuthConfig.js.map +1 -0
- package/src/Filter.d.ts +76 -0
- package/src/Filter.js +75 -0
- package/src/Filter.js.map +1 -0
- package/src/FilterChain.d.ts +30 -0
- package/src/FilterChain.js +63 -0
- package/src/FilterChain.js.map +1 -0
- package/src/FilterMatcher.d.ts +2 -2
- package/src/FilterMatcher.js.map +1 -1
- package/src/InProcessApiClientFactory.d.ts +1 -0
- package/src/InProcessApiClientFactory.js +15 -3
- package/src/InProcessApiClientFactory.js.map +1 -1
- package/src/MethodMeta.d.ts +53 -0
- package/src/MethodMeta.js +74 -0
- package/src/MethodMeta.js.map +1 -0
- package/src/RouteBuilderImpl.d.ts +11 -3
- package/src/RouteBuilderImpl.js +20 -11
- package/src/RouteBuilderImpl.js.map +1 -1
- package/src/RouteHandler.d.ts +1 -1
- package/src/RouteHandler.js.map +1 -1
- package/src/WebAppMeta.d.ts +6 -15
- package/src/WebAppMeta.js +11 -7
- package/src/WebAppMeta.js.map +1 -1
- package/src/WebpiecesRouter.d.ts +21 -10
- package/src/WebpiecesRouter.js +27 -13
- package/src/WebpiecesRouter.js.map +1 -1
- package/src/fillContext.d.ts +11 -0
- package/src/fillContext.js +35 -0
- package/src/fillContext.js.map +1 -0
- package/src/filters/AuthFilter.d.ts +24 -0
- package/src/filters/AuthFilter.js +102 -0
- package/src/filters/AuthFilter.js.map +1 -0
- package/src/filters/ErrorLogFilter.d.ts +15 -0
- package/src/filters/ErrorLogFilter.js +40 -0
- package/src/filters/ErrorLogFilter.js.map +1 -0
- package/src/index.d.ts +9 -4
- package/src/index.js +27 -14
- package/src/index.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebpiecesRouter.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WebpiecesRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, ContainerModule, inject } from 'inversify';\nimport { buildProviderModule } from '@inversifyjs/binding-decorators';\nimport { DocumentDesign } from '@webpieces/core-util';\nimport { provideFrameworkSingleton, buildFrameworkModule } from '@webpieces/core-context';\nimport { RouteBuilderImpl } from './RouteBuilderImpl';\nimport { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';\nimport { FilterDefinition } from './WebAppMeta';\nimport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\nimport { InProcessApiClientFactory } from './InProcessApiClientFactory';\n\n/**\n * Options for {@link WebpiecesRouterFactory.create}.\n *\n * appBindings - REQUIRED DI ContainerModules to load (framework + app), e.g.\n * [WebpiecesModule, CompanyHeadersModule, AppModule]. Loaded after the\n * @provideSingleton auto-scan so they can add/override bindings.\n * appOverrides - A single ContainerModule loaded LAST so tests can rebind real\n * controllers/clients to mocks (see @webpieces/core-mock createMock()).\n */\nexport interface WebpiecesRouterOptions {\n appBindings: ContainerModule[];\n appOverrides?: ContainerModule;\n}\n\n/**\n * WebpiecesRouter - the node-only heart of a webpieces app: a DI container + a filter\n * chain + an in-process API client. It has NO express dependency, so it runs anywhere\n * node runs and is fully testable with zero HTTP.\n *\n * DI-resolved from the platform container (like the old WebpiecesServerImpl):\n * `@provideSingleton @injectable`, RouteBuilderImpl injected, and the two containers set in\n * initialize(). Built by {@link WebpiecesRouterFactory.create} — never `new`ed by callers.\n *\n * Two-container pattern (mirrors Java WebPieces):\n * - webpiecesContainer : framework bindings (config token, @DocumentDesign design roots)\n * - appContainer : your controllers/filters/modules (a child of the framework one)\n *\n * Usage:\n * ```typescript\n * const router = await WebpiecesRouterFactory.create(new WebpiecesConfig(), {\n * appBindings: [WebpiecesModule, CompanyHeadersModule],\n * });\n * router.addRoutes(SaveApi, SaveController);\n * router.addFilter(new FilterDefinition(1800, LogApiFilter, '*')); // api tier\n * router.addFilter(new FilterDefinition(1950, ServiceAuthFilter, '*', 'express')); // express tier\n *\n * // test (no express): runs the api-tier filter chain -> controller\n * const api = router.createApiClient(SaveApi);\n * await api.save(new SaveRequest(...));\n * ```\n *\n * To serve real HTTP, hand this router to the express adapter in @webpieces/http-server\n * (bindExpress / bindAndStartExpress) — express lifecycle lives THERE, never here.\n *\n * @DocumentDesign marks it a design root so it appears in http-routing's designed-lib graph.\n */\n@DocumentDesign()\n@provideFrameworkSingleton()\nexport class WebpiecesRouter {\n private webpiecesContainer!: Container;\n private appContainer!: Container;\n\n constructor(\n @inject(RouteBuilderImpl) private readonly routeBuilder: RouteBuilderImpl,\n ) {}\n\n /**\n * Build the app container (child of the framework container), load the @provideSingleton\n * auto-scan + appBindings + appOverrides, and point the RouteBuilder at it. Called once by\n * the factory after this router is resolved from the framework container.\n */\n async initialize(webpiecesContainer: Container, options: WebpiecesRouterOptions): Promise<void> {\n this.webpiecesContainer = webpiecesContainer;\n\n // App container is a child so app bindings see framework bindings while staying separate.\n this.appContainer = new Container({ parent: webpiecesContainer });\n this.routeBuilder.setContainer(this.appContainer);\n\n await this.loadDIModules(options);\n }\n\n private async loadDIModules(options: WebpiecesRouterOptions): Promise<void> {\n // Load BOTH registries: framework classes (provideFrameworkSingleton) + the client's\n // own @provideSingleton classes (binding-decorators global). A client's\n // buildProviderModule() only ever contains the client's classes — never framework internals.\n await this.appContainer.load(buildFrameworkModule());\n await this.appContainer.load(buildProviderModule());\n\n // Load all modules into application container\n // (webpiecesContainer is currently empty, reserved for future framework bindings)\n for (const module of options.appBindings) {\n await this.appContainer.load(module);\n }\n\n // Load appOverrides LAST so they can override existing bindings\n if (options.appOverrides) {\n await this.appContainer.load(options.appOverrides);\n }\n }\n\n /**\n * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller.\n * The controller is resolved from the container at request time.\n */\n addRoutes<TApi, TController extends TApi>(\n api: ClassType<TApi>,\n controller: ClassType<TController>,\n ): this {\n new ApiRoutingFactory(api, controller).configure(this.routeBuilder);\n return this;\n }\n\n /**\n * Register a filter. Defaults to the 'api' tier (runs in-process AND over HTTP);\n * pass a 'express'-tier FilterDefinition for transport-boundary filters.\n */\n addFilter(filter: FilterDefinition): this {\n this.routeBuilder.addFilter(filter);\n return this;\n }\n\n /**\n * Create an in-process API client that runs the api-tier filter chain + controller\n * with NO express/HTTP. The primary path for tests and node-only callers.\n */\n // webpieces-disable no-any-unknown -- abstract constructor signature requires any[] args\n createApiClient<T>(apiPrototype: abstract new (...args: any[]) => T): T {\n return new InProcessApiClientFactory(this.routeBuilder).createApiClient(apiPrototype);\n }\n\n /** The application DI container (child of the framework container). */\n getContainer(): Container {\n return this.appContainer;\n }\n\n /** The framework container (holds the config token + @DocumentDesign design roots). */\n getFrameworkContainer(): Container {\n return this.webpiecesContainer;\n }\n\n /** The route table + filter chain. Used by the express adapter to mount HTTP routes. */\n getRouteBuilder(): RouteBuilderImpl {\n return this.routeBuilder;\n }\n}\n\n/**\n * Builds a {@link WebpiecesRouter}: constructs the platform container (mirrors\n * WebpiecesServerFactory.create), RESOLVES the router from DI, then initializes its app child\n * container with the @provideSingleton auto-scan + appBindings + optional test overrides.\n */\nexport class WebpiecesRouterFactory {\n static async create(\n config: WebpiecesConfig,\n options: WebpiecesRouterOptions,\n ): Promise<WebpiecesRouter> {\n // Platform (framework) container — build via buildFrameworkModule so framework\n // singletons (WebpiecesRouter, RouteBuilderImpl) come from the webpieces registry,\n // NOT the client's global one.\n const webpiecesContainer = new Container();\n webpiecesContainer.bind(WEBPIECES_CONFIG_TOKEN).toConstantValue(config);\n await webpiecesContainer.load(buildFrameworkModule());\n\n // Resolve the router from the container (NOT new'd) so @DocumentDesign + DI hold.\n const router = webpiecesContainer.get(WebpiecesRouter);\n await router.initialize(webpiecesContainer, options);\n return router;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"WebpiecesRouter.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WebpiecesRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Container, ContainerModule, inject } from 'inversify';\nimport { buildProviderModule } from '@inversifyjs/binding-decorators';\nimport { DocumentDesign } from '@webpieces/core-util';\nimport { provideFrameworkSingleton, buildFrameworkModule } from '@webpieces/core-context';\nimport { RouteBuilderImpl } from './RouteBuilderImpl';\nimport { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';\nimport { FilterDefinition } from './WebAppMeta';\nimport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\nimport { InProcessApiClientFactory } from './InProcessApiClientFactory';\nimport { ApiFactory } from './ApiFactory';\nimport { ApiClient } from './ApiClient';\nimport { ErrorLogFilter } from './filters/ErrorLogFilter';\nimport { AuthFilter } from './filters/AuthFilter';\n\n/**\n * Options for {@link WebpiecesRouterFactory.create}.\n *\n * appBindings - REQUIRED DI ContainerModules to load (framework + app), e.g.\n * [WebpiecesModule, CompanyHeadersModule, AppModule]. Loaded after the\n * @provideSingleton auto-scan so they can add/override bindings.\n * appOverrides - A single ContainerModule loaded LAST so tests can rebind real\n * controllers/clients to mocks (see @webpieces/core-mock createMock()).\n */\nexport interface WebpiecesRouterOptions {\n appBindings: ContainerModule[];\n appOverrides?: ContainerModule;\n}\n\n/**\n * WebpiecesRouter - the node-only heart of a webpieces app: a DI container + a filter\n * chain + an in-process API client. It has NO express dependency, so it runs anywhere\n * node runs and is fully testable with zero HTTP.\n *\n * DI-resolved from the platform container (like the old WebpiecesServerImpl):\n * `@provideSingleton @injectable`, RouteBuilderImpl injected, and the two containers set in\n * initialize(). Built by {@link WebpiecesRouterFactory.create} — never `new`ed by callers.\n *\n * Two-container pattern (mirrors Java WebPieces):\n * - webpiecesContainer : framework bindings (config token, @DocumentDesign design roots)\n * - appContainer : your controllers/filters/modules (a child of the framework one)\n *\n * Usage:\n * ```typescript\n * const router = await WebpiecesRouterFactory.create(new WebpiecesConfig(), {\n * appBindings: [WebpiecesModule, CompanyHeadersModule],\n * });\n * router.addRoutes(SaveApi, SaveController);\n * router.addFilter(new FilterDefinition(1800, LogApiFilter, '*')); // your own filters\n * // (ErrorLogFilter + AuthFilter are auto-installed above yours; auth is AuthMode-driven)\n *\n * // test (no express): runs the SAME filter chain (incl. auth) -> controller\n * const api = router.createApiClient(SaveApi);\n * await api.save(new SaveRequest(...));\n * ```\n *\n * To serve real HTTP, hand this router to the express adapter in @webpieces/http-server\n * (bindExpress / bindAndStartExpress) — express lifecycle lives THERE, never here.\n *\n * @DocumentDesign marks it a design root so it appears in http-routing's designed-lib graph.\n */\n@DocumentDesign()\n@provideFrameworkSingleton()\nexport class WebpiecesRouter implements ApiFactory {\n private webpiecesContainer!: Container;\n private appContainer!: Container;\n\n constructor(\n @inject(RouteBuilderImpl) private readonly routeBuilder: RouteBuilderImpl,\n ) {}\n\n /**\n * Build the app container (child of the framework container), load the @provideSingleton\n * auto-scan + appBindings + appOverrides, and point the RouteBuilder at it. Called once by\n * the factory after this router is resolved from the framework container.\n */\n async initialize(webpiecesContainer: Container, options: WebpiecesRouterOptions): Promise<void> {\n this.webpiecesContainer = webpiecesContainer;\n\n // App container is a child so app bindings see framework bindings while staying separate.\n this.appContainer = new Container({ parent: webpiecesContainer });\n this.routeBuilder.setContainer(this.appContainer);\n\n await this.loadDIModules(options);\n this.installFixedFilters();\n }\n\n /**\n * Auto-install the two fixed framework filters on every route (apps add only their own\n * filters below these): ErrorLogFilter outermost (log + let the transport translate), then\n * AuthFilter (enforces the endpoint's AuthMode off the HttpRequest). Both run over HTTP AND\n * in-process — there is no transport tier.\n */\n private installFixedFilters(): void {\n this.addFilter(new FilterDefinition(1_000_000, ErrorLogFilter, '*'));\n this.addFilter(new FilterDefinition(900_000, AuthFilter, '*'));\n }\n\n private async loadDIModules(options: WebpiecesRouterOptions): Promise<void> {\n // Load BOTH registries: framework classes (provideFrameworkSingleton) + the client's\n // own @provideSingleton classes (binding-decorators global). A client's\n // buildProviderModule() only ever contains the client's classes — never framework internals.\n await this.appContainer.load(buildFrameworkModule());\n await this.appContainer.load(buildProviderModule());\n\n // Load all modules into application container\n // (webpiecesContainer is currently empty, reserved for future framework bindings)\n for (const module of options.appBindings) {\n await this.appContainer.load(module);\n }\n\n // Load appOverrides LAST so they can override existing bindings\n if (options.appOverrides) {\n await this.appContainer.load(options.appOverrides);\n }\n }\n\n /**\n * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller.\n * The controller is resolved from the container at request time.\n */\n addRoutes<TApi, TController extends TApi>(\n api: ClassType<TApi>,\n controller: ClassType<TController>,\n ): this {\n new ApiRoutingFactory(api, controller).configure(this.routeBuilder);\n return this;\n }\n\n /**\n * Register a user filter (runs in-process AND over HTTP, below the auto-installed fixed\n * ErrorLogFilter + AuthFilter).\n */\n addFilter(filter: FilterDefinition): this {\n this.routeBuilder.addFilter(filter);\n return this;\n }\n\n /**\n * Create an in-process API client that runs the api-tier filter chain + controller\n * with NO express/HTTP. The primary path for tests and node-only callers.\n */\n // webpieces-disable no-any-unknown -- abstract constructor signature requires any[] args\n createApiClient<T>(apiPrototype: abstract new (...args: any[]) => T): T {\n return new InProcessApiClientFactory(this.routeBuilder).createApiClient(apiPrototype);\n }\n\n /**\n * Reify the registered routes as {@link ApiClient}s (api contract + routeMeta + composed\n * filter-chain→controller impl). This is the ONLY handoff to the express layer — the\n * internal RouteBuilder never leaves this class.\n */\n apiClients(): ApiClient[] {\n return this.routeBuilder.apiClients();\n }\n\n /** The application DI container (child of the framework container). */\n getContainer(): Container {\n return this.appContainer;\n }\n}\n\n/**\n * Builds a {@link WebpiecesRouter}: constructs the platform container (mirrors\n * WebpiecesServerFactory.create), RESOLVES the router from DI, then initializes its app child\n * container with the @provideSingleton auto-scan + appBindings + optional test overrides.\n */\nexport class WebpiecesRouterFactory {\n static async create(\n config: WebpiecesConfig,\n options: WebpiecesRouterOptions,\n ): Promise<WebpiecesRouter> {\n // Platform (framework) container — build via buildFrameworkModule so framework\n // singletons (WebpiecesRouter, RouteBuilderImpl) come from the webpieces registry,\n // NOT the client's global one.\n const webpiecesContainer = new Container();\n webpiecesContainer.bind(WEBPIECES_CONFIG_TOKEN).toConstantValue(config);\n await webpiecesContainer.load(buildFrameworkModule());\n\n // Resolve the router from the container (NOT new'd) so @DocumentDesign + DI hold.\n const router = webpiecesContainer.get(WebpiecesRouter);\n await router.initialize(webpiecesContainer, options);\n return router;\n }\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fillContext - ABOVE-the-boundary context setup, shared by every transport (the express
|
|
3
|
+
* adapter AND the in-process client). Call it once, inside RequestContext.run() and after
|
|
4
|
+
* RequestContext.setRequest(httpRequest): it transfers the platform/context headers from the
|
|
5
|
+
* HttpRequest into RequestContext (for logging + outbound propagation) and ensures a REQUEST_ID.
|
|
6
|
+
*
|
|
7
|
+
* This is the old below-boundary ContextFilter's job, moved above the api boundary so the raw
|
|
8
|
+
* request never has to survive as a chain filter — the fixed error/auth filters and the
|
|
9
|
+
* controller run below, reading the already-populated context (and the HttpRequest for auth).
|
|
10
|
+
*/
|
|
11
|
+
export declare function fillContext(): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fillContext = fillContext;
|
|
4
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
5
|
+
const core_util_1 = require("@webpieces/core-util");
|
|
6
|
+
/**
|
|
7
|
+
* fillContext - ABOVE-the-boundary context setup, shared by every transport (the express
|
|
8
|
+
* adapter AND the in-process client). Call it once, inside RequestContext.run() and after
|
|
9
|
+
* RequestContext.setRequest(httpRequest): it transfers the platform/context headers from the
|
|
10
|
+
* HttpRequest into RequestContext (for logging + outbound propagation) and ensures a REQUEST_ID.
|
|
11
|
+
*
|
|
12
|
+
* This is the old below-boundary ContextFilter's job, moved above the api boundary so the raw
|
|
13
|
+
* request never has to survive as a chain filter — the fixed error/auth filters and the
|
|
14
|
+
* controller run below, reading the already-populated context (and the HttpRequest for auth).
|
|
15
|
+
*/
|
|
16
|
+
function fillContext() {
|
|
17
|
+
const request = core_context_1.RequestContext.getRequest();
|
|
18
|
+
const registry = core_util_1.HeaderRegistry.get();
|
|
19
|
+
if (request) {
|
|
20
|
+
// Transfer each transferred key (read by wire name, store under key.name).
|
|
21
|
+
for (const key of registry.getTransferredKeys()) {
|
|
22
|
+
const values = request.getHeaderValues(key);
|
|
23
|
+
if (values && values.length > 0) {
|
|
24
|
+
core_context_1.RequestContext.putHeader(key, values[0]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (!core_context_1.RequestContext.hasHeader(core_util_1.WebpiecesCoreHeaders.REQUEST_ID)) {
|
|
29
|
+
core_context_1.RequestContext.putHeader(core_util_1.WebpiecesCoreHeaders.REQUEST_ID, generateRequestId());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function generateRequestId() {
|
|
33
|
+
return `svrGenReqId-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=fillContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fillContext.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/fillContext.ts"],"names":[],"mappings":";;AAaA,kCAiBC;AA9BD,0DAAyD;AACzD,oDAA4E;AAE5E;;;;;;;;;GASG;AACH,SAAgB,WAAW;IACvB,MAAM,OAAO,GAAG,6BAAc,CAAC,UAAU,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,0BAAc,CAAC,GAAG,EAAE,CAAC;IAEtC,IAAI,OAAO,EAAE,CAAC;QACV,2EAA2E;QAC3E,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAC5C,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,6BAAc,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;QACL,CAAC;IACL,CAAC;IAED,IAAI,CAAC,6BAAc,CAAC,SAAS,CAAC,gCAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7D,6BAAc,CAAC,SAAS,CAAC,gCAAoB,CAAC,UAAU,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACnF,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB;IACtB,OAAO,eAAe,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACtF,CAAC","sourcesContent":["import { RequestContext } from '@webpieces/core-context';\nimport { HeaderRegistry, WebpiecesCoreHeaders } from '@webpieces/core-util';\n\n/**\n * fillContext - ABOVE-the-boundary context setup, shared by every transport (the express\n * adapter AND the in-process client). Call it once, inside RequestContext.run() and after\n * RequestContext.setRequest(httpRequest): it transfers the platform/context headers from the\n * HttpRequest into RequestContext (for logging + outbound propagation) and ensures a REQUEST_ID.\n *\n * This is the old below-boundary ContextFilter's job, moved above the api boundary so the raw\n * request never has to survive as a chain filter — the fixed error/auth filters and the\n * controller run below, reading the already-populated context (and the HttpRequest for auth).\n */\nexport function fillContext(): void {\n const request = RequestContext.getRequest();\n const registry = HeaderRegistry.get();\n\n if (request) {\n // Transfer each transferred key (read by wire name, store under key.name).\n for (const key of registry.getTransferredKeys()) {\n const values = request.getHeaderValues(key);\n if (values && values.length > 0) {\n RequestContext.putHeader(key, values[0]);\n }\n }\n }\n\n if (!RequestContext.hasHeader(WebpiecesCoreHeaders.REQUEST_ID)) {\n RequestContext.putHeader(WebpiecesCoreHeaders.REQUEST_ID, generateRequestId());\n }\n}\n\nfunction generateRequestId(): string {\n return `svrGenReqId-${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Filter, WpResponse, Service } from '../Filter';
|
|
2
|
+
import { MethodMeta } from '../MethodMeta';
|
|
3
|
+
import { AuthConfig } from '../AuthConfig';
|
|
4
|
+
/**
|
|
5
|
+
* AuthFilter - the ONE framework auth filter, auto-installed just below the error filter on
|
|
6
|
+
* every route. It is TRANSPORT-NEUTRAL: it reads the raw credential from the {@link HttpRequest}
|
|
7
|
+
* in RequestContext (never express), so the SAME check runs over HTTP and via createApiClient.
|
|
8
|
+
*
|
|
9
|
+
* It enforces the endpoint's AuthMode (public/jwt/oidc/shared-secret) using the injected
|
|
10
|
+
* {@link AuthConfig} — the concrete verifiers are app-provided and container-bound (rebindable
|
|
11
|
+
* in tests), so http-routing needs no crypto / gcp-identity. Replaces the old app AuthFilter +
|
|
12
|
+
* framework ServiceAuthFilter and removes the express/api filter tier.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AuthFilter extends Filter<MethodMeta, WpResponse<unknown>> {
|
|
15
|
+
private readonly authConfig?;
|
|
16
|
+
constructor(authConfig?: AuthConfig | undefined);
|
|
17
|
+
filter(meta: MethodMeta, nextFilter: Service<MethodMeta, WpResponse<unknown>>): Promise<WpResponse<unknown>>;
|
|
18
|
+
private requireAuthConfig;
|
|
19
|
+
private enforceJwt;
|
|
20
|
+
private enforceOidc;
|
|
21
|
+
private enforceSharedSecret;
|
|
22
|
+
private stripBearer;
|
|
23
|
+
private constantTimeEquals;
|
|
24
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthFilter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const inversify_1 = require("inversify");
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
8
|
+
const core_util_1 = require("@webpieces/core-util");
|
|
9
|
+
const Filter_1 = require("../Filter");
|
|
10
|
+
const AuthConfig_1 = require("../AuthConfig");
|
|
11
|
+
/** Reserved context key holding the authenticated Principal (stamped after a jwt verify). */
|
|
12
|
+
const PRINCIPAL_KEY = '__webpieces_principal__';
|
|
13
|
+
/**
|
|
14
|
+
* AuthFilter - the ONE framework auth filter, auto-installed just below the error filter on
|
|
15
|
+
* every route. It is TRANSPORT-NEUTRAL: it reads the raw credential from the {@link HttpRequest}
|
|
16
|
+
* in RequestContext (never express), so the SAME check runs over HTTP and via createApiClient.
|
|
17
|
+
*
|
|
18
|
+
* It enforces the endpoint's AuthMode (public/jwt/oidc/shared-secret) using the injected
|
|
19
|
+
* {@link AuthConfig} — the concrete verifiers are app-provided and container-bound (rebindable
|
|
20
|
+
* in tests), so http-routing needs no crypto / gcp-identity. Replaces the old app AuthFilter +
|
|
21
|
+
* framework ServiceAuthFilter and removes the express/api filter tier.
|
|
22
|
+
*/
|
|
23
|
+
let AuthFilter = class AuthFilter extends Filter_1.Filter {
|
|
24
|
+
authConfig;
|
|
25
|
+
constructor(authConfig) {
|
|
26
|
+
super();
|
|
27
|
+
this.authConfig = authConfig;
|
|
28
|
+
}
|
|
29
|
+
// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility
|
|
30
|
+
async filter(meta, nextFilter) {
|
|
31
|
+
const mode = meta.authMeta?.mode;
|
|
32
|
+
if (!mode || mode.kind === 'public') {
|
|
33
|
+
return nextFilter.invoke(meta);
|
|
34
|
+
}
|
|
35
|
+
const request = core_context_1.RequestContext.getRequest();
|
|
36
|
+
switch (mode.kind) {
|
|
37
|
+
case 'jwt':
|
|
38
|
+
this.enforceJwt(request?.getHeader(core_util_1.WebpiecesCoreHeaders.AUTHORIZATION));
|
|
39
|
+
break;
|
|
40
|
+
case 'oidc':
|
|
41
|
+
await this.enforceOidc(request?.getHeader(core_util_1.WebpiecesCoreHeaders.AUTHORIZATION), mode.callers);
|
|
42
|
+
break;
|
|
43
|
+
case 'shared-secret':
|
|
44
|
+
this.enforceSharedSecret(request?.getHeader(core_util_1.WebpiecesCoreHeaders.SHARED_SECRET), mode.secretEnv);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
return nextFilter.invoke(meta);
|
|
48
|
+
}
|
|
49
|
+
requireAuthConfig() {
|
|
50
|
+
if (!this.authConfig) {
|
|
51
|
+
throw new core_util_1.HttpUnauthorizedError('No AuthConfig bound — cannot enforce a non-public endpoint');
|
|
52
|
+
}
|
|
53
|
+
return this.authConfig;
|
|
54
|
+
}
|
|
55
|
+
enforceJwt(header) {
|
|
56
|
+
const token = this.stripBearer(header);
|
|
57
|
+
if (!token) {
|
|
58
|
+
throw new core_util_1.HttpUnauthorizedError('Authentication required');
|
|
59
|
+
}
|
|
60
|
+
const principal = this.requireAuthConfig().verifyJwt(token);
|
|
61
|
+
core_context_1.RequestContext.put(PRINCIPAL_KEY, principal);
|
|
62
|
+
}
|
|
63
|
+
async enforceOidc(header, callers) {
|
|
64
|
+
const token = this.stripBearer(header);
|
|
65
|
+
if (!token) {
|
|
66
|
+
throw new core_util_1.HttpUnauthorizedError('Missing OIDC bearer token for @AuthOidc endpoint');
|
|
67
|
+
}
|
|
68
|
+
await this.requireAuthConfig().verifyOidc(token, callers);
|
|
69
|
+
}
|
|
70
|
+
enforceSharedSecret(provided, secretEnv) {
|
|
71
|
+
const expected = this.requireAuthConfig().sharedSecret(secretEnv);
|
|
72
|
+
if (!expected || !provided || !this.constantTimeEquals(provided, expected)) {
|
|
73
|
+
throw new core_util_1.HttpUnauthorizedError('Invalid shared secret for @AuthSharedSecret endpoint');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
stripBearer(header) {
|
|
77
|
+
if (!header) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const prefix = 'Bearer ';
|
|
81
|
+
return header.startsWith(prefix) ? header.substring(prefix.length) : header;
|
|
82
|
+
}
|
|
83
|
+
constantTimeEquals(a, b) {
|
|
84
|
+
const bufA = Buffer.from(a, 'utf8');
|
|
85
|
+
const bufB = Buffer.from(b, 'utf8');
|
|
86
|
+
if (bufA.length !== bufB.length) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return (0, crypto_1.timingSafeEqual)(bufA, bufB);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.AuthFilter = AuthFilter;
|
|
93
|
+
exports.AuthFilter = AuthFilter = tslib_1.__decorate([
|
|
94
|
+
(0, core_context_1.provideFrameworkSingleton)(),
|
|
95
|
+
(0, inversify_1.injectable)()
|
|
96
|
+
// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility
|
|
97
|
+
,
|
|
98
|
+
tslib_1.__param(0, (0, inversify_1.optional)()),
|
|
99
|
+
tslib_1.__param(0, (0, inversify_1.inject)(AuthConfig_1.AuthConfig)),
|
|
100
|
+
tslib_1.__metadata("design:paramtypes", [AuthConfig_1.AuthConfig])
|
|
101
|
+
], AuthFilter);
|
|
102
|
+
//# sourceMappingURL=AuthFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthFilter.js","sourceRoot":"","sources":["../../../../../../packages/http/http-routing/src/filters/AuthFilter.ts"],"names":[],"mappings":"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","sourcesContent":["import { inject, injectable, optional } from 'inversify';\nimport { timingSafeEqual } from 'crypto';\nimport { provideFrameworkSingleton, RequestContext } from '@webpieces/core-context';\nimport { WebpiecesCoreHeaders, HttpUnauthorizedError } from '@webpieces/core-util';\nimport { Filter, WpResponse, Service } from '../Filter';\nimport { MethodMeta } from '../MethodMeta';\nimport { AuthConfig } from '../AuthConfig';\n\n/** Reserved context key holding the authenticated Principal (stamped after a jwt verify). */\nconst PRINCIPAL_KEY = '__webpieces_principal__';\n\n/**\n * AuthFilter - the ONE framework auth filter, auto-installed just below the error filter on\n * every route. It is TRANSPORT-NEUTRAL: it reads the raw credential from the {@link HttpRequest}\n * in RequestContext (never express), so the SAME check runs over HTTP and via createApiClient.\n *\n * It enforces the endpoint's AuthMode (public/jwt/oidc/shared-secret) using the injected\n * {@link AuthConfig} — the concrete verifiers are app-provided and container-bound (rebindable\n * in tests), so http-routing needs no crypto / gcp-identity. Replaces the old app AuthFilter +\n * framework ServiceAuthFilter and removes the express/api filter tier.\n */\n@provideFrameworkSingleton()\n@injectable()\n// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility\nexport class AuthFilter extends Filter<MethodMeta, WpResponse<unknown>> {\n constructor(\n // @optional: a public-only server need not bind an AuthConfig; a non-public route\n // then fails fast in requireAuthConfig().\n @optional() @inject(AuthConfig) private readonly authConfig?: AuthConfig,\n ) {\n super();\n }\n\n // webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility\n override async filter(\n meta: MethodMeta,\n nextFilter: Service<MethodMeta, WpResponse<unknown>>,\n ): Promise<WpResponse<unknown>> {\n const mode = meta.authMeta?.mode;\n if (!mode || mode.kind === 'public') {\n return nextFilter.invoke(meta);\n }\n\n const request = RequestContext.getRequest();\n switch (mode.kind) {\n case 'jwt':\n this.enforceJwt(request?.getHeader(WebpiecesCoreHeaders.AUTHORIZATION));\n break;\n case 'oidc':\n await this.enforceOidc(request?.getHeader(WebpiecesCoreHeaders.AUTHORIZATION), mode.callers);\n break;\n case 'shared-secret':\n this.enforceSharedSecret(request?.getHeader(WebpiecesCoreHeaders.SHARED_SECRET), mode.secretEnv);\n break;\n }\n return nextFilter.invoke(meta);\n }\n\n private requireAuthConfig(): AuthConfig {\n if (!this.authConfig) {\n throw new HttpUnauthorizedError('No AuthConfig bound — cannot enforce a non-public endpoint');\n }\n return this.authConfig;\n }\n\n private enforceJwt(header: string | undefined): void {\n const token = this.stripBearer(header);\n if (!token) {\n throw new HttpUnauthorizedError('Authentication required');\n }\n const principal = this.requireAuthConfig().verifyJwt(token);\n RequestContext.put(PRINCIPAL_KEY, principal);\n }\n\n private async enforceOidc(header: string | undefined, callers: string[]): Promise<void> {\n const token = this.stripBearer(header);\n if (!token) {\n throw new HttpUnauthorizedError('Missing OIDC bearer token for @AuthOidc endpoint');\n }\n await this.requireAuthConfig().verifyOidc(token, callers);\n }\n\n private enforceSharedSecret(provided: string | undefined, secretEnv: string): void {\n const expected = this.requireAuthConfig().sharedSecret(secretEnv);\n if (!expected || !provided || !this.constantTimeEquals(provided, expected)) {\n throw new HttpUnauthorizedError('Invalid shared secret for @AuthSharedSecret endpoint');\n }\n }\n\n private stripBearer(header: string | undefined): string | undefined {\n if (!header) {\n return undefined;\n }\n const prefix = 'Bearer ';\n return header.startsWith(prefix) ? header.substring(prefix.length) : header;\n }\n\n private constantTimeEquals(a: string, b: string): boolean {\n const bufA = Buffer.from(a, 'utf8');\n const bufB = Buffer.from(b, 'utf8');\n if (bufA.length !== bufB.length) {\n return false;\n }\n return timingSafeEqual(bufA, bufB);\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Filter, WpResponse, Service } from '../Filter';
|
|
2
|
+
import { MethodMeta } from '../MethodMeta';
|
|
3
|
+
/**
|
|
4
|
+
* ErrorLogFilter - the OUTERMOST fixed framework filter (auto-installed above the auth filter on
|
|
5
|
+
* every route). It wraps the whole chain in a try/catch so EVERY failure — over HTTP or via
|
|
6
|
+
* createApiClient — is logged once WITH the request context (correlation/request id, etc.) that
|
|
7
|
+
* fillContext() established above the boundary.
|
|
8
|
+
*
|
|
9
|
+
* It re-throws the error unchanged; the transport (express adapter, or another framework's
|
|
10
|
+
* adapter) maps HttpError subclasses → HTTP status. Being a below-boundary filter means the
|
|
11
|
+
* in-process path gets the same consistent logging the HTTP path always had.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ErrorLogFilter extends Filter<MethodMeta, WpResponse<unknown>> {
|
|
14
|
+
filter(meta: MethodMeta, nextFilter: Service<MethodMeta, WpResponse<unknown>>): Promise<WpResponse<unknown>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorLogFilter = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const inversify_1 = require("inversify");
|
|
6
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
7
|
+
const core_util_1 = require("@webpieces/core-util");
|
|
8
|
+
const Filter_1 = require("../Filter");
|
|
9
|
+
const log = core_util_1.LogManager.getLogger('ErrorLogFilter');
|
|
10
|
+
/**
|
|
11
|
+
* ErrorLogFilter - the OUTERMOST fixed framework filter (auto-installed above the auth filter on
|
|
12
|
+
* every route). It wraps the whole chain in a try/catch so EVERY failure — over HTTP or via
|
|
13
|
+
* createApiClient — is logged once WITH the request context (correlation/request id, etc.) that
|
|
14
|
+
* fillContext() established above the boundary.
|
|
15
|
+
*
|
|
16
|
+
* It re-throws the error unchanged; the transport (express adapter, or another framework's
|
|
17
|
+
* adapter) maps HttpError subclasses → HTTP status. Being a below-boundary filter means the
|
|
18
|
+
* in-process path gets the same consistent logging the HTTP path always had.
|
|
19
|
+
*/
|
|
20
|
+
let ErrorLogFilter = class ErrorLogFilter extends Filter_1.Filter {
|
|
21
|
+
// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility
|
|
22
|
+
async filter(meta, nextFilter) {
|
|
23
|
+
// eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- fixed boundary filter: log every failure with context, then re-throw for the transport to translate to a status
|
|
24
|
+
try {
|
|
25
|
+
return await nextFilter.invoke(meta);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
const error = (0, core_util_1.toError)(err);
|
|
29
|
+
log.error(`[${meta.httpMethod} ${meta.path}] ${error.name}: ${error.message}`, error);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.ErrorLogFilter = ErrorLogFilter;
|
|
35
|
+
exports.ErrorLogFilter = ErrorLogFilter = tslib_1.__decorate([
|
|
36
|
+
(0, core_context_1.provideFrameworkSingleton)(),
|
|
37
|
+
(0, inversify_1.injectable)()
|
|
38
|
+
// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility
|
|
39
|
+
], ErrorLogFilter);
|
|
40
|
+
//# sourceMappingURL=ErrorLogFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorLogFilter.js","sourceRoot":"","sources":["../../../../../../packages/http/http-routing/src/filters/ErrorLogFilter.ts"],"names":[],"mappings":";;;;AAAA,yCAAuC;AACvC,0DAAoE;AACpE,oDAA2D;AAC3D,sCAAwD;AAGxD,MAAM,GAAG,GAAG,sBAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AAEnD;;;;;;;;;GASG;AAII,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,eAAuC;IACvE,iGAAiG;IACxF,KAAK,CAAC,MAAM,CACjB,IAAgB,EAChB,UAAoD;QAEpD,iLAAiL;QACjL,IAAI,CAAC;YACD,OAAO,MAAM,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;YACtF,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;CACJ,CAAA;AAfY,wCAAc;yBAAd,cAAc;IAH1B,IAAA,wCAAyB,GAAE;IAC3B,IAAA,sBAAU,GAAE;IACb,iGAAiG;GACpF,cAAc,CAe1B","sourcesContent":["import { injectable } from 'inversify';\nimport { provideFrameworkSingleton } from '@webpieces/core-context';\nimport { toError, LogManager } from '@webpieces/core-util';\nimport { Filter, WpResponse, Service } from '../Filter';\nimport { MethodMeta } from '../MethodMeta';\n\nconst log = LogManager.getLogger('ErrorLogFilter');\n\n/**\n * ErrorLogFilter - the OUTERMOST fixed framework filter (auto-installed above the auth filter on\n * every route). It wraps the whole chain in a try/catch so EVERY failure — over HTTP or via\n * createApiClient — is logged once WITH the request context (correlation/request id, etc.) that\n * fillContext() established above the boundary.\n *\n * It re-throws the error unchanged; the transport (express adapter, or another framework's\n * adapter) maps HttpError subclasses → HTTP status. Being a below-boundary filter means the\n * in-process path gets the same consistent logging the HTTP path always had.\n */\n@provideFrameworkSingleton()\n@injectable()\n// webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility\nexport class ErrorLogFilter extends Filter<MethodMeta, WpResponse<unknown>> {\n // webpieces-disable no-any-unknown -- Filter generic params use unknown for response flexibility\n override async filter(\n meta: MethodMeta,\n nextFilter: Service<MethodMeta, WpResponse<unknown>>,\n ): Promise<WpResponse<unknown>> {\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- fixed boundary filter: log every failure with context, then re-throw for the transport to translate to a status\n try {\n return await nextFilter.invoke(meta);\n } catch (err: unknown) {\n const error = toError(err);\n log.error(`[${meta.httpMethod} ${meta.path}] ${error.name}: ${error.message}`, error);\n throw error;\n }\n }\n}\n"]}
|
package/src/index.d.ts
CHANGED
|
@@ -4,12 +4,17 @@ export { SourceFile, ROUTING_METADATA_KEYS, } from './decorators';
|
|
|
4
4
|
export { provideSingleton, provideSingletonAs, provideTransient } from '@webpieces/core-context';
|
|
5
5
|
export { provideFrameworkSingleton, provideFrameworkSingletonAs, buildFrameworkModule, } from '@webpieces/core-context';
|
|
6
6
|
export { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';
|
|
7
|
-
export { Routes, RouteBuilder, RouteDefinition, FilterDefinition,
|
|
8
|
-
export {
|
|
7
|
+
export { Routes, RouteBuilder, RouteDefinition, FilterDefinition, } from './WebAppMeta';
|
|
8
|
+
export { HttpRequest } from '@webpieces/core-context';
|
|
9
|
+
export { Filter, WpResponse, Service } from './Filter';
|
|
10
|
+
export { FilterChain } from './FilterChain';
|
|
11
|
+
export { MethodMeta } from './MethodMeta';
|
|
9
12
|
export { RouteHandler } from './RouteHandler';
|
|
10
|
-
export { RouteBuilderImpl, RouteHandlerWithMeta, FilterWithMeta, } from './RouteBuilderImpl';
|
|
11
13
|
export { FilterMatcher, HttpFilter } from './FilterMatcher';
|
|
12
|
-
export {
|
|
14
|
+
export { ApiFactory } from './ApiFactory';
|
|
15
|
+
export { ApiClient } from './ApiClient';
|
|
16
|
+
export { AuthConfig, Principal } from './AuthConfig';
|
|
17
|
+
export { fillContext } from './fillContext';
|
|
13
18
|
export { WebpiecesRouter, WebpiecesRouterFactory, WebpiecesRouterOptions } from './WebpiecesRouter';
|
|
14
19
|
export { RequestContextReader } from '@webpieces/core-context';
|
|
15
20
|
export { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.WebpiecesRouterFactory = exports.WebpiecesRouter = exports.fillContext = exports.Principal = exports.AuthConfig = exports.ApiClient = exports.FilterMatcher = exports.RouteHandler = exports.MethodMeta = exports.FilterChain = exports.WpResponse = exports.Filter = exports.HttpRequest = exports.FilterDefinition = exports.RouteDefinition = exports.ApiRoutingFactory = exports.buildFrameworkModule = exports.provideFrameworkSingletonAs = exports.provideFrameworkSingleton = exports.provideTransient = exports.provideSingletonAs = exports.provideSingleton = exports.ROUTING_METADATA_KEYS = exports.SourceFile = exports.isDocumentDesign = exports.DocumentDesign = exports.METADATA_KEYS = exports.RouteMetadata = exports.AuthMeta = exports.getQueueName = exports.assertPubSubConventions = exports.assertApiKind = exports.getApiKind = exports.assertEveryEndpointHasAuthMode = exports.getAuthMode = exports.getAuthMeta = exports.isApiPath = exports.getEndpoints = exports.getApiPath = exports.Queue = exports.PubSub = exports.Rpc = exports.AuthSharedSecret = exports.AuthOidc = exports.AuthJwt = exports.Public = exports.AuthenticationConfig = exports.Authentication = exports.Endpoint = exports.ApiPath = void 0;
|
|
4
|
+
exports.WEBPIECES_CONFIG_TOKEN = exports.WebpiecesConfig = exports.RequestContextReader = void 0;
|
|
4
5
|
// Re-export API decorators from core-util for convenience
|
|
5
6
|
var core_util_1 = require("@webpieces/core-util");
|
|
6
7
|
Object.defineProperty(exports, "ApiPath", { enumerable: true, get: function () { return core_util_1.ApiPath; } });
|
|
@@ -51,29 +52,41 @@ Object.defineProperty(exports, "ApiRoutingFactory", { enumerable: true, get: fun
|
|
|
51
52
|
var WebAppMeta_1 = require("./WebAppMeta");
|
|
52
53
|
Object.defineProperty(exports, "RouteDefinition", { enumerable: true, get: function () { return WebAppMeta_1.RouteDefinition; } });
|
|
53
54
|
Object.defineProperty(exports, "FilterDefinition", { enumerable: true, get: function () { return WebAppMeta_1.FilterDefinition; } });
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// The transport-neutral request type (defined in core-context; this is http-routing's
|
|
56
|
+
// public request — a transport adapter builds one and the chain reads it from RequestContext).
|
|
57
|
+
var core_context_3 = require("@webpieces/core-context");
|
|
58
|
+
Object.defineProperty(exports, "HttpRequest", { enumerable: true, get: function () { return core_context_3.HttpRequest; } });
|
|
59
|
+
// Filter-chain primitives (absorbed from the former @webpieces/http-filters package)
|
|
60
|
+
var Filter_1 = require("./Filter");
|
|
61
|
+
Object.defineProperty(exports, "Filter", { enumerable: true, get: function () { return Filter_1.Filter; } });
|
|
62
|
+
Object.defineProperty(exports, "WpResponse", { enumerable: true, get: function () { return Filter_1.WpResponse; } });
|
|
63
|
+
var FilterChain_1 = require("./FilterChain");
|
|
64
|
+
Object.defineProperty(exports, "FilterChain", { enumerable: true, get: function () { return FilterChain_1.FilterChain; } });
|
|
65
|
+
var MethodMeta_1 = require("./MethodMeta");
|
|
66
|
+
Object.defineProperty(exports, "MethodMeta", { enumerable: true, get: function () { return MethodMeta_1.MethodMeta; } });
|
|
57
67
|
var RouteHandler_1 = require("./RouteHandler");
|
|
58
68
|
Object.defineProperty(exports, "RouteHandler", { enumerable: true, get: function () { return RouteHandler_1.RouteHandler; } });
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
Object.defineProperty(exports, "RouteBuilderImpl", { enumerable: true, get: function () { return RouteBuilderImpl_1.RouteBuilderImpl; } });
|
|
62
|
-
Object.defineProperty(exports, "RouteHandlerWithMeta", { enumerable: true, get: function () { return RouteBuilderImpl_1.RouteHandlerWithMeta; } });
|
|
63
|
-
Object.defineProperty(exports, "FilterWithMeta", { enumerable: true, get: function () { return RouteBuilderImpl_1.FilterWithMeta; } });
|
|
69
|
+
// RouteBuilderImpl (the route table + chain composer) is now INTERNAL — it is never
|
|
70
|
+
// handed to upper layers. The express layer consumes ApiFactory.apiClients() instead.
|
|
64
71
|
// Filter matching
|
|
65
72
|
var FilterMatcher_1 = require("./FilterMatcher");
|
|
66
73
|
Object.defineProperty(exports, "FilterMatcher", { enumerable: true, get: function () { return FilterMatcher_1.FilterMatcher; } });
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
var ApiClient_1 = require("./ApiClient");
|
|
75
|
+
Object.defineProperty(exports, "ApiClient", { enumerable: true, get: function () { return ApiClient_1.ApiClient; } });
|
|
76
|
+
// Auth: the app-provided, container-bound verifiers the framework AuthFilter injects.
|
|
77
|
+
var AuthConfig_1 = require("./AuthConfig");
|
|
78
|
+
Object.defineProperty(exports, "AuthConfig", { enumerable: true, get: function () { return AuthConfig_1.AuthConfig; } });
|
|
79
|
+
Object.defineProperty(exports, "Principal", { enumerable: true, get: function () { return AuthConfig_1.Principal; } });
|
|
80
|
+
// Above-boundary context setup shared by every transport adapter.
|
|
81
|
+
var fillContext_1 = require("./fillContext");
|
|
82
|
+
Object.defineProperty(exports, "fillContext", { enumerable: true, get: function () { return fillContext_1.fillContext; } });
|
|
70
83
|
// Node-only router (the express-free heart: container + filter chain + in-process client)
|
|
71
84
|
var WebpiecesRouter_1 = require("./WebpiecesRouter");
|
|
72
85
|
Object.defineProperty(exports, "WebpiecesRouter", { enumerable: true, get: function () { return WebpiecesRouter_1.WebpiecesRouter; } });
|
|
73
86
|
Object.defineProperty(exports, "WebpiecesRouterFactory", { enumerable: true, get: function () { return WebpiecesRouter_1.WebpiecesRouterFactory; } });
|
|
74
87
|
// Context readers (Node.js only) moved to core-context; re-exported for back-compat
|
|
75
|
-
var
|
|
76
|
-
Object.defineProperty(exports, "RequestContextReader", { enumerable: true, get: function () { return
|
|
88
|
+
var core_context_4 = require("@webpieces/core-context");
|
|
89
|
+
Object.defineProperty(exports, "RequestContextReader", { enumerable: true, get: function () { return core_context_4.RequestContextReader; } });
|
|
77
90
|
// Server configuration
|
|
78
91
|
var WebpiecesConfig_1 = require("./WebpiecesConfig");
|
|
79
92
|
Object.defineProperty(exports, "WebpiecesConfig", { enumerable: true, get: function () { return WebpiecesConfig_1.WebpiecesConfig; } });
|
package/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/index.ts"],"names":[],"mappings":";;;;AAAA,0DAA0D;AAC1D,kDA8B8B;AA7B1B,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,2GAAA,cAAc,OAAA;AACd,iHAAA,oBAAoB,OAAA;AACpB,mGAAA,MAAM,OAAA;AACN,oGAAA,OAAO,OAAA;AACP,qGAAA,QAAQ,OAAA;AACR,6GAAA,gBAAgB,OAAA;AAChB,gGAAA,GAAG,OAAA;AACH,mGAAA,MAAM,OAAA;AACN,kGAAA,KAAK,OAAA;AACL,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;AACZ,sGAAA,SAAS,OAAA;AACT,wGAAA,WAAW,OAAA;AACX,wGAAA,WAAW,OAAA;AACX,2HAAA,8BAA8B,OAAA;AAC9B,uGAAA,UAAU,OAAA;AACV,0GAAA,aAAa,OAAA;AACb,oHAAA,uBAAuB,OAAA;AACvB,yGAAA,YAAY,OAAA;AACZ,qGAAA,QAAQ,OAAA;AACR,0GAAA,aAAa,OAAA;AACb,0GAAA,aAAa,OAAA;AAEb,2EAA2E;AAC3E,oCAAoC;AACpC,2GAAA,cAAc,OAAA;AACd,6GAAA,gBAAgB,OAAA;AAIpB,+CAA+C;AAC/C,2CAGsB;AAFlB,wGAAA,UAAU,OAAA;AACV,mHAAA,qBAAqB,OAAA;AAGzB,iFAAiF;AACjF,wDAAiG;AAAxF,gHAAA,gBAAgB,OAAA;AAAE,kHAAA,kBAAkB,OAAA;AAAE,gHAAA,gBAAgB,OAAA;AAC/D,gGAAgG;AAChG,wDAIiC;AAH7B,yHAAA,yBAAyB,OAAA;AACzB,2HAAA,2BAA2B,OAAA;AAC3B,oHAAA,oBAAoB,OAAA;AAGxB,yDAAmE;AAA1D,sHAAA,iBAAiB,OAAA;AAE1B,qBAAqB;AACrB,2CAKsB;AAFlB,6GAAA,eAAe,OAAA;AACf,8GAAA,gBAAgB,OAAA;AAGpB,sFAAsF;AACtF,+FAA+F;AAC/F,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AAEpB,qFAAqF;AACrF,mCAAuD;AAA9C,gGAAA,MAAM,OAAA;AAAE,oGAAA,UAAU,OAAA;AAC3B,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AACnB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,oFAAoF;AACpF,sFAAsF;AAEtF,kBAAkB;AAClB,iDAA4D;AAAnD,8GAAA,aAAa,OAAA;AAItB,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAElB,sFAAsF;AACtF,2CAAqD;AAA5C,wGAAA,UAAU,OAAA;AAAE,uGAAA,SAAS,OAAA;AAE9B,kEAAkE;AAClE,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AAEpB,0FAA0F;AAC1F,qDAAoG;AAA3F,kHAAA,eAAe,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AAEhD,oFAAoF;AACpF,wDAA+D;AAAtD,oHAAA,oBAAoB,OAAA;AAE7B,uBAAuB;AACvB,qDAA4E;AAAnE,kHAAA,eAAe,OAAA;AAAE,yHAAA,sBAAsB,OAAA","sourcesContent":["// Re-export API decorators from core-util for convenience\nexport {\n ApiPath,\n Endpoint,\n Authentication,\n AuthenticationConfig,\n Public,\n AuthJwt,\n AuthOidc,\n AuthSharedSecret,\n Rpc,\n PubSub,\n Queue,\n getApiPath,\n getEndpoints,\n isApiPath,\n getAuthMeta,\n getAuthMode,\n assertEveryEndpointHasAuthMode,\n getApiKind,\n assertApiKind,\n assertPubSubConventions,\n getQueueName,\n AuthMeta,\n RouteMetadata,\n METADATA_KEYS,\n ValidateImplementation,\n // @DocumentDesign moved to core-util (design-root marker, browser + Node);\n // re-exported here for back-compat.\n DocumentDesign,\n isDocumentDesign,\n} from '@webpieces/core-util';\nexport type { AuthMode, ApiKind } from '@webpieces/core-util';\n\n// Server-side routing decorators and utilities\nexport {\n SourceFile,\n ROUTING_METADATA_KEYS,\n} from './decorators';\n\n// DI provider decorators moved to core-context; re-exported here for back-compat\nexport { provideSingleton, provideSingletonAs, provideTransient } from '@webpieces/core-context';\n// Framework-only DI registry (packages/** framework classes use these; see frameworkProvide.ts)\nexport {\n provideFrameworkSingleton,\n provideFrameworkSingletonAs,\n buildFrameworkModule,\n} from '@webpieces/core-context';\n\nexport { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';\n\n// Core routing types\nexport {\n Routes,\n RouteBuilder,\n RouteDefinition,\n FilterDefinition,\n} from './WebAppMeta';\n\n// The transport-neutral request type (defined in core-context; this is http-routing's\n// public request — a transport adapter builds one and the chain reads it from RequestContext).\nexport { HttpRequest } from '@webpieces/core-context';\n\n// Filter-chain primitives (absorbed from the former @webpieces/http-filters package)\nexport { Filter, WpResponse, Service } from './Filter';\nexport { FilterChain } from './FilterChain';\nexport { MethodMeta } from './MethodMeta';\nexport { RouteHandler } from './RouteHandler';\n\n// RouteBuilderImpl (the route table + chain composer) is now INTERNAL — it is never\n// handed to upper layers. The express layer consumes ApiFactory.apiClients() instead.\n\n// Filter matching\nexport { FilterMatcher, HttpFilter } from './FilterMatcher';\n\n// The public API-surface abstraction: declare routes/filters, get them back as ApiClient[].\nexport { ApiFactory } from './ApiFactory';\nexport { ApiClient } from './ApiClient';\n\n// Auth: the app-provided, container-bound verifiers the framework AuthFilter injects.\nexport { AuthConfig, Principal } from './AuthConfig';\n\n// Above-boundary context setup shared by every transport adapter.\nexport { fillContext } from './fillContext';\n\n// Node-only router (the express-free heart: container + filter chain + in-process client)\nexport { WebpiecesRouter, WebpiecesRouterFactory, WebpiecesRouterOptions } from './WebpiecesRouter';\n\n// Context readers (Node.js only) moved to core-context; re-exported for back-compat\nexport { RequestContextReader } from '@webpieces/core-context';\n\n// Server configuration\nexport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\n"]}
|