lupine.api 1.1.55 → 1.1.56

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.
@@ -12,7 +12,7 @@ export const AdminConfigPage = () => {
12
12
  const json = JSON.parse(ref.$('.input-cfg').value);
13
13
  const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/config/save', { json });
14
14
  if (data.json && data.json.status === 'ok') {
15
- NotificationMessage.sendMessage('Saved', NotificationColor.Success);
15
+ NotificationMessage.sendMessage('Saved, and please refresh the page to load new configs', NotificationColor.Success);
16
16
  }
17
17
  } catch (e) {
18
18
  NotificationMessage.sendMessage('Config is not valid JSON', NotificationColor.Error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lupine.api",
3
- "version": "1.1.55",
3
+ "version": "1.1.56",
4
4
  "license": "MIT",
5
5
  "author": "uuware.com",
6
6
  "homepage": "https://github.com/uuware/lupine.js",
@@ -52,4 +52,4 @@
52
52
  "devDependencies": {
53
53
  "@types/better-sqlite3": "^7.6.12"
54
54
  }
55
- }
55
+ }
@@ -1,6 +1,6 @@
1
1
  import { ServerResponse } from 'http';
2
2
  import * as fs from 'fs/promises';
3
- import { IApiBase, Logger, apiCache, ServerRequest, ApiRouter, ApiHelper, langHelper, FsUtils } from 'lupine.api';
3
+ import { IApiBase, Logger, apiCache, ServerRequest, ApiRouter, ApiHelper, langHelper, FsUtils, appStorage } from 'lupine.api';
4
4
  import path from 'path';
5
5
 
