@forklaunch/core 0.1.2 → 0.1.5
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/http/httpStatusCodes.d.ts +74 -0
- package/dist/http/httpStatusCodes.js +1050 -0
- package/dist/http/httpStatusCodes.js.map +1 -0
- package/dist/http/index.d.ts +3 -1
- package/dist/http/index.js +3 -1
- package/dist/http/index.js.map +1 -1
- package/dist/http/middleware/index.js.map +1 -0
- package/dist/http/middleware/request.middleware.js.map +1 -0
- package/dist/http/middleware/response.middleware.js.map +1 -0
- package/dist/http/openApiV3Generator.d.ts +4 -0
- package/dist/http/openApiV3Generator.js +137 -0
- package/dist/http/openApiV3Generator.js.map +1 -0
- package/dist/http/types/forklaunch.types.d.ts +13 -0
- package/dist/http/types/forklaunch.types.js +3 -0
- package/dist/http/types/forklaunch.types.js.map +1 -0
- package/dist/http/types/index.d.ts +1 -0
- package/dist/http/types/index.js +1 -0
- package/dist/http/types/index.js.map +1 -1
- package/dist/jest.config.js +10 -0
- package/dist/tests/http.middleware.test.js +1 -1
- package/dist/tests/http.middleware.test.js.map +1 -1
- package/dist/tests/openApiV3Generator.test.d.ts +1 -0
- package/dist/tests/openApiV3Generator.test.js +71 -0
- package/dist/tests/openApiV3Generator.test.js.map +1 -0
- package/package.json +4 -2
- package/.prettierignore +0 -2
- package/.prettierrc +0 -6
- package/dist/http/middlewares/index.js.map +0 -1
- package/dist/http/middlewares/request.middleware.js.map +0 -1
- package/dist/http/middlewares/response.middleware.js.map +0 -1
- package/entityMapper/index.ts +0 -2
- package/entityMapper/interfaces/entityMapper.interface.ts +0 -17
- package/entityMapper/models/baseEntityMapper.model.ts +0 -110
- package/entityMapper/models/requestEntityMapper.model.ts +0 -111
- package/entityMapper/models/responseEntityMapper.model.ts +0 -98
- package/entityMapper/types/entityMapper.types.ts +0 -12
- package/eslint.config.mjs +0 -12
- package/http/index.ts +0 -2
- package/http/middlewares/index.ts +0 -2
- package/http/middlewares/request.middleware.ts +0 -257
- package/http/middlewares/response.middleware.ts +0 -63
- package/http/types/api.types.ts +0 -83
- package/http/types/index.ts +0 -2
- package/http/types/primitive.types.ts +0 -76
- package/index.ts +0 -6
- package/jest.config.ts +0 -10
- package/tests/entityMapper.test.ts +0 -219
- package/tests/http.middleware.test.ts +0 -99
- package/tests/redisTtlCache.test.ts +0 -62
- /package/dist/http/{middlewares → middleware}/index.d.ts +0 -0
- /package/dist/http/{middlewares → middleware}/index.js +0 -0
- /package/dist/http/{middlewares → middleware}/request.middleware.d.ts +0 -0
- /package/dist/http/{middlewares → middleware}/request.middleware.js +0 -0
- /package/dist/http/{middlewares → middleware}/response.middleware.d.ts +0 -0
- /package/dist/http/{middlewares → middleware}/response.middleware.js +0 -0
@@ -1,111 +0,0 @@
|
|
1
|
-
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
-
import { BaseEntity } from '../../database/mikro/models/entities/base.entity';
|
3
|
-
import { EntityMapperConstructor } from '../interfaces/entityMapper.interface';
|
4
|
-
import { BaseEntityMapper, construct } from './baseEntityMapper.model';
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Abstract class representing a request entityMapper.
|
8
|
-
*
|
9
|
-
* @template Entity - A type that extends BaseEntity.
|
10
|
-
* @template SV - A type that extends SchemaValidator.
|
11
|
-
* @extends {BaseEntityMapper<SV>}
|
12
|
-
*/
|
13
|
-
export abstract class RequestEntityMapper<
|
14
|
-
Entity extends BaseEntity,
|
15
|
-
SV extends AnySchemaValidator
|
16
|
-
> extends BaseEntityMapper<SV> {
|
17
|
-
/**
|
18
|
-
* The entity.
|
19
|
-
* @type {Entity}
|
20
|
-
* @protected
|
21
|
-
*/
|
22
|
-
_Entity!: Entity;
|
23
|
-
|
24
|
-
/**
|
25
|
-
* Converts the underlying DTO to an entity.
|
26
|
-
*
|
27
|
-
* @abstract
|
28
|
-
* @param {...unknown[]} additionalArgs - Additional arguments.
|
29
|
-
* @returns {Entity} - The entity.
|
30
|
-
*/
|
31
|
-
abstract toEntity(...additionalArgs: unknown[]): Entity;
|
32
|
-
|
33
|
-
/**
|
34
|
-
* Populates the DTO with data from a JSON object.
|
35
|
-
*
|
36
|
-
* @param {this['_dto']} json - The JSON object.
|
37
|
-
* @returns {this} - The instance of the RequestEntityMapper.
|
38
|
-
*/
|
39
|
-
fromJson(json: this['_dto']): this {
|
40
|
-
if (
|
41
|
-
!this.schemaValidator.validate(
|
42
|
-
this.schemaValidator.schemify(this.schema),
|
43
|
-
json
|
44
|
-
)
|
45
|
-
) {
|
46
|
-
throw new Error('Invalid DTO');
|
47
|
-
}
|
48
|
-
this.dto = json;
|
49
|
-
return this;
|
50
|
-
}
|
51
|
-
|
52
|
-
/**
|
53
|
-
* Deserializes a JSON object to an entity.
|
54
|
-
*
|
55
|
-
* @param {this['_dto']} json - The JSON object.
|
56
|
-
* @param {...unknown[]} additionalArgs - Additional arguments.
|
57
|
-
* @returns {Entity} - The entity.
|
58
|
-
*/
|
59
|
-
deserializeJsonToEntity(
|
60
|
-
json: this['_dto'],
|
61
|
-
...additionalArgs: unknown[]
|
62
|
-
): Entity {
|
63
|
-
return this.fromJson(json).toEntity(...additionalArgs);
|
64
|
-
}
|
65
|
-
|
66
|
-
/**
|
67
|
-
* Creates an instance of a RequestEntityMapper from a JSON object.
|
68
|
-
*
|
69
|
-
* @template T - A type that extends RequestEntityMapper.
|
70
|
-
* @param {EntityMapperConstructor<T>} this - The constructor of the T.
|
71
|
-
* @param {T['_SV']} schemaValidator - The schema provider.
|
72
|
-
* @param {T['_dto']} json - The JSON object.
|
73
|
-
* @returns {T} - An instance of the T.
|
74
|
-
*/
|
75
|
-
static fromJson<
|
76
|
-
T extends RequestEntityMapper<BaseEntity, SV>,
|
77
|
-
SV extends AnySchemaValidator,
|
78
|
-
JsonType extends T['_dto']
|
79
|
-
>(
|
80
|
-
this: EntityMapperConstructor<T, SV>,
|
81
|
-
schemaValidator: SV,
|
82
|
-
json: JsonType
|
83
|
-
): T {
|
84
|
-
return construct(this, schemaValidator).fromJson(json);
|
85
|
-
}
|
86
|
-
|
87
|
-
/**
|
88
|
-
* Deserializes a JSON object to an entity.
|
89
|
-
*
|
90
|
-
* @template T - A type that extends RequestEntityMapper.
|
91
|
-
* @param {EntityMapperConstructor<T>} this - The constructor of the T.
|
92
|
-
* @param {T['_SV']} schemaValidator - The schema provider.
|
93
|
-
* @param {T['_dto']} json - The JSON object.
|
94
|
-
* @param {...unknown[]} additionalArgs - Additional arguments.
|
95
|
-
* @returns {T['_Entity']} - The entity.
|
96
|
-
*/
|
97
|
-
static deserializeJsonToEntity<
|
98
|
-
T extends RequestEntityMapper<BaseEntity, SV>,
|
99
|
-
SV extends AnySchemaValidator,
|
100
|
-
JsonType extends T['_dto']
|
101
|
-
>(
|
102
|
-
this: EntityMapperConstructor<T, SV>,
|
103
|
-
schemaValidator: SV,
|
104
|
-
json: JsonType,
|
105
|
-
...additionalArgs: unknown[]
|
106
|
-
): T['_Entity'] {
|
107
|
-
return construct(this, schemaValidator)
|
108
|
-
.fromJson(json)
|
109
|
-
.toEntity(...additionalArgs);
|
110
|
-
}
|
111
|
-
}
|
@@ -1,98 +0,0 @@
|
|
1
|
-
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
-
import { BaseEntity } from '../../database/mikro/models/entities/base.entity';
|
3
|
-
import { EntityMapperConstructor } from '../interfaces/entityMapper.interface';
|
4
|
-
import { BaseEntityMapper, construct } from './baseEntityMapper.model';
|
5
|
-
|
6
|
-
/**
|
7
|
-
* Abstract class representing a response entityMapper.
|
8
|
-
*
|
9
|
-
* @template Entity - A type that extends BaseEntity.
|
10
|
-
* @template SV - A type that extends SchemaValidator.
|
11
|
-
* @extends {BaseEntityMapper<SV>}
|
12
|
-
*/
|
13
|
-
export abstract class ResponseEntityMapper<
|
14
|
-
Entity extends BaseEntity,
|
15
|
-
SV extends AnySchemaValidator
|
16
|
-
> extends BaseEntityMapper<SV> {
|
17
|
-
/**
|
18
|
-
* The entity type.
|
19
|
-
* @type {Entity}
|
20
|
-
* @protected
|
21
|
-
*/
|
22
|
-
_Entity!: Entity;
|
23
|
-
|
24
|
-
/**
|
25
|
-
* Populates entityMapper with DTO from an entity.
|
26
|
-
*
|
27
|
-
* @abstract
|
28
|
-
* @param {Entity} entity - The entity to convert.
|
29
|
-
* @returns {this} - The instance of the ResponseEntityMapper.
|
30
|
-
*/
|
31
|
-
abstract fromEntity(entity: Entity, ...additionalArgs: unknown[]): this;
|
32
|
-
|
33
|
-
/**
|
34
|
-
* Converts the underlying DTO to a JSON object.
|
35
|
-
*
|
36
|
-
* @param {...unknown[]} additionalArgs - Additional arguments.
|
37
|
-
* @returns {this['_dto']} - The JSON object.
|
38
|
-
*/
|
39
|
-
toJson(): this['_dto'] {
|
40
|
-
if (
|
41
|
-
!this.schemaValidator.validate(
|
42
|
-
this.schemaValidator.schemify(this.schema),
|
43
|
-
this.dto
|
44
|
-
)
|
45
|
-
) {
|
46
|
-
throw new Error('Invalid DTO');
|
47
|
-
}
|
48
|
-
return this.dto;
|
49
|
-
}
|
50
|
-
|
51
|
-
/**
|
52
|
-
* Serializes an entity to a JSON object.
|
53
|
-
*
|
54
|
-
* @param {Entity} entity - The entity to serialize.
|
55
|
-
* @returns {this['_dto']} - The JSON object.
|
56
|
-
*/
|
57
|
-
serializeEntityToJson(entity: Entity): this['_dto'] {
|
58
|
-
return this.fromEntity(entity).toJson();
|
59
|
-
}
|
60
|
-
|
61
|
-
/**
|
62
|
-
* Populates entityMapper with DTO from an entity.
|
63
|
-
*
|
64
|
-
* @template T - A type that extends ResponseEntityMapper.
|
65
|
-
* @param {EntityMapperConstructor<T>} this - The constructor of the T.
|
66
|
-
* @param {T['_Entity']} entity - The entity to convert.
|
67
|
-
* @returns {T} - An instance of the T.
|
68
|
-
*/
|
69
|
-
static fromEntity<
|
70
|
-
T extends ResponseEntityMapper<BaseEntity, SV>,
|
71
|
-
SV extends AnySchemaValidator
|
72
|
-
>(
|
73
|
-
this: EntityMapperConstructor<T, SV>,
|
74
|
-
schemaValidator: SV,
|
75
|
-
entity: T['_Entity']
|
76
|
-
): T {
|
77
|
-
return construct(this, schemaValidator).fromEntity(entity);
|
78
|
-
}
|
79
|
-
|
80
|
-
/**
|
81
|
-
* Serializes an entity to a JSON object.
|
82
|
-
*
|
83
|
-
* @template T - A type that extends ResponseEntityMapper.
|
84
|
-
* @param {EntityMapperConstructor<T>} this - The constructor of the T.
|
85
|
-
* @param {T['_Entity']} entity - The entity to serialize.
|
86
|
-
* @returns {T['_dto']} - The JSON object.
|
87
|
-
*/
|
88
|
-
static serializeEntityToJson<
|
89
|
-
T extends ResponseEntityMapper<BaseEntity, SV>,
|
90
|
-
SV extends AnySchemaValidator
|
91
|
-
>(
|
92
|
-
this: EntityMapperConstructor<T, SV>,
|
93
|
-
schemaValidator: SV,
|
94
|
-
entity: T['_Entity']
|
95
|
-
): T['_dto'] {
|
96
|
-
return construct(this, schemaValidator).serializeEntityToJson(entity);
|
97
|
-
}
|
98
|
-
}
|
@@ -1,12 +0,0 @@
|
|
1
|
-
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
-
import { UnboxedObjectSchema } from '@forklaunch/validator/types';
|
3
|
-
|
4
|
-
/**
|
5
|
-
* Type representing a schema validator object for an entity mapper.
|
6
|
-
*
|
7
|
-
* @template SV - A type that extends SchemaValidator.
|
8
|
-
* @typedef {ValidSchemaObject<SV> | UnboxedObjectSchema<SchemaCatchall<SV>> & {}} EntityMapperSchemaValidatorObject
|
9
|
-
*/
|
10
|
-
export type EntityMapperSchemaValidatorObject<SV extends AnySchemaValidator> =
|
11
|
-
| SV['_ValidSchemaObject']
|
12
|
-
| UnboxedObjectSchema<SV>;
|
package/eslint.config.mjs
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
import pluginJs from "@eslint/js";
|
2
|
-
import globals from "globals";
|
3
|
-
import tseslint from "typescript-eslint";
|
4
|
-
|
5
|
-
|
6
|
-
export default [
|
7
|
-
{files: ["**/*.{ts}"]},
|
8
|
-
{ignores: ["tests/**/*", "dist/**/*", "node_modules/**/*"]},
|
9
|
-
{languageOptions: { globals: globals.browser }},
|
10
|
-
pluginJs.configs.recommended,
|
11
|
-
...tseslint.configs.recommended,
|
12
|
-
];
|
package/http/index.ts
DELETED
@@ -1,257 +0,0 @@
|
|
1
|
-
import { AnySchemaValidator, SchemaValidator } from '@forklaunch/validator';
|
2
|
-
import * as jose from 'jose';
|
3
|
-
import { v4 } from 'uuid';
|
4
|
-
import {
|
5
|
-
ForklaunchNextFunction,
|
6
|
-
ForklaunchRequest,
|
7
|
-
ForklaunchResponse
|
8
|
-
} from '../types/api.types';
|
9
|
-
import {
|
10
|
-
AuthMethod,
|
11
|
-
HttpContractDetails,
|
12
|
-
PathParamHttpContractDetails,
|
13
|
-
StringOnlyObject
|
14
|
-
} from '../types/primitive.types';
|
15
|
-
|
16
|
-
export function createRequestContext<
|
17
|
-
SV extends AnySchemaValidator,
|
18
|
-
Request extends ForklaunchRequest<SV>,
|
19
|
-
Response extends ForklaunchResponse,
|
20
|
-
NextFunction extends ForklaunchNextFunction
|
21
|
-
>(schemaValidator: SV) {
|
22
|
-
return (req: Request, res: Response, next?: NextFunction) => {
|
23
|
-
req.schemaValidator = schemaValidator as SchemaValidator;
|
24
|
-
|
25
|
-
let correlationId = v4();
|
26
|
-
|
27
|
-
if (req.headers['x-correlation-id']) {
|
28
|
-
correlationId = req.headers['x-correlation-id'] as string;
|
29
|
-
}
|
30
|
-
|
31
|
-
res.setHeader('x-correlation-id', correlationId);
|
32
|
-
|
33
|
-
req.context = {
|
34
|
-
correlationId: correlationId
|
35
|
-
};
|
36
|
-
|
37
|
-
if (next) {
|
38
|
-
next();
|
39
|
-
}
|
40
|
-
};
|
41
|
-
}
|
42
|
-
|
43
|
-
export function enrichRequestDetails<
|
44
|
-
SV extends AnySchemaValidator,
|
45
|
-
Request extends ForklaunchRequest<SV>,
|
46
|
-
Response extends ForklaunchResponse,
|
47
|
-
NextFunction extends ForklaunchNextFunction
|
48
|
-
>(contractDetails: PathParamHttpContractDetails<SV> | HttpContractDetails<SV>) {
|
49
|
-
return (req: Request, _res: Response, next?: NextFunction) => {
|
50
|
-
req.contractDetails = contractDetails;
|
51
|
-
|
52
|
-
if (next) {
|
53
|
-
next();
|
54
|
-
}
|
55
|
-
};
|
56
|
-
}
|
57
|
-
|
58
|
-
export function preHandlerParse<SV extends AnySchemaValidator>(
|
59
|
-
schemaValidator: SchemaValidator,
|
60
|
-
object: unknown,
|
61
|
-
schemaInput?: StringOnlyObject<SV>
|
62
|
-
) {
|
63
|
-
if (!schemaInput) {
|
64
|
-
return;
|
65
|
-
}
|
66
|
-
|
67
|
-
const schema = schemaValidator.schemify(schemaInput);
|
68
|
-
if (!schemaValidator.validate(schema, object)) {
|
69
|
-
return 400;
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
export function parseRequestParams<
|
74
|
-
SV extends AnySchemaValidator,
|
75
|
-
Request extends ForklaunchRequest<SV>,
|
76
|
-
Response extends ForklaunchResponse,
|
77
|
-
NextFunction extends ForklaunchNextFunction
|
78
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
79
|
-
const params = req.contractDetails.params;
|
80
|
-
if (preHandlerParse(req.schemaValidator, req.params, params) === 400) {
|
81
|
-
res.status(400).send('Invalid request parameters.');
|
82
|
-
if (next) {
|
83
|
-
next(new Error('Invalid request parameters.'));
|
84
|
-
}
|
85
|
-
}
|
86
|
-
if (next) {
|
87
|
-
next();
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
export function parseRequestBody<
|
92
|
-
SV extends AnySchemaValidator,
|
93
|
-
Request extends ForklaunchRequest<SV>,
|
94
|
-
Response extends ForklaunchResponse,
|
95
|
-
NextFunction extends ForklaunchNextFunction
|
96
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
97
|
-
if (req.headers['content-type'] === 'application/json') {
|
98
|
-
const body = (req.schemaValidator,
|
99
|
-
req.contractDetails as HttpContractDetails<SV>).body;
|
100
|
-
if (
|
101
|
-
preHandlerParse(
|
102
|
-
req.schemaValidator,
|
103
|
-
req.body,
|
104
|
-
body as StringOnlyObject<SV>
|
105
|
-
) === 400
|
106
|
-
) {
|
107
|
-
res.status(400).send('Invalid request body.');
|
108
|
-
if (next) {
|
109
|
-
next(new Error('Invalid request body.'));
|
110
|
-
}
|
111
|
-
}
|
112
|
-
}
|
113
|
-
if (next) {
|
114
|
-
next();
|
115
|
-
}
|
116
|
-
}
|
117
|
-
|
118
|
-
export function parseRequestHeaders<
|
119
|
-
SV extends AnySchemaValidator,
|
120
|
-
Request extends ForklaunchRequest<SV>,
|
121
|
-
Response extends ForklaunchResponse,
|
122
|
-
NextFunction extends ForklaunchNextFunction
|
123
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
124
|
-
const headers = req.contractDetails.requestHeaders;
|
125
|
-
if (preHandlerParse(req.schemaValidator, req.headers, headers) === 400) {
|
126
|
-
res.status(400).send('Invalid request headers.');
|
127
|
-
if (next) {
|
128
|
-
next(new Error('Invalid request headers.'));
|
129
|
-
}
|
130
|
-
}
|
131
|
-
if (next) {
|
132
|
-
next();
|
133
|
-
}
|
134
|
-
}
|
135
|
-
|
136
|
-
export function parseRequestQuery<
|
137
|
-
SV extends AnySchemaValidator,
|
138
|
-
Request extends ForklaunchRequest<SV>,
|
139
|
-
Response extends ForklaunchResponse,
|
140
|
-
NextFunction extends ForklaunchNextFunction
|
141
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
142
|
-
const query = req.contractDetails.query;
|
143
|
-
if (preHandlerParse(req.schemaValidator, req.query, query) === 400) {
|
144
|
-
res.status(400).send('Invalid request query.');
|
145
|
-
if (next) {
|
146
|
-
next(new Error('Invalid request query.'));
|
147
|
-
}
|
148
|
-
}
|
149
|
-
if (next) {
|
150
|
-
next();
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
async function checkAuthorizationToken(
|
155
|
-
authorizationMethod?: AuthMethod,
|
156
|
-
authorizationString?: string
|
157
|
-
): Promise<[401 | 403, string] | string | undefined> {
|
158
|
-
if (!authorizationString) {
|
159
|
-
return [401, 'No Authorization token provided.'];
|
160
|
-
}
|
161
|
-
switch (authorizationMethod) {
|
162
|
-
case 'jwt': {
|
163
|
-
if (!authorizationString.startsWith('Bearer ')) {
|
164
|
-
return [401, 'Invalid Authorization token format.'];
|
165
|
-
}
|
166
|
-
try {
|
167
|
-
const decodedJwt = await jose.jwtVerify(
|
168
|
-
authorizationString.split(' ')[1],
|
169
|
-
new TextEncoder().encode(
|
170
|
-
process.env.JWT_SECRET || 'your-256-bit-secret'
|
171
|
-
)
|
172
|
-
);
|
173
|
-
return decodedJwt.payload.iss;
|
174
|
-
} catch (error) {
|
175
|
-
console.error(error);
|
176
|
-
return [403, 'Invalid Authorization token.'];
|
177
|
-
}
|
178
|
-
}
|
179
|
-
default:
|
180
|
-
return [401, 'Invalid Authorization method.'];
|
181
|
-
}
|
182
|
-
}
|
183
|
-
|
184
|
-
function mapRoles(
|
185
|
-
authorizationType?: AuthMethod,
|
186
|
-
authorizationToken?: string
|
187
|
-
): string[] {
|
188
|
-
return [];
|
189
|
-
}
|
190
|
-
function mapPermissions(
|
191
|
-
authorizationType?: AuthMethod,
|
192
|
-
authorizationToken?: string
|
193
|
-
): string[] {
|
194
|
-
return [];
|
195
|
-
}
|
196
|
-
|
197
|
-
export async function parseRequestAuth<
|
198
|
-
SV extends AnySchemaValidator,
|
199
|
-
Request extends ForklaunchRequest<SV>,
|
200
|
-
Response extends ForklaunchResponse,
|
201
|
-
NextFunction extends ForklaunchNextFunction
|
202
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
203
|
-
const auth = req.contractDetails.auth;
|
204
|
-
if (auth) {
|
205
|
-
const errorAndMessage = await checkAuthorizationToken(
|
206
|
-
auth.method,
|
207
|
-
req.headers.authorization
|
208
|
-
);
|
209
|
-
if (Array.isArray(errorAndMessage)) {
|
210
|
-
res.status(errorAndMessage[0]).send(errorAndMessage[1]);
|
211
|
-
if (next) {
|
212
|
-
next(new Error(errorAndMessage[1]));
|
213
|
-
}
|
214
|
-
}
|
215
|
-
|
216
|
-
// TODO: Implement role and permission checking
|
217
|
-
const permissionSlugs = mapPermissions(
|
218
|
-
auth.method,
|
219
|
-
req.headers.authorization
|
220
|
-
);
|
221
|
-
const roles = mapRoles(auth.method, req.headers.authorization);
|
222
|
-
|
223
|
-
const permissionErrorMessage =
|
224
|
-
'User does not have sufficient permissions to perform action.';
|
225
|
-
const roleErrorMessage =
|
226
|
-
'User does not have correct role to perform action.';
|
227
|
-
|
228
|
-
// this is wrong, we need to check if any of the user's permissions are in the allowed permissions, while checking that any of the permissions is not in the forbidden slugs
|
229
|
-
// currently this is checking if any of the user's permissions are NOT in the allowed permissions
|
230
|
-
permissionSlugs.forEach((permissionSlug) => {
|
231
|
-
if (
|
232
|
-
!req.contractDetails.auth?.allowedSlugs?.has(permissionSlug) ||
|
233
|
-
req.contractDetails.auth?.forbiddenSlugs?.has(permissionSlug)
|
234
|
-
) {
|
235
|
-
res.status(403).send(permissionErrorMessage);
|
236
|
-
if (next) {
|
237
|
-
next(new Error(permissionErrorMessage));
|
238
|
-
}
|
239
|
-
}
|
240
|
-
});
|
241
|
-
roles.forEach((role) => {
|
242
|
-
if (
|
243
|
-
!req.contractDetails.auth?.allowedRoles?.has(role) ||
|
244
|
-
req.contractDetails.auth?.forbiddenRoles?.has(role)
|
245
|
-
) {
|
246
|
-
res.status(403).send(roleErrorMessage);
|
247
|
-
if (next) {
|
248
|
-
next(new Error(roleErrorMessage));
|
249
|
-
}
|
250
|
-
}
|
251
|
-
});
|
252
|
-
}
|
253
|
-
|
254
|
-
// if (next) {
|
255
|
-
// next();
|
256
|
-
// }
|
257
|
-
}
|
@@ -1,63 +0,0 @@
|
|
1
|
-
import { AnySchemaValidator } from '@forklaunch/validator';
|
2
|
-
import {
|
3
|
-
ForklaunchNextFunction,
|
4
|
-
ForklaunchRequest,
|
5
|
-
ForklaunchResponse
|
6
|
-
} from '../types/api.types';
|
7
|
-
import { HttpContractDetails } from '../types/primitive.types';
|
8
|
-
|
9
|
-
function checkAnyValidation<SV extends AnySchemaValidator>(
|
10
|
-
contractDetails: HttpContractDetails<SV>
|
11
|
-
) {
|
12
|
-
return (
|
13
|
-
contractDetails.body ||
|
14
|
-
contractDetails.params ||
|
15
|
-
contractDetails.requestHeaders ||
|
16
|
-
contractDetails.query
|
17
|
-
);
|
18
|
-
}
|
19
|
-
|
20
|
-
export function parseResponse<
|
21
|
-
SV extends AnySchemaValidator,
|
22
|
-
Request extends ForklaunchRequest<SV>,
|
23
|
-
Response extends ForklaunchResponse,
|
24
|
-
NextFunction extends ForklaunchNextFunction
|
25
|
-
>(req: Request, res: Response, next?: NextFunction) {
|
26
|
-
if (req.contractDetails.responseHeaders) {
|
27
|
-
const schema = req.schemaValidator.schemify(
|
28
|
-
req.contractDetails.responseHeaders
|
29
|
-
);
|
30
|
-
req.schemaValidator.validate(schema, res.getHeaders());
|
31
|
-
}
|
32
|
-
|
33
|
-
if (
|
34
|
-
res.statusCode === 500 ||
|
35
|
-
(checkAnyValidation(req.contractDetails) && res.statusCode === 400) ||
|
36
|
-
(req.contractDetails.auth &&
|
37
|
-
(res.statusCode === 401 || res.statusCode === 403))
|
38
|
-
) {
|
39
|
-
req.schemaValidator.validate(req.schemaValidator.string, res.bodyData);
|
40
|
-
return;
|
41
|
-
}
|
42
|
-
if (
|
43
|
-
Object.prototype.hasOwnProperty.call(
|
44
|
-
!req.contractDetails.responses,
|
45
|
-
res.statusCode
|
46
|
-
)
|
47
|
-
) {
|
48
|
-
if (next) {
|
49
|
-
next(
|
50
|
-
new Error(`Response code ${res.statusCode} not defined in contract.`)
|
51
|
-
);
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
const schema = req.schemaValidator.schemify(
|
56
|
-
req.contractDetails.responses[res.statusCode]
|
57
|
-
);
|
58
|
-
req.schemaValidator.validate(schema, res.bodyData);
|
59
|
-
|
60
|
-
if (next) {
|
61
|
-
next();
|
62
|
-
}
|
63
|
-
}
|
package/http/types/api.types.ts
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
import { Prettify } from '@forklaunch/common';
|
2
|
-
import {
|
3
|
-
AnySchemaValidator,
|
4
|
-
Schema
|
5
|
-
} from '@forklaunch/validator';
|
6
|
-
import { IdiomaticSchema, SchemaValidator } from '@forklaunch/validator/types';
|
7
|
-
import { IncomingHttpHeaders, OutgoingHttpHeader } from 'http';
|
8
|
-
import { ParsedQs } from 'qs';
|
9
|
-
import {
|
10
|
-
HttpContractDetails,
|
11
|
-
ParamsDictionary,
|
12
|
-
PathParamHttpContractDetails
|
13
|
-
} from './primitive.types';
|
14
|
-
|
15
|
-
export interface RequestContext {
|
16
|
-
correlationId: string;
|
17
|
-
idempotencyKey?: string;
|
18
|
-
}
|
19
|
-
|
20
|
-
export interface ForklaunchRequest<
|
21
|
-
SV extends AnySchemaValidator,
|
22
|
-
P = ParamsDictionary,
|
23
|
-
ReqBody = unknown,
|
24
|
-
ReqQuery = ParsedQs,
|
25
|
-
Headers = IncomingHttpHeaders
|
26
|
-
> {
|
27
|
-
context: Prettify<RequestContext>;
|
28
|
-
contractDetails: HttpContractDetails<SV> | PathParamHttpContractDetails<SV>;
|
29
|
-
schemaValidator: SchemaValidator;
|
30
|
-
|
31
|
-
params: P;
|
32
|
-
headers: Headers;
|
33
|
-
body: ReqBody;
|
34
|
-
query: ReqQuery;
|
35
|
-
}
|
36
|
-
|
37
|
-
export interface ForklaunchResponse<
|
38
|
-
ResBody = {
|
39
|
-
400: unknown;
|
40
|
-
401: unknown;
|
41
|
-
403: unknown;
|
42
|
-
500: unknown;
|
43
|
-
},
|
44
|
-
StatusCode = number
|
45
|
-
> {
|
46
|
-
bodyData: unknown;
|
47
|
-
statusCode: StatusCode;
|
48
|
-
corked: boolean;
|
49
|
-
|
50
|
-
getHeaders: () => OutgoingHttpHeader;
|
51
|
-
setHeader: (key: string, value: string) => void;
|
52
|
-
status: {
|
53
|
-
<U extends keyof ResBody>(code: U): ForklaunchResponse<ResBody[U], U>;
|
54
|
-
<U extends keyof ResBody>(
|
55
|
-
code: U,
|
56
|
-
message?: string
|
57
|
-
): ForklaunchResponse<ResBody[U], U>;
|
58
|
-
<U extends 500>(code: U): ForklaunchResponse<string, U>;
|
59
|
-
<U extends 500>(code: U, message?: string): ForklaunchResponse<string, U>;
|
60
|
-
};
|
61
|
-
send: {
|
62
|
-
<T>(body?: ResBody, close_connection?: boolean): T;
|
63
|
-
<T>(body?: ResBody): T;
|
64
|
-
};
|
65
|
-
json: {
|
66
|
-
(body?: ResBody): boolean;
|
67
|
-
<T>(body?: ResBody): T;
|
68
|
-
};
|
69
|
-
jsonp: {
|
70
|
-
(body?: ResBody): boolean;
|
71
|
-
<T>(body?: ResBody): T;
|
72
|
-
};
|
73
|
-
}
|
74
|
-
export type MapSchema<
|
75
|
-
SV extends AnySchemaValidator,
|
76
|
-
T extends IdiomaticSchema<SV> | SV['_ValidSchemaObject']
|
77
|
-
> =
|
78
|
-
Schema<T, SV> extends infer U
|
79
|
-
? { [key: string]: unknown } extends U
|
80
|
-
? never
|
81
|
-
: U
|
82
|
-
: never;
|
83
|
-
export type ForklaunchNextFunction = (err?: unknown) => void;
|
package/http/types/index.ts
DELETED