@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
package/dist/index.mjs CHANGED
@@ -1,171 +1,229 @@
1
- //#region src/classes/controller-contract-controller-builder/builder-steps/post-input-step.ts
2
- var PostInputStep = class {
1
+ //#region src/classes/controller-builder/input-builder/steps/after-body-step.ts
2
+ var AfterBodyStep = class {
3
+ paramsSchema;
4
+ querySchema;
5
+ bodySchema;
6
+ constructor(paramsSchema, querySchema, bodySchema) {
7
+ this.paramsSchema = paramsSchema;
8
+ this.querySchema = querySchema;
9
+ this.bodySchema = bodySchema;
10
+ }
11
+ getSchemas() {
12
+ return {
13
+ params: this.paramsSchema,
14
+ query: this.querySchema,
15
+ body: this.bodySchema
16
+ };
17
+ }
18
+ };
19
+ //#endregion
20
+ //#region src/classes/controller-builder/input-builder/steps/after-query-step.ts
21
+ var AfterQueryStep = class {
22
+ paramsSchema;
23
+ querySchema;
24
+ constructor(paramsSchema, querySchema) {
25
+ this.paramsSchema = paramsSchema;
26
+ this.querySchema = querySchema;
27
+ }
28
+ body(schema) {
29
+ return new AfterBodyStep(this.paramsSchema, this.querySchema, schema);
30
+ }
31
+ getSchemas() {
32
+ return {
33
+ params: this.paramsSchema,
34
+ query: this.querySchema,
35
+ body: null
36
+ };
37
+ }
38
+ };
39
+ //#endregion
40
+ //#region src/classes/controller-builder/input-builder/steps/after-params-step.ts
41
+ var AfterParamsStep = class {
42
+ paramsSchema;
43
+ constructor(paramsSchema) {
44
+ this.paramsSchema = paramsSchema;
45
+ }
46
+ query(schema) {
47
+ return new AfterQueryStep(this.paramsSchema, schema);
48
+ }
49
+ body(schema) {
50
+ return new AfterBodyStep(this.paramsSchema, null, schema);
51
+ }
52
+ getSchemas() {
53
+ return {
54
+ params: this.paramsSchema,
55
+ query: null,
56
+ body: null
57
+ };
58
+ }
59
+ };
60
+ //#endregion
61
+ //#region src/classes/controller-builder/input-builder/input-builder.ts
62
+ var InputBuilder = class {
63
+ params(schema) {
64
+ return new AfterParamsStep(schema);
65
+ }
66
+ query(schema) {
67
+ return new AfterQueryStep(null, schema);
68
+ }
69
+ body(schema) {
70
+ return new AfterBodyStep(null, null, schema);
71
+ }
72
+ };
73
+ //#endregion
74
+ //#region src/classes/controller-builder/steps/output-step.ts
75
+ var OutputStep = class {
3
76
  injectable;
4
- integrator;
77
+ createRoute;
5
78
  method;
6
79
  path;
7
- channel;
8
- schema;
9
- constructor(injectable, integrator, method, path, channel, schema) {
80
+ schemas;
81
+ constructor(injectable, createRoute, method, path, schemas) {
10
82
  this.injectable = injectable;
11
- this.integrator = integrator;
83
+ this.createRoute = createRoute;
12
84
  this.method = method;
13
85
  this.path = path;
14
- this.channel = channel;
15
- this.schema = schema;
86
+ this.schemas = schemas;
16
87
  }
17
88
  output(outputFn) {
18
- const product = this.integrator({
19
- type: "sanitized",
89
+ const route = this.createRoute({
20
90
  injectable: this.injectable,
21
91
  method: this.method,
22
92
  path: this.path,
23
- channel: this.channel,
24
- schema: this.schema,
93
+ schemas: this.schemas,
25
94
  outputFn
26
95
  });
27
- return (() => product);
96
+ return (() => route);
28
97
  }
29
98
  };
30
99
  //#endregion
31
- //#region src/classes/controller-contract-controller-builder/builder-steps/post-endpoint-step.ts
32
- var PostEndpointStep = class {
100
+ //#region src/classes/controller-builder/steps/input-step.ts
101
+ var InputStep = class {
33
102
  injectable;
34
- integrator;
103
+ createRoute;
35
104
  method;
36
105
  path;
37
- constructor(injectable, integrator, method, path) {
106
+ constructor(injectable, createRoute, method, path) {
38
107
  this.injectable = injectable;
39
- this.integrator = integrator;
108
+ this.createRoute = createRoute;
40
109
  this.method = method;
41
110
  this.path = path;
42
111
  }
43
- input(channel, schema) {
44
- return new PostInputStep(this.injectable, this.integrator, this.method, this.path, channel, schema);
112
+ input(inputBuilderFn) {
113
+ const schemas = inputBuilderFn(new InputBuilder()).getSchemas();
114
+ return new OutputStep(this.injectable, this.createRoute, this.method, this.path, schemas);
45
115
  }
46
116
  output(outputFn) {
47
- const product = this.integrator({
48
- type: "nullary",
117
+ const route = this.createRoute({
118
+ injectable: this.injectable,
49
119
  method: this.method,
50
120
  path: this.path,
51
- injectable: this.injectable,
121
+ schemas: {
122
+ params: null,
123
+ query: null,
124
+ body: null
125
+ },
52
126
  outputFn
53
127
  });
54
- return (() => product);
128
+ return (() => route);
55
129
  }
56
130
  };
57
131
  //#endregion
58
- //#region src/classes/controller-contract-controller-builder/builder-steps/post-inject-step.ts
59
- var PostInjectStep = class {
132
+ //#region src/classes/controller-builder/steps/endpoint-step.ts
133
+ var EndpointStep = class {
60
134
  injectable;
61
- integrator;
62
- constructor(injectable, integrator) {
135
+ createRoute;
136
+ constructor(injectable, createRoute) {
63
137
  this.injectable = injectable;
64
- this.integrator = integrator;
138
+ this.createRoute = createRoute;
65
139
  }
66
140
  endpoint(method, path) {
67
- return new PostEndpointStep(this.injectable, this.integrator, method, path);
141
+ return new InputStep(this.injectable, this.createRoute, method, path);
68
142
  }
69
143
  };
70
144
  //#endregion
71
- //#region src/classes/controller-contract-controller-builder/controller-contract-controller-builder.ts
72
- var ControllerContractControllerBuilder = class {
73
- injectableDefaultValue;
74
- integrator;
75
- constructor(injectableDefaultValue, integrator) {
76
- this.injectableDefaultValue = injectableDefaultValue;
77
- this.integrator = integrator;
145
+ //#region src/classes/controller-builder/controller-builder.ts
146
+ var ControllerBuilder = class {
147
+ defaultInjectable;
148
+ createRoute;
149
+ constructor(defaultInjectable, createRoute) {
150
+ this.defaultInjectable = defaultInjectable;
151
+ this.createRoute = createRoute;
78
152
  }
79
153
  inject(injectable) {
80
- return new PostInjectStep(injectable, this.integrator);
154
+ return new EndpointStep(injectable, this.createRoute);
81
155
  }
82
156
  endpoint(method, path) {
83
- return new PostEndpointStep(this.injectableDefaultValue, this.integrator, method, path);
157
+ return new InputStep(this.defaultInjectable, this.createRoute, method, path);
84
158
  }
85
159
  };
86
160
  //#endregion
87
- //#region src/classes/controller-contract-controller-router/controller-contract-controller-router.ts
88
- var ControllerContractControllerRouter = class {
89
- integrator;
161
+ //#region src/classes/controller-router.ts
162
+ var ControllerRouter = class {
163
+ combineRoutes;
90
164
  routes;
91
- constructor(integrator, routes) {
92
- this.integrator = integrator;
165
+ constructor(combineRoutes, routes) {
166
+ this.combineRoutes = combineRoutes;
93
167
  this.routes = routes;
94
168
  }
95
- getIntegratedRouter() {
96
- return this.integrator(this.routes);
169
+ /**
170
+ * @example
171
+ * const usersRouter = controllerRouterFactory.createControllerRouter({ getUser, createUser });
172
+ *
173
+ * const app = express();
174
+ * app.use(express.json());
175
+ * app.use(usersRouter.toRouter());
176
+ * app.listen(3000);
177
+ */
178
+ toRouter() {
179
+ return this.combineRoutes(this.routes);
97
180
  }
98
181
  };
99
182
  //#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;
105
- }
106
- createControllerContractControllerRouter(routes) {
107
- return new ControllerContractControllerRouter(this.integrator, routes);
183
+ //#region src/classes/controller-router-factory.ts
184
+ var ControllerRouterFactory = class {
185
+ combineRoutes;
186
+ constructor(combineRoutes) {
187
+ this.combineRoutes = combineRoutes;
188
+ }
189
+ /**
190
+ * @example
191
+ * const getUser = builder
192
+ * .endpoint('get', '/api/users/:id')
193
+ * .output(async ({ inputs, outputs }) => outputs.pass({ id: inputs.params.id }));
194
+ *
195
+ * const createUser = builder
196
+ * .endpoint('post', '/api/users')
197
+ * .input((s) => s.body(z.object({ name: z.string() })))
198
+ * .output(async ({ inputs, outputs }) => outputs.pass({ name: inputs.body.name }, 201));
199
+ *
200
+ * const usersRouter = controllerRouterFactory.createControllerRouter({ getUser, createUser });
201
+ */
202
+ createControllerRouter(routes) {
203
+ return new ControllerRouter(this.combineRoutes, routes);
108
204
  }
109
205
  };
110
206
  //#endregion
111
- //#region src/classes/framework-integration-factory.ts
112
- var FrameworkIntegrationFactory = class {
113
- createControllerContractControllerBuilder(injectableDefaultValue, integrator) {
114
- return new ControllerContractControllerBuilder(injectableDefaultValue, integrator);
115
- }
116
- createControllerContractControllerRouterFactory(integrator) {
117
- return new ControllerContractControllerRouterFactory(integrator);
207
+ //#region src/classes/framework-setup.ts
208
+ /**
209
+ * @example
210
+ * const setup = new FrameworkSetup<Request, RequestHandler[], Router>();
211
+ */
212
+ var FrameworkSetup = class {
213
+ /**
214
+ * @example
215
+ * const builder = setup.createControllerBuilder([], (blueprint) => { ... });
216
+ */
217
+ createControllerBuilder(defaultInjectable, createRoute) {
218
+ return new ControllerBuilder(defaultInjectable, createRoute);
219
+ }
220
+ /**
221
+ * @example
222
+ * const routerFactory = setup.createControllerRouterFactory((routes) => { ... });
223
+ */
224
+ createControllerRouterFactory(combineRoutes) {
225
+ return new ControllerRouterFactory(combineRoutes);
118
226
  }
119
227
  };
120
228
  //#endregion
121
- //#region src/utils/outputs.ts
122
- let outputs;
123
- (function(_outputs) {
124
- function next(data, code = 100) {
125
- return {
126
- type: "next",
127
- code,
128
- data
129
- };
130
- }
131
- _outputs.next = next;
132
- function pass(data, code = 200) {
133
- return {
134
- type: "pass",
135
- code,
136
- data
137
- };
138
- }
139
- _outputs.pass = pass;
140
- function fail(data, code = 400) {
141
- return {
142
- type: "fail",
143
- code,
144
- data
145
- };
146
- }
147
- _outputs.fail = fail;
148
- function exit() {
149
- return { type: "exit" };
150
- }
151
- _outputs.exit = exit;
152
- })(outputs || (outputs = {}));
153
- function rootOnly(message) {
154
- return [{
155
- key: "root",
156
- message
157
- }];
158
- }
159
- const StandardOutputs = Object.freeze({
160
- OK: outputs.pass(rootOnly("ok"), 200),
161
- Created: outputs.pass(rootOnly("Created"), 201),
162
- Accepted: outputs.pass(rootOnly("Accepted"), 202),
163
- BadRequest: outputs.fail(rootOnly("Bad Request"), 400),
164
- Unauthorized: outputs.fail(rootOnly("Unauthorized"), 401),
165
- Forbidden: outputs.fail(rootOnly("Forbidden"), 403),
166
- NotFound: outputs.fail(rootOnly("Not Found"), 404),
167
- InternalServerError: outputs.fail(rootOnly("Internal Server Error"), 500),
168
- BadGateway: outputs.fail(rootOnly("Bad Gateway"), 502)
169
- });
170
- //#endregion
171
- export { FrameworkIntegrationFactory, StandardOutputs, outputs, rootOnly };
229
+ export { FrameworkSetup };
@@ -0,0 +1,2 @@
1
+ import { n as rootOnly, r as outputs, t as StandardOutputs } from "./index-DvVe6qYj.mjs";
2
+ export { StandardOutputs, outputs, rootOnly };
package/dist/utils.mjs ADDED
@@ -0,0 +1,59 @@
1
+ //#region src/utils/outputs.ts
2
+ const outputs = Object.freeze({
3
+ next(data, code = 100) {
4
+ return {
5
+ type: "next",
6
+ code,
7
+ data
8
+ };
9
+ },
10
+ pass(data, code = 200) {
11
+ return {
12
+ type: "pass",
13
+ code,
14
+ data
15
+ };
16
+ },
17
+ fail(data, code = 400) {
18
+ return {
19
+ type: "fail",
20
+ code,
21
+ data
22
+ };
23
+ },
24
+ /**
25
+ * Used to escape the controller contract state machine, useful for redirects.
26
+ */
27
+ exit() {
28
+ return { type: "exit" };
29
+ }
30
+ });
31
+ //#endregion
32
+ //#region src/utils/root-only.ts
33
+ /**
34
+ * Useful for quickly sending a root level error to the client.
35
+ */
36
+ function rootOnly(message) {
37
+ return [{
38
+ key: "root",
39
+ message
40
+ }];
41
+ }
42
+ //#endregion
43
+ //#region src/utils/standard-outputs.ts
44
+ /**
45
+ * Useful for quick http basic responses.
46
+ */
47
+ const StandardOutputs = Object.freeze({
48
+ OK: outputs.pass(rootOnly("ok"), 200),
49
+ Created: outputs.pass(rootOnly("Created"), 201),
50
+ Accepted: outputs.pass(rootOnly("Accepted"), 202),
51
+ BadRequest: outputs.fail(rootOnly("Bad Request"), 400),
52
+ Unauthorized: outputs.fail(rootOnly("Unauthorized"), 401),
53
+ Forbidden: outputs.fail(rootOnly("Forbidden"), 403),
54
+ NotFound: outputs.fail(rootOnly("Not Found"), 404),
55
+ InternalServerError: outputs.fail(rootOnly("Internal Server Error"), 500),
56
+ BadGateway: outputs.fail(rootOnly("Bad Gateway"), 502)
57
+ });
58
+ //#endregion
59
+ export { StandardOutputs, outputs, rootOnly };
package/package.json CHANGED
@@ -1,30 +1,34 @@
1
1
  {
2
2
  "name": "@controller-contract/server",
3
- "type": "module",
4
- "version": "0.3.3",
5
- "author": "kennychulo",
3
+ "version": "0.4.0",
6
4
  "license": "MIT",
5
+ "author": "kennychulo",
7
6
  "files": [
8
7
  "dist",
9
8
  "src",
10
9
  "LICENSE",
11
10
  "package.json"
12
11
  ],
12
+ "type": "module",
13
13
  "exports": {
14
14
  ".": "./dist/index.mjs",
15
+ "./utils": "./dist/utils.mjs",
15
16
  "./package.json": "./package.json"
16
17
  },
17
18
  "publishConfig": {
18
19
  "access": "public"
19
20
  },
20
- "devDependencies": {
21
- "@controller-contract/core": "0.3.2"
22
- },
23
21
  "dependencies": {
24
22
  "@standard-schema/spec": "1.1.0"
25
23
  },
24
+ "devDependencies": {
25
+ "@controller-contract/core": "0.4.2"
26
+ },
26
27
  "peerDependencies": {
27
- "@controller-contract/core": "0.3.2"
28
+ "@controller-contract/core": "0.4.2"
29
+ },
30
+ "engines": {
31
+ "node": ">=24"
28
32
  },
29
33
  "scripts": {
30
34
  "build": "tsdown",
@@ -0,0 +1,24 @@
1
+ import type { Method } from '@controller-contract/core';
2
+
3
+ import type { CreateRouteFn } from '../../types';
4
+ import { EndpointStep } from './steps/endpoint-step';
5
+ import { InputStep } from './steps/input-step';
6
+
7
+ export class ControllerBuilder<TFrameworkContext, TFrameworkInjectable, TFrameworkRouter> {
8
+ constructor(
9
+ private readonly defaultInjectable: TFrameworkInjectable,
10
+ private readonly createRoute: CreateRouteFn<
11
+ TFrameworkContext,
12
+ TFrameworkInjectable,
13
+ TFrameworkRouter
14
+ >,
15
+ ) {}
16
+
17
+ inject(injectable: TFrameworkInjectable) {
18
+ return new EndpointStep(injectable, this.createRoute);
19
+ }
20
+
21
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
22
+ return new InputStep(this.defaultInjectable, this.createRoute, method, path);
23
+ }
24
+ }
@@ -0,0 +1,20 @@
1
+ import type { NoInput } from '@controller-contract/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+
4
+ import { AfterBodyStep } from './steps/after-body-step';
5
+ import { AfterParamsStep } from './steps/after-params-step';
6
+ import { AfterQueryStep } from './steps/after-query-step';
7
+
8
+ export class InputBuilder {
9
+ params<TParams>(schema: StandardSchemaV1<any, TParams>) {
10
+ return new AfterParamsStep<TParams>(schema);
11
+ }
12
+
13
+ query<TQuery>(schema: StandardSchemaV1<any, TQuery>) {
14
+ return new AfterQueryStep<NoInput, TQuery>(null, schema);
15
+ }
16
+
17
+ body<TBody>(schema: StandardSchemaV1<any, TBody>) {
18
+ return new AfterBodyStep<NoInput, NoInput, TBody>(null, null, schema);
19
+ }
20
+ }
@@ -0,0 +1,19 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+
3
+ import type { ControllerBlueprintSchemas, Endable } from '../../../../interfaces';
4
+
5
+ export class AfterBodyStep<TParams, TQuery, TBody> implements Endable<TParams, TQuery, TBody> {
6
+ constructor(
7
+ private readonly paramsSchema: StandardSchemaV1<any, TParams> | null,
8
+ private readonly querySchema: StandardSchemaV1<any, TQuery> | null,
9
+ private readonly bodySchema: StandardSchemaV1<any, TBody>,
10
+ ) {}
11
+
12
+ getSchemas(): ControllerBlueprintSchemas<TParams, TQuery, TBody> {
13
+ return {
14
+ params: this.paramsSchema,
15
+ query: this.querySchema,
16
+ body: this.bodySchema,
17
+ };
18
+ }
19
+ }
@@ -0,0 +1,26 @@
1
+ import type { NoInput } from '@controller-contract/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+
4
+ import type { ControllerBlueprintSchemas, Endable } from '../../../../interfaces';
5
+ import { AfterBodyStep } from './after-body-step';
6
+ import { AfterQueryStep } from './after-query-step';
7
+
8
+ export class AfterParamsStep<TParams> implements Endable<TParams, NoInput, NoInput> {
9
+ constructor(private readonly paramsSchema: StandardSchemaV1<any, TParams>) {}
10
+
11
+ query<TQuery>(schema: StandardSchemaV1<any, TQuery>) {
12
+ return new AfterQueryStep<TParams, TQuery>(this.paramsSchema, schema);
13
+ }
14
+
15
+ body<TBody>(schema: StandardSchemaV1<any, TBody>) {
16
+ return new AfterBodyStep<TParams, NoInput, TBody>(this.paramsSchema, null, schema);
17
+ }
18
+
19
+ getSchemas(): ControllerBlueprintSchemas<TParams, NoInput, NoInput> {
20
+ return {
21
+ params: this.paramsSchema,
22
+ query: null,
23
+ body: null,
24
+ };
25
+ }
26
+ }
@@ -0,0 +1,24 @@
1
+ import type { NoInput } from '@controller-contract/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+
4
+ import type { ControllerBlueprintSchemas, Endable } from '../../../../interfaces';
5
+ import { AfterBodyStep } from './after-body-step';
6
+
7
+ export class AfterQueryStep<TParams, TQuery> implements Endable<TParams, TQuery, NoInput> {
8
+ constructor(
9
+ private readonly paramsSchema: StandardSchemaV1<any, TParams> | null,
10
+ private readonly querySchema: StandardSchemaV1<any, TQuery>,
11
+ ) {}
12
+
13
+ body<TBody>(schema: StandardSchemaV1<any, TBody>) {
14
+ return new AfterBodyStep<TParams, TQuery, TBody>(this.paramsSchema, this.querySchema, schema);
15
+ }
16
+
17
+ getSchemas(): ControllerBlueprintSchemas<TParams, TQuery, NoInput> {
18
+ return {
19
+ params: this.paramsSchema,
20
+ query: this.querySchema,
21
+ body: null,
22
+ };
23
+ }
24
+ }
@@ -0,0 +1,19 @@
1
+ import type { Method } from '@controller-contract/core';
2
+
3
+ import type { CreateRouteFn } from '../../../types';
4
+ import { InputStep } from './input-step';
5
+
6
+ export class EndpointStep<TFrameworkContext, TFrameworkInjectable, TFrameworkRouter> {
7
+ constructor(
8
+ private readonly injectable: TFrameworkInjectable,
9
+ private readonly createRoute: CreateRouteFn<
10
+ TFrameworkContext,
11
+ TFrameworkInjectable,
12
+ TFrameworkRouter
13
+ >,
14
+ ) {}
15
+
16
+ endpoint<const TMethod extends Method, const TPath extends string>(method: TMethod, path: TPath) {
17
+ return new InputStep(this.injectable, this.createRoute, method, path);
18
+ }
19
+ }
@@ -0,0 +1,67 @@
1
+ import type {
2
+ ExitOutput,
3
+ FailOutput,
4
+ Method,
5
+ NoInput,
6
+ PassOutput,
7
+ PathParams,
8
+ } from '@controller-contract/core';
9
+
10
+ import type { Controller, CreateRouteFn, InputBuilderFn, OutputFn, Prettify } from '../../../types';
11
+ import { InputBuilder } from '../input-builder/input-builder';
12
+ import { OutputStep } from './output-step';
13
+
14
+ export class InputStep<
15
+ TFrameworkContext,
16
+ TFrameworkInjectable,
17
+ TFrameworkRouter,
18
+ const TMethod extends Method,
19
+ const TPath extends string,
20
+ > {
21
+ constructor(
22
+ private readonly injectable: TFrameworkInjectable,
23
+ private readonly createRoute: CreateRouteFn<
24
+ TFrameworkContext,
25
+ TFrameworkInjectable,
26
+ TFrameworkRouter
27
+ >,
28
+ private readonly method: TMethod,
29
+ private readonly path: TPath,
30
+ ) {}
31
+
32
+ input<TParams, TQuery, TBody>(inputBuilderFn: InputBuilderFn<TParams, TQuery, TBody>) {
33
+ const inputBuilder = new InputBuilder();
34
+
35
+ const schemas = inputBuilderFn(inputBuilder).getSchemas();
36
+
37
+ return new OutputStep(this.injectable, this.createRoute, this.method, this.path, schemas);
38
+ }
39
+
40
+ output<TOutput extends PassOutput<any> | FailOutput<any> | ExitOutput>(
41
+ outputFn: OutputFn<TFrameworkContext, Prettify<PathParams<TPath>>, NoInput, NoInput, TOutput>,
42
+ ) {
43
+ const route = this.createRoute({
44
+ injectable: this.injectable,
45
+ method: this.method,
46
+ path: this.path,
47
+ schemas: {
48
+ params: null,
49
+ query: null,
50
+ body: null,
51
+ },
52
+ outputFn,
53
+ });
54
+
55
+ return <
56
+ Controller<
57
+ TMethod,
58
+ TPath,
59
+ Prettify<PathParams<TPath>>,
60
+ NoInput,
61
+ NoInput,
62
+ TOutput,
63
+ TFrameworkRouter
64
+ >
65
+ >(() => route);
66
+ }
67
+ }