rename .config to .values and _emitter to _config
This commit is contained in:
Родитель
ad49597fd6
Коммит
2c78b71d54
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible Node.js debug attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Mocha",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
|
||||
"stopOnEntry": false,
|
||||
"args": [
|
||||
"${workspaceRoot}/test/*.js"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "localhost"
|
||||
},
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Coverage",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/node_modules/istanbul/lib/cli.js",
|
||||
"stopOnEntry": false,
|
||||
"args": [
|
||||
"cover",
|
||||
"${workspaceRoot}/node_modules/mocha/bin/_mocha",
|
||||
"${workspaceRoot}/test/*.js"
|
||||
],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"runtimeExecutable": null,
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "localhost"
|
||||
},
|
||||
"console": "internalConsole"
|
||||
}
|
||||
]
|
||||
}
|
13
README.md
13
README.md
|
@ -35,10 +35,9 @@ the changes that were detected.
|
|||
* ```refresh(config)```: Emitted whenever the configuration is refreshed from the store where ```config```
|
||||
is the configuration after the refresh.
|
||||
|
||||
The object returned from ```getAll()``` also has an event emitter in the ```_emitter``` property. This
|
||||
event emitter will emit the same ```changed(config, patch)``` event as ```RefreshingConfig```. This can
|
||||
be useful if you want to pass the configuration object around you application and allow different parts
|
||||
of your application to subscribe to updates to the configuration.
|
||||
The object returned from ```getAll()``` also has the ```RefreshingConfig``` instance itself in the ```_config``` property. This is
|
||||
useful if you want to pass the configuration object around your application and allowing it to subscribe to updates or otherwise
|
||||
manage the configuration.
|
||||
|
||||
# Extensions
|
||||
You can extend refreshing-config's behavior by attaching extensions using ```withExtension```:
|
||||
|
@ -50,7 +49,7 @@ const config = new RefreshingConfig.RefreshingConfig(store)
|
|||
```
|
||||
|
||||
## Refresh policies
|
||||
Refresh policies define when refreshing-config should go back to the store to get updated configuration values. Refresh policies can either be reactive (refreshing-config asks them if it should go back to the store)
|
||||
Refresh policies define when refreshing-config should go back to the store to get updated configuration values. Refresh policies can either be reactive (refreshing-config asks them if it should go back to the store)
|
||||
or proactive (they notify refreshing-config that it needs to refresh). If there are multiple refresh policies attached then refreshing-config will go back to the store if **any** of them say a refresh is required.
|
||||
|
||||
Refresh policies are bypassed in the following scenarios:
|
||||
|
@ -113,6 +112,6 @@ be ```set``` or ```delete```, the ```name``` will be the name of the configurati
|
|||
# Contributing
|
||||
Pull requests will gladly be considered!
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see
|
||||
the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com)
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see
|
||||
the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com)
|
||||
with any additional questions or comments.
|
32
index.js
32
index.js
|
@ -25,8 +25,8 @@ class RefreshingConfig extends EventEmitter {
|
|||
this.store = store;
|
||||
this.refreshPolicies = [];
|
||||
this.changePublishers = [];
|
||||
this.config = {};
|
||||
this.config._emitter = this;
|
||||
this.values = {};
|
||||
this.values._config = this;
|
||||
this.firstTime = true;
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,13 @@ class RefreshingConfig extends EventEmitter {
|
|||
throw new Error('Missing name');
|
||||
}
|
||||
return this.refreshIfNeeded().then(() => {
|
||||
return this.config[name];
|
||||
return this.values[name];
|
||||
});
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.refreshIfNeeded().then(() => {
|
||||
return this.config;
|
||||
return this.values;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -82,14 +82,14 @@ class RefreshingConfig extends EventEmitter {
|
|||
apply(patches) {
|
||||
// Snapshot the properties/name and apply the patches. If a changed property is still present,
|
||||
// it was changed so set. If it is now missing, delete it.
|
||||
const newConfig = Object.assign({}, this.config);
|
||||
patch.apply(newConfig, patches);
|
||||
const newValues = Object.assign({}, this.values);
|
||||
patch.apply(newValues, patches);
|
||||
const affected = this._getAffectedProperties(patches);
|
||||
return Q.all(affected.map(key => {
|
||||
if (newConfig[key] === undefined) {
|
||||
if (newValues[key] === undefined) {
|
||||
return this.delete(key);
|
||||
} else {
|
||||
return this.set(key, newConfig[key]);
|
||||
return this.set(key, newValues[key]);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -123,20 +123,20 @@ class RefreshingConfig extends EventEmitter {
|
|||
}
|
||||
const self = this;
|
||||
this.refreshPromise = this.store.getAll()
|
||||
.then(newConfig => {
|
||||
.then(newValues => {
|
||||
self.refreshPromise = null;
|
||||
const configPatch = patch.compare(self.config, newConfig);
|
||||
const emitterPatchIndex = configPatch.findIndex(patch => patch.path === '/_emitter');
|
||||
const configPatch = patch.compare(self.values, newValues);
|
||||
const emitterPatchIndex = configPatch.findIndex(patch => patch.path === '/_config');
|
||||
/* istanbul ignore else */
|
||||
if (emitterPatchIndex >= 0) {
|
||||
configPatch.splice(emitterPatchIndex, 1);
|
||||
}
|
||||
if (configPatch.length !== 0) {
|
||||
patch.apply(self.config, configPatch);
|
||||
self.emit('changed', self.config, configPatch);
|
||||
patch.apply(self.values, configPatch);
|
||||
self.emit('changed', self.values, configPatch);
|
||||
}
|
||||
self.emit('refresh', self.config);
|
||||
return self.config;
|
||||
self.emit('refresh', self.values);
|
||||
return self.values;
|
||||
});
|
||||
return this.refreshPromise;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ class RefreshingConfig extends EventEmitter {
|
|||
if (shouldRefresh) {
|
||||
return this.refresh();
|
||||
}
|
||||
return Q(this.config);
|
||||
return Q(this.values);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@ describe('RefreshingConfig', () => {
|
|||
};
|
||||
const target = new config.RefreshingConfig(store);
|
||||
return target.getAll().then(value => {
|
||||
value._emitter.should.be.instanceof(events.EventEmitter);
|
||||
delete value._emitter;
|
||||
value._config.should.be.instanceof(events.EventEmitter);
|
||||
delete value._config;
|
||||
value.should.deep.equal(values);
|
||||
});
|
||||
});
|
||||
|
@ -108,7 +108,8 @@ describe('RefreshingConfig', () => {
|
|||
const target = new config.RefreshingConfig(store)
|
||||
.withExtension(yesRefreshPolicy)
|
||||
.withExtension(noRefreshPolicy);
|
||||
return Q.all([target.get('foo'), target.get('bar')])
|
||||
// chain the gets here as concurrent gets will get coalesced
|
||||
return target.get('foo').then(() => target.get('bar'))
|
||||
.then(() => {
|
||||
store.getAll.calledTwice.should.be.true;
|
||||
yesRefreshPolicy.shouldRefresh.should.be.calledOnce;
|
||||
|
@ -165,7 +166,7 @@ describe('RefreshingConfig', () => {
|
|||
target.on('changed', (newValues, diff) => {
|
||||
invokeCount += 1;
|
||||
newValues = clone(newValues);
|
||||
delete newValues._emitter;
|
||||
delete newValues._config;
|
||||
if (invokeCount === 1) {
|
||||
newValues.should.deep.equal(firstResponse);
|
||||
diff.length.should.equal(1);
|
||||
|
@ -178,21 +179,21 @@ describe('RefreshingConfig', () => {
|
|||
});
|
||||
const getAllPromise = target.getAll()
|
||||
.then(values => {
|
||||
values._emitter.on('changed', (newValues, diff) => {
|
||||
values._config.on('changed', (newValues, diff) => {
|
||||
newValues = clone(newValues);
|
||||
delete newValues._emitter;
|
||||
delete newValues._config;
|
||||
newValues.should.deep.equal(secondResponse);
|
||||
diff.length.should.equal(2);
|
||||
valuesEmitDeferand.resolve();
|
||||
});
|
||||
values = clone(values);
|
||||
delete values._emitter;
|
||||
delete values._config;
|
||||
values.should.deep.equal(firstResponse);
|
||||
})
|
||||
.then(target.getAll.bind(target))
|
||||
.then(values => {
|
||||
values = clone(values);
|
||||
delete values._emitter;
|
||||
delete values._config;
|
||||
values.should.deep.equal(secondResponse);
|
||||
});
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче