@controller-contract/server 0.3.3 → 0.4.0

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 (47) hide show
  1. package/dist/index-DvVe6qYj.d.mts +44 -0
  2. package/dist/index.d.mts +181 -104
  3. package/dist/index.mjs +171 -113
  4. package/dist/utils.d.mts +2 -0
  5. package/dist/utils.mjs +59 -0
  6. package/package.json +11 -7
  7. package/src/classes/controller-builder/controller-builder.ts +24 -0
  8. package/src/classes/controller-builder/input-builder/input-builder.ts +20 -0
  9. package/src/classes/controller-builder/input-builder/steps/after-body-step.ts +19 -0
  10. package/src/classes/controller-builder/input-builder/steps/after-params-step.ts +26 -0
  11. package/src/classes/controller-builder/input-builder/steps/after-query-step.ts +24 -0
  12. package/src/classes/controller-builder/steps/endpoint-step.ts +19 -0
  13. package/src/classes/controller-builder/steps/input-step.ts +67 -0
  14. package/src/classes/controller-builder/steps/output-step.ts +70 -0
  15. package/src/classes/controller-router-factory.ts +31 -0
  16. package/src/classes/controller-router.ts +25 -0
  17. package/src/classes/framework-setup.ts +28 -0
  18. package/src/index.ts +1 -2
  19. package/src/interfaces/controller-blueprint.ts +34 -0
  20. package/src/interfaces/endable.ts +5 -0
  21. package/src/interfaces/index.ts +2 -0
  22. package/src/types/combine-routes-fn.ts +7 -0
  23. package/src/{classes/controller-contract-controller/controller-contract-controller.ts → types/controller.ts} +5 -5
  24. package/src/types/create-route-fn.ts +5 -0
  25. package/src/types/fail-output-from.ts +8 -0
  26. package/src/types/index.ts +12 -44
  27. package/src/types/infer-controller-contract.ts +8 -0
  28. package/src/types/infer-controller-contracts-from-router.ts +3 -3
  29. package/src/types/input-builder-fn.ts +6 -0
  30. package/src/types/map-to-controller-contract.ts +7 -0
  31. package/src/types/no-output-from-inputs.ts +1 -0
  32. package/src/types/output-fn-outputs.ts +4 -0
  33. package/src/types/output-fn.ts +23 -0
  34. package/src/types/prettify.ts +1 -0
  35. package/src/types/resolved-params.ts +8 -0
  36. package/src/utils/index.ts +2 -0
  37. package/src/utils/outputs.ts +9 -28
  38. package/src/utils/root-only.ts +8 -0
  39. package/src/utils/standard-outputs.ts +20 -0
  40. package/src/classes/controller-contract-controller-builder/builder-steps/post-endpoint-step.ts +0 -48
  41. package/src/classes/controller-contract-controller-builder/builder-steps/post-inject-step.ts +0 -19
  42. package/src/classes/controller-contract-controller-builder/builder-steps/post-input-step.ts +0 -49
  43. package/src/classes/controller-contract-controller-builder/controller-contract-controller-builder.ts +0 -24
  44. package/src/classes/controller-contract-controller-router/controller-contract-controller-router-factory.ts +0 -13
  45. package/src/classes/controller-contract-controller-router/controller-contract-controller-router.ts +0 -16
  46. package/src/classes/framework-integration-factory.ts +0 -19
  47. package/src/interfaces/ControllerContractSpec.ts +0 -25
