Simplify user extensions api (#6420)

* Simplify user extensions api

* Change structure
This commit is contained in:
John Doe
2021-02-23 21:00:45 +08:00
committed by GitHub
parent 9badca362a
commit 2d0b18c17b
2 changed files with 16 additions and 24 deletions
+12 -15
View File
@@ -15,9 +15,9 @@ class ExternalExtension extends Extension {
this.addExtension = addExtension;
this.enableDisableExtension = enableDisableExtension;
this.extensionsBaseDir = 'extension';
this.loadExtension = this.loadExtension.bind(this);
this.requestLookup = {
'save': this.saveExtension.bind(this),
'read': this.readExtensionCode.bind(this),
};
this.loadUserDefinedExtensions();
}
@@ -28,13 +28,16 @@ class ExternalExtension extends Extension {
getListOfUserDefinedExtensions() {
const basePath = this.getExtensionsBasePath();
if (fs.existsSync(basePath)) {
return fs.readdirSync(basePath).filter((f) => f.endsWith('.js'));
return fs.readdirSync(basePath).filter((f) => f.endsWith('.js')).map((fileName) => {
const extensonFilePath = path.join(basePath, fileName);
return {'name': fileName, 'code': fs.readFileSync(extensonFilePath, 'utf-8')};
});
} else {
return [];
}
}
saveExtension({name, content}) {
const ModuleConstructor = utils.loadModuleFromText(content);
saveExtension({name, code}) {
const ModuleConstructor = utils.loadModuleFromText(code);
this.loadExtension(ModuleConstructor);
const basePath = this.getExtensionsBasePath();
/* istanbul ignore else */
@@ -42,15 +45,11 @@ class ExternalExtension extends Extension {
fs.mkdirSync(basePath);
}
const extensonFilePath = path.join(basePath, name);
fs.writeFileSync(extensonFilePath, content);
fs.writeFileSync(extensonFilePath, code);
this.publishExtensions();
return utils.getResponse(`Extension ${name} loaded`, {}, null);
}
readExtensionCode({name}) {
const extensonFilePath = path.join(this.getExtensionsBasePath(), name);
const response = {name, content: fs.readFileSync(extensonFilePath, 'utf-8')};
return utils.getResponse(`Extension ${name} code read`, response, null);
}
async onMQTTMessage(topic, message) {
const match = topic.match(requestRegex);
@@ -74,11 +73,9 @@ class ExternalExtension extends Extension {
loadUserDefinedExtensions() {
const extensions = this.getListOfUserDefinedExtensions();
const extensionPath = this.getExtensionsBasePath();
for (const extension of extensions) {
const Extension = utils.loadModuleFromFile(path.join(extensionPath, extension));
this.loadExtension(Extension);
}
extensions
.map(({code}) => utils.loadModuleFromText(code))
.map(this.loadExtension);
}
async onMQTTConnected() {
this.publishExtensions();
+4 -9
View File
@@ -44,12 +44,7 @@ describe('User extensions', () => {
await controller.start();
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/example/extension', 'test', { retain: false, qos: 0 }, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extensions', stringify(['exampleExtension.js']), { retain: true, qos: 0 }, expect.any(Function));
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/extension/request/read', stringify({"name": "exampleExtension.js"}));
await flushPromises();
const expectedResponse = {"data": {"name": "exampleExtension.js", "content": extensionCode}, "status":"ok"};
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extension/response/read', stringify(expectedResponse), { retain: false, qos: 0 }, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extensions', stringify([{"name": "exampleExtension.js", "code": extensionCode}]), { retain: true, qos: 0 }, expect.any(Function));
});
it('Load user extension from api call', async () => {
@@ -59,9 +54,9 @@ describe('User extensions', () => {
await controller.start();
await flushPromises();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/extension/request/save', stringify({"name": "foo.js", "content": extensionCode}));
MQTT.events.message('zigbee2mqtt/bridge/extension/request/save', stringify({"name": "foo.js", "code": extensionCode}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extensions', stringify(['foo.js']), { retain: true, qos: 0 }, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extensions', stringify([{"name": "foo.js", "code": extensionCode}]), { retain: true, qos: 0 }, expect.any(Function));
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/example/extension', 'call from constructor', { retain: false, qos: 0 }, expect.any(Function));
expect(mkdirSyncSpy).toHaveBeenCalledWith(extensionPath);
});
@@ -73,7 +68,7 @@ describe('User extensions', () => {
await controller.start();
await flushPromises();
MQTT.publish.mockClear();
MQTT.events.message('zigbee2mqtt/bridge/extension/request/save', stringify({"name": "foo.js", "content": extensionCode}));
MQTT.events.message('zigbee2mqtt/bridge/extension/request/save', stringify({"name": "foo.js", "code": extensionCode}));
await flushPromises();
expect(MQTT.publish).toHaveBeenCalledWith('zigbee2mqtt/bridge/extension/response/save', stringify({"data":{},"error":"Unexpected identifier","status":"error"}), { retain: false, qos: 0 }, expect.any(Function));