alemonjs 2.1.82 → 2.1.83-alpha.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.
Files changed (42) hide show
  1. package/lib/app/event-error.d.ts +2 -0
  2. package/lib/app/event-error.js +20 -0
  3. package/lib/app/event-processor-callHandler.d.ts +5 -1
  4. package/lib/app/event-processor-callHandler.js +18 -2
  5. package/lib/app/event-processor-cycleFiles.d.ts +4 -1
  6. package/lib/app/event-processor-cycleFiles.js +21 -6
  7. package/lib/app/event-processor-cycleRoute.d.ts +4 -1
  8. package/lib/app/event-processor-cycleRoute.js +16 -2
  9. package/lib/app/event-processor-event.js +2 -2
  10. package/lib/app/event-processor-middleware.js +2 -2
  11. package/lib/app/event-processor-subscribe.js +31 -3
  12. package/lib/app/event-processor.js +6 -1
  13. package/lib/app/hook-event-context.d.ts +7 -3
  14. package/lib/app/hook-event-context.js +24 -5
  15. package/lib/app/hook-use/subscribe.js +3 -1
  16. package/lib/app/index.js +2 -2
  17. package/lib/app/lifecycle-callbacks.d.ts +14 -0
  18. package/lib/app/lifecycle-callbacks.js +99 -0
  19. package/lib/app/load_modules/loadChild.js +13 -10
  20. package/lib/app/router/dsl.js +2 -2
  21. package/lib/app/store.d.ts +2 -0
  22. package/lib/app/store.js +31 -5
  23. package/lib/cbp/connects/client.js +34 -32
  24. package/lib/cbp/connects/platform.js +45 -68
  25. package/lib/cbp/normalize.d.ts +16 -0
  26. package/lib/cbp/normalize.js +328 -0
  27. package/lib/cbp/processor/actions.js +15 -13
  28. package/lib/cbp/processor/api.js +15 -13
  29. package/lib/cbp/processor/config.d.ts +8 -4
  30. package/lib/cbp/processor/config.js +9 -5
  31. package/lib/cbp/server/main.js +28 -30
  32. package/lib/cbp/typings.d.ts +139 -0
  33. package/lib/client.js +11 -7
  34. package/lib/core/config.d.ts +3 -3
  35. package/lib/index.js +2 -2
  36. package/lib/server/routers/router.js +111 -17
  37. package/lib/types/actions.d.ts +20 -1
  38. package/lib/types/apis.d.ts +2 -1
  39. package/lib/types/cycle/index.d.ts +50 -0
  40. package/lib/types/event/index.d.ts +1 -0
  41. package/lib/types/subscribe/index.d.ts +1 -0
  42. package/package.json +1 -1
package/lib/app/store.js CHANGED
@@ -2,6 +2,7 @@ import { SinglyLinkedList } from './SinglyLinkedList.js';
2
2
  import { mkdirSync } from 'node:fs';
3
3
  import log4js from 'log4js';
4
4
  import { disposeExpose } from './expose.js';
5
+ import { dispatchRuntimeStatusChange } from './lifecycle-callbacks.js';
5
6
 
