@webpieces/http-routing 0.4.989 → 0.4.990

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,9 +97,18 @@ same final handler. Denied calls do not import the implementation. A mixed API i
97
97
  feature: its first permitted method loads that controller, rather than independently loading each
98
98
  method's JavaScript.
99
99
 
100
- `LazyImplementation` declares four things: the concrete controller, binding modules, private concrete
100
+ Use `new ApplicationImplementation(feature.AdminController)` when the implementation uses the
101
+ application's existing bindings and shared concrete singleton graph. This is an import-only boundary:
102
+ first authorized use imports the class and resolves it in the original application container, in the
103
+ same detached initialization context. Different deferred APIs continue to share their application
104
+ singletons. It accepts no late binding modules and performs no rebinding; binding declarations remain
105
+ at startup. As with existing eager DI, constructing a legitimate shared collaborator before a later
106
+ constructor fails is not an atomic transaction and is not rolled back. Remaining eager binding-barrel
107
+ imports must be measured separately; this mode alone does not remove them.
108
+
109
+ Use `LazyImplementation` for an isolated feature with private bindings. It declares four things: the concrete controller, binding modules, private concrete
101
110
  singletons (excluding the controller, which is implicit), and explicitly shared application dependencies.
102
- Private bindings live in an isolated container with autobinding disabled. Each shared dependency must
111
+ In isolated mode, private bindings live in an isolated container with autobinding disabled. Each shared dependency must
103
112
  already be explicitly bound in the application; the bridge returns the application's instance and
104
113
  preserves its scope instead of creating a second singleton. Bind shared services explicitly at startup
105
114
  when no essential route would otherwise resolve them. Merely importing a class does not bind it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/http-routing",
3
- "version": "0.4.989",
3
+ "version": "0.4.990",
4
4
  "description": "Decorator-based routing with auto-wiring for WebPieces",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -22,14 +22,14 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@inversifyjs/binding-decorators": "1.1.5",
25
- "@webpieces/core-context": "0.4.989",
26
- "@webpieces/core-util": "0.4.989",
27
- "@webpieces/gcp-identity": "0.4.989",
25
+ "@webpieces/core-context": "0.4.990",
26
+ "@webpieces/core-util": "0.4.990",
27
+ "@webpieces/gcp-identity": "0.4.990",
28
28
  "inversify": "7.10.4",
29
29
  "jsonwebtoken": "9.0.2",
30
30
  "minimatch": "10.0.1",
31
- "@webpieces/http-client-core": "0.4.989",
32
- "@webpieces/http-client-node": "0.4.989",
33
- "@webpieces/cloudtasks-client": "0.4.989"
31
+ "@webpieces/http-client-core": "0.4.990",
32
+ "@webpieces/http-client-node": "0.4.990",
33
+ "@webpieces/cloudtasks-client": "0.4.990"
34
34
  }
35
35
  }
@@ -18,6 +18,11 @@ export declare class LazyImplementation<T extends object> {
18
18
  readonly shared: readonly ServiceIdentifier[];
19
19
  constructor(controller: Newable<T>, bindings: readonly BindModule[], singletons: readonly Newable<object>[], shared: readonly ServiceIdentifier[]);
20
20
  }
21
+ /** Import-only boundary: resolve in the existing app container and preserve its singleton graph. */
22
+ export declare class ApplicationImplementation<T extends object> {
23
+ readonly controller: Newable<T>;
24
+ constructor(controller: Newable<T>);
25
+ }
21
26
  /**
22
27
  * Eager identity/security metadata, deferred implementation. The loader imports one feature and
23
28
  * returns declarative bindings; it must not open resources or perform request work. A failure is
@@ -27,8 +32,8 @@ export declare class LazyController<T extends object> {
27
32
  readonly name: string;
28
33
  readonly filepath: string;
29
34
  readonly timeoutMillis: number;
30
- readonly load: () => Promise<LazyImplementation<T>>;
31
- constructor(name: string, filepath: string, timeoutMillis: number, load: () => Promise<LazyImplementation<T>>);
35
+ readonly load: () => Promise<LazyImplementation<T> | ApplicationImplementation<T>>;
36
+ constructor(name: string, filepath: string, timeoutMillis: number, load: () => Promise<LazyImplementation<T> | ApplicationImplementation<T>>);
32
37
  }
33
38
  /** One retained initialization promise per descriptor per router; callers keep their own context. */
