underpost 2.8.853 → 2.8.854

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.
@@ -2,22 +2,22 @@
2
2
  apiVersion: apps/v1
3
3
  kind: Deployment
4
4
  metadata:
5
- name: dd-template-development-blue
5
+ name: dd-default-development-blue
6
6
  labels:
7
- app: dd-template-development-blue
7
+ app: dd-default-development-blue
8
8
  spec:
9
9
  replicas: 1
10
10
  selector:
11
11
  matchLabels:
12
- app: dd-template-development-blue
12
+ app: dd-default-development-blue
13
13
  template:
14
14
  metadata:
15
15
  labels:
16
- app: dd-template-development-blue
16
+ app: dd-default-development-blue
17
17
  spec:
18
18
  containers:
19
- - name: dd-template-development-blue
20
- image: localhost/rockylinux9-underpost:v2.8.853
19
+ - name: dd-default-development-blue
20
+ image: localhost/rockylinux9-underpost:v2.8.854
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -40,10 +40,10 @@ spec:
40
40
  apiVersion: v1
41
41
  kind: Service
42
42
  metadata:
43
- name: dd-template-development-blue-service
43
+ name: dd-default-development-blue-service
44
44
  spec:
45
45
  selector:
46
- app: dd-template-development-blue
46
+ app: dd-default-development-blue
47
47
  ports:
48
48
  - name: 'tcp-4001'
49
49
  protocol: TCP
@@ -85,22 +85,22 @@ spec:
85
85
  apiVersion: apps/v1
86
86
  kind: Deployment
87
87
  metadata:
88
- name: dd-template-development-green
88
+ name: dd-default-development-green
89
89
  labels:
90
- app: dd-template-development-green
90
+ app: dd-default-development-green
91
91
  spec:
92
92
  replicas: 1
93
93
  selector:
94
94
  matchLabels:
95
- app: dd-template-development-green
95
+ app: dd-default-development-green
96
96
  template:
97
97
  metadata:
98
98
  labels:
99
- app: dd-template-development-green
99
+ app: dd-default-development-green
100
100
  spec:
101
101
  containers:
102
- - name: dd-template-development-green
103
- image: localhost/rockylinux9-underpost:v2.8.853
102
+ - name: dd-default-development-green
103
+ image: localhost/rockylinux9-underpost:v2.8.854
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -124,10 +124,10 @@ spec:
124
124
  apiVersion: v1
125
125
  kind: Service
126
126
  metadata:
127
- name: dd-template-development-green-service
127
+ name: dd-default-development-green-service
128
128
  spec:
129
129
  selector:
130
- app: dd-template-development-green
130
+ app: dd-default-development-green
131
131
  ports:
132
132
  - name: 'tcp-4001'
133
133
  protocol: TCP
@@ -16,7 +16,7 @@ spec:
16
16
  - prefix: /
17
17
  enableWebsockets: true
18
18
  services:
19
- - name: dd-template-development-blue-service
19
+ - name: dd-default-development-blue-service
20
20
  port: 4001
21
21
  weight: 100
22
22
 
@@ -24,7 +24,7 @@ spec:
24
24
  - prefix: /peer
25
25
  enableWebsockets: true
26
26
  services:
27
- - name: dd-template-development-blue-service
27
+ - name: dd-default-development-blue-service
28
28
  port: 4002
29
29
  weight: 100
30
30
 
@@ -41,6 +41,6 @@ spec:
41
41
  - prefix: /
42
42
  enableWebsockets: true
43
43
  services:
44
- - name: dd-template-development-blue-service
44
+ - name: dd-default-development-blue-service
45
45
  port: 4003
46
46
  weight: 100
