@zhin.js/core 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/lib/adapter.d.ts +8 -6
  3. package/lib/adapter.d.ts.map +1 -1
  4. package/lib/adapter.js +13 -7
  5. package/lib/adapter.js.map +1 -1
  6. package/lib/app.d.ts +72 -14
  7. package/lib/app.d.ts.map +1 -1
  8. package/lib/app.js +241 -83
  9. package/lib/app.js.map +1 -1
  10. package/lib/bot.d.ts +10 -8
  11. package/lib/bot.d.ts.map +1 -1
  12. package/lib/config.d.ts +44 -14
  13. package/lib/config.d.ts.map +1 -1
  14. package/lib/config.js +275 -208
  15. package/lib/config.js.map +1 -1
  16. package/lib/index.d.ts +1 -1
  17. package/lib/index.d.ts.map +1 -1
  18. package/lib/index.js +1 -1
  19. package/lib/index.js.map +1 -1
  20. package/lib/log-transport.js +1 -1
  21. package/lib/log-transport.js.map +1 -1
  22. package/lib/models/system-log.d.ts +2 -2
  23. package/lib/models/system-log.d.ts.map +1 -1
  24. package/lib/models/system-log.js +1 -1
  25. package/lib/models/system-log.js.map +1 -1
  26. package/lib/models/user.d.ts +2 -2
  27. package/lib/models/user.d.ts.map +1 -1
  28. package/lib/models/user.js +1 -1
  29. package/lib/models/user.js.map +1 -1
  30. package/lib/plugin.d.ts +7 -3
  31. package/lib/plugin.d.ts.map +1 -1
  32. package/lib/plugin.js +16 -5
  33. package/lib/plugin.js.map +1 -1
  34. package/lib/prompt.d.ts +1 -1
  35. package/lib/prompt.d.ts.map +1 -1
  36. package/lib/prompt.js +9 -7
  37. package/lib/prompt.js.map +1 -1
  38. package/lib/types.d.ts +6 -5
  39. package/lib/types.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/src/adapter.ts +18 -11
  42. package/src/app.ts +358 -105
  43. package/src/bot.ts +27 -25
  44. package/src/config.ts +352 -230
  45. package/src/index.ts +1 -1
  46. package/src/log-transport.ts +1 -1
  47. package/src/models/system-log.ts +2 -2
  48. package/src/models/user.ts +2 -2
  49. package/src/plugin.ts +19 -6
  50. package/src/prompt.ts +10 -9
  51. package/src/types.ts +8 -5
  52. package/tests/adapter.test.ts +5 -200
  53. package/tests/app.test.ts +208 -181
  54. package/tests/command.test.ts +2 -2
  55. package/tests/config.test.ts +5 -326
  56. package/tests/cron.test.ts +277 -0
  57. package/tests/jsx.test.ts +300 -0
  58. package/tests/permissions.test.ts +358 -0
  59. package/tests/plugin.test.ts +40 -177
  60. package/tests/prompt.test.ts +223 -0
  61. package/tests/schema.test.ts +248 -0
  62. package/lib/schema.d.ts +0 -83
  63. package/lib/schema.d.ts.map +0 -1
  64. package/lib/schema.js +0 -245
  65. package/lib/schema.js.map +0 -1
  66. package/src/schema.ts +0 -273
