@webpieces/http-routing 0.4.987 → 0.4.989

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.
Files changed (42) hide show
  1. package/README.md +111 -0
  2. package/package.json +7 -7
  3. package/src/ApiClient.d.ts +1 -1
  4. package/src/ApiClient.js.map +1 -1
  5. package/src/ApiClientFactory.js.map +1 -1
  6. package/src/ApiRoutingFactory.d.ts +6 -9
  7. package/src/ApiRoutingFactory.js +14 -7
  8. package/src/ApiRoutingFactory.js.map +1 -1
  9. package/src/BindModule.d.ts +6 -0
  10. package/src/BindModule.js +3 -0
  11. package/src/BindModule.js.map +1 -0
  12. package/src/ClassType.d.ts +4 -0
  13. package/src/ClassType.js +3 -0
  14. package/src/ClassType.js.map +1 -0
  15. package/src/LazyController.d.ts +46 -0
  16. package/src/LazyController.js +184 -0
  17. package/src/LazyController.js.map +1 -0
  18. package/src/LazyControllerCompileAssertions.d.ts +14 -0
  19. package/src/LazyControllerCompileAssertions.js +23 -0
  20. package/src/LazyControllerCompileAssertions.js.map +1 -0
  21. package/src/RouteBuilderImpl.d.ts +8 -0
  22. package/src/RouteBuilderImpl.js +51 -5
  23. package/src/RouteBuilderImpl.js.map +1 -1
  24. package/src/RuntimeStartupTiming.d.ts +44 -0
  25. package/src/RuntimeStartupTiming.js +100 -0
  26. package/src/RuntimeStartupTiming.js.map +1 -0
  27. package/src/WebAppMeta.d.ts +6 -4
  28. package/src/WebAppMeta.js +3 -5
  29. package/src/WebAppMeta.js.map +1 -1
  30. package/src/WebpiecesRouter.d.ts +14 -3
  31. package/src/WebpiecesRouter.js +26 -10
  32. package/src/WebpiecesRouter.js.map +1 -1
  33. package/src/Wiring.d.ts +2 -6
  34. package/src/Wiring.js.map +1 -1
  35. package/src/WiringCompileAssertions.d.ts +2 -1
  36. package/src/WiringCompileAssertions.js.map +1 -1
  37. package/src/index.d.ts +7 -2
  38. package/src/index.js +9 -1
  39. package/src/index.js.map +1 -1
  40. package/src/setupRuntime.d.ts +6 -1
  41. package/src/setupRuntime.js +15 -8
  42. package/src/setupRuntime.js.map +1 -1
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RuntimeStartupTiming = exports.RuntimeStartupOperation = exports.RuntimeStartupPhase = void 0;
4
+ const core_util_1 = require("@webpieces/core-util");
5
+ /** Startup operations; durations are inclusive, so nested operations must not be added together. */
6
+ var RuntimeStartupPhase;
7
+ (function (RuntimeStartupPhase) {
8
+ RuntimeStartupPhase["HEADERS"] = "headers";
9
+ RuntimeStartupPhase["LOGGING"] = "logging";
10
+ RuntimeStartupPhase["WIRING"] = "wiring";
11
+ RuntimeStartupPhase["CONTAINER"] = "container";
12
+ RuntimeStartupPhase["FRAMEWORK_DI"] = "framework-di";
13
+ RuntimeStartupPhase["APPLICATION_DI"] = "application-di";
14
+ RuntimeStartupPhase["BIND_MODULE"] = "binding-module";
15
+ RuntimeStartupPhase["FIXED_FILTERS"] = "fixed-filters";
16
+ RuntimeStartupPhase["FILTER"] = "filter-resolution";
17
+ RuntimeStartupPhase["ROUTE_MODULE"] = "route-module";
18
+ RuntimeStartupPhase["ROUTES"] = "route-registration";
19
+ RuntimeStartupPhase["CONTROLLER"] = "controller-resolution";
20
+ })(RuntimeStartupPhase || (exports.RuntimeStartupPhase = RuntimeStartupPhase = {}));
21
+ /** Code identity only: never configuration, credentials, request data or exception payloads. */
22
+ class RuntimeStartupOperation {
23
+ phase;
24
+ name;
25
+ constructor(phase, name) {
26
+ this.phase = phase;
27
+ this.name = name;
28
+ }
29
+ }
30
+ exports.RuntimeStartupOperation = RuntimeStartupOperation;
31
+ /** Internal operation boundary. With no observer it creates no timing records and reads no clock. */
32
+ class RuntimeStartupTiming {
33
+ observer;
34
+ disabled = false;
35
+ constructor(observer) {
36
+ this.observer = observer;
37
+ }
38
+ run(phase, name, operation) {
39
+ const span = this.begin(phase, name);
40
+ let succeeded = false;
41
+ // webpieces-disable no-unmanaged-exceptions -- finally only closes diagnostics; the original application error propagates unchanged
42
+ try {
43
+ const result = operation();
44
+ succeeded = true;
45
+ return result;
46
+ }
47
+ finally {
48
+ this.finish(span, succeeded);
49
+ }
50
+ }
51
+ async runAsync(phase, name, operation) {
52
+ const span = this.begin(phase, name);
53
+ let succeeded = false;
54
+ // webpieces-disable no-unmanaged-exceptions -- finally only closes diagnostics; the original application error propagates unchanged
55
+ try {
56
+ const result = await operation();
57
+ succeeded = true;
58
+ return result;
59
+ }
60
+ finally {
61
+ this.finish(span, succeeded);
62
+ }
63
+ }
64
+ begin(phase, name) {
65
+ if (!this.observer || this.disabled)
66
+ return undefined;
67
+ // webpieces-disable no-unmanaged-exceptions -- an optional observer must not replace startup's result/error; disable it with a bounded bootstrap diagnostic
68
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- diagnostic callback boundary preserves the application result and original error
69
+ try {
70
+ return this.observer.start(new RuntimeStartupOperation(phase, name));
71
+ }
72
+ catch (err) {
73
+ const error = (0, core_util_1.toError)(err);
74
+ this.disabled = true;
75
+ // Headers/logging may not exist yet; use one bootstrap diagnostic for this boundary.
76
+ console.warn('[startup] timing observer disabled after failure', error);
77
+ return undefined;
78
+ }
79
+ }
80
+ finish(span, succeeded) {
81
+ if (!span || this.disabled)
82
+ return;
83
+ // webpieces-disable no-unmanaged-exceptions -- preserve the application's original exception even if diagnostic output fails
84
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- diagnostic callback failure must not replace the original startup exception
85
+ try {
86
+ if (succeeded)
87
+ span.success();
88
+ else
89
+ span.failure();
90
+ }
91
+ catch (err) {
92
+ const error = (0, core_util_1.toError)(err);
93
+ this.disabled = true;
94
+ // Headers/logging may not exist yet; use one bootstrap diagnostic for this boundary.
95
+ console.warn('[startup] timing observer disabled after failure', error);
96
+ }
97
+ }
98
+ }
99
+ exports.RuntimeStartupTiming = RuntimeStartupTiming;
100
+ //# sourceMappingURL=RuntimeStartupTiming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RuntimeStartupTiming.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/RuntimeStartupTiming.ts"],"names":[],"mappings":";;;AAAA,oDAA+C;AAE/C,oGAAoG;AACpG,IAAY,mBAaX;AAbD,WAAY,mBAAmB;IAC3B,0CAAmB,CAAA;IACnB,0CAAmB,CAAA;IACnB,wCAAiB,CAAA;IACjB,8CAAuB,CAAA;IACvB,oDAA6B,CAAA;IAC7B,wDAAiC,CAAA;IACjC,qDAA8B,CAAA;IAC9B,sDAA+B,CAAA;IAC/B,mDAA4B,CAAA;IAC5B,oDAA6B,CAAA;IAC7B,oDAA6B,CAAA;IAC7B,2DAAoC,CAAA;AACxC,CAAC,EAbW,mBAAmB,mCAAnB,mBAAmB,QAa9B;AAED,gGAAgG;AAChG,MAAa,uBAAuB;IAEZ;IACA;IAFpB,YACoB,KAA0B,EAC1B,IAAY;QADZ,UAAK,GAAL,KAAK,CAAqB;QAC1B,SAAI,GAAJ,IAAI,CAAQ;IAC7B,CAAC;CACP;AALD,0DAKC;AAiBD,qGAAqG;AACrG,MAAa,oBAAoB;IAGA;IAFrB,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAA6B,QAAiC;QAAjC,aAAQ,GAAR,QAAQ,CAAyB;IAAG,CAAC;IAElE,GAAG,CAAI,KAA0B,EAAE,IAAY,EAAE,SAAkB;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACrC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,oIAAoI;QACpI,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAC3B,SAAS,GAAG,IAAI,CAAC;YACjB,OAAO,MAAM,CAAC;QAClB,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CACV,KAA0B,EAC1B,IAAY,EACZ,SAA+B;QAE/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACrC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,oIAAoI;QACpI,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,SAAS,GAAG,IAAI,CAAC;YACjB,OAAO,MAAM,CAAC;QAClB,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,KAA0B,EAAE,IAAY;QAClD,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QACtD,4JAA4J;QAC5J,kJAAkJ;QAClJ,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,uBAAuB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,qFAAqF;YACrF,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAC;YACxE,OAAO,SAAS,CAAC;QACrB,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,IAAoC,EAAE,SAAkB;QACnE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QACnC,6HAA6H;QAC7H,6IAA6I;QAC7I,IAAI,CAAC;YACD,IAAI,SAAS;gBAAE,IAAI,CAAC,OAAO,EAAE,CAAC;;gBACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,qFAAqF;YACrF,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAC;QAC5E,CAAC;IACL,CAAC;CACJ;AAhED,oDAgEC","sourcesContent":["import { toError } from '@webpieces/core-util';\n\n/** Startup operations; durations are inclusive, so nested operations must not be added together. */\nexport enum RuntimeStartupPhase {\n HEADERS = 'headers',\n LOGGING = 'logging',\n WIRING = 'wiring',\n CONTAINER = 'container',\n FRAMEWORK_DI = 'framework-di',\n APPLICATION_DI = 'application-di',\n BIND_MODULE = 'binding-module',\n FIXED_FILTERS = 'fixed-filters',\n FILTER = 'filter-resolution',\n ROUTE_MODULE = 'route-module',\n ROUTES = 'route-registration',\n CONTROLLER = 'controller-resolution',\n}\n\n/** Code identity only: never configuration, credentials, request data or exception payloads. */\nexport class RuntimeStartupOperation {\n constructor(\n public readonly phase: RuntimeStartupPhase,\n public readonly name: string,\n ) {}\n}\n\n/** The host owns the monotonic clock/output and closes each started span exactly once. */\nexport interface RuntimeStartupSpan {\n success(): void;\n failure(): void;\n}\n\n/**\n * Optional startup-only diagnostics. Start/finish use the host's clock, so timing requires no SDK.\n * A controller-resolution event measures container.get, including dependencies and singleton reuse;\n * it does not assert that a new controller was constructed. Normal API calls emit no events.\n */\nexport interface RuntimeStartupObserver {\n start(operation: RuntimeStartupOperation): RuntimeStartupSpan;\n}\n\n/** Internal operation boundary. With no observer it creates no timing records and reads no clock. */\nexport class RuntimeStartupTiming {\n private disabled = false;\n\n constructor(private readonly observer?: RuntimeStartupObserver) {}\n\n run<T>(phase: RuntimeStartupPhase, name: string, operation: () => T): T {\n const span = this.begin(phase, name);\n let succeeded = false;\n // webpieces-disable no-unmanaged-exceptions -- finally only closes diagnostics; the original application error propagates unchanged\n try {\n const result = operation();\n succeeded = true;\n return result;\n } finally {\n this.finish(span, succeeded);\n }\n }\n\n async runAsync<T>(\n phase: RuntimeStartupPhase,\n name: string,\n operation: () => T | Promise<T>,\n ): Promise<T> {\n const span = this.begin(phase, name);\n let succeeded = false;\n // webpieces-disable no-unmanaged-exceptions -- finally only closes diagnostics; the original application error propagates unchanged\n try {\n const result = await operation();\n succeeded = true;\n return result;\n } finally {\n this.finish(span, succeeded);\n }\n }\n\n private begin(phase: RuntimeStartupPhase, name: string): RuntimeStartupSpan | undefined {\n if (!this.observer || this.disabled) return undefined;\n // webpieces-disable no-unmanaged-exceptions -- an optional observer must not replace startup's result/error; disable it with a bounded bootstrap diagnostic\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- diagnostic callback boundary preserves the application result and original error\n try {\n return this.observer.start(new RuntimeStartupOperation(phase, name));\n } catch (err: unknown) {\n const error = toError(err);\n this.disabled = true;\n // Headers/logging may not exist yet; use one bootstrap diagnostic for this boundary.\n console.warn('[startup] timing observer disabled after failure', error);\n return undefined;\n }\n }\n\n private finish(span: RuntimeStartupSpan | undefined, succeeded: boolean): void {\n if (!span || this.disabled) return;\n // webpieces-disable no-unmanaged-exceptions -- preserve the application's original exception even if diagnostic output fails\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- diagnostic callback failure must not replace the original startup exception\n try {\n if (succeeded) span.success();\n else span.failure();\n } catch (err: unknown) {\n const error = toError(err);\n this.disabled = true;\n // Headers/logging may not exist yet; use one bootstrap diagnostic for this boundary.\n console.warn('[startup] timing observer disabled after failure', error);\n }\n }\n}\n"]}
@@ -1,4 +1,6 @@
1
- import { RouteMetadata } from "@webpieces/core-util";
1
+ import type { ClassType } from './ClassType';
2
+ import type { LazyController } from './LazyController';
3
+ import { RouteMetadata } from '@webpieces/core-util';
2
4
  /**
3
5
  * Represents a route configuration that can be registered with the router.
4
6
  * Similar to Java WebPieces Routes interface.
@@ -25,10 +27,10 @@ export interface RouteBuilder {
25
27
  */
