-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathschemaParser.ts
99 lines (92 loc) · 2.85 KB
/
schemaParser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
APISchema,
TemplateMetadata,
TYPES as CORE_TYPES,
IValidatorLoader,
} from '@vulcan/core';
import { SchemaData, SchemaFormat, SchemaReader } from './schema-reader';
import * as yaml from 'js-yaml';
import {
RawAPISchema,
SchemaParserMiddleware,
generateUrl,
checkValidator,
transformValidator,
generateTemplateSource,
checkParameter,
fallbackErrors,
addMissingErrors,
normalizeFieldIn,
generateDataType,
normalizeDataType,
generatePathParameters,
addRequiredValidatorForPath,
setConstraints,
} from './middleware';
import * as compose from 'koa-compose';
import { inject, injectable, interfaces } from 'inversify';
import { TYPES } from '@vulcan/build/containers';
import { SchemaParserOptions } from '@vulcan/build/options';
export interface SchemaParseResult {
schemas: APISchema[];
}
@injectable()
export class SchemaParser {
private schemaReader: SchemaReader;
private middleware: SchemaParserMiddleware[] = [];
constructor(
@inject(TYPES.Factory_SchemaReader)
schemaReaderFactory: interfaces.AutoNamedFactory<SchemaReader>,
@inject(TYPES.SchemaParserOptions) schemaParserOptions: SchemaParserOptions,
@inject(CORE_TYPES.ValidatorLoader) validatorLoader: IValidatorLoader
) {
this.schemaReader = schemaReaderFactory(schemaParserOptions.reader);
// Global middleware
this.use(generateUrl());
this.use(generateTemplateSource());
this.use(transformValidator());
this.use(checkValidator(validatorLoader));
this.use(fallbackErrors());
this.use(normalizeFieldIn());
this.use(generateDataType());
this.use(normalizeDataType());
this.use(generatePathParameters());
this.use(addRequiredValidatorForPath());
this.use(setConstraints(validatorLoader));
}
public async parse({
metadata,
}: {
metadata?: Record<string, TemplateMetadata>;
} = {}): Promise<SchemaParseResult> {
const middleware = [...this.middleware];
if (metadata) {
middleware.push(checkParameter(metadata));
middleware.push(addMissingErrors(metadata));
}
const execute = compose(middleware);
const schemas: APISchema[] = [];
for await (const schemaData of this.schemaReader.readSchema()) {
const schema = await this.parseContent(schemaData);
// execute middleware
await execute(schema);
schemas.push(schema as APISchema);
}
return { schemas };
}
public use(middleware: SchemaParserMiddleware): this {
this.middleware.push(middleware);
return this;
}
private async parseContent(schemaData: SchemaData): Promise<RawAPISchema> {
switch (schemaData.type) {
case SchemaFormat.YAML:
return {
sourceName: schemaData.sourceName,
...(yaml.load(schemaData.content) as object),
} as RawAPISchema;
default:
throw new Error(`Unsupported schema type: ${schemaData.type}`);
}
}
}