mirror of https://github.com/msgbyte/tailchat
feat: 增加手动安装插件功能
parent
ca8df00861
commit
7929ef1ecf
@ -0,0 +1,18 @@
|
|||||||
|
import { isValidJson } from '../json-helper';
|
||||||
|
|
||||||
|
describe('isValidJson', () => {
|
||||||
|
test.each([
|
||||||
|
['foo', false],
|
||||||
|
['[]', true],
|
||||||
|
['{}', true],
|
||||||
|
['{"foo": []}', true],
|
||||||
|
['{"foo": [}', false],
|
||||||
|
['{foo: bar}', false],
|
||||||
|
['{"foo": "bar"}', true],
|
||||||
|
[[], false],
|
||||||
|
[null, false],
|
||||||
|
[undefined, false],
|
||||||
|
])('%s => %s', (input: any, should) => {
|
||||||
|
expect(isValidJson(input)).toBe(should);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* 判断是否是一个合法的json字符串
|
||||||
|
* @param jsonStr json字符串
|
||||||
|
*/
|
||||||
|
export function isValidJson(jsonStr: string): boolean {
|
||||||
|
if (typeof jsonStr !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSON.parse(jsonStr);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,17 @@
|
|||||||
// mock
|
// mock
|
||||||
jest.mock('tailchat-shared/i18n');
|
jest.mock('tailchat-shared/i18n');
|
||||||
|
|
||||||
|
const ignoreErroMessages = [
|
||||||
|
/Warning.*not wrapped in act/,
|
||||||
|
/PluginManifest validation/,
|
||||||
|
];
|
||||||
|
|
||||||
// https://github.com/testing-library/react-testing-library#suppressing-unnecessary-warnings-on-react-dom-168
|
// https://github.com/testing-library/react-testing-library#suppressing-unnecessary-warnings-on-react-dom-168
|
||||||
const originalError = console.error;
|
const originalError = console.error;
|
||||||
console.error = (...args) => {
|
console.error = (...args) => {
|
||||||
if (/Warning.*not wrapped in act/.test(args[0])) {
|
if (ignoreErroMessages.some((re) => re.test(args[0]))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
originalError.call(console, ...args);
|
originalError.call(console, ...args);
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
import { parsePluginManifest } from '../utils';
|
||||||
|
|
||||||
|
describe('parsePluginManifest', () => {
|
||||||
|
test.each([
|
||||||
|
[
|
||||||
|
'correct',
|
||||||
|
JSON.stringify({
|
||||||
|
label: '网页面板插件',
|
||||||
|
name: 'com.msgbyte.webview',
|
||||||
|
url: '/plugins/com.msgbyte.webview/index.js',
|
||||||
|
version: '0.0.0',
|
||||||
|
author: 'msgbyte',
|
||||||
|
description: '为群组提供创建网页面板的功能',
|
||||||
|
requireRestart: false,
|
||||||
|
}),
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
['string', 'foo.bar', false],
|
||||||
|
[
|
||||||
|
'no used properties',
|
||||||
|
JSON.stringify({
|
||||||
|
label: '网页面板插件',
|
||||||
|
foo: 'bar',
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'more properties',
|
||||||
|
JSON.stringify({
|
||||||
|
label: '网页面板插件',
|
||||||
|
name: 'com.msgbyte.webview',
|
||||||
|
url: '/plugins/com.msgbyte.webview/index.js',
|
||||||
|
version: '0.0.0',
|
||||||
|
author: 'msgbyte',
|
||||||
|
description: '为群组提供创建网页面板的功能',
|
||||||
|
requireRestart: false,
|
||||||
|
foo: 'bar',
|
||||||
|
}),
|
||||||
|
true,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'missed properties',
|
||||||
|
JSON.stringify({
|
||||||
|
label: '网页面板插件',
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
],
|
||||||
|
])('case: %# %s', (title, input, valid) => {
|
||||||
|
if (valid === true) {
|
||||||
|
expect(parsePluginManifest(input)).toEqual(JSON.parse(input));
|
||||||
|
} else {
|
||||||
|
expect(() => parsePluginManifest(input)).toThrowError();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,39 @@
|
|||||||
|
import { isValidJson, PluginManifest, t } from 'tailchat-shared';
|
||||||
|
import { Validator } from 'jsonschema';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析json字符串成插件对象
|
||||||
|
* 如果格式不合法则会抛出异常
|
||||||
|
*/
|
||||||
|
export function parsePluginManifest(json: string): PluginManifest {
|
||||||
|
if (!isValidJson(json)) {
|
||||||
|
throw new Error(t('不是一个合法的JSON字符串'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = JSON.parse(json);
|
||||||
|
const { valid, errors } = new Validator().validate(obj, {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
label: { type: 'string' },
|
||||||
|
name: { type: 'string' },
|
||||||
|
url: { type: 'string' },
|
||||||
|
version: { type: 'string' },
|
||||||
|
author: { type: 'string' },
|
||||||
|
description: { type: 'string' },
|
||||||
|
requireRestart: { type: 'boolean' },
|
||||||
|
},
|
||||||
|
required: ['label', 'name', 'url', 'version', 'author', 'description'],
|
||||||
|
additionalProperties: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
console.error(
|
||||||
|
'[PluginManifest validation]:',
|
||||||
|
errors.map((e) => e.message).join(', ')
|
||||||
|
);
|
||||||
|
|
||||||
|
throw new Error(t('不是一个合法的插件配置'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
Loading…
Reference in New Issue