6
7
  const createLogger = () => {
7
8
  if (process.env.BROWSER_ENV === 'browser') {
@@ -212,6 +213,7 @@ const updateRuntimeAppStatus = (name, status, error) => {
212
213
  return;
213
214
  }
214
215
  const normalizedError = normalizeRuntimeAppError(error);
216
+ const previousStatus = current.status;
215
217
  if (current.status === status && sameRuntimeAppError(current.error, normalizedError)) {
216
218
  return current;
217
219
  }
@@ -220,6 +222,17 @@ const updateRuntimeAppStatus = (name, status, error) => {
220
222
  current.error = normalizedError;
221
223
  const level = status === 'failed' ? 'warn' : status === 'disposed' ? 'info' : 'debug';
222
224
  logRuntimeAppStatus(level, current);
225
+ void dispatchRuntimeStatusChange({
226
+ appName: name,
227
+ previousStatus,
228
+ status,
229
+ error: normalizedError
230
+ ? {
231
+ message: normalizedError.message,
232
+ time: normalizedError.time
233
+ }
234
+ : undefined
235
+ });
223
236
  return current;
224
237
  };
225
238
  const updateRuntimeAppCapabilities = (name, capabilities) => {
@@ -408,6 +421,13 @@ function mergeFileTree(target, source) {
408
421
  }
409
422
  }
410
423
  }
424
+ const attachRouteAppName = (appName, routes = []) => {
425
+ return routes.map(route => ({
426
+ ...route,
427
+ appName,
428
+ children: route.children ? attachRouteAppName(appName, route.children) : route.children
429
+ }));
430
+ };
411
431
  class MiddlewareTree {
412
432
  #cache = null;
413
433
  #cacheVersion = -1;
@@ -456,10 +476,10 @@ class ResponseRouter {
456
476
  return [];
457
477
  }
458
478
  if (alemonjsCore.storeChildrenApp[key].register?.responseRouter) {
459
- return alemonjsCore.storeChildrenApp[key].register?.responseRouter?.current ?? [];
479
+ return attachRouteAppName(key, alemonjsCore.storeChildrenApp[key].register?.responseRouter?.current ?? []);
460
480
  }
461
481
  if (alemonjsCore.storeChildrenApp[key].register?.response) {
462
- return alemonjsCore.storeChildrenApp[key].register?.response?.current ?? [];
482
+ return attachRouteAppName(key, alemonjsCore.storeChildrenApp[key].register?.response?.current ?? []);
463
483
  }
464
484
  return [];
465
485
  });
@@ -480,10 +500,10 @@ class MiddlewareRouter {
480
500
  return [];
481
501
  }
482
502
  if (alemonjsCore.storeChildrenApp[key].register?.middlewareRouter) {
483
- return alemonjsCore.storeChildrenApp[key].register?.middlewareRouter?.current ?? [];
503
+ return attachRouteAppName(key, alemonjsCore.storeChildrenApp[key].register?.middlewareRouter?.current ?? []);
484
504
  }
485
505
  if (alemonjsCore.storeChildrenApp[key].register?.middleware) {
486
- return alemonjsCore.storeChildrenApp[key].register?.middleware?.current ?? [];
506
+ return attachRouteAppName(key, alemonjsCore.storeChildrenApp[key].register?.middleware?.current ?? []);
487
507
  }
488
508
  return [];
489
509
  });
@@ -632,6 +652,12 @@ class ChildrenApp {
632
652
  return alemonjsCore.storeChildrenApp[this.#name];
633
653
  }
634
654
  }
655
+ const getChildrenApp = (name) => {
656
+ return alemonjsCore.storeChildrenApp[name] ?? null;
657
+ };
658
+ const listChildrenApps = () => {
659
+ return Object.values(alemonjsCore.storeChildrenApp);
660
+ };
635
661
  const ProcessorEventAutoClearMap = new Map();
636
662
  const ProcessorEventUserAutoClearMap = new Map();
637
663
  const logger = new Logger().value;
@@ -645,4 +671,4 @@ process?.on?.('exit', code => {
645
671
  logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
646
672
  });
647
673
 
648
- export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, clearRuntimeAppKoaRouters, core, disposeAllRuntimeApps, disposeRuntimeApp, getRuntimeApp, getRuntimeAppKoaRouters, getSubscribeList, hasRuntimeAppCapability, listRuntimeAppKoaRouters, listRuntimeApps, logger, registerRuntimeApp, setRuntimeAppKoaRouters, toRuntimeAppSnapshot, updateRuntimeAppCapabilities, updateRuntimeAppStatus };
674
+ export { ChildrenApp, Core, Logger, Middleware, MiddlewareRouter, MiddlewareTree, ProcessorEventAutoClearMap, ProcessorEventUserAutoClearMap, Response, ResponseMiddleware, ResponseRouter, ResponseTree, State, StateSubscribe, SubscribeList, bumpStoreVersion, clearRuntimeAppKoaRouters, core, disposeAllRuntimeApps, disposeRuntimeApp, getChildrenApp, getRuntimeApp, getRuntimeAppKoaRouters, getSubscribeList, hasRuntimeAppCapability, listChildrenApps, listRuntimeAppKoaRouters, listRuntimeApps, logger, registerRuntimeApp, setRuntimeAppKoaRouters, toRuntimeAppSnapshot, updateRuntimeAppCapabilities, updateRuntimeAppStatus };
@@ -14,8 +14,9 @@ import { onProcessor } from '../../app/event-processor.js';
14
14
  import '../../app/event-response.js';
