underpost 2.8.878 → 2.8.882
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/.env.development +35 -3
- package/.env.production +40 -3
- package/.env.test +35 -3
- package/.github/workflows/release.cd.yml +3 -3
- package/README.md +20 -2
- package/bin/deploy.js +40 -0
- package/cli.md +3 -1
- package/conf.js +29 -3
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +6 -6
- package/package.json +1 -2
- package/src/api/document/document.controller.js +66 -0
- package/src/api/document/document.model.js +51 -0
- package/src/api/document/document.router.js +24 -0
- package/src/api/document/document.service.js +133 -0
- package/src/cli/deploy.js +1 -1
- package/src/cli/index.js +2 -0
- package/src/cli/repository.js +2 -0
- package/src/cli/run.js +27 -1
- package/src/client/Default.index.js +46 -1
- package/src/client/components/core/Account.js +8 -1
- package/src/client/components/core/AgGrid.js +18 -9
- package/src/client/components/core/Auth.js +258 -89
- package/src/client/components/core/BtnIcon.js +13 -3
- package/src/client/components/core/Content.js +2 -1
- package/src/client/components/core/CssCore.js +40 -27
- package/src/client/components/core/Docs.js +189 -88
- package/src/client/components/core/Input.js +34 -19
- package/src/client/components/core/LoadingAnimation.js +5 -10
- package/src/client/components/core/Modal.js +280 -123
- package/src/client/components/core/ObjectLayerEngine.js +470 -104
- package/src/client/components/core/ObjectLayerEngineModal.js +1 -0
- package/src/client/components/core/Panel.js +9 -2
- package/src/client/components/core/PanelForm.js +234 -76
- package/src/client/components/core/Router.js +15 -15
- package/src/client/components/core/ToolTip.js +83 -19
- package/src/client/components/core/Translate.js +1 -1
- package/src/client/components/core/VanillaJs.js +7 -3
- package/src/client/components/core/windowGetDimensions.js +202 -0
- package/src/client/components/default/MenuDefault.js +105 -41
- package/src/client/components/default/RoutesDefault.js +2 -0
- package/src/client/services/default/default.management.js +1 -0
- package/src/client/services/document/document.service.js +97 -0
- package/src/client/services/file/file.service.js +2 -0
- package/src/client/ssr/Render.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +2 -0
- package/src/client/ssr/head/Seo.js +1 -0
- package/src/index.js +1 -1
- package/src/mailer/EmailRender.js +1 -1
- package/src/server/auth.js +68 -17
- package/src/server/client-build.js +2 -3
- package/src/server/client-formatted.js +40 -12
- package/src/server/conf.js +5 -1
- package/src/server/crypto.js +195 -76
- package/src/server/object-layer.js +196 -0
- package/src/server/peer.js +47 -5
- package/src/server/process.js +85 -1
- package/src/server/runtime.js +23 -23
- package/src/server/ssr.js +52 -10
- package/src/server/valkey.js +89 -1
- package/test/crypto.test.js +117 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { loggerFactory } from '../../server/logger.js';
|
|
2
|
+
import { DataBaseProvider } from '../../db/DataBaseProvider.js';
|
|
3
|
+
import { DocumentDto } from './document.model.js';
|
|
4
|
+
import { uniqueArray } from '../../client/components/core/CommonJs.js';
|
|
5
|
+
import { getBearerToken, verifyJWT } from '../../server/auth.js';
|
|
6
|
+
import { isValidObjectId } from 'mongoose';
|
|
7
|
+
|
|
8
|
+
const logger = loggerFactory(import.meta);
|
|
9
|
+
|
|
10
|
+
const DocumentService = {
|
|
11
|
+
post: async (req, res, options) => {
|
|
12
|
+
/** @type {import('./document.model.js').DocumentModel} */
|
|
13
|
+
const Document = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.Document;
|
|
14
|
+
|
|
15
|
+
switch (req.params.id) {
|
|
16
|
+
default:
|
|
17
|
+
req.body.userId = req.auth.user._id;
|
|
18
|
+
return await new Document(req.body).save();
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
get: async (req, res, options) => {
|
|
22
|
+
/** @type {import('./document.model.js').DocumentModel} */
|
|
23
|
+
const Document = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.Document;
|
|
24
|
+
/** @type {import('../user/user.model.js').UserModel} */
|
|
25
|
+
const User = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.User;
|
|
26
|
+
|
|
27
|
+
if (req.path.startsWith('/public') && req.query['tags']) {
|
|
28
|
+
const publisherUsers = await User.find({ $or: [{ role: 'admin' }, { role: 'moderator' }] });
|
|
29
|
+
|
|
30
|
+
const token = getBearerToken(req);
|
|
31
|
+
let user;
|
|
32
|
+
if (token) user = verifyJWT(token, options);
|
|
33
|
+
|
|
34
|
+
const queryPayload = {
|
|
35
|
+
userId: {
|
|
36
|
+
$in: publisherUsers.map((p) => p._id).concat(user?.role && user.role !== 'guest' ? [user._id] : []),
|
|
37
|
+
},
|
|
38
|
+
tags: {
|
|
39
|
+
// $in: uniqueArray(['public'].concat(req.query['tags'].split(','))),
|
|
40
|
+
$all: uniqueArray(['public'].concat(req.query['tags'].split(','))),
|
|
41
|
+
},
|
|
42
|
+
...(req.query.cid
|
|
43
|
+
? {
|
|
44
|
+
_id: {
|
|
45
|
+
$in: req.query.cid.split(',').filter((cid) => isValidObjectId(cid)),
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
: undefined),
|
|
49
|
+
};
|
|
50
|
+
logger.info('queryPayload', queryPayload);
|
|
51
|
+
// sort in descending (-1) order by length
|
|
52
|
+
const sort = { createdAt: -1 };
|
|
53
|
+
const limit = req.query.limit ? parseInt(req.query.limit, 10) : 6;
|
|
54
|
+
const skip = req.query.skip ? parseInt(req.query.skip, 10) : 0;
|
|
55
|
+
|
|
56
|
+
const data = await Document.find(queryPayload)
|
|
57
|
+
.sort(sort)
|
|
58
|
+
.limit(limit)
|
|
59
|
+
.skip(skip)
|
|
60
|
+
.populate(DocumentDto.populate.file())
|
|
61
|
+
.populate(user && user.role !== 'guest' ? DocumentDto.populate.user() : null);
|
|
62
|
+
|
|
63
|
+
const lastDoc = await Document.findOne(queryPayload, '_id').sort({ createdAt: 1 });
|
|
64
|
+
const lastId = lastDoc ? lastDoc._id : null;
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
data,
|
|
68
|
+
lastId,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
switch (req.params.id) {
|
|
73
|
+
default:
|
|
74
|
+
return await Document.find({
|
|
75
|
+
userId: req.auth.user._id,
|
|
76
|
+
...(req.params.id ? { _id: req.params.id } : undefined),
|
|
77
|
+
}).populate(DocumentDto.populate.file());
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
delete: async (req, res, options) => {
|
|
81
|
+
/** @type {import('./document.model.js').DocumentModel} */
|
|
82
|
+
const Document = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.Document;
|
|
83
|
+
/** @type {import('../file/file.model.js').FileModel} */
|
|
84
|
+
const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
|
|
85
|
+
|
|
86
|
+
switch (req.params.id) {
|
|
87
|
+
default: {
|
|
88
|
+
const document = await Document.findOne({ _id: req.params.id });
|
|
89
|
+
if (!document) throw new Error('document not found');
|
|
90
|
+
|
|
91
|
+
if (document.userId.toString() !== req.auth.user._id) throw new Error('invalid user');
|
|
92
|
+
|
|
93
|
+
if (document.mdFileId) {
|
|
94
|
+
const file = await File.findOne({ _id: document.mdFileId });
|
|
95
|
+
if (file) await File.findByIdAndDelete(document.mdFileId);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (document.fileId) {
|
|
99
|
+
const file = await File.findOne({ _id: document.fileId });
|
|
100
|
+
if (file) await File.findByIdAndDelete(document.fileId);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return await Document.findByIdAndDelete(req.params.id);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
put: async (req, res, options) => {
|
|
108
|
+
/** @type {import('./document.model.js').DocumentModel} */
|
|
109
|
+
const Document = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.Document;
|
|
110
|
+
/** @type {import('../file/file.model.js').FileModel} */
|
|
111
|
+
const File = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.File;
|
|
112
|
+
|
|
113
|
+
switch (req.params.id) {
|
|
114
|
+
default: {
|
|
115
|
+
const document = await Document.findOne({ _id: req.params.id });
|
|
116
|
+
if (!document) throw new Error(`Document not found`);
|
|
117
|
+
|
|
118
|
+
if (document.mdFileId) {
|
|
119
|
+
const file = await File.findOne({ _id: document.mdFileId });
|
|
120
|
+
if (file) await File.findByIdAndDelete(document.mdFileId);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (document.fileId) {
|
|
124
|
+
const file = await File.findOne({ _id: document.fileId });
|
|
125
|
+
if (file) await File.findByIdAndDelete(document.fileId);
|
|
126
|
+
}
|
|
127
|
+
return await Document.findByIdAndUpdate(req.params.id, req.body);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export { DocumentService };
|
package/src/cli/deploy.js
CHANGED
|
@@ -334,7 +334,7 @@ EOF`);
|
|
|
334
334
|
if (!options.replicas) options.replicas = 1;
|
|
335
335
|
if (options.sync) UnderpostDeploy.API.sync(deployList, options);
|
|
336
336
|
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env, options);
|
|
337
|
-
if (options.infoRouter === true) {
|
|
337
|
+
if (options.infoRouter === true || options.buildManifest === true) {
|
|
338
338
|
logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
|
|
339
339
|
return;
|
|
340
340
|
}
|
package/src/cli/index.js
CHANGED
|
@@ -360,6 +360,8 @@ program
|
|
|
360
360
|
.option('--image-name <image-name>', 'Optional: Specifies the image name for test execution.')
|
|
361
361
|
.option('--container-name <container-name>', 'Optional: Specifies the container name for test execution.')
|
|
362
362
|
.option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
|
|
363
|
+
.option('--kubeadm', 'Flag to indicate Kubeadm cluster type context')
|
|
364
|
+
.option('--k3s', 'Flag to indicate K3s cluster type context')
|
|
363
365
|
.description('Runs a script from the specified path.')
|
|
364
366
|
.action(UnderpostRun.API.callback);
|
|
365
367
|
|
package/src/cli/repository.js
CHANGED
|
@@ -153,6 +153,8 @@ class UnderpostRepository {
|
|
|
153
153
|
if (fs.existsSync(privateRepoPath)) fs.removeSync(privateRepoPath);
|
|
154
154
|
shellExec(`cd .. && underpost clone ${process.env.GITHUB_USERNAME}/${privateRepoName}`);
|
|
155
155
|
shellExec(`cd ${privateRepoPath} && underpost pull . ${process.env.GITHUB_USERNAME}/${privateRepoName}`);
|
|
156
|
+
shellExec(`underpost run secret`);
|
|
157
|
+
shellExec(`underpost run underpost-config`);
|
|
156
158
|
const packageJsonDeploy = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/package.json`, 'utf8'));
|
|
157
159
|
const packageJsonEngine = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
|
|
158
160
|
if (packageJsonDeploy.version !== packageJsonEngine.version) {
|
package/src/cli/run.js
CHANGED
|
@@ -23,6 +23,8 @@ class UnderpostRun {
|
|
|
23
23
|
namespace: '',
|
|
24
24
|
build: false,
|
|
25
25
|
replicas: 1,
|
|
26
|
+
k3s: false,
|
|
27
|
+
kubeadm: false,
|
|
26
28
|
};
|
|
27
29
|
static RUNNERS = {
|
|
28
30
|
'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
@@ -253,7 +255,24 @@ class UnderpostRun {
|
|
|
253
255
|
},
|
|
254
256
|
'db-client': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
255
257
|
const { underpostRoot } = options;
|
|
258
|
+
|
|
259
|
+
const image = 'adminer:4.7.6-standalone';
|
|
260
|
+
|
|
261
|
+
if (!options.kubeadm && !options.k3s) {
|
|
262
|
+
// Only load if not kubeadm/k3s (Kind needs it)
|
|
263
|
+
shellExec(`docker pull ${image}`);
|
|
264
|
+
shellExec(`sudo kind load docker-image ${image}`);
|
|
265
|
+
} else if (options.kubeadm || options.k3s)
|
|
266
|
+
// For kubeadm/k3s, ensure it's available for containerd
|
|
267
|
+
shellExec(`sudo crictl pull ${image}`);
|
|
268
|
+
|
|
269
|
+
shellExec(`kubectl delete deployment adminer`);
|
|
256
270
|
shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/.`);
|
|
271
|
+
const successInstance = await UnderpostTest.API.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
|
|
272
|
+
|
|
273
|
+
if (successInstance) {
|
|
274
|
+
shellExec(`underpost deploy --expose adminer`);
|
|
275
|
+
}
|
|
257
276
|
},
|
|
258
277
|
promote: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
259
278
|
let [inputDeployId, inputEnv, inputReplicas] = path.split(',');
|
|
@@ -332,8 +351,15 @@ class UnderpostRun {
|
|
|
332
351
|
const checkStatusIterationMsDelay = 1000;
|
|
333
352
|
const iteratorTag = `[${deployId}-${env}-${targetTraffic}]`;
|
|
334
353
|
logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay });
|
|
354
|
+
const minReadyOk = 3;
|
|
355
|
+
let readyOk = 0;
|
|
335
356
|
|
|
336
|
-
while (
|
|
357
|
+
while (readyOk < minReadyOk) {
|
|
358
|
+
const ready = UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods).ready;
|
|
359
|
+
if (ready === true) {
|
|
360
|
+
readyOk++;
|
|
361
|
+
logger.info(`${iteratorTag} | Deployment ready. Verification number: ${readyOk}`);
|
|
362
|
+
}
|
|
337
363
|
await timer(checkStatusIterationMsDelay);
|
|
338
364
|
checkStatusIteration++;
|
|
339
365
|
logger.info(
|
|
@@ -16,6 +16,50 @@ import { SocketIo } from './components/core/SocketIo.js';
|
|
|
16
16
|
import { SocketIoDefault } from './components/default/SocketIoDefault.js';
|
|
17
17
|
import { ElementsDefault } from './components/default/ElementsDefault.js';
|
|
18
18
|
import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
|
|
19
|
+
import { EventsUI } from './components/core/EventsUI.js';
|
|
20
|
+
import { Modal } from './components/core/Modal.js';
|
|
21
|
+
|
|
22
|
+
const htmlMainBody = async () => {
|
|
23
|
+
setTimeout(() => {
|
|
24
|
+
EventsUI.onClick('.get-started-button', (e) => {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
location.href = `https://www.nexodev.org/docs/?cid=src`;
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
return html`
|
|
30
|
+
<div class="landing-container">
|
|
31
|
+
<div class="content-wrapper">
|
|
32
|
+
<h1 class="animated-text">
|
|
33
|
+
<span class="greeting">Hello, World!</span>
|
|
34
|
+
<span class="subtitle">Welcome to Our Platform</span>
|
|
35
|
+
</h1>
|
|
36
|
+
|
|
37
|
+
<div class="features">
|
|
38
|
+
<div class="feature-card">
|
|
39
|
+
<i class="icon">🚀</i>
|
|
40
|
+
<h3>Fast & Reliable</h3>
|
|
41
|
+
<p>Lightning-fast performance with 99.9% uptime</p>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="feature-card">
|
|
44
|
+
<i class="icon">🎨</i>
|
|
45
|
+
<h3>Beautiful UI</h3>
|
|
46
|
+
<p>Modern and intuitive user interface</p>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="feature-card">
|
|
49
|
+
<i class="icon">⚡</i>
|
|
50
|
+
<h3>Powerful Features</h3>
|
|
51
|
+
<p>Everything you need in one place</p>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<button class="cta-button get-started-button">
|
|
56
|
+
Get Started
|
|
57
|
+
<span class="button-icon">→</span>
|
|
58
|
+
</button>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
`;
|
|
62
|
+
};
|
|
19
63
|
|
|
20
64
|
window.onload = () =>
|
|
21
65
|
Worker.instance({
|
|
@@ -25,7 +69,7 @@ window.onload = () =>
|
|
|
25
69
|
await TranslateCore.Init();
|
|
26
70
|
await TranslateDefault.Init();
|
|
27
71
|
await Responsive.Init();
|
|
28
|
-
await MenuDefault.Render();
|
|
72
|
+
await MenuDefault.Render({ htmlMainBody });
|
|
29
73
|
await SocketIo.Init({
|
|
30
74
|
channels: ElementsDefault.Data,
|
|
31
75
|
path: `/`,
|
|
@@ -35,5 +79,6 @@ window.onload = () =>
|
|
|
35
79
|
await LogOutDefault();
|
|
36
80
|
await SignUpDefault();
|
|
37
81
|
await Keyboard.Init({ callBackTime: DefaultParams.EVENT_CALLBACK_TIME });
|
|
82
|
+
await Modal.RenderSeoSanitizer();
|
|
38
83
|
},
|
|
39
84
|
});
|
|
@@ -195,7 +195,14 @@ const Account = {
|
|
|
195
195
|
await this.instanceModalUiEvents({ user });
|
|
196
196
|
});
|
|
197
197
|
return html`
|
|
198
|
-
<
|
|
198
|
+
<label for="account-profile-image-input-label"
|
|
199
|
+
><span class="hide">Profile Image</span>
|
|
200
|
+
<input
|
|
201
|
+
type="file"
|
|
202
|
+
accept="${profileFileAccept.join(', ')}"
|
|
203
|
+
class="account-profile-image-input hide"
|
|
204
|
+
id="account-profile-image-input-label"
|
|
205
|
+
/></label>
|
|
199
206
|
${renderWave({ id: waveAnimationId })}
|
|
200
207
|
|
|
201
208
|
<form class="in">
|
|
@@ -5,6 +5,7 @@ import { ThemeEvents, darkTheme } from './Css.js';
|
|
|
5
5
|
import { append, htmls, s } from './VanillaJs.js';
|
|
6
6
|
import { getProxyPath } from './Router.js';
|
|
7
7
|
import './Pagination.js';
|
|
8
|
+
import { Modal } from './Modal.js';
|
|
8
9
|
|
|
9
10
|
const AgGrid = {
|
|
10
11
|
grids: {},
|
|
@@ -57,18 +58,26 @@ const AgGrid = {
|
|
|
57
58
|
delete ThemeEvents[id];
|
|
58
59
|
}
|
|
59
60
|
};
|
|
61
|
+
|
|
62
|
+
if (!options.style || !options.style.height) {
|
|
63
|
+
if (options.parentModal && Modal.Data[options.parentModal].options.observer) {
|
|
64
|
+
Modal.Data[options.parentModal].onObserverListener[id + '-observer'] = ({ width, height }) => {
|
|
65
|
+
if (s(`.${id}`)) s(`.${id}`).style.height = `${height - 180}px`;
|
|
66
|
+
else delete Modal.Data[options.parentModal].onObserverListener[id + '-observer'];
|
|
67
|
+
};
|
|
68
|
+
s(`.${id}`).style.height = `${s(`.${options.parentModal}`).offsetHeight - 180}px`;
|
|
69
|
+
} else s(`.${id}`).style.height = '500px';
|
|
70
|
+
}
|
|
60
71
|
});
|
|
61
72
|
const usePagination = options?.usePagination;
|
|
62
73
|
return html`
|
|
63
|
-
<div
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
style
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
${usePagination ? `<ag-pagination id="ag-pagination-${id}"></ag-pagination>` : ''}
|
|
71
|
-
</div>
|
|
74
|
+
<div
|
|
75
|
+
class="${id} ${this.theme}${options?.darkTheme ? `-dark` : ''}"
|
|
76
|
+
style="${options?.style
|
|
77
|
+
? Object.keys(options.style).map((styleKey) => `${styleKey}: ${options.style[styleKey]}; `)
|
|
78
|
+
: ''}"
|
|
79
|
+
></div>
|
|
80
|
+
${usePagination ? `<ag-pagination id="ag-pagination-${id}"></ag-pagination>` : ''}
|
|
72
81
|
`;
|
|
73
82
|
},
|
|
74
83
|
RenderStyle: async function (
|