lupine.api 1.1.58 → 1.1.59
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/README.md +3 -3
- package/admin/admin-about.tsx +12 -16
- package/admin/admin-config.tsx +47 -44
- package/admin/admin-css.tsx +3 -3
- package/admin/admin-db.tsx +75 -75
- package/admin/admin-frame-helper.tsx +364 -364
- package/admin/admin-frame.tsx +164 -164
- package/admin/admin-index.tsx +65 -65
- package/admin/admin-login.tsx +111 -111
- package/admin/admin-menu-edit.tsx +637 -637
- package/admin/admin-menu-list.tsx +87 -87
- package/admin/admin-page-edit.tsx +564 -564
- package/admin/admin-page-list.tsx +83 -83
- package/admin/admin-performance.tsx +28 -28
- package/admin/admin-release.tsx +427 -426
- package/admin/admin-resources.tsx +382 -382
- package/admin/admin-shell.tsx +89 -89
- package/admin/admin-table-data.tsx +146 -146
- package/admin/admin-table-list.tsx +230 -230
- package/admin/admin-test-animations.tsx +395 -395
- package/admin/admin-test-component.tsx +823 -808
- package/admin/admin-test-edit.tsx +319 -319
- package/admin/admin-test-themes.tsx +56 -56
- package/admin/admin-tokens.tsx +338 -338
- package/admin/design/admin-design.tsx +174 -174
- package/admin/design/block-grid.tsx +36 -36
- package/admin/design/block-grid1.tsx +21 -21
- package/admin/design/block-paragraph.tsx +19 -19
- package/admin/design/block-title.tsx +19 -19
- package/admin/design/design-block-box.tsx +140 -140
- package/admin/design/drag-data.tsx +24 -24
- package/admin/index.ts +9 -9
- package/admin/package.json +15 -15
- package/admin/tsconfig.json +127 -127
- package/dev/copy-folder.js +32 -32
- package/dev/cp-index-html.js +69 -69
- package/dev/file-utils.js +12 -12
- package/dev/index.js +18 -19
- package/dev/package.json +12 -12
- package/dev/plugin-ifelse.js +168 -168
- package/dev/plugin-ifelse.test.js +37 -37
- package/dev/run-cmd.js +14 -14
- package/dev/send-request.js +12 -12
- package/package.json +55 -55
- package/src/admin-api/admin-api-helper.ts +210 -205
- package/src/admin-api/admin-api.ts +65 -65
- package/src/admin-api/admin-auth.ts +152 -146
- package/src/admin-api/admin-config.ts +94 -84
- package/src/admin-api/admin-csv.ts +94 -94
- package/src/admin-api/admin-db.ts +269 -269
- package/src/admin-api/admin-menu.ts +135 -135
- package/src/admin-api/admin-page.ts +135 -135
- package/src/admin-api/admin-performance.ts +128 -128
- package/src/admin-api/admin-release.ts +703 -700
- package/src/admin-api/admin-resources.ts +318 -318
- package/src/admin-api/admin-token-helper.ts +82 -79
- package/src/admin-api/admin-tokens.ts +90 -90
- package/src/admin-api/index.ts +2 -2
- package/src/admin-api/web-config-api.ts +19 -19
- package/src/api/api-cache.ts +103 -103
- package/src/api/api-helper.ts +44 -44
- package/src/api/api-module.ts +67 -60
- package/src/api/api-router.ts +177 -177
- package/src/api/api-shared-storage.ts +64 -64
- package/src/api/async-storage.ts +5 -5
- package/src/api/debug-service.ts +56 -56
- package/src/api/encode-html.ts +27 -27
- package/src/api/handle-status.ts +75 -75
- package/src/api/index.ts +15 -16
- package/src/api/mini-web-socket.ts +270 -270
- package/src/api/server-content-type.ts +82 -82
- package/src/api/server-render.ts +235 -215
- package/src/api/shell-service.ts +74 -74
- package/src/api/simple-storage.ts +80 -80
- package/src/api/static-server.ts +128 -125
- package/src/api/to-client-delivery.ts +26 -26
- package/src/app/app-cache.ts +55 -55
- package/src/app/app-helper.ts +62 -62
- package/src/app/app-message.ts +109 -109
- package/src/app/app-shared-storage.ts +363 -363
- package/src/app/app-start.ts +136 -136
- package/src/app/cleanup-exit.ts +16 -16
- package/src/app/host-to-path.ts +38 -38
- package/src/app/index.ts +11 -11
- package/src/app/process-dev-requests.ts +130 -130
- package/src/app/web-listener.ts +294 -294
- package/src/app/web-processor.ts +47 -42
- package/src/app/web-server.ts +100 -100
- package/src/common-js/web-env.js +104 -104
- package/src/index.ts +7 -7
- package/src/lang/api-lang-en.ts +26 -26
- package/src/lang/api-lang-zh-cn.ts +27 -27
- package/src/lang/index.ts +2 -2
- package/src/lang/lang-helper.ts +76 -76
- package/src/lang/lang-props.ts +6 -6
- package/src/lib/db/db-helper.ts +23 -23
- package/src/lib/db/db-mysql.ts +249 -250
- package/src/lib/db/db-sqlite.ts +101 -101
- package/src/lib/db/db.spec.ts +28 -28
- package/src/lib/db/db.ts +325 -325
- package/src/lib/db/index.ts +5 -5
- package/src/lib/index.ts +3 -3
- package/src/lib/logger.spec.ts +214 -214
- package/src/lib/logger.ts +281 -281
- package/src/lib/runtime-require.ts +37 -37
- package/src/lib/utils/cookie-util.ts +34 -34
- package/src/lib/utils/crypto.ts +58 -58
- package/src/lib/utils/date-utils.ts +317 -317
- package/src/lib/utils/deep-merge.ts +37 -37
- package/src/lib/utils/delay.ts +12 -12
- package/src/lib/utils/file-setting.ts +55 -55
- package/src/lib/utils/format-bytes.ts +11 -11
- package/src/lib/utils/fs-utils.ts +158 -158
- package/src/lib/utils/get-env.ts +27 -27
- package/src/lib/utils/index.ts +12 -12
- package/src/lib/utils/is-type.ts +48 -48
- package/src/lib/utils/load-env.ts +14 -14
- package/src/lib/utils/pad.ts +6 -6
- package/src/models/api-base.ts +5 -5
- package/src/models/api-module-props.ts +10 -11
- package/src/models/api-router-props.ts +26 -26
- package/src/models/app-cache-props.ts +33 -33
- package/src/models/app-data-props.ts +10 -10
- package/src/models/app-helper-props.ts +6 -6
- package/src/models/app-shared-storage-props.ts +38 -38
- package/src/models/app-start-props.ts +18 -18
- package/src/models/async-storage-props.ts +13 -13
- package/src/models/db-config.ts +30 -30
- package/src/models/host-to-path-props.ts +12 -12
- package/src/models/index.ts +16 -16
- package/src/models/json-object.ts +8 -8
- package/src/models/locals-props.ts +36 -36
- package/src/models/logger-props.ts +84 -84
- package/src/models/simple-storage-props.ts +13 -14
- package/src/models/to-client-delivery-props.ts +6 -6
- package/tsconfig.json +115 -115
- package/dev/plugin-gen-versions.js +0 -20
package/src/app/app-cache.ts
CHANGED
|
@@ -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();
|
package/src/app/app-helper.ts
CHANGED
|
@@ -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();
|
package/src/app/app-message.ts
CHANGED
|
@@ -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
|
+
};
|