forked from launchdarkly/node-server-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
prepare 5.7.0 release (launchdarkly#134)
- Loading branch information
1 parent
1273ba9
commit d7a95a4
Showing
21 changed files
with
1,926 additions
and
911 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"env": { | ||
"test": { | ||
"presets": [ | ||
[ | ||
"env", | ||
{ | ||
"targets": { | ||
"node": "6" | ||
} | ||
} | ||
] | ||
] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
var fs = require('fs'), | ||
winston = require('winston'), | ||
yaml = require('yaml'), | ||
dataKind = require('./versioned_data_kind'); | ||
|
||
/* | ||
FileDataSource provides a way to use local files as a source of feature flag state, instead of | ||
connecting to LaunchDarkly. This would typically be used in a test environment. | ||
See documentation in index.d.ts. | ||
*/ | ||
function FileDataSource(options) { | ||
var paths = (options && options.paths) || []; | ||
var autoUpdate = !!options.autoUpdate; | ||
|
||
return config => { | ||
var featureStore = config.featureStore; | ||
var watchers = []; | ||
var pendingUpdate = false; | ||
var logger = options.logger || config.logger || defaultLogger(); | ||
var inited = false; | ||
|
||
function defaultLogger() { | ||
return new winston.Logger({ | ||
level: 'info', | ||
transports: [ new (winston.transports.Console)() ] | ||
}); | ||
} | ||
|
||
function loadFilePromise(path, allData) { | ||
return new Promise((resolve, reject) => | ||
fs.readFile(path, 'utf8', (err, data) => | ||
err ? reject(err) : resolve(data)) | ||
).then(data => { | ||
var parsed = parseData(data) || {}; | ||
var addItem = (kind, item) => { | ||
if (!allData[kind.namespace]) { | ||
allData[kind.namespace] = {}; | ||
} | ||
if (allData[kind.namespace][item.key]) { | ||
throw new Error('found duplicate key: "' + item.key + '"'); | ||
} else { | ||
allData[kind.namespace][item.key] = item; | ||
} | ||
} | ||
Object.keys(parsed.flags || {}).forEach(key => { | ||
addItem(dataKind.features, parsed.flags[key]); | ||
}); | ||
Object.keys(parsed.flagValues || {}).forEach(key => { | ||
addItem(dataKind.features, makeFlagWithValue(key, parsed.flagValues[key])); | ||
}); | ||
Object.keys(parsed.segments || {}).forEach(key => { | ||
addItem(dataKind.segments, parsed.segments[key]); | ||
}); | ||
}); | ||
} | ||
|
||
function loadAllPromise() { | ||
pendingUpdate = false; | ||
var allData = {}; | ||
var p = Promise.resolve(); | ||
for (var i = 0; i < paths.length; i++) { | ||
(path => { | ||
p = p.then(() => loadFilePromise(path, allData)) | ||
.catch(e => { | ||
throw new Error('Unable to load flags: ' + e + ' [' + path + ']'); | ||
}); | ||
})(paths[i]); | ||
} | ||
return p.then(() => initStorePromise(allData)); | ||
} | ||
|
||
function initStorePromise(data) { | ||
return new Promise(resolve => featureStore.init(data, () => { | ||
inited = true; | ||
resolve(); | ||
})); | ||
} | ||
|
||
function parseData(data) { | ||
// Every valid JSON document is also a valid YAML document (for parsers that comply | ||
// with the spec, which this one does) so we can parse both with the same parser. | ||
return yaml.parse(data); | ||
} | ||
|
||
function makeFlagWithValue(key, value) { | ||
return { | ||
key: key, | ||
on: true, | ||
fallthrough: { variation: 0 }, | ||
variations: [ value ] | ||
}; | ||
} | ||
|
||
function startWatching() { | ||
var reload = () => { | ||
loadAllPromise().then(() => { | ||
logger && logger.warn('Reloaded flags from file data'); | ||
}).catch(() => {}); | ||
}; | ||
paths.forEach(path => { | ||
var watcher = fs.watch(path, { persistent: false }, (event, filename) => { | ||
if (!pendingUpdate) { // coalesce updates to avoid reloading repeatedly | ||
pendingUpdate = true; | ||
setTimeout(reload, 0); | ||
} | ||
}); | ||
watchers.push(watcher); | ||
}); | ||
} | ||
|
||
function stopWatching() { | ||
watchers.forEach(w => w.close()); | ||
watchers = []; | ||
} | ||
|
||
var fds = {}; | ||
|
||
fds.start = fn => { | ||
var cb = fn || (() => {}); | ||
|
||
if (autoUpdate) { | ||
startWatching(); | ||
} | ||
|
||
loadAllPromise().then(() => cb(), err => cb(err)); | ||
}; | ||
|
||
fds.stop = () => { | ||
if (autoUpdate) { | ||
stopWatching(); | ||
} | ||
}; | ||
|
||
fds.initialized = () => { | ||
return inited; | ||
}; | ||
|
||
fds.close = () => { | ||
fds.stop(); | ||
}; | ||
|
||
return fds; | ||
} | ||
} | ||
|
||
module.exports = FileDataSource; |
Oops, something went wrong.