underpost 3.1.2 → 3.2.0
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.example +0 -2
- package/.github/workflows/ghpkg.ci.yml +4 -4
- package/.github/workflows/npmpkg.ci.yml +38 -7
- package/.github/workflows/pwa-microservices-template-page.cd.yml +3 -4
- package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
- package/.github/workflows/release.cd.yml +4 -4
- package/CHANGELOG.md +365 -1
- package/CLI-HELP.md +55 -3
- package/README.md +7 -3
- package/bin/build.js +18 -12
- package/bin/deploy.js +205 -225
- package/bin/file.js +3 -0
- package/conf.js +4 -10
- package/jsdoc.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +72 -50
- package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +21 -14
- package/scripts/ports-ls.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/file/file.ref.json +18 -0
- package/src/api/user/user.service.js +8 -7
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +76 -242
- package/src/cli/deploy.js +104 -65
- package/src/cli/env.js +1 -0
- package/src/cli/fs.js +2 -1
- package/src/cli/index.js +50 -1
- package/src/cli/kubectl.js +211 -0
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +328 -112
- package/src/cli/run.js +283 -69
- package/src/cli/test.js +3 -3
- package/src/client/Default.index.js +3 -4
- package/src/client/components/core/Alert.js +2 -2
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/Docs.js +9 -2
- package/src/client/components/core/DropDown.js +129 -17
- package/src/client/components/core/Keyboard.js +2 -2
- package/src/client/components/core/LogIn.js +2 -2
- package/src/client/components/core/LogOut.js +2 -2
- package/src/client/components/core/Modal.js +0 -1
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- package/src/client/components/core/RichText.js +1 -2
- package/src/client/components/core/SocketIo.js +82 -29
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/LogInDefault.js +3 -3
- package/src/client/components/default/LogOutDefault.js +2 -2
- package/src/client/components/default/MenuDefault.js +5 -5
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/services/core/core.service.js +20 -8
- package/src/client/services/user/user.management.js +2 -2
- package/src/client/ssr/body/404.js +15 -11
- package/src/client/ssr/body/500.js +15 -11
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
- package/src/client/ssr/pages/Test.js +11 -10
- package/src/index.js +24 -1
- package/src/runtime/express/Express.js +26 -9
- package/src/runtime/lampp/Dockerfile +9 -2
- package/src/runtime/lampp/Lampp.js +4 -3
- package/src/runtime/wp/Dockerfile +64 -0
- package/src/runtime/wp/Wp.js +497 -0
- package/src/server/auth.js +30 -6
- package/src/server/backup.js +19 -1
- package/src/server/client-build-docs.js +51 -110
- package/src/server/client-build.js +55 -64
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +19 -15
- package/src/server/ipfs-client.js +24 -1
- package/src/server/peer.js +8 -0
- package/src/server/runtime.js +25 -1
- package/src/server/start.js +21 -8
- package/src/ws/IoInterface.js +1 -10
- package/src/ws/IoServer.js +14 -33
- package/src/ws/core/channels/core.ws.chat.js +65 -20
- package/src/ws/core/channels/core.ws.mailer.js +113 -32
- package/src/ws/core/channels/core.ws.stream.js +90 -31
- package/src/ws/core/core.ws.connection.js +12 -33
- package/src/ws/core/core.ws.emit.js +10 -26
- package/src/ws/core/core.ws.server.js +25 -58
- package/src/ws/default/channels/default.ws.main.js +53 -12
- package/src/ws/default/default.ws.connection.js +26 -13
- package/src/ws/default/default.ws.server.js +30 -12
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/ws/core/management/core.ws.chat.js +0 -8
- package/src/ws/core/management/core.ws.mailer.js +0 -16
- package/src/ws/core/management/core.ws.stream.js +0 -8
- package/src/ws/default/management/default.ws.main.js +0 -8
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared factory for app-specific WebSocket event handlers.
|
|
3
|
+
* Eliminates duplication across per-app SocketIo*.js modules by providing
|
|
4
|
+
* common channel event handling (chat, email-confirmed, etc.).
|
|
5
|
+
*
|
|
6
|
+
* @module client/core/SocketIoHandler
|
|
7
|
+
* @namespace SocketIoHandlerProvider
|
|
8
|
+
*/
|
|
9
|
+
import { Account } from './Account.js';
|
|
10
|
+
import { Chat } from './Chat.js';
|
|
11
|
+
import { s4 } from './CommonJs.js';
|
|
12
|
+
import { loggerFactory } from './Logger.js';
|
|
13
|
+
import { SocketIo } from './SocketIo.js';
|
|
14
|
+
import { s } from './VanillaJs.js';
|
|
15
|
+
|
|
16
|
+
const logger = loggerFactory(import.meta);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @class SocketIoHandlerProvider
|
|
20
|
+
* @classdesc Provides a static factory method to create app-specific SocketIo event handlers
|
|
21
|
+
* from an {@link AppStore} instance. Handles common channel events (chat, email-confirmed)
|
|
22
|
+
* and wires connect/disconnect lifecycle.
|
|
23
|
+
* @memberof SocketIoHandlerProvider
|
|
24
|
+
*/
|
|
25
|
+
class SocketIoHandlerProvider {
|
|
26
|
+
/**
|
|
27
|
+
* Creates a standard SocketIo event initialization object for an app module.
|
|
28
|
+
*
|
|
29
|
+
* @static
|
|
30
|
+
* @param {import('./AppStore.js').AppStore} appStore - The app-specific AppStore instance.
|
|
31
|
+
* @returns {{ Init: function(): Promise<void> }} An object with an `Init` method for SocketIo event registration.
|
|
32
|
+
*/
|
|
33
|
+
static create(appStore) {
|
|
34
|
+
return {
|
|
35
|
+
Init() {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
for (const type of Object.keys(appStore.Data)) {
|
|
38
|
+
SocketIo.Event[type][s4()] = async (args) => {
|
|
39
|
+
args = JSON.parse(args[0]);
|
|
40
|
+
switch (type) {
|
|
41
|
+
case 'chat':
|
|
42
|
+
{
|
|
43
|
+
const idModal = 'modal-chat';
|
|
44
|
+
if (s(`.${idModal}-chat-box`)) Chat.appendChatBox({ idModal, ...args });
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
default:
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
const { status } = args;
|
|
52
|
+
|
|
53
|
+
switch (status) {
|
|
54
|
+
case 'email-confirmed': {
|
|
55
|
+
const newUser = { ...appStore.Data.user.main.model.user, emailConfirmed: true };
|
|
56
|
+
Account.renderVerifyEmailStatus(newUser);
|
|
57
|
+
Account.triggerUpdateEvent({ user: newUser });
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
SocketIo.Event.connect[s4()] = async (reason) => {};
|
|
67
|
+
SocketIo.Event.disconnect[s4()] = async (reason) => {};
|
|
68
|
+
return resolve();
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { SocketIoHandlerProvider };
|
|
@@ -1,113 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side WebRTC stream manager backed by PeerJS.
|
|
3
|
+
* Handles peer creation, media capture, and room-based A/V streaming.
|
|
4
|
+
*
|
|
5
|
+
* @module client/core/Stream
|
|
6
|
+
* @see https://peerjs.com/docs/
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { loggerFactory } from './Logger.js';
|
|
2
10
|
import { getProxyPath } from './Router.js';
|
|
3
11
|
|
|
4
|
-
// https://peerjs.com/docs/
|
|
5
|
-
|
|
6
12
|
const logger = loggerFactory(import.meta);
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @class Stream
|
|
16
|
+
* @classdesc Static manager for PeerJS connections and MediaStream lifecycle.
|
|
17
|
+
* Supports multiple concurrent peer sessions keyed by an arbitrary `id`.
|
|
18
|
+
*/
|
|
19
|
+
class Stream {
|
|
20
|
+
/** @type {Object.<string, { peer: Peer, options: Object }>} Active peer sessions keyed by session id. */
|
|
21
|
+
static #sessions = {};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Builds PeerJS connection options from current page location.
|
|
25
|
+
* @returns {{ host: string, port: number, path: string, secure: boolean }}
|
|
26
|
+
*/
|
|
27
|
+
static #buildPeerOptions() {
|
|
28
|
+
return {
|
|
29
|
+
host: location.hostname,
|
|
13
30
|
port: location.protocol === 'https:' ? 443 : location.port ? parseInt(location.port) + 1 : 80,
|
|
14
31
|
path: `${getProxyPath()}peer`,
|
|
15
32
|
secure: location.protocol === 'https:',
|
|
16
33
|
};
|
|
17
|
-
|
|
18
|
-
this.Data[id] = {
|
|
19
|
-
peer: {
|
|
20
|
-
peerOptions,
|
|
21
|
-
server: new Peer(undefined, peerOptions),
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
return this.Data[id].peer;
|
|
25
|
-
},
|
|
26
|
-
connectToNewUser: function (
|
|
27
|
-
mediaType,
|
|
28
|
-
id,
|
|
29
|
-
userId,
|
|
30
|
-
stream,
|
|
31
|
-
onConnectStream = (mediaElement) => null,
|
|
32
|
-
onDisconnectStream = (mediaElement) => null,
|
|
33
|
-
) {
|
|
34
|
-
// This runs when someone joins our room
|
|
35
|
-
const call = this.Data[id].peer.server.call(userId, stream); // Call the user who just joined
|
|
36
|
-
const mediaElement = this.createMediaElement(mediaType);
|
|
34
|
+
}
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Creates a PeerJS client for the given session id.
|
|
38
|
+
* @param {string} id - Unique session identifier.
|
|
39
|
+
* @returns {{ peer: Peer, options: Object }} The Peer instance and its options.
|
|
40
|
+
*/
|
|
41
|
+
static createPeer(id) {
|
|
42
|
+
this.destroyPeer(id);
|
|
43
|
+
const options = this.#buildPeerOptions();
|
|
44
|
+
logger.info('peerOptions', options);
|
|
45
|
+
const peer = new Peer(undefined, options);
|
|
46
|
+
this.#sessions[id] = { peer, options };
|
|
47
|
+
return this.#sessions[id];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Returns an existing session or `undefined`.
|
|
52
|
+
* @param {string} id
|
|
53
|
+
* @returns {{ peer: Peer, options: Object }|undefined}
|
|
54
|
+
*/
|
|
55
|
+
static getSession(id) {
|
|
56
|
+
return this.#sessions[id];
|
|
57
|
+
}
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Destroys a peer session — closes all connections and the peer itself.
|
|
61
|
+
* @param {string} id - Session identifier.
|
|
62
|
+
*/
|
|
63
|
+
static destroyPeer(id) {
|
|
64
|
+
const session = this.#sessions[id];
|
|
65
|
+
if (!session) return;
|
|
66
|
+
const { peer } = session;
|
|
67
|
+
if (peer) {
|
|
68
|
+
for (const key in peer.connections) {
|
|
69
|
+
for (const conn of peer.connections[key]) {
|
|
70
|
+
if (conn.peerConnection?.close) conn.peerConnection.close();
|
|
71
|
+
if (conn.close) conn.close();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!peer.destroyed) peer.destroy();
|
|
57
75
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.then((stream) => resolve(stream))
|
|
80
|
-
.catch((error) => {
|
|
81
|
-
logger.error(error);
|
|
82
|
-
resolve(undefined);
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
},
|
|
86
|
-
removeMediaStream: function (stream) {
|
|
87
|
-
// later you can do below
|
|
88
|
-
// stop both video and audio
|
|
89
|
-
stream.getTracks().forEach((track) => {
|
|
90
|
-
track.stop();
|
|
76
|
+
delete this.#sessions[id];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Calls a remote peer and streams local media to them.
|
|
81
|
+
* @param {string} id - Session identifier.
|
|
82
|
+
* @param {string} remotePeerId - The remote peer's ID.
|
|
83
|
+
* @param {MediaStream} localStream - Local media stream to send.
|
|
84
|
+
* @param {Object} [callbacks]
|
|
85
|
+
* @param {function(HTMLMediaElement): void} [callbacks.onStream] - Called when remote stream arrives.
|
|
86
|
+
* @param {function(HTMLMediaElement): void} [callbacks.onClose] - Called when the call closes.
|
|
87
|
+
* @returns {{ call: import('peerjs').MediaConnection, element: HTMLVideoElement }}
|
|
88
|
+
*/
|
|
89
|
+
static callPeer(id, remotePeerId, localStream, { onStream, onClose } = {}) {
|
|
90
|
+
const session = this.#sessions[id];
|
|
91
|
+
if (!session) throw new Error(`No peer session "${id}"`);
|
|
92
|
+
const call = session.peer.call(remotePeerId, localStream);
|
|
93
|
+
const element = this.createVideoElement();
|
|
94
|
+
call.on('stream', (remoteStream) => {
|
|
95
|
+
this.attachStream(element, remoteStream);
|
|
96
|
+
onStream?.(element);
|
|
91
97
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
createMediaElement: function (mediaType) {
|
|
98
|
-
let mediaElement;
|
|
99
|
-
switch (mediaType) {
|
|
100
|
-
case 'audio-video':
|
|
101
|
-
mediaElement = document.createElement('video'); // Create a new audio/video tag to show our audio/video
|
|
102
|
-
// mediaElement.muted = true; // Mute ourselves on our end so there is no feedback loop
|
|
98
|
+
call.on('close', () => onClose?.(element));
|
|
99
|
+
return { call, element };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ── Media helpers ────────────────────────────────────────────────
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Requests user media (camera / microphone) with graceful fallback.
|
|
106
|
+
* Falls back to video-only if audio is unavailable (NotReadableError).
|
|
107
|
+
* @param {{ video?: boolean|MediaTrackConstraints, audio?: boolean|MediaTrackConstraints }} [constraints]
|
|
108
|
+
* @returns {Promise<MediaStream|undefined>}
|
|
109
|
+
*/
|
|
110
|
+
static async getMediaStream(constraints = { video: true, audio: true }) {
|
|
111
|
+
const fallbacks = [
|
|
112
|
+
constraints,
|
|
113
|
+
constraints.audio ? { video: constraints.video, audio: false } : null,
|
|
114
|
+
constraints.video ? { video: false, audio: constraints.audio } : null,
|
|
115
|
+
].filter(Boolean);
|
|
105
116
|
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
for (const c of fallbacks) {
|
|
118
|
+
try {
|
|
119
|
+
return await navigator.mediaDevices.getUserMedia(c);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
logger.warn(`getUserMedia failed (${err.name}): ${err.message}`, c);
|
|
122
|
+
}
|
|
108
123
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
124
|
+
logger.error('All media capture attempts failed');
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Stops all tracks of a MediaStream.
|
|
130
|
+
* @param {MediaStream} stream
|
|
131
|
+
*/
|
|
132
|
+
static stopStream(stream) {
|
|
133
|
+
if (!stream) return;
|
|
134
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates a `<video>` element pre-configured for inline autoplay.
|
|
139
|
+
* @returns {HTMLVideoElement}
|
|
140
|
+
*/
|
|
141
|
+
static createVideoElement() {
|
|
142
|
+
const video = document.createElement('video');
|
|
143
|
+
video.playsInline = true;
|
|
144
|
+
video.autoplay = true;
|
|
145
|
+
return video;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Attaches a MediaStream to a media element and starts playback.
|
|
150
|
+
* @param {HTMLMediaElement} element
|
|
151
|
+
* @param {MediaStream} stream
|
|
152
|
+
* @returns {HTMLMediaElement}
|
|
153
|
+
*/
|
|
154
|
+
static attachStream(element, stream) {
|
|
155
|
+
element.srcObject = stream;
|
|
156
|
+
element.addEventListener('loadedmetadata', () => element.play());
|
|
157
|
+
return element;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
112
160
|
|
|
113
161
|
export { Stream };
|
|
@@ -1,7 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket session registration bridge.
|
|
3
|
+
* Registers and unregisters the authenticated user's identity with the server-side
|
|
4
|
+
* WebSocket management layer, enabling targeted real-time pushes (e.g. email confirmation).
|
|
5
|
+
*
|
|
6
|
+
* @module client/core/Webhook
|
|
7
|
+
* @namespace WebhookProvider
|
|
8
|
+
*/
|
|
1
9
|
import { SocketIo } from './SocketIo.js';
|
|
2
10
|
|
|
3
|
-
|
|
4
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @class WebhookProvider
|
|
13
|
+
* @classdesc Provides static methods to register/unregister the authenticated user
|
|
14
|
+
* with the server-side WebSocket session management channels.
|
|
15
|
+
* @memberof WebhookProvider
|
|
16
|
+
*/
|
|
17
|
+
class WebhookProvider {
|
|
18
|
+
/**
|
|
19
|
+
* Registers the authenticated user with the server-side WebSocket channels.
|
|
20
|
+
* Creates a user↔socket mapping on the server, enabling targeted events.
|
|
21
|
+
*
|
|
22
|
+
* @static
|
|
23
|
+
* @async
|
|
24
|
+
* @param {Object} options - Registration options.
|
|
25
|
+
* @param {Object} options.user - The authenticated user object to register.
|
|
26
|
+
* @returns {Promise<void>}
|
|
27
|
+
*/
|
|
28
|
+
static async register(options = { user: {} }) {
|
|
5
29
|
const { user } = options;
|
|
6
30
|
SocketIo.Emit('mailer', {
|
|
7
31
|
status: 'register-user',
|
|
@@ -11,15 +35,24 @@ const Webhook = {
|
|
|
11
35
|
status: 'register-user',
|
|
12
36
|
user,
|
|
13
37
|
});
|
|
14
|
-
}
|
|
15
|
-
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Unregisters the current user from server-side WebSocket channels.
|
|
42
|
+
* Cleans up the user↔socket mapping on the server.
|
|
43
|
+
*
|
|
44
|
+
* @static
|
|
45
|
+
* @async
|
|
46
|
+
* @returns {Promise<void>}
|
|
47
|
+
*/
|
|
48
|
+
static async unregister() {
|
|
16
49
|
SocketIo.Emit('mailer', {
|
|
17
50
|
status: 'unregister-user',
|
|
18
51
|
});
|
|
19
52
|
SocketIo.Emit('user', {
|
|
20
53
|
status: 'unregister-user',
|
|
21
54
|
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
24
57
|
|
|
25
|
-
export {
|
|
58
|
+
export { WebhookProvider };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Auth } from '../core/Auth.js';
|
|
2
2
|
import { LogIn } from '../core/LogIn.js';
|
|
3
|
-
import {
|
|
3
|
+
import { AppStoreDefault } from './AppStoreDefault.js';
|
|
4
4
|
|
|
5
5
|
const LogInDefault = async function () {
|
|
6
6
|
LogIn.Event['LogInDefault'] = async (options) => {
|
|
7
7
|
const { token, user } = options;
|
|
8
|
-
|
|
8
|
+
AppStoreDefault.Data.user.main.model.user = user;
|
|
9
9
|
};
|
|
10
10
|
const { user } = await Auth.sessionIn();
|
|
11
|
-
|
|
11
|
+
AppStoreDefault.Data.user.main.model.user = user;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export { LogInDefault };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { LogOut } from '../core/LogOut.js';
|
|
2
|
-
import {
|
|
2
|
+
import { AppStoreDefault } from './AppStoreDefault.js';
|
|
3
3
|
|
|
4
4
|
const LogOutDefault = async function () {
|
|
5
5
|
LogOut.Event['LogOutDefault'] = async (result = { user: { _id: '' } }) => {
|
|
6
|
-
|
|
6
|
+
AppStoreDefault.Data.user.main.model.user = result.user;
|
|
7
7
|
};
|
|
8
8
|
};
|
|
9
9
|
|
|
@@ -10,7 +10,7 @@ import { SignUp } from '../core/SignUp.js';
|
|
|
10
10
|
import { Translate } from '../core/Translate.js';
|
|
11
11
|
import { htmls, s } from '../core/VanillaJs.js';
|
|
12
12
|
import { extractUsernameFromPath, getProxyPath, getQueryParams } from '../core/Router.js';
|
|
13
|
-
import {
|
|
13
|
+
import { AppStoreDefault } from './AppStoreDefault.js';
|
|
14
14
|
import Sortable from 'sortablejs';
|
|
15
15
|
import { RouterDefault, BannerAppTemplate } from './RoutesDefault.js';
|
|
16
16
|
import { SettingsDefault } from './SettingsDefault.js';
|
|
@@ -551,7 +551,7 @@ const MenuDefault = {
|
|
|
551
551
|
html: async () =>
|
|
552
552
|
await Account.Render({
|
|
553
553
|
idModal: 'modal-account',
|
|
554
|
-
user:
|
|
554
|
+
user: AppStoreDefault.Data.user.main.model.user,
|
|
555
555
|
disabled: [],
|
|
556
556
|
}),
|
|
557
557
|
handleType: 'bar',
|
|
@@ -565,7 +565,7 @@ const MenuDefault = {
|
|
|
565
565
|
EventsUI.onClick(`.main-btn-public-profile`, async () => {
|
|
566
566
|
const { barConfig } = await Themes[Css.currentTheme]();
|
|
567
567
|
const idModal = 'modal-public-profile';
|
|
568
|
-
const user =
|
|
568
|
+
const user = AppStoreDefault.Data.user.main.model.user;
|
|
569
569
|
|
|
570
570
|
// Check if modal already exists
|
|
571
571
|
const existingModal = s(`.${idModal}`);
|
|
@@ -635,7 +635,7 @@ const MenuDefault = {
|
|
|
635
635
|
text: Translate.Render('recover'),
|
|
636
636
|
}),
|
|
637
637
|
html: async () =>
|
|
638
|
-
await Recover.Render({ idModal: 'modal-recover', user:
|
|
638
|
+
await Recover.Render({ idModal: 'modal-recover', user: AppStoreDefault.Data.user.main.model.user }),
|
|
639
639
|
handleType: 'bar',
|
|
640
640
|
maximize: true,
|
|
641
641
|
mode: 'view',
|
|
@@ -723,7 +723,7 @@ const MenuDefault = {
|
|
|
723
723
|
await PanelForm.instance({
|
|
724
724
|
idPanel: 'default-blog',
|
|
725
725
|
defaultUrlImage: `${getProxyPath()}android-chrome-96x96.png`,
|
|
726
|
-
|
|
726
|
+
appStore: AppStoreDefault,
|
|
727
727
|
parentIdModal: idModal,
|
|
728
728
|
scrollClassContainer: `html-${idModal}`,
|
|
729
729
|
route: routeModal,
|
|
@@ -1,54 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { s4 } from '../core/CommonJs.js';
|
|
4
|
-
import { loggerFactory } from '../core/Logger.js';
|
|
5
|
-
import { SocketIo } from '../core/SocketIo.js';
|
|
6
|
-
import { s } from '../core/VanillaJs.js';
|
|
7
|
-
import { ElementsDefault } from './ElementsDefault.js';
|
|
1
|
+
import { SocketIoHandlerProvider } from '../core/SocketIoHandler.js';
|
|
2
|
+
import { AppStoreDefault } from './AppStoreDefault.js';
|
|
8
3
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const SocketIoDefault = {
|
|
12
|
-
Init: function () {
|
|
13
|
-
return new Promise((resolve) => {
|
|
14
|
-
for (const type of Object.keys(ElementsDefault.Data)) {
|
|
15
|
-
SocketIo.Event[type][s4()] = async (args) => {
|
|
16
|
-
args = JSON.parse(args[0]);
|
|
17
|
-
switch (type) {
|
|
18
|
-
case 'chat':
|
|
19
|
-
{
|
|
20
|
-
const idModal = 'modal-chat';
|
|
21
|
-
if (s(`.${idModal}-chat-box`)) Chat.appendChatBox({ idModal, ...args });
|
|
22
|
-
}
|
|
23
|
-
break;
|
|
24
|
-
|
|
25
|
-
default:
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
const { status } = args;
|
|
29
|
-
|
|
30
|
-
switch (status) {
|
|
31
|
-
case 'email-confirmed': {
|
|
32
|
-
const newUser = { ...ElementsDefault.Data.user.main.model.user, emailConfirmed: true };
|
|
33
|
-
Account.renderVerifyEmailStatus(newUser);
|
|
34
|
-
Account.triggerUpdateEvent({ user: newUser });
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
default:
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
SocketIo.Event.connect[s4()] = async (reason) => {
|
|
44
|
-
// ElementsDefault.Init({ type, id, element });
|
|
45
|
-
};
|
|
46
|
-
SocketIo.Event.disconnect[s4()] = async (reason) => {
|
|
47
|
-
// ElementsDefault.removeAll();
|
|
48
|
-
};
|
|
49
|
-
return resolve();
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
};
|
|
4
|
+
const SocketIoDefault = SocketIoHandlerProvider.create(AppStoreDefault);
|
|
53
5
|
|
|
54
6
|
export { SocketIoDefault };
|
|
@@ -17,6 +17,19 @@ const endpoint = 'core';
|
|
|
17
17
|
|
|
18
18
|
// https://developer.mozilla.org/en-US/docs/Web/API/AbortController
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Returns the normalized proxy path from renderPayload (always trailing `/`).
|
|
22
|
+
* Falls back to `null` when no apiBaseProxyPath is set.
|
|
23
|
+
* @memberof CoreServiceClient
|
|
24
|
+
* @return {string|null}
|
|
25
|
+
*/
|
|
26
|
+
const getApiBaseProxyPath = () =>
|
|
27
|
+
window.renderPayload?.apiBaseProxyPath
|
|
28
|
+
? window.renderPayload.apiBaseProxyPath === '/'
|
|
29
|
+
? window.renderPayload.apiBaseProxyPath
|
|
30
|
+
: `${window.renderPayload.apiBaseProxyPath}/`
|
|
31
|
+
: null;
|
|
32
|
+
|
|
20
33
|
/**
|
|
21
34
|
* Gets the base host for API requests.
|
|
22
35
|
* Uses the apiBaseHost from renderPayload if available, otherwise falls back to location.host.
|
|
@@ -35,13 +48,7 @@ const getBaseHost = () => (window.renderPayload?.apiBaseHost ? window.renderPayl
|
|
|
35
48
|
*/
|
|
36
49
|
const getApiBasePath = (options) =>
|
|
37
50
|
`${
|
|
38
|
-
options?.proxyPath
|
|
39
|
-
? `/${options.proxyPath}/`
|
|
40
|
-
: window.renderPayload?.apiBaseProxyPath
|
|
41
|
-
? window.renderPayload.apiBaseProxyPath == '/'
|
|
42
|
-
? window.renderPayload.apiBaseProxyPath
|
|
43
|
-
: `${window.renderPayload.apiBaseProxyPath}/`
|
|
44
|
-
: getProxyPath()
|
|
51
|
+
options?.proxyPath ? `/${options.proxyPath}/` : getApiBaseProxyPath() || getProxyPath()
|
|
45
52
|
}${window.renderPayload?.apiBasePath ? window.renderPayload.apiBasePath : 'api'}/`;
|
|
46
53
|
|
|
47
54
|
/**
|
|
@@ -65,7 +72,11 @@ const getApiBaseUrl = (options = { id: '', endpoint: '', proxyPath: '' }) =>
|
|
|
65
72
|
* @memberof CoreServiceClient
|
|
66
73
|
* @return {string} The WebSocket base path.
|
|
67
74
|
*/
|
|
68
|
-
const getWsBasePath = () =>
|
|
75
|
+
const getWsBasePath = () => {
|
|
76
|
+
const proxyPath = getApiBaseProxyPath();
|
|
77
|
+
if (proxyPath) return proxyPath !== '/' ? `${proxyPath}socket.io/` : '/socket.io/';
|
|
78
|
+
return getProxyPath() !== '/' ? `${getProxyPath()}socket.io/` : '/socket.io/';
|
|
79
|
+
};
|
|
69
80
|
|
|
70
81
|
/**
|
|
71
82
|
* Constructs the full WebSocket base URL for connections.
|
|
@@ -321,6 +332,7 @@ export {
|
|
|
321
332
|
payloadFactory,
|
|
322
333
|
buildQueryUrl,
|
|
323
334
|
getBaseHost,
|
|
335
|
+
getApiBaseProxyPath,
|
|
324
336
|
getApiBasePath,
|
|
325
337
|
getApiBaseUrl,
|
|
326
338
|
getWsBasePath,
|
|
@@ -2,8 +2,8 @@ import { DefaultManagement } from '../default/default.management.js';
|
|
|
2
2
|
import { UserService } from './user.service.js';
|
|
3
3
|
|
|
4
4
|
const UserManagement = {
|
|
5
|
-
RenderTable: async ({
|
|
6
|
-
const user =
|
|
5
|
+
RenderTable: async ({ appStore }) => {
|
|
6
|
+
const user = appStore.Data.user.main.model.user;
|
|
7
7
|
const { role } = user;
|
|
8
8
|
return await DefaultManagement.RenderTable({
|
|
9
9
|
idModal: 'modal-user-management',
|
|
@@ -47,9 +47,12 @@ const main = () => {
|
|
|
47
47
|
a {
|
|
48
48
|
color: black;
|
|
49
49
|
}
|
|
50
|
+
.main-body-ssr-404 {
|
|
51
|
+
top: 45%;
|
|
52
|
+
}
|
|
50
53
|
</style>
|
|
51
54
|
|
|
52
|
-
<div class="abs center
|
|
55
|
+
<div class="abs center main-body-ssr-404">
|
|
53
56
|
${icon}
|
|
54
57
|
<br />
|
|
55
58
|
<br />
|
|
@@ -57,17 +60,18 @@ const main = () => {
|
|
|
57
60
|
<br />
|
|
58
61
|
<br />${Translate.Render('page-not-found')} <br />
|
|
59
62
|
<br />
|
|
60
|
-
<a href="${location.origin}">${Translate.Render('back')}</a>
|
|
63
|
+
<a target="_top" href="${location.origin}">${Translate.Render('back')}</a>
|
|
61
64
|
</div>`,
|
|
62
65
|
);
|
|
63
66
|
};
|
|
64
67
|
|
|
65
|
-
SrrComponent = () =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
SrrComponent = () =>
|
|
69
|
+
html`<script>
|
|
70
|
+
{
|
|
71
|
+
const s = ${s};
|
|
72
|
+
const append = ${append};
|
|
73
|
+
const getLang = ${getLang};
|
|
74
|
+
const main = ${main};
|
|
75
|
+
window.onload = main;
|
|
76
|
+
}
|
|
77
|
+
</script>`;
|