lupine.api 1.1.58 → 1.1.60

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 (137) hide show
  1. package/README.md +3 -3
  2. package/admin/admin-about.tsx +12 -16
  3. package/admin/admin-config.tsx +47 -44
  4. package/admin/admin-css.tsx +3 -3
  5. package/admin/admin-db.tsx +75 -75
  6. package/admin/admin-frame-helper.tsx +364 -364
  7. package/admin/admin-frame.tsx +164 -164
  8. package/admin/admin-index.tsx +65 -65
  9. package/admin/admin-login.tsx +111 -111
  10. package/admin/admin-menu-edit.tsx +637 -637
  11. package/admin/admin-menu-list.tsx +87 -87
  12. package/admin/admin-page-edit.tsx +564 -564
  13. package/admin/admin-page-list.tsx +83 -83
  14. package/admin/admin-performance.tsx +28 -28
  15. package/admin/admin-release.tsx +427 -426
  16. package/admin/admin-resources.tsx +382 -382
  17. package/admin/admin-shell.tsx +89 -89
  18. package/admin/admin-table-data.tsx +146 -146
  19. package/admin/admin-table-list.tsx +230 -230
  20. package/admin/admin-test-animations.tsx +395 -395
  21. package/admin/admin-test-component.tsx +823 -808
  22. package/admin/admin-test-edit.tsx +319 -319
  23. package/admin/admin-test-themes.tsx +56 -56
  24. package/admin/admin-tokens.tsx +338 -338
  25. package/admin/design/admin-design.tsx +174 -174
  26. package/admin/design/block-grid.tsx +36 -36
  27. package/admin/design/block-grid1.tsx +21 -21
  28. package/admin/design/block-paragraph.tsx +19 -19
  29. package/admin/design/block-title.tsx +19 -19
  30. package/admin/design/design-block-box.tsx +140 -140
  31. package/admin/design/drag-data.tsx +24 -24
  32. package/admin/index.ts +9 -9
  33. package/admin/package.json +15 -15
  34. package/admin/tsconfig.json +127 -127
  35. package/dev/copy-folder.js +32 -32
  36. package/dev/cp-index-html.js +69 -69
  37. package/dev/file-utils.js +12 -12
  38. package/dev/index.js +18 -19
  39. package/dev/package.json +12 -12
  40. package/dev/plugin-ifelse.js +168 -168
  41. package/dev/plugin-ifelse.test.js +37 -37
  42. package/dev/run-cmd.js +14 -14
  43. package/dev/send-request.js +12 -12
  44. package/package.json +55 -55
  45. package/src/admin-api/admin-api-helper.ts +210 -205
  46. package/src/admin-api/admin-api.ts +65 -65
  47. package/src/admin-api/admin-auth.ts +152 -146
  48. package/src/admin-api/admin-config.ts +94 -84
  49. package/src/admin-api/admin-csv.ts +94 -94
  50. package/src/admin-api/admin-db.ts +269 -269
  51. package/src/admin-api/admin-menu.ts +135 -135
  52. package/src/admin-api/admin-page.ts +135 -135
  53. package/src/admin-api/admin-performance.ts +128 -128
  54. package/src/admin-api/admin-release.ts +706 -700
  55. package/src/admin-api/admin-resources.ts +318 -318
  56. package/src/admin-api/admin-token-helper.ts +82 -79
  57. package/src/admin-api/admin-tokens.ts +90 -90
  58. package/src/admin-api/index.ts +2 -2
  59. package/src/admin-api/web-config-api.ts +19 -19
  60. package/src/api/api-cache.ts +103 -103
  61. package/src/api/api-helper.ts +44 -44
  62. package/src/api/api-module.ts +67 -60
  63. package/src/api/api-router.ts +177 -177
  64. package/src/api/api-shared-storage.ts +64 -64
  65. package/src/api/async-storage.ts +5 -5
  66. package/src/api/debug-service.ts +56 -56
  67. package/src/api/encode-html.ts +27 -27
  68. package/src/api/handle-status.ts +75 -75
  69. package/src/api/index.ts +15 -16
  70. package/src/api/mini-web-socket.ts +270 -270
  71. package/src/api/server-content-type.ts +82 -82
  72. package/src/api/server-render.ts +235 -215
  73. package/src/api/shell-service.ts +74 -74
  74. package/src/api/simple-storage.ts +80 -80
  75. package/src/api/static-server.ts +128 -125
  76. package/src/api/to-client-delivery.ts +26 -26
  77. package/src/app/app-cache.ts +55 -55
  78. package/src/app/app-helper.ts +62 -62
  79. package/src/app/app-message.ts +109 -109
  80. package/src/app/app-shared-storage.ts +363 -363
  81. package/src/app/app-start.ts +136 -136
  82. package/src/app/cleanup-exit.ts +16 -16
  83. package/src/app/host-to-path.ts +38 -38
  84. package/src/app/index.ts +11 -11
  85. package/src/app/process-dev-requests.ts +130 -130
  86. package/src/app/web-listener.ts +294 -294
  87. package/src/app/web-processor.ts +47 -42
  88. package/src/app/web-server.ts +100 -100
  89. package/src/common-js/web-env.js +104 -104
  90. package/src/index.ts +7 -7
  91. package/src/lang/api-lang-en.ts +26 -26
  92. package/src/lang/api-lang-zh-cn.ts +27 -27
  93. package/src/lang/index.ts +2 -2
  94. package/src/lang/lang-helper.ts +76 -76
  95. package/src/lang/lang-props.ts +6 -6
  96. package/src/lib/db/db-helper.ts +23 -23
  97. package/src/lib/db/db-mysql.ts +249 -250
  98. package/src/lib/db/db-sqlite.ts +101 -101
  99. package/src/lib/db/db.spec.ts +28 -28
  100. package/src/lib/db/db.ts +325 -325
  101. package/src/lib/db/index.ts +5 -5
  102. package/src/lib/index.ts +3 -3
  103. package/src/lib/logger.spec.ts +214 -214
  104. package/src/lib/logger.ts +281 -281
  105. package/src/lib/runtime-require.ts +37 -37
  106. package/src/lib/utils/cookie-util.ts +34 -34
  107. package/src/lib/utils/crypto.ts +58 -58
  108. package/src/lib/utils/date-utils.ts +317 -317
  109. package/src/lib/utils/deep-merge.ts +37 -37
  110. package/src/lib/utils/delay.ts +12 -12
  111. package/src/lib/utils/file-setting.ts +55 -55
  112. package/src/lib/utils/format-bytes.ts +11 -11
  113. package/src/lib/utils/fs-utils.ts +158 -158
  114. package/src/lib/utils/get-env.ts +27 -27
  115. package/src/lib/utils/index.ts +12 -12
  116. package/src/lib/utils/is-type.ts +48 -48
  117. package/src/lib/utils/load-env.ts +14 -14
  118. package/src/lib/utils/pad.ts +6 -6
  119. package/src/models/api-base.ts +5 -5
  120. package/src/models/api-module-props.ts +10 -11
  121. package/src/models/api-router-props.ts +26 -26
  122. package/src/models/app-cache-props.ts +33 -33
  123. package/src/models/app-data-props.ts +10 -10
  124. package/src/models/app-helper-props.ts +6 -6
  125. package/src/models/app-shared-storage-props.ts +38 -38
  126. package/src/models/app-start-props.ts +18 -18
  127. package/src/models/async-storage-props.ts +13 -13
  128. package/src/models/db-config.ts +30 -30
  129. package/src/models/host-to-path-props.ts +12 -12
  130. package/src/models/index.ts +16 -16
  131. package/src/models/json-object.ts +8 -8
  132. package/src/models/locals-props.ts +36 -36
  133. package/src/models/logger-props.ts +84 -84
  134. package/src/models/simple-storage-props.ts +13 -14
  135. package/src/models/to-client-delivery-props.ts +6 -6
  136. package/tsconfig.json +115 -115
  137. package/dev/plugin-gen-versions.js +0 -20
