imean-service-engine 2.0.0 → 2.0.2
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.
- package/dist/index.d.mts +77 -52
- package/dist/index.d.ts +77 -52
- package/dist/index.js +2078 -1945
- package/dist/index.mjs +2076 -1944
- package/package.json +9 -2
- package/.vscode/settings.json +0 -8
- package/src/core/checker.ts +0 -33
- package/src/core/decorators.test.ts +0 -96
- package/src/core/decorators.ts +0 -68
- package/src/core/engine.test.ts +0 -218
- package/src/core/engine.ts +0 -635
- package/src/core/errors.ts +0 -28
- package/src/core/factory.test.ts +0 -73
- package/src/core/factory.ts +0 -92
- package/src/core/logger.ts +0 -65
- package/src/core/testing.ts +0 -73
- package/src/core/types.ts +0 -191
- package/src/index.ts +0 -49
- package/src/metadata/README.md +0 -422
- package/src/metadata/metadata.test.ts +0 -369
- package/src/metadata/metadata.ts +0 -512
- package/src/plugins/action/action-plugin.test.ts +0 -660
- package/src/plugins/action/decorator.ts +0 -14
- package/src/plugins/action/index.ts +0 -4
- package/src/plugins/action/plugin.ts +0 -349
- package/src/plugins/action/types.ts +0 -49
- package/src/plugins/action/utils.test.ts +0 -196
- package/src/plugins/action/utils.ts +0 -111
- package/src/plugins/cache/adapter.test.ts +0 -689
- package/src/plugins/cache/adapter.ts +0 -324
- package/src/plugins/cache/cache-plugin.test.ts +0 -269
- package/src/plugins/cache/decorator.ts +0 -26
- package/src/plugins/cache/index.ts +0 -20
- package/src/plugins/cache/plugin.ts +0 -299
- package/src/plugins/cache/types.ts +0 -69
- package/src/plugins/client-code/client-code-plugin.test.ts +0 -511
- package/src/plugins/client-code/format.ts +0 -9
- package/src/plugins/client-code/generator.test.ts +0 -52
- package/src/plugins/client-code/generator.ts +0 -263
- package/src/plugins/client-code/index.ts +0 -15
- package/src/plugins/client-code/plugin.ts +0 -158
- package/src/plugins/client-code/types.ts +0 -52
- package/src/plugins/client-code/utils.ts +0 -164
- package/src/plugins/graceful-shutdown/graceful-shutdown-plugin.test.ts +0 -401
- package/src/plugins/graceful-shutdown/index.ts +0 -3
- package/src/plugins/graceful-shutdown/plugin.ts +0 -279
- package/src/plugins/graceful-shutdown/types.ts +0 -17
- package/src/plugins/rate-limit/rate-limit-plugin.example.ts +0 -171
- package/src/plugins/route/components/Layout.tsx +0 -42
- package/src/plugins/route/components/ServiceStatusPage.tsx +0 -141
- package/src/plugins/route/decorator.ts +0 -50
- package/src/plugins/route/index.ts +0 -16
- package/src/plugins/route/plugin.ts +0 -218
- package/src/plugins/route/route-plugin.test.ts +0 -759
- package/src/plugins/route/types.ts +0 -72
- package/src/plugins/schedule/README.md +0 -309
- package/src/plugins/schedule/decorator.ts +0 -25
- package/src/plugins/schedule/index.ts +0 -12
- package/src/plugins/schedule/mock-etcd.ts +0 -145
- package/src/plugins/schedule/plugin.ts +0 -164
- package/src/plugins/schedule/schedule-plugin.test.ts +0 -312
- package/src/plugins/schedule/scheduler.ts +0 -164
- package/src/plugins/schedule/types.ts +0 -94
- package/src/plugins/schedule/utils.test.ts +0 -163
- package/src/plugins/schedule/utils.ts +0 -41
- package/tests/integration/client.test.ts +0 -203
- package/tests/integration/dev-service.ts +0 -301
- package/tests/integration/generated/client.ts +0 -123
- package/tests/integration/start-service.ts +0 -21
- package/tsconfig.json +0 -27
- package/tsup.config.ts +0 -16
- package/vitest.config.ts +0 -19
|
@@ -1,369 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
createClassDecorator,
|
|
4
|
-
createMethodDecorator,
|
|
5
|
-
getAllMethodMetadata,
|
|
6
|
-
getClassMetadata,
|
|
7
|
-
getClassesByKey,
|
|
8
|
-
getKeysByClass,
|
|
9
|
-
getMethodMetadata,
|
|
10
|
-
hasClassMetadata,
|
|
11
|
-
hasMethodMetadata,
|
|
12
|
-
} from "./metadata";
|
|
13
|
-
|
|
14
|
-
describe("通用元数据工具库", () => {
|
|
15
|
-
describe("类装饰器", () => {
|
|
16
|
-
it("应该能够创建和使用类装饰器", () => {
|
|
17
|
-
const Module = createClassDecorator();
|
|
18
|
-
|
|
19
|
-
@Module({ name: "test-module", version: "1.0.0" })
|
|
20
|
-
class TestService {}
|
|
21
|
-
|
|
22
|
-
const metadata = getClassMetadata(TestService);
|
|
23
|
-
expect(metadata.name).toBe("test-module");
|
|
24
|
-
expect(metadata.version).toBe("1.0.0");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("应该支持合并多个装饰器的元数据", () => {
|
|
28
|
-
const Module = createClassDecorator();
|
|
29
|
-
const Config = createClassDecorator();
|
|
30
|
-
|
|
31
|
-
@Module({ name: "test" })
|
|
32
|
-
@Config({ env: "production" })
|
|
33
|
-
class TestService {}
|
|
34
|
-
|
|
35
|
-
const metadata = getClassMetadata(TestService);
|
|
36
|
-
expect(metadata.name).toBe("test");
|
|
37
|
-
expect(metadata.env).toBe("production");
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("应该能够检查类是否有元数据", () => {
|
|
41
|
-
const Module = createClassDecorator();
|
|
42
|
-
|
|
43
|
-
@Module({ name: "test" })
|
|
44
|
-
class TestService {}
|
|
45
|
-
|
|
46
|
-
class EmptyService {}
|
|
47
|
-
|
|
48
|
-
expect(hasClassMetadata(TestService)).toBe(true);
|
|
49
|
-
expect(hasClassMetadata(EmptyService)).toBe(false);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("应该支持自定义元数据键", () => {
|
|
53
|
-
const CUSTOM_KEY = Symbol.for("custom-key");
|
|
54
|
-
const CustomDecorator = createClassDecorator(CUSTOM_KEY);
|
|
55
|
-
|
|
56
|
-
@CustomDecorator({ custom: "value" })
|
|
57
|
-
class TestService {}
|
|
58
|
-
|
|
59
|
-
const metadata = getClassMetadata(TestService, CUSTOM_KEY);
|
|
60
|
-
expect(metadata.custom).toBe("value");
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe("双向访问功能", () => {
|
|
65
|
-
it("应该能够通过 key 获取所有被装饰的类", () => {
|
|
66
|
-
// 使用唯一的 key 避免测试之间的干扰
|
|
67
|
-
const uniqueKey = Symbol("test-key-1");
|
|
68
|
-
const Module = createClassDecorator(uniqueKey);
|
|
69
|
-
|
|
70
|
-
@Module({ name: "module1" })
|
|
71
|
-
class Module1 {}
|
|
72
|
-
|
|
73
|
-
@Module({ name: "module2" })
|
|
74
|
-
class Module2 {}
|
|
75
|
-
|
|
76
|
-
// 实例化类以确保 addInitializer 执行
|
|
77
|
-
new Module1();
|
|
78
|
-
new Module2();
|
|
79
|
-
|
|
80
|
-
const classes = getClassesByKey(uniqueKey);
|
|
81
|
-
expect(classes.size).toBe(2);
|
|
82
|
-
expect(classes.has(Module1)).toBe(true);
|
|
83
|
-
expect(classes.has(Module2)).toBe(true);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("应该能够通过类获取所有装饰它的 key", () => {
|
|
87
|
-
const Module = createClassDecorator();
|
|
88
|
-
const Config = createClassDecorator(Symbol.for("config"));
|
|
89
|
-
const Cache = createClassDecorator(Symbol.for("cache"));
|
|
90
|
-
|
|
91
|
-
const moduleKey = Symbol.for("imean:classMetadata");
|
|
92
|
-
const configKey = Symbol.for("config");
|
|
93
|
-
const cacheKey = Symbol.for("cache");
|
|
94
|
-
|
|
95
|
-
@Module({ name: "test" })
|
|
96
|
-
@Config({ env: "prod" })
|
|
97
|
-
@Cache({ ttl: 60 })
|
|
98
|
-
class TestService {}
|
|
99
|
-
|
|
100
|
-
// 实例化类以确保 addInitializer 执行
|
|
101
|
-
new TestService();
|
|
102
|
-
|
|
103
|
-
const keys = getKeysByClass(TestService);
|
|
104
|
-
expect(keys.size).toBe(3);
|
|
105
|
-
expect(keys.has(moduleKey)).toBe(true);
|
|
106
|
-
expect(keys.has(configKey)).toBe(true);
|
|
107
|
-
expect(keys.has(cacheKey)).toBe(true);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("应该能够通过 key 查找类并获取元数据", () => {
|
|
111
|
-
// 使用唯一的 key 避免测试之间的干扰
|
|
112
|
-
const uniqueKey = Symbol("test-key-2");
|
|
113
|
-
const Module = createClassDecorator(uniqueKey);
|
|
114
|
-
|
|
115
|
-
@Module({ name: "user-module" })
|
|
116
|
-
class UserService {}
|
|
117
|
-
|
|
118
|
-
@Module({ name: "order-module" })
|
|
119
|
-
class OrderService {}
|
|
120
|
-
|
|
121
|
-
// 实例化类以确保 addInitializer 执行
|
|
122
|
-
new UserService();
|
|
123
|
-
new OrderService();
|
|
124
|
-
|
|
125
|
-
const classes = getClassesByKey(uniqueKey);
|
|
126
|
-
expect(classes.size).toBe(2);
|
|
127
|
-
|
|
128
|
-
// 遍历所有类并获取元数据
|
|
129
|
-
const metadataList: Array<{ name: string }> = [];
|
|
130
|
-
for (const ModuleClass of classes) {
|
|
131
|
-
const metadata = getClassMetadata(ModuleClass, uniqueKey);
|
|
132
|
-
metadataList.push(metadata);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
expect(metadataList).toHaveLength(2);
|
|
136
|
-
const names = metadataList.map((m) => m.name).sort();
|
|
137
|
-
expect(names).toEqual(["order-module", "user-module"]);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("应该能够通过类查找所有 key 并获取对应的元数据", () => {
|
|
141
|
-
const Module = createClassDecorator();
|
|
142
|
-
const Config = createClassDecorator(Symbol.for("config"));
|
|
143
|
-
|
|
144
|
-
const moduleKey = Symbol.for("imean:classMetadata");
|
|
145
|
-
const configKey = Symbol.for("config");
|
|
146
|
-
|
|
147
|
-
@Module({ name: "test-module" })
|
|
148
|
-
@Config({ env: "production", debug: true })
|
|
149
|
-
class TestService {}
|
|
150
|
-
|
|
151
|
-
// 实例化类以确保 addInitializer 执行
|
|
152
|
-
new TestService();
|
|
153
|
-
|
|
154
|
-
const keys = getKeysByClass(TestService);
|
|
155
|
-
expect(keys.size).toBe(2);
|
|
156
|
-
|
|
157
|
-
// 遍历所有 key 并获取对应的元数据
|
|
158
|
-
const moduleMetadata = getClassMetadata(TestService, moduleKey);
|
|
159
|
-
const configMetadata = getClassMetadata(TestService, configKey);
|
|
160
|
-
|
|
161
|
-
expect(moduleMetadata.name).toBe("test-module");
|
|
162
|
-
expect(configMetadata.env).toBe("production");
|
|
163
|
-
expect(configMetadata.debug).toBe(true);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("方法装饰器也应该在类上注册 key", () => {
|
|
167
|
-
const Handler = createMethodDecorator();
|
|
168
|
-
const methodKey = Symbol.for("imean:methodMetadata");
|
|
169
|
-
|
|
170
|
-
class TestService {
|
|
171
|
-
@Handler({ type: "route" })
|
|
172
|
-
getUser() {}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// 实例化类以确保 addInitializer 执行
|
|
176
|
-
new TestService();
|
|
177
|
-
|
|
178
|
-
// 方法装饰器也会在类上注册 key
|
|
179
|
-
const keys = getKeysByClass(TestService);
|
|
180
|
-
expect(keys.has(methodKey)).toBe(true);
|
|
181
|
-
|
|
182
|
-
// 通过 key 应该能找到这个类
|
|
183
|
-
const classes = getClassesByKey(methodKey);
|
|
184
|
-
expect(classes.has(TestService)).toBe(true);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("未装饰的类应该返回空的 key Set", () => {
|
|
188
|
-
class EmptyService {}
|
|
189
|
-
|
|
190
|
-
const keys = getKeysByClass(EmptyService);
|
|
191
|
-
expect(keys.size).toBe(0);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it("不存在的 key 应该返回空的类 Set", () => {
|
|
195
|
-
const nonExistentKey = Symbol.for("non-existent-key");
|
|
196
|
-
const classes = getClassesByKey(nonExistentKey);
|
|
197
|
-
expect(classes.size).toBe(0);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it("应该支持从实例获取 keys", () => {
|
|
201
|
-
const Module = createClassDecorator();
|
|
202
|
-
const Config = createClassDecorator(Symbol.for("config"));
|
|
203
|
-
|
|
204
|
-
const moduleKey = Symbol.for("imean:classMetadata");
|
|
205
|
-
const configKey = Symbol.for("config");
|
|
206
|
-
|
|
207
|
-
@Module({ name: "test" })
|
|
208
|
-
@Config({ env: "prod" })
|
|
209
|
-
class TestService {}
|
|
210
|
-
|
|
211
|
-
const instance = new TestService();
|
|
212
|
-
const keys = getKeysByClass(instance);
|
|
213
|
-
|
|
214
|
-
expect(keys.size).toBe(2);
|
|
215
|
-
expect(keys.has(moduleKey)).toBe(true);
|
|
216
|
-
expect(keys.has(configKey)).toBe(true);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("多个类使用同一个 key 时应该都能被找到", () => {
|
|
220
|
-
// 使用唯一的 key 避免测试之间的干扰
|
|
221
|
-
const uniqueKey = Symbol("test-key-3");
|
|
222
|
-
const Module = createClassDecorator(uniqueKey);
|
|
223
|
-
|
|
224
|
-
@Module({ name: "service1" })
|
|
225
|
-
class Service1 {}
|
|
226
|
-
|
|
227
|
-
@Module({ name: "service2" })
|
|
228
|
-
class Service2 {}
|
|
229
|
-
|
|
230
|
-
@Module({ name: "service3" })
|
|
231
|
-
class Service3 {}
|
|
232
|
-
|
|
233
|
-
// 实例化类以确保 addInitializer 执行
|
|
234
|
-
new Service1();
|
|
235
|
-
new Service2();
|
|
236
|
-
new Service3();
|
|
237
|
-
|
|
238
|
-
const classes = getClassesByKey(uniqueKey);
|
|
239
|
-
expect(classes.size).toBe(3);
|
|
240
|
-
expect(classes.has(Service1)).toBe(true);
|
|
241
|
-
expect(classes.has(Service2)).toBe(true);
|
|
242
|
-
expect(classes.has(Service3)).toBe(true);
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
describe("方法装饰器", () => {
|
|
247
|
-
it("应该能够创建和使用方法装饰器", () => {
|
|
248
|
-
const Handler = createMethodDecorator();
|
|
249
|
-
|
|
250
|
-
class TestService {
|
|
251
|
-
@Handler({ type: "route", options: { method: "GET" } })
|
|
252
|
-
getUser() {}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// 实例化类以确保 addInitializer 执行
|
|
256
|
-
new TestService();
|
|
257
|
-
|
|
258
|
-
const metadata = getMethodMetadata(TestService, "getUser");
|
|
259
|
-
expect(metadata).toHaveLength(1);
|
|
260
|
-
expect(metadata[0].type).toBe("route");
|
|
261
|
-
expect(metadata[0].options.method).toBe("GET");
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("应该支持同一方法应用多个装饰器", () => {
|
|
265
|
-
const Handler = createMethodDecorator();
|
|
266
|
-
|
|
267
|
-
class TestService {
|
|
268
|
-
@Handler({ type: "route", options: { method: "GET" } })
|
|
269
|
-
@Handler({ type: "cache", options: { ttl: 60 } })
|
|
270
|
-
@Handler({ type: "auth", options: { required: true } })
|
|
271
|
-
getUser() {}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// 实例化类以确保 addInitializer 执行
|
|
275
|
-
new TestService();
|
|
276
|
-
|
|
277
|
-
const metadata = getMethodMetadata(TestService, "getUser");
|
|
278
|
-
expect(metadata).toHaveLength(3);
|
|
279
|
-
// 装饰器从下往上执行,所以顺序是反的
|
|
280
|
-
expect(metadata[0].type).toBe("auth");
|
|
281
|
-
expect(metadata[1].type).toBe("cache");
|
|
282
|
-
expect(metadata[2].type).toBe("route");
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it("应该能够获取类的所有方法元数据", () => {
|
|
286
|
-
const Handler = createMethodDecorator();
|
|
287
|
-
|
|
288
|
-
class TestService {
|
|
289
|
-
@Handler({ type: "route" })
|
|
290
|
-
getUser() {}
|
|
291
|
-
|
|
292
|
-
@Handler({ type: "route" })
|
|
293
|
-
createUser() {}
|
|
294
|
-
|
|
295
|
-
// 没有装饰器的方法不应该出现在元数据中
|
|
296
|
-
deleteUser() {}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// 实例化类以确保 addInitializer 执行
|
|
300
|
-
new TestService();
|
|
301
|
-
|
|
302
|
-
const allMetadata = getAllMethodMetadata(TestService);
|
|
303
|
-
expect(allMetadata.size).toBe(2);
|
|
304
|
-
expect(allMetadata.has("getUser")).toBe(true);
|
|
305
|
-
expect(allMetadata.has("createUser")).toBe(true);
|
|
306
|
-
expect(allMetadata.has("deleteUser")).toBe(false);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it("应该能够检查方法是否有元数据", () => {
|
|
310
|
-
const Handler = createMethodDecorator();
|
|
311
|
-
|
|
312
|
-
class TestService {
|
|
313
|
-
@Handler({ type: "route" })
|
|
314
|
-
getUser() {}
|
|
315
|
-
|
|
316
|
-
deleteUser() {}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// 实例化类以确保 addInitializer 执行
|
|
320
|
-
new TestService();
|
|
321
|
-
|
|
322
|
-
expect(hasMethodMetadata(TestService, "getUser")).toBe(true);
|
|
323
|
-
expect(hasMethodMetadata(TestService, "deleteUser")).toBe(false);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it("应该支持自定义元数据键", () => {
|
|
327
|
-
const CUSTOM_KEY = Symbol.for("custom-handler-key");
|
|
328
|
-
const CustomHandler = createMethodDecorator(CUSTOM_KEY);
|
|
329
|
-
|
|
330
|
-
class TestService {
|
|
331
|
-
@CustomHandler({ type: "custom", options: { value: 123 } })
|
|
332
|
-
method() {}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// 实例化类以确保 addInitializer 执行
|
|
336
|
-
new TestService();
|
|
337
|
-
|
|
338
|
-
const metadata = getMethodMetadata(TestService, "method", CUSTOM_KEY);
|
|
339
|
-
expect(metadata[0].type).toBe("custom");
|
|
340
|
-
expect(metadata[0].options.value).toBe(123);
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
describe("实例化后的元数据访问", () => {
|
|
345
|
-
it("应该能够从实例访问类元数据", () => {
|
|
346
|
-
const Module = createClassDecorator();
|
|
347
|
-
|
|
348
|
-
@Module({ name: "test-module" })
|
|
349
|
-
class TestService {}
|
|
350
|
-
|
|
351
|
-
const instance = new TestService();
|
|
352
|
-
const metadata = getClassMetadata(instance);
|
|
353
|
-
expect(metadata.name).toBe("test-module");
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it("应该能够从实例访问方法元数据", () => {
|
|
357
|
-
const Handler = createMethodDecorator();
|
|
358
|
-
|
|
359
|
-
class TestService {
|
|
360
|
-
@Handler({ type: "route" })
|
|
361
|
-
getUser() {}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const instance = new TestService();
|
|
365
|
-
const metadata = getMethodMetadata(instance, "getUser");
|
|
366
|
-
expect(metadata[0].type).toBe("route");
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
});
|