@@ -0,0 +1,57 @@
1
+ ---
2
+ apiVersion: apps/v1
3
+ kind: Deployment
4
+ metadata:
5
+ labels:
6
+ app: grafana
7
+ name: grafana
8
+ spec:
9
+ selector:
10
+ matchLabels:
11
+ app: grafana
12
+ template:
13
+ metadata:
14
+ labels:
15
+ app: grafana
16
+ spec:
17
+ securityContext:
18
+ fsGroup: 472
19
+ supplementalGroups:
20
+ - 0
21
+ containers:
22
+ - name: grafana
23
+ image: grafana/grafana:latest
24
+ imagePullPolicy: IfNotPresent
25
+ ports:
26
+ - containerPort: 3000
27
+ name: http-grafana
28
+ protocol: TCP
29
+ readinessProbe:
30
+ failureThreshold: 3
31
+ httpGet:
32
+ path: /robots.txt
33
+ port: 3000
34
+ scheme: HTTP
35
+ initialDelaySeconds: 10
36
+ periodSeconds: 30
37
+ successThreshold: 1
38
+ timeoutSeconds: 2
39
+ livenessProbe:
40
+ failureThreshold: 3
41
+ initialDelaySeconds: 30
42
+ periodSeconds: 10
43
+ successThreshold: 1
44
+ tcpSocket:
45
+ port: 3000
46
+ timeoutSeconds: 1
47
+ resources:
48
+ requests:
49
+ cpu: 250m
50
+ memory: 750Mi
51
+ volumeMounts:
52
+ - mountPath: /var/lib/grafana
53
+ name: grafana-pv
54
+ volumes:
55
+ - name: grafana-pv
56
+ persistentVolumeClaim:
57
+ claimName: grafana-pvc
@@ -0,0 +1,7 @@
1
+ ---
2
+ apiVersion: kustomize.config.k8s.io/v1beta1
3
+ kind: Kustomization
4
+ resources:
5
+ - pvc.yaml
6
+ - deployment.yaml
7
+ - service.yaml
@@ -0,0 +1,12 @@
1
+ ---
2
+ apiVersion: v1
3
+ kind: PersistentVolumeClaim
4
+ metadata:
5
+ name: grafana-pvc
6
+ spec:
7
+ accessModes:
8
+ - ReadWriteOnce
9
+ storageClassName: local-path
10
+ resources:
11
+ requests:
12
+ storage: 5Gi
@@ -0,0 +1,14 @@
1
+ ---
2
+ apiVersion: v1
3
+ kind: Service
4
+ metadata:
5
+ name: grafana
6
+ spec:
7
+ ports:
8
+ - port: 3000
9
+ protocol: TCP
10
+ targetPort: http-grafana
11
+ selector:
12
+ app: grafana
13
+ sessionAffinity: None
14
+ type: LoadBalancer
@@ -0,0 +1,82 @@
1
+ ---
2
+ apiVersion: v1
3
+ kind: ConfigMap
4
+ metadata:
5
+ name: prometheus-config
6
+ labels:
7
+ app: prometheus
8
+ data:
9
+ prometheus.yml: |
10
+ global:
11
+ scrape_interval: 30s
12
+ evaluation_interval: 30s
13
+
14
+ scrape_configs:
15
+ - job_name: 'scraper'
16
+ metrics_path: /metrics
17
+ scheme: https
18
+ static_configs:
19
+ - targets: []
20
+ # tls_config:
21
+ # insecure_skip_verify: true
22
+
23
+ ---
24
+ apiVersion: apps/v1
25
+ kind: Deployment
26
+ metadata:
27
+ name: prometheus
28
+ labels:
29
+ app: prometheus
30
+ spec:
31
+ replicas: 1
32
+ selector:
33
+ matchLabels:
34
+ app: prometheus
35
+ template:
36
+ metadata:
37
+ labels:
38
+ app: prometheus
39
+ spec:
40
+ containers:
41
+ - name: prometheus
42
+ image: prom/prometheus:latest
43
+ args:
44
+ - '--config.file=/etc/prometheus/prometheus.yml'
45
+ - '--storage.tsdb.path=/prometheus'
46
+ - '--web.console.libraries=/usr/share/prometheus/console_libraries'
47
+ - '--web.console.templates=/usr/share/prometheus/consoles'
48
+ ports:
49
+ - containerPort: 9090
50
+ name: web
51
+ volumeMounts:
52
+ - name: prometheus-config
53
+ mountPath: /etc/prometheus/
54
+ - name: prometheus-data
55
+ mountPath: /prometheus
56
+ resources:
57
+ requests:
58
+ memory: '200Mi'
59
+ cpu: '100m'
60
+ volumes:
61
+ - name: prometheus-config
62
+ configMap:
63
+ name: prometheus-config
64
+ - name: prometheus-data
65
+ emptyDir: {}
66
+
67
+ ---
68
+ apiVersion: v1
69
+ kind: Service
70
+ metadata:
71
+ name: prometheus
72
+ labels:
73
+ app: prometheus
74
+ spec:
75
+ ports:
76
+ - port: 9090
77
+ targetPort: 9090
78
+ protocol: TCP
79
+ name: web
80
+ selector:
81
+ app: prometheus
82
+ type: ClusterIP
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.8.853",
5
+ "version": "2.8.854",
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",
@@ -21,7 +21,6 @@
21
21
  "install-test": "npm install -g mocha && npm install -g c8 && npm install -g nyc && npm install -g coveralls",
