ztxkutils 10.0.11 → 20.0.2

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 (58) hide show
  1. package/dist/businessTools.js +4 -3
  2. package/dist/dataModel-b3629ef3.js +26 -0
  3. package/dist/dataModel.js +2 -1
  4. package/dist/fileOperation.d.ts +19 -0
  5. package/dist/fileOperation.js +74 -10
  6. package/dist/hooks.js +36 -22
  7. package/dist/i18next.js +7 -19
  8. package/dist/index.js +5 -4
  9. package/dist/myIndexDb.d.ts +1 -1
  10. package/dist/print.d.ts +4 -5
  11. package/dist/print.js +12 -19
  12. package/dist/reqUrl.js +1 -1
  13. package/dist/request-d1972b41.js +2992 -0
  14. package/dist/request.d.ts +13 -0
  15. package/dist/request.js +2 -1
  16. package/dist/stompClient.js +21 -8
  17. package/dist/useFileIdToBase64.js +2 -0
  18. package/dist/validate-21b58a69.js +260 -0
  19. package/dist/validate.js +2 -1
  20. package/dist/workflow.js +3 -5
  21. package/locales/en-US.json +64 -0
  22. package/locales/zh-CN.json +64 -0
  23. package/package.json +41 -4
  24. package/zti18n-cli/bin/index.js +3 -0
  25. package/zti18n-cli/index.js +23 -0
  26. package/zti18n-cli/src/command/collect.js +353 -0
  27. package/zti18n-cli/src/command/convert.js +17 -0
  28. package/zti18n-cli/src/command/convert2.js +35 -0
  29. package/zti18n-cli/src/command/initFileConf.js +133 -0
  30. package/zti18n-cli/src/command/publish.js +24 -0
  31. package/zti18n-cli/src/conf/BaseConf.js +21 -0
  32. package/zti18n-cli/src/conf/FileConf.js +116 -0
  33. package/zti18n-cli/src/index.js +75 -0
  34. package/zti18n-cli/src/translate/google.js +87 -0
  35. package/zti18n-cli/src/utils/isChinese.js +3 -0
  36. package/zti18n-cli/src/utils/log.js +8 -0
  37. package/zti18n-cli/src/utils/mergeOptions.js +45 -0
  38. package/zti18n-cli/src/utils/reactOptions.js +73 -0
  39. package/zti18n-cli/src/utils/vueOptions.js +69 -0
  40. package/zti18n-core/index.js +1 -0
  41. package/zti18n-core/src/index.js +5 -0
  42. package/zti18n-core/src/plugin/reactIntlToReactIntlUniversal.js +224 -0
  43. package/zti18n-core/src/plugin/reactIntlUniversalToDi18n.js +64 -0
  44. package/zti18n-core/src/transform/defaultPkMap.js +79 -0
  45. package/zti18n-core/src/transform/transformHtml.js +271 -0
  46. package/zti18n-core/src/transform/transformJs.js +489 -0
  47. package/zti18n-core/src/transform/transformPug.js +272 -0
  48. package/zti18n-core/src/transform/transformReactIntlToReactIntlUniversal.js +96 -0
  49. package/zti18n-core/src/transform/transformReactIntlUniveralToDi18n.js +90 -0
  50. package/zti18n-core/src/transform/transformToDi18n.js +22 -0
  51. package/zti18n-core/src/transform/transformTs.js +41 -0
  52. package/zti18n-core/src/transform/transformVue.js +126 -0
  53. package/zti18n-core/src/transform/transformZeroToDi18n.js +105 -0
  54. package/zti18n-core/src/translate/google.js +6 -0
  55. package/zti18n-core/src/utils/constants.js +3 -0
  56. package/zti18n-core/src/utils/getIgnoreLines.js +14 -0
  57. package/zti18n-core/src/utils/isChinese.js +3 -0
  58. package/zti18n-core/src/utils/log.js +8 -0