package/src/schema.ts DELETED
@@ -1,273 +0,0 @@
1
- import { isEmpty } from './utils.js';
2
-
3
- export class Schema<S = any, T = S> {
4
- public [Symbol.toStringTag] = 'Schema';
5
- constructor(
6
- public meta: Schema.Meta<S, T>,
7
- public options: Schema.Options = {},
8
- ) {
9
- const _this = this;
10
- const schema = function (value?: S) {
11
- const formatter = Schema.resolve(_this.meta.type);
12
- if (!formatter) throw new Error(`type ${_this.meta.type} not found`);
13
- return formatter.call(_this, value);
14
- } as Schema<S, T>;
15
- return new Proxy(schema, {
16
- get(target, p: string | symbol, receiver: any): any {
17
- return Reflect.get(_this, p, receiver);
18
- },
19
- set(target, p: string | symbol, value: any, receiver: any): boolean {
20
- return Reflect.set(_this, p, value, receiver);
21
- },
22
- });
23
- }
24
- static fromJSON<S, T>(json: Schema.JSON<S, T>) {
25
- const { object, inner, list, ...meta } = json;
26
- const options: Schema.Options = {};
27
- if (object)
28
- options.object = Object.fromEntries(Object.entries(object).map(([key, value]) => [key, Schema.fromJSON(value)]));
29
- if (inner) options.inner = Schema.fromJSON(inner);
30
- return new Schema<S, T>(meta, options);
31
- }
32
- toJSON(): Record<string, any> {
33
- return Object.fromEntries(
34
- Object.entries({
35
- ...this.meta,
36
- default: typeof this.meta.default === 'function' ? this.meta.default() : this.meta.default,
37
- inner: this.options.inner?.toJSON(),
38
- dict: this.options.object
39
- ? Object.fromEntries(Object.entries(this.options.object || {}).map(([key, value]) => [key, value.toJSON()]))
40
- : undefined,
41
- }).filter(([key, value]) => typeof value !== 'undefined'),
42
- );
43
- }
44
- [Symbol.unscopables]() {
45
- return {
46
- options: true,
47
- meta: true,
48
- };
49
- }
50
- /** 设置是否必填 */
51
- required(): this {
52
- this.meta.required = true;
53
- return this;
54
- }
55
- /** 是否隐藏 */
56
- hidden(): this {
57
- this.meta.hidden = true;
58
- return this;
59
- }
60
- /** 设置描述 */
61
- description(description: string): this {
62
- this.meta.description = description;
63
- return this;
64
- }
65
- /** 设置默认值 */
66
- default(defaultValue: T): this {
67
- this.meta.default = defaultValue;
68
- return this;
69
- }
70
- /** 设置选项列表 */
71
- option(list: (T | Schema.Option<T>)[]): this {
72
- this.meta.options = Schema.formatOptionList(list);
73
- return this;
74
- }
75
- /** 设置是否允许多选 */
76
- multiple(): this {
77
- if (this.meta.type !== 'list') throw new Error('multiple only support list type');
78
- this.meta.multiple = true;
79
- return this;
80
- }
81
- /** 声明一个数字类型 */
82
- static number(description: string): Schema<number> {
83
- return new Schema<number>({ type: 'number', description });
84
- }
85
- /** 声明一个字符串类型 */
86
- static string(description: string): Schema<string> {
87
- return new Schema<string>({ type: 'string', description });
88
- }
89
- /** 声明一个布尔类型 */
90
- static boolean(description: string): Schema<boolean> {
91
- return new Schema<boolean>({ type: 'boolean', description });
92
- }
93
- /** 声明一个正则类型 */
94
- static regexp(description: string) {
95
- return new Schema<RegExp | string, RegExp>({ type: 'regexp', description });
96
- }
97
- /** 声明一个日期类型 */
98
- static date(description: string) {
99
- return new Schema<Date | number, Date>({ type: 'date', description });
100
- }
101
- /** 声明一个字典类型 */
102
- static dict<X extends Schema>(input: X, description: string) {
103
- return new Schema<Record<string, Schema.Types<X>>>({ type: 'dict', description }, { inner: input });
104
- }
105
- static object<X extends Record<string, Schema>>(input: X, description: string = '') {
106
- return new Schema<Schema.RecordTypes<X>>({ type: 'object', description }, { object: input });
107
- }
108
- /** 声明一个列表类型 */
109
- static list<X extends Schema>(inner: X, description: string) {
110
- return new Schema<Schema.Types<X>[]>({ type: 'list', description }, { inner });
111
- }
112
- /** 声明一个常量 */
113
- static const<X extends string | number | boolean>(value: X, description: string) {
114
- return new Schema<X>({ type: 'const', default: value as any, description });
115
- }
116
- static resolve<T extends string>(type: T): Schema.Formatter {
117
- return Schema.formatters.get(type)!;
118
- }
119
- static extend<T extends string>(type: T, formatter: Schema.Formatter) {
120
- Schema.formatters.set(type, formatter);
121
- }
122
- }
123
- export interface Schema<S = any> {
124
- (value?: S): S;
125
- }
126
- export namespace Schema {
127
- export const formatters: Map<string, Formatter> = new Map<string, Formatter>();
128
- export type Formatter<S = any, T = S> = (this: Schema, value: S) => T;
129
- export type JSON<S = any, T = S> = Meta<S, T> & {
130
- object?: Record<string, JSON>;
131
- inner?: JSON;
132
- list?: JSON[];
133
- };
134
- export interface Meta<S = any, T = S> {
135
- hidden?: boolean;
136
- type: string;
137
- default?: T;
138
- required?: boolean;
139
- options?: Option<T>[];
140
- multiple?: boolean;
141
- description: string;
142
- component?: string;
143
- min?: number;
144
- max?: number;
145
- step?: number;
146
- }
147
- export interface Options {
148
- object?: Record<string, Schema>;
149
- inner?: Schema;
150
- }
151
- export type Types<T> = T extends Schema<infer S> ? S : never;
152
- export type RecordTypes<T> = T extends Record<string, Schema>
153
- ? {
154
- [K in keyof T]?: Types<T[K]>;
155
- }
156
- : unknown;
157
- export function checkDefault<T>(schema: Schema, value: T, fallback: T = value) {
158
- if (isEmpty(value)) {
159
- value = schema.meta.default || fallback;
160
- }
161
- const validateType = (schema: Schema, value: any) => {
162
- switch (schema.meta.type) {
163
- case 'string':
164
- if (!['string', 'undefined'].includes(typeof value)) throw new TypeError(`value is not a string`);
165
- break;
166
- case 'number':
167
- if (!['number', 'undefined'].includes(typeof value)) throw new TypeError(`value is not a number`);
168
- break;
169
- case 'boolean':
170
- if (!['boolean', 'undefined'].includes(typeof value)) throw new TypeError(`value is not a boolean`);
171
- break;
172
- case 'regexp':
173
- if (!['string', 'undefined'].includes(typeof value) && !(value instanceof RegExp))
174
- throw new TypeError(`value is not a RegExp|string`);
175
- break;
176
- case 'date':
177
- if (!['number', 'undefined'].includes(typeof value) && !(value instanceof Date))
178
- throw new TypeError(`value is not a Date|number`);
179
- if (value instanceof Date && isNaN(value.getTime())) throw new TypeError(`value is not a valid Date`);
180
- break;
181
- case 'dict':
182
- if (!['object', 'undefined', 'null'].includes(typeof value)) throw new TypeError(`value is not a object`);
183
- break;
184
- case 'object':
185
- if (!['object', 'undefined', 'null'].includes(typeof value)) throw new TypeError(`value is not a object`);
186
- break;
187
- case 'list':
188
- if (typeof value !== 'undefined' && !Array.isArray(value)) throw new TypeError(`value is not a list`);
189
- break;
190
- case 'const':
191
- if (typeof value !== 'undefined' && value !== schema.meta.default) throw new TypeError(`value is not const`);
192
- break;
193
- default:
194
- throw new TypeError(`value is not a valid type`);
195
- }
196
- };
197
- if (schema.meta.required && typeof value === 'undefined') throw new Error(`value is required`);
198
- validateType(schema, value);
199
- return value;
200
- }
201
- export type Option<T = any> = {
202
- label: string;
203
- value: T;
204
- };
205
- export function formatOptionList<T extends (any | Schema.Option)[]>(list: T): Schema.Option[] {
206
- return list.map(item => {
207
- if (typeof item === 'string') {
208
- return {
209
- label: `${item}`,
210
- value: item,
211
- } as Schema.Option;
212
- }
213
- return item as unknown as Schema.Option;
214
- });
215
- }
216
- }
217
- Schema.extend('number', function (this: Schema, value: any) {
218
- value = Schema.checkDefault(this, value);
219
- return value;
220
- });
221
- Schema.extend('string', function (this: Schema, value: any) {
222
- value = Schema.checkDefault(this, value);
223
- return value;
224
- });
225
- Schema.extend('boolean', function (this: Schema, value: any) {
226
- return Schema.checkDefault(this, value);
227
- });
228
- Schema.extend('dict', function (this: Schema, value: any) {
229
- value = Schema.checkDefault(this, value, {});
230
- return Object.fromEntries(
231
- Object.entries(value).map(([key, schema]) => {
232
- return [key, this.options.inner!(schema)];
233
- }),
234
- );
235
- });
236
-
237
- Schema.extend('object', function (this: Schema, value: any) {
238
- const getDefault = (schema: Schema) => {
239
- const result = Object.create(null);
240
- for (const key in schema.options.object) {
241
- result[key] = getDefault(schema.options.object[key]);
242
- }
243
- return result;
244
- };
245
- value = Schema.checkDefault(this, value, getDefault(this));
246
- return Object.fromEntries(
247
- Object.entries(value).map(([key, schema]) => {
248
- return [key, this.options.object![key](schema)];
249
- }),
250
- );
251
- });
252
- Schema.extend('list', function (this: Schema, value: any) {
253
- value = Schema.checkDefault(this, value, []);
254
- return value.map((item: any) => this.options.inner!(item));
255
- });
256
- Schema.extend('regexp', function (this: Schema, value: any) {
257
- value = Schema.checkDefault(this, value);
258
- if (typeof value === 'string') {
259
- return new RegExp(value);
260
- }
261
- return value;
262
- });
263
- Schema.extend('date', function (this: Schema, value: any) {
264
- value = Schema.checkDefault(this, value);
265
- return new Date(value);
266
- });
267
- Schema.extend('const', function (this: Schema, value: any) {
268
- value = Schema.checkDefault(this, value);
269
- if (value !== this.meta.default) {
270
- throw new Error('const value not match');
271
- }
272
- return value;
273
- });