UNPKG

@launchdarkly/js-server-sdk-common

Version:
127 lines 5.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const serialization_1 = require("../store/serialization"); const VersionedDataKinds_1 = require("../store/VersionedDataKinds"); const FileLoader_1 = require("./FileLoader"); function makeFlagWithValue(key, value, version) { return { key, on: true, fallthrough: { variation: 0 }, variations: [value], version, }; } class FileDataSource { /** * This is internal because we want instances to only be created with the * factory. * @internal */ constructor(options, filesystem, _featureStore, _initSuccessHandler = () => { }, _errorHandler) { var _a; this._featureStore = _featureStore; this._initSuccessHandler = _initSuccessHandler; this._errorHandler = _errorHandler; this._allData = {}; this._fileLoader = new FileLoader_1.default(filesystem, options.paths, (_a = options.autoUpdate) !== null && _a !== void 0 ? _a : false, (results) => { var _a, _b; // Whenever changes are detected we re-process all of the data. // The FileLoader will have handled debouncing for us. try { this._processFileData(results); } catch (err) { // If this was during start, then the initCallback will be present. (_a = this._errorHandler) === null || _a === void 0 ? void 0 : _a.call(this, err); (_b = this._logger) === null || _b === void 0 ? void 0 : _b.error(`Error processing files: ${err}`); } }); this._logger = options.logger; this._yamlParser = options.yamlParser; } start() { // Use an immediately invoked function expression to allow handling of the // async loading without making start async itself. (async () => { var _a; try { await this._fileLoader.loadAndWatch(); } catch (err) { // There was an issue loading/watching the files. // Report back to the caller. (_a = this._errorHandler) === null || _a === void 0 ? void 0 : _a.call(this, err); } })(); } stop() { this._fileLoader.close(); } close() { this.stop(); } _addItem(kind, item) { if (!this._allData[kind.namespace]) { this._allData[kind.namespace] = {}; } if (this._allData[kind.namespace][item.key]) { throw new Error(`found duplicate key: "${item.key}"`); } else { this._allData[kind.namespace][item.key] = item; } } _processFileData(fileData) { // Clear any existing data before re-populating it. const oldData = this._allData; this._allData = {}; // We let the parsers throw, and the caller can handle the rejection. fileData.forEach((fd) => { let parsed; if (fd.path.endsWith('.yml') || fd.path.endsWith('.yaml')) { if (this._yamlParser) { parsed = this._yamlParser(fd.data); } else { throw new Error(`Attempted to parse yaml file (${fd.path}) without parser.`); } } else { parsed = JSON.parse(fd.data); } this._processParsedData(parsed, oldData); }); this._featureStore.init(this._allData, () => { // Call the init callback if present. // Then clear the callback so we cannot call it again. this._initSuccessHandler(); this._initSuccessHandler = () => { }; }); } _processParsedData(parsed, oldData) { Object.keys(parsed.flags || {}).forEach((key) => { (0, serialization_1.processFlag)(parsed.flags[key]); this._addItem(VersionedDataKinds_1.default.Features, parsed.flags[key]); }); Object.keys(parsed.flagValues || {}).forEach((key) => { var _a, _b; const previousInstance = (_a = oldData[VersionedDataKinds_1.default.Features.namespace]) === null || _a === void 0 ? void 0 : _a[key]; let { version } = previousInstance !== null && previousInstance !== void 0 ? previousInstance : { version: 1 }; // If the data is different, then we want to increment the version. if (previousInstance && JSON.stringify(parsed.flagValues[key]) !== JSON.stringify((_b = previousInstance === null || previousInstance === void 0 ? void 0 : previousInstance.variations) === null || _b === void 0 ? void 0 : _b[0])) { version += 1; } const flag = makeFlagWithValue(key, parsed.flagValues[key], version); (0, serialization_1.processFlag)(flag); this._addItem(VersionedDataKinds_1.default.Features, flag); }); Object.keys(parsed.segments || {}).forEach((key) => { (0, serialization_1.processSegment)(parsed.segments[key]); this._addItem(VersionedDataKinds_1.default.Segments, parsed.segments[key]); }); } } exports.default = FileDataSource; //# sourceMappingURL=FileDataSource.js.map