26
28
  export declare class RouteDefinition {
27
29
  routeMeta: RouteMetadata;
28
- controllerClass: any;
30
+ implementation: ClassType<object> | LazyController<object>;
29
31
  controllerFilepath?: string | undefined;
30
- apiClass?: unknown | undefined;
31
- constructor(routeMeta: RouteMetadata, controllerClass: any, controllerFilepath?: string | undefined, apiClass?: unknown | undefined);
32
+ apiClass?: ClassType<object> | undefined;
33
+ constructor(routeMeta: RouteMetadata, implementation: ClassType<object> | LazyController<object>, controllerFilepath?: string | undefined, apiClass?: ClassType<object> | undefined);
32
34
  }
33
35
  /**
34
36
  * Definition of a filter with priority.
package/src/WebAppMeta.js CHANGED
@@ -9,16 +9,14 @@ exports.FilterDefinition = exports.RouteDefinition = void 0;
9
9
  */
10
10
  class RouteDefinition {
11
11
  routeMeta;
12
- controllerClass;
12
+ implementation;
13
13
  controllerFilepath;
14
14
  apiClass;
15
- constructor(routeMeta,
16
- // webpieces-disable no-any-unknown -- arbitrary DI controller class used as a container token
17
- controllerClass, controllerFilepath,
15
+ constructor(routeMeta, implementation, controllerFilepath,
18
16
  // The @ApiPath prototype this route belongs to; surfaced on ApiFactory.apiClients().
19
17
  apiClass) {
20
18
  this.routeMeta = routeMeta;
21
- this.controllerClass = controllerClass;
19
+ this.implementation = implementation;
22
20
  this.controllerFilepath = controllerFilepath;
23
21
  this.apiClass = apiClass;
24
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebAppMeta.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WebAppMeta.ts"],"names":[],"mappings":";;;AAsBA;;;;;GAKG;AACH,MAAa,eAAe;IAEb;IAEA;IACA;IAEA;IANX,YACW,SAAwB;IAC/B,8FAA8F;IACvF,eAAoB,EACpB,kBAA2B;IAClC,qFAAqF;IAC9E,QAAkB;QALlB,cAAS,GAAT,SAAS,CAAe;QAExB,oBAAe,GAAf,eAAe,CAAK;QACpB,uBAAkB,GAAlB,kBAAkB,CAAS;QAE3B,aAAQ,GAAR,QAAQ,CAAU;IAC1B,CAAC;CACP;AATD,0CASC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAa,gBAAgB;IACzB,QAAQ,CAAS;IACjB,6FAA6F;IAC7F,WAAW,CAAM;IACjB,uFAAuF;IACvF,MAAM,CAAO,CAAC,+DAA+D;IAE7E;;;OAGG;IACH,eAAe,CAAS;IAExB,8FAA8F;IAC9F,YAAY,QAAgB,EAAE,WAAgB,EAAE,eAAuB;QACnE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,4BAA4B;IACzD,CAAC;CACJ;AApBD,4CAoBC;AAGD,0FAA0F;AAC1F,2FAA2F;AAC3F,uGAAuG","sourcesContent":["import {RouteMetadata} from \"@webpieces/core-util\";\n\n/**\n * Represents a route configuration that can be registered with the router.\n * Similar to Java WebPieces Routes interface.\n */\nexport interface Routes {\n /**\n * Configure routes using the provided RouteBuilder.\n */\n configure(routeBuilder: RouteBuilder): void;\n}\n\n/**\n * Builder for registering routes.\n * Will be implemented in http-server package.\n */\nexport interface RouteBuilder {\n addRoute(route: RouteDefinition): void;\n addFilter(filter: FilterDefinition): void;\n}\n\n/**\n * Definition of a single route.\n *\n * Generic type parameter TResult represents the return type of the route handler.\n * This provides type safety for the entire request/response cycle.\n */\nexport class RouteDefinition {\n constructor(\n public routeMeta: RouteMetadata,\n // webpieces-disable no-any-unknown -- arbitrary DI controller class used as a container token\n public controllerClass: any,\n public controllerFilepath?: string,\n // The @ApiPath prototype this route belongs to; surfaced on ApiFactory.apiClients().\n public apiClass?: unknown,\n ) {}\n}\n\n/**\n * Definition of a filter with priority.\n *\n * Use filepathPattern to scope filters to specific controllers:\n * - 'src/controllers/admin/**' + '/*.ts' - All admin controllers\n * - '**' + '/admin/**' - Any file in admin directories\n * - '**' + '/UserController.ts' - Specific controller file\n *\n * If filepathPattern is not specified, the filter matches all controllers.\n *\n * Every filter runs for BOTH real HTTP requests AND the in-process createApiClient — there is\n * no transport tier. Transport-boundary auth is a fixed framework filter (AuthFilter) that\n * reads the transport-neutral HttpRequest, so it runs identically in both.\n */\nexport class FilterDefinition {\n priority: number;\n // webpieces-disable no-any-unknown -- an arbitrary DI filter class used as a container token\n filterClass: any;\n // webpieces-disable no-any-unknown -- the resolved filter instance, of arbitrary shape\n filter?: any; // Filter instance (set by RouteBuilder when resolving from DI)\n\n /**\n * Glob pattern to match controller file paths.\n * If not specified, defaults to matching all controllers.\n */\n filepathPattern: string;\n\n // webpieces-disable no-any-unknown -- filterClass param is an arbitrary DI filter class token\n constructor(priority: number, filterClass: any, filepathPattern: string) {\n this.priority = priority;\n this.filterClass = filterClass;\n this.filepathPattern = filepathPattern;\n this.filter = undefined; // Set later by RouteBuilder\n }\n}\n\n\n// The old WebAppMeta interface + WEBAPP_META_TOKEN were removed with the WebpiecesServer/\n// WebpiecesFactory flip. Apps now configure routes/filters imperatively on WebpiecesRouter\n// (see WebpiecesRouter.addRoutes/addFilter) instead of implementing WebAppMeta.getDIModules/getRoutes.\n"]}
1
+ {"version":3,"file":"WebAppMeta.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WebAppMeta.ts"],"names":[],"mappings":";;;AAwBA;;;;;GAKG;AACH,MAAa,eAAe;IAEb;IACA;IACA;IAEA;IALX,YACW,SAAwB,EACxB,cAA0D,EAC1D,kBAA2B;IAClC,qFAAqF;IAC9E,QAA4B;QAJ5B,cAAS,GAAT,SAAS,CAAe;QACxB,mBAAc,GAAd,cAAc,CAA4C;QAC1D,uBAAkB,GAAlB,kBAAkB,CAAS;QAE3B,aAAQ,GAAR,QAAQ,CAAoB;IACpC,CAAC;CACP;AARD,0CAQC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAa,gBAAgB;IACzB,QAAQ,CAAS;IACjB,6FAA6F;IAC7F,WAAW,CAAM;IACjB,uFAAuF;IACvF,MAAM,CAAO,CAAC,+DAA+D;IAE7E;;;OAGG;IACH,eAAe,CAAS;IAExB,8FAA8F;IAC9F,YAAY,QAAgB,EAAE,WAAgB,EAAE,eAAuB;QACnE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,4BAA4B;IACzD,CAAC;CACJ;AApBD,4CAoBC;AAED,0FAA0F;AAC1F,2FAA2F;AAC3F,uGAAuG","sourcesContent":["import type { ClassType } from './ClassType';\nimport type { LazyController } from './LazyController';\nimport { RouteMetadata } from '@webpieces/core-util';\n\n/**\n * Represents a route configuration that can be registered with the router.\n * Similar to Java WebPieces Routes interface.\n */\nexport interface Routes {\n /**\n * Configure routes using the provided RouteBuilder.\n */\n configure(routeBuilder: RouteBuilder): void;\n}\n\n/**\n * Builder for registering routes.\n * Will be implemented in http-server package.\n */\nexport interface RouteBuilder {\n addRoute(route: RouteDefinition): void;\n addFilter(filter: FilterDefinition): void;\n}\n\n/**\n * Definition of a single route.\n *\n * Generic type parameter TResult represents the return type of the route handler.\n * This provides type safety for the entire request/response cycle.\n */\nexport class RouteDefinition {\n constructor(\n public routeMeta: RouteMetadata,\n public implementation: ClassType<object> | LazyController<object>,\n public controllerFilepath?: string,\n // The @ApiPath prototype this route belongs to; surfaced on ApiFactory.apiClients().\n public apiClass?: ClassType<object>,\n ) {}\n}\n\n/**\n * Definition of a filter with priority.\n *\n * Use filepathPattern to scope filters to specific controllers:\n * - 'src/controllers/admin/**' + '/*.ts' - All admin controllers\n * - '**' + '/admin/**' - Any file in admin directories\n * - '**' + '/UserController.ts' - Specific controller file\n *\n * If filepathPattern is not specified, the filter matches all controllers.\n *\n * Every filter runs for BOTH real HTTP requests AND the in-process createApiClient — there is\n * no transport tier. Transport-boundary auth is a fixed framework filter (AuthFilter) that\n * reads the transport-neutral HttpRequest, so it runs identically in both.\n */\nexport class FilterDefinition {\n priority: number;\n // webpieces-disable no-any-unknown -- an arbitrary DI filter class used as a container token\n filterClass: any;\n // webpieces-disable no-any-unknown -- the resolved filter instance, of arbitrary shape\n filter?: any; // Filter instance (set by RouteBuilder when resolving from DI)\n\n /**\n * Glob pattern to match controller file paths.\n * If not specified, defaults to matching all controllers.\n */\n filepathPattern: string;\n\n // webpieces-disable no-any-unknown -- filterClass param is an arbitrary DI filter class token\n constructor(priority: number, filterClass: any, filepathPattern: string) {\n this.priority = priority;\n this.filterClass = filterClass;\n this.filepathPattern = filepathPattern;\n this.filter = undefined; // Set later by RouteBuilder\n }\n}\n\n// The old WebAppMeta interface + WEBAPP_META_TOKEN were removed with the WebpiecesServer/\n// WebpiecesFactory flip. Apps now configure routes/filters imperatively on WebpiecesRouter\n// (see WebpiecesRouter.addRoutes/addFilter) instead of implementing WebAppMeta.getDIModules/getRoutes.\n"]}
@@ -1,13 +1,15 @@
1
+ import { LazyController } from './LazyController';
1
2
  import { AuthorizationService } from './AuthorizationHook';
