underpost 2.89.0 → 2.89.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.
@@ -30,7 +30,9 @@ jobs:
30
30
  echo "Starting remote release deploy"
31
31
  underpost run pull
32
32
  underpost run secret
33
+ npm install -g underpost
33
34
  cd /home/dd/engine
35
+ underpost run secret
34
36
  node bin run --dev git-conf
35
37
  node bin run --dev template-deploy-image
36
38
  node bin run --dev ssh-deploy sync-engine-test
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  <!-- badges -->
20
20
 
21
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.89.0)](https://socket.dev/npm/package/underpost/overview/2.89.0) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
21
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.89.1)](https://socket.dev/npm/package/underpost/overview/2.89.1) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
22
22
 
23
23
  <!-- end-badges -->
24
24
 
@@ -66,7 +66,7 @@ Run dev client server
66
66
  npm run dev
67
67
  ```
68
68
  <!-- -->
69
- ## underpost ci/cd cli v2.89.0
69
+ ## underpost ci/cd cli v2.89.1
70
70
 
71
71
  ### Usage: `underpost [options] [command]`
72
72
  ```
package/bin/index.js CHANGED
@@ -1,5 +1,12 @@
1
1
  #! /usr/bin/env node
2
2
 
3
3
  import { program } from '../src/cli/index.js';
4
+ import { loggerFactory } from '../src/server/logger.js';
4
5
 
5
- program.parse();
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ try {
9
+ program.parse();
10
+ } catch (error) {
11
+ logger.error(error);
12
+ }
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.89.0
1
+ ## underpost ci/cd cli v2.89.1
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v2.89.0
20
+ image: localhost/rockylinux9-underpost:v2.89.1
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-default-development-green
103
- image: localhost/rockylinux9-underpost:v2.89.0
103
+ image: localhost/rockylinux9-underpost:v2.89.1
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-test-development-blue
20
- image: localhost/rockylinux9-underpost:v2.89.0
20
+ image: localhost/rockylinux9-underpost:v2.89.1
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "96294Ki"
@@ -104,7 +104,7 @@ spec:
104
104
  spec:
105
105
  containers:
106
106
  - name: dd-test-development-green
107
- image: localhost/rockylinux9-underpost:v2.89.0
107
+ image: localhost/rockylinux9-underpost:v2.89.1
108
108
  # resources:
109
109
  # requests:
110
110
  # memory: "96294Ki"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.89.0",
5
+ "version": "2.89.1",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Purpose: enable required repos (CRB, EPEL, RPM Fusion) and attempt to install ffmpeg on Rocky/Alma/RHEL-9 compatible systems.
5
+
6
+ if [ "${EUID:-$(id -u)}" -ne 0 ]; then
7
+ echo "This script must be run as root or with sudo. Exiting."
8
+ exit 1
9
+ fi
10
+
11
+ echo "1) Ensure dnf-plugins-core is available (for config-manager)"
12
+ dnf -y install dnf-plugins-core || true
13
+
14
+ echo "2) Enable CodeReady / CRB (needed for some deps, e.g. ladspa)"
15
+ # On RHEL you'd use subscription-manager; on CentOS/Rocky/Alma use config-manager
16
+ dnf config-manager --set-enabled crb || true
17
+
18
+ echo "3) Install EPEL release (required by some ffmpeg deps)"
19
+ dnf -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm || true
20
+
21
+ echo "4) Add RPM Fusion (free + nonfree) repositories"
22
+ # Using mirrors.rpmfusion.org recommended links
23
+ dnf -y install https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-9.noarch.rpm \
24
+ https://mirrors.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-9.noarch.rpm || true
25
+
26
+ echo "5) Refresh metadata and update system"
27
+ dnf -y makecache
28
+ # Optional: update system packages (comment out if you don't want a full update)
29
+ # dnf -y update
30
+
31
+ echo "6) Try to install audio helper packages that sometimes block ffmpeg (ladspa, rubberband)"
32
+ # These may be provided by CRB/EPEL or other compatible repos
33
+ dnf -y install ladspa || echo "ladspa not available from enabled repos (will try later)"
34
+ dnf -y install rubberband || echo "rubberband not available from enabled repos (will try later)"
35
+
36
+ echo "7) Try installing ffmpeg (several fallbacks tried)"
37
+ if dnf -y install ffmpeg ffmpeg-devel --allowerasing; then
38
+ echo "ffmpeg installed successfully (used --allowerasing)."
39
+ elif dnf -y install ffmpeg ffmpeg-devel --nobest; then
40
+ echo "ffmpeg installed successfully (used --nobest)."
41
+ elif dnf -y install ffmpeg ffmpeg-devel --skip-broken; then
42
+ echo "ffmpeg installed (skip-broken). Some optional packages may have been skipped."
43
+ else
44
+ echo "Automatic install failed."
45
+ echo "Helpful troubleshooting steps:"
46
+ echo " - Check which repo provides ladspa: dnf repoquery --whatprovides 'ladspa'"
47
+ echo " - Check which package provides librubberband: dnf repoquery --whatprovides 'librubberband.so.2'"
48
+ echo " - Try enabling CRB and EPEL (we already attempted that). If ladspa/rubberband are still missing you can fetch their EL9 rpm from a trusted mirror or build them."
49
+ echo " - Example manual install (ONLY if you trust the source): sudo dnf install /path/to/ladspa-*.el9.rpm /path/to/rubberband-*.el9.rpm"
50
+ echo " - After satisfying ladspa/rubberband, rerun: sudo dnf install ffmpeg ffmpeg-devel"
51
+ exit 2
52
+ fi
53
+
54
+ echo "\nInstallation finished. Verify with: ffmpeg -version"
55
+ exit 0
package/src/cli/run.js CHANGED
@@ -938,7 +938,14 @@ class UnderpostRun {
938
938
  * @param {Object} options - The default underpost runner options for customizing workflow
939
939
  * @memberof UnderpostRun
940
940
  */
941
- sh: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
941
+ sh: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
942
+ let [operator, arg0, arg1] = path.split(',');
943
+ if (operator == 'copy') {
944
+ shellExec(
945
+ `kitty @ get-text ${arg0 === 'all' ? '--match all' : '--self'} --extent all${arg1 === 'ansi' ? ' --ansi yes' : ''} | kitty +kitten clipboard`,
946
+ );
947
+ return;
948
+ }
942
949
  shellExec(`kitty -o allow_remote_control=yes`);
943
950
  },
944
951
 
@@ -1,11 +1,11 @@
1
- import { getQueryParams, setQueryParams } from './Router.js';
1
+ import { getQueryParams, setQueryParams, listenQueryParamsChange } from './Router.js';
2
2
 
3
3
  class AgPagination extends HTMLElement {
4
4
  constructor() {
5
5
  super();
6
6
  this.attachShadow({ mode: 'open' });
7
7
  this._gridId = null;
8
- const queryParams = getQueryParams();
8
+ let queryParams = getQueryParams();
9
9
  this._currentPage = parseInt(queryParams.page, 10) || 1;
10
10
  this._limit = parseInt(queryParams.limit, 10) || 10;
11
11
  this._totalPages = 1;
@@ -13,6 +13,8 @@ class AgPagination extends HTMLElement {
13
13
  this._limitOptions = [10, 20, 50, 100]; // Default options
14
14
  this.handlePageChange = this.handlePageChange.bind(this);
15
15
  this.handleLimitChange = this.handleLimitChange.bind(this);
16
+
17
+ this.handleQueryParamsChange = this.handleQueryParamsChange.bind(this);
16
18
  }
17
19
 
18
20
  static get observedAttributes() {
@@ -53,11 +55,43 @@ class AgPagination extends HTMLElement {
53
55
  connectedCallback() {
54
56
  this.render();
55
57
  this.addEventListeners();
56
- this.update();
58
+ // Subscribe to query parameter changes once the component is connected and _gridId is potentially set.
59
+ listenQueryParamsChange({
60
+ id: `ag-pagination-${this._gridId || 'default'}`, // Use _gridId for a unique listener ID
61
+ event: this.handleQueryParamsChange,
62
+ });
63
+ // The initial state is already set in the constructor from getQueryParams().
64
+ // The `listenQueryParamsChange` in `Router.js` will trigger an immediate (setTimeout) call
65
+ // to `handleQueryParamsChange`, which will re-sync the state if needed and update the component.
66
+ this.update(); // Keep the initial update for rendering based on constructor's initial state.
57
67
  }
58
68
 
59
69
  disconnectedCallback() {
60
- // Event listeners on shadow DOM are garbage collected with the component
70
+ // If Router.js held strong references to queryParamsChangeListeners, you might need to unsubscribe here.
71
+ // However, for this example, we'll assume the component's lifecycle or weak references handle cleanup.
72
+ }
73
+
74
+ handleQueryParamsChange(queryParams) {
75
+ const newPage = parseInt(queryParams.page, 10) || 1;
76
+ const newLimit = parseInt(queryParams.limit, 10) || 10;
77
+
78
+ let shouldUpdate = false;
79
+
80
+ if (newPage !== this._currentPage) {
81
+ this._currentPage = newPage;
82
+ shouldUpdate = true;
83
+ }
84
+ if (newLimit !== this._limit) {
85
+ this._limit = newLimit;
86
+ shouldUpdate = true;
87
+ }
88
+
89
+ if (shouldUpdate) {
90
+ this.update();
91
+ this.dispatchEvent(
92
+ new CustomEvent('pagination-query-params-change', { detail: { page: this._currentPage, limit: this._limit } }),
93
+ );
94
+ }
61
95
  }
62
96
 
63
97
  handlePageChange(newPage) {
@@ -65,7 +99,7 @@ class AgPagination extends HTMLElement {
65
99
  return;
66
100
  }
67
101
  this._currentPage = newPage;
68
- setQueryParams({ page: newPage, limit: this._limit });
102
+ setQueryParams({ page: newPage, limit: this._limit }, { replace: false }); // Use pushState
69
103
  this.dispatchEvent(new CustomEvent('page-change', { detail: { page: newPage } }));
70
104
  }
71
105
 
@@ -76,7 +110,7 @@ class AgPagination extends HTMLElement {
76
110
  }
77
111
  this._limit = newLimit;
78
112
  this._currentPage = 1; // Reset to first page on limit change
79
- setQueryParams({ page: 1, limit: newLimit });
113
+ setQueryParams({ page: 1, limit: newLimit }, { replace: false }); // Use pushState
80
114
  this.dispatchEvent(new CustomEvent('limit-change', { detail: { limit: newLimit } }));
81
115
  }
82
116
 
@@ -98,7 +132,8 @@ class AgPagination extends HTMLElement {
98
132
  this.shadowRoot.querySelector('#page-info').textContent = `Page ${this._currentPage} of ${this._totalPages}`;
99
133
 
100
134
  const limitSelector = this.shadowRoot.querySelector('#limit-selector');
101
- if (limitSelector.value != this._limit) {
135
+ if (limitSelector && limitSelector.value != this._limit) {
136
+ // Added null check for limitSelector
102
137
  limitSelector.value = this._limit;
103
138
  }
104
139
 
@@ -19,6 +19,13 @@ const logger = loggerFactory(import.meta, { trace: true });
19
19
  */
20
20
  const RouterEvents = {};
21
21
 
22
+ /**
23
+ * @type {Object.<string, function>}\n
24
+ * @description Holds event listeners for query parameter changes.\n
25
+ * @memberof PwaRouter
26
+ */
27
+ const queryParamsChangeListeners = {};
28
+
22
29
  /**
23
30
  * @type {string[]}
24
31
  * @description Array of core UI component IDs that should not trigger modal close route changes.
@@ -227,6 +234,22 @@ const listenQueryPathInstance = ({ id, routeId, event }, queryKey = 'cid') => {
227
234
  });
228
235
  };
229
236
 
237
+ /**
238
+ * Registers a listener for changes to query parameters.\n
239
+ * The provided event callback is triggered with the current query parameters object.\n
240
+ * @param {object} options - The listener options.\n
241
+ * @param {string} options.id - A unique ID for the listener.\n
242
+ * @param {function(Object.<string, string>): void} options.event - The callback function to execute with the new query parameters.\n
243
+ * @memberof PwaRouter
244
+ */
245
+ const listenQueryParamsChange = ({ id, event }) => {
246
+ queryParamsChangeListeners[id] = event;
247
+ // Immediately call with current query params for initial state
248
+ setTimeout(() => {
249
+ event(getQueryParams());
250
+ });
251
+ };
252
+
230
253
  /**
231
254
  * Handles the logic for changing the route when a modal is closed. It determines the next URL
232
255
  * based on the remaining open modals or falls back to a home URL.
@@ -305,6 +328,13 @@ const setQueryParams = (newParams, options = { replace: true }) => {
305
328
  } else {
306
329
  history.pushState(history.state, '', newPath);
307
330
  }
331
+
332
+ const updatedParams = getQueryParams();
333
+ for (const listenerId in queryParamsChangeListeners) {
334
+ if (Object.hasOwnProperty.call(queryParamsChangeListeners, listenerId)) {
335
+ queryParamsChangeListeners[listenerId](updatedParams);
336
+ }
337
+ }
308
338
  };
309
339
 
310
340
  export {
@@ -323,4 +353,6 @@ export {
323
353
  setPath,
324
354
  setQueryParams,
325
355
  sanitizeRoute,
356
+ queryParamsChangeListeners,
357
+ listenQueryParamsChange,
326
358
  };
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ class Underpost {
35
35
  * @type {String}
36
36
  * @memberof Underpost
37
37
  */
38
- static version = 'v2.89.0';
38
+ static version = 'v2.89.1';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static
@@ -573,7 +573,7 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [] }
573
573
  apiBaseHost,
574
574
  apiBasePath: process.env.BASE_API,
575
575
  version: Underpost.version,
576
- dev: isDevelopment,
576
+ ...(isDevelopment ? { dev: true } : undefined),
577
577
  },
578
578
  renderApi: {
579
579
  JSONweb,
@@ -667,7 +667,7 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
667
667
  apiBaseHost,
668
668
  apiBasePath: process.env.BASE_API,
669
669
  version: Underpost.version,
670
- dev: isDevelopment,
670
+ ...(isDevelopment ? { dev: true } : undefined),
671
671
  },
672
672
  renderApi: {
673
673
  JSONweb,