-
Notifications
You must be signed in to change notification settings - Fork 648
/
parser.ts
109 lines (84 loc) · 3.47 KB
/
parser.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
100
101
102
103
104
105
106
107
108
109
import * as path from 'path';
import { cloneDeep } from 'lodash';
import { loadJSONFile } from '@hint/utils-fs';
import { finalConfig, IJSONResult, parseJSON, SchemaValidationResult, validate } from '@hint/utils-json';
import { Engine, FetchEnd, Parser } from 'hint';
import { TypeScriptConfig, TypeScriptConfigEvents } from './types';
export * from './types';
export default class TypeScriptConfigParser extends Parser<TypeScriptConfigEvents> {
private schema: any;
private schemaPath: string = path.join(__dirname, 'schema.json');
public constructor(engine: Engine<TypeScriptConfigEvents>) {
super(engine, 'typescript-config');
this.schema = loadJSONFile(this.schemaPath);
engine.on('fetch::end::*', this.parseTypeScript.bind(this));
}
private async validateSchema(config: TypeScriptConfig, resource: string, result: IJSONResult): Promise<SchemaValidationResult> {
const validationResult = validate(this.schema, config, result.getLocation);
const valid = validationResult.valid;
if (!valid) {
await this.engine.emitAsync(`parse::error::typescript-config::schema`, {
error: new Error('Invalid TypeScript configuration'),
errors: validationResult.errors,
groupedErrors: validationResult.groupedErrors,
prettifiedErrors: validationResult.prettifiedErrors,
resource
});
}
return validationResult;
}
private async parseTypeScript(fetchEnd: FetchEnd) {
const resource = fetchEnd.resource;
const fileName = path.basename(resource);
/**
* Match examples:
* tsconfig.json
* tsconfig.improved.json
* tsconfig.whatever.json
*
* Not Match examples:
* tsconfigimproved.json
* anythingelse.json
* tsconfig.schema.json
*/
if (!fileName.match(/^tsconfig\.([^.]*\.)?json$/gi) || fileName === 'tsconfig.schema.json') {
return;
}
await this.engine.emitAsync(`parse::start::typescript-config`, { resource });
let result: IJSONResult;
try {
result = parseJSON(fetchEnd.response.body.content);
const originalConfig = cloneDeep(result.data);
const config = finalConfig<TypeScriptConfig>(result.data, resource);
if (config instanceof Error) {
await this.engine.emitAsync(`parse::error::typescript-config::extends`,
{
error: config,
getLocation: result.getLocation,
resource: config.resource
});
return;
}
if (!config) {
return;
}
// Validate if the TypeScript configuration is valid.
const validationResult = await this.validateSchema(config, resource, result);
if (!validationResult.valid) {
return;
}
await this.engine.emitAsync(`parse::end::typescript-config`, {
config: validationResult.data,
getLocation: result.getLocation,
mergedConfig: config,
originalConfig,
resource
});
} catch (err) {
await this.engine.emitAsync(`parse::error::typescript-config::json`, {
error: err,
resource
});
}
}
}