@underpostnet/underpost 2.7.94 → 2.8.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.
- package/.vscode/settings.json +5 -1
- package/bin/deploy.js +41 -16
- package/bin/index.js +4 -5
- package/bin/util.js +18 -0
- package/conf.js +8 -1
- package/docker-compose.yml +1 -1
- package/package.json +11 -8
- package/src/api/user/user.model.js +1 -1
- package/src/api/user/user.service.js +22 -21
- package/src/client/components/core/Account.js +144 -124
- package/src/client/components/core/Auth.js +94 -1
- package/src/client/components/core/Docs.js +2 -1
- package/src/client/components/core/JoyStick.js +8 -5
- package/src/client/components/core/LogIn.js +8 -1
- package/src/client/components/core/LogOut.js +3 -2
- package/src/client/components/core/Modal.js +14 -9
- package/src/client/components/core/Panel.js +17 -3
- package/src/client/components/core/PanelForm.js +8 -1
- package/src/client/components/core/SignUp.js +3 -3
- package/src/client/components/core/SocketIo.js +2 -0
- package/src/client/components/core/Translate.js +14 -0
- package/src/client/components/core/Validator.js +9 -2
- package/src/client/components/core/VanillaJs.js +4 -1
- package/src/client/components/default/LogInDefault.js +2 -23
- package/src/client/components/default/LogOutDefault.js +3 -5
- package/src/client/public/default/plantuml/client-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-schema.svg +1 -1
- package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
- package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
- package/src/client/services/core/core.service.js +2 -0
- package/src/client/services/user/user.service.js +9 -1
- package/src/client/ssr/body/CacheControl.js +2 -1
- package/src/client/ssr/body/DefaultSplashScreen.js +3 -3
- package/src/client/ssr/offline/Maintenance.js +63 -0
- package/src/client/sw/default.sw.js +31 -5
- package/src/index.js +8 -0
- package/src/server/client-build.js +27 -25
- package/src/server/client-icons.js +13 -3
- package/src/server/conf.js +5 -4
- package/src/server/logger.js +8 -6
- package/src/server/network.js +4 -0
- package/src/server/ssl.js +2 -2
- package/src/server/valkey.js +126 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const s = (el) => document.querySelector(el);
|
|
2
|
+
|
|
3
|
+
const append = (el, html) => s(el).insertAdjacentHTML('beforeend', html);
|
|
4
|
+
|
|
5
|
+
const getLang = () =>
|
|
6
|
+
(localStorage.getItem('lang') || navigator.language || navigator.userLanguage || s('html').lang)
|
|
7
|
+
.slice(0, 2)
|
|
8
|
+
.toLowerCase();
|
|
9
|
+
|
|
10
|
+
const main = () => {
|
|
11
|
+
const Translate = {
|
|
12
|
+
Data: {
|
|
13
|
+
['server-maintenance']: {
|
|
14
|
+
en: "The server is under maintenance <br> we'll be back soon.",
|
|
15
|
+
es: 'El servidor está en mantenimiento <br> volveremos pronto.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
Render: function (id) {
|
|
19
|
+
return this.Data[id][getLang()] ? this.Data[id][getLang()] : this.Data[id]['en'];
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const icon = html`<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 24 24">
|
|
23
|
+
<path
|
|
24
|
+
fill="none"
|
|
25
|
+
stroke="currentColor"
|
|
26
|
+
stroke-linecap="round"
|
|
27
|
+
stroke-linejoin="round"
|
|
28
|
+
stroke-width="2"
|
|
29
|
+
d="M3 7a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm9 13H6a3 3 0 0 1-3-3v-2a3 3 0 0 1 3-3h10.5m-.5 6a2 2 0 1 0 4 0a2 2 0 1 0-4 0m2-3.5V16m0 4v1.5m3.032-5.25l-1.299.75m-3.463 2l-1.3.75m0-3.5l1.3.75m3.463 2l1.3.75M7 8v.01M7 16v.01"
|
|
30
|
+
/>
|
|
31
|
+
</svg>`;
|
|
32
|
+
|
|
33
|
+
append(
|
|
34
|
+
'body',
|
|
35
|
+
html` <style>
|
|
36
|
+
body {
|
|
37
|
+
font-family: arial;
|
|
38
|
+
font-size: 20px;
|
|
39
|
+
background-color: #d8d8d8;
|
|
40
|
+
color: #333;
|
|
41
|
+
}
|
|
42
|
+
a {
|
|
43
|
+
color: black;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
|
|
47
|
+
<div class="abs center" style="top: 45%">
|
|
48
|
+
${icon}
|
|
49
|
+
<br />
|
|
50
|
+
<br />${Translate.Render('server-maintenance')}
|
|
51
|
+
</div>`,
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
SrrComponent = () => html`<script>
|
|
56
|
+
{
|
|
57
|
+
const s = ${s};
|
|
58
|
+
const append = ${append};
|
|
59
|
+
const getLang = ${getLang};
|
|
60
|
+
const main = ${main};
|
|
61
|
+
window.onload = main;
|
|
62
|
+
}
|
|
63
|
+
</script>`;
|
|
@@ -62,12 +62,38 @@ self.addEventListener('fetch', (event) => {
|
|
|
62
62
|
if (!preCachedResponse) throw new Error(error.message);
|
|
63
63
|
return preCachedResponse;
|
|
64
64
|
} catch (error) {
|
|
65
|
-
console.error('Error opening cache for pre cached page',
|
|
65
|
+
console.error('Error opening cache for pre cached page', {
|
|
66
|
+
url: event.request.url,
|
|
67
|
+
error,
|
|
68
|
+
onLine: navigator.onLine,
|
|
69
|
+
});
|
|
66
70
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
if (!navigator.onLine) {
|
|
72
|
+
if (event.request.method.toUpperCase() === 'GET') {
|
|
73
|
+
const cache = await caches.open(CACHE_NAME);
|
|
74
|
+
const preCachedResponse = await cache.match(
|
|
75
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/offline/index.html`,
|
|
76
|
+
);
|
|
77
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
78
|
+
return preCachedResponse;
|
|
79
|
+
}
|
|
80
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'offline test response' }));
|
|
81
|
+
// response.status = 200;
|
|
82
|
+
response.headers.set('Content-Type', 'application/json');
|
|
83
|
+
return response;
|
|
84
|
+
}
|
|
85
|
+
if (event.request.method.toUpperCase() === 'GET') {
|
|
86
|
+
const cache = await caches.open(CACHE_NAME);
|
|
87
|
+
const preCachedResponse = await cache.match(
|
|
88
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/maintenance/index.html`,
|
|
89
|
+
);
|
|
90
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
91
|
+
return preCachedResponse;
|
|
92
|
+
}
|
|
93
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'server in maintenance' }));
|
|
94
|
+
// response.status = 200;
|
|
95
|
+
response.headers.set('Content-Type', 'application/json');
|
|
96
|
+
return response;
|
|
71
97
|
} catch (error) {
|
|
72
98
|
console.error('Error opening cache for offline page', event.request.url, error);
|
|
73
99
|
const response = new Response(JSON.stringify({ status: 'error', message: error.message }));
|
package/src/index.js
CHANGED
|
@@ -14,6 +14,14 @@ const logger = loggerFactory(import.meta);
|
|
|
14
14
|
* @memberof Underpost
|
|
15
15
|
*/
|
|
16
16
|
class Underpost {
|
|
17
|
+
/**
|
|
18
|
+
* Underpost engine version
|
|
19
|
+
* @static
|
|
20
|
+
* @type {String}
|
|
21
|
+
* @memberof Underpost
|
|
22
|
+
*/
|
|
23
|
+
static version = 'v2.8.1';
|
|
24
|
+
|
|
17
25
|
constructor() {}
|
|
18
26
|
|
|
19
27
|
/**
|
|
@@ -465,10 +465,11 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
465
465
|
case 'DefaultSplashScreen':
|
|
466
466
|
if (backgroundImage) {
|
|
467
467
|
ssrHeadComponents += SrrComponent({
|
|
468
|
-
|
|
469
|
-
.readFileSync(backgroundImage)
|
|
470
|
-
.toString('base64')}`,
|
|
468
|
+
backgroundImage: (path === '/' ? path : `${path}/`) + backgroundImage,
|
|
471
469
|
});
|
|
470
|
+
// `data:image/${backgroundImage.split('.').pop()};base64,${fs
|
|
471
|
+
// .readFileSync()
|
|
472
|
+
// .toString('base64')}`,
|
|
472
473
|
break;
|
|
473
474
|
} else {
|
|
474
475
|
ssrHeadComponents += SrrComponent({ metadata });
|
|
@@ -480,7 +481,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
480
481
|
bgColor: metadata?.themeColor ? metadata.themeColor : '#ececec',
|
|
481
482
|
});
|
|
482
483
|
ssrHeadComponents += SrrComponent({
|
|
483
|
-
|
|
484
|
+
backgroundImage: `data:image/png;base64,${bufferBackgroundImage.toString('base64')}`,
|
|
484
485
|
});
|
|
485
486
|
}
|
|
486
487
|
|
|
@@ -700,28 +701,7 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
700
701
|
|
|
701
702
|
await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
|
|
702
703
|
}
|
|
703
|
-
if (!enableLiveRebuild && process.argv.includes('zip')) {
|
|
704
|
-
logger.warn('build zip', rootClientPath);
|
|
705
|
-
|
|
706
|
-
if (!fs.existsSync('./build')) fs.mkdirSync('./build');
|
|
707
|
-
|
|
708
|
-
const zip = new AdmZip();
|
|
709
|
-
const files = await fs.readdir(rootClientPath, { recursive: true });
|
|
710
|
-
|
|
711
|
-
for (const relativePath of files) {
|
|
712
|
-
const filePath = dir.resolve(`${rootClientPath}/${relativePath}`);
|
|
713
|
-
if (!fs.lstatSync(filePath).isDirectory()) {
|
|
714
|
-
const folder = dir.relative(`public/${host}${path}`, dir.dirname(filePath));
|
|
715
|
-
zip.addLocalFile(filePath, folder);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
const buildId = `${host}-${path.replaceAll('/', '')}`;
|
|
720
704
|
|
|
721
|
-
logger.warn('write zip', `./build/${buildId}.zip`);
|
|
722
|
-
|
|
723
|
-
zip.writeZip(`./build/${buildId}.zip`);
|
|
724
|
-
}
|
|
725
705
|
if (client) {
|
|
726
706
|
let PRE_CACHED_RESOURCES = [];
|
|
727
707
|
|
|
@@ -792,6 +772,28 @@ root file where the route starts, such as index.js, app.js, routes.js, etc ... *
|
|
|
792
772
|
);
|
|
793
773
|
}
|
|
794
774
|
}
|
|
775
|
+
if (!enableLiveRebuild && process.argv.includes('zip')) {
|
|
776
|
+
logger.warn('build zip', rootClientPath);
|
|
777
|
+
|
|
778
|
+
if (!fs.existsSync('./build')) fs.mkdirSync('./build');
|
|
779
|
+
|
|
780
|
+
const zip = new AdmZip();
|
|
781
|
+
const files = await fs.readdir(rootClientPath, { recursive: true });
|
|
782
|
+
|
|
783
|
+
for (const relativePath of files) {
|
|
784
|
+
const filePath = dir.resolve(`${rootClientPath}/${relativePath}`);
|
|
785
|
+
if (!fs.lstatSync(filePath).isDirectory()) {
|
|
786
|
+
const folder = dir.relative(`public/${host}${path}`, dir.dirname(filePath));
|
|
787
|
+
zip.addLocalFile(filePath, folder);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
const buildId = `${host}-${path.replaceAll('/', '')}`;
|
|
792
|
+
|
|
793
|
+
logger.warn('write zip', `./build/${buildId}.zip`);
|
|
794
|
+
|
|
795
|
+
zip.writeZip(`./build/${buildId}.zip`);
|
|
796
|
+
}
|
|
795
797
|
}
|
|
796
798
|
}
|
|
797
799
|
};
|
|
@@ -3,8 +3,9 @@ import { favicons } from 'favicons';
|
|
|
3
3
|
// import textToImage from 'text-to-image';
|
|
4
4
|
import { loggerFactory } from './logger.js';
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
|
-
import { png3x } from 'font-awesome-assets';
|
|
7
6
|
import { getCapVariableName, s4 } from '../client/components/core/CommonJs.js';
|
|
7
|
+
import { FileFactory } from '../api/file/file.service.js';
|
|
8
|
+
import { svg, png, png3x } from 'font-awesome-assets';
|
|
8
9
|
|
|
9
10
|
const logger = loggerFactory(import.meta);
|
|
10
11
|
|
|
@@ -140,7 +141,7 @@ const buildIcons = async ({
|
|
|
140
141
|
for (const file of response.files)
|
|
141
142
|
fs.writeFileSync(`./src/client/public/${publicClientId}/${file.name}`, file.contents, 'utf8');
|
|
142
143
|
|
|
143
|
-
const ssrPath = `./src/client/ssr/
|
|
144
|
+
const ssrPath = `./src/client/ssr/head/Pwa${getCapVariableName(publicClientId)}.js`;
|
|
144
145
|
if (!fs.existsSync(ssrPath))
|
|
145
146
|
fs.writeFileSync(ssrPath, 'SrrComponent = () => html`' + response.html.join(`\n`) + '`;', 'utf8');
|
|
146
147
|
} catch (error) {
|
|
@@ -148,4 +149,13 @@ const buildIcons = async ({
|
|
|
148
149
|
}
|
|
149
150
|
};
|
|
150
151
|
|
|
151
|
-
|
|
152
|
+
const getDefaultProfileImageId = async (File) => {
|
|
153
|
+
const faId = 'user';
|
|
154
|
+
const tmpFilePath = `./tmp/${faId}-${s4() + s4()}.svg`;
|
|
155
|
+
fs.writeFileSync(tmpFilePath, svg(faId, '#f5f5f5d1'), 'utf8');
|
|
156
|
+
const file = await new File(FileFactory.svg(fs.readFileSync(tmpFilePath), `${faId}.svg`)).save();
|
|
157
|
+
fs.removeSync(tmpFilePath);
|
|
158
|
+
return file._id;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export { buildIcons, buildTextImg, defaultBaseTextImgOptions, faBase64Png, getBufferPngText, getDefaultProfileImageId };
|
package/src/server/conf.js
CHANGED
|
@@ -253,8 +253,8 @@ const buildClientSrc = async (
|
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
fs.writeFileSync(
|
|
256
|
-
`./src/client/ssr/
|
|
257
|
-
formattedSrc(fs.readFileSync(`./src/client/ssr/
|
|
256
|
+
`./src/client/ssr/head/${toClientVariableName}Scripts.js`,
|
|
257
|
+
formattedSrc(fs.readFileSync(`./src/client/ssr/head/${fromClientVariableName}Scripts.js`, 'utf8')),
|
|
258
258
|
'utf8',
|
|
259
259
|
);
|
|
260
260
|
|
|
@@ -473,7 +473,7 @@ const buildProxyRouter = () => {
|
|
|
473
473
|
title: 'Site in maintenance',
|
|
474
474
|
ssrPath: '/',
|
|
475
475
|
ssrHeadComponents: '',
|
|
476
|
-
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/
|
|
476
|
+
ssrBodyComponents: (await ssrFactory(`./src/client/ssr/offline/Maintenance.js`))(),
|
|
477
477
|
});
|
|
478
478
|
})();
|
|
479
479
|
|
|
@@ -583,7 +583,7 @@ const validateTemplatePath = (absolutePath = '') => {
|
|
|
583
583
|
const confServer = DefaultConf.server[host][path];
|
|
584
584
|
const confClient = DefaultConf.client[client];
|
|
585
585
|
const confSsr = DefaultConf.ssr[ssr];
|
|
586
|
-
const clients = Object.keys(confClient).concat(['core', 'test', 'default']);
|
|
586
|
+
const clients = Object.keys(confClient).concat(['core', 'test', 'default', 'user']);
|
|
587
587
|
|
|
588
588
|
if (absolutePath.match('src/api') && !confServer.apis.find((p) => absolutePath.match(`src/api/${p}/`))) {
|
|
589
589
|
return false;
|
|
@@ -935,6 +935,7 @@ const maintenanceMiddleware = (req, res, port, proxyRouter) => {
|
|
|
935
935
|
|
|
936
936
|
const setUpProxyMaintenanceServer = ({ deployGroupId }) => {
|
|
937
937
|
shellExec(`pm2 kill`);
|
|
938
|
+
shellExec(`node bin/deploy valkey-service`);
|
|
938
939
|
const proxyDeployId = fs.readFileSync(`./engine-private/deploy/${deployGroupId}.proxy`, 'utf8').trim();
|
|
939
940
|
shellExec(`node bin/deploy conf ${proxyDeployId} production`);
|
|
940
941
|
shellExec(`node bin/deploy run ${proxyDeployId} maintenance`);
|
package/src/server/logger.js
CHANGED
|
@@ -86,6 +86,7 @@ const format = (meta) =>
|
|
|
86
86
|
* @memberof Logger
|
|
87
87
|
*/
|
|
88
88
|
const setUpInfo = async (logger = new winston.Logger()) => {
|
|
89
|
+
logger.info('npm_package_version', process.env.npm_package_version);
|
|
89
90
|
logger.info('argv', process.argv);
|
|
90
91
|
logger.info('platform', process.platform);
|
|
91
92
|
logger.info('env', process.env.NODE_ENV);
|
|
@@ -179,12 +180,13 @@ const loggerMiddleware = (meta = { url: '' }) => {
|
|
|
179
180
|
};
|
|
180
181
|
|
|
181
182
|
const underpostASCI = () => `
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
183
|
+
|
|
184
|
+
██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░██████╗░░█████╗░░██████╗████████╗
|
|
185
|
+
██║░░░██║████╗░██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝
|
|
186
|
+
██║░░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██████╔╝██║░░██║╚█████╗░░░░██║░░░
|
|
187
|
+
██║░░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██╔═══╝░██║░░██║░╚═══██╗░░░██║░░░
|
|
188
|
+
╚██████╔╝██║░╚███║██████╔╝███████╗██║░░██║██║░░░░░╚█████╔╝██████╔╝░░░██║░░░
|
|
189
|
+
░╚═════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚═╝░░░░░░╚════╝░╚═════╝░░░░╚═╝░░░
|
|
188
190
|
`;
|
|
189
191
|
|
|
190
192
|
export { loggerFactory, loggerMiddleware, setUpInfo, underpostASCI };
|
package/src/server/network.js
CHANGED
|
@@ -74,6 +74,10 @@ const saveRuntimeRouter = async () => {
|
|
|
74
74
|
const host = process.env.DEFAULT_DEPLOY_HOST;
|
|
75
75
|
const path = process.env.DEFAULT_DEPLOY_PATH;
|
|
76
76
|
const confServerPath = `./engine-private/conf/${deployId}/conf.server.json`;
|
|
77
|
+
if (!deployId || !host || !path) {
|
|
78
|
+
logger.warn('default deploy instance not found');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
77
81
|
const confServer = JSON.parse(fs.readFileSync(confServerPath, 'utf8'));
|
|
78
82
|
const { db } = confServer[host][path];
|
|
79
83
|
|
package/src/server/ssl.js
CHANGED
|
@@ -50,8 +50,8 @@ const buildSSL = async (host) => {
|
|
|
50
50
|
|
|
51
51
|
fs.writeFileSync(`./engine-private/ssl/${host}/_ca_bundle.crt`, ca, 'utf8');
|
|
52
52
|
fs.writeFileSync(`./engine-private/ssl/${host}/_ca_full_bundle.crt`, caFull, 'utf8');
|
|
53
|
-
|
|
54
|
-
fs.removeSync(`${sslPath}/${folderHost}`);
|
|
53
|
+
// TODO: no repeat folderHost match
|
|
54
|
+
// fs.removeSync(`${sslPath}/${folderHost}`);
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import Valkey from 'iovalkey';
|
|
2
|
+
import mongoose from 'mongoose';
|
|
3
|
+
import { hashPassword } from './auth.js';
|
|
4
|
+
import { loggerFactory } from './logger.js';
|
|
5
|
+
|
|
6
|
+
const logger = loggerFactory(import.meta);
|
|
7
|
+
|
|
8
|
+
let valkeyEnabled = true;
|
|
9
|
+
|
|
10
|
+
const disableValkeyErrorMessage = 'valkey is not enabled';
|
|
11
|
+
|
|
12
|
+
const isValkeyEnable = () => valkeyEnabled;
|
|
13
|
+
|
|
14
|
+
const selectDtoFactory = (payload, select) => {
|
|
15
|
+
const result = {};
|
|
16
|
+
for (const key of Object.keys(select)) {
|
|
17
|
+
if (select[key] === 1 && key in payload) result[key] = payload[key];
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const valkeyClientFactory = async () => {
|
|
23
|
+
const valkey = new Valkey({
|
|
24
|
+
retryStrategy: (attempt) => {
|
|
25
|
+
if (attempt === 1) {
|
|
26
|
+
valkey.disconnect();
|
|
27
|
+
valkeyEnabled = false;
|
|
28
|
+
logger.warn('Valkey service not enabled', { valkeyEnabled });
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
return 1000; // 1 second interval attempt
|
|
32
|
+
},
|
|
33
|
+
}); // Connect to 127.0.0.1:6379
|
|
34
|
+
// new Valkey(6380); // 127.0.0.1:6380
|
|
35
|
+
// new Valkey(6379, '192.168.1.1'); // 192.168.1.1:6379
|
|
36
|
+
// new Valkey('/tmp/redis.sock');
|
|
37
|
+
// new Valkey({
|
|
38
|
+
// port: 6379, // Valkey port
|
|
39
|
+
// host: '127.0.0.1', // Valkey host
|
|
40
|
+
// username: 'default', // needs Valkey >= 6
|
|
41
|
+
// password: 'my-top-secret',
|
|
42
|
+
// db: 0, // Defaults to 0
|
|
43
|
+
// });
|
|
44
|
+
return valkey;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const getValkeyObject = async (key = '') => {
|
|
48
|
+
if (!valkeyEnabled) {
|
|
49
|
+
logger.warn(disableValkeyErrorMessage + ' get', key);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const object = await valkey.get(key);
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(object);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
logger.error(error);
|
|
57
|
+
return object;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const setValkeyObject = async (key = '', payload = {}) => {
|
|
62
|
+
if (!valkeyEnabled) throw new Error(disableValkeyErrorMessage);
|
|
63
|
+
return await valkey.set(key, JSON.stringify(payload));
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const updateValkeyObject = async (key = '', payload = {}) => {
|
|
67
|
+
if (!valkeyEnabled) throw new Error(disableValkeyErrorMessage);
|
|
68
|
+
const object = await getValkeyObject(key, valkey);
|
|
69
|
+
object.updatedAt = new Date().toISOString();
|
|
70
|
+
return await valkey.set(key, JSON.stringify({ ...object, ...payload }));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const valkeyObjectFactory = async (module = '', options = { host: 'localhost', object: {} }) => {
|
|
74
|
+
if (!valkeyEnabled) throw new Error(disableValkeyErrorMessage);
|
|
75
|
+
const idoDate = new Date().toISOString();
|
|
76
|
+
options.object = options.object || {};
|
|
77
|
+
const { object } = options;
|
|
78
|
+
const _id = new mongoose.Types.ObjectId().toString();
|
|
79
|
+
object._id = _id;
|
|
80
|
+
object.createdAt = idoDate;
|
|
81
|
+
object.updatedAt = idoDate;
|
|
82
|
+
switch (module) {
|
|
83
|
+
case 'user': {
|
|
84
|
+
const role = 'guest';
|
|
85
|
+
object._id = `${role}${_id}`;
|
|
86
|
+
return {
|
|
87
|
+
...object,
|
|
88
|
+
username: `${role}${_id.slice(-5)}`,
|
|
89
|
+
email: `${_id}@${options.host}`,
|
|
90
|
+
password: hashPassword(process.env.JWT_SECRET),
|
|
91
|
+
role,
|
|
92
|
+
failedLoginAttempts: 0,
|
|
93
|
+
phoneNumbers: [],
|
|
94
|
+
publicKey: [],
|
|
95
|
+
profileImageId: null,
|
|
96
|
+
emailConfirmed: false,
|
|
97
|
+
recoverTimeOut: null,
|
|
98
|
+
lastLoginDate: null,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`module schema not found: ${module}`);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const ValkeyAPI = {
|
|
107
|
+
valkeyClientFactory,
|
|
108
|
+
selectDtoFactory,
|
|
109
|
+
getValkeyObject,
|
|
110
|
+
setValkeyObject,
|
|
111
|
+
valkeyObjectFactory,
|
|
112
|
+
updateValkeyObject,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const valkey = await ValkeyAPI.valkeyClientFactory();
|
|
116
|
+
|
|
117
|
+
export {
|
|
118
|
+
valkeyClientFactory,
|
|
119
|
+
selectDtoFactory,
|
|
120
|
+
getValkeyObject,
|
|
121
|
+
setValkeyObject,
|
|
122
|
+
valkeyObjectFactory,
|
|
123
|
+
updateValkeyObject,
|
|
124
|
+
isValkeyEnable,
|
|
125
|
+
ValkeyAPI,
|
|
126
|
+
};
|