underpost 2.85.7 → 2.89.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/.github/workflows/release.cd.yml +1 -1
- package/README.md +2 -2
- package/bin/build.js +8 -10
- package/cli.md +3 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +50 -50
- package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
- package/package.json +1 -1
- package/src/api/file/file.service.js +29 -3
- package/src/cli/baremetal.js +1 -2
- package/src/cli/index.js +1 -0
- package/src/cli/repository.js +8 -1
- package/src/cli/run.js +97 -36
- package/src/client/components/core/AgGrid.js +42 -3
- package/src/client/components/core/CommonJs.js +4 -0
- package/src/client/components/core/Css.js +95 -48
- package/src/client/components/core/CssCore.js +0 -1
- package/src/client/components/core/LoadingAnimation.js +2 -2
- package/src/client/components/core/Logger.js +2 -9
- package/src/client/components/core/Modal.js +22 -14
- package/src/client/components/core/ObjectLayerEngine.js +300 -9
- package/src/client/components/core/ObjectLayerEngineModal.js +686 -148
- package/src/client/components/core/ObjectLayerEngineViewer.js +1061 -0
- package/src/client/components/core/Pagination.js +15 -5
- package/src/client/components/core/Router.js +5 -1
- package/src/client/components/core/Translate.js +4 -0
- package/src/client/components/core/Worker.js +8 -1
- package/src/client/services/default/default.management.js +86 -16
- package/src/db/mariadb/MariaDB.js +2 -2
- package/src/index.js +1 -1
- package/src/server/client-build.js +57 -2
- package/src/server/object-layer.js +44 -0
- package/src/server/start.js +12 -0
- package/src/ws/IoInterface.js +2 -3
- package/AUTHORS.md +0 -21
- package/src/server/network.js +0 -72
|
@@ -10,12 +10,13 @@ class AgPagination extends HTMLElement {
|
|
|
10
10
|
this._limit = parseInt(queryParams.limit, 10) || 10;
|
|
11
11
|
this._totalPages = 1;
|
|
12
12
|
this._totalItems = 0;
|
|
13
|
+
this._limitOptions = [10, 20, 50, 100]; // Default options
|
|
13
14
|
this.handlePageChange = this.handlePageChange.bind(this);
|
|
14
15
|
this.handleLimitChange = this.handleLimitChange.bind(this);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
static get observedAttributes() {
|
|
18
|
-
return ['grid-id', 'current-page', 'total-pages', 'total-items', 'limit'];
|
|
19
|
+
return ['grid-id', 'current-page', 'total-pages', 'total-items', 'limit', 'limit-options'];
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
@@ -35,6 +36,16 @@ class AgPagination extends HTMLElement {
|
|
|
35
36
|
case 'limit':
|
|
36
37
|
this._limit = parseInt(newValue, 10) || this._limit;
|
|
37
38
|
break;
|
|
39
|
+
case 'limit-options':
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(newValue);
|
|
42
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
43
|
+
this._limitOptions = parsed.map((v) => parseInt(v, 10)).filter((v) => !isNaN(v) && v > 0);
|
|
44
|
+
}
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.warn('Invalid limit-options format, using defaults');
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
38
49
|
}
|
|
39
50
|
this.update();
|
|
40
51
|
}
|
|
@@ -133,6 +144,8 @@ class AgPagination extends HTMLElement {
|
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
render() {
|
|
147
|
+
const limitOptionsHtml = this._limitOptions.map((value) => `<option value="${value}">${value}</option>`).join('');
|
|
148
|
+
|
|
136
149
|
this.shadowRoot.innerHTML = html`
|
|
137
150
|
<style>
|
|
138
151
|
:host {
|
|
@@ -193,10 +206,7 @@ class AgPagination extends HTMLElement {
|
|
|
193
206
|
<button id="next-page">Next</button>
|
|
194
207
|
<button id="last-page">Last</button>
|
|
195
208
|
<select id="limit-selector">
|
|
196
|
-
|
|
197
|
-
<option value="20">20</option>
|
|
198
|
-
<option value="50">50</option>
|
|
199
|
-
<option value="100">100</option>
|
|
209
|
+
${limitOptionsHtml}
|
|
200
210
|
</select>
|
|
201
211
|
`;
|
|
202
212
|
}
|
|
@@ -300,7 +300,11 @@ const setQueryParams = (newParams, options = { replace: true }) => {
|
|
|
300
300
|
|
|
301
301
|
const newPath = url.pathname + url.search + url.hash;
|
|
302
302
|
|
|
303
|
-
|
|
303
|
+
if (options.replace) {
|
|
304
|
+
history.replaceState(history.state, '', newPath);
|
|
305
|
+
} else {
|
|
306
|
+
history.pushState(history.state, '', newPath);
|
|
307
|
+
}
|
|
304
308
|
};
|
|
305
309
|
|
|
306
310
|
export {
|
|
@@ -53,15 +53,22 @@ class PwaWorker {
|
|
|
53
53
|
*/
|
|
54
54
|
constructor() {
|
|
55
55
|
this.title = `${s('title').textContent}`;
|
|
56
|
+
if (!window.renderPayload.dev) {
|
|
57
|
+
console.log = () => null;
|
|
58
|
+
console.error = () => null;
|
|
59
|
+
console.info = () => null;
|
|
60
|
+
console.warn = () => null;
|
|
61
|
+
}
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
/**
|
|
59
65
|
* Checks if the application is running in development mode (localhost or 127.0.0.1).
|
|
66
|
+
* @method devMode
|
|
60
67
|
* @memberof PwaWorker
|
|
61
68
|
* @returns {boolean} True if in development mode.
|
|
62
69
|
*/
|
|
63
70
|
devMode() {
|
|
64
|
-
return location.origin.match('localhost') || location.origin.match('127.0.0.1');
|
|
71
|
+
return window.renderPayload.dev || location.origin.match('localhost') || location.origin.match('127.0.0.1');
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
/**
|
|
@@ -18,7 +18,7 @@ const DefaultOptions = {
|
|
|
18
18
|
serviceId: 'default-management',
|
|
19
19
|
entity: 'default',
|
|
20
20
|
columnDefs: [
|
|
21
|
-
{ field: '0', headerName: '0' },
|
|
21
|
+
{ field: '0', headerName: '0', cellClassRules: { 'row-new-highlight': (params) => true } },
|
|
22
22
|
{ field: '1', headerName: '1' },
|
|
23
23
|
{ field: '2', headerName: '2' },
|
|
24
24
|
{ field: 'createdAt', headerName: 'createdAt', cellDataType: 'date', editable: false },
|
|
@@ -29,6 +29,10 @@ const DefaultOptions = {
|
|
|
29
29
|
permissions: {
|
|
30
30
|
add: true,
|
|
31
31
|
remove: true,
|
|
32
|
+
reload: true,
|
|
33
|
+
},
|
|
34
|
+
paginationOptions: {
|
|
35
|
+
limitOptions: [10, 20, 50, 100],
|
|
32
36
|
},
|
|
33
37
|
};
|
|
34
38
|
|
|
@@ -66,25 +70,36 @@ const DefaultManagement = {
|
|
|
66
70
|
paginationComp.setAttribute('current-page', this.Tokens[id].page);
|
|
67
71
|
paginationComp.setAttribute('total-pages', this.Tokens[id].totalPages);
|
|
68
72
|
paginationComp.setAttribute('total-items', this.Tokens[id].total);
|
|
73
|
+
setTimeout(async () => {
|
|
74
|
+
if (DefaultManagement.Tokens[id].readyRowDataEvent)
|
|
75
|
+
for (const event of Object.keys(DefaultManagement.Tokens[id].readyRowDataEvent))
|
|
76
|
+
await DefaultManagement.Tokens[id].readyRowDataEvent[event](rowDataScope);
|
|
77
|
+
}, 1);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
refreshTable: async function (id) {
|
|
81
|
+
const gridApi = AgGrid.grids[this.Tokens[id].gridId];
|
|
82
|
+
if (gridApi) {
|
|
83
|
+
// Use refreshCells with change detection for optimal performance
|
|
84
|
+
// This is preferred over redrawRows() as it only updates changed cells
|
|
85
|
+
gridApi.refreshCells({
|
|
86
|
+
force: false, // Use change detection - only refresh cells whose values have changed
|
|
87
|
+
suppressFlash: false, // Show flash animation for changed cells (requires enableCellChangeFlash)
|
|
88
|
+
});
|
|
69
89
|
}
|
|
70
90
|
},
|
|
71
91
|
RenderTable: async function (options = DefaultOptions) {
|
|
72
92
|
if (!options) options = DefaultOptions;
|
|
73
|
-
const { serviceId, columnDefs, entity, defaultColKeyFocus, ServiceProvider, permissions } =
|
|
93
|
+
const { serviceId, columnDefs, entity, defaultColKeyFocus, ServiceProvider, permissions, paginationOptions } =
|
|
94
|
+
options;
|
|
74
95
|
logger.info('DefaultManagement RenderTable', options);
|
|
75
96
|
const id = options?.idModal ? options.idModal : getId(this.Tokens, `${serviceId}-`);
|
|
76
97
|
const gridId = `${serviceId}-grid-${id}`;
|
|
77
98
|
const queryParams = getQueryParams();
|
|
78
99
|
const page = parseInt(queryParams.page) || 1;
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
gridId,
|
|
83
|
-
page,
|
|
84
|
-
limit,
|
|
85
|
-
total: 0,
|
|
86
|
-
totalPages: 1,
|
|
87
|
-
};
|
|
100
|
+
const defaultLimit = paginationOptions?.limitOptions?.[0] || 10;
|
|
101
|
+
const limit = parseInt(queryParams.limit) || defaultLimit;
|
|
102
|
+
this.Tokens[id] = { ...this.Tokens[id], ...options, gridId, page, limit, total: 0, totalPages: 1 };
|
|
88
103
|
|
|
89
104
|
setQueryParams({ page, limit });
|
|
90
105
|
setTimeout(async () => {
|
|
@@ -107,7 +122,7 @@ const DefaultManagement = {
|
|
|
107
122
|
label: html`<div class="abs center">
|
|
108
123
|
<i class="fas fa-times"></i>
|
|
109
124
|
</div> `,
|
|
110
|
-
class: `in fll section-mp management-table-btn-mini management-table-btn-remove-${id}-${cellRenderId}`,
|
|
125
|
+
class: `in fll section-mp management-table-btn-mini management-table-btn-remove-${id}-${cellRenderId} ${!params.data._id ? 'hide' : ''}`,
|
|
111
126
|
})}`;
|
|
112
127
|
setTimeout(() => {
|
|
113
128
|
EventsUI.onClick(
|
|
@@ -191,9 +206,16 @@ const DefaultManagement = {
|
|
|
191
206
|
// }
|
|
192
207
|
// }
|
|
193
208
|
s(`.management-table-btn-save-${id}`).onclick = () => {
|
|
209
|
+
s(`.management-table-btn-save-${id}`).classList.add('hide');
|
|
210
|
+
// s(`.management-table-btn-stop-${id}`).classList.add('hide');
|
|
211
|
+
if (permissions.add) s(`.management-table-btn-add-${id}`).classList.remove('hide');
|
|
212
|
+
if (permissions.remove) s(`.management-table-btn-clean-${id}`).classList.remove('hide');
|
|
213
|
+
if (permissions.reload) s(`.management-table-btn-reload-${id}`).classList.remove('hide');
|
|
194
214
|
AgGrid.grids[gridId].stopEditing();
|
|
195
215
|
};
|
|
196
216
|
EventsUI.onClick(`.management-table-btn-add-${id}`, async () => {
|
|
217
|
+
if (options.customEvent && options.customEvent.add) return await options.customEvent.add();
|
|
218
|
+
|
|
197
219
|
const rowObj = {};
|
|
198
220
|
for (const def of columnDefs) {
|
|
199
221
|
rowObj[def.field] = '';
|
|
@@ -260,6 +282,11 @@ const DefaultManagement = {
|
|
|
260
282
|
// }
|
|
261
283
|
|
|
262
284
|
setTimeout(() => {
|
|
285
|
+
s(`.management-table-btn-save-${id}`).classList.remove('hide');
|
|
286
|
+
// s(`.management-table-btn-stop-${id}`).classList.remove('hide');
|
|
287
|
+
if (permissions.add) s(`.management-table-btn-add-${id}`).classList.add('hide');
|
|
288
|
+
if (permissions.remove) s(`.management-table-btn-clean-${id}`).classList.add('hide');
|
|
289
|
+
if (permissions.reload) s(`.management-table-btn-reload-${id}`).classList.add('hide');
|
|
263
290
|
AgGrid.grids[gridId].startEditingCell({
|
|
264
291
|
rowIndex: 0,
|
|
265
292
|
colKey: defaultColKeyFocus,
|
|
@@ -268,6 +295,15 @@ const DefaultManagement = {
|
|
|
268
295
|
});
|
|
269
296
|
});
|
|
270
297
|
});
|
|
298
|
+
|
|
299
|
+
EventsUI.onClick(`.management-table-btn-stop-${id}`, async () => {
|
|
300
|
+
s(`.management-table-btn-save-${id}`).classList.add('hide');
|
|
301
|
+
// s(`.management-table-btn-stop-${id}`).classList.add('hide');
|
|
302
|
+
if (permissions.add) s(`.management-table-btn-add-${id}`).classList.remove('hide');
|
|
303
|
+
if (permissions.remove) s(`.management-table-btn-clean-${id}`).classList.remove('hide');
|
|
304
|
+
if (permissions.reload) s(`.management-table-btn-reload-${id}`).classList.remove('hide');
|
|
305
|
+
AgGrid.grids[gridId].stopEditing();
|
|
306
|
+
});
|
|
271
307
|
EventsUI.onClick(`.management-table-btn-clean-${id}`, async () => {
|
|
272
308
|
const confirmResult = await Modal.RenderConfirm(
|
|
273
309
|
{
|
|
@@ -292,6 +328,26 @@ const DefaultManagement = {
|
|
|
292
328
|
DefaultManagement.loadTable(id);
|
|
293
329
|
}
|
|
294
330
|
});
|
|
331
|
+
EventsUI.onClick(`.management-table-btn-reload-${id}`, async () => {
|
|
332
|
+
try {
|
|
333
|
+
// Reload data from server
|
|
334
|
+
await DefaultManagement.loadTable(id);
|
|
335
|
+
|
|
336
|
+
// Other option: Refresh cells to update UI
|
|
337
|
+
// DefaultManagement.refreshTable(id);
|
|
338
|
+
|
|
339
|
+
NotificationManager.Push({
|
|
340
|
+
html: Translate.Render('success-reload-data') || 'Data reloaded successfully',
|
|
341
|
+
status: 'success',
|
|
342
|
+
});
|
|
343
|
+
} catch (error) {
|
|
344
|
+
NotificationManager.Push({
|
|
345
|
+
html: error.message || 'Error reloading data',
|
|
346
|
+
status: 'error',
|
|
347
|
+
});
|
|
348
|
+
} finally {
|
|
349
|
+
}
|
|
350
|
+
});
|
|
295
351
|
s(`#ag-pagination-${gridId}`).addEventListener('page-change', async (event) => {
|
|
296
352
|
const token = DefaultManagement.Tokens[id];
|
|
297
353
|
token.page = event.detail.page;
|
|
@@ -318,7 +374,7 @@ const DefaultManagement = {
|
|
|
318
374
|
}
|
|
319
375
|
};
|
|
320
376
|
}, 1);
|
|
321
|
-
return html`<div class="fl">
|
|
377
|
+
return html`<div class="fl management-table-toolbar">
|
|
322
378
|
${await BtnIcon.Render({
|
|
323
379
|
class: `in fll section-mp management-table-btn-mini management-table-btn-add-${id} ${
|
|
324
380
|
permissions.add ? '' : 'hide'
|
|
@@ -327,12 +383,15 @@ const DefaultManagement = {
|
|
|
327
383
|
type: 'button',
|
|
328
384
|
})}
|
|
329
385
|
${await BtnIcon.Render({
|
|
330
|
-
class: `in fll section-mp management-table-btn-mini management-table-btn-save-${id}
|
|
331
|
-
permissions.add ? '' : 'hide'
|
|
332
|
-
}`,
|
|
386
|
+
class: `in fll section-mp management-table-btn-mini management-table-btn-save-${id} hide`,
|
|
333
387
|
label: html`<div class="abs center btn-save-${id}-label"><i class="fas fa-save"></i></div> `,
|
|
334
388
|
type: 'button',
|
|
335
389
|
})}
|
|
390
|
+
${await BtnIcon.Render({
|
|
391
|
+
class: `in fll section-mp management-table-btn-mini management-table-btn-stop-${id} hide`,
|
|
392
|
+
label: html`<div class="abs center btn-save-${id}-label"><i class="fa-solid fa-rectangle-xmark"></i></div> `,
|
|
393
|
+
type: 'button',
|
|
394
|
+
})}
|
|
336
395
|
${await BtnIcon.Render({
|
|
337
396
|
class: `in fll section-mp management-table-btn-mini management-table-btn-clean-${id} ${
|
|
338
397
|
permissions.remove ? '' : 'hide'
|
|
@@ -340,12 +399,21 @@ const DefaultManagement = {
|
|
|
340
399
|
label: html`<div class="abs center btn-clean-${id}-label"><i class="fas fa-broom"></i></div> `,
|
|
341
400
|
type: 'button',
|
|
342
401
|
})}
|
|
402
|
+
${await BtnIcon.Render({
|
|
403
|
+
class: `in fll section-mp management-table-btn-mini management-table-btn-reload-${id} ${
|
|
404
|
+
permissions.reload ? '' : 'hide'
|
|
405
|
+
}`,
|
|
406
|
+
label: html`<div class="abs center btn-reload-${id}-label"><i class="fas fa-sync-alt"></i></div> `,
|
|
407
|
+
type: 'button',
|
|
408
|
+
})}
|
|
343
409
|
</div>
|
|
344
410
|
<div class="in section-mp">
|
|
345
411
|
${await AgGrid.Render({
|
|
346
412
|
id: gridId,
|
|
347
413
|
parentModal: options.idModal,
|
|
348
414
|
usePagination: true,
|
|
415
|
+
paginationOptions,
|
|
416
|
+
customHeightOffset: !permissions.add && !permissions.remove && !permissions.reload ? 50 : 0,
|
|
349
417
|
darkTheme,
|
|
350
418
|
gridOptions: {
|
|
351
419
|
defaultColDef: {
|
|
@@ -425,6 +493,7 @@ const DefaultManagement = {
|
|
|
425
493
|
// rowNode.setData(newRow);
|
|
426
494
|
// }, 2000);
|
|
427
495
|
}
|
|
496
|
+
s(`.management-table-btn-save-${id}`).click();
|
|
428
497
|
}
|
|
429
498
|
} else {
|
|
430
499
|
const body = event.data ? event.data : {};
|
|
@@ -441,6 +510,7 @@ const DefaultManagement = {
|
|
|
441
510
|
}
|
|
442
511
|
}
|
|
443
512
|
},
|
|
513
|
+
...(options.gridOptions ? options.gridOptions : undefined),
|
|
444
514
|
},
|
|
445
515
|
})}
|
|
446
516
|
</div>`;
|
|
@@ -42,9 +42,9 @@ class MariaDBService {
|
|
|
42
42
|
try {
|
|
43
43
|
conn = await pool.getConnection();
|
|
44
44
|
result = await conn.query(query, { supportBigNumbers: true, bigNumberStrings: true });
|
|
45
|
-
logger.info(query
|
|
45
|
+
logger.info('query');
|
|
46
|
+
console.log(result);
|
|
46
47
|
} catch (error) {
|
|
47
|
-
if (error.stack.startsWith('TypeError: Do not know how to serialize a BigInt')) return;
|
|
48
48
|
logger.error(error, error.stack);
|
|
49
49
|
} finally {
|
|
50
50
|
if (conn) conn.release(); // release to pool
|
package/src/index.js
CHANGED
|
@@ -32,6 +32,51 @@ dotenv.config();
|
|
|
32
32
|
|
|
33
33
|
// Static Site Generation (SSG)
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Recursively copies files from source to destination, but only files that don't exist in destination.
|
|
37
|
+
* @function copyNonExistingFiles
|
|
38
|
+
* @param {string} src - Source directory path
|
|
39
|
+
* @param {string} dest - Destination directory path
|
|
40
|
+
* @returns {void}
|
|
41
|
+
* @memberof clientBuild
|
|
42
|
+
*/
|
|
43
|
+
const copyNonExistingFiles = (src, dest) => {
|
|
44
|
+
// Ensure source exists
|
|
45
|
+
if (!fs.existsSync(src)) {
|
|
46
|
+
throw new Error(`Source directory does not exist: ${src}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Get stats for source
|
|
50
|
+
const srcStats = fs.statSync(src);
|
|
51
|
+
|
|
52
|
+
// If source is a file, copy only if it doesn't exist in destination
|
|
53
|
+
if (srcStats.isFile()) {
|
|
54
|
+
if (!fs.existsSync(dest)) {
|
|
55
|
+
const destDir = dir.dirname(dest);
|
|
56
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
57
|
+
fs.copyFileSync(src, dest);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// If source is a directory, create destination if it doesn't exist
|
|
63
|
+
if (srcStats.isDirectory()) {
|
|
64
|
+
if (!fs.existsSync(dest)) {
|
|
65
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Read all items in source directory
|
|
69
|
+
const items = fs.readdirSync(src);
|
|
70
|
+
|
|
71
|
+
// Recursively process each item
|
|
72
|
+
for (const item of items) {
|
|
73
|
+
const srcPath = dir.join(src, item);
|
|
74
|
+
const destPath = dir.join(dest, item);
|
|
75
|
+
copyNonExistingFiles(srcPath, destPath);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
35
80
|
/**
|
|
36
81
|
* @async
|
|
37
82
|
* @function buildClient
|
|
@@ -83,6 +128,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
83
128
|
* @param {string} options.publicClientId - Public client ID.
|
|
84
129
|
* @param {boolean} options.iconsBuild - Whether to build icons.
|
|
85
130
|
* @param {Object} options.metadata - Metadata for the client.
|
|
131
|
+
* @param {boolean} options.publicCopyNonExistingFiles - Whether to copy non-existing files from public directory.
|
|
86
132
|
* @returns {Promise<void>} - Promise that resolves when the full build is complete.
|
|
87
133
|
* @throws {Error} - If the full build fails.
|
|
88
134
|
* @memberof clientBuild
|
|
@@ -98,6 +144,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
98
144
|
publicClientId,
|
|
99
145
|
iconsBuild,
|
|
100
146
|
metadata,
|
|
147
|
+
publicCopyNonExistingFiles,
|
|
101
148
|
}) => {
|
|
102
149
|
logger.warn('Full build', rootClientPath);
|
|
103
150
|
|
|
@@ -169,11 +216,15 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
169
216
|
fs.copySync(dist.styles, `${rootClientPath}${dist.public_styles_folder}`);
|
|
170
217
|
}
|
|
171
218
|
}
|
|
219
|
+
|
|
220
|
+
if (publicCopyNonExistingFiles)
|
|
221
|
+
copyNonExistingFiles(`./src/client/public/${publicCopyNonExistingFiles}`, rootClientPath);
|
|
172
222
|
};
|
|
173
223
|
|
|
174
224
|
// { srcBuildPath, publicBuildPath }
|
|
175
225
|
const enableLiveRebuild =
|
|
176
226
|
options && options.liveClientBuildPaths && options.liveClientBuildPaths.length > 0 ? true : false;
|
|
227
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
177
228
|
|
|
178
229
|
let currentPort = parseInt(process.env.PORT) + 1;
|
|
179
230
|
for (const host of Object.keys(confServer)) {
|
|
@@ -205,7 +256,8 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
205
256
|
} = confServer[host][path];
|
|
206
257
|
if (singleReplica) continue;
|
|
207
258
|
if (!confClient[client]) confClient[client] = {};
|
|
208
|
-
const { components, dists, views, services, metadata, publicRef } =
|
|
259
|
+
const { components, dists, views, services, metadata, publicRef, publicCopyNonExistingFiles } =
|
|
260
|
+
confClient[client];
|
|
209
261
|
let backgroundImage;
|
|
210
262
|
if (metadata) {
|
|
211
263
|
backgroundImage = metadata.backgroundImage;
|
|
@@ -240,6 +292,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
240
292
|
publicClientId,
|
|
241
293
|
iconsBuild,
|
|
242
294
|
metadata,
|
|
295
|
+
publicCopyNonExistingFiles,
|
|
243
296
|
});
|
|
244
297
|
|
|
245
298
|
if (components)
|
|
@@ -520,6 +573,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
|
|
|
520
573
|
apiBaseHost,
|
|
521
574
|
apiBasePath: process.env.BASE_API,
|
|
522
575
|
version: Underpost.version,
|
|
576
|
+
dev: isDevelopment,
|
|
523
577
|
},
|
|
524
578
|
renderApi: {
|
|
525
579
|
JSONweb,
|
|
@@ -613,6 +667,7 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
|
|
|
613
667
|
apiBaseHost,
|
|
614
668
|
apiBasePath: process.env.BASE_API,
|
|
615
669
|
version: Underpost.version,
|
|
670
|
+
dev: isDevelopment,
|
|
616
671
|
},
|
|
617
672
|
renderApi: {
|
|
618
673
|
JSONweb,
|
|
@@ -687,4 +742,4 @@ ${fs.readFileSync(`${rootClientPath}/sw.js`, 'utf8')}`,
|
|
|
687
742
|
}
|
|
688
743
|
};
|
|
689
744
|
|
|
690
|
-
export { buildClient };
|
|
745
|
+
export { buildClient, copyNonExistingFiles };
|
|
@@ -192,6 +192,49 @@ export class ObjectLayerEngine {
|
|
|
192
192
|
return objectLayerFrameDirections;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* @memberof CyberiaObjectLayer
|
|
197
|
+
* @static
|
|
198
|
+
* @description Processes an image file through frameFactory and adds the resulting frame to the render data structure.
|
|
199
|
+
* Updates the color palette and pushes the frame to all keyframe directions corresponding to the given direction code.
|
|
200
|
+
* Initializes colors array, frames object, and direction arrays if they don't exist.
|
|
201
|
+
* @param {Object} renderData - The render data object containing frames and colors.
|
|
202
|
+
* @param {string} imagePath - The path to the image file to process.
|
|
203
|
+
* @param {string} directionCode - The numerical direction code (e.g., '08', '14').
|
|
204
|
+
* @returns {Promise<Object>} - The updated render data object.
|
|
205
|
+
* @memberof CyberiaObjectLayer
|
|
206
|
+
*/
|
|
207
|
+
static async processAndPushFrame(renderData, imagePath, directionCode) {
|
|
208
|
+
// Initialize colors array if it doesn't exist
|
|
209
|
+
if (!renderData.colors) {
|
|
210
|
+
renderData.colors = [];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Initialize frames object if it doesn't exist
|
|
214
|
+
if (!renderData.frames) {
|
|
215
|
+
renderData.frames = {};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Process the image and extract frame matrix and updated colors
|
|
219
|
+
const frameFactoryResult = await ObjectLayerEngine.frameFactory(imagePath, renderData.colors);
|
|
220
|
+
|
|
221
|
+
// Update the colors palette
|
|
222
|
+
renderData.colors = frameFactoryResult.colors;
|
|
223
|
+
|
|
224
|
+
// Get all keyframe directions for this direction code
|
|
225
|
+
const keyframeDirections = ObjectLayerEngine.getKeyFramesDirectionsFromNumberFolderDirection(directionCode);
|
|
226
|
+
|
|
227
|
+
// Push the frame to all corresponding directions
|
|
228
|
+
for (const keyframeDirection of keyframeDirections) {
|
|
229
|
+
if (!renderData.frames[keyframeDirection]) {
|
|
230
|
+
renderData.frames[keyframeDirection] = [];
|
|
231
|
+
}
|
|
232
|
+
renderData.frames[keyframeDirection].push(frameFactoryResult.frame);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return renderData;
|
|
236
|
+
}
|
|
237
|
+
|
|
195
238
|
/**
|
|
196
239
|
* @memberof CyberiaObjectLayer
|
|
197
240
|
* @static
|
|
@@ -290,5 +333,6 @@ export const readPngAsync = ObjectLayerEngine.readPngAsync;
|
|
|
290
333
|
export const frameFactory = ObjectLayerEngine.frameFactory;
|
|
291
334
|
export const getKeyFramesDirectionsFromNumberFolderDirection =
|
|
292
335
|
ObjectLayerEngine.getKeyFramesDirectionsFromNumberFolderDirection;
|
|
336
|
+
export const processAndPushFrame = ObjectLayerEngine.processAndPushFrame;
|
|
293
337
|
export const buildImgFromTile = ObjectLayerEngine.buildImgFromTile;
|
|
294
338
|
export const generateRandomStats = ObjectLayerEngine.generateRandomStats;
|
package/src/server/start.js
CHANGED
|
@@ -122,6 +122,12 @@ class UnderpostStartUp {
|
|
|
122
122
|
if (options.build === true) await UnderpostStartUp.API.build(deployId, env);
|
|
123
123
|
if (options.run === true) await UnderpostStartUp.API.run(deployId, env);
|
|
124
124
|
},
|
|
125
|
+
/**
|
|
126
|
+
* Run itc-scripts and builds client bundle.
|
|
127
|
+
* @param {string} deployId - The ID of the deployment.
|
|
128
|
+
* @param {string} env - The environment of the deployment.
|
|
129
|
+
* @memberof UnderpostStartUp
|
|
130
|
+
*/
|
|
125
131
|
async build(deployId = 'dd-default', env = 'development') {
|
|
126
132
|
const buildBasePath = `/home/dd`;
|
|
127
133
|
const repoName = `engine-${deployId.split('-')[1]}`;
|
|
@@ -139,6 +145,12 @@ class UnderpostStartUp {
|
|
|
139
145
|
}
|
|
140
146
|
shellExec(`node bin/deploy build-full-client ${deployId}`);
|
|
141
147
|
},
|
|
148
|
+
/**
|
|
149
|
+
* Runs a deployment.
|
|
150
|
+
* @param {string} deployId - The ID of the deployment.
|
|
151
|
+
* @param {string} env - The environment of the deployment.
|
|
152
|
+
* @memberof UnderpostStartUp
|
|
153
|
+
*/
|
|
142
154
|
async run(deployId = 'dd-default', env = 'development') {
|
|
143
155
|
const runCmd = env === 'production' ? 'run prod-img' : 'run dev-img';
|
|
144
156
|
if (fs.existsSync(`./engine-private/replica`)) {
|
package/src/ws/IoInterface.js
CHANGED
|
@@ -21,11 +21,10 @@ const logger = loggerFactory(import.meta);
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
+
* Manages the logic, client map, and event listeners for a specific WebSocket channel,
|
|
25
|
+
* ensuring robust message handling and lifecycle management.
|
|
24
26
|
* @class IoChannel
|
|
25
|
-
* @alias IoChannel
|
|
26
27
|
* @memberof SocketIoInterface
|
|
27
|
-
* @classdesc Manages the logic, client map, and event listeners for a specific WebSocket channel,
|
|
28
|
-
* ensuring robust message handling and lifecycle management.
|
|
29
28
|
*/
|
|
30
29
|
class IoChannel {
|
|
31
30
|
/**
|
package/AUTHORS.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Authors
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Author: fcoverdugoa <52893447+underpostnet@users.noreply.github.com>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Author: fcoverdugoa <fcoverdugoa@underpost.net>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Author: fcoverdugo <fcoverdugoa@underpost.net>
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Author: underpost.net <52893447+underpostnet@users.noreply.github.com>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Author: underpostnet <fcoverdugoa@underpost.net>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
#### Generated by [underpost.net](https://underpost.net)
|
package/src/server/network.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import Underpost from '../index.js';
|
|
2
|
-
import { actionInitLog, loggerFactory } from './logger.js';
|
|
3
|
-
|
|
4
|
-
const logger = loggerFactory(import.meta);
|
|
5
|
-
|
|
6
|
-
const logRuntimeRouter = () => {
|
|
7
|
-
const displayLog = {};
|
|
8
|
-
|
|
9
|
-
for (const host of Object.keys(Underpost.deployNetwork))
|
|
10
|
-
for (const path of Object.keys(Underpost.deployNetwork[host]))
|
|
11
|
-
displayLog[Underpost.deployNetwork[host][path].publicHost] = Underpost.deployNetwork[host][path].local;
|
|
12
|
-
|
|
13
|
-
logger.info('Runtime network', displayLog);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const listenServerFactory = (logic = async () => {}) => {
|
|
17
|
-
return {
|
|
18
|
-
listen: async (...args) => (
|
|
19
|
-
setTimeout(() => {
|
|
20
|
-
const message = 'Listen server factory timeout';
|
|
21
|
-
logger.error(message);
|
|
22
|
-
throw new Error(message);
|
|
23
|
-
}, 80000000), // ~ 55 days
|
|
24
|
-
(logic ? await logic(...args) : undefined, args[1]())
|
|
25
|
-
),
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const listenPortController = async (server, port, metadata) =>
|
|
30
|
-
new Promise((resolve) => {
|
|
31
|
-
try {
|
|
32
|
-
if (port === ':') {
|
|
33
|
-
server.listen(port, actionInitLog);
|
|
34
|
-
return resolve(true);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const { host, path, client, runtime, meta } = metadata;
|
|
38
|
-
const error = [];
|
|
39
|
-
if (port === undefined) error.push(`port`);
|
|
40
|
-
if (host === undefined) error.push(`host`);
|
|
41
|
-
if (path === undefined) error.push(`path`);
|
|
42
|
-
if (client === undefined) error.push(`client`);
|
|
43
|
-
if (runtime === undefined) error.push(`runtime`);
|
|
44
|
-
if (meta === undefined) error.push(`meta`);
|
|
45
|
-
if (error.length > 0) throw new Error('Listen port controller requires values: ' + error.join(', '));
|
|
46
|
-
|
|
47
|
-
server.listen(port, () => {
|
|
48
|
-
if (!Underpost.deployNetwork[host]) Underpost.deployNetwork[host] = {};
|
|
49
|
-
Underpost.deployNetwork[host][path] = {
|
|
50
|
-
meta,
|
|
51
|
-
client,
|
|
52
|
-
runtime,
|
|
53
|
-
port,
|
|
54
|
-
publicHost:
|
|
55
|
-
port === 80
|
|
56
|
-
? `http://${host}${path}`
|
|
57
|
-
: port === 443
|
|
58
|
-
? `https://${host}${path}`
|
|
59
|
-
: `http://${host}:${port}${path}`,
|
|
60
|
-
local: `http://localhost:${port}${path}`,
|
|
61
|
-
apis: metadata.apis,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
return resolve(true);
|
|
65
|
-
});
|
|
66
|
-
} catch (error) {
|
|
67
|
-
logger.error(error, { metadata, port, stack: error.stack });
|
|
68
|
-
resolve(false);
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
export { listenPortController, logRuntimeRouter, listenServerFactory };
|