-
-
Notifications
You must be signed in to change notification settings - Fork 658
/
state-service.js
122 lines (109 loc) · 3.56 KB
/
state-service.js
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
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
const joi = require('@hapi/joi');
const fs = require('fs');
const mime = require('mime');
const { featureShema } = require('./routes/admin-api/feature-schema');
const strategySchema = require('./routes/admin-api/strategy-schema');
const YAML = require('js-yaml');
const {
FEATURE_IMPORT,
DROP_FEATURES,
STRATEGY_IMPORT,
DROP_STRATEGIES,
} = require('./event-type');
const dataSchema = joi.object().keys({
version: joi.number(),
features: joi
.array()
.optional()
.items(featureShema),
strategies: joi
.array()
.optional()
.items(strategySchema),
});
function readFile(file) {
return new Promise((resolve, reject) =>
fs.readFile(file, (err, v) => (err ? reject(err) : resolve(v)))
);
}
function parseFile(file, data) {
return mime.getType(file) === 'text/yaml'
? YAML.safeLoad(data)
: JSON.parse(data);
}
class StateService {
constructor(config) {
this.config = config;
this.logger = config.getLogger('state-service.js');
}
importFile({ file, dropBeforeImport, userName }) {
return readFile(file)
.then(data => parseFile(file, data))
.then(data => this.import({ data, userName, dropBeforeImport }));
}
async import({ data, userName, dropBeforeImport }) {
const { eventStore } = this.config.stores;
const importData = await dataSchema.validateAsync(data);
if (importData.features) {
this.logger.info(
`Importing ${importData.features.length} features`
);
if (dropBeforeImport) {
this.logger.info(`Dropping existing features`);
await eventStore.store({
type: DROP_FEATURES,
createdBy: userName,
data: { name: 'all-features' },
});
}
await Promise.all(
importData.features.map(feature =>
eventStore.store({
type: FEATURE_IMPORT,
createdBy: userName,
data: feature,
})
)
);
}
if (importData.strategies) {
this.logger.info(
`Importing ${importData.strategies.length} strategies`
);
if (dropBeforeImport) {
this.logger.info(`Dropping existing strategies`);
await eventStore.store({
type: DROP_STRATEGIES,
createdBy: userName,
data: { name: 'all-strategies' },
});
}
await Promise.all(
importData.strategies.map(strategy =>
eventStore.store({
type: STRATEGY_IMPORT,
createdBy: userName,
data: strategy,
})
)
);
}
}
async export({ includeFeatureToggles = true, includeStrategies = true }) {
const { featureToggleStore, strategyStore } = this.config.stores;
return Promise.all([
includeFeatureToggles
? featureToggleStore.getFeatures()
: Promise.resolve(),
includeStrategies
? strategyStore.getEditableStrategies()
: Promise.resolve(),
]).then(([features, strategies]) => ({
version: 1,
features,
strategies,
}));
}
}
module.exports = StateService;