6
6
  export class AdminConfig implements IApiBase {
@@ -72,6 +72,8 @@ export class AdminConfig implements IApiBase {
72
72
  const cfgPath = path.join(appData.dataPath, 'config.json');
73
73
  await fs.writeFile(cfgPath, JSON.stringify(data.json));
74
74
 
75
+ await appStorage.load(appData.appName, appData.dataPath);
76
+
75
77
  const response = {
76
78
  status: 'ok',
77
79
  message: langHelper.getLang('shared:operation_success'),
@@ -536,6 +536,7 @@ export class AdminRelease implements IApiBase {
536
536
  !chkOption ||
537
537
  !toList ||
538
538
  (chkOption !== 'server' &&
539
+ chkOption !== 'app-loader' &&
539
540
  chkOption !== 'api' &&
540
541
  chkOption !== 'web' &&
541
542
  chkOption !== 'web-sub' &&
@@ -22,7 +22,7 @@ export class ApiModule implements IApiModule {
22
22
  return result;
23
23
  }
24
24
 
25
- // appCache is from app-loader (parent scope), not the same in current scope
25
+ // appCache is from app-helper (parent scope), not the same in current scope
26
26
  public async initApi(appConfig: HostToPathProps, appCacheFromApp: IAppCache, appStorageFromApp: IAppSharedStorage) {
27
27
 
28
28
  // const evnFile = appCacheFromApp.get(AppCacheGlobal, AppCacheKeys.APP_ENV_FILE);
@@ -4,8 +4,8 @@ import { appCache } from './app-cache';
4
4
  import { AppCacheKeys, AppLoaderProps, HostToPathProps, IApiModule, setAppCache } from '../models';
5
5
  import { appStorage } from './app-shared-storage';
6
6
 
7
- class AppLoader {
8
- logger: Logger = new Logger('app-loader');
7
+ class AppHelper {
8
+ logger: Logger = new Logger('app-helper');
9
9
 
10
10
  constructor() {}
11
11
 
@@ -59,4 +59,4 @@ class AppLoader {
59
59
  }
60
60
  }
61
61
 
62
- export const appLoader = /* @__PURE__ */ new AppLoader();
62
+ export const appHelper = /* @__PURE__ */ new AppHelper();
@@ -1,6 +1,6 @@
1
1
  import cluster from 'cluster';
2
2
  import { Logger, LogWriter, LogWriterMessageId } from '../lib';
3
- import { processDebugMessage, snedRestartAppMsgToLoader } from './process-dev-requests';
3
+ import { processDebugMessage, sendRestartAppMsgToLoader } from './process-dev-requests';
4
4
  import { cleanupAndExit } from './cleanup-exit';
5
5
 
6
6
  export type AppMessageProps = {
@@ -79,7 +79,7 @@ export const processMessageFromWorker = (msgObject: AppMessageProps) => {
79
79
  `Message from worker ${cluster.worker?.id}, message: ${msgObject.message}, appName: ${msgObject.appName}`
80
80
  );
81
81
  if (msgObject.message === 'restartApp') {
82
- snedRestartAppMsgToLoader();
82
+ sendRestartAppMsgToLoader();
83
83
  return;
84
84
  } else if (msgObject.message === 'refresh') {
85
85
  broadcast(msgObject);
@@ -99,6 +99,8 @@ export class AppSharedStorage implements IAppSharedStorage {
99
99
  } else if (msgObject.action === 'set') {
100
100
  const storage = this.getStorage(msgObject.appName);
101
101
  storage.set(msgObject.key, msgObject.value);
102
+ } else if (msgObject.action === 'load') {
103
+ this.load(msgObject.appName, msgObject.rootPath || '');
102
104
  } else if (msgObject.action === 'save') {
103
105
  this.save(msgObject.appName);
104
106
  } else {
@@ -116,7 +118,9 @@ export class AppSharedStorage implements IAppSharedStorage {
116
118
  // should be only called from primary when the app is starting
117
119
  async load(appName: string, rootPath: string) {
118
120
  if (!cluster.isPrimary) {
119
- throw new Error('AppStorage.load should be only called from primary');
121
+ // throw new Error('AppStorage.load should be only called from primary');
122
+ await AppSharedStorageWorker.load(appName, rootPath);
123
+ return;
120
124
  }
121
125
 
122
126
  const map = this.getStorageMap(appName);
@@ -147,6 +151,7 @@ export class AppSharedStorage implements IAppSharedStorage {
147
151
  return;
148
152
  }
149
153
 
154
+ console.log(`${process.pid} - AppStorage save, appName: ${appName}, exit: ${exit}`);
150
155
  if (appName) {
151
156
  const map = this.configMap[appName];
152
157
  if (map && map.fPath && map.storage.size() > 0 && map.storage.Dirty) {
@@ -166,7 +171,7 @@ export class AppSharedStorage implements IAppSharedStorage {
166
171
  // this can be called in primary or worker
167
172
  get(appName: string, key: string): Promise<string> {
168
173
  return new Promise((resolve, reject) => {
169
- console.log(`${process.pid} - AppStorage get value for key: ${key}`);
174
+ // console.log(`${process.pid} - AppStorage get value for key: ${key}`);
170
175
 
171
176
  if (!cluster.isPrimary) {
172
177
  AppSharedStorageWorker.get(appName, key, resolve, reject);
@@ -196,7 +201,7 @@ export class AppSharedStorage implements IAppSharedStorage {
196
201
  }
197
202
  getWithPrefix(appName: string, prefixKey: string): Promise<SimpleStorageDataProps> {
198
203
  return new Promise((resolve, reject) => {
199
- console.log(`${process.pid} - AppStorage getWithPrefix for prefixKey: ${prefixKey}`);
204
+ // console.log(`${process.pid} - AppStorage getWithPrefix for prefixKey: ${prefixKey}`);
200
205
 
201
206
  if (!cluster.isPrimary) {
202
207
  AppSharedStorageWorker.getWithPrefix(appName, prefixKey, resolve, reject);
@@ -238,7 +243,7 @@ class AppSharedStorageWorker {
238
243
  }
239
244
 
240
245
  if (msgObject.action === 'get') {
241
- console.log(`${process.pid} - AppStorage get value end for key: ${msgObject.key}`);
246
+ // console.log(`${process.pid} - AppStorage get value end for key: ${msgObject.key}`);
242
247
 
243
248
  const value = msgObject.value;
244
249
  // how to pass the value to the caller
@@ -265,6 +270,22 @@ class AppSharedStorageWorker {
265
270
  }
266
271
  }
267
272
 
273
+ static async load(appName: string, rootPath: string) {
274
+ if (cluster.isPrimary) {
275
+ throw new Error('AppSharedStorageWorker should be only called from workers');
276
+ }
277
+ const obj: StorageMessageFromSubProcess = {
278
+ id: AppSharedStorageMessageId,
279
+ pid: process.pid,
280
+ workerId: cluster.worker?.id || 0,
281
+ action: 'load',
282
+ appName: appName,
283
+ rootPath: rootPath,
284
+ key: 'load',
285
+ };
286
+ process.send!(obj);
287
+ }
288
+
268
289
  static async save(appName?: string) {
269
290
  if (cluster.isPrimary) {
270
291
  throw new Error('AppSharedStorageWorker should be only called from workers');
@@ -1,6 +1,6 @@
1
1
  import cluster from 'cluster';
2
2
  import { WebProcessor } from './web-processor';
3
- import { appLoader } from './app-loader';
3
+ import { appHelper } from './app-helper';
4
4
  import { processMessageFromPrimary, processMessageFromWorker } from './app-message';
5
5
  import { WebServer } from './web-server';
6
6
  import { processDevRequests } from './process-dev-requests';
@@ -59,7 +59,7 @@ class AppStart {
59
59
  process.on('message', processMessageFromPrimary);
60
60
 
61
61
  HostToPath.setHostToPathList(props.apiConfig.webHostMap);
62
- appLoader.loadApi(props.apiConfig);
62
+ appHelper.loadApi(props.apiConfig);
63
63
  this.initServer(props.serverConfig);
64
64
  } else if (cluster.isPrimary) {
65
65
  const numCPUs = props.debug ? 1 : require('os').cpus().length;
package/src/app/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from './app-cache';
2
- export * from './app-loader';
2
+ export * from './app-helper';
3
3
  export * from './app-message';
4
4
  export * from './app-shared-storage';
5
5
  export * from './app-start';
@@ -2,7 +2,7 @@ import cluster from 'cluster';
2
2
  import { Logger } from '../lib/logger';
3
3
  import { ServerResponse } from 'http';
4
4
  import { AddressInfo } from 'net';
5
- import { appLoader } from './app-loader';
5
+ import { appHelper } from './app-helper';
6
6
  import { DebugService } from '../api/debug-service';
7
7
  import { AppCacheGlobal, AppCacheKeys, getAppCache, ServerRequest } from '../models';
8
8
  import { cleanupAndExit } from './cleanup-exit';
@@ -27,13 +27,13 @@ export const processDebugMessage = async (msgObject: any) => {
27
27
  if (msgObject.id === 'debug' && msgObject.message === 'refresh') {
28
28
  if (msgObject.appName) {
29
29
  const appConfig = getAppCache().get(msgObject.appName, AppCacheKeys.API_CONFIG);
30
- appLoader.refreshApi(appConfig);
30
+ appHelper.refreshApi(appConfig);
31
31
  } else {
32
32
  // refresh all in a worker (app scope)
33
33
  let appList = getAppCache().get(AppCacheGlobal, AppCacheKeys.APP_LIST);
34
34
  for (const appName of appList) {
35
35
  const appConfig = getAppCache().get(appName, AppCacheKeys.API_CONFIG);
36
- appLoader.refreshApi(appConfig);
36
+ appHelper.refreshApi(appConfig);
37
37
  }
38
38
  }
39
39
 
@@ -72,7 +72,7 @@ export async function processRestartApp(req: ServerRequest) {
72
72
  }
73
73
  // in case if it's only one process (primary process)
74
74
  else {
75
- snedRestartAppMsgToLoader();
75
+ sendRestartAppMsgToLoader();
76
76
  }
77
77
  }
78
78
 
@@ -103,7 +103,7 @@ export async function processDevRequests(req: ServerRequest, res: ServerResponse
103
103
  }
104
104
 
105
105
  // this is called from a request and passes the restartApp message to loader
106
- export const snedRestartAppMsgToLoader = async () => {
106
+ export const sendRestartAppMsgToLoader = async () => {
107
107
  if (!cluster.isPrimary) {
108
108
  console.warn(`restartApp: shouldn't come here`);
109
109
  return;
@@ -2,7 +2,7 @@ import { ISimpleStorage, SimpleStorageDataProps } from './simple-storage-props';
2
2
 
3
3
  // interface of AppSharedStorage
4
4
  export const AppSharedStorageMessageId = 'AppSharedStorage';
5
- export type StorageMessageAction = 'get' | 'set' | 'save' | 'getWithPrefix';
5
+ export type StorageMessageAction = 'get' | 'set' | 'load' | 'save' | 'getWithPrefix';
6
6
  export interface StorageMessageFromSubProcess {
7
7
  id: string;
8
8
  pid: number | undefined;
@@ -13,6 +13,7 @@ export interface StorageMessageFromSubProcess {
13
13
  value?: any;
14
14
  uniqueKey?: string;
15
15
  appName: string;
16
+ rootPath?: string;
16
17
  }
17
18
 
18
19
  // also used in packages\lupine.api\src\common-js\web-env.js
@@ -1,5 +1,5 @@
1
1
  import { RenderPageFunctionsType } from '../api';
2
- import { AppLoaderProps } from './app-loader-props';
2
+ import { AppLoaderProps } from './app-helper-props';
3
3
 
4
4
  export type InitStartProps = {
5
5
  bindIp: string;
@@ -3,7 +3,7 @@ export * from './api-module-props';
3
3
  export * from './api-router-props';
4
4
  export * from './app-cache-props';
5
5
  export * from './app-data-props';
6
- export * from './app-loader-props';
6
+ export * from './app-helper-props';
7
7
  export * from './app-shared-storage-props';
8
8
  export * from './app-start-props';
9
9
  export * from './async-storage-props';