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,42 +1,47 @@
1
- import { ServerResponse } from 'http';
2
- import { Logger } from '../lib/logger';
3
- import { handler404 } from '../api';
4
- import { ApiRouterCallback, AppCacheKeys, AsyncStorageProps, getAppCache, ServerRequest } from '../models';
5
- const logger = new Logger('web-processor');
6
-
7
- export class WebProcessor {
8
- static debugPath: string | undefined;
9
- static debugHandler: ApiRouterCallback | undefined;
10
-
11
- static enableDebug(path: string, debugHandler: ApiRouterCallback) {
12
- WebProcessor.debugPath = path;
13
- WebProcessor.debugHandler = debugHandler;
14
- }
15
-
16
- async processRequest(store: AsyncStorageProps, req: ServerRequest, res: ServerResponse) {
17
- if (WebProcessor.debugPath && req.locals.urlWithoutQuery.startsWith(WebProcessor.debugPath)) {
18
- if (WebProcessor.debugHandler) {
19
- await WebProcessor.debugHandler(req, res, req.locals.urlWithoutQuery);
20
- return true;
21
- }
22
- }
23
-
24
- // check if the request is handled by the api
25
- try {
26
- const _lupineApi = getAppCache().get(store.appName, AppCacheKeys.API_MODULE);
27
- if (_lupineApi && _lupineApi.processApi) {
28
- const result = await _lupineApi.processApi(store, store.locals.urlWithoutQuery, req, res);
29
- if (result) {
30
- return true;
31
- }
32
- } else {
33
- logger.error(`url: ${store.locals.url}, appName: ${store.appName}, no api module found`);
34
- }
35
- } catch (e: any) {
36
- logger.error(`url: ${store.locals.url}, appName: ${store.appName}, process api error: `, e.message);
37
- }
38
-
39
- handler404(res, `Request is not processed, url: ${req.locals.url}`);
40
- return true;
41
- }
42
- }
1
+ import { ServerResponse } from 'http';
2
+ import { Logger } from '../lib/logger';
3
+ import { handler404 } from '../api';
4
+ import { ApiRouterCallback, AppCacheKeys, AsyncStorageProps, getAppCache, ServerRequest } from '../models';
5
+ import { processRestartApp } from './process-dev-requests';
6
+ const logger = new Logger('web-processor');
7
+
8
+ export class WebProcessor {
9
+ static debugPath: string | undefined;
10
+ static debugHandler: ApiRouterCallback | undefined;
11
+
12
+ static enableDebug(path: string, debugHandler: ApiRouterCallback) {
13
+ WebProcessor.debugPath = path;
14
+ WebProcessor.debugHandler = debugHandler;
15
+ }
16
+
17
+ async processRequest(store: AsyncStorageProps, req: ServerRequest, res: ServerResponse) {
18
+ if (WebProcessor.debugPath && req.locals.urlWithoutQuery.startsWith(WebProcessor.debugPath)) {
19
+ if (WebProcessor.debugHandler) {
20
+ await WebProcessor.debugHandler(req, res, req.locals.urlWithoutQuery);
21
+ return true;
22
+ }
23
+ }
24
+
25
+ // check if the request is handled by the api
26
+ try {
27
+ const _lupineApi = getAppCache().get(store.appName, AppCacheKeys.API_MODULE);
28
+ if (_lupineApi && _lupineApi.processApi) {
29
+ const result = await _lupineApi.processApi(store, store.locals.urlWithoutQuery, req, res);
30
+ if (result) {
31
+ return true;
32
+ }
33
+ } else {
34
+ logger.error(`url: ${store.locals.url}, appName: ${store.appName}, no api module found`);
35
+ }
36
+ } catch (e: any) {
37
+ logger.error(`url: ${store.locals.url}, appName: ${store.appName}, process api error: `, e.message);
38
+ }
39
+
40
+ // rescue
41
+ if (req.locals.urlWithoutQuery.startsWith('/admin_dev')) {
42
+ await processRestartApp();
43
+ }
44
+ handler404(res, `Request is not processed, url: ${req.locals.url}`);
45
+ return true;
46
+ }
47
+ }
@@ -1,100 +1,100 @@
1
- import { ServerOptions } from 'https';
2
- import { Logger } from '../lib/logger';
3
- import { WebListener } from './web-listener';
4
- import * as fs from 'fs';
5
- import * as http from 'http';
6
- import * as https from 'https';
7
- import { IncomingMessage, ServerResponse } from 'http';
8
- import { Duplex } from 'stream';
9
- import { WebProcessor } from './web-processor';
10
- import { DebugService } from '../api/debug-service';
11
- import cluster from 'cluster';
12
- const logger = new Logger('web-server');
13
-
14
- export class WebServer {
15
- webListener: WebListener;
16
- constructor(webListener?: WebListener) {
17
- this.webListener = webListener || new WebListener(new WebProcessor());
18
- }
19
-
20
- handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer) {
21
- const clientIp = `${(socket as any).remoteAddress}:${(socket as any).remotePort}`;
22
- if (req.url?.startsWith('/debug') && socket.readable && socket.writable) {
23
- logger.debug(`Upgrade WebSocket access: ${req.url} from ${clientIp}.`);
24
- DebugService.handleUpgrade(req, socket, head);
25
- } else {
26
- logger.error(`Unexpected web socket access: ${req.url} from ${clientIp}`);
27
- socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
28
- socket.destroy();
29
- }
30
- }
31
-
32
- async listenerWrap(reqOrigin: IncomingMessage, res: ServerResponse) {
33
- try {
34
- await this.webListener.listener.bind(this.webListener)(reqOrigin, res);
35
- } catch (err) {
36
- console.error('Request error:', err);
37
- if (!res.headersSent) {
38
- res.statusCode = 500;
39
- res.end('Internal Server Error');
40
- }
41
- }
42
- }
43
-
44
- startHttp(httpPort: number, bindIp?: string, timeout?: number) {
45
- const httpServer = http.createServer(this.listenerWrap.bind(this));
46
- if (typeof timeout === 'number') httpServer.setTimeout(timeout);
47
-
48
- httpServer.on('upgrade', this.handleUpgrade.bind(this));
49
-
50
- httpServer.listen(httpPort, bindIp, () => {
51
- logger.info(`Http Server ${cluster.worker ? cluster.worker.id : -1} is started: http://localhost:${httpPort}`);
52
- });
53
- httpServer.on('error', (error: any) => {
54
- logger.error('Error occurred on http server', error);
55
- });
56
- return httpServer;
57
- }
58
-
59
- // multi domain https hosting
60
- // https://stackoverflow.com/questions/38162077/expressjs-multi-domain-https-hosting
61
- startHttps(httpsPort: number, bindIp?: string, sslKeyPath?: string, sslCrtPath?: string, timeout?: number) {
62
- const httpsOptions: ServerOptions = {};
63
- if (sslKeyPath && fs.existsSync(sslKeyPath) && sslCrtPath && fs.existsSync(sslCrtPath)) {
64
- logger.info('Load site ssl certificate.');
65
- // The options to https.createServer must include key and cert as they are required.
66
- // Even though that set won't be used if SNI provides a hostname.
67
- httpsOptions['key'] = fs.readFileSync(sslKeyPath, 'utf8');
68
- httpsOptions['cert'] = fs.readFileSync(sslCrtPath, 'utf8');
69
- // httpsOptions['ca'] = 'pem';
70
- // httpsOptions['SNICallback'] = function (domain, cb) {
71
- // if (typeof sites[domain] === "undefined") {
72
- // cb(new Error("domain not found"), null);
73
- // console.log("Error: domain not found: " + domain);
74
-
75
- // } else {
76
- // cb(null, sites[domain].context);
77
- // }
78
- // };
79
- } else {
80
- logger.warn(
81
- `Ssl certificate is not defined or doesn't exist, key file: ${sslKeyPath}, certificate file: ${sslCrtPath}`
82
- );
83
- }
84
-
85
- const httpsServer = https.createServer(httpsOptions, this.listenerWrap.bind(this));
86
- httpsServer.on('upgrade', this.handleUpgrade.bind(this));
87
-
88
- if (typeof timeout === 'number') {
89
- httpsServer.setTimeout(timeout);
90
- }
91
- httpsServer.listen(httpsPort, bindIp, () => {
92
- logger.info(`Https Server ${cluster.worker ? cluster.worker.id : -1} is started: https://localhost:${httpsPort}`);
93
- });
94
- httpsServer.on('error', (error: any) => {
95
- logger.error('Error occurred on https server', error);
96
- });
97
-
98
- return httpsServer;
99
- }
100
- }
1
+ import { ServerOptions } from 'https';
2
+ import { Logger } from '../lib/logger';
3
+ import { WebListener } from './web-listener';
4
+ import * as fs from 'fs';
5
+ import * as http from 'http';
6
+ import * as https from 'https';
7
+ import { IncomingMessage, ServerResponse } from 'http';
8
+ import { Duplex } from 'stream';
9
+ import { WebProcessor } from './web-processor';
10
+ import { DebugService } from '../api/debug-service';
11
+ import cluster from 'cluster';
12
+ const logger = new Logger('web-server');
13
+
14
+ export class WebServer {
15
+ webListener: WebListener;
16
+ constructor(webListener?: WebListener) {
17
+ this.webListener = webListener || new WebListener(new WebProcessor());
18
+ }
19
+
20
+ handleUpgrade(req: IncomingMessage, socket: Duplex, head: Buffer) {
21
+ const clientIp = `${(socket as any).remoteAddress}:${(socket as any).remotePort}`;
22
+ if (req.url?.startsWith('/debug') && socket.readable && socket.writable) {
23
+ logger.debug(`Upgrade WebSocket access: ${req.url} from ${clientIp}.`);
24
+ DebugService.handleUpgrade(req, socket, head);
25
+ } else {
26
+ logger.error(`Unexpected web socket access: ${req.url} from ${clientIp}`);
27
+ socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
28
+ socket.destroy();
29
+ }
30
+ }
31
+
32
+ async listenerWrap(reqOrigin: IncomingMessage, res: ServerResponse) {
33
+ try {
34
+ await this.webListener.listener.bind(this.webListener)(reqOrigin, res);
35
+ } catch (err) {
36
+ console.error('Request error:', err);
37
+ if (!res.headersSent) {
38
+ res.statusCode = 500;
39
+ res.end('Internal Server Error');
40
+ }
41
+ }
42
+ }
43
+
44
+ startHttp(httpPort: number, bindIp?: string, timeout?: number) {
45
+ const httpServer = http.createServer(this.listenerWrap.bind(this));
46
+ if (typeof timeout === 'number') httpServer.setTimeout(timeout);
47
+
48
+ httpServer.on('upgrade', this.handleUpgrade.bind(this));
49
+
50
+ httpServer.listen(httpPort, bindIp, () => {
51
+ logger.info(`Http Server ${cluster.worker ? cluster.worker.id : -1} is started: http://localhost:${httpPort}`);
52
+ });
53
+ httpServer.on('error', (error: any) => {
54
+ logger.error('Error occurred on http server', error);
55
+ });
56
+ return httpServer;
57
+ }
58
+
59
+ // multi domain https hosting
60
+ // https://stackoverflow.com/questions/38162077/expressjs-multi-domain-https-hosting
61
+ startHttps(httpsPort: number, bindIp?: string, sslKeyPath?: string, sslCrtPath?: string, timeout?: number) {
62
+ const httpsOptions: ServerOptions = {};
63
+ if (sslKeyPath && fs.existsSync(sslKeyPath) && sslCrtPath && fs.existsSync(sslCrtPath)) {
64
+ logger.info('Load site ssl certificate.');
65
+ // The options to https.createServer must include key and cert as they are required.
66
+ // Even though that set won't be used if SNI provides a hostname.
67
+ httpsOptions['key'] = fs.readFileSync(sslKeyPath, 'utf8');
68
+ httpsOptions['cert'] = fs.readFileSync(sslCrtPath, 'utf8');
69
+ // httpsOptions['ca'] = 'pem';
70
+ // httpsOptions['SNICallback'] = function (domain, cb) {
71
+ // if (typeof sites[domain] === "undefined") {
72
+ // cb(new Error("domain not found"), null);
73
+ // console.log("Error: domain not found: " + domain);
74
+
75
+ // } else {
76
+ // cb(null, sites[domain].context);
77
+ // }
78
+ // };
79
+ } else {
80
+ logger.warn(
81
+ `Ssl certificate is not defined or doesn't exist, key file: ${sslKeyPath}, certificate file: ${sslCrtPath}`
82
+ );
83
+ }
84
+
85
+ const httpsServer = https.createServer(httpsOptions, this.listenerWrap.bind(this));
86
+ httpsServer.on('upgrade', this.handleUpgrade.bind(this));
87
+
88
+ if (typeof timeout === 'number') {
89
+ httpsServer.setTimeout(timeout);
90
+ }
91
+ httpsServer.listen(httpsPort, bindIp, () => {
92
+ logger.info(`Https Server ${cluster.worker ? cluster.worker.id : -1} is started: https://localhost:${httpsPort}`);
93
+ });
94
+ httpsServer.on('error', (error: any) => {
95
+ logger.error('Error occurred on https server', error);
96
+ });
97
+
98
+ return httpsServer;
99
+ }
100
+ }
@@ -1,104 +1,104 @@
1
- // This file is defined as CommonJS module, because it's used in dev as well
2
- const fs = require('fs/promises');
3
- const path = require('path');
4
-
5
- exports.readFile = async (filePath) => {
6
- try {
7
- const text = await fs.readFile(filePath, 'utf-8');
8
- return text;
9
- } catch {
10
- return undefined;
11
- }
12
- };
13
-
14
- exports.parseEnv = async (envFile) => {
15
- let obj = {};
16
- const text = await exports.readFile(envFile);
17
- if (!text) {
18
- return obj;
19
- }
20
-
21
- let lines = text.replace(/\r\n?/gm, '\n').split('\n');
22
- for (let i = 0; i < lines.length; i++) {
23
- const line = lines[i].split(/=(.*)/s);
24
- const key = line[0].trim();
25
-
26
- if (key && !key.startsWith('#')) {
27
- if (key.endsWith('+')) {
28
- // if the line is like [key+=...] then it will be added to the same key
29
- obj[key.substring(0, key.length - 1)] += line[1] || '';
30
- } else if (key.endsWith('*')) {
31
- // if the line is like [key*=LINE_MARKER] then it's a multiline string, ending with "LINE_MARKER"
32
- const LINE_MARKER = line[1].trim();
33
- line[1] = '';
34
- for (i++; i < lines.length; i++) {
35
- if (lines[i].trim() === LINE_MARKER) {
36
- break;
37
- }
38
- line[1] += lines[i] + '\n';
39
- }
40
- obj[key.substring(0, key.length - 1)] = line[1];
41
- } else {
42
- obj[key] = line[1] || ''; // .replace(/\\n/g, '\n').replace(/\\r/g, '\r')
43
- }
44
- } else if (key.startsWith('#!import ')) {
45
- // use "#!import file_name" to import another env file
46
- const file = key.substring(9).trim();
47
- const newObj = await exports.parseEnv(path.join(path.dirname(envFile), file));
48
- obj = Object.assign(obj, newObj);
49
- }
50
- }
51
-
52
- return obj;
53
- };
54
-
55
- exports.copyToProcessEnv = (envObject, overrideEnv) => {
56
- for (const key of Object.keys(envObject)) {
57
- if (overrideEnv || typeof process.env[key] === 'undefined') {
58
- process.env[key] = envObject[key];
59
- }
60
- }
61
- };
62
-
63
- exports.loadEnv = async (envFile, overrideEnv = false) => {
64
- console.log(`Load env from: ${envFile}`);
65
- const envObject = await exports.parseEnv(envFile);
66
- exports.copyToProcessEnv(envObject, overrideEnv);
67
- };
68
-
69
- exports.getWebEnv = (appName) => {
70
- const envWeb = {};
71
- for (const envName in process.env) {
72
- if (envName.startsWith(`WEB.`)) {
73
- envWeb[envName.substring(4)] = process.env[envName];
74
- } else if (envName.startsWith(`${appName}.WEB.`)) {
75
- envWeb[envName.substring(appName.length + 5)] = process.env[envName];
76
- }
77
- }
78
- return envWeb;
79
- };
80
-
81
- // defined app-shared-storage-props.ts
82
- const AppSharedStorageWebPrefix = 'WEB.';
83
- exports.getWebConfig = (allConfig) => {
84
- const result = {};
85
- for (let key in allConfig) {
86
- if (key.startsWith(AppSharedStorageWebPrefix)) {
87
- result[key.substring(AppSharedStorageWebPrefix.length)] = allConfig[key];
88
- }
89
- }
90
- return result;
91
- };
92
-
93
- // // Replace <!--META-ENV-START-->...<!--META-ENV-END--> for mobile app and replace it again for web app
94
- // exports.replaceWebEnv = (html, appName, addMetaTag) => {
95
- // const envWeb = exports.getWebEnv(appName);
96
- // return html.replace(
97
- // /\<\!--META-ENV-START--\>(.*?)\<\!--META-ENV-END--\>/gm,
98
- // addMetaTag
99
- // ? '<!--META-ENV-START--><script id="web-env" type="application/json">' +
100
- // JSON.stringify(envWeb) +
101
- // '</script><!--META-ENV-END-->'
102
- // : '<script id="web-env" type="application/json">' + JSON.stringify(envWeb) + '</script>'
103
- // );
104
- // };
1
+ // This file is defined as CommonJS module, because it's used in dev as well
2
+ const fs = require('fs/promises');
3
+ const path = require('path');
4
+
5
+ exports.readFile = async (filePath) => {
6
+ try {
7
+ const text = await fs.readFile(filePath, 'utf-8');
8
+ return text;
9
+ } catch {
10
+ return undefined;
11
+ }
12
+ };
13
+
14
+ exports.parseEnv = async (envFile) => {
15
+ let obj = {};
16
+ const text = await exports.readFile(envFile);
17
+ if (!text) {
18
+ return obj;
19
+ }
20
+
21
+ let lines = text.replace(/\r\n?/gm, '\n').split('\n');
22
+ for (let i = 0; i < lines.length; i++) {
23
+ const line = lines[i].split(/=(.*)/s);
24
+ const key = line[0].trim();
25
+
26
+ if (key && !key.startsWith('#')) {
27
+ if (key.endsWith('+')) {
28
+ // if the line is like [key+=...] then it will be added to the same key
29
+ obj[key.substring(0, key.length - 1)] += line[1] || '';
30
+ } else if (key.endsWith('*')) {
31
+ // if the line is like [key*=LINE_MARKER] then it's a multiline string, ending with "LINE_MARKER"
32
+ const LINE_MARKER = line[1].trim();
33
+ line[1] = '';
34
+ for (i++; i < lines.length; i++) {
35
+ if (lines[i].trim() === LINE_MARKER) {
36
+ break;
37
+ }
38
+ line[1] += lines[i] + '\n';
39
+ }
40
+ obj[key.substring(0, key.length - 1)] = line[1];
41
+ } else {
42
+ obj[key] = line[1] || ''; // .replace(/\\n/g, '\n').replace(/\\r/g, '\r')
43
+ }
44
+ } else if (key.startsWith('#!import ')) {
45
+ // use "#!import file_name" to import another env file
46
+ const file = key.substring(9).trim();
47
+ const newObj = await exports.parseEnv(path.join(path.dirname(envFile), file));
48
+ obj = Object.assign(obj, newObj);
49
+ }
50
+ }
51
+
52
+ return obj;
53
+ };
54
+
55
+ exports.copyToProcessEnv = (envObject, overrideEnv) => {
56
+ for (const key of Object.keys(envObject)) {
57
+ if (overrideEnv || typeof process.env[key] === 'undefined') {
58
+ process.env[key] = envObject[key];
59
+ }
60
+ }
61
+ };
62
+
63
+ exports.loadEnv = async (envFile, overrideEnv = false) => {
64
+ console.log(`Load env from: ${envFile}`);
65
+ const envObject = await exports.parseEnv(envFile);
66
+ exports.copyToProcessEnv(envObject, overrideEnv);
67
+ };
68
+
69
+ exports.getWebEnv = (appName) => {
70
+ const envWeb = {};
71
+ for (const envName in process.env) {
72
+ if (envName.startsWith(`WEB.`)) {
73
+ envWeb[envName.substring(4)] = process.env[envName];
74
+ } else if (envName.startsWith(`${appName}.WEB.`)) {
75
+ envWeb[envName.substring(appName.length + 5)] = process.env[envName];
76
+ }
77
+ }
78
+ return envWeb;
79
+ };
80
+
81
+ // defined app-shared-storage-props.ts
82
+ const AppSharedStorageWebPrefix = 'WEB.';
83
+ exports.getWebConfig = (allConfig) => {
84
+ const result = {};
85
+ for (let key in allConfig) {
86
+ if (key.startsWith(AppSharedStorageWebPrefix)) {
87
+ result[key.substring(AppSharedStorageWebPrefix.length)] = allConfig[key];
88
+ }
89
+ }
90
+ return result;
91
+ };
92
+
93
+ // // Replace <!--META-ENV-START-->...<!--META-ENV-END--> for mobile app and replace it again for web app
94
+ // exports.replaceWebEnv = (html, appName, addMetaTag) => {
95
+ // const envWeb = exports.getWebEnv(appName);
96
+ // return html.replace(
97
+ // /\<\!--META-ENV-START--\>(.*?)\<\!--META-ENV-END--\>/gm,
98
+ // addMetaTag
99
+ // ? '<!--META-ENV-START--><script id="web-env" type="application/json">' +
100
+ // JSON.stringify(envWeb) +
101
+ // '</script><!--META-ENV-END-->'
102
+ // : '<script id="web-env" type="application/json">' + JSON.stringify(envWeb) + '</script>'
103
+ // );
104
+ // };
package/src/index.ts CHANGED
@@ -1,7 +1,7 @@
1
- export * from './models';
2
- export * from './lib';
3
- export * from './lang';
4
-
5
- export * from './admin-api';
6
- export * from './api';
7
- export * from './app';
1
+ export * from './models';
2
+ export * from './lib';
3
+ export * from './lang';
4
+
5
+ export * from './admin-api';
6
+ export * from './api';
7
+ export * from './app';
@@ -1,26 +1,26 @@
1
- import { OneLangProps } from './lang-props';
2
-
3
- export const apiLangEn: OneLangProps = {
4
- langName: 'en',
5
- langs: {
6
- 'shared:operation_success': 'Operation success',
7
- 'shared:operation_error': 'Operation error',
8
-
9
- 'shared:wrong_data': 'Wrong data.',
10
- 'shared:permission_denied': 'Permission denied.',
11
- 'shared:name_not_existed': '{name} not existed.',
12
- 'shared:name_not_set': '{name} not set.',
13
- 'shared:name_is_wrong': '{name} is wrong.',
14
-
15
- 'shared:login_success': 'Logged in.',
16
- 'shared:login_failed': 'Login failed.',
17
- 'shared:not_logged_in': 'Not logged in.',
18
-
19
- 'shared:user_not_found': 'User not found.',
20
- 'shared:user_locked': 'User locked.',
21
-
22
- 'shared:not_found_file': 'File {fileName} is not found.',
23
-
24
- 'shared:wrong_hash': 'Wrong hash.',
25
- },
26
- };
1
+ import { OneLangProps } from './lang-props';
2
+
3
+ export const apiLangEn: OneLangProps = {
4
+ langName: 'en',
5
+ langs: {
6
+ 'shared:operation_success': 'Operation success',
7
+ 'shared:operation_error': 'Operation error',
8
+
9
+ 'shared:wrong_data': 'Wrong data.',
10
+ 'shared:permission_denied': 'Permission denied.',
11
+ 'shared:name_not_existed': '{name} not existed.',
12
+ 'shared:name_not_set': '{name} not set.',
13
+ 'shared:name_is_wrong': '{name} is wrong.',
14
+
15
+ 'shared:login_success': 'Logged in.',
16
+ 'shared:login_failed': 'Login failed.',
17
+ 'shared:not_logged_in': 'Not logged in.',
18
+
19
+ 'shared:user_not_found': 'User not found.',
20
+ 'shared:user_locked': 'User locked.',
21
+
22
+ 'shared:not_found_file': 'File {fileName} is not found.',
23
+
24
+ 'shared:wrong_hash': 'Wrong hash.',
25
+ },
26
+ };
@@ -1,27 +1,27 @@
1
- import { OneLangProps } from './lang-props';
2
-
3
- export const apiLangZhCn: OneLangProps = {
4
- langName: 'zh-cn',
5
- langs: {
6
- 'shared:operation_success': '操作成功',
7
- 'shared:operation_error': '操作失败',
8
-
9
- 'shared:wrong_data': '数据错误',
10
- 'shared:permission_denied': '权限拒绝',
11
-
12
- 'shared:name_not_existed': '{name} 不存在',
13
- 'shared:name_not_set': '{name} 未设置',
14
- 'shared:name_is_wrong': '{name} 是错误的',
15
-
16
- 'shared:login_success': '登录成功',
17
- 'shared:login_failed': '登录失败',
18
- 'shared:not_logged_in': '未登录',
19
-
20
- 'shared:user_not_found': '用户未找到',
21
- 'shared:user_locked': '用户已封锁',
22
-
23
- 'shared:not_found_file': '文件 {fileName} 未找到',
24
-
25
- 'shared:wrong_hash': '错误的hash',
26
- },
27
- };
1
+ import { OneLangProps } from './lang-props';
2
+
3
+ export const apiLangZhCn: OneLangProps = {
4
+ langName: 'zh-cn',
5
+ langs: {
6
+ 'shared:operation_success': '操作成功',
7
+ 'shared:operation_error': '操作失败',
8
+
9
+ 'shared:wrong_data': '数据错误',
10
+ 'shared:permission_denied': '权限拒绝',
11
+
12
+ 'shared:name_not_existed': '{name} 不存在',
13
+ 'shared:name_not_set': '{name} 未设置',
14
+ 'shared:name_is_wrong': '{name} 是错误的',
15
+
16
+ 'shared:login_success': '登录成功',
17
+ 'shared:login_failed': '登录失败',
18
+ 'shared:not_logged_in': '未登录',
19
+
20
+ 'shared:user_not_found': '用户未找到',
21
+ 'shared:user_locked': '用户已封锁',
22
+
23
+ 'shared:not_found_file': '文件 {fileName} 未找到',
24
+
25
+ 'shared:wrong_hash': '错误的hash',
26
+ },
27
+ };
package/src/lang/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from './lang-helper';
2
- export * from './lang-props';
1
+ export * from './lang-helper';
2
+ export * from './lang-props';