34
39
  export declare class LazyControllerState<T extends object> {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LazyControllerState = exports.LazyController = exports.LazyImplementation = exports.LazyFeatureTimer = exports.LazyFeatureDeadline = void 0;
3
+ exports.LazyControllerState = exports.LazyController = exports.ApplicationImplementation = exports.LazyImplementation = exports.LazyFeatureTimer = exports.LazyFeatureDeadline = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const decorators_1 = require("./decorators");
6
6
  const inversify_1 = require("inversify");
@@ -41,6 +41,14 @@ class LazyImplementation {
41
41
  }
42
42
  }
43
43
  exports.LazyImplementation = LazyImplementation;
44
+ /** Import-only boundary: resolve in the existing app container and preserve its singleton graph. */
45
+ class ApplicationImplementation {
46
+ controller;
47
+ constructor(controller) {
48
+ this.controller = controller;
49
+ }
50
+ }
51
+ exports.ApplicationImplementation = ApplicationImplementation;
44
52
  /**
45
53
  * Eager identity/security metadata, deferred implementation. The loader imports one feature and
46
54
  * returns declarative bindings; it must not open resources or perform request work. A failure is
@@ -158,6 +166,8 @@ class LazyControllerState {
158
166
  Reflect.get(this.api.prototype, method))
159
167
  throw new Error(`Lazy controller ${this.definition.name} must implement ${this.api.name}.${method}.`);
160
168
  }
169
+ if (implementation instanceof ApplicationImplementation)
170
+ return this.parent.get(controller);
161
171
  for (const token of implementation.shared) {
162
172
  if (!this.parent.isCurrentBound(token) &&
163
173
  !(typeof token !== 'function' && this.parent.isBound(token)))
@@ -1 +1 @@
1
- {"version":3,"file":"LazyController.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/LazyController.ts"],"names":[],"mappings":"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","sourcesContent":["import { ROUTING_METADATA_KEYS } from './decorators';\nimport {\n Container,\n ContainerModule,\n type ContainerModuleLoadOptions,\n type Newable,\n type ServiceIdentifier,\n type BindToFluentSyntax,\n} from 'inversify';\nimport { RequestContext, provideFrameworkSingletonDefaultForApi } from '@webpieces/core-context';\nimport { type ApiPrototype } from '@webpieces/http-client-core';\nimport type { ClassType } from './ClassType';\nimport { ContainerBinder, type ClientBindOptions, type PubSubBindOptions } from './Binder';\nimport type { BindModule } from './BindModule';\n\n/** The cancellable native deadline edge; feature tests replace only this clock. */\nexport class LazyFeatureDeadline {\n constructor(public readonly cancel: () => void) {}\n}\n\n/** Schedules a bounded first-use initialization; never a per-request authorization cache. */\nexport abstract class LazyFeatureTimer {\n abstract schedule(timeoutMillis: number, expire: () => void): Promise<LazyFeatureDeadline>;\n}\n\n@provideFrameworkSingletonDefaultForApi(LazyFeatureTimer)\nclass NodeLazyFeatureTimer extends LazyFeatureTimer {\n override async schedule(\n timeoutMillis: number,\n expire: () => void,\n ): Promise<LazyFeatureDeadline> {\n const timer = setTimeout(expire, timeoutMillis);\n return new LazyFeatureDeadline(() => clearTimeout(timer));\n }\n}\n\n/** Imported only on first permitted use. Explicitly list private concrete singletons. */\nexport class LazyImplementation<T extends object> {\n constructor(\n public readonly controller: Newable<T>,\n public readonly bindings: readonly BindModule[],\n public readonly singletons: readonly Newable<object>[],\n public readonly shared: readonly ServiceIdentifier[],\n ) {}\n}\n\n/**\n * Eager identity/security metadata, deferred implementation. The loader imports one feature and\n * returns declarative bindings; it must not open resources or perform request work. A failure is\n * retained per router until restart. The required deadline bounds waiting, not JavaScript CPU.\n */\nexport class LazyController<T extends object> {\n constructor(\n public readonly name: string,\n public readonly filepath: string,\n public readonly timeoutMillis: number,\n public readonly load: () => Promise<LazyImplementation<T>>,\n ) {\n if (!name.trim() || !filepath.trim())\n throw new Error('LazyController requires a stable name and filter filepath.');\n if (!Number.isFinite(timeoutMillis) || timeoutMillis <= 0 || timeoutMillis > 2_147_483_647)\n throw new Error(\n 'LazyController timeoutMillis must be positive, finite and at most 2147483647.',\n );\n }\n}\n\n/** Isolated scope: cannot replace application bindings; explicitly inherited external overrides win. */\nclass LazyFeatureBinder extends ContainerBinder {\n constructor(\n options: ContainerModuleLoadOptions,\n private readonly scope: Container,\n private readonly parent: Container,\n ) {\n super(options);\n }\n\n override bind<T>(token: ServiceIdentifier<T>): BindToFluentSyntax<T> {\n if (this.scope.isCurrentBound(token) || this.parent.isCurrentBound(token))\n throw new Error(`Lazy feature cannot shadow or duplicate binding ${String(token)}.`);\n return super.bind(token);\n }\n\n override createRpcClientAndBind<T extends object>(\n api: ApiPrototype<T>,\n deployment: string,\n options?: ClientBindOptions<NoInfer<T>>,\n ): void {\n if (!this.inherit(options?.token ?? api))\n super.createRpcClientAndBind(api, deployment, options);\n }\n\n override createPubSubClientAndBind<T extends object>(\n api: ApiPrototype<T>,\n deployment: string,\n options?: PubSubBindOptions<NoInfer<T>>,\n ): void {\n if (!this.inherit(options?.token ?? api))\n super.createPubSubClientAndBind(api, deployment, options);\n }\n\n override bindExternal<T extends object>(\n api: ApiPrototype<T>,\n implementation: Newable<NoInfer<T>>,\n ): void {\n if (!this.inherit(api)) super.bindExternal(api, implementation);\n }\n private inherit<T>(token: ServiceIdentifier<T>): boolean {\n if (!this.parent.isCurrentBound(token)) return false;\n if (!this.scope.isCurrentBound(token))\n this.scope.bind(token).toDynamicValue(() => this.parent.get(token));\n return true;\n }\n}\n\n/** One retained initialization promise per descriptor per router; callers keep their own context. */\nexport class LazyControllerState<T extends object> {\n private initialized?: Promise<T>;\n\n constructor(\n private readonly parent: Container,\n private readonly api: ClassType<T>,\n private readonly definition: LazyController<T>,\n private readonly timer: LazyFeatureTimer,\n private readonly methods: readonly string[],\n ) {}\n\n matchesApi(api: ClassType<object>): boolean {\n return this.api === api;\n }\n\n resolve(): Promise<T> {\n this.initialized ??= RequestContext.runDetachedScope(() => this.initialize());\n return this.initialized;\n }\n\n private async initialize(): Promise<T> {\n // No parent-container autobinding: private classes and shared dependencies are explicit.\n // Inversify parent isBound/get can autobind into the parent, even when this child disables it.\n const scope = new Container();\n let abandoned = false;\n let rejectDeadline!: (error: Error) => void;\n const expired = new Promise<never>((_resolve, reject) => {\n rejectDeadline = reject;\n });\n const deadline = await this.timer.schedule(this.definition.timeoutMillis, () => {\n abandoned = true;\n rejectDeadline(\n new Error(\n `Lazy feature ${this.definition.name} initialization exceeded ${this.definition.timeoutMillis}ms.`,\n ),\n );\n });\n // webpieces-disable no-unmanaged-exceptions -- terminal initialization boundary: release deadline on success, import/binding failure or timeout; rejection is retained and reported by normal dispatch\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n return await Promise.race([expired, this.build(scope, () => abandoned)]);\n } finally {\n deadline.cancel();\n }\n }\n\n private async build(scope: Container, abandoned: () => boolean): Promise<T> {\n const implementation = await this.definition.load();\n if (abandoned())\n throw new Error(`Lazy feature ${this.definition.name} initialization was abandoned.`);\n const controller = implementation.controller;\n if (\n controller.name !== this.definition.name ||\n !this.api.prototype.isPrototypeOf(controller.prototype)\n )\n throw new Error(\n `Lazy controller ${this.definition.name} must preserve its declared name and extend ${this.api.name}.`,\n );\n const source: string | undefined = Reflect.getMetadata(\n ROUTING_METADATA_KEYS.SOURCE_FILEPATH,\n controller,\n );\n if (source !== undefined && source !== this.definition.filepath)\n throw new Error(\n `Lazy controller ${controller.name} filepath must match its @SourceFile metadata.`,\n );\n for (const method of this.methods) {\n if (\n typeof Reflect.get(controller.prototype, method) !== 'function' ||\n Reflect.get(controller.prototype, method) ===\n Reflect.get(this.api.prototype, method)\n )\n throw new Error(\n `Lazy controller ${this.definition.name} must implement ${this.api.name}.${method}.`,\n );\n }\n for (const token of implementation.shared) {\n if (\n !this.parent.isCurrentBound(token) &&\n !(typeof token !== 'function' && this.parent.isBound(token))\n )\n throw new Error(\n `Lazy feature requires an explicitly bound shared dependency ${String(token)}.`,\n );\n if (scope.isCurrentBound(token))\n throw new Error(`Duplicate shared feature dependency ${String(token)}.`);\n scope.bind(token).toDynamicValue(() => this.parent.get(token));\n }\n // Candidate bindings never mutate the shared container, including when a module fails halfway.\n for (const module of implementation.bindings) {\n await scope.load(\n new ContainerModule((options: ContainerModuleLoadOptions) =>\n module.configure(new LazyFeatureBinder(options, scope, this.parent)),\n ),\n );\n if (abandoned())\n throw new Error(\n `Lazy feature ${this.definition.name} initialization was abandoned.`,\n );\n }\n for (const singleton of [...implementation.singletons, controller]) {\n if (scope.isCurrentBound(singleton) || this.parent.isCurrentBound(singleton))\n throw new Error(\n `Lazy feature cannot shadow or duplicate singleton ${singleton.name}.`,\n );\n scope.bind(singleton).toSelf().inSingletonScope();\n }\n return scope.get(controller);\n }\n}\n"]}
1
+ {"version":3,"file":"LazyController.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/LazyController.ts"],"names":[],"mappings":"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","sourcesContent":["import { ROUTING_METADATA_KEYS } from './decorators';\nimport {\n Container,\n ContainerModule,\n type ContainerModuleLoadOptions,\n type Newable,\n type ServiceIdentifier,\n type BindToFluentSyntax,\n} from 'inversify';\nimport { RequestContext, provideFrameworkSingletonDefaultForApi } from '@webpieces/core-context';\nimport { type ApiPrototype } from '@webpieces/http-client-core';\nimport type { ClassType } from './ClassType';\nimport { ContainerBinder, type ClientBindOptions, type PubSubBindOptions } from './Binder';\nimport type { BindModule } from './BindModule';\n\n/** The cancellable native deadline edge; feature tests replace only this clock. */\nexport class LazyFeatureDeadline {\n constructor(public readonly cancel: () => void) {}\n}\n\n/** Schedules a bounded first-use initialization; never a per-request authorization cache. */\nexport abstract class LazyFeatureTimer {\n abstract schedule(timeoutMillis: number, expire: () => void): Promise<LazyFeatureDeadline>;\n}\n\n@provideFrameworkSingletonDefaultForApi(LazyFeatureTimer)\nclass NodeLazyFeatureTimer extends LazyFeatureTimer {\n override async schedule(\n timeoutMillis: number,\n expire: () => void,\n ): Promise<LazyFeatureDeadline> {\n const timer = setTimeout(expire, timeoutMillis);\n return new LazyFeatureDeadline(() => clearTimeout(timer));\n }\n}\n\n/** Imported only on first permitted use. Explicitly list private concrete singletons. */\nexport class LazyImplementation<T extends object> {\n constructor(\n public readonly controller: Newable<T>,\n public readonly bindings: readonly BindModule[],\n public readonly singletons: readonly Newable<object>[],\n public readonly shared: readonly ServiceIdentifier[],\n ) {}\n}\n\n/** Import-only boundary: resolve in the existing app container and preserve its singleton graph. */\nexport class ApplicationImplementation<T extends object> {\n constructor(public readonly controller: Newable<T>) {}\n}\n\n/**\n * Eager identity/security metadata, deferred implementation. The loader imports one feature and\n * returns declarative bindings; it must not open resources or perform request work. A failure is\n * retained per router until restart. The required deadline bounds waiting, not JavaScript CPU.\n */\nexport class LazyController<T extends object> {\n constructor(\n public readonly name: string,\n public readonly filepath: string,\n public readonly timeoutMillis: number,\n public readonly load: () => Promise<LazyImplementation<T> | ApplicationImplementation<T>>,\n ) {\n if (!name.trim() || !filepath.trim())\n throw new Error('LazyController requires a stable name and filter filepath.');\n if (!Number.isFinite(timeoutMillis) || timeoutMillis <= 0 || timeoutMillis > 2_147_483_647)\n throw new Error(\n 'LazyController timeoutMillis must be positive, finite and at most 2147483647.',\n );\n }\n}\n\n/** Isolated scope: cannot replace application bindings; explicitly inherited external overrides win. */\nclass LazyFeatureBinder extends ContainerBinder {\n constructor(\n options: ContainerModuleLoadOptions,\n private readonly scope: Container,\n private readonly parent: Container,\n ) {\n super(options);\n }\n\n override bind<T>(token: ServiceIdentifier<T>): BindToFluentSyntax<T> {\n if (this.scope.isCurrentBound(token) || this.parent.isCurrentBound(token))\n throw new Error(`Lazy feature cannot shadow or duplicate binding ${String(token)}.`);\n return super.bind(token);\n }\n\n override createRpcClientAndBind<T extends object>(\n api: ApiPrototype<T>,\n deployment: string,\n options?: ClientBindOptions<NoInfer<T>>,\n ): void {\n if (!this.inherit(options?.token ?? api))\n super.createRpcClientAndBind(api, deployment, options);\n }\n\n override createPubSubClientAndBind<T extends object>(\n api: ApiPrototype<T>,\n deployment: string,\n options?: PubSubBindOptions<NoInfer<T>>,\n ): void {\n if (!this.inherit(options?.token ?? api))\n super.createPubSubClientAndBind(api, deployment, options);\n }\n\n override bindExternal<T extends object>(\n api: ApiPrototype<T>,\n implementation: Newable<NoInfer<T>>,\n ): void {\n if (!this.inherit(api)) super.bindExternal(api, implementation);\n }\n private inherit<T>(token: ServiceIdentifier<T>): boolean {\n if (!this.parent.isCurrentBound(token)) return false;\n if (!this.scope.isCurrentBound(token))\n this.scope.bind(token).toDynamicValue(() => this.parent.get(token));\n return true;\n }\n}\n\n/** One retained initialization promise per descriptor per router; callers keep their own context. */\nexport class LazyControllerState<T extends object> {\n private initialized?: Promise<T>;\n\n constructor(\n private readonly parent: Container,\n private readonly api: ClassType<T>,\n private readonly definition: LazyController<T>,\n private readonly timer: LazyFeatureTimer,\n private readonly methods: readonly string[],\n ) {}\n\n matchesApi(api: ClassType<object>): boolean {\n return this.api === api;\n }\n\n resolve(): Promise<T> {\n this.initialized ??= RequestContext.runDetachedScope(() => this.initialize());\n return this.initialized;\n }\n\n private async initialize(): Promise<T> {\n // No parent-container autobinding: private classes and shared dependencies are explicit.\n // Inversify parent isBound/get can autobind into the parent, even when this child disables it.\n const scope = new Container();\n let abandoned = false;\n let rejectDeadline!: (error: Error) => void;\n const expired = new Promise<never>((_resolve, reject) => {\n rejectDeadline = reject;\n });\n const deadline = await this.timer.schedule(this.definition.timeoutMillis, () => {\n abandoned = true;\n rejectDeadline(\n new Error(\n `Lazy feature ${this.definition.name} initialization exceeded ${this.definition.timeoutMillis}ms.`,\n ),\n );\n });\n // webpieces-disable no-unmanaged-exceptions -- terminal initialization boundary: release deadline on success, import/binding failure or timeout; rejection is retained and reported by normal dispatch\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n return await Promise.race([expired, this.build(scope, () => abandoned)]);\n } finally {\n deadline.cancel();\n }\n }\n\n private async build(scope: Container, abandoned: () => boolean): Promise<T> {\n const implementation = await this.definition.load();\n if (abandoned())\n throw new Error(`Lazy feature ${this.definition.name} initialization was abandoned.`);\n const controller = implementation.controller;\n if (\n controller.name !== this.definition.name ||\n !this.api.prototype.isPrototypeOf(controller.prototype)\n )\n throw new Error(\n `Lazy controller ${this.definition.name} must preserve its declared name and extend ${this.api.name}.`,\n );\n const source: string | undefined = Reflect.getMetadata(\n ROUTING_METADATA_KEYS.SOURCE_FILEPATH,\n controller,\n );\n if (source !== undefined && source !== this.definition.filepath)\n throw new Error(\n `Lazy controller ${controller.name} filepath must match its @SourceFile metadata.`,\n );\n for (const method of this.methods) {\n if (\n typeof Reflect.get(controller.prototype, method) !== 'function' ||\n Reflect.get(controller.prototype, method) ===\n Reflect.get(this.api.prototype, method)\n )\n throw new Error(\n `Lazy controller ${this.definition.name} must implement ${this.api.name}.${method}.`,\n );\n }\n if (implementation instanceof ApplicationImplementation) return this.parent.get(controller);\n\n for (const token of implementation.shared) {\n if (\n !this.parent.isCurrentBound(token) &&\n !(typeof token !== 'function' && this.parent.isBound(token))\n )\n throw new Error(\n `Lazy feature requires an explicitly bound shared dependency ${String(token)}.`,\n );\n if (scope.isCurrentBound(token))\n throw new Error(`Duplicate shared feature dependency ${String(token)}.`);\n scope.bind(token).toDynamicValue(() => this.parent.get(token));\n }\n // Candidate bindings never mutate the shared container, including when a module fails halfway.\n for (const module of implementation.bindings) {\n await scope.load(\n new ContainerModule((options: ContainerModuleLoadOptions) =>\n module.configure(new LazyFeatureBinder(options, scope, this.parent)),\n ),\n );\n if (abandoned())\n throw new Error(\n `Lazy feature ${this.definition.name} initialization was abandoned.`,\n );\n }\n for (const singleton of [...implementation.singletons, controller]) {\n if (scope.isCurrentBound(singleton) || this.parent.isCurrentBound(singleton))\n throw new Error(\n `Lazy feature cannot shadow or duplicate singleton ${singleton.name}.`,\n );\n scope.bind(singleton).toSelf().inSingletonScope();\n }\n return scope.get(controller);\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { WebpiecesRouter } from './WebpiecesRouter';
2
- import type { LazyController, LazyImplementation } from './LazyController';
2
+ import type { LazyController, LazyImplementation, ApplicationImplementation } from './LazyController';
3
3
  declare abstract class StringApi {
4
4
  abstract read(): Promise<string>;
5
5
  }
@@ -10,5 +10,6 @@ declare abstract class NumberApi {
10
10
  export declare class LazyControllerCompileAssertions {
11
11
  routes(router: WebpiecesRouter, strings: LazyController<StringApi>, numbers: LazyController<NumberApi>): void;
12
12
  implementation(strings: LazyImplementation<StringApi>, numbers: LazyImplementation<NumberApi>): void;
13
+ application(strings: ApplicationImplementation<StringApi>, numbers: ApplicationImplementation<NumberApi>): void;
13
14
  }
14
15
  export {};
@@ -18,6 +18,12 @@ class LazyControllerCompileAssertions {
18
18
  void invalid;
19
19
  void strings;
20
20
  }
21
+ application(strings, numbers) {
22
+ // @ts-expect-error Application-container mode still enforces the API's result type.
23
+ const invalid = numbers;
24
+ void invalid;
25
+ void strings;
26
+ }
21
27
  }
22
28
  exports.LazyControllerCompileAssertions = LazyControllerCompileAssertions;
23
29
  //# sourceMappingURL=LazyControllerCompileAssertions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LazyControllerCompileAssertions.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/LazyControllerCompileAssertions.ts"],"names":[],"mappings":";;;AAGA,MAAe,SAAS;CAEvB;AACD,MAAe,SAAS;CAEvB;AAED,+FAA+F;AAC/F,MAAa,+BAA+B;IACxC,MAAM,CACF,MAAuB,EACvB,OAAkC,EAClC,OAAkC;QAElC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACrC,uFAAuF;QACvF,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IACD,cAAc,CACV,OAAsC,EACtC,OAAsC;QAEtC,4FAA4F;QAC5F,MAAM,OAAO,GAAkC,OAAO,CAAC;QACvD,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;IACjB,CAAC;CACJ;AAnBD,0EAmBC","sourcesContent":["import type { WebpiecesRouter } from './WebpiecesRouter';\nimport type { LazyController, LazyImplementation } from './LazyController';\n\nabstract class StringApi {\n abstract read(): Promise<string>;\n}\nabstract class NumberApi {\n abstract read(): Promise<number>;\n}\n\n/** Compiled by tsc, never invoked: implementation types must agree with the registered API. */\nexport class LazyControllerCompileAssertions {\n routes(\n router: WebpiecesRouter,\n strings: LazyController<StringApi>,\n numbers: LazyController<NumberApi>,\n ): void {\n router.addRoutes(StringApi, strings);\n // @ts-expect-error The deferred controller must implement this contract's result type.\n router.addRoutes(StringApi, numbers);\n }\n implementation(\n strings: LazyImplementation<StringApi>,\n numbers: LazyImplementation<NumberApi>,\n ): void {\n // @ts-expect-error A number-result implementation cannot be a string-result implementation.\n const invalid: LazyImplementation<StringApi> = numbers;\n void invalid;\n void strings;\n }\n}\n"]}
1
+ {"version":3,"file":"LazyControllerCompileAssertions.js","sourceRoot":"","sources":["../../../../../packages/http/http-routing/src/LazyControllerCompileAssertions.ts"],"names":[],"mappings":";;;AAOA,MAAe,SAAS;CAEvB;AACD,MAAe,SAAS;CAEvB;AAED,+FAA+F;AAC/F,MAAa,+BAA+B;IACxC,MAAM,CACF,MAAuB,EACvB,OAAkC,EAClC,OAAkC;QAElC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACrC,uFAAuF;QACvF,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IACD,cAAc,CACV,OAAsC,EACtC,OAAsC;QAEtC,4FAA4F;QAC5F,MAAM,OAAO,GAAkC,OAAO,CAAC;QACvD,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;IACjB,CAAC;IACD,WAAW,CACP,OAA6C,EAC7C,OAA6C;QAE7C,oFAAoF;QACpF,MAAM,OAAO,GAAyC,OAAO,CAAC;QAC9D,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;IACjB,CAAC;CACJ;AA5BD,0EA4BC","sourcesContent":["import type { WebpiecesRouter } from './WebpiecesRouter';\nimport type {\n LazyController,\n LazyImplementation,\n ApplicationImplementation,\n} from './LazyController';\n\nabstract class StringApi {\n abstract read(): Promise<string>;\n}\nabstract class NumberApi {\n abstract read(): Promise<number>;\n}\n\n/** Compiled by tsc, never invoked: implementation types must agree with the registered API. */\nexport class LazyControllerCompileAssertions {\n routes(\n router: WebpiecesRouter,\n strings: LazyController<StringApi>,\n numbers: LazyController<NumberApi>,\n ): void {\n router.addRoutes(StringApi, strings);\n // @ts-expect-error The deferred controller must implement this contract's result type.\n router.addRoutes(StringApi, numbers);\n }\n implementation(\n strings: LazyImplementation<StringApi>,\n numbers: LazyImplementation<NumberApi>,\n ): void {\n // @ts-expect-error A number-result implementation cannot be a string-result implementation.\n const invalid: LazyImplementation<StringApi> = numbers;\n void invalid;\n void strings;\n }\n application(\n strings: ApplicationImplementation<StringApi>,\n numbers: ApplicationImplementation<NumberApi>,\n ): void {\n // @ts-expect-error Application-container mode still enforces the API's result type.\n const invalid: ApplicationImplementation<StringApi> = numbers;\n void invalid;\n void strings;\n }\n}\n"]}
package/src/index.d.ts CHANGED
@@ -36,4 +36,4 @@ export type { ApiDocumentObject, ApiDocumentValue } from './AuthorizedApiDocumen
36
36
  export { WiringPolicy } from '@webpieces/http-client-core';
37
37
  export { RuntimeStartupPhase, RuntimeStartupOperation } from './RuntimeStartupTiming';
38
38
  export type { RuntimeStartupObserver, RuntimeStartupSpan } from './RuntimeStartupTiming';
39
- export { LazyController, LazyImplementation, LazyFeatureTimer, LazyFeatureDeadline } from './LazyController';
39
+ export { LazyController, LazyImplementation, ApplicationImplementation, 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.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;
5
+ exports.LazyFeatureDeadline = exports.LazyFeatureTimer = exports.ApplicationImplementation = 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; } });
@@ -186,6 +186,7 @@ Object.defineProperty(exports, "RuntimeStartupOperation", { enumerable: true, ge
186
186
  var LazyController_1 = require("./LazyController");
187
187
  Object.defineProperty(exports, "LazyController", { enumerable: true, get: function () { return LazyController_1.LazyController; } });
188
188
  Object.defineProperty(exports, "LazyImplementation", { enumerable: true, get: function () { return LazyController_1.LazyImplementation; } });
189
+ Object.defineProperty(exports, "ApplicationImplementation", { enumerable: true, get: function () { return LazyController_1.ApplicationImplementation; } });
189
190
  Object.defineProperty(exports, "LazyFeatureTimer", { enumerable: true, get: function () { return LazyController_1.LazyFeatureTimer; } });
190
191
  Object.defineProperty(exports, "LazyFeatureDeadline", { enumerable: true, get: function () { return LazyController_1.LazyFeatureDeadline; } });
191
192
  //# 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 } 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"]}
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, ApplicationImplementation, LazyFeatureTimer, LazyFeatureDeadline } from './LazyController';\n"]}