15
15
  import { createResult } from '../../core/utils.js';
16
16
  import '../../app/hook-event-context.js';
17
- import { apiResolves, apiTimeouts, actionResolves, actionTimeouts, FULL_RECEIVE_HEADER } from '../processor/config.js';
17
+ import { apiRequestResolves, apiRequestTimeouts, actionRequestResolves, actionRequestTimeouts, FULL_RECEIVE_HEADER } from '../processor/config.js';
18
18
  import { setDirectSend } from '../processor/transport.js';
19
+ import { normalizeInboundMessage } from '../normalize.js';
19
20
  import '../../app/message-format-old.js';
20
21
  import 'cron';
21
22
  import '../../app/event-utils.js';
@@ -23,48 +24,60 @@ import '../../app/message-api.js';
23
24
  import { createWSConnector } from './base.js';
24
25
  import { createDirectServer } from '../../process/direct-channel.js';
25
26
 
26
- const handleParsedMessage = (parsedMessage) => {
27
- if (parsedMessage?.apiId) {
28
- const resolve = apiResolves.get(parsedMessage.apiId);
27
+ const handleInboundMessage = (message) => {
28
+ const normalized = normalizeInboundMessage(message);
29
+ if (!normalized) {
30
+ return;
31
+ }
32
+ if (normalized.kind === 'api.res') {
33
+ const resolve = apiRequestResolves.get(normalized.replyTo);
29
34
  if (resolve) {
30
- apiResolves.delete(parsedMessage.apiId);
31
- const timeout = apiTimeouts.get(parsedMessage.apiId);
35
+ apiRequestResolves.delete(normalized.replyTo);
36
+ const timeout = apiRequestTimeouts.get(normalized.replyTo);
32
37
  if (timeout) {
33
- apiTimeouts.delete(parsedMessage.apiId);
38
+ apiRequestTimeouts.delete(normalized.replyTo);
34
39
  clearTimeout(timeout);
35
40
  }
36
- if (Array.isArray(parsedMessage.payload)) {
37
- resolve(parsedMessage.payload);
41
+ if (Array.isArray(normalized.results)) {
42
+ resolve(normalized.results);
38
43
  }
39
44
  else {
40
45
  resolve([createResult(ResultCode.Fail, '接口处理错误', null)]);
41
46
  }
42
47
  }
43
48
  }
44
- else if (parsedMessage?.actionId) {
45
- const resolve = actionResolves.get(parsedMessage.actionId);
49
+ else if (normalized.kind === 'action.res') {
50
+ const resolve = actionRequestResolves.get(normalized.replyTo);
46
51
  if (resolve) {
47
- actionResolves.delete(parsedMessage.actionId);
48
- const timeout = actionTimeouts.get(parsedMessage.actionId);
52
+ actionRequestResolves.delete(normalized.replyTo);
53
+ const timeout = actionRequestTimeouts.get(normalized.replyTo);
49
54
  if (timeout) {
50
- actionTimeouts.delete(parsedMessage.actionId);
55
+ actionRequestTimeouts.delete(normalized.replyTo);
51
56
  clearTimeout(timeout);
52
57
  }
53
- if (Array.isArray(parsedMessage.payload)) {
54
- resolve(parsedMessage.payload);
58
+ if (Array.isArray(normalized.results)) {
59
+ resolve(normalized.results);
55
60
  }
56
61
  else {
57
62
  resolve([createResult(ResultCode.Fail, '消费处理错误', null)]);
58
63
  }
59
64
  }
60
65
  }
61
- else if (parsedMessage.name) {
62
- onProcessor(parsedMessage.name, parsedMessage, parsedMessage.value);
66
+ else if (normalized.kind === 'event') {
67
+ onProcessor(normalized.eventName, normalized.event, normalized.raw);
68
+ }
69
+ else if (normalized.kind === 'control' && normalized.op === 'sync') {
70
+ const env = normalized.payload?.env;
71
+ if (env && typeof env === 'object') {
72
+ for (const key in env) {
73
+ process.env[key] = String(env[key]);
74
+ }
75
+ }
63
76
  }
64
77
  };
65
78
  const cbpClientDirect = (sockPath, open) => {
66
79
  createDirectServer(sockPath, (data) => {
67
- handleParsedMessage(data);
80
+ handleInboundMessage(data);
68
81
  })
69
82
  .then(channel => {
70
83
  setDirectSend(channel.send);
@@ -89,7 +102,7 @@ const cbpClientIPC = (open) => {
89
102
  try {
90
103
  const msg = typeof message === 'string' ? JSON.parse(message) : message;
91
104
  if (msg?.type === 'ipc:data') {
92
- handleParsedMessage(msg.data);
105
+ handleInboundMessage(msg.data);
93
106
  }
94
107
  }
95
108
  catch (error) {
@@ -128,18 +141,7 @@ const cbpClient = (url, options = {}) => {
128
141
  onMessage: (messageStr) => {
129
142
  try {
130
143
  const parsedMessage = flattedJSON.parse(messageStr);
131
- if (parsedMessage?.activeId) {
132
- if (parsedMessage.active === 'sync') {
133
- const configs = parsedMessage.payload;
134
- const env = configs.env || {};
135
- for (const key in env) {
136
- process.env[key] = env[key];
137
- }
138
- }
139
- }
140
- else {
141
- handleParsedMessage(parsedMessage);
142
- }
144
+ handleInboundMessage(parsedMessage);
143
145
  }
144
146
  catch (error) {
145
147
  logger.error({
@@ -8,7 +8,30 @@ import 'yaml';
8
8
  import { sanitizeForSerialization } from '../../core/utils.js';
9
9
  import { createWSConnector } from './base.js';
10
10
  import { createDirectClient } from '../../process/direct-channel.js';
11
+ import { createEventEnvelope, normalizeInboundMessage, isNormalizedApiRequest, toLegacyApiData, createApiResponseEnvelope, isNormalizedActionRequest, toLegacyActionData, createActionResponseEnvelope } from '../normalize.js';
11
12
 
13
+ const dispatchLegacyActionHandlers = (actionReplys, replyAction, input) => {
14
+ const normalized = normalizeInboundMessage(input);
15
+ if (!isNormalizedActionRequest(normalized)) {
16
+ return false;
17
+ }
18
+ const legacy = toLegacyActionData(normalized);
19
+ for (const cb of actionReplys) {
20
+ void cb(legacy, val => replyAction(legacy, val));
21
+ }
22
+ return true;
23
+ };
24
+ const dispatchLegacyApiHandlers = (apiReplys, replyApi, input) => {
25
+ const normalized = normalizeInboundMessage(input);
26
+ if (!isNormalizedApiRequest(normalized)) {
27
+ return false;
28
+ }
29
+ const legacy = toLegacyApiData(normalized);
30
+ for (const cb of apiReplys) {
31
+ void cb(legacy, val => replyApi(legacy, val));
32
+ }
33
+ return true;
34
+ };
12
35
  const cbpPlatformDirect = (sockPath, open) => {
13
36
  const actionReplys = [];
14
37
  const apiReplys = [];
@@ -17,28 +40,19 @@ const cbpPlatformDirect = (sockPath, open) => {
17
40
  const send = (data) => {
18
41
  data.DeviceId = deviceId;
19
42
  data.CreateAt = Date.now();
43
+ const envelope = createEventEnvelope(data);
20
44
  if (channel) {
21
- channel.send(data);
45
+ channel.send(envelope);
22
46
  }
23
47
  else {
24
- pendingQueue.push({ ...data });
48
+ pendingQueue.push(envelope);
25
49
  }
26
50
  };
27
51
  const replyAction = (data, payload) => {
28
- channel?.send({
29
- action: data.action,
30
- payload: payload,
31
- actionId: data.actionId,
32
- DeviceId: data.DeviceId
33
- });
52
+ channel?.send(createActionResponseEnvelope(data, payload));
34
53
  };
35
54
  const replyApi = (data, payload) => {
36
- channel?.send({
37
- action: data.action,
38
- apiId: data.apiId,
39
- DeviceId: data.DeviceId,
40
- payload: payload
41
- });
55
+ channel?.send(createApiResponseEnvelope(data, payload));
42
56
  };
43
57
  const onactions = (reply) => {
44
58
  actionReplys.push(reply);
@@ -47,16 +61,10 @@ const cbpPlatformDirect = (sockPath, open) => {
47
61
  apiReplys.push(reply);
48
62
  };
49
63
  createDirectClient(sockPath, (data) => {
50
- if (data?.apiId) {
51
- for (const cb of apiReplys) {
52
- void cb(data, val => replyApi(data, val));
53
- }
54
- }
55
- else if (data?.actionId) {
56
- for (const cb of actionReplys) {
57
- void cb(data, val => replyAction(data, val));
58
- }
64
+ if (dispatchLegacyApiHandlers(apiReplys, replyApi, data)) {
65
+ return;
59
66
  }
67
+ dispatchLegacyActionHandlers(actionReplys, replyAction, data);
60
68
  })
61
69
  .then(ch => {
62
70
  channel = ch;
@@ -88,19 +96,15 @@ const cbpPlatformIPC = (open, existingActionReplys, existingApiReplys) => {
88
96
  if (typeof process.send === 'function') {
89
97
  data.DeviceId = deviceId;
90
98
  data.CreateAt = Date.now();
91
- process.send({ type: 'ipc:data', data: sanitizeForSerialization(data) });
99
+ const envelope = createEventEnvelope(data);
100
+ process.send({ type: 'ipc:data', data: sanitizeForSerialization(envelope) });
92
101
  }
93
102
  };
94
103
  const replyAction = (data, payload) => {
95
104
  if (typeof process.send === 'function') {
96
105
  process.send({
97
106
  type: 'ipc:data',
98
- data: {
99
- action: data.action,
100
- payload: payload,
101
- actionId: data.actionId,
102
- DeviceId: data.DeviceId
103
- }
107
+ data: sanitizeForSerialization(createActionResponseEnvelope(data, payload))
104
108
  });
105
109
  }
106
110
  };
@@ -108,12 +112,7 @@ const cbpPlatformIPC = (open, existingActionReplys, existingApiReplys) => {
108
112
  if (typeof process.send === 'function') {
109
113
  process.send({
110
114
  type: 'ipc:data',
111
- data: {
112
- action: data.action,
113
- apiId: data.apiId,
114
- DeviceId: data.DeviceId,
115
- payload: payload
116
- }
115
+ data: sanitizeForSerialization(createApiResponseEnvelope(data, payload))
117
116
  });
118
117
  }
119
118
  };
@@ -127,17 +126,10 @@ const cbpPlatformIPC = (open, existingActionReplys, existingApiReplys) => {
127
126
  try {
128
127
  const msg = typeof message === 'string' ? JSON.parse(message) : message;
129
128
  if (msg?.type === 'ipc:data') {
130
- const data = msg.data;
131
- if (data?.apiId) {
132
- for (const cb of apiReplys) {
133
- void cb(data, val => replyApi(data, val));
134
- }
135
- }
136
- else if (data?.actionId) {
137
- for (const cb of actionReplys) {
138
- void cb(data, val => replyAction(data, val));
139
- }
129
+ if (dispatchLegacyApiHandlers(apiReplys, replyApi, msg.data)) {
130
+ return;
140
131
  }
132
+ dispatchLegacyActionHandlers(actionReplys, replyAction, msg.data);
141
133
  }
142
134
  }
143
135
  catch (error) {
@@ -188,29 +180,20 @@ const cbpPlatform = (url, options = {
188
180
  if (global.chatbotPlatform?.readyState === WebSocket.OPEN) {
189
181
  data.DeviceId = deviceId;
190
182
  data.CreateAt = Date.now();
191
- global.chatbotPlatform.send(flattedJSON.stringify(sanitizeForSerialization(data)));
183
+ const envelope = createEventEnvelope(data);
184
+ global.chatbotPlatform.send(flattedJSON.stringify(sanitizeForSerialization(envelope)));
192
185
  }
193
186
  };
194
187
  const actionReplys = [];
195
188
  const apiReplys = [];
196
189
  const replyAction = (data, payload) => {
197
190
  if (global.chatbotPlatform?.readyState === WebSocket.OPEN) {
198
- global.chatbotPlatform.send(flattedJSON.stringify({
199
- action: data.action,
200
- payload: payload,
201
- actionId: data.actionId,
202
- DeviceId: data.DeviceId
203
- }));
191
+ global.chatbotPlatform.send(flattedJSON.stringify(createActionResponseEnvelope(data, payload)));
204
192
  }
205
193
  };
206
194
  const replyApi = (data, payload) => {
207
195
  if (global.chatbotPlatform?.readyState === WebSocket.OPEN) {
208
- global.chatbotPlatform.send(flattedJSON.stringify({
209
- action: data.action,
210
- apiId: data.apiId,
211
- DeviceId: data.DeviceId,
212
- payload: payload
213
- }));
196
+ global.chatbotPlatform.send(flattedJSON.stringify(createApiResponseEnvelope(data, payload)));
214
197
  }
215
198
  };
216
199
  const onactions = (reply) => {
@@ -227,16 +210,10 @@ const cbpPlatform = (url, options = {
227
210
  onMessage: (messageStr) => {
228
211
  try {
229
212
  const data = flattedJSON.parse(messageStr);
230
- if (data.apiId) {
231
- for (const cb of apiReplys) {
232
- void cb(data, val => replyApi(data, val));
233
- }
234
- }
235
- else if (data.actionId) {
236
- for (const cb of actionReplys) {
237
- void cb(data, val => replyAction(data, val));
238
- }
213
+ if (dispatchLegacyApiHandlers(apiReplys, replyApi, data)) {
214
+ return;
239
215
  }
216
+ dispatchLegacyActionHandlers(actionReplys, replyAction, data);
240
217
  }
241
218
  catch (error) {
242
219
  logger.error({
@@ -0,0 +1,16 @@
1
+ import type { Actions, Apis } from '../types';
2
+ import type { Result } from '../core/utils';
3
+ import type { CBPEnvelope, CBPError, CBPResult, NormalizedActionRequestMessage, NormalizedApiRequestMessage, NormalizedCBPMessage } from './typings';
4
+ export declare const isCBPEnvelope: (input: unknown) => input is CBPEnvelope;
5
+ export declare const normalizeInboundMessage: (input: unknown) => NormalizedCBPMessage | null;
6
+ export declare const toLegacyActionData: (message: NormalizedActionRequestMessage) => Actions;
7
+ export declare const toLegacyApiData: (message: NormalizedApiRequestMessage) => Apis;
8
+ export declare const isNormalizedActionRequest: (message: NormalizedCBPMessage | null | undefined) => message is NormalizedActionRequestMessage;
9
+ export declare const isNormalizedApiRequest: (message: NormalizedCBPMessage | null | undefined) => message is NormalizedApiRequestMessage;
10
+ export declare const getNormalizedDeviceId: (message: NormalizedCBPMessage) => string;
11
+ export declare const getNormalizedEventRouteId: (message: NormalizedCBPMessage) => string;
12
+ export declare const createActionRequestEnvelope: (data: Actions) => CBPEnvelope;
13
+ export declare const createApiRequestEnvelope: (data: Apis) => CBPEnvelope;
14
+ export declare const createActionResponseEnvelope: (data: Actions, payload: CBPResult[] | Result[], error?: CBPError) => CBPEnvelope;
15
+ export declare const createApiResponseEnvelope: (data: Apis, payload: CBPResult[] | Result[], error?: CBPError) => CBPEnvelope;
16
+ export declare const createEventEnvelope: (data: Record<string, unknown>) => CBPEnvelope;