UNPKG

4.71 kBPlain TextView Raw
1import fs from 'fs';
2import path from 'path';
3import importFresh from 'import-fresh';
4import stripComments from 'strip-json-comments';
5import yaml from 'js-yaml';
6import { PROJECT_CONFIG, DEVKIT_CONFIG } from '../../shared/constant';
7
8export default class Config {
9 public ctx: any;
10 constructor(ctx: any) {
11 this.ctx = ctx;
12 }
13
14 getProjectDirectory(): string {
15 let currDir: string = process.cwd();
16
17 const isConfigExits = () => {
18 for (const filename of PROJECT_CONFIG) {
19 if (fs.existsSync(path.join(currDir, filename))) {
20 return true;
21 }
22 }
23 return false;
24 };
25
26 while (!isConfigExits()) {
27 currDir = path.join(currDir, '../');
28 if (currDir === '/' || /^[a-zA-Z]:\\$/.test(currDir)) {
29 return '';
30 }
31 }
32
33 return currDir;
34 }
35
36 loadProjectConfig() {
37 const directoryPath = this.getProjectDirectory();
38 return this.loadConfig(directoryPath, PROJECT_CONFIG);
39 }
40
41 loadDevkitConfig(directoryPath: string) {
42 return this.loadConfig(directoryPath, DEVKIT_CONFIG);
43 }
44
45 loadConfig(directoryPath: string, configArray: Array<string>) {
46 for (const filename of configArray) {
47 const filePath = path.join(directoryPath, filename);
48 if (fs.existsSync(filePath)) {
49 let configData;
50
51 try {
52 configData = this.loadConfigFile(filePath);
53 } catch (error) {
54 if (!error || error.code !== 'FEFLOW_CONFIG_FIELD_NOT_FOUND') {
55 throw error;
56 }
57 }
58
59 if (configData) {
60 this.ctx.logger.debug('Config file found', filePath);
61 this.ctx.logger.debug('Config data', configData);
62
63 return configData;
64 }
65 }
66 }
67
68 this.ctx.logger.debug(`Config file not found.`);
69 return null;
70 }
71
72 loadConfigFile(filePath: string) {
73 switch (path.extname(filePath)) {
74 case '.js':
75 return this.loadJSConfigFile(filePath);
76
77 case '.json':
78 if (path.basename(filePath) === 'package.json') {
79 return this.loadPackageJSONConfigFile(filePath);
80 }
81 return this.loadJSONConfigFile(filePath);
82
83 case '.yaml':
84 case '.yml':
85 return this.loadYAMLConfigFile(filePath);
86
87 default:
88 return this.loadLegacyConfigFile(filePath);
89 }
90 }
91
92 loadJSConfigFile(filePath: string) {
93 this.ctx.logger.debug(`Loading JS config file: ${filePath}`);
94 try {
95 return importFresh(filePath);
96 } catch (e) {
97 this.ctx.logger.debug(`Error reading JavaScript file: ${filePath}`);
98 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
99 throw e;
100 }
101 }
102
103 loadYAMLConfigFile(filePath: string) {
104 this.ctx.logger.debug(`Loading YAML config file: ${filePath}`);
105 try {
106 return yaml.safeLoad(this.readFile(filePath)) || {};
107 } catch (e) {
108 this.ctx.logger.debug(`Error reading YAML file: ${filePath}`);
109 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
110 throw e;
111 }
112 }
113
114 loadPackageJSONConfigFile(filePath: string) {
115 this.ctx.logger.debug(`Loading package.json config file: ${filePath}`);
116 try {
117 const packageData = this.loadJSONConfigFile(filePath);
118
119 if (!Object.hasOwnProperty.call(packageData, 'feflowConfig')) {
120 throw Object.assign(
121 new Error("package.json file doesn't have 'feflowConfig' field."),
122 { code: 'FEFLOW_CONFIG_FIELD_NOT_FOUND' }
123 );
124 }
125
126 return packageData.feflowConfig;
127 } catch (e) {
128 this.ctx.logger.debug(`Error reading package.json file: ${filePath}`);
129 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
130 throw e;
131 }
132 }
133
134 loadJSONConfigFile(filePath: string) {
135 this.ctx.logger.debug(`Loading JSON config file: ${filePath}`);
136
137 try {
138 return JSON.parse(stripComments(this.readFile(filePath)));
139 } catch (e) {
140 this.ctx.logger.debug(`Error reading JSON file: ${filePath}`);
141 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
142 e.messageTemplate = 'failed-to-read-json';
143 e.messageData = {
144 path: filePath,
145 message: e.message
146 };
147 throw e;
148 }
149 }
150
151 loadLegacyConfigFile(filePath: string) {
152 this.ctx.logger.debug(`Loading legacy config file: ${filePath}`);
153 try {
154 return yaml.safeLoad(stripComments(this.readFile(filePath))) || {};
155 } catch (e) {
156 this.ctx.logger.debug('Error reading YAML file: %s\n%o', filePath, e);
157 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
158 throw e;
159 }
160 }
161
162 readFile(filePath: string) {
163 return fs.readFileSync(filePath, 'utf8').replace(/^\ufeff/u, '');
164 }
165}