@controller-contract/server 0.2.7 → 0.3.3

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/dist/index.d.mts CHANGED
@@ -1,24 +1,28 @@
1
- import { ControllerContractProduct, ExitOutput, FailOutput, InputChannel, Method, NextOutput, NoInput, Output, ParamsFrom, PassOutput } from "@controller-contract/core";
1
+ import { ControllerContract, ExitOutput, FailOutput, InputChannel, Method, NextOutput, NoInput, Output, ParamsFrom, PassOutput } from "@controller-contract/core";
2
2
  import { StandardSchemaV1 } from "@standard-schema/spec";
3
-
3
+ //#region src/classes/controller-contract-controller/controller-contract-controller.d.ts
4
+ type ControllerContractController<TMethod extends Method, TPath extends string, TParamsInput, TQueryInput, TBodyInput, TOuput extends Output, TRouter> = (() => TRouter) & {
5
+ '~cc'?: TMethod | TPath | TParamsInput | TQueryInput | TBodyInput | TOuput;
6
+ };
7
+ //#endregion
4
8
  //#region src/interfaces/ControllerContractSpec.d.ts
5
- interface NullaryControllerContractSpec<TContext, TInject> {
9
+ interface NullaryControllerContractSpec<TFrameworkContext, TInject> {
6
10
  readonly type: 'nullary';
7
11
  readonly injectable: TInject;
8
12
  readonly method: Method;
9
13
  readonly path: string;
10
- readonly outputFn: OutputFn<TContext, string, Output>;
14
+ readonly outputFn: OutputFn<TFrameworkContext, string, Output>;
11
15
  }
12
- interface SanitizedControllerContractSpec<TContext, TInject> {
16
+ interface SanitizedControllerContractSpec<TFrameworkContext, TInject> {
13
17
  readonly type: 'sanitized';
14
18
  readonly injectable: TInject;
15
19
  readonly method: Method;
16
20
  readonly path: string;
17
21
  readonly channel: InputChannel;
18
22
  readonly schema: StandardSchemaV1;
19
- readonly outputFn: SanitizedOutputFn<TContext, string, unknown, Output>;
23
+ readonly outputFn: SanitizedOutputFn<TFrameworkContext, string, unknown, Output>;
20
24
  }
21
- type ControllerContractSpec<TContext, TInject> = NullaryControllerContractSpec<TContext, TInject> | SanitizedControllerContractSpec<TContext, TInject>;
25
+ type ControllerContractSpec<TFrameworkContext, TInject> = NullaryControllerContractSpec<TFrameworkContext, TInject> | SanitizedControllerContractSpec<TFrameworkContext, TInject>;
22
26
  //#endregion
23
27
  //#region src/utils/outputs.d.ts
24
28
  declare namespace outputs {
@@ -53,68 +57,81 @@ declare const StandardOutputs: Readonly<{
53
57
  }>;
54
58
  //#endregion
55
59
  //#region src/types/index.d.ts
56
- type IntegratorFn<TContext, TInject, TProduct> = (spec: ControllerContractSpec<TContext, TInject>) => TProduct;
57
- type RouterAdapterFn<TProduct> = (routes: Record<string, TProduct>) => TProduct;
58
- type Prettify<T> = { [K in keyof T]: T[K] } & {};
59
- type OutputFn<TContext, TPath extends string, TOutput> = (context: Prettify<TContext & {
60
+ type BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter> = (spec: ControllerContractSpec<TFrameworkContext, TFrameworkInject>) => TFrameworkRouter;
61
+ type RouterIntegratorFn<TRouter> = <TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>>(routes: TRoutes) => TRouter;
62
+ type Prettify<T> = { [K in keyof T]: T[K]; } & {};
63
+ type OutputFn<TFrameworkContext, TPath extends string, TOutput> = (context: Prettify<TFrameworkContext & {
60
64
  params: ParamsFrom<TPath>;
61
65
  outputs: typeof outputs;
62
66
  }>) => Promise<TOutput>;
63
- type SanitizedOutputFn<TContext, TPath extends string, TInput, TOutput> = OutputFn<TContext & {
67
+ type SanitizedOutputFn<TFrameworkContext, TPath extends string, TInput, TOutput> = OutputFn<TFrameworkContext & {
64
68
  input: TInput;
65
69
  }, TPath, TOutput>;
70
+ type InferControllerContract<T> = T extends ControllerContractController<infer M, infer P, any, infer Q, infer B, infer O, any> ? ControllerContract<M, P, ParamsFrom<P>, Q, B, O> : never;
71
+ type MapToControllerContract<TRoutes> = { [TRouteName in Extract<keyof TRoutes, string> as Capitalize<TRouteName>]: InferControllerContract<TRoutes[TRouteName]>; };
66
72
  //#endregion
67
- //#region src/classes/PostInputStep.d.ts
68
- declare class PostInputStep<TContext, TInject, TProduct, const TMethod extends Method, const TPath extends string, const TChannel extends InputChannel, TInput, TOutputFromInput extends Output> {
73
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-input-step.d.ts
74
+ declare class PostInputStep<TFrameworkContext, TFrameworkInject, TRouter, const TMethod extends Method, const TPath extends string, const TChannel extends InputChannel, TInput, TOutputFromInput extends Output> {
69
75
  private readonly injectable;
70
76
  private readonly integrator;
71
77
  private readonly method;
72
78
  private readonly path;
73
79
  private readonly channel;
74
80
  private readonly schema;
75
- constructor(injectable: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>, method: TMethod, path: TPath, channel: TChannel, schema: StandardSchemaV1<TInput>);
76
- output<TOutput extends Output>(outputFn: SanitizedOutputFn<TContext, TPath, TInput, TOutput>): ControllerContractProduct<TMethod, TPath, ParamsFrom<TPath>, TChannel extends "query" ? TInput : NoInput, TChannel extends "body" ? TInput : NoInput, TOutputFromInput | TOutput, TProduct>;
81
+ constructor(injectable: TFrameworkInject, integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>, method: TMethod, path: TPath, channel: TChannel, schema: StandardSchemaV1<TInput>);
82
+ output<TOutput extends Output>(outputFn: SanitizedOutputFn<TFrameworkContext, TPath, TInput, TOutput>): ControllerContractController<TMethod, TPath, ParamsFrom<TPath>, TChannel extends 'query' ? TInput : NoInput, TChannel extends 'body' ? TInput : NoInput, TOutputFromInput | TOutput, TRouter>;
77
83
  }
78
84
  //#endregion
79
- //#region src/classes/PostEndpointStep.d.ts
80
- declare class PostEndpointStep<TContext, TInject, TProduct, const TMethod extends Method, const TPath extends string> {
85
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-endpoint-step.d.ts
86
+ declare class PostEndpointStep<TFrameworkContext, TFrameworkInject, TRouter, const TMethod extends Method, const TPath extends string> {
81
87
  private readonly injectable;
82
88
  private readonly integrator;
83
89
  private readonly method;
84
90
  private readonly path;
85
- constructor(injectable: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>, method: TMethod, path: TPath);
86
- input<const TChannel extends InputChannel, TInput>(channel: TChannel, schema: StandardSchemaV1<TInput>): PostInputStep<TContext, TInject, TProduct, TMethod, TPath, TChannel, TInput, FailOutput<Extract<keyof TInput, string>>>;
87
- output<TOutput extends Output>(outputFn: OutputFn<TContext, TPath, TOutput>): ControllerContractProduct<TMethod, TPath, ParamsFrom<TPath>, NoInput, NoInput, TOutput, TProduct>;
91
+ constructor(injectable: TFrameworkInject, integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>, method: TMethod, path: TPath);
92
+ input<const TChannel extends InputChannel, TInput>(channel: TChannel, schema: StandardSchemaV1<TInput>): PostInputStep<TFrameworkContext, TFrameworkInject, TRouter, TMethod, TPath, TChannel, TInput, FailOutput<Extract<keyof TInput, string>>>;
93
+ output<TOutput extends Output>(outputFn: OutputFn<TFrameworkContext, TPath, TOutput>): ControllerContractController<TMethod, TPath, ParamsFrom<TPath>, NoInput, NoInput, TOutput, TRouter>;
88
94
  }
89
95
  //#endregion
90
- //#region src/classes/PostInjectStep.d.ts
91
- declare class PostInjectStep<TContext, TInject, TProduct> {
96
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-inject-step.d.ts
97
+ declare class PostInjectStep<TFrameworkContext, TFrameworkInject, TRouter> {
92
98
  private readonly injectable;
93
99
  private readonly integrator;
94
- constructor(injectable: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>);
95
- endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath): PostEndpointStep<TContext, TInject, TProduct, TMethod, TPath>;
100
+ constructor(injectable: TFrameworkInject, integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>);
101
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath): PostEndpointStep<TFrameworkContext, TFrameworkInject, TRouter, TMethod, TPath>;
96
102
  }
97
103
  //#endregion
98
- //#region src/classes/ControllerContractBuilder.d.ts
99
- declare class ControllerContractBuilder<TContext, TInject, TProduct> {
104
+ //#region src/classes/controller-contract-controller-builder/controller-contract-controller-builder.d.ts
105
+ declare class ControllerContractControllerBuilder<TFrameworkContext, TFrameworkInject, TFrameworkRouter> {
100
106
  private readonly injectableDefaultValue;
101
107
  private readonly integrator;
102
- constructor(injectableDefaultValue: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>);
103
- inject(injectable: TInject): PostInjectStep<TContext, TInject, TProduct>;
104
- endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath): PostEndpointStep<TContext, TInject, TProduct, TMethod, TPath>;
108
+ constructor(injectableDefaultValue: TFrameworkInject, integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter>);
109
+ inject(injectable: TFrameworkInject): PostInjectStep<TFrameworkContext, TFrameworkInject, TFrameworkRouter>;
110
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath): PostEndpointStep<TFrameworkContext, TFrameworkInject, TFrameworkRouter, TMethod, TPath>;
111
+ }
112
+ //#endregion
113
+ //#region src/classes/controller-contract-controller-router/controller-contract-controller-router.d.ts
114
+ declare class ControllerContractControllerRouter<TRouter, TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>> {
115
+ private readonly integrator;
116
+ private readonly routes;
117
+ constructor(integrator: RouterIntegratorFn<TRouter>, routes: TRoutes);
118
+ getIntegratedRouter(): TRouter;
105
119
  }
106
120
  //#endregion
107
- //#region src/classes/ControllerContractRouter.d.ts
108
- declare class ControllerContractRouter<TProduct> {
109
- private readonly routerAdapterFn;
110
- constructor(routerAdapterFn: RouterAdapterFn<TProduct>);
111
- getRouter(routes: Record<string, TProduct>): TProduct;
121
+ //#region src/classes/controller-contract-controller-router/controller-contract-controller-router-factory.d.ts
122
+ declare class ControllerContractControllerRouterFactory<TRouter> {
123
+ private readonly integrator;
124
+ constructor(integrator: RouterIntegratorFn<TRouter>);
125
+ createControllerContractControllerRouter<TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>>(routes: TRoutes): ControllerContractControllerRouter<TRouter, TRoutes>;
112
126
  }
113
127
  //#endregion
114
- //#region src/classes/ControllerContractAdapterFactory.d.ts
115
- declare class ControllerContractAdapterFactory<TContext, TInject, TProduct> {
116
- createBuilder(injectableDefaultValue: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>): ControllerContractBuilder<TContext, TInject, TProduct>;
117
- createRouter(routerAdapterFn: RouterAdapterFn<TProduct>): ControllerContractRouter<TProduct>;
128
+ //#region src/classes/framework-integration-factory.d.ts
129
+ declare class FrameworkIntegrationFactory<TFrameworkContext, TFrameworkInject, TFrameworkRouter> {
130
+ createControllerContractControllerBuilder(injectableDefaultValue: TFrameworkInject, integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter>): ControllerContractControllerBuilder<TFrameworkContext, TFrameworkInject, TFrameworkRouter>;
131
+ createControllerContractControllerRouterFactory(integrator: RouterIntegratorFn<TFrameworkRouter>): ControllerContractControllerRouterFactory<TFrameworkRouter>;
118
132
  }
119
133
  //#endregion
120
- export { ControllerContractAdapterFactory, StandardOutputs, outputs, rootOnly };
134
+ //#region src/types/infer-controller-contracts-from-router.d.ts
135
+ type InferControllerContractsFromRouter<T> = T extends ControllerContractControllerRouter<any, infer TRoutes> ? MapToControllerContract<TRoutes> : never;
136
+ //#endregion
137
+ export { FrameworkIntegrationFactory, InferControllerContractsFromRouter, StandardOutputs, outputs, rootOnly };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/classes/PostInputStep.ts
1
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-input-step.ts
2
2
  var PostInputStep = class {
3
3
  injectable;
4
4
  integrator;
@@ -28,7 +28,7 @@ var PostInputStep = class {
28
28
  }
29
29
  };
30
30
  //#endregion
31
- //#region src/classes/PostEndpointStep.ts
31
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-endpoint-step.ts
32
32
  var PostEndpointStep = class {
33
33
  injectable;
34
34
  integrator;
@@ -55,7 +55,7 @@ var PostEndpointStep = class {
55
55
  }
56
56
  };
57
57
  //#endregion
58
- //#region src/classes/PostInjectStep.ts
58
+ //#region src/classes/controller-contract-controller-builder/builder-steps/post-inject-step.ts
59
59
  var PostInjectStep = class {
60
60
  injectable;
61
61
  integrator;
@@ -68,8 +68,8 @@ var PostInjectStep = class {
68
68
  }
69
69
  };
70
70
  //#endregion
71
- //#region src/classes/ControllerContractBuilder.ts
72
- var ControllerContractBuilder = class {
71
+ //#region src/classes/controller-contract-controller-builder/controller-contract-controller-builder.ts
72
+ var ControllerContractControllerBuilder = class {
73
73
  injectableDefaultValue;
74
74
  integrator;
75
75
  constructor(injectableDefaultValue, integrator) {
@@ -84,24 +84,37 @@ var ControllerContractBuilder = class {
84
84
  }
85
85
  };
86
86
  //#endregion
87
- //#region src/classes/ControllerContractRouter.ts
88
- var ControllerContractRouter = class {
89
- routerAdapterFn;
90
- constructor(routerAdapterFn) {
91
- this.routerAdapterFn = routerAdapterFn;
87
+ //#region src/classes/controller-contract-controller-router/controller-contract-controller-router.ts
88
+ var ControllerContractControllerRouter = class {
89
+ integrator;
90
+ routes;
91
+ constructor(integrator, routes) {
92
+ this.integrator = integrator;
93
+ this.routes = routes;
94
+ }
95
+ getIntegratedRouter() {
96
+ return this.integrator(this.routes);
97
+ }
98
+ };
99
+ //#endregion
100
+ //#region src/classes/controller-contract-controller-router/controller-contract-controller-router-factory.ts
101
+ var ControllerContractControllerRouterFactory = class {
102
+ integrator;
103
+ constructor(integrator) {
104
+ this.integrator = integrator;
92
105
  }
93
- getRouter(routes) {
94
- return this.routerAdapterFn(routes);
106
+ createControllerContractControllerRouter(routes) {
107
+ return new ControllerContractControllerRouter(this.integrator, routes);
95
108
  }
96
109
  };
97
110
  //#endregion
98
- //#region src/classes/ControllerContractAdapterFactory.ts
99
- var ControllerContractAdapterFactory = class {
100
- createBuilder(injectableDefaultValue, integrator) {
101
- return new ControllerContractBuilder(injectableDefaultValue, integrator);
111
+ //#region src/classes/framework-integration-factory.ts
112
+ var FrameworkIntegrationFactory = class {
113
+ createControllerContractControllerBuilder(injectableDefaultValue, integrator) {
114
+ return new ControllerContractControllerBuilder(injectableDefaultValue, integrator);
102
115
  }
103
- createRouter(routerAdapterFn) {
104
- return new ControllerContractRouter(routerAdapterFn);
116
+ createControllerContractControllerRouterFactory(integrator) {
117
+ return new ControllerContractControllerRouterFactory(integrator);
105
118
  }
106
119
  };
107
120
  //#endregion
@@ -155,4 +168,4 @@ const StandardOutputs = Object.freeze({
155
168
  BadGateway: outputs.fail(rootOnly("Bad Gateway"), 502)
156
169
  });
157
170
  //#endregion
158
- export { ControllerContractAdapterFactory, StandardOutputs, outputs, rootOnly };
171
+ export { FrameworkIntegrationFactory, StandardOutputs, outputs, rootOnly };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@controller-contract/server",
3
3
  "type": "module",
4
- "version": "0.2.7",
4
+ "version": "0.3.3",
5
5
  "author": "kennychulo",
6
6
  "license": "MIT",
7
7
  "files": [
@@ -18,14 +18,14 @@
18
18
  "access": "public"
19
19
  },
20
20
  "devDependencies": {
21
- "@types/node": "22.19.19",
22
- "tsdown": "0.22.0",
23
- "typescript": "6.0.3"
21
+ "@controller-contract/core": "0.3.2"
24
22
  },
25
23
  "dependencies": {
26
- "@controller-contract/core": "0.2.12",
27
24
  "@standard-schema/spec": "1.1.0"
28
25
  },
26
+ "peerDependencies": {
27
+ "@controller-contract/core": "0.3.2"
28
+ },
29
29
  "scripts": {
30
30
  "build": "tsdown",
31
31
  "release": "pnpm publish"
@@ -0,0 +1,14 @@
1
+ import type { Method, Output } from '@controller-contract/core';
2
+
3
+ export type ControllerContractController<
4
+ TMethod extends Method,
5
+ TPath extends string,
6
+ TParamsInput,
7
+ TQueryInput,
8
+ TBodyInput,
9
+ TOuput extends Output,
10
+ TRouter,
11
+ > = (() => TRouter) & {
12
+ // Suppresses the linter warning about unused variables
13
+ '~cc'?: TMethod | TPath | TParamsInput | TQueryInput | TBodyInput | TOuput;
14
+ };
@@ -0,0 +1,48 @@
1
+ import type { FailOutput, InputChannel, Method, NoInput, Output, ParamsFrom } from '@controller-contract/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import type { NullaryControllerContractSpec } from '../../../interfaces/ControllerContractSpec';
4
+ import type { BuilderIntegratorFn, OutputFn } from '../../../types';
5
+ import type { ControllerContractController } from '../../controller-contract-controller/controller-contract-controller';
6
+ import { PostInputStep } from './post-input-step';
7
+
8
+ export class PostEndpointStep<
9
+ TFrameworkContext,
10
+ TFrameworkInject,
11
+ TRouter,
12
+ const TMethod extends Method,
13
+ const TPath extends string,
14
+ > {
15
+ constructor(
16
+ private readonly injectable: TFrameworkInject,
17
+ private readonly integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>,
18
+ private readonly method: TMethod,
19
+ private readonly path: TPath,
20
+ ) {}
21
+
22
+ input<const TChannel extends InputChannel, TInput>(channel: TChannel, schema: StandardSchemaV1<TInput>) {
23
+ return new PostInputStep<
24
+ TFrameworkContext,
25
+ TFrameworkInject,
26
+ TRouter,
27
+ TMethod,
28
+ TPath,
29
+ TChannel,
30
+ TInput,
31
+ FailOutput<Extract<keyof TInput, string>>
32
+ >(this.injectable, this.integrator, this.method, this.path, channel, schema);
33
+ }
34
+
35
+ output<TOutput extends Output>(outputFn: OutputFn<TFrameworkContext, TPath, TOutput>) {
36
+ const product = this.integrator(<NullaryControllerContractSpec<TFrameworkContext, TFrameworkInject>>{
37
+ type: 'nullary',
38
+ method: this.method,
39
+ path: this.path,
40
+ injectable: this.injectable,
41
+ outputFn,
42
+ });
43
+
44
+ return <ControllerContractController<TMethod, TPath, ParamsFrom<TPath>, NoInput, NoInput, TOutput, TRouter>>(
45
+ (() => product)
46
+ );
47
+ }
48
+ }
@@ -0,0 +1,19 @@
1
+ import type { Method } from '@controller-contract/core';
2
+ import type { BuilderIntegratorFn } from '../../../types';
3
+ import { PostEndpointStep } from './post-endpoint-step';
4
+
5
+ export class PostInjectStep<TFrameworkContext, TFrameworkInject, TRouter> {
6
+ constructor(
7
+ private readonly injectable: TFrameworkInject,
8
+ private readonly integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>,
9
+ ) {}
10
+
11
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
12
+ return new PostEndpointStep<TFrameworkContext, TFrameworkInject, TRouter, TMethod, TPath>(
13
+ this.injectable,
14
+ this.integrator,
15
+ method,
16
+ path,
17
+ );
18
+ }
19
+ }
@@ -1,19 +1,13 @@
1
- import type {
2
- ControllerContractProduct,
3
- InputChannel,
4
- Method,
5
- NoInput,
6
- Output,
7
- ParamsFrom,
8
- } from '@controller-contract/core';
1
+ import type { InputChannel, Method, NoInput, Output, ParamsFrom } from '@controller-contract/core';
9
2
  import type { StandardSchemaV1 } from '@standard-schema/spec';
10
- import type { SanitizedControllerContractSpec } from '../interfaces/ControllerContractSpec';
11
- import type { IntegratorFn, SanitizedOutputFn } from '../types';
3
+ import type { SanitizedControllerContractSpec } from '../../../interfaces/ControllerContractSpec';
4
+ import type { BuilderIntegratorFn, SanitizedOutputFn } from '../../../types';
5
+ import type { ControllerContractController } from '../../controller-contract-controller/controller-contract-controller';
12
6
 
13
7
  export class PostInputStep<
14
- TContext,
15
- TInject,
16
- TProduct,
8
+ TFrameworkContext,
9
+ TFrameworkInject,
10
+ TRouter,
17
11
  const TMethod extends Method,
18
12
  const TPath extends string,
19
13
  const TChannel extends InputChannel,
@@ -21,16 +15,16 @@ export class PostInputStep<
21
15
  TOutputFromInput extends Output,
22
16
  > {
23
17
  constructor(
24
- private readonly injectable: TInject,
25
- private readonly integrator: IntegratorFn<TContext, TInject, TProduct>,
18
+ private readonly injectable: TFrameworkInject,
19
+ private readonly integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>,
26
20
  private readonly method: TMethod,
27
21
  private readonly path: TPath,
28
22
  private readonly channel: TChannel,
29
23
  private readonly schema: StandardSchemaV1<TInput>,
30
24
  ) {}
31
25
 
32
- output<TOutput extends Output>(outputFn: SanitizedOutputFn<TContext, TPath, TInput, TOutput>) {
33
- const product = this.integrator(<SanitizedControllerContractSpec<TContext, TInject>>{
26
+ output<TOutput extends Output>(outputFn: SanitizedOutputFn<TFrameworkContext, TPath, TInput, TOutput>) {
27
+ const product = this.integrator(<SanitizedControllerContractSpec<TFrameworkContext, TFrameworkInject>>{
34
28
  type: 'sanitized',
35
29
  injectable: this.injectable,
36
30
  method: this.method,
@@ -41,14 +35,14 @@ export class PostInputStep<
41
35
  });
42
36
 
43
37
  return <
44
- ControllerContractProduct<
38
+ ControllerContractController<
45
39
  TMethod,
46
40
  TPath,
47
41
  ParamsFrom<TPath>,
48
42
  TChannel extends 'query' ? TInput : NoInput,
49
43
  TChannel extends 'body' ? TInput : NoInput,
50
44
  TOutputFromInput | TOutput,
51
- TProduct
45
+ TRouter
52
46
  >
53
47
  >(() => product);
54
48
  }
@@ -0,0 +1,24 @@
1
+ import type { Method } from '@controller-contract/core';
2
+ import type { BuilderIntegratorFn } from '../../types';
3
+ import { PostEndpointStep } from './builder-steps/post-endpoint-step';
4
+ import { PostInjectStep } from './builder-steps/post-inject-step';
5
+
6
+ export class ControllerContractControllerBuilder<TFrameworkContext, TFrameworkInject, TFrameworkRouter> {
7
+ constructor(
8
+ private readonly injectableDefaultValue: TFrameworkInject,
9
+ private readonly integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter>,
10
+ ) {}
11
+
12
+ inject(injectable: TFrameworkInject) {
13
+ return new PostInjectStep<TFrameworkContext, TFrameworkInject, TFrameworkRouter>(injectable, this.integrator);
14
+ }
15
+
16
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
17
+ return new PostEndpointStep<TFrameworkContext, TFrameworkInject, TFrameworkRouter, TMethod, TPath>(
18
+ this.injectableDefaultValue,
19
+ this.integrator,
20
+ method,
21
+ path,
22
+ );
23
+ }
24
+ }
@@ -0,0 +1,13 @@
1
+ import type { RouterIntegratorFn } from '../../types';
2
+ import type { ControllerContractController } from '../controller-contract-controller/controller-contract-controller';
3
+ import { ControllerContractControllerRouter } from './controller-contract-controller-router';
4
+
5
+ export class ControllerContractControllerRouterFactory<TRouter> {
6
+ constructor(private readonly integrator: RouterIntegratorFn<TRouter>) {}
7
+
8
+ createControllerContractControllerRouter<
9
+ TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>,
10
+ >(routes: TRoutes) {
11
+ return new ControllerContractControllerRouter(this.integrator, routes);
12
+ }
13
+ }
@@ -0,0 +1,16 @@
1
+ import type { RouterIntegratorFn } from '../../types';
2
+ import type { ControllerContractController } from '../controller-contract-controller/controller-contract-controller';
3
+
4
+ export class ControllerContractControllerRouter<
5
+ TRouter,
6
+ TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>,
7
+ > {
8
+ constructor(
9
+ private readonly integrator: RouterIntegratorFn<TRouter>,
10
+ private readonly routes: TRoutes,
11
+ ) {}
12
+
13
+ getIntegratedRouter(): TRouter {
14
+ return this.integrator(this.routes);
15
+ }
16
+ }
@@ -0,0 +1,19 @@
1
+ import type { BuilderIntegratorFn, RouterIntegratorFn } from '../types';
2
+ import { ControllerContractControllerBuilder } from './controller-contract-controller-builder/controller-contract-controller-builder';
3
+ import { ControllerContractControllerRouterFactory } from './controller-contract-controller-router/controller-contract-controller-router-factory';
4
+
5
+ export class FrameworkIntegrationFactory<TFrameworkContext, TFrameworkInject, TFrameworkRouter> {
6
+ createControllerContractControllerBuilder(
7
+ injectableDefaultValue: TFrameworkInject,
8
+ integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter>,
9
+ ) {
10
+ return new ControllerContractControllerBuilder<TFrameworkContext, TFrameworkInject, TFrameworkRouter>(
11
+ injectableDefaultValue,
12
+ integrator,
13
+ );
14
+ }
15
+
16
+ createControllerContractControllerRouterFactory(integrator: RouterIntegratorFn<TFrameworkRouter>) {
17
+ return new ControllerContractControllerRouterFactory<TFrameworkRouter>(integrator);
18
+ }
19
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
- export * from './classes/ControllerContractAdapterFactory';
1
+ export * from './classes/framework-integration-factory';
2
+ export * from './types/infer-controller-contracts-from-router';
2
3
  export * from './utils';
@@ -2,24 +2,24 @@ import type { InputChannel, Method, Output } from '@controller-contract/core';
2
2
  import type { StandardSchemaV1 } from '@standard-schema/spec';
3
3
  import type { OutputFn, SanitizedOutputFn } from '../types';
4
4
 
5
- export interface NullaryControllerContractSpec<TContext, TInject> {
5
+ export interface NullaryControllerContractSpec<TFrameworkContext, TInject> {
6
6
  readonly type: 'nullary';
7
7
  readonly injectable: TInject;
8
8
  readonly method: Method;
9
9
  readonly path: string;
10
- readonly outputFn: OutputFn<TContext, string, Output>;
10
+ readonly outputFn: OutputFn<TFrameworkContext, string, Output>;
11
11
  }
12
12
 
13
- export interface SanitizedControllerContractSpec<TContext, TInject> {
13
+ export interface SanitizedControllerContractSpec<TFrameworkContext, TInject> {
14
14
  readonly type: 'sanitized';
15
15
  readonly injectable: TInject;
16
16
  readonly method: Method;
17
17
  readonly path: string;
18
18
  readonly channel: InputChannel;
19
19
  readonly schema: StandardSchemaV1;
20
- readonly outputFn: SanitizedOutputFn<TContext, string, unknown, Output>;
20
+ readonly outputFn: SanitizedOutputFn<TFrameworkContext, string, unknown, Output>;
21
21
  }
22
22
 
23
- export type ControllerContractSpec<TContext, TInject> =
24
- | NullaryControllerContractSpec<TContext, TInject>
25
- | SanitizedControllerContractSpec<TContext, TInject>;
23
+ export type ControllerContractSpec<TFrameworkContext, TInject> =
24
+ | NullaryControllerContractSpec<TFrameworkContext, TInject>
25
+ | SanitizedControllerContractSpec<TFrameworkContext, TInject>;
@@ -1,26 +1,44 @@
1
- import type { ParamsFrom } from '@controller-contract/core';
1
+ import type { ControllerContract, ParamsFrom } from '@controller-contract/core';
2
+ import type { ControllerContractController } from '../classes/controller-contract-controller/controller-contract-controller';
2
3
  import type { ControllerContractSpec } from '../interfaces/ControllerContractSpec';
3
4
  import type { outputs } from '../utils';
4
5
 
5
- export type IntegratorFn<TContext, TInject, TProduct> = (spec: ControllerContractSpec<TContext, TInject>) => TProduct;
6
+ export type BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter> = (
7
+ spec: ControllerContractSpec<TFrameworkContext, TFrameworkInject>,
8
+ ) => TFrameworkRouter;
6
9
 
7
- export type RouterAdapterFn<TProduct> = (routes: Record<string, TProduct>) => TProduct;
10
+ export type RouterIntegratorFn<TRouter> = <
11
+ TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>,
12
+ >(
13
+ routes: TRoutes,
14
+ ) => TRouter;
8
15
 
9
16
  export type Prettify<T> = {
10
17
  [K in keyof T]: T[K];
11
18
  } & {};
12
19
 
13
- export type OutputFn<TContext, TPath extends string, TOutput> = (
20
+ export type OutputFn<TFrameworkContext, TPath extends string, TOutput> = (
14
21
  context: Prettify<
15
- TContext & {
22
+ TFrameworkContext & {
16
23
  params: ParamsFrom<TPath>;
17
24
  outputs: typeof outputs;
18
25
  }
19
26
  >,
20
27
  ) => Promise<TOutput>;
21
28
 
22
- export type SanitizedOutputFn<TContext, TPath extends string, TInput, TOutput> = OutputFn<
23
- TContext & { input: TInput },
29
+ export type SanitizedOutputFn<TFrameworkContext, TPath extends string, TInput, TOutput> = OutputFn<
30
+ TFrameworkContext & { input: TInput },
24
31
  TPath,
25
32
  TOutput
26
33
  >;
34
+
35
+ export type InferControllerContract<T> =
36
+ T extends ControllerContractController<infer M, infer P, any, infer Q, infer B, infer O, any>
37
+ ? ControllerContract<M, P, ParamsFrom<P>, Q, B, O>
38
+ : never;
39
+
40
+ export type MapToControllerContract<TRoutes> = {
41
+ [TRouteName in Extract<keyof TRoutes, string> as Capitalize<TRouteName>]: InferControllerContract<
42
+ TRoutes[TRouteName]
43
+ >;
44
+ };
@@ -0,0 +1,5 @@
1
+ import type { ControllerContractControllerRouter } from '../classes/controller-contract-controller-router/controller-contract-controller-router';
2
+ import type { MapToControllerContract } from './index';
3
+
4
+ export type InferControllerContractsFromRouter<T> =
5
+ T extends ControllerContractControllerRouter<any, infer TRoutes> ? MapToControllerContract<TRoutes> : never;
@@ -1,13 +0,0 @@
1
- import type { IntegratorFn, RouterAdapterFn } from '../types';
2
- import { ControllerContractBuilder } from './ControllerContractBuilder';
3
- import { ControllerContractRouter } from './ControllerContractRouter';
4
-
5
- export class ControllerContractAdapterFactory<TContext, TInject, TProduct> {
6
- createBuilder(injectableDefaultValue: TInject, integrator: IntegratorFn<TContext, TInject, TProduct>) {
7
- return new ControllerContractBuilder<TContext, TInject, TProduct>(injectableDefaultValue, integrator);
8
- }
9
-
10
- createRouter(routerAdapterFn: RouterAdapterFn<TProduct>) {
11
- return new ControllerContractRouter<TProduct>(routerAdapterFn);
12
- }
13
- }
@@ -1,24 +0,0 @@
1
- import type { Method } from '@controller-contract/core';
2
- import type { IntegratorFn } from '../types';
3
- import { PostEndpointStep } from './PostEndpointStep';
4
- import { PostInjectStep } from './PostInjectStep';
5
-
6
- export class ControllerContractBuilder<TContext, TInject, TProduct> {
7
- constructor(
8
- private readonly injectableDefaultValue: TInject,
9
- private readonly integrator: IntegratorFn<TContext, TInject, TProduct>,
10
- ) {}
11
-
12
- inject(injectable: TInject) {
13
- return new PostInjectStep<TContext, TInject, TProduct>(injectable, this.integrator);
14
- }
15
-
16
- endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
17
- return new PostEndpointStep<TContext, TInject, TProduct, TMethod, TPath>(
18
- this.injectableDefaultValue,
19
- this.integrator,
20
- method,
21
- path,
22
- );
23
- }
24
- }
@@ -1,9 +0,0 @@
1
- import type { RouterAdapterFn } from '../types';
2
-
3
- export class ControllerContractRouter<TProduct> {
4
- constructor(private readonly routerAdapterFn: RouterAdapterFn<TProduct>) {}
5
-
6
- getRouter(routes: Record<string, TProduct>): TProduct {
7
- return this.routerAdapterFn(routes);
8
- }
9
- }
@@ -1,49 +0,0 @@
1
- import type {
2
- ControllerContractProduct,
3
- FailOutput,
4
- InputChannel,
5
- Method,
6
- NoInput,
7
- Output,
8
- ParamsFrom,
9
- } from '@controller-contract/core';
10
- import type { StandardSchemaV1 } from '@standard-schema/spec';
11
- import type { NullaryControllerContractSpec } from '../interfaces/ControllerContractSpec';
12
- import type { IntegratorFn, OutputFn } from '../types';
13
- import { PostInputStep } from './PostInputStep';
14
-
15
- export class PostEndpointStep<TContext, TInject, TProduct, const TMethod extends Method, const TPath extends string> {
16
- constructor(
17
- private readonly injectable: TInject,
18
- private readonly integrator: IntegratorFn<TContext, TInject, TProduct>,
19
- private readonly method: TMethod,
20
- private readonly path: TPath,
21
- ) {}
22
-
23
- input<const TChannel extends InputChannel, TInput>(channel: TChannel, schema: StandardSchemaV1<TInput>) {
24
- return new PostInputStep<
25
- TContext,
26
- TInject,
27
- TProduct,
28
- TMethod,
29
- TPath,
30
- TChannel,
31
- TInput,
32
- FailOutput<Extract<keyof TInput, string>>
33
- >(this.injectable, this.integrator, this.method, this.path, channel, schema);
34
- }
35
-
36
- output<TOutput extends Output>(outputFn: OutputFn<TContext, TPath, TOutput>) {
37
- const product = this.integrator(<NullaryControllerContractSpec<TContext, TInject>>{
38
- type: 'nullary',
39
- method: this.method,
40
- path: this.path,
41
- injectable: this.injectable,
42
- outputFn,
43
- });
44
-
45
- return <ControllerContractProduct<TMethod, TPath, ParamsFrom<TPath>, NoInput, NoInput, TOutput, TProduct>>(
46
- (() => product)
47
- );
48
- }
49
- }
@@ -1,19 +0,0 @@
1
- import type { Method } from '@controller-contract/core';
2
- import type { IntegratorFn } from '../types';
3
- import { PostEndpointStep } from './PostEndpointStep';
4
-
5
- export class PostInjectStep<TContext, TInject, TProduct> {
6
- constructor(
7
- private readonly injectable: TInject,
8
- private readonly integrator: IntegratorFn<TContext, TInject, TProduct>,
9
- ) {}
10
-
11
- endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
12
- return new PostEndpointStep<TContext, TInject, TProduct, TMethod, TPath>(
13
- this.injectable,
14
- this.integrator,
15
- method,
16
- path,
17
- );
18
- }
19
- }