2
3
  import { InvocationAuthentication } from './InvocationAuthentication';
3
4
  import { Container, ContainerModule } from 'inversify';
4
5
  import { RouteBuilderImpl } from './RouteBuilderImpl';
5
- import { ClassType } from './ApiRoutingFactory';
6
+ import type { ClassType } from './ClassType';
6
7
  import { FilterDefinition } from './WebAppMeta';
7
8
  import { WebpiecesConfig } from './WebpiecesConfig';
8
9
  import { ApiClientFactory } from './ApiClientFactory';
9
10
  import { ApiFactory } from './ApiFactory';
10
11
  import { ApiClient } from './ApiClient';
12
+ import { RuntimeStartupObserver } from './RuntimeStartupTiming';
11
13
  /**
12
14
  * Options for {@link WebpiecesRouterFactory.create} — one object (config lives inside it).
13
15
  *
@@ -21,6 +23,8 @@ export interface WebpiecesRouterOptions {
21
23
  appBindings: ContainerModule[];
22
24
  appOverrides?: ContainerModule;
23
25
  config?: WebpiecesConfig;
26
+ /** Optional startup spans; no observer means no clock or timing-output work. */
27
+ startupObserver?: RuntimeStartupObserver;
24
28
  }
25
29
  /**
26
30
  * WebpiecesRouter - the node-only heart of a webpieces app: a DI container + a filter
@@ -58,6 +62,7 @@ export declare class WebpiecesRouter implements ApiFactory {
58
62
  private readonly apiClientFactory;
59
63
  private webpiecesContainer;
60
64
  private appContainer;
65
+ private startupTiming;
61
66
  constructor(routeBuilder: RouteBuilderImpl, apiClientFactory: ApiClientFactory);
62
67
  /**
63
68
  * Build the app container (child of the framework container), load the @provideSingleton
@@ -77,9 +82,10 @@ export declare class WebpiecesRouter implements ApiFactory {
77
82
  private loadDIModules;
78
83
  /**
79
84
  * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller.
80
- * The controller is resolved from the container at request time.
85
+ * A class resolves eagerly. A LazyController retains metadata now and imports its implementation
86
+ * only after the ordinary filter chain permits an invocation.
81
87
  */
82
- addRoutes<TApi, TController extends TApi>(api: ClassType<TApi>, controller: ClassType<TController>): this;
88
+ addRoutes<TApi extends object, TController extends TApi>(api: ClassType<TApi>, controller: ClassType<TController> | LazyController<TController>): this;
83
89
  /**
84
90
  * Register a user filter (runs in-process AND over HTTP, below the auto-installed fixed
85
91
  * LogApiFilter + AuthFilter).
@@ -99,6 +105,11 @@ export declare class WebpiecesRouter implements ApiFactory {
99
105
  */
100
106
  apiClients(): ApiClient[];
101
107
  authorizationService(): AuthorizationService;
108
+ /**
109
+ * Warm and validate every optional implementation in a SEPARATE build/integration process with
110
+ * fake external providers. Never invoke this in the production entry point or from a request.
111
+ */
112
+ validateLazyRoutesForBuild(): Promise<void>;
102
113
  /** The application DI container (child of the framework container). */
103
114
  getContainer(): Container;
104
115
  }
@@ -15,6 +15,7 @@ const ApiClientFactory_1 = require("./ApiClientFactory");
15
15
  const LogApiFilter_1 = require("./filters/LogApiFilter");
16
16
  const AuthFilter_1 = require("./filters/AuthFilter");
17
17
  const AuthorizationFilter_1 = require("./filters/AuthorizationFilter");
18
+ const RuntimeStartupTiming_1 = require("./RuntimeStartupTiming");
18
19
  /**
19
20
  * WebpiecesRouter - the node-only heart of a webpieces app: a DI container + a filter
20
21
  * chain + an in-process API client. It has NO express dependency, so it runs anywhere
@@ -51,6 +52,7 @@ let WebpiecesRouter = class WebpiecesRouter {
51
52
  apiClientFactory;
52
53
  webpiecesContainer;
53
54
  appContainer;
55
+ startupTiming = new RuntimeStartupTiming_1.RuntimeStartupTiming();
54
56
  constructor(routeBuilder, apiClientFactory) {
55
57
  this.routeBuilder = routeBuilder;
56
58
  this.apiClientFactory = apiClientFactory;
@@ -62,6 +64,8 @@ let WebpiecesRouter = class WebpiecesRouter {
62
64
  */