22
22
  "install-underpost": "cp -a $(npm root -g)/underpost/node_modules ./node_modules && npm install --only=dev --ignore-scripts",
23
23
  "install": "npm run install-global && npm run install-test",
24
- "docker:start": "docker-compose up",
25
24
  "prettier": "prettier --write .",
26
25
  "fix": "npm audit fix --force && npm audit",
27
26
  "changelog": "auto-changelog"
@@ -5,6 +5,7 @@ import UnderpostBaremetal from './baremetal.js';
5
5
  import UnderpostDeploy from './deploy.js';
6
6
  import UnderpostTest from './test.js';
7
7
  import os from 'os';
8
+ import fs from 'fs-extra';
8
9
 
9
10
  const logger = loggerFactory(import.meta);
10
11
 
@@ -33,12 +34,13 @@ class UnderpostCluster {
33
34
  * @param {string} [options.nsUse=''] - Set the current kubectl namespace.
34
35
  * @param {boolean} [options.infoCapacity=false] - Display resource capacity information for the cluster.
35
36
  * @param {boolean} [options.infoCapacityPod=false] - Display resource capacity information for pods.
36
- * @param {boolean} [options.istio=false] - Deploy Istio service mesh.
37
37
  * @param {boolean} [options.pullImage=false] - Pull necessary Docker images before deployment.
38
38
  * @param {boolean} [options.dedicatedGpu=false] - Configure for dedicated GPU usage (e.g., NVIDIA GPU Operator).
39
39
  * @param {boolean} [options.kubeadm=false] - Initialize the cluster using Kubeadm.
40
40
  * @param {boolean} [options.k3s=false] - Initialize the cluster using K3s.
41
41
  * @param {boolean} [options.initHost=false] - Perform initial host setup (install Docker, Podman, Kind, Kubeadm, Helm).
42
+ * @param {boolean} [options.grafana=false] - Initialize the cluster with a Grafana deployment.
43
+ * @param {string} [options.prom=''] - Initialize the cluster with a Prometheus Operator deployment and monitor scrap for specified hosts.
42
44
  * @param {boolean} [options.uninstallHost=false] - Uninstall all host components.
43
45
  * @param {boolean} [options.config=false] - Apply general host configuration (SELinux, containerd, sysctl, firewalld).
44
46
  * @param {boolean} [options.worker=false] - Configure as a worker node (for Kubeadm or K3s join).
@@ -63,12 +65,13 @@ class UnderpostCluster {
63
65
  nsUse: '',
64
66
  infoCapacity: false,
65
67
  infoCapacityPod: false,
66
- istio: false,
67
68
  pullImage: false,
68
69
  dedicatedGpu: false,
69
70
  kubeadm: false,
70
71
  k3s: false,
71
72
  initHost: false,
73
+ grafana: false,
74
+ prom: '',
72
75
  uninstallHost: false,
73
76
  config: false,
74
77
  worker: false,
@@ -260,6 +263,42 @@ class UnderpostCluster {
260
263
  );
261
264
  }
262
265
 
266
+ if (options.grafana === true) {
267
+ shellExec(`kubectl delete deployment grafana --ignore-not-found`);
268
+ shellExec(`kubectl apply -k ${underpostRoot}/manifests/grafana`);
269
+ }
270
+
271
+ if (options.prom && typeof options.prom === 'string') {
272
+ shellExec(`kubectl delete deployment prometheus --ignore-not-found`);
273
+ shellExec(`kubectl delete configmap prometheus-config --ignore-not-found`);
274
+ shellExec(`kubectl delete service prometheus --ignore-not-found`);
275
+ // Prometheus server host: http://<prometheus-cluster-ip>:9090
276
+ const yaml = `${fs.readFileSync(`${underpostRoot}/manifests/prometheus/deployment.yaml`, 'utf8').replace(
277
+ '- targets: []',
278
+ `- targets: [${options.prom
279
+ .split(',')
280
+ .map((host) => `'${host}'`)
281
+ .join(',')}]`,
282
+ )}`;
283
+ console.log(yaml);
284
+ shellExec(`kubectl apply -f - <<EOF
285
+ ${yaml}
286
+ EOF
287
+ `);
288
+
289
+ // https://grafana.com/docs/grafana-cloud/monitor-infrastructure/kubernetes-monitoring/configuration/config-other-methods/prometheus/prometheus-operator/
290
+ // shellExec(
291
+ // `kubectl create -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/master/bundle.yaml`,
292
+ // );
293
+ // shellExec(`kubectl apply -f ${underpostRoot}/manifests/prometheus/prometheus-cr.yaml`);
294
+ // shellExec(`kubectl rollout status sts prometheus-prometheus -n default`);
295
+ // shellExec(`kubectl apply -f ${underpostRoot}/manifests/prometheus/prometheus-server.yaml`);
296
+ // shellExec(`helm repo add prometheus-community https://prometheus-community.github.io/helm-charts`);
297
+ // shellExec(`helm repo update`);
298
+ // shellExec(`helm install prometheus prometheus-community/prometheus`);
299
+ // shellExec(`kubectl rollout status deployment prometheus-server -n default`);
300
+ }
301
+
263
302
  if (options.full === true || options.valkey === true) {
264
303
  if (options.pullImage === true) {
265
304
  // shellExec(`sudo podman pull valkey/valkey:latest`);
package/src/cli/index.js CHANGED
@@ -123,6 +123,11 @@ program
123
123
  .option('--full', 'Initializes the cluster with all available statefulsets and services.')
124
124
  .option('--ns-use <ns-name>', 'Switches the current Kubernetes context to the specified namespace.')
125
125
  .option('--kubeadm', 'Initializes the cluster using kubeadm for control plane management.')
126
+ .option('--grafana', 'Initializes the cluster with a Grafana deployment.')
127
+ .option(
128
+ '--prom [hosts]',
129
+ 'Initializes the cluster with a Prometheus Operator deployment and monitor scrap for specified hosts.',
130
+ )
126
131
  .option('--dev', 'Initializes a development-specific cluster configuration.')
127
132
  .option('--list-pods', 'Displays detailed information about all pods.')
128
133
  .option('--info-capacity', 'Displays the current total machine capacity information.')
package/src/cli/run.js CHANGED
@@ -98,6 +98,19 @@ class UnderpostRun {
98
98
  shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
99
99
  shellExec(`${baseCommand} push . underpostnet/engine`);
100
100
  },
101
+ clean: (path, options = UnderpostRun.DEFAULT_OPTION) => {
102
+ shellCd(path ?? `/home/dd/engine`);
103
+ shellExec(`node bin/deploy clean-core-repo`);
104
+ },
105
+ upgrade: (path, options = UnderpostRun.DEFAULT_OPTION) => {
106
+ const { underpostRoot } = options;
107
+ shellExec(`npm install -g underpost`);
108
+ shellExec(`underpost run secret`);
109
+ shellCd(`/home/dd/engine`);
110
+ shellExec(`node bin/deploy clean-core-repo`);
111
+ shellExec(`underpost pull . underpostnet/engine`);
112
+ shellExec(`underpost pull engine-private underpostnet/engine-private`, { silent: true });
113
+ },
101
114
  'ssh-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
102
115
  const baseCommand = options.dev || true ? 'node bin' : 'underpost';
103
116
  shellCd('/home/dd/engine');
@@ -15,7 +15,6 @@ import { DefaultParams } from './components/default/CommonDefault.js';
15
15
  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
- import { Scroll } from './components/core/Scroll.js';
19
18
  import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
20
19
 
21
20
  const htmlMainBody = async () => {
@@ -39,7 +38,6 @@ window.onload = () =>
39
38
  await LogInDefault();
40
39
  await LogOutDefault();
41
40
  await SignUpDefault();
42
- await Scroll.pullTopRefresh();
43
41
  await Keyboard.Init({ callBackTime: DefaultParams.EVENT_CALLBACK_TIME });
44
42
  },
45
43
  });
@@ -502,7 +502,7 @@ const Modal = {
502
502
  class="abs modal slide-menu-top-bar-fix"
503
503
  style="height: ${options.heightTopBar}px; top: 0px"
504
504
  >
505
- <a class="a-link-top-banner">
505
+ <a class="a-link-top-banner fl">
506
506
  <div class="inl">${await options.slideMenuTopBarBannerFix()}</div></a
507
507
  >
508
508
  </div>`
@@ -1160,7 +1160,7 @@ const Modal = {
1160
1160
  if (s(`.slide-menu-top-bar-fix`)) {
1161
1161
  htmls(
1162
1162
  `.slide-menu-top-bar-fix`,
1163
- html`<a class="a-link-top-banner">${await options.slideMenuTopBarBannerFix()}</a>`,
1163
+ html`<a class="a-link-top-banner fl">${await options.slideMenuTopBarBannerFix()}</a>`,
1164
1164
  );
1165
1165
  Modal.setTopBannerLink();
1166
1166
  }
@@ -1,131 +1,76 @@
1
- import { borderChar } from './Css.js';
2
- import { Modal } from './Modal.js';
3
- import { append, s } from './VanillaJs.js';
1
+ import { s } from './VanillaJs.js';
4
2
 
5
- const Scroll = {
6
- data: {},
7
- init: function (selector) {
8
- s(selector).addEventListener('scroll', Scroll.scrollHandler);
9
- Scroll.data[selector] = {
10
- element: s(selector),
3
+ class Scroll {
4
+ /**
5
+ * Attach scroll listener to an element (resolved with s(selector)).
6
+ * @param {string} selector - selector passed to s(selector)
7
+ * @param {function} [callback] - callback function to be called on scroll
8
+ * @param {object} options
9
+ * @param {number} [options.threshold=1] - px margin to treat as bottom
10
+ * @param {number} [options.precision=3] - decimal places for percentages
11
+ */
12
+ static setEvent(selector, callback = async () => {}, options = { threshold: 1, precision: 3 }) {
13
+ const el = s(selector);
14
+ if (!el) return;
15
+
16
+ const threshold = options.threshold ?? 1; // px tolerance for bottom detection
17
+ const precision = options.precision ?? 3;
18
+ let ticking = false;
19
+
20
+ const round = (v) => {
21
+ const m = Math.pow(10, precision);
22
+ return Math.round(v * m) / m;
11
23
  };
12
- return Scroll.data[selector];
13
- },
14
- getScrollPosition: function (selector) {
15
- // Scroll.data[selector].element.clientHeight -
16
- return Scroll.data[selector].element.scrollTop;
17
- },
18
- scrollHandler: async function () {
19
- for (const selector in Scroll.data) await Scroll.data[selector].callback(Scroll.getScrollPosition(selector));
20
- },
21
- addEvent: function (selector = '', callback = (position = 0) => {}) {
22
- Scroll.data[selector].callback = callback;
23
- },
24
- removeEvent: function (selector) {
25
- delete Scroll.data[selector];
26
- },
27
- to: function (elector = '', options = { top: 100, left: 100, behavior: 'smooth' }) {
28
- Scroll.data[selector].element.scrollTo({
29
- top: options.top || Scroll.getScrollPosition(selector),
30
- left: options.left || 0,
31
- behavior: options.behavior || 'smooth',
32
- });
33
- },
34
- topRefreshEvents: {},
35
- addTopRefreshEvent: function (options = { id: '', callback: () => {}, condition: () => {} }) {
36
- this.topRefreshEvents[options.id] = options;
37
- },
38
- removeTopRefreshEvent: function (id = '') {
39
- delete this.topRefreshEvents[id];
40
- },
41
- pullTopRefresh: function () {
42
- return;
43
- append(
44
- 'body',
45
- html` <style>
46
- .pull-refresh-icon-container {
47
- height: 60px;
48
- width: 100%;
49
- z-index: 10;
50
- transition: 0.3s;
51
- left: 0px;
52
- }
53
- .pull-refresh-icon {
54
- width: 60px;
55
- height: 60px;
56
- margin: auto;
57
- color: white;
58
- font-size: 30px;
59
- }
60
- </style>
61
- ${borderChar(2, 'black', [' .pull-refresh-icon-container'])}
62
- <div style="top: -60px" class="abs pull-refresh-icon-container">
63
- <div class="in pull-refresh-icon">
64
- <div class="abs center"><i class="fa-solid fa-arrows-rotate"></i></div>
65
- </div>
66
- </div>`,
67
- );
68
24
 
69
- let touchstartY = 0;
70
- let reload = false;
71
- const minHeightDragReload = 3;
72
- const maxHeightDragReload = 20;
25
+ const listener = (event) => {
26
+ if (ticking) return;
27
+ ticking = true;
28
+
29
+ requestAnimationFrame(() => {
30
+ const scrollHeight = el.scrollHeight;
31
+ const clientHeight = el.clientHeight;
32
+ const scrollTop = el.scrollTop;
33
+
34
+ // pixels left to scroll (clamped to >= 0)
35
+ const remaining = Math.max(0, scrollHeight - clientHeight - scrollTop);
73
36
 
74
- document.addEventListener('touchstart', (e) => {
75
- touchstartY = e.touches[0].clientY;
76
- // console.warn('touchstart', touchstartY);
77
- });
37
+ // maximum possible remaining (0 if content fits without scrolling)
38
+ const maxRemaining = Math.max(0, scrollHeight - clientHeight);
78
39
 
79
- document.addEventListener('touchmove', (e) => {
80
- if (
81
- !Object.keys(Scroll.topRefreshEvents).find((event) => Scroll.topRefreshEvents[event].condition()) ||
82
- (!s(`.btn-bar-center-icon-close`).classList.contains('hide') &&
83
- !s(
84
- `.btn-icon-menu-mode-${Modal.Data['modal-menu'].options.mode !== 'slide-menu-right' ? 'left' : 'right'}`,
85
- ).classList.contains('hide'))
86
- )
87
- return;
40
+ // percentRemaining: 1 = top (all remaining), 0 = bottom (none remaining)
41
+ let percentRemaining = maxRemaining === 0 ? 0 : remaining / maxRemaining;
42
+ percentRemaining = Math.max(0, Math.min(1, percentRemaining));
88
43
 
89
- const touchY = e.touches[0].clientY;
90
- const touchDiff = touchY - touchstartY;
44
+ // percentScrolled: complementary value (0 = top, 1 = bottom)
45
+ let percentScrolled = 1 - percentRemaining;
46
+ percentScrolled = Math.max(0, Math.min(1, percentScrolled));
91
47
 
92
- // console.warn('touchDiff', touchDiff, maxHeightDragReload);
48
+ const payload = {
49
+ scrollHeight,
50
+ clientHeight,
51
+ scrollTop,
52
+ remaining, // px left (>= 0)
53
+ scrollBottom: remaining <= threshold ? 0 : remaining,
54
+ atBottom: remaining <= threshold,
55
+ percentRemaining: round(percentRemaining), // 0..1
56
+ percentScrolled: round(percentScrolled), // 0..1
57
+ };
93
58
 
94
- if (touchDiff > maxHeightDragReload)
95
- s(`.pull-refresh-icon-container`).style.top = 60 + maxHeightDragReload + 'px';
96
- else s(`.pull-refresh-icon-container`).style.top = 60 + touchDiff + 'px';
59
+ // replace this with an event dispatch or callback if you prefer
60
+ // console.warn('scroll', event, JSON.stringify(payload, null, 2));
61
+ callback(payload);
97
62
 
98
- if (touchDiff > minHeightDragReload && window.scrollY === 0) {
99
- reload = true;
100
- } else {
101
- reload = false;
102
- }
103
- });
104
- document.addEventListener('touchend', (e) => {
105
- // console.warn('touchend');
106
- s(`.pull-refresh-icon-container`).style.top = '-60px';
107
- if (reload) {
108
- for (const event of Object.keys(Scroll.topRefreshEvents))
109
- if (Scroll.topRefreshEvents[event].condition()) Scroll.topRefreshEvents[event].callback();
110
- }
111
- reload = false;
112
- });
113
- Scroll.addTopRefreshEvent({
114
- id: 'main-body',
115
- callback: () => {
116
- location.reload();
117
- },
118
- condition: () => {
119
- return (
120
- s('.main-body') &&
121
- s('.main-body').scrollTop === 0 &&
122
- !Object.keys(Modal.Data).find(
123
- (idModal) => !['modal-menu', 'main-body', 'bottom-bar', 'main-body-top'].includes(idModal),
124
- )
125
- );
126
- },
127
- });
128
- },
129
- };
63
+ ticking = false;
64
+ });
65
+ };
66
+
67
+ el.addEventListener('scroll', listener, { passive: true });
68
+
69
+ return {
70
+ removeEvent: () => el.removeEventListener('scroll', listener),
71
+ };
72
+ }
73
+ }
130
74
 
131
75
  export { Scroll };
76
+ export default Scroll;
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.8.853';
38
+ static version = 'v2.8.854';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static