@@ -0,0 +1,23 @@
1
+ const program = require('./src');
2
+ const initFileConf = require('./src/command/initFileConf');
3
+
4
+ program
5
+ .command('init')
6
+ .alias('i')
7
+ .description('init locales conf')
8
+ .option('--vue', 'init for vue project')
9
+ .action(function (options) {
10
+ initFileConf(options.vue);
11
+ })
12
+ .on('--help', function () {
13
+ console.log(' Examples:');
14
+ console.log();
15
+ console.log(' $ zti18n init -c ./config/prod.config.js');
16
+ console.log();
17
+ });
18
+
19
+ program.command('*').action(function (cmd) {
20
+ console.log('unknown command "%s"', cmd);
21
+ });
22
+
23
+ program.parse(process.argv);
@@ -0,0 +1,353 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const glob = require('glob');
4
+ const { transformZeroToDi18n } = require('../../../zti18n-core');
5
+ const mergeOptions = require('../utils/mergeOptions');
6
+ const isChinese = require('../utils/isChinese');
7
+ const log = require('../utils/log');
8
+
9
+ function getSourceFiles({ entry, exclude }) {
10
+ return glob.sync(`${entry}/**/*.{js,ts,tsx,jsx,vue}`, {
11
+ ignore: exclude || [],
12
+ });
13
+ }
14
+
15
+ /**
16
+ * 同步一个非中文语言的配置
17
+ */
18
+ async function syncOneNonChineseLocalesConf(
19
+ key,
20
+ option,
21
+ chineseLocales,
22
+ updatedTranslatedWord,
23
+ publish,
24
+ confService
25
+ ) {
26
+ const confName = key;
27
+ const { disableAutoTranslate, translator, appid, privatekey } = option;
28
+
29
+ const translate = translator
30
+ ? require(path.join(process.cwd(), translator))
31
+ : require('../translate/google');
32
+
33
+ log.warning(`start to update conf ${confName}`);
34
+
35
+ const res = await confService.getConf(confName, key);
36
+
37
+ if (res.code !== 0) {
38
+ log.error(`! failed to read apollo conf, ${res.message}`);
39
+ return null;
40
+ }
41
+
42
+ const allKeys = Object.keys(chineseLocales);
43
+ let mergedLocales = {};
44
+
45
+ res.data.forEach((item) => {
46
+ if (updatedTranslatedWord.hasOwnProperty(item.key)) {
47
+ mergedLocales[updatedTranslatedWord[item.key]] = item.value;
48
+ } else if (allKeys.indexOf(item.key) >= 0) {
49
+ mergedLocales[item.key] = item.value;
50
+ }
51
+ });
52
+
53
+ mergedLocales = { ...chineseLocales, ...mergedLocales };
54
+
55
+ const translateTasks = [];
56
+
57
+ Object.keys(mergedLocales).forEach((k) => {
58
+ const text = mergedLocales[k];
59
+ let targetLang = key.split(/_|-/)[0];
60
+ if (isChinese(text)) {
61
+ if (disableAutoTranslate || !appid || !privatekey) {
62
+ mergedLocales[k] = text;
63
+ } else {
64
+ translateTasks.push([k, targetLang]);
65
+ }
66
+ }
67
+ });
68
+
69
+ const total = translateTasks.length;
70
+
71
+ // 控制并发数
72
+ const concurrenceCount = 3;
73
+
74
+ while (translateTasks.length > 0) {
75
+ const tasks = translateTasks.splice(0, concurrenceCount);
76
+
77
+ await Promise.all(
78
+ tasks.map(([k, targetLang]) => {
79
+ const text = mergedLocales[k];
80
+
81
+ return translate(text, targetLang, appid, privatekey)
82
+ .then((res) => {
83
+ mergedLocales[k] = res.transResult
84
+ .replaceAll('{ { ', '{{')
85
+ .replaceAll(' } }', '}}');
86
+ })
87
+ .catch((err) => {
88
+ log.warning(`[AutoTranslate]: ${err.message}`);
89
+ mergedLocales[k] = text;
90
+ });
91
+ })
92
+ );
93
+
94
+ log.info(`[AutoTranslate]: ${total - translateTasks.length}/${total}`);
95
+ }
96
+
97
+ const updateConfRes = await confService.updateConf(
98
+ confName,
99
+ mergedLocales,
100
+ chineseLocales,
101
+ key
102
+ );
103
+ if (updateConfRes.code !== 0) {
104
+ log.error(`update conf ${confName} fail, ${res.message}`);
105
+ return [];
106
+ }
107
+
108
+ log.success(`updated conf ${confName}`);
109
+
110
+ if (publish) {
111
+ log.warning(`start to publish conf ${confName}`);
112
+ const publishRes = await confService.publishConf(confName);
113
+ if (publishRes.code === 0) {
114
+ log.success(`published conf ${confName}`);
115
+ } else {
116
+ log.error(`publish conf ${confName} failed, ${publishRes.message}`);
117
+ }
118
+ } else {
119
+ log.warning(`${confName} is updated but unpublished!`);
120
+ }
121
+
122
+ return {
123
+ key,
124
+ locales: mergedLocales,
125
+ };
126
+ }
127
+
128
+ /**
129
+ * 同步更新非中文配置
130
+ * @param {object} chineseLocales 中文资源
131
+ * @param {object} updatedTranslatedWord 在远端做过中文文案修改的 key/value
132
+ * @param {object} option 参数
133
+ * @param {boolean} publish 更新后是否立即发布配置
134
+ */
135
+ async function syncNonChineseLocalesConf(
136
+ chineseLocales,
137
+ updatedTranslatedWord,
138
+ option,
139
+ publish,
140
+ confService
141
+ ) {
142
+ const { primaryLocale, supportedLocales } = option;
143
+
144
+ const syncTasks = supportedLocales
145
+ .filter((key) => key !== primaryLocale)
146
+ .map((key) =>
147
+ syncOneNonChineseLocalesConf(
148
+ key,
149
+ option,
150
+ chineseLocales,
151
+ updatedTranslatedWord,
152
+ publish,
153
+ confService
154
+ )
155
+ );
156
+
157
+ const nonChineseLocales = await Promise.all(syncTasks);
158
+
159
+ return nonChineseLocales;
160
+ }
161
+
162
+ /**
163
+ * 收集源码中的中文字符
164
+ * @param {object} option 命令行或者配置文件中传入的参数信息
165
+ * @param {boolean} publish 同步后,是否立即发布新的配置
166
+ */
167
+ async function collectChineseWords(option, publish, confService) {
168
+ const { entry, output, exclude, entryNoImport = [] } = option;
169
+
170
+ if (!Array.isArray(entry) && typeof entry !== 'string') {
171
+ log.error('entry must be a string or array');
172
+ process.exit(2);
173
+ }
174
+
175
+ let zhData = {};
176
+ const allTranslatedWord = {};
177
+ const updatedTranslatedWord = {}; // 在远端做过中文文案修改的 key/value
178
+ const keysInUse = [];
179
+
180
+ const zhConfName = 'zh-CN';
181
+
182
+ const res = await confService.getConf(zhConfName, 'zh-CN');
183
+
184
+ if (res.code !== 0) {
185
+ log.error(`failed to read apollo conf, ${res.message}`);
186
+ process.exit(2);
187
+ }
188
+
189
+ res.data.forEach((item) => {
190
+ zhData[item.key] = item.value;
191
+ });
192
+
193
+ Object.keys(zhData).forEach((k) => {
194
+ const chineseValue = zhData[k];
195
+ if (chineseValue.trim() !== k.replace(/\{context,\s*\S+\}$/, '').trim()) {
196
+ updatedTranslatedWord[k] = chineseValue;
197
+ } else {
198
+ if (Array.isArray(allTranslatedWord[chineseValue])) {
199
+ allTranslatedWord[chineseValue].push(k);
200
+ } else {
201
+ allTranslatedWord[chineseValue] = [k];
202
+ }
203
+ }
204
+ });
205
+ const outputs = output ? [].concat(output) : [];
206
+ let targetFiles = [].concat(entry).reduce((prev, cur, index) => {
207
+ const files = getSourceFiles({ entry: cur, exclude }).map((file) => ({
208
+ filePath: file,
209
+ currentEntry: cur,
210
+ currentOutput: outputs[index],
211
+ ext: path.extname(file),
212
+ }));
213
+ return prev.concat(files);
214
+ }, []);
215
+ targetFiles = targetFiles.concat(
216
+ entryNoImport.reduce((prev, cur, index) => {
217
+ const files = getSourceFiles({ entry: cur, exclude: [] }).map((file) => ({
218
+ filePath: file,
219
+ currentEntry: cur,
220
+ ext: path.extname(file),
221
+ noImport: true,
222
+ }));
223
+ return prev.concat(files);
224
+ }, [])
225
+ );
226
+
227
+ targetFiles.forEach((codeFileInfo) => {
228
+ transformZeroToDi18n(
229
+ codeFileInfo,
230
+ allTranslatedWord,
231
+ updatedTranslatedWord,
232
+ keysInUse,
233
+ option
234
+ );
235
+ log.success(`done: ${codeFileInfo.filePath}`);
236
+ });
237
+
238
+ const localeResouce = {};
239
+ const unusedKeys = [];
240
+ Object.keys(allTranslatedWord).forEach((k) => {
241
+ allTranslatedWord[k].forEach((key) => {
242
+ if (keysInUse.includes(key)) {
243
+ localeResouce[key] = k;
244
+ } else {
245
+ unusedKeys.push(key);
246
+ }
247
+ });
248
+ });
249
+
250
+ if (unusedKeys.length > 0) {
251
+ log.info('the following keys are unused and will be removed:');
252
+ log.info(unusedKeys);
253
+ }
254
+
255
+ const allTranslatedWordKeysCount = Object.keys(allTranslatedWord).reduce(
256
+ (prev, cur) => prev + allTranslatedWord[cur].length,
257
+ 0
258
+ );
259
+ const allLocalesKeyCount = Object.keys(localeResouce).length;
260
+ const allTranstedInUseCount = allTranslatedWordKeysCount - unusedKeys.length;
261
+
262
+ log.info(`keys in use count: ${allTranstedInUseCount}`);
263
+ log.info(`locales in use count: ${allLocalesKeyCount}`);
264
+
265
+ if (allTranstedInUseCount !== allLocalesKeyCount) {
266
+ log.error('ATTENTION:keys and locales are not match');
267
+ }
268
+
269
+ log.info(`start to update conf ${zhConfName}`);
270
+ // 更新配置
271
+ const updateConfRes = await confService.updateConf(
272
+ zhConfName,
273
+ localeResouce,
274
+ {},
275
+ 'zh-CN'
276
+ );
277
+
278
+ if (updateConfRes.code !== 0) {
279
+ log.error(`update conf ${zhConfName} failed, ${updateConfRes.message}`);
280
+ return null;
281
+ }
282
+
283
+ log.success(`updated conf ${zhConfName}`);
284
+
285
+ const unChineseLocales = await syncNonChineseLocalesConf(
286
+ localeResouce,
287
+ updatedTranslatedWord,
288
+ option,
289
+ publish,
290
+ confService
291
+ );
292
+
293
+ // XXX: 英文 publish 也放到这里
294
+ if (publish) {
295
+ log.warning(`start to publish conf ${zhConfName}`);
296
+ const publishRes = await confService.publishConf(zhConfName);
297
+ if (publishRes.code === 0) {
298
+ log.success(`published conf ${zhConfName}`);
299
+ } else {
300
+ log.error(`publish conf ${zhConfName} failed, ${publishRes.message}`);
301
+ }
302
+ } else {
303
+ log.warning(`${zhConfName} is synced, but unpublihsed !!`);
304
+ }
305
+
306
+ return unChineseLocales.concat({
307
+ key: 'zh-CN',
308
+ locales: localeResouce,
309
+ });
310
+ }
311
+
312
+ module.exports = function doCollectChineseWords(
313
+ programOption,
314
+ publish = false
315
+ ) {
316
+ const options = mergeOptions(programOption, ['entry', 'exclude', 'locales']);
317
+
318
+ let confService = null;
319
+ if (options.localeConf.type === 'file') {
320
+ const FileConf = require('../conf/FileConf');
321
+ confService = new FileConf(options.localeConf.folder);
322
+ } else {
323
+ const Conf = require(options.localeConf.path);
324
+ confService = new Conf(options.localeConf);
325
+ }
326
+
327
+ if (!options.entry) {
328
+ log.error('no entry is specified');
329
+ process.exit(2);
330
+ }
331
+
332
+ if (Array.isArray(options.entry)) {
333
+ if (!Array.isArray(options.output)) {
334
+ log.error('output should be array too, since entry is array');
335
+ process.exit(2);
336
+ }
337
+
338
+ if (options.output.length !== options.entry.length) {
339
+ log.error('output length are not equal to entry length');
340
+ process.exit(2);
341
+ }
342
+ }
343
+
344
+ if (options.output) {
345
+ [].concat(options.output).forEach((outputDir) => {
346
+ if (!fs.existsSync(outputDir)) {
347
+ fs.mkdirSync(outputDir);
348
+ }
349
+ });
350
+ }
351
+
352
+ return collectChineseWords(options, publish, confService);
353
+ };
@@ -0,0 +1,17 @@
1
+ const {
2
+ transformReactIntlToReactIntlUniversal,
3
+ } = require('../../../zti18n-core');
4
+ const mergeOptions = require('../utils/mergeOptions');
5
+ const log = require('../utils/log');
6
+
7
+ module.exports = function doConvertToReactIntlUniversal(programOption) {
8
+ const options = mergeOptions(programOption, ['entry', 'exclude', 'locales']);
9
+
10
+ if (!options.entry) {
11
+ log.error('\n · 使用 -e [path] 或 --entry [path] 命令增加待转换的源码目录');
12
+ log.error(" · 或在配置文件中设置 'entry' 字段\n");
13
+ process.exit(2);
14
+ }
15
+
16
+ transformReactIntlToReactIntlUniversal(options);
17
+ };
@@ -0,0 +1,35 @@
1
+ const fs = require('fs');
2
+ const { transformReactIntlUniveralToDi18n } = require('../../../zti18n-core');
3
+ const mergeOptions = require('../utils/mergeOptions');
4
+ const log = require('../utils/log');
5
+
6
+ module.exports = function doConvert(programOption) {
7
+ const options = mergeOptions(programOption, ['entry', 'exclude', 'locales']);
8
+
9
+ if (!options.entry) {
10
+ log.error('no entry is specified');
11
+ process.exit(2);
12
+ }
13
+
14
+ if (Array.isArray(options.entry)) {
15
+ if (!Array.isArray(options.output)) {
16
+ log.error('output should be array too, since entry is array');
17
+ process.exit(2);
18
+ }
19
+
20
+ if (options.output.length !== options.entry.length) {
21
+ log.error('output length are not equal to entry length');
22
+ process.exit(2);
23
+ }
24
+ }
25
+
26
+ if (options.output) {
27
+ [].concat(options.output).forEach((outputDir) => {
28
+ if (!fs.existsSync(outputDir)) {
29
+ fs.mkdirSync(outputDir);
30
+ }
31
+ });
32
+ }
33
+
34
+ return transformReactIntlUniveralToDi18n(options);
35
+ };
@@ -0,0 +1,133 @@
1
+ const glob = require('glob');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const inquirer = require('inquirer');
5
+ const prettier = require('prettier');
6
+ const FileConf = require('../conf/FileConf');
7
+ const reactOptions = require('../utils/reactOptions');
8
+ const vueOptions = require('../utils/vueOptions');
9
+ const log = require('../utils/log');
10
+
11
+ function getLocaleFiles({ path, exclude }) {
12
+ return glob.sync(`${path}/**/*.json`, {
13
+ ignore: (exclude || []).map((e) => `${path}/${e}`),
14
+ });
15
+ }
16
+
17
+ async function doInquire() {
18
+ // 1. whether overwrite?
19
+ let configExist = true;
20
+ try {
21
+ fs.accessSync('./zti18n.config.js');
22
+ } catch (e) {
23
+ configExist = false;
24
+ }
25
+
26
+ if (configExist) {
27
+ const ans = await inquirer.prompt([
28
+ {
29
+ name: 'overwrite',
30
+ type: 'confirm',
31
+ message: '配置文件 zti18n.config.js 已存在,是否覆盖?',
32
+ },
33
+ ]);
34
+
35
+ if (!ans.overwrite) process.exit(0);
36
+ }
37
+
38
+ // 2. first i18n?
39
+ let ans = await inquirer.prompt([
40
+ {
41
+ name: 'firstI18n',
42
+ type: 'confirm',
43
+ message: '是否初次国际化?',
44
+ },
45
+ {
46
+ name: 'localePath',
47
+ type: 'input',
48
+ message: '请输入现有国际化资源路径:',
49
+ when(answers) {
50
+ return !answers.firstI18n;
51
+ },
52
+ },
53
+ ]);
54
+
55
+ return ans;
56
+ }
57
+
58
+ module.exports = async function initFileConf(isVue) {
59
+ const answers = await doInquire();
60
+ const { localePath = 'locales', firstI18n } = answers;
61
+
62
+ const defaultOptions = isVue ? vueOptions : reactOptions;
63
+ const options = {
64
+ ...defaultOptions,
65
+ localeConf: { type: 'file', folder: localePath },
66
+ };
67
+
68
+ // 配置信息写入文件
69
+ fs.writeFileSync(
70
+ './zti18n.config.js',
71
+ prettier.format('module.exports = ' + JSON.stringify(options), {
72
+ parser: 'babel',
73
+ singleQuote: true,
74
+ trailingComma: 'es5',
75
+ }),
76
+ 'utf8'
77
+ );
78
+
79
+ let createTasks = [];
80
+ const confService = new FileConf(options.localeConf.folder);
81
+
82
+ if (!firstI18n) {
83
+ // 非首次国际化,本地代码中已有国际化资源
84
+ const locales = getLocaleFiles({ path: localePath });
85
+
86
+ // 读取国际化资源
87
+ const data = locales.map((element) => {
88
+ // TODO: 支持国际化资源为 js 文件的情况,目前只支持为 json 文件。
89
+ const json = fs.readFileSync(element, {
90
+ encoding: 'utf-8',
91
+ });
92
+
93
+ // 使用现有文件名为语言 key
94
+ const key = path.parse(element).name;
95
+
96
+ return {
97
+ key,
98
+ value: JSON.parse(json),
99
+ confName: key,
100
+ };
101
+ });
102
+
103
+ createTasks = data.map(({ confName, value, key }) => {
104
+ let commentValue = {};
105
+ if (key !== options.primaryLocale) {
106
+ commentValue = data.find((d) => d.key === options.primaryLocale).value;
107
+ }
108
+ return confService.createConf(confName, value, commentValue, key);
109
+ });
110
+ } else {
111
+ // 首次国际化,只需要创建配置
112
+ createTasks = options.supportedLocales.map((key) => {
113
+ const value = { TBD: 'TBD' }; // 创建配置时,必须要有一个 k/V
114
+ const confName = key; // 初始化时,先创建测试环境的配置
115
+ return confService.createConf(confName, value, {}, key);
116
+ });
117
+ }
118
+
119
+ const createTaskResults = await Promise.all(createTasks);
120
+ log.success('[done] conf created');
121
+ console.log(createTaskResults);
122
+
123
+ // 将已有国际化资源的配置发布
124
+ if (!firstI18n) {
125
+ const publishTasks = options.supportedLocales.map((key) => {
126
+ return confService.publishConf(`${key}-test`);
127
+ });
128
+
129
+ const publishTaskResults = await Promise.all(publishTasks);
130
+ log.success('[done] conf published');
131
+ console.log(publishTaskResults);
132
+ }
133
+ };
@@ -0,0 +1,24 @@
1
+ const path = require('path');
2
+ const mergeOptions = require('../utils/mergeOptions');
3
+ const log = require('../utils/log');
4
+
5
+ module.exports = async function publish(programOption, env = '') {
6
+ const options = mergeOptions(programOption, ['locales']);
7
+
8
+ let confService = null;
9
+ if (options.localeConf.type === 'file') {
10
+ const FileConf = require('../conf/FileConf');
11
+ confService = new FileConf(options.locales);
12
+ } else {
13
+ const Conf = require(path.join(process.cwd(), options.localeConf.path));
14
+ confService = new Conf(options.localeConf);
15
+ }
16
+
17
+ const publishTasks = options.supportedLocales.map((key) => {
18
+ return confService.publishConf(`${key}-${env}`);
19
+ });
20
+
21
+ const publishTaskResults = await Promise.all(publishTasks);
22
+ log.success('[done] conf published');
23
+ console.log(publishTaskResults);
24
+ };
@@ -0,0 +1,21 @@
1
+ module.exports = class BaseConf {
2
+ createService() {
3
+ return Promise.resolve(true);
4
+ }
5
+
6
+ createConf() {
7
+ throw new Error('`createConf` must be overrided');
8
+ }
9
+
10
+ updateConf() {
11
+ throw new Error('`updateConf` must be overrided');
12
+ }
13
+
14
+ getConf() {
15
+ throw new Error('`getConf` must be overrided');
16
+ }
17
+
18
+ publishConf() {
19
+ return Promise.resolve(true);
20
+ }
21
+ };