@@ -1,55 +1,55 @@
1
- /**
2
- * A simple settings/config class for storing key/value pairs in memory
3
- */
4
-
5
- import { AppCacheGlobal, AppCacheKeys, IAppCache } from '../models/app-cache-props';
6
- // For cross clusters sharing, use AppSharedStorage
7
- // ApiCache doesn't share cross clusters
8
- // Since apis and app are independent, so AppCache in apis and app are different instances.
9
- // That's why replaceInstance is used to copy data from app to apis,
10
- // and also AppCache is not shared cross app and apis, so `set` is only supposed to be called when app starts
11
- export class AppCache implements IAppCache {
12
- private static instance: AppCache;
13
-
14
- cacheMap: { [key: string]: any } = {};
15
-
16
- private constructor() {}
17
-
18
- public static getInstance(): AppCache {
19
- if (!AppCache.instance) {
20
- AppCache.instance = new AppCache();
21
- }
22
- return AppCache.instance;
23
- }
24
-
25
- clear(appName: string | undefined) {
26
- const preKey = appName + '.';
27
- Object.keys(this.cacheMap).forEach((key) => {
28
- if (!appName || key.startsWith(preKey)) {
29
- delete this.cacheMap[key];
30
- }
31
- });
32
- }
33
-
34
- get(appName: string, key: string) {
35
- return this.cacheMap[`${appName}.${key}`];
36
- }
37
-
38
- set(appName: string, key: string, value: any) {
39
- if (typeof value === 'undefined') {
40
- delete this.cacheMap[`${appName}.${key}`];
41
- } else {
42
- this.cacheMap[`${appName}.${key}`] = value;
43
- }
44
- }
45
-
46
- clearTemplateCache() {
47
- const appList = this.get(AppCacheGlobal, AppCacheKeys.APP_LIST) as string[];
48
- appList.forEach((appName) => {
49
- this.set(appName, AppCacheKeys.TEMPLATE, undefined);
50
- });
51
- }
52
- }
53
-
54
- // this can be used in app, but in api, it should use getAppCache()
55
- export const appCache = /* @__PURE__ */ AppCache.getInstance();
1
+ /**
2
+ * A simple settings/config class for storing key/value pairs in memory
3
+ */
4
+
5
+ import { AppCacheGlobal, AppCacheKeys, IAppCache } from '../models/app-cache-props';
6
+ // For cross clusters sharing, use AppSharedStorage
7
+ // ApiCache doesn't share cross clusters
8
+ // Since apis and app are independent, so AppCache in apis and app are different instances.
9
+ // That's why replaceInstance is used to copy data from app to apis,
10
+ // and also AppCache is not shared cross app and apis, so `set` is only supposed to be called when app starts
11
+ export class AppCache implements IAppCache {
12
+ private static instance: AppCache;
13
+
14
+ cacheMap: { [key: string]: any } = {};
15
+
16
+ private constructor() {}
17
+
18
+ public static getInstance(): AppCache {
19
+ if (!AppCache.instance) {
20
+ AppCache.instance = new AppCache();
21
+ }
22
+ return AppCache.instance;
23
+ }
24
+
25
+ clear(appName: string | undefined) {
26
+ const preKey = appName + '.';
27
+ Object.keys(this.cacheMap).forEach((key) => {
28
+ if (!appName || key.startsWith(preKey)) {
29
+ delete this.cacheMap[key];
30
+ }
31
+ });
32
+ }
33
+
34
+ get(appName: string, key: string) {
35
+ return this.cacheMap[`${appName}.${key}`];
36
+ }
37
+
38
+ set(appName: string, key: string, value: any) {
39
+ if (typeof value === 'undefined') {
40
+ delete this.cacheMap[`${appName}.${key}`];
41
+ } else {
42
+ this.cacheMap[`${appName}.${key}`] = value;
43
+ }
44
+ }
45
+
46
+ clearTemplateCache() {
47
+ const appList = this.get(AppCacheGlobal, AppCacheKeys.APP_LIST) as string[];
48
+ appList.forEach((appName) => {
49
+ this.set(appName, AppCacheKeys.TEMPLATE, undefined);
50
+ });
51
+ }
52
+ }
53
+
54
+ // this can be used in app, but in api, it should use getAppCache()
55
+ export const appCache = /* @__PURE__ */ AppCache.getInstance();
@@ -1,62 +1,62 @@
1
- import { Logger } from '../lib';
2
- import path from 'path';
3
- import { appCache } from './app-cache';
4
- import { AppCacheKeys, AppLoaderProps, HostToPathProps, IApiModule, setAppCache } from '../models';
5
- import { appStorage } from './app-shared-storage';
6
-
7
- class AppHelper {
8
- logger: Logger = new Logger('app-helper');
9
-
10
- constructor() {}
11
-
12
- async loadApi(config: AppLoaderProps) {
13
- // const apps: Set<string> = new Set();
14
- // for (let key in config.webHostMap) {
15
- // // one app may be defined for multiple hosts, but Set only stores unique values
16
- // apps.add(config.webHostMap[key].appName);
17
- // config.webHostMap[key].webPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_web');
18
- // config.webHostMap[key].dataPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_data');
19
- // config.webHostMap[key].apiPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_api');
20
- // }
21
-
22
- for (let appConfig of config.webHostMap) {
23
- await this.callInitApi(appConfig);
24
- appCache.set(appConfig.appName, AppCacheKeys.API_CONFIG, appConfig);
25
- }
26
- }
27
-
28
- async callInitApi(appConfig: HostToPathProps) {
29
- const apiPath = path.join(process.cwd(), 'dist/server_root', appConfig.appName + '_api/index.js');
30
- try {
31
- // const module = await import(apiPath);
32
- const module = require(apiPath);
33
- this.logger.debug(`========= ${appConfig.appName} apiModule: `, module);
34
-
35
- if (module && module.apiModule && typeof module.apiModule.initApi === 'function') {
36
- const apiModule = module.apiModule as IApiModule;
37
- appCache.set(appConfig.appName, AppCacheKeys.API_MODULE, apiModule);
38
-
39
- // getAppCache should be only called inside api scope, but set it in app scope in case it's used
40
- setAppCache(appCache);
41
- // setAppStorage(appStorage);
42
- await apiModule.initApi(appConfig, appCache, appStorage);
43
- }
44
- } catch (err: any) {
45
- this.logger.error(`appName: ${appConfig.appName}, load api error: `, err);
46
- }
47
- }
48
-
49
- async refreshApi(appConfig: HostToPathProps) {
50
- // TODO: call unloadApi?
51
- const apiPath = path.join(process.cwd(), 'dist/server_root', appConfig.appName + '_api/index.js');
52
- for (const path in require.cache) {
53
- if (path.endsWith('.js') && path.indexOf(apiPath) <= 0) {
54
- console.log(`${process.pid} - clear cache: ${path}`);
55
- delete require.cache[path];
56
- }
57
- }
58
- await this.callInitApi(appConfig);
59
- }
60
- }
61
-
62
- export const appHelper = /* @__PURE__ */ new AppHelper();
1
+ import { Logger } from '../lib';
2
+ import path from 'path';
3
+ import { appCache } from './app-cache';
4
+ import { AppCacheKeys, AppLoaderProps, HostToPathProps, IApiModule, setAppCache } from '../models';
5
+ import { appStorage } from './app-shared-storage';
6
+
7
+ class AppHelper {
8
+ logger: Logger = new Logger('app-helper');
9
+
10
+ constructor() {}
11
+
12
+ async loadApi(config: AppLoaderProps) {
13
+ // const apps: Set<string> = new Set();
14
+ // for (let key in config.webHostMap) {
15
+ // // one app may be defined for multiple hosts, but Set only stores unique values
16
+ // apps.add(config.webHostMap[key].appName);
17
+ // config.webHostMap[key].webPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_web');
18
+ // config.webHostMap[key].dataPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_data');
19
+ // config.webHostMap[key].apiPath = path.join(config.serverRoot, config.webHostMap[key].appName + '_api');
20
+ // }
21
+
22
+ for (let appConfig of config.webHostMap) {
23
+ await this.callInitApi(appConfig);
24
+ appCache.set(appConfig.appName, AppCacheKeys.API_CONFIG, appConfig);
25
+ }
26
+ }
27
+
28
+ async callInitApi(appConfig: HostToPathProps) {
29
+ const apiPath = path.join(process.cwd(), 'dist/server_root', appConfig.appName + '_api/index.js');
30
+ try {
31
+ // const module = await import(apiPath);
32
+ const module = require(apiPath);
33
+ this.logger.debug(`========= ${appConfig.appName} apiModule: `, module);
34
+
35
+ if (module && module.apiModule && typeof module.apiModule.initApi === 'function') {
36
+ const apiModule = module.apiModule as IApiModule;
37
+ appCache.set(appConfig.appName, AppCacheKeys.API_MODULE, apiModule);
38
+
39
+ // getAppCache should be only called inside api scope, but set it in app scope in case it's used
40
+ setAppCache(appCache);
41
+ // setAppStorage(appStorage);
42
+ await apiModule.initApi(appConfig, appCache, appStorage);
43
+ }
44
+ } catch (err: any) {
45
+ this.logger.error(`appName: ${appConfig.appName}, load api error: `, err.message);
46
+ }
47
+ }
48
+
49
+ async refreshApi(appConfig: HostToPathProps) {
50
+ // TODO: call unloadApi?
51
+ const apiPath = path.join(process.cwd(), 'dist/server_root', appConfig.appName + '_api/index.js');
52
+ for (const path in require.cache) {
53
+ if (path.endsWith('.js') && path.indexOf(apiPath) <= 0) {
54
+ console.log(`${process.pid} - clear cache: ${path}`);
55
+ delete require.cache[path];
56
+ }
57
+ }
58
+ await this.callInitApi(appConfig);
59
+ }
60
+ }
61
+
62
+ export const appHelper = /* @__PURE__ */ new AppHelper();
@@ -1,109 +1,109 @@
1
- import cluster from 'cluster';
2
- import { Logger, LogWriter, LogWriterMessageId } from '../lib';
3
- import { processDebugMessage, sendRestartAppMsgToLoader } from './process-dev-requests';
4
- import { cleanupAndExit } from './cleanup-exit';
5
-
6
- export type AppMessageProps = {
7
- id: string;
8
- message: string;
9
- appName?: string;
10
- [id: string]: any;
11
- };
12
- const _savedMessageHandler: {
13
- fromPrimary: { [messageId: string]: (msgObject: AppMessageProps) => void };
14
- fromWorker: { [messageId: string]: (msgObject: AppMessageProps) => void };
15
- } = {
16
- fromPrimary: {},
17
- fromWorker: {},
18
- };
19
-
20
- export const registerMessageHandlerFromPrimary = (messageId: string, handler: (msgObject: AppMessageProps) => void) => {
21
- _savedMessageHandler.fromPrimary[messageId] = handler;
22
- };
23
-
24
- export const registerMessageHandlerFromWorker = (messageId: string, handler: (msgObject: AppMessageProps) => void) => {
25
- _savedMessageHandler.fromWorker[messageId] = handler;
26
- };
27
-
28
- const logger = new Logger('app-message');
29
- // send msg to all clients
30
- const broadcast = (msgObject: AppMessageProps) => {
31
- for (let i in cluster.workers) {
32
- if (cluster.workers[i]) cluster.workers[i].send(msgObject);
33
- }
34
- };
35
-
36
- // this is a worker and msg is from Primary
37
- // when debug is on, it's in primary, but it shouldn't receive those msgs
38
- export const processMessageFromPrimary = (msgObject: AppMessageProps) => {
39
- if (!msgObject || !msgObject.id) {
40
- logger.warn(`Unknown message from master in work: ${cluster.worker?.id}`);
41
- return;
42
- }
43
-
44
- const primaryFn = _savedMessageHandler.fromPrimary[msgObject.id];
45
- if (primaryFn) {
46
- primaryFn(msgObject);
47
- return;
48
- }
49
-
50
- if (msgObject.id == 'debug') {
51
- processDebugMessage(msgObject);
52
- // } else if (msgObject.id == AppSharedStorageMessageId) {
53
- // appStorage.messageFromPrimaryProcess(msgObject);
54
- } else {
55
- logger.warn(`Unknown message: ${msgObject.id}`);
56
- }
57
- };
58
-
59
- // this is primary, msg is from a client
60
- export const processMessageFromWorker = (msgObject: AppMessageProps) => {
61
- if (!msgObject || !msgObject.id) {
62
- if (msgObject['watch:require']) return;
63
- logger.warn(`Unknown message from work: ${cluster.worker?.id}`);
64
- return;
65
- }
66
-
67
- const workerFn = _savedMessageHandler.fromWorker[msgObject.id];
68
- if (workerFn) {
69
- workerFn(msgObject);
70
- return;
71
- }
72
-
73
- if (msgObject.id == LogWriterMessageId) {
74
- LogWriter.messageFromSubProcess(msgObject as any);
75
- // } else if (msgObject.id == AppSharedStorageMessageId) {
76
- // appStorage.messageFromSubProcess(msgObject);
77
- } else if (msgObject.id == 'debug') {
78
- logger.debug(
79
- `Message from worker ${cluster.worker?.id}, message: ${msgObject.message}, appName: ${msgObject.appName}`
80
- );
81
- if (msgObject.message === 'restartApp') {
82
- sendRestartAppMsgToLoader();
83
- return;
84
- } else if (msgObject.message === 'refresh') {
85
- broadcast(msgObject);
86
- } else if (msgObject.message === 'shutdown') {
87
- broadcast(msgObject);
88
- // if it's shutdown, the primary process will exit
89
- setTimeout(async () => {
90
- console.log(`[server primary] Received shutdown command.`, cluster.workers);
91
- await cleanupAndExit();
92
- }, 100);
93
- } else {
94
- logger.warn(`Unknown message: ${msgObject.id}`);
95
- }
96
- } else {
97
- logger.warn(`Unknown message id: ${msgObject.id}`);
98
- }
99
- };
100
-
101
- // this is primary, and receive messages from loader
102
- export const receiveMessageFromLoader = () => {
103
- process.on('message', async (msg: AppMessageProps) => {
104
- if (msg?.id === 'debug' && msg?.message === 'shutdown') {
105
- console.log(`App ${process.pid}: received shutdown message from loader.`);
106
- processMessageFromWorker(msg);
107
- }
108
- });
109
- };
1
+ import cluster from 'cluster';
2
+ import { Logger, LogWriter, LogWriterMessageId } from '../lib';
3
+ import { processDebugMessage, sendRestartAppMsgToLoader } from './process-dev-requests';
4
+ import { cleanupAndExit } from './cleanup-exit';
5
+
6
+ export type AppMessageProps = {
7
+ id: string;
8
+ message: string;
9
+ appName?: string;
10
+ [id: string]: any;
11
+ };
12
+ const _savedMessageHandler: {
13
+ fromPrimary: { [messageId: string]: (msgObject: AppMessageProps) => void };
14
+ fromWorker: { [messageId: string]: (msgObject: AppMessageProps) => void };
15
+ } = {
16
+ fromPrimary: {},
17
+ fromWorker: {},
18
+ };
19
+
20
+ export const registerMessageHandlerFromPrimary = (messageId: string, handler: (msgObject: AppMessageProps) => void) => {
21
+ _savedMessageHandler.fromPrimary[messageId] = handler;
22
+ };
23
+
24
+ export const registerMessageHandlerFromWorker = (messageId: string, handler: (msgObject: AppMessageProps) => void) => {
25
+ _savedMessageHandler.fromWorker[messageId] = handler;
26
+ };
27
+
28
+ const logger = new Logger('app-message');
29
+ // send msg to all clients
30
+ const broadcast = (msgObject: AppMessageProps) => {
31
+ for (let i in cluster.workers) {
32
+ if (cluster.workers[i]) cluster.workers[i].send(msgObject);
33
+ }
34
+ };
35
+
36
+ // this is a worker and msg is from Primary
37
+ // when debug is on, it's in primary, but it shouldn't receive those msgs
38
+ export const processMessageFromPrimary = (msgObject: AppMessageProps) => {
39
+ if (!msgObject || !msgObject.id) {
40
+ logger.warn(`Unknown message from master in work: ${cluster.worker?.id}`);
41
+ return;
42
+ }
43
+
44
+ const primaryFn = _savedMessageHandler.fromPrimary[msgObject.id];
45
+ if (primaryFn) {
46
+ primaryFn(msgObject);
47
+ return;
48
+ }
49
+
50
+ if (msgObject.id == 'debug') {
51
+ processDebugMessage(msgObject);
52
+ // } else if (msgObject.id == AppSharedStorageMessageId) {
53
+ // appStorage.messageFromPrimaryProcess(msgObject);
54
+ } else {
55
+ logger.warn(`Unknown message: ${msgObject.id}`);
56
+ }
57
+ };
58
+
59
+ // this is primary, msg is from a client
60
+ export const processMessageFromWorker = (msgObject: AppMessageProps) => {
61
+ if (!msgObject || !msgObject.id) {
62
+ if (msgObject['watch:require']) return;
63
+ logger.warn(`Unknown message from work: ${cluster.worker?.id}`);
64
+ return;
65
+ }
66
+
67
+ const workerFn = _savedMessageHandler.fromWorker[msgObject.id];
68
+ if (workerFn) {
69
+ workerFn(msgObject);
70
+ return;
71
+ }
72
+
73
+ if (msgObject.id == LogWriterMessageId) {
74
+ LogWriter.messageFromSubProcess(msgObject as any);
75
+ // } else if (msgObject.id == AppSharedStorageMessageId) {
76
+ // appStorage.messageFromSubProcess(msgObject);
77
+ } else if (msgObject.id == 'debug') {
78
+ logger.debug(
79
+ `Message from worker ${cluster.worker?.id}, message: ${msgObject.message}, appName: ${msgObject.appName}`
80
+ );
81
+ if (msgObject.message === 'restartApp') {
82
+ sendRestartAppMsgToLoader();
83
+ return;
84
+ } else if (msgObject.message === 'refresh') {
85
+ broadcast(msgObject);
86
+ } else if (msgObject.message === 'shutdown') {
87
+ broadcast(msgObject);
88
+ // if it's shutdown, the primary process will exit
89
+ setTimeout(async () => {
90
+ console.log(`[server primary] Received shutdown command.`, cluster.workers);
91
+ await cleanupAndExit();
92
+ }, 100);
93
+ } else {
94
+ logger.warn(`Unknown message: ${msgObject.id}`);
95
+ }
96
+ } else {
97
+ logger.warn(`Unknown message id: ${msgObject.id}`);
98
+ }
99
+ };
100
+
101
+ // this is primary, and receive messages from loader
102
+ export const receiveMessageFromLoader = () => {
103
+ process.on('message', async (msg: AppMessageProps) => {
104
+ if (msg?.id === 'debug' && msg?.message === 'shutdown') {
105
+ console.log(`App ${process.pid}: received shutdown message from loader.`);
106
+ processMessageFromWorker(msg);
107
+ }
108
+ });
109
+ };