63
65
  async initialize(webpiecesContainer, options) {
64
66
  this.webpiecesContainer = webpiecesContainer;
67
+ this.startupTiming = new RuntimeStartupTiming_1.RuntimeStartupTiming(options.startupObserver);
68
+ this.routeBuilder.setStartupObserver(options.startupObserver);
65
69
  // App container is a child so app bindings see framework bindings while staying separate.
66
70
  // autobind:true lets a concrete @injectable(Singleton) app class self-bind on first resolve
67
71
  // (inject-by-type, no @provideSingleton). Framework singletons stay explicit in the parent
@@ -69,7 +73,7 @@ let WebpiecesRouter = class WebpiecesRouter {
69
73
  this.appContainer = new inversify_1.Container({ parent: webpiecesContainer, autobind: true });
70
74
  this.routeBuilder.setContainer(this.appContainer);
71
75
  await this.loadDIModules(options);
72
- this.installFixedFilters();
76
+ this.startupTiming.run(RuntimeStartupTiming_1.RuntimeStartupPhase.FIXED_FILTERS, 'fixed-filters', () => this.installFixedFilters());
73
77
  }
74
78
  /**
75
79
  * Auto-install the two fixed framework filters on every route (apps add only their own
@@ -88,24 +92,26 @@ let WebpiecesRouter = class WebpiecesRouter {
88
92
  // Load BOTH registries: framework classes (provideFrameworkSingleton) + the client's
89
93
  // own @provideSingleton classes (binding-decorators global). A client's
90
94
  // buildProviderModule() only ever contains the client's classes — never framework internals.
91
- await this.appContainer.load((0, core_context_1.buildFrameworkModule)());
92
- await this.appContainer.load((0, binding_decorators_1.buildProviderModule)());
95
+ await this.startupTiming.runAsync(RuntimeStartupTiming_1.RuntimeStartupPhase.FRAMEWORK_DI, 'application-framework-bindings', () => this.appContainer.load((0, core_context_1.buildFrameworkModule)()));
96
+ await this.startupTiming.runAsync(RuntimeStartupTiming_1.RuntimeStartupPhase.APPLICATION_DI, 'provider-bindings', () => this.appContainer.load((0, binding_decorators_1.buildProviderModule)()));
93
97
  // Load all app modules into application container
94
98
  // (webpiecesContainer is currently empty, reserved for future framework bindings)
95
- for (const module of options.appBindings) {
96
- await this.appContainer.load(module);
99
+ for (const [index, module] of options.appBindings.entries()) {
100
+ await this.startupTiming.runAsync(RuntimeStartupTiming_1.RuntimeStartupPhase.APPLICATION_DI, `app-binding-${index}`, () => this.appContainer.load(module));
97
101
  }
98
102
  // Load appOverrides LAST so they can override existing bindings
99
103
  if (options.appOverrides) {
100
- await this.appContainer.load(options.appOverrides);
104
+ const overrides = options.appOverrides;
105
+ await this.startupTiming.runAsync(RuntimeStartupTiming_1.RuntimeStartupPhase.APPLICATION_DI, 'app-overrides', () => this.appContainer.load(overrides));
101
106
  }
102
107
  }
103
108
  /**
104
109
  * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller.
105
- * The controller is resolved from the container at request time.
110
+ * A class resolves eagerly. A LazyController retains metadata now and imports its implementation
111
+ * only after the ordinary filter chain permits an invocation.
106
112
  */
107
113
  addRoutes(api, controller) {
108
- new ApiRoutingFactory_1.ApiRoutingFactory(api, controller).configure(this.routeBuilder);
114
+ this.startupTiming.run(RuntimeStartupTiming_1.RuntimeStartupPhase.ROUTES, `${api.name}:${controller.name}`, () => new ApiRoutingFactory_1.ApiRoutingFactory(api, controller).configure(this.routeBuilder));
109
115
  return this;
110
116
  }
111
117
  /**
@@ -140,6 +146,15 @@ let WebpiecesRouter = class WebpiecesRouter {
140
146
  authorizationService() {
141
147
  return this.appContainer.get(AuthorizationHook_1.AuthorizationService);
142
148
  }
149
+ /**
150
+ * Warm and validate every optional implementation in a SEPARATE build/integration process with
151
+ * fake external providers. Never invoke this in the production entry point or from a request.
152
+ */
153
+ async validateLazyRoutesForBuild() {
154
+ if (core_context_1.RequestContext.isActive())
155
+ throw new Error('Lazy implementation build validation cannot run inside a request.');
156
+ await this.routeBuilder.validateLazyRoutesForBuild();
157
+ }
143
158
  /** The application DI container (child of the framework container). */
144
159
  getContainer() {
145
160
  return this.appContainer;
@@ -164,13 +179,14 @@ class WebpiecesRouterFactory {
164
179
  // Platform (framework) container — build via buildFrameworkModule so framework
165
180
  // singletons (WebpiecesRouter, RouteBuilderImpl) come from the webpieces registry,
166
181
  // NOT the client's global one.
182
+ const timing = new RuntimeStartupTiming_1.RuntimeStartupTiming(options.startupObserver);
167
183
  const webpiecesContainer = new inversify_1.Container();
168
184
  webpiecesContainer
169
185
  .bind(WebpiecesConfig_1.WEBPIECES_CONFIG_TOKEN)
170
186
  .toConstantValue(options.config ?? new WebpiecesConfig_1.WebpiecesConfig());
171
- await webpiecesContainer.load((0, core_context_1.buildFrameworkModule)());
187
+ await timing.runAsync(RuntimeStartupTiming_1.RuntimeStartupPhase.FRAMEWORK_DI, 'platform-framework-bindings', () => webpiecesContainer.load((0, core_context_1.buildFrameworkModule)()));
172
188
  // Resolve the router from the container (NOT new'd) so @DocumentDesign + DI hold.
173
- const router = webpiecesContainer.get(WebpiecesRouter);
189
+ const router = timing.run(RuntimeStartupTiming_1.RuntimeStartupPhase.FRAMEWORK_DI, 'router-resolution', () => webpiecesContainer.get(WebpiecesRouter));
174
190
  await router.initialize(webpiecesContainer, options);
175
191
  return router;
176
192
  }
@@ -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 { AuthorizationService } from './AuthorizationHook';\nimport { InvocationAuthentication } from './InvocationAuthentication';\nimport { 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 { ApiClientFactory } from './ApiClientFactory';\nimport { ApiFactory } from './ApiFactory';\nimport { ApiClient } from './ApiClient';\nimport { LogApiFilter } from './filters/LogApiFilter';\nimport { AuthFilter } from './filters/AuthFilter';\nimport { AuthorizationFilter } from './filters/AuthorizationFilter';\n\n/**\n * Options for {@link WebpiecesRouterFactory.create} — one object (config lives inside it).\n *\n * appBindings - DI ContainerModules to load (framework + app). 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 * config - Optional {@link WebpiecesConfig} (recording flags, etc.); defaults to a fresh one.\n */\nexport interface WebpiecesRouterOptions {\n appBindings: ContainerModule[];\n appOverrides?: ContainerModule;\n config?: WebpiecesConfig;\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({ appBindings: [AppModule] });\n * router.addRoutes(SaveApi, SaveController);\n * router.addFilter(new FilterDefinition(1800, MyFilter, '*')); // your own filters\n * // (LogApiFilter + AuthFilter are auto-installed above yours; auth is AuthMode-driven.\n * // LogApiFilter logs request+response for EVERY call — do NOT install it yourself.)\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 @inject(ApiClientFactory) private readonly apiClientFactory: ApiClientFactory,\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(\n webpiecesContainer: Container,\n options: WebpiecesRouterOptions,\n ): Promise<void> {\n this.webpiecesContainer = webpiecesContainer;\n\n // App container is a child so app bindings see framework bindings while staying separate.\n // autobind:true lets a concrete @injectable(Singleton) app class self-bind on first resolve\n // (inject-by-type, no @provideSingleton). Framework singletons stay explicit in the parent\n // (provideFrameworkSingleton -> buildFrameworkModule), found before child-autobind kicks in.\n this.appContainer = new Container({ parent: webpiecesContainer, autobind: true });\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): LogApiFilter outermost (logs request + response/failure for every\n * call and stamps [Controller.method], then re-throws for the transport to 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. Because LogApiFilter is outermost, requests that\n * AuthFilter rejects (401) are still logged with their body + controller identity.\n */\n private installFixedFilters(): void {\n this.addFilter(new FilterDefinition(1_000_000, LogApiFilter, '*'));\n this.addFilter(new FilterDefinition(900_000, AuthFilter, '*'));\n this.addFilter(new FilterDefinition(800_000, AuthorizationFilter, '*'));\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 app 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 * LogApiFilter + 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 this.apiClientFactory.createApiClient(apiPrototype);\n }\n\n /** Transport-only credential bridge; ordinary endpoint filters remain mandatory. */\n // webpieces-disable no-any-unknown -- abstract API constructor signature\n createInvocationApiClient<T>(\n apiPrototype: abstract new (...args: any[]) => T,\n authentication: InvocationAuthentication,\n ): T {\n return this.apiClientFactory.createInvocationApiClient(apiPrototype, authentication);\n }\n\n /**\n * Reify the registered APIs as {@link ApiClient}s (contract + the createApiClient proxy) via\n * the shared {@link ApiClientFactory}. This is the ONLY handoff to the express layer — the\n * internal RouteBuilder never leaves.\n */\n apiClients(): ApiClient[] {\n return this.apiClientFactory.apiClients();\n }\n\n authorizationService(): AuthorizationService {\n return this.appContainer.get(AuthorizationService);\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(options: WebpiecesRouterOptions): 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\n .bind(WEBPIECES_CONFIG_TOKEN)\n .toConstantValue(options.config ?? new WebpiecesConfig());\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 { LazyController } from './LazyController';\nimport { AuthorizationService } from './AuthorizationHook';\nimport { InvocationAuthentication } from './InvocationAuthentication';\nimport { Container, ContainerModule, inject } from 'inversify';\nimport { buildProviderModule } from '@inversifyjs/binding-decorators';\nimport { DocumentDesign } from '@webpieces/core-util';\nimport {\n provideFrameworkSingleton,\n buildFrameworkModule,\n RequestContext,\n} from '@webpieces/core-context';\nimport { RouteBuilderImpl } from './RouteBuilderImpl';\nimport { ApiRoutingFactory } from './ApiRoutingFactory';\nimport type { ClassType } from './ClassType';\nimport { FilterDefinition } from './WebAppMeta';\nimport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\nimport { ApiClientFactory } from './ApiClientFactory';\nimport { ApiFactory } from './ApiFactory';\nimport { ApiClient } from './ApiClient';\nimport { LogApiFilter } from './filters/LogApiFilter';\nimport { AuthFilter } from './filters/AuthFilter';\nimport { AuthorizationFilter } from './filters/AuthorizationFilter';\nimport {\n RuntimeStartupObserver,\n RuntimeStartupPhase,\n RuntimeStartupTiming,\n} from './RuntimeStartupTiming';\n\n/**\n * Options for {@link WebpiecesRouterFactory.create} — one object (config lives inside it).\n *\n * appBindings - DI ContainerModules to load (framework + app). 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 * config - Optional {@link WebpiecesConfig} (recording flags, etc.); defaults to a fresh one.\n */\nexport interface WebpiecesRouterOptions {\n appBindings: ContainerModule[];\n appOverrides?: ContainerModule;\n config?: WebpiecesConfig;\n /** Optional startup spans; no observer means no clock or timing-output work. */\n startupObserver?: RuntimeStartupObserver;\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({ appBindings: [AppModule] });\n * router.addRoutes(SaveApi, SaveController);\n * router.addFilter(new FilterDefinition(1800, MyFilter, '*')); // your own filters\n * // (LogApiFilter + AuthFilter are auto-installed above yours; auth is AuthMode-driven.\n * // LogApiFilter logs request+response for EVERY call — do NOT install it yourself.)\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 private startupTiming = new RuntimeStartupTiming();\n\n constructor(\n @inject(RouteBuilderImpl) private readonly routeBuilder: RouteBuilderImpl,\n @inject(ApiClientFactory) private readonly apiClientFactory: ApiClientFactory,\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(\n webpiecesContainer: Container,\n options: WebpiecesRouterOptions,\n ): Promise<void> {\n this.webpiecesContainer = webpiecesContainer;\n this.startupTiming = new RuntimeStartupTiming(options.startupObserver);\n this.routeBuilder.setStartupObserver(options.startupObserver);\n\n // App container is a child so app bindings see framework bindings while staying separate.\n // autobind:true lets a concrete @injectable(Singleton) app class self-bind on first resolve\n // (inject-by-type, no @provideSingleton). Framework singletons stay explicit in the parent\n // (provideFrameworkSingleton -> buildFrameworkModule), found before child-autobind kicks in.\n this.appContainer = new Container({ parent: webpiecesContainer, autobind: true });\n this.routeBuilder.setContainer(this.appContainer);\n\n await this.loadDIModules(options);\n this.startupTiming.run(RuntimeStartupPhase.FIXED_FILTERS, 'fixed-filters', () =>\n this.installFixedFilters(),\n );\n }\n\n /**\n * Auto-install the two fixed framework filters on every route (apps add only their own\n * filters below these): LogApiFilter outermost (logs request + response/failure for every\n * call and stamps [Controller.method], then re-throws for the transport to 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. Because LogApiFilter is outermost, requests that\n * AuthFilter rejects (401) are still logged with their body + controller identity.\n */\n private installFixedFilters(): void {\n this.addFilter(new FilterDefinition(1_000_000, LogApiFilter, '*'));\n this.addFilter(new FilterDefinition(900_000, AuthFilter, '*'));\n this.addFilter(new FilterDefinition(800_000, AuthorizationFilter, '*'));\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.startupTiming.runAsync(\n RuntimeStartupPhase.FRAMEWORK_DI,\n 'application-framework-bindings',\n () => this.appContainer.load(buildFrameworkModule()),\n );\n await this.startupTiming.runAsync(\n RuntimeStartupPhase.APPLICATION_DI,\n 'provider-bindings',\n () => this.appContainer.load(buildProviderModule()),\n );\n\n // Load all app modules into application container\n // (webpiecesContainer is currently empty, reserved for future framework bindings)\n for (const [index, module] of options.appBindings.entries()) {\n await this.startupTiming.runAsync(\n RuntimeStartupPhase.APPLICATION_DI,\n `app-binding-${index}`,\n () => this.appContainer.load(module),\n );\n }\n\n // Load appOverrides LAST so they can override existing bindings\n if (options.appOverrides) {\n const overrides = options.appOverrides;\n await this.startupTiming.runAsync(\n RuntimeStartupPhase.APPLICATION_DI,\n 'app-overrides',\n () => this.appContainer.load(overrides),\n );\n }\n }\n\n /**\n * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller.\n * A class resolves eagerly. A LazyController retains metadata now and imports its implementation\n * only after the ordinary filter chain permits an invocation.\n */\n addRoutes<TApi extends object, TController extends TApi>(\n api: ClassType<TApi>,\n controller: ClassType<TController> | LazyController<TController>,\n ): this {\n this.startupTiming.run(RuntimeStartupPhase.ROUTES, `${api.name}:${controller.name}`, () =>\n new ApiRoutingFactory(api, controller).configure(this.routeBuilder),\n );\n return this;\n }\n\n /**\n * Register a user filter (runs in-process AND over HTTP, below the auto-installed fixed\n * LogApiFilter + 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 this.apiClientFactory.createApiClient(apiPrototype);\n }\n\n /** Transport-only credential bridge; ordinary endpoint filters remain mandatory. */\n // webpieces-disable no-any-unknown -- abstract API constructor signature\n createInvocationApiClient<T>(\n apiPrototype: abstract new (...args: any[]) => T,\n authentication: InvocationAuthentication,\n ): T {\n return this.apiClientFactory.createInvocationApiClient(apiPrototype, authentication);\n }\n\n /**\n * Reify the registered APIs as {@link ApiClient}s (contract + the createApiClient proxy) via\n * the shared {@link ApiClientFactory}. This is the ONLY handoff to the express layer — the\n * internal RouteBuilder never leaves.\n */\n apiClients(): ApiClient[] {\n return this.apiClientFactory.apiClients();\n }\n\n authorizationService(): AuthorizationService {\n return this.appContainer.get(AuthorizationService);\n }\n\n /**\n * Warm and validate every optional implementation in a SEPARATE build/integration process with\n * fake external providers. Never invoke this in the production entry point or from a request.\n */\n async validateLazyRoutesForBuild(): Promise<void> {\n if (RequestContext.isActive())\n throw new Error('Lazy implementation build validation cannot run inside a request.');\n await this.routeBuilder.validateLazyRoutesForBuild();\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(options: WebpiecesRouterOptions): 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 timing = new RuntimeStartupTiming(options.startupObserver);\n const webpiecesContainer = new Container();\n webpiecesContainer\n .bind(WEBPIECES_CONFIG_TOKEN)\n .toConstantValue(options.config ?? new WebpiecesConfig());\n await timing.runAsync(RuntimeStartupPhase.FRAMEWORK_DI, 'platform-framework-bindings', () =>\n webpiecesContainer.load(buildFrameworkModule()),\n );\n\n // Resolve the router from the container (NOT new'd) so @DocumentDesign + DI hold.\n const router = timing.run(RuntimeStartupPhase.FRAMEWORK_DI, 'router-resolution', () =>\n webpiecesContainer.get(WebpiecesRouter),\n );\n await router.initialize(webpiecesContainer, options);\n return router;\n }\n}\n"]}
package/src/Wiring.d.ts CHANGED
@@ -1,11 +1,7 @@
1
1
  import type { AnyContextKey } from '@webpieces/core-util';
2
- import type { BindModule as HostBindModule, Wiring as HostWiring, AppWiring as HostAppWiring } from '@webpieces/http-client-core';
3
- import type { Binder } from './Binder';
2
+ import type { Wiring as HostWiring, AppWiring as HostAppWiring } from '@webpieces/http-client-core';
3
+ import type { BindModule } from './BindModule';
4
4
  import type { WebpiecesRouter } from './WebpiecesRouter';
5
- /** Named DI declaration. setupRuntime hands it the Node {@link Binder} over one Inversify load. */
6
- export interface BindModule extends HostBindModule<Binder> {
7
- configure(binder: Binder): void | Promise<void>;
8
- }
9
5
  /** api -> controller routes and filters. Node-only: only a server has routes. */
10
6
  export interface RouteModule {
11
7
  configure(router: WebpiecesRouter): void;
package/src/Wiring.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Wiring.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/Wiring.ts"],"names":[],"mappings":";;;AAMA,kEAA0D;AAuB1D,iFAAiF;AACjF,MAAa,iBAAiB;IACjB,WAAW,CAAe;IAC1B,YAAY,CAAgB;IAErC,YAAY,GAAc;QACtB,MAAM,KAAK,GAAG,IAAI,8BAAW,CAAS,GAAG,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;IACpF,CAAC;CACJ;AATD,8CASC","sourcesContent":["import type { AnyContextKey } from '@webpieces/core-util';\nimport type {\n BindModule as HostBindModule,\n Wiring as HostWiring,\n AppWiring as HostAppWiring,\n} from '@webpieces/http-client-core';\nimport { WiringOrder } from '@webpieces/http-client-core';\nimport type { Binder } from './Binder';\nimport type { WebpiecesRouter } from './WebpiecesRouter';\n\n/** Named DI declaration. setupRuntime hands it the Node {@link Binder} over one Inversify load. */\nexport interface BindModule extends HostBindModule<Binder> {\n configure(binder: Binder): void | Promise<void>;\n}\n\n/** api -> controller routes and filters. Node-only: only a server has routes. */\nexport interface RouteModule {\n configure(router: WebpiecesRouter): void;\n}\n\nexport interface Wiring extends HostWiring<BindModule> {\n getRouteModules(): RouteModule[];\n}\n\n/** Applications retain ownership of their server context headers. */\nexport interface AppWiring extends HostAppWiring<BindModule, Wiring>, Wiring {\n getHeaders(): AnyContextKey[];\n}\n\n/** The app's modules first, then each selected library's, in selection order. */\nexport class NodeWiringModules {\n readonly bindModules: BindModule[];\n readonly routeModules: RouteModule[];\n\n constructor(app: AppWiring) {\n const order = new WiringOrder<Wiring>(app, app.getWirings());\n this.bindModules = order.collect((wiring: Wiring) => wiring.getBindModules());\n this.routeModules = order.collect((wiring: Wiring) => wiring.getRouteModules());\n }\n}\n"]}
1
+ {"version":3,"file":"Wiring.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/Wiring.ts"],"names":[],"mappings":";;;AAEA,kEAA0D;AAkB1D,iFAAiF;AACjF,MAAa,iBAAiB;IACjB,WAAW,CAAe;IAC1B,YAAY,CAAgB;IAErC,YAAY,GAAc;QACtB,MAAM,KAAK,GAAG,IAAI,8BAAW,CAAS,GAAG,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;IACpF,CAAC;CACJ;AATD,8CASC","sourcesContent":["import type { AnyContextKey } from '@webpieces/core-util';\nimport type { Wiring as HostWiring, AppWiring as HostAppWiring } from '@webpieces/http-client-core';\nimport { WiringOrder } from '@webpieces/http-client-core';\nimport type { BindModule } from './BindModule';\nimport type { WebpiecesRouter } from './WebpiecesRouter';\n\n/** api -> controller routes and filters. Node-only: only a server has routes. */\nexport interface RouteModule {\n configure(router: WebpiecesRouter): void;\n}\n\nexport interface Wiring extends HostWiring<BindModule> {\n getRouteModules(): RouteModule[];\n}\n\n/** Applications retain ownership of their server context headers. */\nexport interface AppWiring extends HostAppWiring<BindModule, Wiring>, Wiring {\n getHeaders(): AnyContextKey[];\n}\n\n/** The app's modules first, then each selected library's, in selection order. */\nexport class NodeWiringModules {\n readonly bindModules: BindModule[];\n readonly routeModules: RouteModule[];\n\n constructor(app: AppWiring) {\n const order = new WiringOrder<Wiring>(app, app.getWirings());\n this.bindModules = order.collect((wiring: Wiring) => wiring.getBindModules());\n this.routeModules = order.collect((wiring: Wiring) => wiring.getRouteModules());\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
- import type { AppWiring, BindModule, RouteModule, Wiring } from './Wiring';
1
+ import type { AppWiring, RouteModule, Wiring } from './Wiring';
2
+ import type { BindModule } from './BindModule';
2
3
  import type { Binder } from './Binder';
3
4
  /** Checked by tsc, never invoked; vitest strips types, so these guarantees live in compiled source. */
4
5
  export declare class WiringCompileAssertions {
@@ -1 +1 @@
1
- {"version":3,"file":"WiringCompileAssertions.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WiringCompileAssertions.ts"],"names":[],"mappings":";;;AAEA,qCAAgE;AAEhE,MAAe,SAAS;CAEvB;AACD,MAAe,SAAS;CAEvB;AACD,MAAM,YAAa,SAAQ,SAAS;IAChC,IAAI;QACA,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ;AAED,uGAAuG;AACvG,MAAa,uBAAuB;IAChC,KAAK,CAAC,OAAmB,EAAE,OAAoB;QAC3C,6DAA6D;QAC7D,MAAM,cAAc,GAAe,OAAO,CAAC;QAC3C,4DAA4D;QAC5D,MAAM,YAAY,GAAgB,OAAO,CAAC;QAC1C,KAAK,cAAc,CAAC;QACpB,KAAK,YAAY,CAAC;IACtB,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,GAAc;QACnC,+EAA+E;QAC/E,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3B,+EAA+E;QAC/E,GAAG,CAAC,iBAAiB,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,OAAe;QAClC,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACpD,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,0BAAiB,CAAY,OAAO,CAAC,CAAC,CAAC;QAC/F,0DAA0D;QAC1D,MAAM,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QACzC,kFAAkF;QAClF,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,0BAAiB,CAAY,OAAO,CAAC,CAAC,CAAC;QAClG,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC7C,mFAAmF;QACnF,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;CACJ;AA7BD,0DA6BC","sourcesContent":["import type { AppWiring, BindModule, RouteModule, Wiring } from './Wiring';\nimport type { Binder } from './Binder';\nimport { ClientBindOptions, PubSubBindOptions } from './Binder';\n\nabstract class StringApi {\n abstract read(): string;\n}\nabstract class NumberApi {\n abstract read(): number;\n}\nclass StringClient extends StringApi {\n read(): string {\n return 'value';\n }\n}\n\n/** Checked by tsc, never invoked; vitest strips types, so these guarantees live in compiled source. */\nexport class WiringCompileAssertions {\n check(binding: BindModule, routing: RouteModule): void {\n // @ts-expect-error A route module cannot configure a binder.\n const invalidBinding: BindModule = routing;\n // @ts-expect-error A bind module cannot configure a router.\n const invalidRoute: RouteModule = binding;\n void invalidBinding;\n void invalidRoute;\n }\n\n channels(wiring: Wiring, app: AppWiring): void {\n // @ts-expect-error The getters were renamed: getBindModules / getRouteModules.\n wiring.getBindingModules();\n // @ts-expect-error The getters were renamed: getBindModules / getRouteModules.\n app.getRoutingModules();\n }\n\n binder(binder: Binder, strings: symbol): void {\n binder.createRpcClientAndBind(StringApi, 'strings');\n binder.createRpcClientAndBind(StringApi, 'strings', new ClientBindOptions<StringApi>(strings));\n // @ts-expect-error The deployment is a required argument.\n binder.createRpcClientAndBind(StringApi);\n // @ts-expect-error Destination wrappers were removed; pass the deployment string.\n binder.createRpcClientAndBind(StringApi, { serviceName: 'strings' });\n binder.createPubSubClientAndBind(StringApi, 'strings', new PubSubBindOptions<StringApi>(strings));\n binder.bindExternal(StringApi, StringClient);\n // @ts-expect-error The vendor implementation must implement the external contract.\n binder.bindExternal(NumberApi, StringClient);\n }\n}\n"]}
1
+ {"version":3,"file":"WiringCompileAssertions.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/WiringCompileAssertions.ts"],"names":[],"mappings":";;;AAGA,qCAAgE;AAEhE,MAAe,SAAS;CAEvB;AACD,MAAe,SAAS;CAEvB;AACD,MAAM,YAAa,SAAQ,SAAS;IAChC,IAAI;QACA,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ;AAED,uGAAuG;AACvG,MAAa,uBAAuB;IAChC,KAAK,CAAC,OAAmB,EAAE,OAAoB;QAC3C,6DAA6D;QAC7D,MAAM,cAAc,GAAe,OAAO,CAAC;QAC3C,4DAA4D;QAC5D,MAAM,YAAY,GAAgB,OAAO,CAAC;QAC1C,KAAK,cAAc,CAAC;QACpB,KAAK,YAAY,CAAC;IACtB,CAAC;IAED,QAAQ,CAAC,MAAc,EAAE,GAAc;QACnC,+EAA+E;QAC/E,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3B,+EAA+E;QAC/E,GAAG,CAAC,iBAAiB,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,MAAc,EAAE,OAAe;QAClC,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACpD,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,0BAAiB,CAAY,OAAO,CAAC,CAAC,CAAC;QAC/F,0DAA0D;QAC1D,MAAM,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QACzC,kFAAkF;QAClF,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,0BAAiB,CAAY,OAAO,CAAC,CAAC,CAAC;QAClG,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC7C,mFAAmF;QACnF,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;CACJ;AA7BD,0DA6BC","sourcesContent":["import type { AppWiring, RouteModule, Wiring } from './Wiring';\nimport type { BindModule } from './BindModule';\nimport type { Binder } from './Binder';\nimport { ClientBindOptions, PubSubBindOptions } from './Binder';\n\nabstract class StringApi {\n abstract read(): string;\n}\nabstract class NumberApi {\n abstract read(): number;\n}\nclass StringClient extends StringApi {\n read(): string {\n return 'value';\n }\n}\n\n/** Checked by tsc, never invoked; vitest strips types, so these guarantees live in compiled source. */\nexport class WiringCompileAssertions {\n check(binding: BindModule, routing: RouteModule): void {\n // @ts-expect-error A route module cannot configure a binder.\n const invalidBinding: BindModule = routing;\n // @ts-expect-error A bind module cannot configure a router.\n const invalidRoute: RouteModule = binding;\n void invalidBinding;\n void invalidRoute;\n }\n\n channels(wiring: Wiring, app: AppWiring): void {\n // @ts-expect-error The getters were renamed: getBindModules / getRouteModules.\n wiring.getBindingModules();\n // @ts-expect-error The getters were renamed: getBindModules / getRouteModules.\n app.getRoutingModules();\n }\n\n binder(binder: Binder, strings: symbol): void {\n binder.createRpcClientAndBind(StringApi, 'strings');\n binder.createRpcClientAndBind(StringApi, 'strings', new ClientBindOptions<StringApi>(strings));\n // @ts-expect-error The deployment is a required argument.\n binder.createRpcClientAndBind(StringApi);\n // @ts-expect-error Destination wrappers were removed; pass the deployment string.\n binder.createRpcClientAndBind(StringApi, { serviceName: 'strings' });\n binder.createPubSubClientAndBind(StringApi, 'strings', new PubSubBindOptions<StringApi>(strings));\n binder.bindExternal(StringApi, StringClient);\n // @ts-expect-error The vendor implementation must implement the external contract.\n binder.bindExternal(NumberApi, StringClient);\n }\n}\n"]}
package/src/index.d.ts CHANGED
@@ -3,7 +3,8 @@ export type { AuthMode, ApiKind, HttpMethod, EndpointOperation, EndpointKind, En
3
3
  export { SourceFile, ROUTING_METADATA_KEYS } from './decorators';
4
4
  export { provideSingletonDefaultForApi } from '@webpieces/core-context';
5
5
  export { provideFrameworkSingleton, provideFrameworkSingletonDefaultForApi, buildFrameworkModule, } from '@webpieces/core-context';
6
- export { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';
6
+ export { ApiRoutingFactory } from './ApiRoutingFactory';
7
+ export type { ClassType } from './ClassType';
7
8
  export { Routes, RouteBuilder, RouteDefinition, FilterDefinition } from './WebAppMeta';
8
9
  export { HttpRequest, RawHttpRequest, RawRequest } from '@webpieces/core-context';
9
10
  export { WpResponse } from './WpResponse';
@@ -13,7 +14,8 @@ export { MethodMeta } from './MethodMeta';
13
14
  export { RouteHandler } from './RouteHandler';
14
15
  export { LogApiFilter } from './filters/LogApiFilter';
15
16
  export { FilterMatcher, HttpFilter } from './FilterMatcher';
16
- export type { Wiring, AppWiring, BindModule, RouteModule } from './Wiring';
17
+ export type { Wiring, AppWiring, RouteModule } from './Wiring';
18
+ export type { BindModule } from './BindModule';
17
19
  export { NodeWiringModules } from './Wiring';
18
20
  export type { Binder } from './Binder';
19
21
  export { ContainerBinder, ClientBindOptions, PubSubBindOptions } from './Binder';
@@ -32,3 +34,6 @@ export { AuthorizationHook, AuthorizationService, CanonicalUserRoles, AUTHORIZAT
32
34
  export { AuthorizedApiDocument } from './AuthorizedApiDocument';
33
35
  export type { ApiDocumentObject, ApiDocumentValue } from './AuthorizedApiDocument';
34
36
  export { WiringPolicy } from '@webpieces/http-client-core';
37
+ export { RuntimeStartupPhase, RuntimeStartupOperation } from './RuntimeStartupTiming';
38
+ export type { RuntimeStartupObserver, RuntimeStartupSpan } from './RuntimeStartupTiming';
39
+ export { LazyController, LazyImplementation, LazyFeatureTimer, LazyFeatureDeadline } from './LazyController';
package/src/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WRITE_IDEMPOTENT = exports.READ = exports.verbCarriesBody = exports.DELETE = exports.PATCH = exports.PUT = exports.POST = exports.GET = exports.METADATA_KEYS = exports.HttpContractMapper = exports.RouteMetadataFactory = exports.RouteMetadata = exports.AuthMeta = exports.getQueueName = exports.assertPubSubConventions = exports.assertApiKind = exports.getApiKind = exports.assertEveryEndpointHasAuthMode = exports.getAuthMeta = exports.isApiPath = exports.isRawBody = exports.isFormPost = exports.getHttpParameterDeclarations = exports.getEndpointOperation = exports.getEndpointHttpMethod = exports.getEndpointOptions = exports.getEndpoints = exports.getApiPath = exports.Queue = exports.PubSub = exports.Rpc = exports.getAuthorization = exports.AuthorizationType = exports.WpAuthorization = exports.apiKey = exports.vendorAuth = exports.sharedSecret = exports.oidcSvcs = exports.oidcSameProject = exports.jwt = exports.isLocalOnly = exports.WpLocalOnly = exports.WpAuth = exports.WpAuthPublic = exports.QueryParams = exports.QueryString = exports.QueryParam = exports.PathParam = exports.Endpoint = exports.ApiPath = void 0;
4
4
  exports.DefaultOidcVerifier = exports.UnverifiableAuthModeError = exports.VENDOR_AUTH_VERIFIER = exports.VendorAuthVerifier = exports.API_KEY_HOOK = exports.ApiKeyHook = exports.OIDC_HOOK = exports.OidcHook = exports.JWT_HOOK = exports.MintedJwt = exports.JwtHook = exports.SharedSecrets = exports.AUTHENTICATED_CALLER_KEY = exports.AuthenticatedMachineIdentity = exports.AuthenticatedCaller = exports.AUTH_CONFIG = exports.AuthConfig = exports.ApiClient = exports.PubSubBindOptions = exports.ClientBindOptions = exports.ContainerBinder = exports.NodeWiringModules = exports.FilterMatcher = exports.LogApiFilter = exports.RouteHandler = exports.MethodMeta = exports.InvocationAuthentication = exports.AuthenticatedCallerContext = exports.WpResponse = exports.RawRequest = exports.HttpRequest = exports.FilterDefinition = exports.RouteDefinition = exports.ApiRoutingFactory = exports.buildFrameworkModule = exports.provideFrameworkSingletonDefaultForApi = exports.provideFrameworkSingleton = exports.provideSingletonDefaultForApi = exports.ROUTING_METADATA_KEYS = exports.SourceFile = exports.isDocumentDesign = exports.DocumentDesign = exports.ExternalContextKeys = exports.EXTERNAL_OUTBOUND = exports.EXTERNAL_INBOUND = exports.CRON = exports.CLOUDTASKS = exports.RPC = exports.NONE = exports.WRITE = void 0;
5
- exports.WiringPolicy = exports.AuthorizedApiDocument = exports.VerifiedMachineCaller = exports.VERIFIED_MACHINE_CALLER = exports.AUTHORIZATION_HOOK = exports.CanonicalUserRoles = exports.AuthorizationService = exports.AuthorizationHook = exports.WEBPIECES_CONFIG_TOKEN = exports.WebpiecesConfig = exports.RuntimeSetupOptions = exports.setupRuntime = exports.WebpiecesRouterFactory = exports.WebpiecesRouter = exports.DefaultJwtMintRequest = exports.DefaultJwtHook = void 0;
5
+ exports.LazyFeatureDeadline = exports.LazyFeatureTimer = exports.LazyImplementation = exports.LazyController = exports.RuntimeStartupOperation = exports.RuntimeStartupPhase = exports.WiringPolicy = exports.AuthorizedApiDocument = exports.VerifiedMachineCaller = exports.VERIFIED_MACHINE_CALLER = exports.AUTHORIZATION_HOOK = exports.CanonicalUserRoles = exports.AuthorizationService = exports.AuthorizationHook = exports.WEBPIECES_CONFIG_TOKEN = exports.WebpiecesConfig = exports.RuntimeSetupOptions = exports.setupRuntime = exports.WebpiecesRouterFactory = exports.WebpiecesRouter = exports.DefaultJwtMintRequest = exports.DefaultJwtHook = void 0;
6
6
  // Re-export API decorators from core-util for convenience
7
7
  var core_util_1 = require("@webpieces/core-util");
8
8
  Object.defineProperty(exports, "ApiPath", { enumerable: true, get: function () { return core_util_1.ApiPath; } });
@@ -180,4 +180,12 @@ var AuthorizedApiDocument_1 = require("./AuthorizedApiDocument");
180
180
  Object.defineProperty(exports, "AuthorizedApiDocument", { enumerable: true, get: function () { return AuthorizedApiDocument_1.AuthorizedApiDocument; } });
181
181
  var http_client_core_1 = require("@webpieces/http-client-core");
182
182
  Object.defineProperty(exports, "WiringPolicy", { enumerable: true, get: function () { return http_client_core_1.WiringPolicy; } });
183
+ var RuntimeStartupTiming_1 = require("./RuntimeStartupTiming");
184
+ Object.defineProperty(exports, "RuntimeStartupPhase", { enumerable: true, get: function () { return RuntimeStartupTiming_1.RuntimeStartupPhase; } });
185
+ Object.defineProperty(exports, "RuntimeStartupOperation", { enumerable: true, get: function () { return RuntimeStartupTiming_1.RuntimeStartupOperation; } });
186
+ var LazyController_1 = require("./LazyController");
187
+ Object.defineProperty(exports, "LazyController", { enumerable: true, get: function () { return LazyController_1.LazyController; } });
188
+ Object.defineProperty(exports, "LazyImplementation", { enumerable: true, get: function () { return LazyController_1.LazyImplementation; } });
189
+ Object.defineProperty(exports, "LazyFeatureTimer", { enumerable: true, get: function () { return LazyController_1.LazyFeatureTimer; } });
190
+ Object.defineProperty(exports, "LazyFeatureDeadline", { enumerable: true, get: function () { return LazyController_1.LazyFeatureDeadline; } });
183
191
  //# sourceMappingURL=index.js.map
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":"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","sourcesContent":["// Re-export API decorators from core-util for convenience\nexport {\n ApiPath,\n Endpoint,\n PathParam,\n QueryParam,\n QueryString,\n QueryParams,\n WpAuthPublic,\n WpAuth, WpLocalOnly, isLocalOnly, jwt, oidcSameProject, oidcSvcs, sharedSecret, vendorAuth, apiKey,\n WpAuthorization, AuthorizationType, getAuthorization,\n Rpc,\n PubSub,\n Queue,\n getApiPath,\n getEndpoints,\n getEndpointOptions,\n getEndpointHttpMethod,\n getEndpointOperation,\n getHttpParameterDeclarations,\n isFormPost,\n isRawBody,\n isApiPath,\n getAuthMeta,\n assertEveryEndpointHasAuthMode,\n getApiKind,\n assertApiKind,\n assertPubSubConventions,\n getQueueName,\n AuthMeta,\n RouteMetadata,\n RouteMetadataFactory,\n HttpContractMapper,\n METADATA_KEYS,\n ValidateImplementation,\n GET,\n POST,\n PUT,\n PATCH,\n DELETE,\n verbCarriesBody,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n NONE,\n RPC,\n CLOUDTASKS,\n CRON,\n EXTERNAL_INBOUND,\n EXTERNAL_OUTBOUND,\n ExternalContextKeys,\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 {\n AuthMode,\n ApiKind,\n HttpMethod,\n EndpointOperation,\n EndpointKind,\n EndpointOptions,\n EndpointResponseType,\n} from '@webpieces/core-util';\n\n// Server-side routing decorators and utilities\nexport { SourceFile, ROUTING_METADATA_KEYS } from './decorators';\n\n// DI provider decorators moved to core-context; re-exported here for back-compat\nexport { provideSingletonDefaultForApi } from '@webpieces/core-context';\n// Framework-only DI registry (packages/** framework classes use these; see frameworkProvide.ts)\nexport {\n provideFrameworkSingleton,\n provideFrameworkSingletonDefaultForApi,\n buildFrameworkModule,\n} from '@webpieces/core-context';\n\nexport { ApiRoutingFactory, ClassType } from './ApiRoutingFactory';\n\n// Core routing types\nexport { Routes, RouteBuilder, RouteDefinition, FilterDefinition } 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, RawHttpRequest, RawRequest } from '@webpieces/core-context';\n\n// The INBOUND chain's response type. `Filter`, `Service` and `FilterChain` are NOT re-exported\n// here: they moved to @webpieces/core-util so the outbound client chain is the SAME abstraction\n// rather than a second spelling of it. Import them from '@webpieces/core-util'.\nexport { WpResponse } from './WpResponse';\nexport { AuthenticatedCallerContext } from './AuthenticatedCallerContext';\nexport { InvocationAuthentication } from './InvocationAuthentication';\nexport { MethodMeta } from './MethodMeta';\nexport { RouteHandler } from './RouteHandler';\n\n// LogApiFilter: the fixed OUTERMOST framework filter (auto-installed at 1,000,000 above\n// AuthFilter). Exported for reference/testing only — apps must NOT install it themselves.\nexport { LogApiFilter } from './filters/LogApiFilter';\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 app's server-surface declaration: DI bind modules + route groups + headers.\nexport type { Wiring, AppWiring, BindModule, RouteModule } from './Wiring';\nexport { NodeWiringModules } from './Wiring';\n// The Node binder every BindModule.configure receives.\nexport type { Binder } from './Binder';\nexport { ContainerBinder, ClientBindOptions, PubSubBindOptions } from './Binder';\n\n// The public API-surface abstraction: declare routes/filters, get them back as ApiClient[].\nexport { ApiFactory } from './ApiFactory';\nexport { ApiClient, ApiClientProxy } from './ApiClient';\n\n// Auth: the app-provided, container-bound pieces the framework AuthFilter injects.\n// - AuthConfig: shared-secret STATE (sharedSecret(...) values).\n// - JwtHook / OidcHook / VendorAuthVerifier / ApiKeyHook: OPTIONAL verification mechanisms\n// (bind only what your served routes declare; a served route declaring a mode whose piece is\n// unbound FAILS STARTUP with UnverifiableAuthModeError naming the binding, never open — #1362).\n// - DefaultOidcVerifier: the built-in Google OIDC verifier used when no OidcHook is bound.\nexport {\n AuthConfig,\n AUTH_CONFIG,\n AuthenticatedCaller,\n AuthenticatedMachineIdentity,\n AUTHENTICATED_CALLER_KEY,\n SharedSecrets,\n} from './AuthConfig';\nexport {\n JwtHook,\n MintedJwt,\n JWT_HOOK,\n OidcHook,\n OIDC_HOOK,\n ApiKeyHook,\n API_KEY_HOOK,\n} from './AuthHooks';\n// vendorAuth(name), INBOUND role: the verifier this server's AuthFilter calls. Defined in\n// @webpieces/core-context beside its OUTBOUND twin VendorAuthMinter (re-exported by\n// @webpieces/http-client-node); the two are independent DI roles, never one binding (#1358).\nexport { VendorAuthVerifier, VENDOR_AUTH_VERIFIER } from '@webpieces/core-context';\nexport { UnverifiableAuthModeError } from './UnverifiableAuthModeError';\nexport { DefaultOidcVerifier } from './DefaultOidcVerifier';\n// DefaultJwtHook: batteries-included HS256 JwtHook — `new DefaultJwtHook(secret)` and go.\nexport { DefaultJwtHook, DefaultJwtMintRequest } from './DefaultJwtHook';\n\n// Above-boundary context setup shared by every transport adapter.\n\n// Node-only router (the express-free heart: container + filter chain + in-process client)\nexport { WebpiecesRouter, WebpiecesRouterFactory, WebpiecesRouterOptions } from './WebpiecesRouter';\n\n// The ONE transport-free startup sequence (headers → logging → router → routes) → ApiFactory.\n// Reusable by any company/app and any framework adapter; a company wraps it with its own headers.\nexport { setupRuntime, RuntimeSetupOptions } from './setupRuntime';\n\n// Server configuration\nexport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\n\n\nexport { AuthorizationHook, AuthorizationService, CanonicalUserRoles, AUTHORIZATION_HOOK, VERIFIED_MACHINE_CALLER, VerifiedMachineCaller } from './AuthorizationHook';\nexport { AuthorizedApiDocument } from './AuthorizedApiDocument';\nexport type { ApiDocumentObject, ApiDocumentValue } from './AuthorizedApiDocument';\n\nexport { WiringPolicy } from '@webpieces/http-client-core';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// Re-export API decorators from core-util for convenience\nexport {\n ApiPath,\n Endpoint,\n PathParam,\n QueryParam,\n QueryString,\n QueryParams,\n WpAuthPublic,\n WpAuth, WpLocalOnly, isLocalOnly, jwt, oidcSameProject, oidcSvcs, sharedSecret, vendorAuth, apiKey,\n WpAuthorization, AuthorizationType, getAuthorization,\n Rpc,\n PubSub,\n Queue,\n getApiPath,\n getEndpoints,\n getEndpointOptions,\n getEndpointHttpMethod,\n getEndpointOperation,\n getHttpParameterDeclarations,\n isFormPost,\n isRawBody,\n isApiPath,\n getAuthMeta,\n assertEveryEndpointHasAuthMode,\n getApiKind,\n assertApiKind,\n assertPubSubConventions,\n getQueueName,\n AuthMeta,\n RouteMetadata,\n RouteMetadataFactory,\n HttpContractMapper,\n METADATA_KEYS,\n ValidateImplementation,\n GET,\n POST,\n PUT,\n PATCH,\n DELETE,\n verbCarriesBody,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n NONE,\n RPC,\n CLOUDTASKS,\n CRON,\n EXTERNAL_INBOUND,\n EXTERNAL_OUTBOUND,\n ExternalContextKeys,\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 {\n AuthMode,\n ApiKind,\n HttpMethod,\n EndpointOperation,\n EndpointKind,\n EndpointOptions,\n EndpointResponseType,\n} from '@webpieces/core-util';\n\n// Server-side routing decorators and utilities\nexport { SourceFile, ROUTING_METADATA_KEYS } from './decorators';\n\n// DI provider decorators moved to core-context; re-exported here for back-compat\nexport { provideSingletonDefaultForApi } from '@webpieces/core-context';\n// Framework-only DI registry (packages/** framework classes use these; see frameworkProvide.ts)\nexport {\n provideFrameworkSingleton,\n provideFrameworkSingletonDefaultForApi,\n buildFrameworkModule,\n} from '@webpieces/core-context';\n\nexport { ApiRoutingFactory } from './ApiRoutingFactory';\nexport type { ClassType } from './ClassType';\n\n// Core routing types\nexport { Routes, RouteBuilder, RouteDefinition, FilterDefinition } 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, RawHttpRequest, RawRequest } from '@webpieces/core-context';\n\n// The INBOUND chain's response type. `Filter`, `Service` and `FilterChain` are NOT re-exported\n// here: they moved to @webpieces/core-util so the outbound client chain is the SAME abstraction\n// rather than a second spelling of it. Import them from '@webpieces/core-util'.\nexport { WpResponse } from './WpResponse';\nexport { AuthenticatedCallerContext } from './AuthenticatedCallerContext';\nexport { InvocationAuthentication } from './InvocationAuthentication';\nexport { MethodMeta } from './MethodMeta';\nexport { RouteHandler } from './RouteHandler';\n\n// LogApiFilter: the fixed OUTERMOST framework filter (auto-installed at 1,000,000 above\n// AuthFilter). Exported for reference/testing only — apps must NOT install it themselves.\nexport { LogApiFilter } from './filters/LogApiFilter';\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 app's server-surface declaration: DI bind modules + route groups + headers.\nexport type { Wiring, AppWiring, RouteModule } from './Wiring';\nexport type { BindModule } from './BindModule';\nexport { NodeWiringModules } from './Wiring';\n// The Node binder every BindModule.configure receives.\nexport type { Binder } from './Binder';\nexport { ContainerBinder, ClientBindOptions, PubSubBindOptions } from './Binder';\n\n// The public API-surface abstraction: declare routes/filters, get them back as ApiClient[].\nexport { ApiFactory } from './ApiFactory';\nexport { ApiClient, ApiClientProxy } from './ApiClient';\n\n// Auth: the app-provided, container-bound pieces the framework AuthFilter injects.\n// - AuthConfig: shared-secret STATE (sharedSecret(...) values).\n// - JwtHook / OidcHook / VendorAuthVerifier / ApiKeyHook: OPTIONAL verification mechanisms\n// (bind only what your served routes declare; a served route declaring a mode whose piece is\n// unbound FAILS STARTUP with UnverifiableAuthModeError naming the binding, never open — #1362).\n// - DefaultOidcVerifier: the built-in Google OIDC verifier used when no OidcHook is bound.\nexport {\n AuthConfig,\n AUTH_CONFIG,\n AuthenticatedCaller,\n AuthenticatedMachineIdentity,\n AUTHENTICATED_CALLER_KEY,\n SharedSecrets,\n} from './AuthConfig';\nexport {\n JwtHook,\n MintedJwt,\n JWT_HOOK,\n OidcHook,\n OIDC_HOOK,\n ApiKeyHook,\n API_KEY_HOOK,\n} from './AuthHooks';\n// vendorAuth(name), INBOUND role: the verifier this server's AuthFilter calls. Defined in\n// @webpieces/core-context beside its OUTBOUND twin VendorAuthMinter (re-exported by\n// @webpieces/http-client-node); the two are independent DI roles, never one binding (#1358).\nexport { VendorAuthVerifier, VENDOR_AUTH_VERIFIER } from '@webpieces/core-context';\nexport { UnverifiableAuthModeError } from './UnverifiableAuthModeError';\nexport { DefaultOidcVerifier } from './DefaultOidcVerifier';\n// DefaultJwtHook: batteries-included HS256 JwtHook — `new DefaultJwtHook(secret)` and go.\nexport { DefaultJwtHook, DefaultJwtMintRequest } from './DefaultJwtHook';\n\n// Above-boundary context setup shared by every transport adapter.\n\n// Node-only router (the express-free heart: container + filter chain + in-process client)\nexport { WebpiecesRouter, WebpiecesRouterFactory, WebpiecesRouterOptions } from './WebpiecesRouter';\n\n// The ONE transport-free startup sequence (headers → logging → router → routes) → ApiFactory.\n// Reusable by any company/app and any framework adapter; a company wraps it with its own headers.\nexport { setupRuntime, RuntimeSetupOptions } from './setupRuntime';\n\n// Server configuration\nexport { WebpiecesConfig, WEBPIECES_CONFIG_TOKEN } from './WebpiecesConfig';\n\n\nexport { AuthorizationHook, AuthorizationService, CanonicalUserRoles, AUTHORIZATION_HOOK, VERIFIED_MACHINE_CALLER, VerifiedMachineCaller } from './AuthorizationHook';\nexport { AuthorizedApiDocument } from './AuthorizedApiDocument';\nexport type { ApiDocumentObject, ApiDocumentValue } from './AuthorizedApiDocument';\n\nexport { WiringPolicy } from '@webpieces/http-client-core';\n\nexport { RuntimeStartupPhase, RuntimeStartupOperation } from './RuntimeStartupTiming';\nexport type { RuntimeStartupObserver, RuntimeStartupSpan } from './RuntimeStartupTiming';\n\nexport { LazyController, LazyImplementation, LazyFeatureTimer, LazyFeatureDeadline } from './LazyController';\n"]}