@jellybit.studio/food.mousse.client 0.0.1

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.
@@ -0,0 +1,29 @@
1
+ /**
2
+ * WebSocket 连接管理
3
+ *
4
+ * 封装 socket.io-client,提供断线重连(指数退避 + jitter)
5
+ */
6
+ import { Socket } from 'socket.io-client';
7
+ export declare class Connection {
8
+ private socket;
9
+ private reconnectAttempts;
10
+ private reconnectTimer;
11
+ private readonly logger;
12
+ private connectCallback;
13
+ private disconnectCallback;
14
+ private errorCallback;
15
+ private readonly options;
16
+ /** 设置回调 */
17
+ onConnect(callback: (socket: Socket) => void): this;
18
+ onDisconnect(callback: () => void): this;
19
+ onError(callback: (error: Error) => void): this;
20
+ /** 建立 WebSocket 连接 */
21
+ connect(): void;
22
+ /** 断开连接 */
23
+ disconnect(): void;
24
+ /** 获取当前 socket 实例 */
25
+ getSocket(): Socket | null;
26
+ /** 计划重连(指数退避 + jitter) */
27
+ private scheduleReconnect;
28
+ }
29
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAM,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAK9C,qBACa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IAEtD,OAAO,CAAC,eAAe,CAA2C;IAClE,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,aAAa,CAAyC;IAG9D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAE/C,WAAW;IACJ,SAAS,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAKnD,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAKxC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAKtD,sBAAsB;IACf,OAAO,IAAI,IAAI;IAkCtB,WAAW;IACJ,UAAU,IAAI,IAAI;IAUzB,qBAAqB;IACd,SAAS,IAAI,MAAM,GAAG,IAAI;IAIjC,0BAA0B;IAC1B,OAAO,CAAC,iBAAiB;CA0B1B"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * WebSocket 连接管理
3
+ *
4
+ * 封装 socket.io-client,提供断线重连(指数退避 + jitter)
5
+ */
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ var __metadata = (this && this.__metadata) || function (k, v) {
13
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
14
+ };
15
+ var Connection_1;
16
+ import { io } from 'socket.io-client';
17
+ import { Inject, Injectable, Logger } from '@nestjs/common';
18
+ import { MOUSSE_OPTIONS_TOKEN } from './module.js';
19
+ let Connection = Connection_1 = class Connection {
20
+ socket = null;
21
+ reconnectAttempts = 0;
22
+ reconnectTimer = null;
23
+ logger = new Logger(Connection_1.name);
24
+ connectCallback = null;
25
+ disconnectCallback = null;
26
+ errorCallback = null;
27
+ options;
28
+ /** 设置回调 */
29
+ onConnect(callback) {
30
+ this.connectCallback = callback;
31
+ return this;
32
+ }
33
+ onDisconnect(callback) {
34
+ this.disconnectCallback = callback;
35
+ return this;
36
+ }
37
+ onError(callback) {
38
+ this.errorCallback = callback;
39
+ return this;
40
+ }
41
+ /** 建立 WebSocket 连接 */
42
+ connect() {
43
+ if (this.socket?.connected) {
44
+ return;
45
+ }
46
+ this.logger.log(`Connecting to ${this.options.serverUrl}...`);
47
+ this.socket = io(this.options.serverUrl, {
48
+ auth: { token: this.options.token },
49
+ transports: ['websocket'],
50
+ reconnection: false, // 我们自己管理重连
51
+ });
52
+ this.socket.on('connect', () => {
53
+ this.reconnectAttempts = 0;
54
+ this.logger.log('WebSocket connected');
55
+ this.connectCallback?.(this.socket);
56
+ });
57
+ this.socket.on('disconnect', (reason) => {
58
+ this.logger.warn(`WebSocket disconnected: ${reason}`);
59
+ this.disconnectCallback?.();
60
+ if (reason !== 'io client disconnect') {
61
+ this.scheduleReconnect();
62
+ }
63
+ });
64
+ this.socket.on('connect_error', (error) => {
65
+ this.logger.error(`WebSocket connect error: ${error.message}`);
66
+ this.errorCallback?.(error);
67
+ this.scheduleReconnect();
68
+ });
69
+ }
70
+ /** 断开连接 */
71
+ disconnect() {
72
+ if (this.reconnectTimer) {
73
+ clearTimeout(this.reconnectTimer);
74
+ this.reconnectTimer = null;
75
+ }
76
+ this.socket?.disconnect();
77
+ this.socket = null;
78
+ this.reconnectAttempts = 0;
79
+ }
80
+ /** 获取当前 socket 实例 */
81
+ getSocket() {
82
+ return this.socket;
83
+ }
84
+ /** 计划重连(指数退避 + jitter) */
85
+ scheduleReconnect() {
86
+ const maxAttempts = this.options.maxReconnectAttempts ?? Infinity;
87
+ if (this.reconnectAttempts >= maxAttempts) {
88
+ this.logger.error(`Max reconnect attempts (${maxAttempts}) reached. Giving up.`);
89
+ this.errorCallback?.(new Error(`Max reconnect attempts (${maxAttempts}) reached`));
90
+ return;
91
+ }
92
+ const baseDelay = this.options.reconnectBaseDelay ?? 1000;
93
+ const delay = baseDelay * Math.pow(2, this.reconnectAttempts);
94
+ const jitter = Math.random() * baseDelay;
95
+ const totalDelay = Math.min(delay + jitter, 30000);
96
+ this.reconnectAttempts++;
97
+ this.logger.log(`Reconnecting in ${Math.round(totalDelay)}ms (attempt ${this.reconnectAttempts})...`);
98
+ this.reconnectTimer = setTimeout(() => {
99
+ this.connect();
100
+ }, totalDelay);
101
+ }
102
+ };
103
+ __decorate([
104
+ Inject(MOUSSE_OPTIONS_TOKEN),
105
+ __metadata("design:type", Object)
106
+ ], Connection.prototype, "options", void 0);
107
+ Connection = Connection_1 = __decorate([
108
+ Injectable()
109
+ ], Connection);
110
+ export { Connection };
111
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @TaskHandler 装饰器
3
+ *
4
+ * 只负责在方法上打元数据标签,不做注册。
5
+ * 注册由 MousseExplorer 在 discovery 阶段完成。
6
+ *
7
+ * handler name 生成规则:
8
+ * - 优先使用用户传入的 name 参数
9
+ * - 未传入时,由 Explorer 在 discovery 阶段自动生成 ClassName.methodName
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * @Injectable()
14
+ * class OrderProcessor {
15
+ * @TaskHandler('send-email')
16
+ * async handleEmail(payload: any) { ... }
17
+ *
18
+ * @TaskHandler() // 自动生成 "OrderProcessor.handleSync"
19
+ * async handleSync(payload: any) { ... }
20
+ * }
21
+ * ```
22
+ */
23
+ /** Reflect metadata key — 存储在方法上 */
24
+ export declare const TASK_HANDLER_METADATA: unique symbol;
25
+ /**
26
+ * 方法级装饰器 — 标记一个方法为任务处理器
27
+ *
28
+ * @param name - handler 名称,可选。不传则由 Explorer 自动生成
29
+ */
30
+ export declare function TaskHandler(name?: string): MethodDecorator;
31
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,oCAAoC;AACpC,eAAO,MAAM,qBAAqB,eAAgC,CAAC;AAEnE;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,eAAe,CAmB1D"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @TaskHandler 装饰器
3
+ *
4
+ * 只负责在方法上打元数据标签,不做注册。
5
+ * 注册由 MousseExplorer 在 discovery 阶段完成。
6
+ *
7
+ * handler name 生成规则:
8
+ * - 优先使用用户传入的 name 参数
9
+ * - 未传入时,由 Explorer 在 discovery 阶段自动生成 ClassName.methodName
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * @Injectable()
14
+ * class OrderProcessor {
15
+ * @TaskHandler('send-email')
16
+ * async handleEmail(payload: any) { ... }
17
+ *
18
+ * @TaskHandler() // 自动生成 "OrderProcessor.handleSync"
19
+ * async handleSync(payload: any) { ... }
20
+ * }
21
+ * ```
22
+ */
23
+ /** Reflect metadata key — 存储在方法上 */
24
+ export const TASK_HANDLER_METADATA = Symbol('mousse:task-handler');
25
+ /**
26
+ * 方法级装饰器 — 标记一个方法为任务处理器
27
+ *
28
+ * @param name - handler 名称,可选。不传则由 Explorer 自动生成
29
+ */
30
+ export function TaskHandler(name) {
31
+ return (_target, propertyKey, descriptor) => {
32
+ if (typeof descriptor.value !== 'function') {
33
+ throw new Error(`@TaskHandler can only be applied to methods. Got: ${String(propertyKey)}`);
34
+ }
35
+ const metadata = {
36
+ // name 为 undefined 时,Explorer 会用 ClassName.methodName 补全
37
+ name: name ?? '',
38
+ };
39
+ Reflect.defineMetadata(TASK_HANDLER_METADATA, metadata, descriptor.value);
40
+ };
41
+ }
42
+ //# sourceMappingURL=decorators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,oCAAoC;AACpC,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAEnE;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,OAAO,CACL,OAAe,EACf,WAA4B,EAC5B,UAA8B,EAC9B,EAAE;QACF,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CACb,qDAAqD,MAAM,CAAC,WAAW,CAAC,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAwB;YACpC,yDAAyD;YACzD,IAAI,EAAE,IAAI,IAAI,EAAE;SACjB,CAAC;QAEF,OAAO,CAAC,cAAc,CAAC,qBAAqB,EAAE,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5E,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * MousseExplorer — 自动发现 @TaskHandler 标记的方法
3
+ *
4
+ * 使用 DiscoveryService 扫描所有 Provider,
5
+ * 找到打了 TASK_HANDLER_METADATA 元数据的方法,注册到 TaskRegistry。
6
+ */
7
+ import { OnModuleInit } from '@nestjs/common';
8
+ export declare class MousseExplorer implements OnModuleInit {
9
+ private readonly logger;
10
+ private readonly discovery;
11
+ private readonly registry;
12
+ onModuleInit(): void;
13
+ private explore;
14
+ }
15
+ //# sourceMappingURL=explorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA8B,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM1E,qBACa,cAAe,YAAW,YAAY;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAG1D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAG9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IAElC,YAAY,IAAI,IAAI;IAW3B,OAAO,CAAC,OAAO;CAmDhB"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * MousseExplorer — 自动发现 @TaskHandler 标记的方法
3
+ *
4
+ * 使用 DiscoveryService 扫描所有 Provider,
5
+ * 找到打了 TASK_HANDLER_METADATA 元数据的方法,注册到 TaskRegistry。
6
+ */
7
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
8
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
9
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
10
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
11
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
12
+ };
13
+ var __metadata = (this && this.__metadata) || function (k, v) {
14
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
15
+ };
16
+ var MousseExplorer_1;
17
+ import { Inject, Injectable, Logger } from '@nestjs/common';
18
+ import { DiscoveryService } from '@nestjs/core';
19
+ import { TaskRegistry } from './task-registry.js';
20
+ import { TASK_HANDLER_METADATA } from './decorators.js';
21
+ let MousseExplorer = MousseExplorer_1 = class MousseExplorer {
22
+ logger = new Logger(MousseExplorer_1.name);
23
+ discovery;
24
+ registry;
25
+ onModuleInit() {
26
+ const handlers = this.explore();
27
+ this.logger.log(`Discovered ${handlers.length} task handler(s): ${handlers.map((h) => h.name).join(', ')}`);
28
+ for (const handler of handlers) {
29
+ this.registry.register(handler);
30
+ }
31
+ }
32
+ explore() {
33
+ const providers = this.discovery.getProviders();
34
+ const handlers = [];
35
+ for (const wrapper of providers) {
36
+ const { instance, metatype } = wrapper;
37
+ if (!instance || !metatype) {
38
+ continue;
39
+ }
40
+ const prototype = Object.getPrototypeOf(instance);
41
+ if (!prototype) {
42
+ continue;
43
+ }
44
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => {
45
+ if (name === 'constructor')
46
+ return false;
47
+ try {
48
+ return typeof prototype[name] === 'function';
49
+ }
50
+ catch {
51
+ return false; // 跳过 getter 等访问会抛异常的属性
52
+ }
53
+ });
54
+ for (const methodName of methods) {
55
+ const handler = instance[methodName];
56
+ if (typeof handler !== 'function') {
57
+ continue;
58
+ }
59
+ const metadata = Reflect.getMetadata(TASK_HANDLER_METADATA, handler);
60
+ if (!metadata) {
61
+ continue;
62
+ }
63
+ handlers.push({
64
+ name: metadata.name || `${metatype.name}.${methodName}`,
65
+ handler: handler.bind(instance),
66
+ className: metatype.name,
67
+ methodName,
68
+ });
69
+ }
70
+ }
71
+ return handlers;
72
+ }
73
+ };
74
+ __decorate([
75
+ Inject(),
76
+ __metadata("design:type", DiscoveryService)
77
+ ], MousseExplorer.prototype, "discovery", void 0);
78
+ __decorate([
79
+ Inject(),
80
+ __metadata("design:type", TaskRegistry)
81
+ ], MousseExplorer.prototype, "registry", void 0);
82
+ MousseExplorer = MousseExplorer_1 = __decorate([
83
+ Injectable()
84
+ ], MousseExplorer);
85
+ export { MousseExplorer };
86
+ //# sourceMappingURL=explorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAgB,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAIjD,IAAM,cAAc,sBAApB,MAAM,cAAc;IACR,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAc,CAAC,IAAI,CAAC,CAAC;IAGzC,SAAS,CAAoB;IAG7B,QAAQ,CAAgB;IAElC,YAAY;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,GAAG,CACb,cAAc,QAAQ,CAAC,MAAM,qBAAqB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3F,CAAC;QAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAEO,OAAO;QACb,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAChD,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAE7C,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;YAChC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;YAEvC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YAClD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;gBACpE,IAAI,IAAI,KAAK,aAAa;oBAAE,OAAO,KAAK,CAAC;gBACzC,IAAI,CAAC;oBACH,OAAO,OAAQ,SAAqC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC;gBAC5E,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAC,CAAC,uBAAuB;gBACvC,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAI,QAAoC,CAAC,UAAU,CAAC,CAAC;gBAClE,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;oBAClC,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAoC,OAAO,CAAC,WAAW,CACnE,qBAAqB,EACrB,OAAO,CACR,CAAC;gBAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,SAAS;gBACX,CAAC;gBAED,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,UAAU,EAAE;oBACvD,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAC/B,SAAS,EAAE,QAAQ,CAAC,IAAI;oBACxB,UAAU;iBACX,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAA;AAnEkB;IADhB,MAAM,EAAE;8BACoB,gBAAgB;iDAAC;AAG7B;IADhB,MAAM,EAAE;8BACmB,YAAY;gDAAC;AAP9B,cAAc;IAD1B,UAAU,EAAE;GACA,cAAc,CAuE1B"}
@@ -0,0 +1,7 @@
1
+ export { MousseModule } from './module.js';
2
+ export { TaskHandler, TASK_HANDLER_METADATA } from './decorators.js';
3
+ export { MousseRunnerService } from './runner-service.js';
4
+ export { TaskRegistry } from './task-registry.js';
5
+ export { MousseExplorer } from './explorer.js';
6
+ export type { MousseModuleOptions, TaskHandlerMetadata, TaskHandlerDescriptor } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // Mousse Client — NestJS Module
2
+ export { MousseModule } from './module.js';
3
+ export { TaskHandler, TASK_HANDLER_METADATA } from './decorators.js';
4
+ export { MousseRunnerService } from './runner-service.js';
5
+ export { TaskRegistry } from './task-registry.js';
6
+ export { MousseExplorer } from './explorer.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MousseModule — NestJS 动态模块
3
+ *
4
+ * 使用方式:
5
+ * ```typescript
6
+ * @Module({
7
+ * imports: [
8
+ * MousseModule.forRoot({
9
+ * serverUrl: 'ws://localhost:3000/runners',
10
+ * token: 'my-secret-token',
11
+ * name: 'order-runner',
12
+ * }),
13
+ * ],
14
+ * providers: [OrderProcessor], // 包含 @TaskHandler 的 Provider
15
+ * })
16
+ * class AppModule {}
17
+ * ```
18
+ *
19
+ * 流程:
20
+ * 1. forRoot() 注册配置 → Connection + TaskRegistry
21
+ * 2. MousseExplorer (OnModuleInit) 扫描所有 Provider,发现 @TaskHandler → 注册到 TaskRegistry
22
+ * 3. MousseRunnerService (OnModuleInit) 读取 TaskRegistry,自动连接服务端
23
+ *
24
+ * 注意:Explorer 的 onModuleInit 先于 RunnerService 执行,
25
+ * 因为 Explorer 在 providers 列表中排在 RunnerService 前面。
26
+ */
27
+ import { DynamicModule } from '@nestjs/common';
28
+ import type { MousseModuleOptions } from './types.js';
29
+ export declare const MOUSSE_OPTIONS_TOKEN: unique symbol;
30
+ export declare class MousseModule {
31
+ /**
32
+ * 注册 Mousse Client 模块
33
+ *
34
+ * @param options - 连接配置
35
+ */
36
+ static forRoot(options: MousseModuleOptions): DynamicModule;
37
+ }
38
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,aAAa,EAAU,MAAM,gBAAgB,CAAC;AAMvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,eAAO,MAAM,oBAAoB,eAAkC,CAAC;AAEpE,qBAGa,YAAY;IACvB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa;CAoB5D"}
package/dist/module.js ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * MousseModule — NestJS 动态模块
3
+ *
4
+ * 使用方式:
5
+ * ```typescript
6
+ * @Module({
7
+ * imports: [
8
+ * MousseModule.forRoot({
9
+ * serverUrl: 'ws://localhost:3000/runners',
10
+ * token: 'my-secret-token',
11
+ * name: 'order-runner',
12
+ * }),
13
+ * ],
14
+ * providers: [OrderProcessor], // 包含 @TaskHandler 的 Provider
15
+ * })
16
+ * class AppModule {}
17
+ * ```
18
+ *
19
+ * 流程:
20
+ * 1. forRoot() 注册配置 → Connection + TaskRegistry
21
+ * 2. MousseExplorer (OnModuleInit) 扫描所有 Provider,发现 @TaskHandler → 注册到 TaskRegistry
22
+ * 3. MousseRunnerService (OnModuleInit) 读取 TaskRegistry,自动连接服务端
23
+ *
24
+ * 注意:Explorer 的 onModuleInit 先于 RunnerService 执行,
25
+ * 因为 Explorer 在 providers 列表中排在 RunnerService 前面。
26
+ */
27
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
28
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
29
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
30
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
31
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
32
+ };
33
+ var MousseModule_1;
34
+ import { Module } from '@nestjs/common';
35
+ import { DiscoveryModule } from '@nestjs/core';
36
+ import { MousseExplorer } from './explorer.js';
37
+ import { MousseRunnerService } from './runner-service.js';
38
+ import { TaskRegistry } from './task-registry.js';
39
+ import { Connection } from './connection.js';
40
+ export const MOUSSE_OPTIONS_TOKEN = Symbol('mousse:module-options');
41
+ let MousseModule = MousseModule_1 = class MousseModule {
42
+ /**
43
+ * 注册 Mousse Client 模块
44
+ *
45
+ * @param options - 连接配置
46
+ */
47
+ static forRoot(options) {
48
+ const optionsProvider = {
49
+ provide: MOUSSE_OPTIONS_TOKEN,
50
+ useValue: options,
51
+ };
52
+ return {
53
+ module: MousseModule_1,
54
+ imports: [DiscoveryModule],
55
+ providers: [
56
+ optionsProvider,
57
+ TaskRegistry,
58
+ // Explorer 必须在 RunnerService 之前初始化
59
+ MousseExplorer,
60
+ Connection,
61
+ MousseRunnerService,
62
+ ],
63
+ exports: [TaskRegistry, MousseRunnerService],
64
+ };
65
+ }
66
+ };
67
+ MousseModule = MousseModule_1 = __decorate([
68
+ Module({
69
+ imports: [DiscoveryModule],
70
+ })
71
+ ], MousseModule);
72
+ export { MousseModule };
73
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;;;;;;AAEH,OAAO,EAAiB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;AAK7D,IAAM,YAAY,oBAAlB,MAAM,YAAY;IACvB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,OAA4B;QACzC,MAAM,eAAe,GAAG;YACtB,OAAO,EAAE,oBAAoB;YAC7B,QAAQ,EAAE,OAAO;SAClB,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,cAAY;YACpB,OAAO,EAAE,CAAC,eAAe,CAAC;YAC1B,SAAS,EAAE;gBACT,eAAe;gBACf,YAAY;gBACZ,mCAAmC;gBACnC,cAAc;gBACd,UAAU;gBACV,mBAAmB;aACpB;YACD,OAAO,EAAE,CAAC,YAAY,EAAE,mBAAmB,CAAC;SAC7C,CAAC;IACJ,CAAC;CACF,CAAA;AA1BY,YAAY;IAHxB,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,eAAe,CAAC;KAC3B,CAAC;GACW,YAAY,CA0BxB"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * MousseRunnerService — 运行器核心服务
3
+ *
4
+ * 在 Explorer 完成发现后自动连接服务端,
5
+ * 管理心跳、任务分发、执行结果回报。
6
+ *
7
+ * 实现 OnModuleInit:发现完成后自动连接
8
+ * 实现 OnModuleDestroy:优雅断开
9
+ */
10
+ import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
11
+ export declare class MousseRunnerService implements OnModuleInit, OnModuleDestroy {
12
+ private readonly logger;
13
+ private readonly activeExecutions;
14
+ private heartbeatTimer;
15
+ private readonly options;
16
+ private readonly registry;
17
+ private readonly connection;
18
+ onModuleInit(): void;
19
+ onModuleDestroy(): Promise<void>;
20
+ private handleConnected;
21
+ private handleDisconnected;
22
+ private handleError;
23
+ private handleTaskDispatch;
24
+ private handleTaskCancel;
25
+ /** 向服务端回报执行结果 */
26
+ private reportResult;
27
+ /** 启动心跳定时器 */
28
+ private startHeartbeat;
29
+ }
30
+ //# sourceMappingURL=runner-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-service.d.ts","sourceRoot":"","sources":["../src/runner-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA8B,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAS3F,qBACa,mBAAoB,YAAW,YAAY,EAAE,eAAe;IACvE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoD;IACrF,OAAO,CAAC,cAAc,CAA+C;IAGrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAG/C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IAGzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAc;IAIlC,YAAY,IAAI,IAAI;IAkBd,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB7C,OAAO,CAAC,eAAe;IAiCvB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,kBAAkB;IA6D1B,OAAO,CAAC,gBAAgB;IASxB,iBAAiB;IACjB,OAAO,CAAC,YAAY;IAiBpB,cAAc;IACd,OAAO,CAAC,cAAc;CAYvB"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * MousseRunnerService — 运行器核心服务
3
+ *
4
+ * 在 Explorer 完成发现后自动连接服务端,
5
+ * 管理心跳、任务分发、执行结果回报。
6
+ *
7
+ * 实现 OnModuleInit:发现完成后自动连接
8
+ * 实现 OnModuleDestroy:优雅断开
9
+ */
10
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
11
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
12
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
13
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
14
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
15
+ };
16
+ var __metadata = (this && this.__metadata) || function (k, v) {
17
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
18
+ };
19
+ var MousseRunnerService_1;
20
+ import { Inject, Injectable, Logger } from '@nestjs/common';
21
+ import { Connection } from './connection.js';
22
+ import { TaskRegistry } from './task-registry.js';
23
+ import { MOUSSE_OPTIONS_TOKEN } from './module.js';
24
+ import { SOCKET_EVENTS } from '@jellybit.studio/food.mousse.shared/constants';
25
+ let MousseRunnerService = MousseRunnerService_1 = class MousseRunnerService {
26
+ logger = new Logger(MousseRunnerService_1.name);
27
+ activeExecutions = new Map();
28
+ heartbeatTimer = null;
29
+ options;
30
+ registry;
31
+ connection;
32
+ // ─── 生命周期(自动触发) ───
33
+ onModuleInit() {
34
+ // 通过 DI 注入的 Connection 设置回调
35
+ this.connection
36
+ .onConnect(this.handleConnected.bind(this))
37
+ .onDisconnect(this.handleDisconnected.bind(this))
38
+ .onError(this.handleError.bind(this));
39
+ const handlerCount = this.registry.size;
40
+ if (handlerCount === 0) {
41
+ this.logger.warn('No task handlers registered. Is @TaskHandler applied correctly?');
42
+ }
43
+ this.logger.log(`Starting runner "${this.options.name}" with ${handlerCount} handler(s)`);
44
+ this.connection.connect();
45
+ }
46
+ async onModuleDestroy() {
47
+ this.logger.log('Shutting down runner...');
48
+ // 等待当前执行中的任务完成(最多 10 秒)
49
+ const maxWait = 10000;
50
+ const start = Date.now();
51
+ while (this.activeExecutions.size > 0 && Date.now() - start < maxWait) {
52
+ await new Promise((resolve) => setTimeout(resolve, 500));
53
+ }
54
+ if (this.activeExecutions.size > 0) {
55
+ this.logger.warn(`${this.activeExecutions.size} task(s) still running after 10s, forcing shutdown`);
56
+ }
57
+ if (this.heartbeatTimer) {
58
+ clearInterval(this.heartbeatTimer);
59
+ }
60
+ this.connection.disconnect();
61
+ }
62
+ // ─── 内部处理 ───
63
+ handleConnected(socket) {
64
+ // 向服务端注册运行器,携带所有 handler 名称
65
+ socket.emit(SOCKET_EVENTS.RUNNER_REGISTER, {
66
+ runnerId: '',
67
+ registrationToken: this.options.token,
68
+ name: this.options.name,
69
+ groupId: this.options.groupId,
70
+ handlers: this.registry.getHandlerNames(),
71
+ });
72
+ // 监听任务分发
73
+ socket.on(SOCKET_EVENTS.TASK_DISPATCH, (payload) => {
74
+ this.handleTaskDispatch(payload);
75
+ });
76
+ // 监听任务取消
77
+ socket.on(SOCKET_EVENTS.TASK_CANCEL, (payload) => {
78
+ this.handleTaskCancel(payload.executionId);
79
+ });
80
+ // 监听心跳 ping
81
+ socket.on(SOCKET_EVENTS.HEARTBEAT_PING, () => {
82
+ socket.emit(SOCKET_EVENTS.HEARTBEAT_PONG);
83
+ });
84
+ // 启动心跳定时器
85
+ this.startHeartbeat(socket);
86
+ this.logger.log(`Runner "${this.options.name}" registered with ${this.registry.size} handler(s)`);
87
+ }
88
+ handleDisconnected() {
89
+ this.logger.warn('Disconnected from server');
90
+ }
91
+ handleError(error) {
92
+ this.logger.error(`Connection error: ${error.message}`);
93
+ }
94
+ handleTaskDispatch(payload) {
95
+ const { executionId, handlerName, payload: taskPayload, timeout } = payload;
96
+ const descriptor = this.registry.get(handlerName);
97
+ if (!descriptor) {
98
+ this.reportResult(executionId, 'failed', undefined, `No handler registered for "${handlerName}"`);
99
+ this.logger.error(`No handler for "${handlerName}"`);
100
+ return;
101
+ }
102
+ this.logger.log(`Dispatching task "${handlerName}" (${executionId}) → ${descriptor.className}.${descriptor.methodName}`);
103
+ // 超时检测
104
+ const timeoutId = setTimeout(() => {
105
+ this.activeExecutions.delete(executionId);
106
+ this.reportResult(executionId, 'timeout', undefined, `Task "${handlerName}" timed out after ${timeout}ms`);
107
+ this.logger.warn(`Task "${handlerName}" (${executionId}) timed out`);
108
+ }, timeout);
109
+ this.activeExecutions.set(executionId, timeoutId);
110
+ // 异步执行处理器
111
+ descriptor
112
+ .handler(taskPayload)
113
+ .then((result) => {
114
+ if (this.activeExecutions.has(executionId)) {
115
+ clearTimeout(this.activeExecutions.get(executionId));
116
+ this.activeExecutions.delete(executionId);
117
+ this.reportResult(executionId, 'success', result);
118
+ this.logger.log(`Task "${handlerName}" (${executionId}) completed`);
119
+ }
120
+ })
121
+ .catch((error) => {
122
+ if (this.activeExecutions.has(executionId)) {
123
+ clearTimeout(this.activeExecutions.get(executionId));
124
+ this.activeExecutions.delete(executionId);
125
+ this.reportResult(executionId, 'failed', undefined, error?.message ?? String(error));
126
+ this.logger.error(`Task "${handlerName}" (${executionId}) failed: ${error?.message ?? error}`);
127
+ }
128
+ });
129
+ }
130
+ handleTaskCancel(executionId) {
131
+ const timeoutId = this.activeExecutions.get(executionId);
132
+ if (timeoutId) {
133
+ clearTimeout(timeoutId);
134
+ this.activeExecutions.delete(executionId);
135
+ this.logger.log(`Task execution ${executionId} cancelled`);
136
+ }
137
+ }
138
+ /** 向服务端回报执行结果 */
139
+ reportResult(executionId, status, result, error) {
140
+ const socket = this.connection.getSocket();
141
+ if (socket?.connected) {
142
+ socket.emit(SOCKET_EVENTS.TASK_RESULT, {
143
+ executionId,
144
+ status,
145
+ result,
146
+ error,
147
+ });
148
+ }
149
+ }
150
+ /** 启动心跳定时器 */
151
+ startHeartbeat(socket) {
152
+ if (this.heartbeatTimer) {
153
+ clearInterval(this.heartbeatTimer);
154
+ }
155
+ const interval = this.options.heartbeatInterval ?? 30000;
156
+ this.heartbeatTimer = setInterval(() => {
157
+ if (socket.connected) {
158
+ socket.emit(SOCKET_EVENTS.HEARTBEAT_PONG);
159
+ }
160
+ }, interval);
161
+ }
162
+ };
163
+ __decorate([
164
+ Inject(MOUSSE_OPTIONS_TOKEN),
165
+ __metadata("design:type", Object)
166
+ ], MousseRunnerService.prototype, "options", void 0);
167
+ __decorate([
168
+ Inject(),
169
+ __metadata("design:type", TaskRegistry)
170
+ ], MousseRunnerService.prototype, "registry", void 0);
171
+ __decorate([
172
+ Inject(),
173
+ __metadata("design:type", Connection)
174
+ ], MousseRunnerService.prototype, "connection", void 0);
175
+ MousseRunnerService = MousseRunnerService_1 = __decorate([
176
+ Injectable()
177
+ ], MousseRunnerService);
178
+ export { MousseRunnerService };
179
+ //# sourceMappingURL=runner-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-service.js","sourceRoot":"","sources":["../src/runner-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 任务处理器注册表
3
+ *
4
+ * 由 MousseExplorer 在 discovery 后填充,由 MousseRunnerService 读取。
5
+ * 不再是全局单例,而是通过 NestJS DI 注入。
6
+ */
7
+ import type { TaskHandlerDescriptor } from './types.js';
8
+ export declare class TaskRegistry {
9
+ private readonly handlers;
10
+ /** 注册一个处理器(由 Explorer 调用) */
11
+ register(descriptor: TaskHandlerDescriptor): void;
12
+ /** 获取处理器 */
13
+ get(name: string): TaskHandlerDescriptor | undefined;
14
+ /** 获取所有已注册的 handler 名称 */
15
+ getHandlerNames(): string[];
16
+ /** 获取所有已注册的 handler 描述符 */
17
+ getAll(): TaskHandlerDescriptor[];
18
+ /** 检查 handler 是否已注册 */
19
+ has(name: string): boolean;
20
+ /** 注册的 handler 总数 */
21
+ get size(): number;
22
+ }
23
+ //# sourceMappingURL=task-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-registry.d.ts","sourceRoot":"","sources":["../src/task-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGxD,qBACa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IAErE,6BAA6B;IACtB,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI;IASxD,YAAY;IACL,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAI3D,0BAA0B;IACnB,eAAe,IAAI,MAAM,EAAE;IAIlC,2BAA2B;IACpB,MAAM,IAAI,qBAAqB,EAAE;IAIxC,uBAAuB;IAChB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,qBAAqB;IACrB,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 任务处理器注册表
3
+ *
4
+ * 由 MousseExplorer 在 discovery 后填充,由 MousseRunnerService 读取。
5
+ * 不再是全局单例,而是通过 NestJS DI 注入。
6
+ */
7
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
8
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
9
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
10
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
11
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
12
+ };
13
+ import { Injectable } from '@nestjs/common';
14
+ let TaskRegistry = class TaskRegistry {
15
+ handlers = new Map();
16
+ /** 注册一个处理器(由 Explorer 调用) */
17
+ register(descriptor) {
18
+ if (this.handlers.has(descriptor.name)) {
19
+ console.warn(`[Mousse] Handler "${descriptor.name}" already registered, overwriting`);
20
+ }
21
+ this.handlers.set(descriptor.name, descriptor);
22
+ }
23
+ /** 获取处理器 */
24
+ get(name) {
25
+ return this.handlers.get(name);
26
+ }
27
+ /** 获取所有已注册的 handler 名称 */
28
+ getHandlerNames() {
29
+ return [...this.handlers.keys()];
30
+ }
31
+ /** 获取所有已注册的 handler 描述符 */
32
+ getAll() {
33
+ return [...this.handlers.values()];
34
+ }
35
+ /** 检查 handler 是否已注册 */
36
+ has(name) {
37
+ return this.handlers.has(name);
38
+ }
39
+ /** 注册的 handler 总数 */
40
+ get size() {
41
+ return this.handlers.size;
42
+ }
43
+ };
44
+ TaskRegistry = __decorate([
45
+ Injectable()
46
+ ], TaskRegistry);
47
+ export { TaskRegistry };
48
+ //# sourceMappingURL=task-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-registry.js","sourceRoot":"","sources":["../src/task-registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGrC,IAAM,YAAY,GAAlB,MAAM,YAAY;IACN,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAC;IAErE,6BAA6B;IACtB,QAAQ,CAAC,UAAiC;QAC/C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CACV,qBAAqB,UAAU,CAAC,IAAI,mCAAmC,CACxE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC;IAED,YAAY;IACL,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,0BAA0B;IACnB,eAAe;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,2BAA2B;IACpB,MAAM;QACX,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,uBAAuB;IAChB,GAAG,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;CACF,CAAA;AArCY,YAAY;IADxB,UAAU,EAAE;GACA,YAAY,CAqCxB"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Mousse Client 类型定义
3
+ */
4
+ /** MousseModule.forRoot() 配置 */
5
+ export interface MousseModuleOptions {
6
+ /** 服务端 WebSocket 地址,例如 ws://localhost:3000/runners */
7
+ serverUrl: string;
8
+ /** 运行器注册令牌(registrationToken),与服务端配置的 runnerRegistration.token 对应 */
9
+ token: string;
10
+ /** 运行器名称,在服务端唯一标识此运行器 */
11
+ name: string;
12
+ /** 运行器分组 ID(可选,用于任务定向分发) */
13
+ groupId?: string;
14
+ /** 心跳间隔(毫秒),默认 30000 */
15
+ heartbeatInterval?: number;
16
+ /** 最大重连次数,默认 Infinity */
17
+ maxReconnectAttempts?: number;
18
+ /** 初始重连延迟(毫秒),默认 1000 */
19
+ reconnectBaseDelay?: number;
20
+ }
21
+ /** @TaskHandler 装饰器存储的元数据 */
22
+ export interface TaskHandlerMetadata {
23
+ /** handler 名称:用户指定或自动生成 */
24
+ name: string;
25
+ }
26
+ /** 内部使用的 handler 描述符(discovery 后产出) */
27
+ export interface TaskHandlerDescriptor {
28
+ name: string;
29
+ handler: (payload: unknown) => Promise<unknown>;
30
+ /** 来源 Provider 的类名,用于日志 */
31
+ className: string;
32
+ /** 方法名,用于日志 */
33
+ methodName: string;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,gCAAgC;AAChC,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,yBAAyB;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,6BAA6B;AAC7B,MAAM,WAAW,mBAAmB;IAClC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uCAAuC;AACvC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Mousse Client 类型定义
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@jellybit.studio/food.mousse.client",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/jellybit-studio/food.mousse.git"
22
+ },
23
+ "author": "纸伞下的烟雨",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "reflect-metadata": "^0.2.2",
27
+ "socket.io-client": "^4.8.1",
28
+ "@jellybit.studio/food.mousse.shared": "0.0.1"
29
+ },
30
+ "peerDependencies": {
31
+ "@nestjs/common": "^11.0.0",
32
+ "@nestjs/core": "^11.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@nestjs/common": "^11.0.0",
36
+ "@nestjs/core": "^11.0.0",
37
+ "@types/node": "^20.9.0",
38
+ "typescript": "^5.6.3"
39
+ },
40
+ "scripts": {
41
+ "build": "tsc",
42
+ "dev": "tsc --watch"
43
+ }
44
+ }