@@ -0,0 +1,70 @@
1
+ import type {
2
+ ExitOutput,
3
+ FailOutput,
4
+ Method,
5
+ PassOutput,
6
+ PathParams,
7
+ } from '@controller-contract/core';
8
+
9
+ import type { ControllerBlueprintSchemas } from '../../../interfaces/controller-blueprint';
10
+ import type {
11
+ CreateRouteFn,
12
+ FailOutputFrom,
13
+ OutputFn,
14
+ Prettify,
15
+ ResolvedParams,
16
+ } from '../../../types';
17
+ import type { Controller } from '../../../types/controller';
18
+
19
+ export class OutputStep<
20
+ TFrameworkContext,
21
+ TFrameworkInjectable,
22
+ TFrameworkRouter,
23
+ const TMethod extends Method,
24
+ const TPath extends string,
25
+ TParams,
26
+ TQuery,
27
+ TBody,
28
+ > {
29
+ constructor(
30
+ private readonly injectable: TFrameworkInjectable,
31
+ private readonly createRoute: CreateRouteFn<
32
+ TFrameworkContext,
33
+ TFrameworkInjectable,
34
+ TFrameworkRouter
35
+ >,
36
+ private readonly method: TMethod,
37
+ private readonly path: TPath,
38
+ private readonly schemas: ControllerBlueprintSchemas<TParams, TQuery, TBody>,
39
+ ) {}
40
+
41
+ output<TOutput extends PassOutput<any> | FailOutput<any> | ExitOutput>(
42
+ outputFn: OutputFn<
43
+ TFrameworkContext,
44
+ Prettify<ResolvedParams<TParams, TPath>>,
45
+ TQuery,
46
+ TBody,
47
+ TOutput
48
+ >,
49
+ ) {
50
+ const route = this.createRoute({
51
+ injectable: this.injectable,
52
+ method: this.method,
53
+ path: this.path,
54
+ schemas: this.schemas,
55
+ outputFn,
56
+ });
57
+
58
+ return <
59
+ Controller<
60
+ TMethod,
61
+ TPath,
62
+ Prettify<PathParams<TPath>>,
63
+ TQuery,
64
+ TBody,
65
+ FailOutputFrom<TParams> | FailOutputFrom<TQuery> | FailOutputFrom<TBody> | TOutput,
66
+ TFrameworkRouter
67
+ >
68
+ >(() => route);
69
+ }
70
+ }
@@ -0,0 +1,31 @@
1
+ import type { CombineRoutesFn } from '../types';
2
+ import type { Controller } from '../types/controller';
3
+ import { ControllerRouter } from './controller-router';
4
+
5
+ type ControllerRouterRecord<TFrameworkRouter> = Record<
6
+ string,
7
+ Controller<any, any, any, any, any, any, TFrameworkRouter>
8
+ >;
9
+
10
+ export class ControllerRouterFactory<TFrameworkRouter> {
11
+ constructor(private readonly combineRoutes: CombineRoutesFn<TFrameworkRouter>) {}
12
+
13
+ /**
14
+ * @example
15
+ * const getUser = builder
16
+ * .endpoint('get', '/api/users/:id')
17
+ * .output(async ({ inputs, outputs }) => outputs.pass({ id: inputs.params.id }));
18
+ *
19
+ * const createUser = builder
20
+ * .endpoint('post', '/api/users')
21
+ * .input((s) => s.body(z.object({ name: z.string() })))
22
+ * .output(async ({ inputs, outputs }) => outputs.pass({ name: inputs.body.name }, 201));
23
+ *
24
+ * const usersRouter = controllerRouterFactory.createControllerRouter({ getUser, createUser });
25
+ */
26
+ createControllerRouter<TRoutes extends ControllerRouterRecord<TFrameworkRouter>>(
27
+ routes: TRoutes,
28
+ ) {
29
+ return new ControllerRouter(this.combineRoutes, routes);
30
+ }
31
+ }
@@ -0,0 +1,25 @@
1
+ import type { CombineRoutesFn } from '../types';
2
+ import type { Controller } from '../types/controller';
3
+
4
+ export class ControllerRouter<
5
+ TFrameworkRouter,
6
+ TRoutes extends Record<any, Controller<any, any, any, any, any, any, TFrameworkRouter>>,
7
+ > {
8
+ constructor(
9
+ private readonly combineRoutes: CombineRoutesFn<TFrameworkRouter>,
10
+ private readonly routes: TRoutes,
11
+ ) {}
12
+
13
+ /**
14
+ * @example
15
+ * const usersRouter = controllerRouterFactory.createControllerRouter({ getUser, createUser });
16
+ *
17
+ * const app = express();
18
+ * app.use(express.json());
19
+ * app.use(usersRouter.toRouter());
20
+ * app.listen(3000);
21
+ */
22
+ toRouter() {
23
+ return this.combineRoutes(this.routes);
24
+ }
25
+ }
@@ -0,0 +1,28 @@
1
+ import type { CombineRoutesFn, CreateRouteFn } from '../types';
2
+ import { ControllerBuilder } from './controller-builder/controller-builder';
3
+ import { ControllerRouterFactory } from './controller-router-factory';
4
+
5
+ /**
6
+ * @example
7
+ * const setup = new FrameworkSetup<Request, RequestHandler[], Router>();
8
+ */
9
+ export class FrameworkSetup<TFrameworkContext, TFrameworkInjectable, TFrameworkRouter> {
10
+ /**
11
+ * @example
12
+ * const builder = setup.createControllerBuilder([], (blueprint) => { ... });
13
+ */
14
+ createControllerBuilder(
15
+ defaultInjectable: TFrameworkInjectable,
16
+ createRoute: CreateRouteFn<TFrameworkContext, TFrameworkInjectable, TFrameworkRouter>,
17
+ ) {
18
+ return new ControllerBuilder(defaultInjectable, createRoute);
19
+ }
20
+
21
+ /**
22
+ * @example
23
+ * const routerFactory = setup.createControllerRouterFactory((routes) => { ... });
24
+ */
25
+ createControllerRouterFactory(combineRoutes: CombineRoutesFn<TFrameworkRouter>) {
26
+ return new ControllerRouterFactory(combineRoutes);
27
+ }
28
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
- export * from './classes/framework-integration-factory';
1
+ export * from './classes/framework-setup';
2
2
  export * from './types/infer-controller-contracts-from-router';
3
- export * from './utils';
@@ -0,0 +1,34 @@
1
+ import type { ExitOutput, FailOutput, Method, PassOutput } from '@controller-contract/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+
4
+ import type { OutputFnOutputs, Prettify } from '../types';
5
+
6
+ /**
7
+ * The true shapes aren't needed at this level. We only need a broad description.
8
+ */
9
+ export interface ControllerBlueprintSchemas<TParams, TQuery, TBody> {
10
+ params: StandardSchemaV1<any, TParams> | null;
11
+ query: StandardSchemaV1<any, TQuery> | null;
12
+ body: StandardSchemaV1<any, TBody> | null;
13
+ }
14
+
15
+ type OutputFnBlueprint<TFrameworkContext> = (
16
+ context: Prettify<
17
+ TFrameworkContext & {
18
+ inputs: {
19
+ params: any;
20
+ query: any;
21
+ body: any;
22
+ };
23
+ outputs: OutputFnOutputs;
24
+ }
25
+ >,
26
+ ) => Promise<PassOutput<any> | FailOutput<any> | ExitOutput>;
27
+
28
+ export interface ControllerBlueprint<TFrameworkContext, TFrameworkInjectable> {
29
+ readonly injectable: TFrameworkInjectable;
30
+ readonly method: Method;
31
+ readonly path: string;
32
+ readonly schemas: ControllerBlueprintSchemas<unknown, unknown, unknown>;
33
+ readonly outputFn: OutputFnBlueprint<TFrameworkContext>;
34
+ }
@@ -0,0 +1,5 @@
1
+ import type { ControllerBlueprintSchemas } from './controller-blueprint';
2
+
3
+ export interface Endable<TParams, TQuery, TBody> {
4
+ getSchemas(): ControllerBlueprintSchemas<TParams, TQuery, TBody>;
5
+ }
@@ -0,0 +1,2 @@
1
+ export * from './controller-blueprint';
2
+ export * from './endable';
@@ -0,0 +1,7 @@
1
+ import type { Controller } from './controller';
2
+
3
+ export type CombineRoutesFn<TFrameworkRouter> = <
4
+ TRoutes extends Record<any, Controller<any, any, any, any, any, any, TFrameworkRouter>>,
5
+ >(
6
+ routes: TRoutes,
7
+ ) => TFrameworkRouter;
@@ -1,14 +1,14 @@
1
1
  import type { Method, Output } from '@controller-contract/core';
2
2
 
3
- export type ControllerContractController<
3
+ export type Controller<
4
4
  TMethod extends Method,
5
5
  TPath extends string,
6
6
  TParamsInput,
7
7
  TQueryInput,
8
8
  TBodyInput,
9
- TOuput extends Output,
10
- TRouter,
11
- > = (() => TRouter) & {
9
+ TOutput extends Output,
10
+ TFrameworkRouter,
11
+ > = (() => TFrameworkRouter) & {
12
12
  // Suppresses the linter warning about unused variables
13
- '~cc'?: TMethod | TPath | TParamsInput | TQueryInput | TBodyInput | TOuput;
13
+ '~cc'?: TMethod | TPath | TParamsInput | TQueryInput | TBodyInput | TOutput;
14
14
  };
@@ -0,0 +1,5 @@
1
+ import type { ControllerBlueprint } from '../interfaces/controller-blueprint';
2
+
3
+ export type CreateRouteFn<TFrameworkContext, TFrameworkInjectable, TFrameworkRouter> = (
4
+ blueprint: ControllerBlueprint<TFrameworkContext, TFrameworkInjectable>,
5
+ ) => TFrameworkRouter;
@@ -0,0 +1,8 @@
1
+ import type { FailOutput, NoInput } from '@controller-contract/core';
2
+
3
+ /**
4
+ * The fail output a validated input can produce. Skipped inputs are `NoInput` and produce none.
5
+ */
6
+ export type FailOutputFrom<T> = [T] extends [NoInput]
7
+ ? never
8
+ : FailOutput<Extract<keyof T, string>>;
@@ -1,44 +1,12 @@
1
- import type { ControllerContract, ParamsFrom } from '@controller-contract/core';
2
- import type { ControllerContractController } from '../classes/controller-contract-controller/controller-contract-controller';
3
- import type { ControllerContractSpec } from '../interfaces/ControllerContractSpec';
4
- import type { outputs } from '../utils';
5
-
6
- export type BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TFrameworkRouter> = (
7
- spec: ControllerContractSpec<TFrameworkContext, TFrameworkInject>,
8
- ) => TFrameworkRouter;
9
-
10
- export type RouterIntegratorFn<TRouter> = <
11
- TRoutes extends Record<any, ControllerContractController<any, any, any, any, any, any, TRouter>>,
12
- >(
13
- routes: TRoutes,
14
- ) => TRouter;
15
-
16
- export type Prettify<T> = {
17
- [K in keyof T]: T[K];
18
- } & {};
19
-
20
- export type OutputFn<TFrameworkContext, TPath extends string, TOutput> = (
21
- context: Prettify<
22
- TFrameworkContext & {
23
- params: ParamsFrom<TPath>;
24
- outputs: typeof outputs;
25
- }
26
- >,
27
- ) => Promise<TOutput>;
28
-
29
- export type SanitizedOutputFn<TFrameworkContext, TPath extends string, TInput, TOutput> = OutputFn<
30
- TFrameworkContext & { input: TInput },
31
- TPath,
32
- TOutput
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
- };
1
+ export * from './combine-routes-fn';
2
+ export * from './controller';
3
+ export * from './create-route-fn';
4
+ export * from './fail-output-from';
5
+ export * from './infer-controller-contract';
6
+ export * from './infer-controller-contracts-from-router';
7
+ export * from './input-builder-fn';
8
+ export * from './map-to-controller-contract';
9
+ export * from './output-fn';
10
+ export * from './output-fn-outputs';
11
+ export * from './prettify';
12
+ export * from './resolved-params';
@@ -0,0 +1,8 @@
1
+ import type { ControllerContract, PathParams } from '@controller-contract/core';
2
+
3
+ import type { Controller } from './controller';
4
+
5
+ export type InferControllerContract<T> =
6
+ T extends Controller<infer M, infer P, any, infer Q, infer B, infer O, any>
7
+ ? ControllerContract<M, P, PathParams<P>, Q, B, O>
8
+ : never;
@@ -1,5 +1,5 @@
1
- import type { ControllerContractControllerRouter } from '../classes/controller-contract-controller-router/controller-contract-controller-router';
2
- import type { MapToControllerContract } from './index';
1
+ import type { ControllerRouter } from '../classes/controller-router';
2
+ import type { MapToControllerContract } from './map-to-controller-contract';
3
3
 
4
4
  export type InferControllerContractsFromRouter<T> =
5
- T extends ControllerContractControllerRouter<any, infer TRoutes> ? MapToControllerContract<TRoutes> : never;
5
+ T extends ControllerRouter<any, infer TRoutes> ? MapToControllerContract<TRoutes> : never;
@@ -0,0 +1,6 @@
1
+ import type { InputBuilder } from '../classes/controller-builder/input-builder/input-builder';
2
+ import type { Endable } from '../interfaces/endable';
3
+
4
+ export type InputBuilderFn<TParams, TQuery, TBody> = (
5
+ inputBuilder: InputBuilder,
6
+ ) => Endable<TParams, TQuery, TBody>;
@@ -0,0 +1,7 @@
1
+ import type { InferControllerContract } from './infer-controller-contract';
2
+
3
+ export type MapToControllerContract<TRoutes> = {
4
+ [TRouteName in Extract<keyof TRoutes, string> as Capitalize<TRouteName>]: InferControllerContract<
5
+ TRoutes[TRouteName]
6
+ >;
7
+ };
@@ -0,0 +1 @@
1
+ export type NoOutputFromInputs = never;
@@ -0,0 +1,4 @@
1
+ import type { outputs } from '../utils';
2
+ import type { Prettify } from './prettify';
3
+
4
+ export type OutputFnOutputs = Prettify<Omit<typeof outputs, 'next'>>;
@@ -0,0 +1,23 @@
1
+ import type { ExitOutput, FailOutput, PassOutput } from '@controller-contract/core';
2
+
3
+ import type { OutputFnOutputs } from './output-fn-outputs';
4
+ import type { Prettify } from './prettify';
5
+
6
+ export type OutputFn<
7
+ TFrameworkContext,
8
+ TParams,
9
+ TQuery,
10
+ TBody,
11
+ TOutput extends PassOutput<any> | FailOutput<any> | ExitOutput,
12
+ > = (
13
+ context: Prettify<
14
+ TFrameworkContext & {
15
+ inputs: {
16
+ params: TParams;
17
+ query: TQuery;
18
+ body: TBody;
19
+ };
20
+ outputs: OutputFnOutputs;
21
+ }
22
+ >,
23
+ ) => Promise<TOutput>;
@@ -0,0 +1 @@
1
+ export type Prettify<T> = { [K in keyof T]: T[K] } & {};
@@ -0,0 +1,8 @@
1
+ import type { NoInput, PathParams } from '@controller-contract/core';
2
+
3
+ /**
4
+ * Falls back to the raw path params when no params schema was given.
5
+ */
6
+ export type ResolvedParams<TParams, TPath extends string> = [TParams] extends [NoInput]
7
+ ? PathParams<TPath>
8
+ : TParams;
@@ -1 +1,3 @@
1
1
  export * from './outputs';
2
+ export * from './root-only';
3
+ export * from './standard-outputs';
@@ -1,55 +1,36 @@
1
1
  import type { ExitOutput, FailOutput, NextOutput, PassOutput } from '@controller-contract/core';
2
2
 
3
- export namespace outputs {
4
- export function next<T>(data: T, code = 100): NextOutput<T> {
3
+ export const outputs = Object.freeze({
4
+ next<T>(data: T, code = 100): NextOutput<T> {
5
5
  return {
6
6
  type: 'next',
7
7
  code,
8
8
  data,
9
9
  };
10
- }
10
+ },
11
11
 
12
- export function pass<T>(data: T, code = 200): PassOutput<T> {
12
+ pass<T>(data: T, code = 200): PassOutput<T> {
13
13
  return {
14
14
  type: 'pass',
15
15
  code,
16
16
  data,
17
17
  };
18
- }
18
+ },
19
19
 
20
- export function fail<const T extends string>(data: FailOutput<T>['data'], code = 400): FailOutput<T> {
20
+ fail<const T extends string>(data: FailOutput<T>['data'], code = 400): FailOutput<T> {
21
21
  return {
22
22
  type: 'fail',
23
23
  code,
24
24
  data,
25
25
  };
26
- }
26
+ },
27
27
 
28
28
  /**
29
29
  * Used to escape the controller contract state machine, useful for redirects.
30
30
  */
31
- export function exit(): ExitOutput {
31
+ exit(): ExitOutput {
32
32
  return {
33
33
  type: 'exit',
34
34
  };
35
- }
36
- }
37
-
38
- export function rootOnly(message: string): FailOutput<'root'>['data'] {
39
- return [{ key: 'root', message }];
40
- }
41
-
42
- export const StandardOutputs = Object.freeze({
43
- // 200
44
- OK: outputs.pass(rootOnly('ok'), 200),
45
- Created: outputs.pass(rootOnly('Created'), 201),
46
- Accepted: outputs.pass(rootOnly('Accepted'), 202),
47
- // 400
48
- BadRequest: outputs.fail(rootOnly('Bad Request'), 400),
49
- Unauthorized: outputs.fail(rootOnly('Unauthorized'), 401),
50
- Forbidden: outputs.fail(rootOnly('Forbidden'), 403),
51
- NotFound: outputs.fail(rootOnly('Not Found'), 404),
52
- // 500
53
- InternalServerError: outputs.fail(rootOnly('Internal Server Error'), 500),
54
- BadGateway: outputs.fail(rootOnly('Bad Gateway'), 502),
35
+ },
55
36
  });
@@ -0,0 +1,8 @@
1
+ import type { FailOutput } from '@controller-contract/core';
2
+
3
+ /**
4
+ * Useful for quickly sending a root level error to the client.
5
+ */
6
+ export function rootOnly(message: string): FailOutput<'root'>['data'] {
7
+ return [{ key: 'root', message }];
8
+ }
@@ -0,0 +1,20 @@
1
+ import { outputs } from './outputs';
2
+ import { rootOnly } from './root-only';
3
+
4
+ /**
5
+ * Useful for quick http basic responses.
6
+ */
7
+ export const StandardOutputs = Object.freeze({
8
+ // 200
9
+ OK: outputs.pass(rootOnly('ok'), 200),
10
+ Created: outputs.pass(rootOnly('Created'), 201),
11
+ Accepted: outputs.pass(rootOnly('Accepted'), 202),
12
+ // 400
13
+ BadRequest: outputs.fail(rootOnly('Bad Request'), 400),
14
+ Unauthorized: outputs.fail(rootOnly('Unauthorized'), 401),
15
+ Forbidden: outputs.fail(rootOnly('Forbidden'), 403),
16
+ NotFound: outputs.fail(rootOnly('Not Found'), 404),
17
+ // 500
18
+ InternalServerError: outputs.fail(rootOnly('Internal Server Error'), 500),
19
+ BadGateway: outputs.fail(rootOnly('Bad Gateway'), 502),
20
+ });
@@ -1,48 +0,0 @@
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
- }
@@ -1,19 +0,0 @@
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,49 +0,0 @@
1
- import type { InputChannel, Method, NoInput, Output, ParamsFrom } from '@controller-contract/core';
2
- import type { StandardSchemaV1 } from '@standard-schema/spec';
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';
6
-
7
- export class PostInputStep<
8
- TFrameworkContext,
9
- TFrameworkInject,
10
- TRouter,
11
- const TMethod extends Method,
12
- const TPath extends string,
13
- const TChannel extends InputChannel,
14
- TInput,
15
- TOutputFromInput extends Output,
16
- > {
17
- constructor(
18
- private readonly injectable: TFrameworkInject,
19
- private readonly integrator: BuilderIntegratorFn<TFrameworkContext, TFrameworkInject, TRouter>,
20
- private readonly method: TMethod,
21
- private readonly path: TPath,
22
- private readonly channel: TChannel,
23
- private readonly schema: StandardSchemaV1<TInput>,
24
- ) {}
25
-
26
- output<TOutput extends Output>(outputFn: SanitizedOutputFn<TFrameworkContext, TPath, TInput, TOutput>) {
27
- const product = this.integrator(<SanitizedControllerContractSpec<TFrameworkContext, TFrameworkInject>>{
28
- type: 'sanitized',
29
- injectable: this.injectable,
30
- method: this.method,
31
- path: this.path,
32
- channel: this.channel,
33
- schema: this.schema,
34
- outputFn,
35
- });
36
-
37
- return <
38
- ControllerContractController<
39
- TMethod,
40
- TPath,
41
- ParamsFrom<TPath>,
42
- TChannel extends 'query' ? TInput : NoInput,
43
- TChannel extends 'body' ? TInput : NoInput,
44
- TOutputFromInput | TOutput,
45
- TRouter
46
- >
47
- >(() => product);
48
- }
49
- }
@@ -1,24 +0,0 @@
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
- }
@@ -1,13 +0,0 @@
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
- }