From c5cec0bfd5fa230c608ae97b0e5390831f40fee7 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 13 Feb 2025 16:27:30 +0100
Subject: [PATCH 01/33] remodel components

---
 .gitignore                               |  1 +
 src/main/cljc/dda/c4k_jitsi/core.cljc    | 43 +++++++++++++-----------
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc   |  8 +++++
 src/main/resources/jitsi/prosody-sa.yaml |  9 +++++
 4 files changed, 41 insertions(+), 20 deletions(-)
 create mode 100644 src/main/resources/jitsi/prosody-sa.yaml

diff --git a/.gitignore b/.gitignore
index 89da7e2..bb41ea4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ auth.edn
 config.edn
 out.yaml
 .eastwood
+tmp/
diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 86def86..e5ba9f4 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -10,7 +10,8 @@
    [dda.c4k-jitsi.jitsi :as jitsi]
    [dda.c4k-common.namespace :as ns]))
 
-(def config-defaults {:issuer "staging", :namespace "jitsi"})
+(def config-defaults {:issuer "staging", 
+                      :namespace "jitsi"})
 
 (s/def ::mon-cfg ::mon/mon-cfg)
 (s/def ::mon-auth ::mon/mon-auth)
@@ -26,25 +27,27 @@
 
 (defn-spec config-objects cp/map-or-seq?
   [config config?]
-  (map yaml/to-string
-       (filter
-        #(not (nil? %))
-        (cm/concat-vec
-         (ns/generate config)
-         [(jitsi/generate-jvb-service config)
-          (jitsi/generate-web-service config)
-          (jitsi/generate-etherpad-service config)
-          (jitsi/generate-excalidraw-backend-service config)
-          (jitsi/generate-modelector-service config)
-          (jitsi/generate-deployment config)
-          (jitsi/generate-excalidraw-deployment config)
-          (jitsi/generate-modelector-deployment config)]
-         (jitsi/generate-ingress-web config)
-         (jitsi/generate-ingress-etherpad config)
-         (jitsi/generate-ingress-excalidraw-backend config)
-         (jitsi/generate-ingress-modelector config)
-         (when (:contains? config :mon-cfg)
-           (mon/generate-config))))))
+  (let [resolved-config (merge config-defaults config)]
+    (map yaml/to-string
+         (filter
+          #(not (nil? %))
+          (cm/concat-vec
+           (ns/generate resolved-config)
+           (jitsi/prosody resolved-config)
+          ;;  [(jitsi/generate-jvb-service config)
+          ;;   (jitsi/generate-web-service config)
+          ;;   (jitsi/generate-etherpad-service config)
+          ;;   (jitsi/generate-excalidraw-backend-service config)
+          ;;   (jitsi/generate-modelector-service config)
+          ;;   (jitsi/generate-deployment config)
+          ;;   (jitsi/generate-excalidraw-deployment config)
+          ;;   (jitsi/generate-modelector-deployment config)]
+          ;;  (jitsi/generate-ingress-web config)
+          ;;  (jitsi/generate-ingress-etherpad config)
+          ;;  (jitsi/generate-ingress-excalidraw-backend config)
+          ;;  (jitsi/generate-ingress-modelector config)
+           (when (:contains? resolved-config :mon-cfg)
+             (mon/generate-config)))))))
 
 (defn-spec auth-objects cp/map-or-seq?
   [config config?
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 941d675..a0c23f8 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -137,3 +137,11 @@
     (->
      (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
      (cm/replace-all-matching "NAMESPACE" namespace))))
+
+(defn-spec prosody cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    [(->
+      (yaml/load-as-edn "jitsi/prosody-sa.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))]))
+
diff --git a/src/main/resources/jitsi/prosody-sa.yaml b/src/main/resources/jitsi/prosody-sa.yaml
new file mode 100644
index 0000000..d9d3922
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-sa.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: prosody
+  namespace: NAMESPACE
+  labels:
+    helm.sh/chart: prosody-1.4.1
+    app.kubernetes.io/name: prosody
+    app.kubernetes.io/version: "stable-9646"
\ No newline at end of file

From 13047d2e8dd86ec1ff96eaefd424f1fbfb2c196d Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 13 Feb 2025 16:45:10 +0100
Subject: [PATCH 02/33] add prosody cfg

---
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        |  7 ++++++
 .../resources/jitsi/prosody-common-cm.yaml    | 22 +++++++++++++++++++
 .../resources/jitsi/prosody-default-cm.yaml   | 16 ++++++++++++++
 src/main/resources/jitsi/prosody-sa.yaml      |  4 +---
 4 files changed, 46 insertions(+), 3 deletions(-)
 create mode 100644 src/main/resources/jitsi/prosody-common-cm.yaml
 create mode 100644 src/main/resources/jitsi/prosody-default-cm.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index a0c23f8..f7b72ce 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -143,5 +143,12 @@
   (let [{:keys [fqdn namespace]} config]
     [(->
       (yaml/load-as-edn "jitsi/prosody-sa.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-common-cm.yaml")
+      (cm/replace-all-matching "JITSI_FQDN" fqdn)
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-default-cm.yaml")
       (cm/replace-all-matching "NAMESPACE" namespace))]))
 
diff --git a/src/main/resources/jitsi/prosody-common-cm.yaml b/src/main/resources/jitsi/prosody-common-cm.yaml
new file mode 100644
index 0000000..5619166
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-common-cm.yaml
@@ -0,0 +1,22 @@
+# Source: jitsi-meet/templates/common-configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: prosody-common
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+data:
+  ENABLE_AUTH: "0"
+  ENABLE_GUESTS: "1"
+  PUBLIC_URL: JITSI_FQDN
+  XMPP_DOMAIN: meet.jitsi
+  XMPP_MUC_DOMAIN: muc.meet.jitsi
+  XMPP_AUTH_DOMAIN: auth.meet.jitsi
+  XMPP_GUEST_DOMAIN: guest.meet.jitsi
+  XMPP_RECORDER_DOMAIN: recorder.meet.jitsi
+  XMPP_INTERNAL_MUC_DOMAIN: internal-muc.meet.jitsi
+  ENABLE_COLIBRI_WEBSOCKET: 'true'
+  ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX: '1'
+  ENABLE_XMPP_WEBSOCKET: 'true'
+  TZ: 'Europe/Amsterdam'
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-default-cm.yaml b/src/main/resources/jitsi/prosody-default-cm.yaml
new file mode 100644
index 0000000..04d1cd4
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-default-cm.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: prosody-defaults
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+data:
+  prosody.cfg.lua: |
+    # Using prosody /default/prosody.cfg.lua from container image
+    
+  saslauthd.conf: |
+    # Using prosody /default/saslauthd.conf from container image
+    
+  jitsi-meet.cfg.lua: |
+    # Using prosody /default/conf.d/jitsi-meet.cfg.lua from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-sa.yaml b/src/main/resources/jitsi/prosody-sa.yaml
index d9d3922..765094f 100644
--- a/src/main/resources/jitsi/prosody-sa.yaml
+++ b/src/main/resources/jitsi/prosody-sa.yaml
@@ -4,6 +4,4 @@ metadata:
   name: prosody
   namespace: NAMESPACE
   labels:
-    helm.sh/chart: prosody-1.4.1
-    app.kubernetes.io/name: prosody
-    app.kubernetes.io/version: "stable-9646"
\ No newline at end of file
+    app.kubernetes.io/name: prosody
\ No newline at end of file

From d6d50c30f5ab03d48cf52ceadcd4ab16f4a23a95 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 13 Feb 2025 16:48:41 +0100
Subject: [PATCH 03/33] add prosody cfg

---
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc | 42 ++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 1e00cd0..56b8172 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -297,4 +297,44 @@
            :selector {:app "excalidraw-backend"}}}
          (cut/generate-excalidraw-backend-service
           {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
\ No newline at end of file
+           :namespace "jitsi"}))))
+
+(deftest should-generate-prosody
+  (is (= {:apiVersion "v1",
+          :kind "ServiceAccount",
+          :metadata
+          {:name "prosody",
+           :namespace "jitsi",
+           :labels
+           {:app.kubernetes.io/name "prosody"}}}
+         (first (cut/prosody
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"}))))
+  (is (= {:apiVersion "v1",
+          :kind "ConfigMap",
+          :metadata
+          {:name "prosody-common",
+           :namespace "jitsi",
+           :labels
+           #:app.kubernetes.io{:name "jitsi-meet"}},
+          :data
+          {:ENABLE_AUTH "0",
+           :ENABLE_GUESTS "1",
+           :PUBLIC_URL "xy.xy.xy",
+           :XMPP_DOMAIN "meet.jitsi",
+           :XMPP_MUC_DOMAIN "muc.meet.jitsi",
+           :XMPP_AUTH_DOMAIN "auth.meet.jitsi",
+           :XMPP_GUEST_DOMAIN "guest.meet.jitsi",
+           :XMPP_RECORDER_DOMAIN "recorder.meet.jitsi",
+           :XMPP_INTERNAL_MUC_DOMAIN "internal-muc.meet.jitsi",
+           :ENABLE_COLIBRI_WEBSOCKET "true",
+           :ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX "1",
+           :ENABLE_XMPP_WEBSOCKET "true",
+           :TZ "Europe/Amsterdam"}}
+         (second (cut/prosody
+                  {:fqdn "xy.xy.xy"
+                   :namespace "jitsi"}))))
+  (is (= 3
+         (count (cut/prosody
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
\ No newline at end of file

From 289245cc42952109b2a296bd35752e042804f1e9 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 13 Feb 2025 16:52:12 +0100
Subject: [PATCH 04/33] add prosody cfg

---
 src/main/resources/jitsi/prosody-envs-cm.yaml |  8 ++++++++
 src/main/resources/jitsi/prosody-init-cm.yaml | 10 ++++++++++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |  2 +-
 3 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 src/main/resources/jitsi/prosody-envs-cm.yaml
 create mode 100644 src/main/resources/jitsi/prosody-init-cm.yaml

diff --git a/src/main/resources/jitsi/prosody-envs-cm.yaml b/src/main/resources/jitsi/prosody-envs-cm.yaml
new file mode 100644
index 0000000..2901a8e
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-envs-cm.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: prosody
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+data:
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-init-cm.yaml b/src/main/resources/jitsi/prosody-init-cm.yaml
new file mode 100644
index 0000000..13d1440
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-init-cm.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: prosody-cont-inits
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+data:
+  10-config: |
+    # Using prosody /etc/cont-init.d/10-config from container image
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 56b8172..a900ae1 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -334,7 +334,7 @@
          (second (cut/prosody
                   {:fqdn "xy.xy.xy"
                    :namespace "jitsi"}))))
-  (is (= 3
+  (is (= 5
          (count (cut/prosody
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
\ No newline at end of file

From c3ebaa0f2f8fa16e72f73189d0fbb7f69c6a26e6 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 13 Feb 2025 17:12:44 +0100
Subject: [PATCH 05/33] prosody service & test

---
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        |  15 +++
 src/main/resources/jitsi/prosody-service.yaml |  27 +++++
 .../resources/jitsi/prosody-stateful-set.yaml | 106 ++++++++++++++++++
 .../jitsi/prosody-test-deployment.yaml        |  24 ++++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |   2 +-
 5 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 src/main/resources/jitsi/prosody-service.yaml
 create mode 100644 src/main/resources/jitsi/prosody-stateful-set.yaml
 create mode 100644 src/main/resources/jitsi/prosody-test-deployment.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index f7b72ce..342ce61 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -150,5 +150,20 @@
       (cm/replace-all-matching "NAMESPACE" namespace))
      (->
       (yaml/load-as-edn "jitsi/prosody-default-cm.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-envs-cm.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-init-cm.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-stateful-set.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-service.yaml")
+      (cm/replace-all-matching "NAMESPACE" namespace))
+     (->
+      (yaml/load-as-edn "jitsi/prosody-test-deployment.yaml")
       (cm/replace-all-matching "NAMESPACE" namespace))]))
 
diff --git a/src/main/resources/jitsi/prosody-service.yaml b/src/main/resources/jitsi/prosody-service.yaml
new file mode 100644
index 0000000..8d186bb
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-service.yaml
@@ -0,0 +1,27 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: prosody
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+spec:
+  type: ClusterIP
+  ports:
+    - port: 5280
+      protocol: TCP
+      name: tcp-bosh-insecure
+    - port: 5281
+      protocol: TCP
+      name: tcp-bosh-secure
+    - port: 5347
+      protocol: TCP
+      name: tcp-xmpp-component
+    - port: 5222
+      protocol: TCP
+      name: tcp-xmpp-c2
+    - port: 5269
+      protocol: TCP
+      name: tcp-xmpp-s2
+  selector:
+    app.kubernetes.io/name: prosody
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-stateful-set.yaml b/src/main/resources/jitsi/prosody-stateful-set.yaml
new file mode 100644
index 0000000..fd57147
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-stateful-set.yaml
@@ -0,0 +1,106 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: prosody
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+spec:
+  serviceName: "prosody"
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: prosody
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: prosody
+    spec:
+      serviceAccountName: prosody
+      securityContext:
+        {}
+      containers:
+        - name: prosody
+          securityContext:
+            {}
+          image: "jitsi/prosody:stable-9909"
+          imagePullPolicy: IfNotPresent
+          envFrom:
+          - configMapRef:
+              name: prosody
+          - secretRef:
+              name: prosody
+          - secretRef:
+              name: 'prosody-jibri'
+          - secretRef:
+              name: 'prosody-jicofo'
+          - secretRef:
+              name: 'prosody-jigasi'
+          - secretRef:
+              name: 'prosody-jvb'
+          - configMapRef:
+              name: 'prosody-common'
+          ports:
+            - name: xmpp-c2s
+              containerPort: 5222
+              protocol: TCP
+            - name: xmpp-s2s
+              containerPort: 5269
+              protocol: TCP
+            - name: xmpp-component
+              containerPort: 5347
+              protocol: TCP
+            - name: bosh-insecure
+              containerPort: 5280
+              protocol: TCP
+            - name: bosh-secure
+              containerPort: 5281
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              path: /http-bind
+              port: bosh-insecure
+          readinessProbe:
+            httpGet:
+              path: /http-bind
+              port: bosh-insecure
+          resources:
+            {}
+          volumeMounts:
+          - name: config
+            mountPath: /config
+          - name: prosody-data
+            mountPath: /config/data
+      volumes:
+      - name: config
+        emptyDir: {}
+      - name: custom-cont-inits
+        configMap:
+          defaultMode: 493
+          name: prosody-cont-inits
+          items:
+            - key: 10-config
+              path: 10-config
+      - name: custom-defaults
+        configMap:
+          name: prosody-defaults
+          items:
+            - key: prosody.cfg.lua
+              path: prosody.cfg.lua
+            - key: saslauthd.conf
+              path: saslauthd.conf
+            - key: jitsi-meet.cfg.lua
+              path: jitsi-meet.cfg.lua
+      - name: prosody-data
+        persistentVolumeClaim:
+          claimName: prosody-data
+  volumeClaimTemplates:
+  - metadata:
+      name: prosody-data
+    spec:
+      accessModes:
+        - ReadWriteOnce
+      volumeMode: Filesystem
+      resources:
+        requests:
+          storage: 3G
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-test-deployment.yaml b/src/main/resources/jitsi/prosody-test-deployment.yaml
new file mode 100644
index 0000000..55993ce
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-test-deployment.yaml
@@ -0,0 +1,24 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: "prosody-test-connection"
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: "prosody-test-connection"
+spec:
+  replicas: 0
+  strategy:
+    type: Recreate
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: "prosody-test-connection"
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: "prosody-test-connection"
+    spec:
+      containers:
+        - name: wget
+          image: busybox
+          command: ['wget']
+          args: ['prosody:5280/http-bind']
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index a900ae1..27ba072 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -334,7 +334,7 @@
          (second (cut/prosody
                   {:fqdn "xy.xy.xy"
                    :namespace "jitsi"}))))
-  (is (= 5
+  (is (= 8
          (count (cut/prosody
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
\ No newline at end of file

From a4a8c3b319a99edb05add57b6f4f67a9e784a6c3 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Fri, 14 Feb 2025 09:03:39 +0100
Subject: [PATCH 06/33] introduce first prosody secret

---
 src/main/cljc/dda/c4k_jitsi/core.cljc        | 5 +++--
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc       | 7 ++++++-
 src/main/resources/jitsi/prosody-secret.yaml | 9 +++++++++
 3 files changed, 18 insertions(+), 3 deletions(-)
 create mode 100644 src/main/resources/jitsi/prosody-secret.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index e5ba9f4..78ca942 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -33,7 +33,7 @@
           #(not (nil? %))
           (cm/concat-vec
            (ns/generate resolved-config)
-           (jitsi/prosody resolved-config)
+           (jitsi/prosody-config resolved-config)
           ;;  [(jitsi/generate-jvb-service config)
           ;;   (jitsi/generate-web-service config)
           ;;   (jitsi/generate-etherpad-service config)
@@ -56,7 +56,8 @@
        (filter
         #(not (nil? %))
         (cm/concat-vec
-         [(jitsi/generate-secret-jitsi config auth)]
+         (jitsi/prosody-secret auth)
+         ;[(jitsi/generate-secret-jitsi config auth)]
          (when (:contains? config :mon-cfg)
            (mon/generate-auth (:mon-cfg config) (:mon-auth auth)))))))
 
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 342ce61..bdd47d9 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -138,7 +138,7 @@
      (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
      (cm/replace-all-matching "NAMESPACE" namespace))))
 
-(defn-spec prosody cp/map-or-seq?
+(defn-spec prosody-config cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
     [(->
@@ -167,3 +167,8 @@
       (yaml/load-as-edn "jitsi/prosody-test-deployment.yaml")
       (cm/replace-all-matching "NAMESPACE" namespace))]))
 
+(defn-spec prosody-secret cp/map-or-seq?
+  [auth auth?]
+  [(->
+    (yaml/load-as-edn "jitsi/prosody-secret.yaml")
+    (cm/replace-all-matching "NAMESPACE" namespace))])
diff --git a/src/main/resources/jitsi/prosody-secret.yaml b/src/main/resources/jitsi/prosody-secret.yaml
new file mode 100644
index 0000000..4cda16f
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: prosody
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: prosody
+type: Opaque
+data:
\ No newline at end of file

From b79956fe7779b3f5b9d8c5c1474f66d09aa8d1ff Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Fri, 14 Feb 2025 10:57:00 +0100
Subject: [PATCH 07/33] review & finish auth

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  2 +-
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 55 +++++++++----------
 .../jitsi/prosody-auth-jibri-secret.yaml      | 10 ++++
 .../jitsi/prosody-auth-jicofo-secret.yaml     | 13 +++++
 .../jitsi/prosody-auth-jigasi-secret.yaml     | 10 ++++
 .../jitsi/prosody-auth-jvb-secret.yaml        | 12 ++++
 ...y-secret.yaml => prosody-auth-secret.yaml} |  1 +
 ...-cm.yaml => prosody-config-common-cm.yaml} |  1 +
 ...cm.yaml => prosody-config-default-cm.yaml} |  1 +
 ...vs-cm.yaml => prosody-config-envs-cm.yaml} |  1 +
 ...it-cm.yaml => prosody-config-init-cm.yaml} |  1 +
 ...rvice.yaml => prosody-config-service.yaml} |  1 +
 ...aml => prosody-config-serviceaccount.yaml} |  3 +-
 ....yaml => prosody-config-stateful-set.yaml} |  1 +
 ...ml => prosody-config-test-deployment.yaml} |  1 +
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   | 17 ++++--
 16 files changed, 94 insertions(+), 36 deletions(-)
 create mode 100644 src/main/resources/jitsi/prosody-auth-jibri-secret.yaml
 create mode 100644 src/main/resources/jitsi/prosody-auth-jicofo-secret.yaml
 create mode 100644 src/main/resources/jitsi/prosody-auth-jigasi-secret.yaml
 create mode 100644 src/main/resources/jitsi/prosody-auth-jvb-secret.yaml
 rename src/main/resources/jitsi/{prosody-secret.yaml => prosody-auth-secret.yaml} (77%)
 rename src/main/resources/jitsi/{prosody-common-cm.yaml => prosody-config-common-cm.yaml} (93%)
 rename src/main/resources/jitsi/{prosody-default-cm.yaml => prosody-config-default-cm.yaml} (91%)
 rename src/main/resources/jitsi/{prosody-envs-cm.yaml => prosody-config-envs-cm.yaml} (76%)
 rename src/main/resources/jitsi/{prosody-init-cm.yaml => prosody-config-init-cm.yaml} (84%)
 rename src/main/resources/jitsi/{prosody-service.yaml => prosody-config-service.yaml} (92%)
 rename src/main/resources/jitsi/{prosody-sa.yaml => prosody-config-serviceaccount.yaml} (55%)
 rename src/main/resources/jitsi/{prosody-stateful-set.yaml => prosody-config-stateful-set.yaml} (98%)
 rename src/main/resources/jitsi/{prosody-test-deployment.yaml => prosody-config-test-deployment.yaml} (93%)

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 78ca942..76291a3 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -56,7 +56,7 @@
        (filter
         #(not (nil? %))
         (cm/concat-vec
-         (jitsi/prosody-secret auth)
+         (jitsi/prosody-auth auth)
          ;[(jitsi/generate-secret-jitsi config auth)]
          (when (:contains? config :mon-cfg)
            (mon/generate-auth (:mon-cfg config) (:mon-auth auth)))))))
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index bdd47d9..2b58835 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -138,37 +138,36 @@
      (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
      (cm/replace-all-matching "NAMESPACE" namespace))))
 
+(defn- load-and-adjust-namespace
+  [file namespace]
+  (->
+   (yaml/load-as-edn file)
+   (cm/replace-all-matching "NAMESPACE" namespace)))
+
 (defn-spec prosody-config cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
-    [(->
-      (yaml/load-as-edn "jitsi/prosody-sa.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
+    [(load-and-adjust-namespace "jitsi/prosody-config-serviceaccount.yaml" namespace)
      (->
-      (yaml/load-as-edn "jitsi/prosody-common-cm.yaml")
-      (cm/replace-all-matching "JITSI_FQDN" fqdn)
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-default-cm.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-envs-cm.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-init-cm.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-stateful-set.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-service.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))
-     (->
-      (yaml/load-as-edn "jitsi/prosody-test-deployment.yaml")
-      (cm/replace-all-matching "NAMESPACE" namespace))]))
+      (load-and-adjust-namespace "jitsi/prosody-config-common-cm.yaml" namespace)
+      (cm/replace-all-matching "JITSI_FQDN" fqdn))
+     (load-and-adjust-namespace "jitsi/prosody-config-default-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-envs-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-init-cm.yaml"namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-stateful-set.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-test-deployment.yaml" namespace)]))
 
-(defn-spec prosody-secret cp/map-or-seq?
+(defn-spec prosody-auth cp/map-or-seq?
   [auth auth?]
-  [(->
-    (yaml/load-as-edn "jitsi/prosody-secret.yaml")
-    (cm/replace-all-matching "NAMESPACE" namespace))])
+  (let [{:keys [jvb-auth-password jicofo-auth-password jicofo-component-secret]} auth]
+  [(load-and-adjust-namespace "jitsi/prosody-auth-secret.yaml" namespace)
+   (load-and-adjust-namespace "jitsi/prosody-auth-jibri-secret.yaml" namespace)
+   (->
+    (load-and-adjust-namespace "jitsi/prosody-auth-jicofo-secret.yaml" namespace)
+    (cm/replace-key-value :JICOFO_AUTH_PASSWORD (b64/encode jicofo-auth-password))
+    (cm/replace-key-value :JICOFO_COMPONENT_SECRET (b64/encode jicofo-component-secret)))
+   (load-and-adjust-namespace "jitsi/prosody-auth-jigasi-secret.yaml" namespace)
+   (-> 
+    (load-and-adjust-namespace "jitsi/prosody-auth-jvb-secret.yaml" namespace)
+    (cm/replace-key-value :JVB_AUTH_PASSWORD (b64/encode jvb-auth-password)))]))
diff --git a/src/main/resources/jitsi/prosody-auth-jibri-secret.yaml b/src/main/resources/jitsi/prosody-auth-jibri-secret.yaml
new file mode 100644
index 0000000..32954d3
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-auth-jibri-secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: prosody-jibri
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+type: Opaque
+data:
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-auth-jicofo-secret.yaml b/src/main/resources/jitsi/prosody-auth-jicofo-secret.yaml
new file mode 100644
index 0000000..77b2bfb
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-auth-jicofo-secret.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: prosody-jicofo
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jicofo
+type: Opaque
+data:
+  JICOFO_AUTH_USER: 'Zm9jdXM='
+  JICOFO_AUTH_PASSWORD: REPLACE_ME
+  JICOFO_COMPONENT_SECRET: REPLACE_ME
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-auth-jigasi-secret.yaml b/src/main/resources/jitsi/prosody-auth-jigasi-secret.yaml
new file mode 100644
index 0000000..eaa13bf
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-auth-jigasi-secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: prosody-jigasi
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jigasi
+type: Opaque
+data:
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-auth-jvb-secret.yaml b/src/main/resources/jitsi/prosody-auth-jvb-secret.yaml
new file mode 100644
index 0000000..e741e2e
--- /dev/null
+++ b/src/main/resources/jitsi/prosody-auth-jvb-secret.yaml
@@ -0,0 +1,12 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: prosody-jvb
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jvb
+type: Opaque
+data:
+  JVB_AUTH_USER: 'anZi'
+  JVB_AUTH_PASSWORD: REPLACE_ME
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-secret.yaml b/src/main/resources/jitsi/prosody-auth-secret.yaml
similarity index 77%
rename from src/main/resources/jitsi/prosody-secret.yaml
rename to src/main/resources/jitsi/prosody-auth-secret.yaml
index 4cda16f..2022112 100644
--- a/src/main/resources/jitsi/prosody-secret.yaml
+++ b/src/main/resources/jitsi/prosody-auth-secret.yaml
@@ -5,5 +5,6 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 type: Opaque
 data:
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-common-cm.yaml b/src/main/resources/jitsi/prosody-config-common-cm.yaml
similarity index 93%
rename from src/main/resources/jitsi/prosody-common-cm.yaml
rename to src/main/resources/jitsi/prosody-config-common-cm.yaml
index 5619166..43040fa 100644
--- a/src/main/resources/jitsi/prosody-common-cm.yaml
+++ b/src/main/resources/jitsi/prosody-config-common-cm.yaml
@@ -6,6 +6,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: prosody
 data:
   ENABLE_AUTH: "0"
   ENABLE_GUESTS: "1"
diff --git a/src/main/resources/jitsi/prosody-default-cm.yaml b/src/main/resources/jitsi/prosody-config-default-cm.yaml
similarity index 91%
rename from src/main/resources/jitsi/prosody-default-cm.yaml
rename to src/main/resources/jitsi/prosody-config-default-cm.yaml
index 04d1cd4..71193b0 100644
--- a/src/main/resources/jitsi/prosody-default-cm.yaml
+++ b/src/main/resources/jitsi/prosody-config-default-cm.yaml
@@ -5,6 +5,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 data:
   prosody.cfg.lua: |
     # Using prosody /default/prosody.cfg.lua from container image
diff --git a/src/main/resources/jitsi/prosody-envs-cm.yaml b/src/main/resources/jitsi/prosody-config-envs-cm.yaml
similarity index 76%
rename from src/main/resources/jitsi/prosody-envs-cm.yaml
rename to src/main/resources/jitsi/prosody-config-envs-cm.yaml
index 2901a8e..d83d8f4 100644
--- a/src/main/resources/jitsi/prosody-envs-cm.yaml
+++ b/src/main/resources/jitsi/prosody-config-envs-cm.yaml
@@ -5,4 +5,5 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 data:
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-init-cm.yaml b/src/main/resources/jitsi/prosody-config-init-cm.yaml
similarity index 84%
rename from src/main/resources/jitsi/prosody-init-cm.yaml
rename to src/main/resources/jitsi/prosody-config-init-cm.yaml
index 13d1440..779e900 100644
--- a/src/main/resources/jitsi/prosody-init-cm.yaml
+++ b/src/main/resources/jitsi/prosody-config-init-cm.yaml
@@ -5,6 +5,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 data:
   10-config: |
     # Using prosody /etc/cont-init.d/10-config from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-service.yaml b/src/main/resources/jitsi/prosody-config-service.yaml
similarity index 92%
rename from src/main/resources/jitsi/prosody-service.yaml
rename to src/main/resources/jitsi/prosody-config-service.yaml
index 8d186bb..54e6db2 100644
--- a/src/main/resources/jitsi/prosody-service.yaml
+++ b/src/main/resources/jitsi/prosody-config-service.yaml
@@ -5,6 +5,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 spec:
   type: ClusterIP
   ports:
diff --git a/src/main/resources/jitsi/prosody-sa.yaml b/src/main/resources/jitsi/prosody-config-serviceaccount.yaml
similarity index 55%
rename from src/main/resources/jitsi/prosody-sa.yaml
rename to src/main/resources/jitsi/prosody-config-serviceaccount.yaml
index 765094f..740da57 100644
--- a/src/main/resources/jitsi/prosody-sa.yaml
+++ b/src/main/resources/jitsi/prosody-config-serviceaccount.yaml
@@ -4,4 +4,5 @@ metadata:
   name: prosody
   namespace: NAMESPACE
   labels:
-    app.kubernetes.io/name: prosody
\ No newline at end of file
+    app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-stateful-set.yaml b/src/main/resources/jitsi/prosody-config-stateful-set.yaml
similarity index 98%
rename from src/main/resources/jitsi/prosody-stateful-set.yaml
rename to src/main/resources/jitsi/prosody-config-stateful-set.yaml
index fd57147..7174b05 100644
--- a/src/main/resources/jitsi/prosody-stateful-set.yaml
+++ b/src/main/resources/jitsi/prosody-config-stateful-set.yaml
@@ -5,6 +5,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: prosody
+    app.kubernetes.io/component: prosody
 spec:
   serviceName: "prosody"
   replicas: 1
diff --git a/src/main/resources/jitsi/prosody-test-deployment.yaml b/src/main/resources/jitsi/prosody-config-test-deployment.yaml
similarity index 93%
rename from src/main/resources/jitsi/prosody-test-deployment.yaml
rename to src/main/resources/jitsi/prosody-config-test-deployment.yaml
index 55993ce..6ea9c08 100644
--- a/src/main/resources/jitsi/prosody-test-deployment.yaml
+++ b/src/main/resources/jitsi/prosody-config-test-deployment.yaml
@@ -5,6 +5,7 @@ metadata:
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: "prosody-test-connection"
+    app.kubernetes.io/component: prosody
 spec:
   replicas: 0
   strategy:
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 27ba072..9025a57 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -306,8 +306,8 @@
           {:name "prosody",
            :namespace "jitsi",
            :labels
-           {:app.kubernetes.io/name "prosody"}}}
-         (first (cut/prosody
+           #:app.kubernetes.io{:name "prosody" :component "prosody"}}}
+         (first (cut/prosody-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"}))))
   (is (= {:apiVersion "v1",
@@ -316,7 +316,7 @@
           {:name "prosody-common",
            :namespace "jitsi",
            :labels
-           #:app.kubernetes.io{:name "jitsi-meet"}},
+           #:app.kubernetes.io{:name "jitsi-meet" :component "prosody"}},
           :data
           {:ENABLE_AUTH "0",
            :ENABLE_GUESTS "1",
@@ -331,10 +331,15 @@
            :ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX "1",
            :ENABLE_XMPP_WEBSOCKET "true",
            :TZ "Europe/Amsterdam"}}
-         (second (cut/prosody
+         (second (cut/prosody-config
                   {:fqdn "xy.xy.xy"
                    :namespace "jitsi"}))))
   (is (= 8
-         (count (cut/prosody
+         (count (cut/prosody-config
                  {:fqdn "xy.xy.xy"
-                  :namespace "jitsi"})))))
\ No newline at end of file
+                  :namespace "jitsi"}))))
+   (is (= 5
+         (count (cut/prosody-auth
+                 {:jvb-auth-password "jvb-auth"
+                  :jicofo-auth-password "jicofo-auth"
+                  :jicofo-component-secret "jicofo-comp"})))))
\ No newline at end of file

From 13c5ac14c9818cadbc518962d3e2b373d26ae3cd Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Fri, 14 Feb 2025 13:49:17 +0100
Subject: [PATCH 08/33] fix ns for secrets

---
 src/main/cljc/dda/c4k_jitsi/core.cljc       | 6 +++---
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc      | 6 ++++--
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc | 2 ++
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 76291a3..8f44e88 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -52,12 +52,12 @@
 (defn-spec auth-objects cp/map-or-seq?
   [config config?
    auth auth?]
+  (let [resolved-config (merge config-defaults config)]
   (map yaml/to-string
        (filter
         #(not (nil? %))
         (cm/concat-vec
-         (jitsi/prosody-auth auth)
+         (jitsi/prosody-auth config auth)
          ;[(jitsi/generate-secret-jitsi config auth)]
          (when (:contains? config :mon-cfg)
-           (mon/generate-auth (:mon-cfg config) (:mon-auth auth)))))))
-
+           (mon/generate-auth (:mon-cfg config) (:mon-auth auth))))))))
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 2b58835..449a498 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -159,8 +159,10 @@
      (load-and-adjust-namespace "jitsi/prosody-config-test-deployment.yaml" namespace)]))
 
 (defn-spec prosody-auth cp/map-or-seq?
-  [auth auth?]
-  (let [{:keys [jvb-auth-password jicofo-auth-password jicofo-component-secret]} auth]
+  [config config?
+   auth auth?]
+  (let [{:keys [namespace]} config
+        {:keys [jvb-auth-password jicofo-auth-password jicofo-component-secret]} auth]
   [(load-and-adjust-namespace "jitsi/prosody-auth-secret.yaml" namespace)
    (load-and-adjust-namespace "jitsi/prosody-auth-jibri-secret.yaml" namespace)
    (->
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 9025a57..2933d5e 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -340,6 +340,8 @@
                   :namespace "jitsi"}))))
    (is (= 5
          (count (cut/prosody-auth
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"}
                  {:jvb-auth-password "jvb-auth"
                   :jicofo-auth-password "jicofo-auth"
                   :jicofo-component-secret "jicofo-comp"})))))
\ No newline at end of file

From 2dc78e87af6fdd099e74b9af0b0ede35e7eefebd Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Fri, 14 Feb 2025 15:02:40 +0100
Subject: [PATCH 09/33] no longer used

---
 src/main/resources/jitsi/secret.yaml | 10 ----------
 1 file changed, 10 deletions(-)
 delete mode 100644 src/main/resources/jitsi/secret.yaml

diff --git a/src/main/resources/jitsi/secret.yaml b/src/main/resources/jitsi/secret.yaml
deleted file mode 100644
index 771b05a..0000000
--- a/src/main/resources/jitsi/secret.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
-  name: jitsi-config
-  namespace: NAMESPACE
-type: Opaque
-data:
-  JVB_AUTH_PASSWORD: "jvb-auth"
-  JICOFO_AUTH_PASSWORD: "jicofo-auth"
-  JICOFO_COMPONENT_SECRET: "comp-sec"
\ No newline at end of file

From 524fae676f901b8591d7b620927dd473703ab4d6 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 11:31:11 +0100
Subject: [PATCH 10/33] add jibri

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |   2 +
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        |  15 ++
 src/main/resources/jitsi/deployment.yaml      |  31 ---
 .../jitsi/jibri-config-default-cm.yaml        |  20 ++
 .../jitsi/jibri-config-deployment.yaml        |  95 +++++++
 .../resources/jitsi/jibri-config-envs.yaml    |  16 ++
 .../resources/jitsi/jibri-config-init-cm.yaml |  11 +
 .../resources/jitsi/jibri-config-service.yaml |  22 ++
 .../jitsi/jitsi-config-serviceaccount.yaml    |   7 +
 .../jitsi/prosody-config-common-cm.yaml       |   4 +-
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   | 236 ++----------------
 11 files changed, 211 insertions(+), 248 deletions(-)
 create mode 100644 src/main/resources/jitsi/jibri-config-default-cm.yaml
 create mode 100644 src/main/resources/jitsi/jibri-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/jibri-config-envs.yaml
 create mode 100644 src/main/resources/jitsi/jibri-config-init-cm.yaml
 create mode 100644 src/main/resources/jitsi/jibri-config-service.yaml
 create mode 100644 src/main/resources/jitsi/jitsi-config-serviceaccount.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 8f44e88..4eb4548 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -34,6 +34,8 @@
           (cm/concat-vec
            (ns/generate resolved-config)
            (jitsi/prosody-config resolved-config)
+           (jitsi/jitsi-config resolved-config)
+           (jitsi/jibri-config resolved-config)
           ;;  [(jitsi/generate-jvb-service config)
           ;;   (jitsi/generate-web-service config)
           ;;   (jitsi/generate-etherpad-service config)
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 449a498..5bb4f8d 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -173,3 +173,18 @@
    (-> 
     (load-and-adjust-namespace "jitsi/prosody-auth-jvb-secret.yaml" namespace)
     (cm/replace-key-value :JVB_AUTH_PASSWORD (b64/encode jvb-auth-password)))]))
+
+(defn-spec jitsi-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    [(load-and-adjust-namespace "jitsi/jitsi-config-serviceaccount.yaml" namespace)]))
+
+(defn-spec jibri-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    [(load-and-adjust-namespace "jitsi/jitsi-config-serviceaccount.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jibri-config-default-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jibri-config-envs.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jibri-config-init-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jibri-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jibri-config-deployment.yaml" namespace)]))
diff --git a/src/main/resources/jitsi/deployment.yaml b/src/main/resources/jitsi/deployment.yaml
index 318eb50..60ce776 100644
--- a/src/main/resources/jitsi/deployment.yaml
+++ b/src/main/resources/jitsi/deployment.yaml
@@ -37,37 +37,6 @@ spec:
                   key: JICOFO_AUTH_PASSWORD
             - name: TZ
               value: Europe/Berlin
-        - name: prosody
-          image: jitsi/prosody:stable-9646
-          imagePullPolicy: IfNotPresent
-          env:
-            - name: PUBLIC_URL
-              value: REPLACE_JITSI_FQDN
-            - name: XMPP_SERVER
-              value: localhost
-            - name: JICOFO_COMPONENT_SECRET
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_COMPONENT_SECRET
-            - name: JVB_AUTH_USER
-              value: jvb
-            - name: JVB_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JVB_AUTH_PASSWORD
-            - name: JICOFO_AUTH_USER
-              value: focus
-            - name: JICOFO_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_AUTH_PASSWORD
-            - name: TZ
-              value: Europe/Berlin
-            - name: JVB_TCP_HARVESTER_DISABLED
-              value: "true"
         - name: web
           image: domaindrivenarchitecture/c4k-jitsi-web
           imagePullPolicy: IfNotPresent
diff --git a/src/main/resources/jitsi/jibri-config-default-cm.yaml b/src/main/resources/jitsi/jibri-config-default-cm.yaml
new file mode 100644
index 0000000..3022246
--- /dev/null
+++ b/src/main/resources/jitsi/jibri-config-default-cm.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jibri-defaults
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+data:
+  jibri.conf: |
+    # Using jibri /default/jibri.conf from container image
+    
+  logging.properties: |
+    # Using jibri /default/logging.properties from container image
+    
+  autoscaler-sidecar.config: |
+    # Using jibri /default/autoscaler-sidecar.config from container image
+    
+  xorg-video-dummy.conf: |
+    # Using jibri /default/xorg-video-dummy.conf from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jibri-config-deployment.yaml b/src/main/resources/jitsi/jibri-config-deployment.yaml
new file mode 100644
index 0000000..5e12829
--- /dev/null
+++ b/src/main/resources/jitsi/jibri-config-deployment.yaml
@@ -0,0 +1,95 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: jitsi-meet-jibri
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: jitsi-meet
+      app.kubernetes.io/component: jibri
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: jitsi-meet
+        app.kubernetes.io/component: jibri
+    spec:
+      serviceAccountName: jitsi-meet
+      containers:
+      - name: jitsi-meet
+        securityContext:
+          capabilities:
+            add: ["SYS_ADMIN"]
+        image: "jitsi/jibri:stable-9646"
+        imagePullPolicy: IfNotPresent
+        ports:
+        - name: http-internal
+          containerPort: 3333
+        - name: http-api
+          containerPort: 2222
+        livenessProbe:
+          exec:
+            command:
+            - /bin/bash
+            - -c
+            - curl -sq localhost:2222/jibri/api/v1.0/health | jq '"\(.status.health.healthStatus)
+              \(.status.busyStatus)"' | grep -qP 'HEALTHY (IDLE|BUSY)'
+          failureThreshold: 2
+          initialDelaySeconds: 5
+          periodSeconds: 5
+        readinessProbe:
+          exec:
+            command:
+            - /bin/bash
+            - -c
+            - curl -sq localhost:2222/jibri/api/v1.0/health | jq '"\(.status.health.healthStatus)
+              \(.status.busyStatus)"' | grep -qP 'HEALTHY (IDLE|BUSY)'
+          failureThreshold: 2
+          initialDelaySeconds: 5
+          periodSeconds: 5
+
+        envFrom:
+        - secretRef:
+            name: prosody-jibri
+        - configMapRef:
+            name: prosody-common
+        - configMapRef:
+            name: jitsi-meet-jibri
+
+        resources:
+            {}
+
+        volumeMounts:
+        - name: config
+          mountPath: /config
+        - name: jibri-data
+          mountPath: /data
+
+      volumes:
+      - name: config
+        emptyDir: {}
+      - name: custom-cont-inits
+        configMap:
+          defaultMode: 493
+          name: jitsi-meet-jibri-cont-inits
+          items:
+            - key: 10-config
+              path: 10-config
+      - name: custom-defaults
+        configMap:
+          name: jitsi-meet-jibri-defaults
+          items:
+            - key: jibri.conf
+              path: jibri.conf
+            - key: logging.properties
+              path: logging.properties
+            - key: autoscaler-sidecar.config
+              path: autoscaler-sidecar.config
+            - key: xorg-video-dummy.conf
+              path: xorg-video-dummy.conf
+      - name: jibri-data
+        emptyDir: {}
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jibri-config-envs.yaml b/src/main/resources/jitsi/jibri-config-envs.yaml
new file mode 100644
index 0000000..fa43c0d
--- /dev/null
+++ b/src/main/resources/jitsi/jibri-config-envs.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jibri
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+data:
+  XMPP_SERVER: 'prosody.NAMESPACE.svc.cluster.local'
+  JIBRI_BREWERY_MUC: 'jibribrewery'
+  JIBRI_RECORDING_DIR: '/data/recordings'
+  JIBRI_FINALIZE_RECORDING_SCRIPT_PATH: "/config/finalize.sh"
+  JIBRI_STRIP_DOMAIN_JID: muc
+  DISPLAY: ":0"
+  JIBRI_SINGLE_USE_MODE: "true"
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jibri-config-init-cm.yaml b/src/main/resources/jitsi/jibri-config-init-cm.yaml
new file mode 100644
index 0000000..bc9510b
--- /dev/null
+++ b/src/main/resources/jitsi/jibri-config-init-cm.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jibri-cont-inits
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+data:
+  10-config: |
+    # Using jibri /etc/cont-init.d/10-config from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jibri-config-service.yaml b/src/main/resources/jitsi/jibri-config-service.yaml
new file mode 100644
index 0000000..31072cf
--- /dev/null
+++ b/src/main/resources/jitsi/jibri-config-service.yaml
@@ -0,0 +1,22 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: jitsi-meet-jibri
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
+spec:
+  type: ClusterIP
+  ports:
+  - name: http-internal
+    port: 3333
+    targetPort: 3333
+    protocol: TCP
+  - name: http-api
+    port: 2222
+    targetPort: 2222
+    protocol: TCP
+  selector:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jibri
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jitsi-config-serviceaccount.yaml b/src/main/resources/jitsi/jitsi-config-serviceaccount.yaml
new file mode 100644
index 0000000..d6ab876
--- /dev/null
+++ b/src/main/resources/jitsi/jitsi-config-serviceaccount.yaml
@@ -0,0 +1,7 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: jitsi-meet
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
\ No newline at end of file
diff --git a/src/main/resources/jitsi/prosody-config-common-cm.yaml b/src/main/resources/jitsi/prosody-config-common-cm.yaml
index 43040fa..8f0e06e 100644
--- a/src/main/resources/jitsi/prosody-config-common-cm.yaml
+++ b/src/main/resources/jitsi/prosody-config-common-cm.yaml
@@ -20,4 +20,6 @@ data:
   ENABLE_COLIBRI_WEBSOCKET: 'true'
   ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX: '1'
   ENABLE_XMPP_WEBSOCKET: 'true'
-  TZ: 'Europe/Amsterdam'
\ No newline at end of file
+  ENABLE_RECORDING: "true"
+  ENABLE_FILE_RECORDING_SERVICE_SHARING: "true"
+  TZ: 'Europe/Berlin'
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 2933d5e..89ca2c8 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -5,220 +5,10 @@
    [clojure.spec.test.alpha :as st]
    [dda.c4k-jitsi.jitsi :as cut]))
 
-(st/instrument `cut/generate-deployment)
-(st/instrument `cut/generate-secret-jitsi)
-(st/instrument `cut/generate-ingress-web)
-(st/instrument `cut/generate-jvb-service)
-
-(deftest should-generate-deployment
-  (is (= {:apiVersion "apps/v1",
-          :kind "Deployment",
-          :metadata
-          {:labels {:app "jitsi"},
-           :name "jitsi"
-           :namespace "jitsi"},
-          :spec
-          {:strategy {:type "Recreate"},
-           :selector {:matchLabels {:app "jitsi"}},
-           :template
-           {:metadata {:labels {:app "jitsi"}},
-            :spec
-            {:containers
-             [{:name "jicofo",
-               :image "jitsi/jicofo:stable-9646",
-               :imagePullPolicy "IfNotPresent",
-               :env
-               [{:name "XMPP_SERVER", :value "localhost"}
-                {:name "JICOFO_COMPONENT_SECRET",
-                 :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_COMPONENT_SECRET"}}}
-                {:name "JICOFO_AUTH_USER", :value "focus"}
-                {:name "JICOFO_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_AUTH_PASSWORD"}}}
-                {:name "TZ", :value "Europe/Berlin"}]}
-              {:name "prosody",
-               :image "jitsi/prosody:stable-9646",
-               :imagePullPolicy "IfNotPresent",
-               :env
-               [{:name "PUBLIC_URL", :value "xy.xy.xy"}
-                {:name "XMPP_SERVER", :value "localhost"}
-                {:name "JICOFO_COMPONENT_SECRET",
-                 :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_COMPONENT_SECRET"}}}
-                {:name "JVB_AUTH_USER", :value "jvb"}
-                {:name "JVB_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JVB_AUTH_PASSWORD"}}}
-                {:name "JICOFO_AUTH_USER", :value "focus"}
-                {:name "JICOFO_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_AUTH_PASSWORD"}}}
-                {:name "TZ", :value "Europe/Berlin"}
-                {:name "JVB_TCP_HARVESTER_DISABLED", :value "true"}]}
-              {:name "web",
-               :image "domaindrivenarchitecture/c4k-jitsi-web",
-               :imagePullPolicy "IfNotPresent",
-               :env
-               [{:name "PUBLIC_URL", :value "xy.xy.xy"}
-                {:name "XMPP_SERVER", :value "localhost"}
-                {:name "XMPP_BOSH_URL_BASE", :value "http://127.0.0.1:5280"}
-                {:name "JICOFO_AUTH_USER", :value "focus"}
-                {:name "TZ", :value "Europe/Berlin"}
-                {:name "JVB_TCP_HARVESTER_DISABLED", :value "true"}
-                {:name "DEFAULT_LANGUAGE", :value "de"}
-                {:name "RESOLUTION", :value "480"}
-                {:name "RESOLUTION_MIN", :value "240"}
-                {:name "RESOLUTION_WIDTH", :value "853"}
-                {:name "RESOLUTION_WIDTH_MIN", :value "427"}
-                {:name "DISABLE_AUDIO_LEVELS", :value "true"}
-                {:name "ETHERPAD_PUBLIC_URL", :value "https://etherpad.xy.xy.xy/p/"}
-                {:name "WHITEBOARD_ENABLED", :value "true"}
-                {:name "WHITEBOARD_COLLAB_SERVER_PUBLIC_URL", :value "https://excalidraw-backend.xy.xy.xy"}
-                {:name "COLIBRI_WEBSOCKET_REGEX", :value "127.0.0.1"}]}
-              {:name "jvb",
-               :image "jitsi/jvb:stable-9646",
-               :imagePullPolicy "IfNotPresent",
-               :env
-               [{:name "PUBLIC_URL", :value "xy.xy.xy"}
-                {:name "XMPP_SERVER", :value "localhost"}
-                {:name "DOCKER_HOST_ADDRESS", :value "xy.xy.xy"}
-                {:name "JICOFO_AUTH_USER", :value "focus"}
-                {:name "JVB_TCP_HARVESTER_DISABLED", :value "true"}
-                {:name "JVB_AUTH_USER", :value "jvb"}
-                {:name "JVB_PORT", :value "30300"}
-                {:name "JVB_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JVB_AUTH_PASSWORD"}}}
-                {:name "JICOFO_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_AUTH_PASSWORD"}}}
-                {:name "TZ", :value "Europe/Berlin"}]}
-              {:name "etherpad",
-               :image "etherpad/etherpad:2",
-               :env
-               [{:name "XMPP_SERVER", :value "localhost"}
-                {:name "JICOFO_COMPONENT_SECRET",
-                 :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_COMPONENT_SECRET"}}}
-                {:name "JICOFO_AUTH_USER", :value "focus"}
-                {:name "JICOFO_AUTH_PASSWORD", :valueFrom {:secretKeyRef {:name "jitsi-config", :key "JICOFO_AUTH_PASSWORD"}}}
-                {:name "TZ", :value "Europe/Berlin"}]}]}}}}
-         (cut/generate-deployment {:fqdn "xy.xy.xy"
-                                   :namespace "jitsi"}))))
-
-(deftest should-generate-secret
-  (is (= {:apiVersion "v1",
-          :kind "Secret",
-          :metadata 
-          {:name "jitsi-config"
-           :namespace "jitsi"},
-          :type "Opaque",
-          :data
-          {:JVB_AUTH_PASSWORD "anZiLWF1dGg=",
-           :JICOFO_AUTH_PASSWORD "amljb2ZvLWF1dGg=",
-           :JICOFO_COMPONENT_SECRET "amljb2ZvLWNvbXA="}}
-         (cut/generate-secret-jitsi 
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}
-          {:jvb-auth-password "jvb-auth"
-           :jicofo-auth-password "jicofo-auth"
-           :jicofo-component-secret "jicofo-comp"}))))
-                                                        
-  (deftest should-generate-ingress-web
-    (is (= [{:apiVersion "cert-manager.io/v1",
-            :kind "Certificate",
-            :metadata
-            {:name "web",
-             :labels {:app.kubernetes.part-of "web"},
-             :namespace "jitsi"},
-            :spec
-            {:secretName "web",
-             :commonName "xy.xy.xy",
-             :duration "2160h",
-             :renewBefore "720h",
-             :dnsNames ["xy.xy.xy"],
-             :issuerRef {:name "staging", :kind "ClusterIssuer"}}}
-           {:apiVersion "networking.k8s.io/v1",
-            :kind "Ingress",
-            :metadata
-            {:namespace "jitsi",
-             :annotations
-             {:traefik.ingress.kubernetes.io/router.entrypoints "web, websecure",
-              :traefik.ingress.kubernetes.io/router.middlewares
-              "default-redirect-https@kubernetescrd",
-              :metallb.universe.tf/address-pool "public"},
-             :name "web",
-             :labels {:app.kubernetes.part-of "web"}},
-            :spec
-            {:tls [{:hosts ["xy.xy.xy"], :secretName "web"}],
-             :rules
-             [{:host "xy.xy.xy",
-               :http
-               {:paths
-                [{:pathType "Prefix",
-                  :path "/",
-                  :backend {:service {:name "web", :port {:number 80}}}}]}}]}}]
-           (cut/generate-ingress-web
-            {:fqdn "xy.xy.xy"
-             :namespace "jitsi"}))))
-
-(deftest should-generate-ingress-modelector
-  (is (= [{:apiVersion "cert-manager.io/v1",
-           :kind "Certificate",
-           :metadata
-           {:name "modelector",
-            :labels {:app.kubernetes.part-of "modelector"},
-            :namespace "jitsi"},
-           :spec
-           {:secretName "modelector",
-            :commonName "modelector.xy.xy",
-            :duration "2160h",
-            :renewBefore "720h",
-            :dnsNames ["modelector.xy.xy"],
-            :issuerRef {:name "staging", :kind "ClusterIssuer"}}}
-          {:apiVersion "networking.k8s.io/v1",
-           :kind "Ingress",
-           :metadata
-           {:namespace "jitsi",
-            :annotations
-            {:traefik.ingress.kubernetes.io/router.entrypoints "web, websecure",
-             :traefik.ingress.kubernetes.io/router.middlewares
-             "default-redirect-https@kubernetescrd",
-             :metallb.universe.tf/address-pool "public"},
-            :name "modelector",
-            :labels {:app.kubernetes.part-of "modelector"}},
-           :spec
-           {:tls [{:hosts ["modelector.xy.xy"], :secretName "modelector"}],
-            :rules
-            [{:host "modelector.xy.xy",
-              :http
-              {:paths
-               [{:pathType "Prefix",
-                 :path "/",
-                 :backend {:service {:name "modelector", :port {:number 80}}}}]}}]}}]
-         (cut/generate-ingress-modelector
-          {:fqdn "xy.xy"
-           :namespace "jitsi"}))))
-
-(deftest should-generate-jvb-service
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata
-          {:labels {:service "jvb"},
-           :annotations
-           #:metallb.universe.tf{:allow-shared-ip "shared-ip-service-group",
-                                 :address-pool "public"},
-           :name "jvb-udp"
-           :namespace "jitsi"},
-          :spec
-          {:type "LoadBalancer",
-           :ports
-           [{:port 30300, :protocol "UDP", :targetPort 30300, :nodePort 30300}],
-           :selector {:app "jitsi"}}}
-         (cut/generate-jvb-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
-
-(deftest should-generate-web-service
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata {:labels {:service "web"}, :name "web", :namespace "jitsi"},
-          :spec
-          {:ports
-           [{:name "http", :port 80, :targetPort 80}
-            {:name "https", :port 443, :targetPort 443}],
-           :selector {:app "jitsi"}}}
-         (cut/generate-web-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
+(st/instrument `cut/prosody-config)
+(st/instrument `cut/prosody-auth)
+(st/instrument `cut/jitsi-config)
+(st/instrument `cut/jibri-config)
 
 (deftest should-generate-etherpad-service
   (is (= {:apiVersion "v1",
@@ -330,7 +120,9 @@
            :ENABLE_COLIBRI_WEBSOCKET "true",
            :ENABLE_COLIBRI_WEBSOCKET_UNSAFE_REGEX "1",
            :ENABLE_XMPP_WEBSOCKET "true",
-           :TZ "Europe/Amsterdam"}}
+           :ENABLE_RECORDING "true",
+           :ENABLE_FILE_RECORDING_SERVICE_SHARING "true",
+           :TZ "Europe/Berlin"}}
          (second (cut/prosody-config
                   {:fqdn "xy.xy.xy"
                    :namespace "jitsi"}))))
@@ -344,4 +136,16 @@
                   :namespace "jitsi"}
                  {:jvb-auth-password "jvb-auth"
                   :jicofo-auth-password "jicofo-auth"
-                  :jicofo-component-secret "jicofo-comp"})))))
\ No newline at end of file
+                  :jicofo-component-secret "jicofo-comp"})))))
+
+(deftest should-generate-jitsi
+  (is (= 1
+         (count (cut/jitsi-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+
+(deftest should-generate-jibri
+  (is (= 6
+         (count (cut/jibri-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))

From 360b4d135703cdf3f882a7320ae08aefdabe4106 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 13:23:09 +0100
Subject: [PATCH 11/33] add jicofo

---
 build.py                                      |  2 +-
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  1 +
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 16 ++++-
 .../jitsi/jicofo-config-defaults-cm.yaml      | 14 ++++
 .../jitsi/jicofo-config-deployment.yaml       | 70 +++++++++++++++++++
 .../jitsi/jicofo-config-envs-cm.yaml          | 13 ++++
 .../jitsi/jicofo-config-init-cm.yaml          | 11 +++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |  6 ++
 8 files changed, 130 insertions(+), 3 deletions(-)
 create mode 100644 src/main/resources/jitsi/jicofo-config-defaults-cm.yaml
 create mode 100644 src/main/resources/jitsi/jicofo-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/jicofo-config-envs-cm.yaml
 create mode 100644 src/main/resources/jitsi/jicofo-config-init-cm.yaml

diff --git a/build.py b/build.py
index 14045cf..1500086 100644
--- a/build.py
+++ b/build.py
@@ -165,12 +165,12 @@ def lint(project):
 @task
 def inst(project):
     package_uberjar(project)
-    package_native(project)
     run(
         f"sudo install -m=755 target/uberjar/{project.name}-standalone.jar /usr/local/bin/{project.name}-standalone.jar",
         shell=True,
         check=True,
     )
+    package_native(project)
     run(
         f"sudo install -m=755 target/graalvm/{project.name} /usr/local/bin/{project.name}",
         shell=True,
diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 4eb4548..84281b9 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -34,6 +34,7 @@
           (cm/concat-vec
            (ns/generate resolved-config)
            (jitsi/prosody-config resolved-config)
+           (jitsi/jicofo-config resolved-config)
            (jitsi/jitsi-config resolved-config)
            (jitsi/jibri-config resolved-config)
           ;;  [(jitsi/generate-jvb-service config)
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 5bb4f8d..b2c504b 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -153,7 +153,7 @@
       (cm/replace-all-matching "JITSI_FQDN" fqdn))
      (load-and-adjust-namespace "jitsi/prosody-config-default-cm.yaml" namespace)
      (load-and-adjust-namespace "jitsi/prosody-config-envs-cm.yaml" namespace)
-     (load-and-adjust-namespace "jitsi/prosody-config-init-cm.yaml"namespace)
+     (load-and-adjust-namespace "jitsi/prosody-config-init-cm.yaml" namespace)
      (load-and-adjust-namespace "jitsi/prosody-config-stateful-set.yaml" namespace)
      (load-and-adjust-namespace "jitsi/prosody-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/prosody-config-test-deployment.yaml" namespace)]))
@@ -174,6 +174,16 @@
     (load-and-adjust-namespace "jitsi/prosody-auth-jvb-secret.yaml" namespace)
     (cm/replace-key-value :JVB_AUTH_PASSWORD (b64/encode jvb-auth-password)))]))
 
+(defn-spec jicofo-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace]} config]
+    [(load-and-adjust-namespace "jitsi/jicofo-config-defaults-cm.yaml" namespace)
+     (->
+      (load-and-adjust-namespace "jitsi/jicofo-config-envs-cm.yaml" namespace)
+      (cm/replace-key-value :XMPP_SERVER (str "prosody." namespace ".svc.cluster.local")))
+     (load-and-adjust-namespace "jitsi/jicofo-config-init-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/jicofo-config-deployment.yaml" namespace)]))
+
 (defn-spec jitsi-config cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
@@ -184,7 +194,9 @@
   (let [{:keys [fqdn namespace]} config]
     [(load-and-adjust-namespace "jitsi/jitsi-config-serviceaccount.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-default-cm.yaml" namespace)
-     (load-and-adjust-namespace "jitsi/jibri-config-envs.yaml" namespace)
+     (->
+      (load-and-adjust-namespace "jitsi/jibri-config-envs.yaml" namespace)
+      (cm/replace-key-value :XMPP_SERVER (str "prosody." namespace ".svc.cluster.local")))
      (load-and-adjust-namespace "jitsi/jibri-config-init-cm.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-deployment.yaml" namespace)]))
diff --git a/src/main/resources/jitsi/jicofo-config-defaults-cm.yaml b/src/main/resources/jitsi/jicofo-config-defaults-cm.yaml
new file mode 100644
index 0000000..e5c8478
--- /dev/null
+++ b/src/main/resources/jitsi/jicofo-config-defaults-cm.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jicofo-defaults
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jicofo
+data:
+  jicofo.conf: |
+    # Using jicofo /default/jicofo.conf from container image
+    
+  logging.properties: |
+    # Using jicofo /default/logging.properties from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jicofo-config-deployment.yaml b/src/main/resources/jitsi/jicofo-config-deployment.yaml
new file mode 100644
index 0000000..7bf78b5
--- /dev/null
+++ b/src/main/resources/jitsi/jicofo-config-deployment.yaml
@@ -0,0 +1,70 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: jitsi-meet-jicofo
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jicofo
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: jitsi-meet
+      app.kubernetes.io/component: jicofo
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: jitsi-meet
+        app.kubernetes.io/component: jicofo
+    spec:
+      serviceAccountName: jitsi-meet
+      securityContext:
+        {}
+      volumes:
+      - name: config
+        emptyDir: {}
+      - name: custom-cont-inits
+        configMap:
+          defaultMode: 493
+          name: jitsi-meet-jicofo-cont-inits
+          items:
+            - key: 10-config
+              path: 10-config
+      - name: custom-defaults
+        configMap:
+          name: jitsi-meet-jicofo-defaults
+          items:
+            - key: jicofo.conf
+              path: jicofo.conf
+            - key: logging.properties
+              path: logging.properties
+      containers:
+        - name: jitsi-meet
+          securityContext:
+            {}
+          image: "jitsi/jicofo:stable-9646"
+          imagePullPolicy: IfNotPresent
+          envFrom:
+          - secretRef:
+              name: prosody-jicofo
+          - configMapRef:
+              name: prosody-common
+          - configMapRef:
+              name: jitsi-meet-jicofo
+          ports:
+            - name: http
+              containerPort: 80
+              protocol: TCP
+          livenessProbe:
+            tcpSocket:
+              port: 8888
+          readinessProbe:
+            tcpSocket:
+              port: 8888
+          resources:
+            {}
+          volumeMounts:
+          # to support readOnlyRootFilesystem
+          - name: config
+            mountPath: /config
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jicofo-config-envs-cm.yaml b/src/main/resources/jitsi/jicofo-config-envs-cm.yaml
new file mode 100644
index 0000000..39cb597
--- /dev/null
+++ b/src/main/resources/jitsi/jicofo-config-envs-cm.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jicofo
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jicofo
+data:
+  JVB_BREWERY_MUC: 'jvbbrewery'
+  XMPP_SERVER: 'prosody.NAMESPACE.svc.cluster.local'
+  JIBRI_BREWERY_MUC: 'jibribrewery'
+  JIBRI_PENDING_TIMEOUT: '90'
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jicofo-config-init-cm.yaml b/src/main/resources/jitsi/jicofo-config-init-cm.yaml
new file mode 100644
index 0000000..cadd09a
--- /dev/null
+++ b/src/main/resources/jitsi/jicofo-config-init-cm.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-jicofo-cont-inits
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jicofo
+data:
+  10-config: |
+    # Using jicofo /etc/cont-init.d/10-config from container image
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 89ca2c8..41f1734 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -138,6 +138,12 @@
                   :jicofo-auth-password "jicofo-auth"
                   :jicofo-component-secret "jicofo-comp"})))))
 
+(deftest should-generate-jicofo
+  (is (= 4
+         (count (cut/jicofo-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+
 (deftest should-generate-jitsi
   (is (= 1
          (count (cut/jitsi-config

From 1009092b9f38daf83fd08ec1e827858dbabe0834 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 14:05:43 +0100
Subject: [PATCH 12/33] add web

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  3 +-
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 16 +++-
 .../jitsi/web-config-conffiles-cm.yaml        | 38 ++++++++
 .../jitsi/web-config-deployment.yaml          | 88 +++++++++++++++++++
 .../resources/jitsi/web-config-envs-cm.yaml   | 13 +++
 .../resources/jitsi/web-config-init-cm.yaml   | 11 +++
 .../resources/jitsi/web-config-service.yaml   | 17 ++++
 .../jitsi/web-config-test-deployment.yaml     | 25 ++++++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |  7 ++
 9 files changed, 215 insertions(+), 3 deletions(-)
 create mode 100644 src/main/resources/jitsi/web-config-conffiles-cm.yaml
 create mode 100644 src/main/resources/jitsi/web-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/web-config-envs-cm.yaml
 create mode 100644 src/main/resources/jitsi/web-config-init-cm.yaml
 create mode 100644 src/main/resources/jitsi/web-config-service.yaml
 create mode 100644 src/main/resources/jitsi/web-config-test-deployment.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 84281b9..5bcc234 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -34,8 +34,9 @@
           (cm/concat-vec
            (ns/generate resolved-config)
            (jitsi/prosody-config resolved-config)
-           (jitsi/jicofo-config resolved-config)
            (jitsi/jitsi-config resolved-config)
+           (jitsi/jicofo-config resolved-config)
+           (jitsi/web-config resolved-config)
            (jitsi/jibri-config resolved-config)
           ;;  [(jitsi/generate-jvb-service config)
           ;;   (jitsi/generate-web-service config)
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index b2c504b..d1a9956 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -174,6 +174,11 @@
     (load-and-adjust-namespace "jitsi/prosody-auth-jvb-secret.yaml" namespace)
     (cm/replace-key-value :JVB_AUTH_PASSWORD (b64/encode jvb-auth-password)))]))
 
+(defn-spec jitsi-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    [(load-and-adjust-namespace "jitsi/jitsi-config-serviceaccount.yaml" namespace)]))
+
 (defn-spec jicofo-config cp/map-or-seq?
   [config config?]
   (let [{:keys [namespace]} config]
@@ -184,10 +189,17 @@
      (load-and-adjust-namespace "jitsi/jicofo-config-init-cm.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jicofo-config-deployment.yaml" namespace)]))
 
-(defn-spec jitsi-config cp/map-or-seq?
+(defn-spec web-config cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
-    [(load-and-adjust-namespace "jitsi/jitsi-config-serviceaccount.yaml" namespace)]))
+    [(load-and-adjust-namespace "jitsi/web-config-conffiles-cm.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/web-config-init-cm.yaml" namespace)
+     (-> 
+      (load-and-adjust-namespace "jitsi/web-config-envs-cm.yaml" namespace)
+      (cm/replace-key-value :XMPP_BOSH_URL_BASE (str "http://prosody." namespace ".svc.cluster.local:5280")))
+     (load-and-adjust-namespace "jitsi/web-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/web-config-deployment.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/web-config-test-deployment.yaml" namespace)]))
 
 (defn-spec jibri-config cp/map-or-seq?
   [config config?]
diff --git a/src/main/resources/jitsi/web-config-conffiles-cm.yaml b/src/main/resources/jitsi/web-config-conffiles-cm.yaml
new file mode 100644
index 0000000..80b60d4
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-conffiles-cm.yaml
@@ -0,0 +1,38 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: jitsi-meet-web-conffiles
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
+data:
+  custom-config.js: |
+  # Not providing /config/custom-config.js
+  
+  custom-interface_config.js: |
+  # Not providing /config/custom-interface_config.js
+  
+  default: |
+  # Using web /defaults/default from container image
+  
+  ffdhe2048.txt: |
+  # Using web /defaults/ffdhe2048.txt from container image
+  
+  interface_config.js: |
+  # Using web /defaults/interface_config.js from container image
+  
+  meet.conf: |
+  # Using web /defaults/meet.conf from container image
+  
+  nginx.conf: |
+  # Using web /defaults/nginx.conf from container image
+  
+  settings-config.js: |
+  # Using web /defaults/settings-config.js from container image
+  
+  ssl.conf: |
+  # Using web /defaults/ssl.conf from container image
+  
+  system-config.js: |
+  # Using web /defaults/system-config.js from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-deployment.yaml b/src/main/resources/jitsi/web-config-deployment.yaml
new file mode 100644
index 0000000..d6c9779
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-deployment.yaml
@@ -0,0 +1,88 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-web
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: jitsi-meet
+      app.kubernetes.io/component: web
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: jitsi-meet
+        app.kubernetes.io/component: web
+    spec:
+      serviceAccountName: jitsi-meet
+      securityContext:
+        {}
+      containers:
+        - name: jitsi-meet
+          securityContext:
+            {}
+          image: "jitsi/web:stable-9646"
+          imagePullPolicy: IfNotPresent
+          envFrom:
+          - configMapRef:
+              name: jitsi-meet-web
+          - configMapRef:
+              name: prosody-common
+          ports:
+            - name: http
+              containerPort: 80
+              protocol: TCP
+            - name: https
+              containerPort: 443
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              path: /
+              port: 80
+          readinessProbe:
+            httpGet:
+              path: /
+              port: 80
+          resources:
+            {}
+          volumeMounts:
+          - name: config
+            mountPath: /config
+      volumes:
+      - name: config
+        emptyDir: {}
+      - name: custom-init
+        configMap:
+          defaultMode: 493
+          name: jitsi-meet-web-init
+          items:
+            - key: 10-config
+              path: 10-config
+      - name: custom-conffiles
+        configMap:
+          name: jitsi-meet-web-conffiles
+          items:
+            - key: custom-config.js
+              path: custom-config.js
+            - key: custom-interface_config.js
+              path: custom-interface_config.js
+            - key: default
+              path: default
+            - key: ffdhe2048.txt
+              path: ffdhe2048.txt
+            - key: interface_config.js
+              path: interface_config.js
+            - key: meet.conf
+              path: meet.conf
+            - key: nginx.conf
+              path: nginx.conf
+            - key: settings-config.js
+              path: settings-config.js
+            - key: ssl.conf
+              path: ssl.conf
+            - key: system-config.js
+              path: system-config.js
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-envs-cm.yaml b/src/main/resources/jitsi/web-config-envs-cm.yaml
new file mode 100644
index 0000000..5b36ccf
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-envs-cm.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-web
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
+data:
+  DISABLE_HTTPS: "1"
+  ENABLE_HTTP_REDIRECT: "0"
+  JICOFO_AUTH_USER: focus
+  XMPP_BOSH_URL_BASE: 'http://prosody.NAMESPACE.svc.cluster.local:5280'
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-init-cm.yaml b/src/main/resources/jitsi/web-config-init-cm.yaml
new file mode 100644
index 0000000..ac085bb
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-init-cm.yaml
@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-web-init
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
+data:
+  10-config: |
+  # Using web /etc/cont-init.d/10-config from container image
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-service.yaml b/src/main/resources/jitsi/web-config-service.yaml
new file mode 100644
index 0000000..eede399
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-service.yaml
@@ -0,0 +1,17 @@
+apiVersion: v1
+kind: Service
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-web
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
+spec:
+  type: ClusterIP
+  ports:
+    - port: 80
+      protocol: TCP
+      name: http
+  selector:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-test-deployment.yaml b/src/main/resources/jitsi/web-config-test-deployment.yaml
new file mode 100644
index 0000000..6ea9c08
--- /dev/null
+++ b/src/main/resources/jitsi/web-config-test-deployment.yaml
@@ -0,0 +1,25 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: "prosody-test-connection"
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: "prosody-test-connection"
+    app.kubernetes.io/component: prosody
+spec:
+  replicas: 0
+  strategy:
+    type: Recreate
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: "prosody-test-connection"
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: "prosody-test-connection"
+    spec:
+      containers:
+        - name: wget
+          image: busybox
+          command: ['wget']
+          args: ['prosody:5280/http-bind']
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 41f1734..a2f8acd 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -155,3 +155,10 @@
          (count (cut/jibri-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
+
+(deftest should-generate-web
+  (is (= 6
+         (count (cut/web-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+

From e4b357e91034fd15f784aa8a5d87311b713220b1 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 15:40:03 +0100
Subject: [PATCH 13/33] add jvb, wtherpad & web

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  36 ++--
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 162 ++++++------------
 .../jitsi/etherpad-config-deployment.yaml     |  20 +++
 .../jitsi/etherpad-config-service.yaml        |  14 ++
 .../jitsi/jvb-config-deployment.yaml          |  62 +++++++
 .../resources/jitsi/jvb-config-envs-cm.yaml   |  15 ++
 .../resources/jitsi/jvb-config-service.yaml   |  21 +++
 .../jitsi/web-config-deployment.yaml          |   2 +-
 .../resources/jitsi/web-config-envs-cm.yaml   |  11 +-
 .../jitsi/web-config-test-deployment.yaml     |  12 +-
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |  27 +--
 11 files changed, 237 insertions(+), 145 deletions(-)
 create mode 100644 src/main/resources/jitsi/etherpad-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/etherpad-config-service.yaml
 create mode 100644 src/main/resources/jitsi/jvb-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/jvb-config-envs-cm.yaml
 create mode 100644 src/main/resources/jitsi/jvb-config-service.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 5bcc234..535cb7b 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -5,6 +5,7 @@
       :cljs [orchestra.core :refer-macros [defn-spec]])
    [dda.c4k-common.common :as cm]
    [dda.c4k-common.predicate :as cp]
+   [dda.c4k-common.ingress :as ing]
    [dda.c4k-common.monitoring :as mon]
    [dda.c4k-common.yaml :as yaml]
    [dda.c4k-jitsi.jitsi :as jitsi]
@@ -37,19 +38,29 @@
            (jitsi/jitsi-config resolved-config)
            (jitsi/jicofo-config resolved-config)
            (jitsi/web-config resolved-config)
+           (jitsi/jvb-config resolved-config)
            (jitsi/jibri-config resolved-config)
-          ;;  [(jitsi/generate-jvb-service config)
-          ;;   (jitsi/generate-web-service config)
-          ;;   (jitsi/generate-etherpad-service config)
-          ;;   (jitsi/generate-excalidraw-backend-service config)
-          ;;   (jitsi/generate-modelector-service config)
-          ;;   (jitsi/generate-deployment config)
-          ;;   (jitsi/generate-excalidraw-deployment config)
-          ;;   (jitsi/generate-modelector-deployment config)]
-          ;;  (jitsi/generate-ingress-web config)
-          ;;  (jitsi/generate-ingress-etherpad config)
-          ;;  (jitsi/generate-ingress-excalidraw-backend config)
-          ;;  (jitsi/generate-ingress-modelector config)
+           (jitsi/etherpad resolved-config)
+           (ing/generate-ingress-and-cert (merge
+                                           {:service-name "jitsi-meet-web"
+                                            :service-port 80
+                                            :fqdns [(:fqdn resolved-config)]}
+                                           resolved-config))
+           (ing/generate-ingress-and-cert (merge
+                                           {:service-name "etherpad"
+                                            :service-port 9001
+                                            :fqdns [(str "etherpad." (:fqdn resolved-config))]}
+                                           resolved-config))
+            (ing/generate-ingress-and-cert (merge
+                                            {:service-name "excalidraw"
+                                             :service-port 3002
+                                             :fqdns [(str "excalidraw." (:fqdn resolved-config))]}
+                                            resolved-config))
+           (ing/generate-ingress-and-cert (merge
+                                           {:service-name "moderator-elector"
+                                            :service-port 80
+                                            :fqdns [(str "moderator-elector." (:fqdn resolved-config))]}
+                                           resolved-config))
            (when (:contains? resolved-config :mon-cfg)
              (mon/generate-config)))))))
 
@@ -62,6 +73,5 @@
         #(not (nil? %))
         (cm/concat-vec
          (jitsi/prosody-auth config auth)
-         ;[(jitsi/generate-secret-jitsi config auth)]
          (when (:contains? config :mon-cfg)
            (mon/generate-auth (:mon-cfg config) (:mon-auth auth))))))))
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index d1a9956..6d0e39b 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -5,7 +5,6 @@
       :cljs [orchestra.core :refer-macros [defn-spec]])
    [dda.c4k-common.yaml :as yaml]
    [dda.c4k-common.common :as cm]
-   [dda.c4k-common.ingress :as ing]
    [dda.c4k-common.base64 :as b64]
    [dda.c4k-common.predicate :as cp]
    #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
@@ -28,116 +27,6 @@
    (defmethod yaml/load-resource :jitsi [resource-name]
      (get (inline-resources "jitsi") resource-name)))
 
-(defn-spec generate-ingress-web cp/map-or-seq?
-  [config config?]
-  (ing/generate-ingress-and-cert
-   (merge
-    {:service-name "web"
-     :service-port 80
-     :fqdns [(:fqdn config)]}
-    config)))
-
-(defn-spec generate-ingress-etherpad cp/map-or-seq?
-  [config config?]
-  (ing/generate-ingress-and-cert
-   (merge
-    {:service-name "etherpad"
-     :service-port 9001
-     :fqdns [(str "etherpad." (:fqdn config))]}
-    config)))
-
-(defn-spec generate-ingress-excalidraw-backend cp/map-or-seq?
-  [config config?]
-  (ing/generate-ingress-and-cert
-   (merge
-    {:service-name "excalidraw-backend"
-     :service-port 3002
-     :fqdns [(str "excalidraw-backend." (:fqdn config))]}
-    config)))
-
-(defn-spec generate-ingress-modelector cp/map-or-seq?
-  [config config?]
-  (ing/generate-ingress-and-cert
-   (merge
-    {:service-name "modelector"
-     :service-port 80
-     :fqdns [(str "modelector." (:fqdn config))]}
-    config)))
-
-(defn-spec generate-secret-jitsi cp/map-or-seq?
-  [config config?
-   auth auth?]
-  (let [{:keys [namespace]} config
-        {:keys [jvb-auth-password jicofo-auth-password jicofo-component-secret]} auth]
-    (->
-     (yaml/from-string (yaml/load-resource "jitsi/secret.yaml"))
-     (cm/replace-all-matching "NAMESPACE" namespace)
-     (cm/replace-key-value :JVB_AUTH_PASSWORD (b64/encode jvb-auth-password))
-     (cm/replace-key-value :JICOFO_AUTH_PASSWORD (b64/encode jicofo-auth-password))
-     (cm/replace-key-value :JICOFO_COMPONENT_SECRET (b64/encode jicofo-component-secret)))))
-
-(defn-spec generate-jvb-service cp/map-or-seq? 
-  [config config?]
-  (let [{:keys [namespace]} config]
-    (->
-     (yaml/from-string (yaml/load-resource "jitsi/jvb-service.yaml"))
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-web-service cp/map-or-seq?
-  [config config?]
-  (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/web-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-etherpad-service cp/map-or-seq?
-  [config config?]
-  (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/etherpad-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-excalidraw-backend-service cp/map-or-seq?
-  [config config?]
-  (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/excalidraw-backend-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-modelector-service cp/map-or-seq?
-  [config config?]
-  (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/modelector-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-deployment cp/map-or-seq?
-  [config config?]
-  (let [{:keys [fqdn namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/deployment.yaml")
-     (cm/replace-all-matching "REPLACE_JITSI_FQDN" fqdn)
-     (cm/replace-all-matching "NAMESPACE" namespace)
-     (cm/replace-all-matching "REPLACE_ETHERPAD_URL"
-                              (str "https://etherpad." fqdn "/p/"))
-     
-     (cm/replace-all-matching "REPLACE_EXCALIDRAW_BACKEND_URL"
-                              (str "https://excalidraw-backend." fqdn)))))
-
-(defn-spec generate-excalidraw-deployment cp/map-or-seq?
-  [config config?]
-  (let [{:keys [fqdn namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/excalidraw-deployment.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-modelector-deployment cp/map-or-seq?
-  [config config?]
-  (let [{:keys [fqdn namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
 (defn- load-and-adjust-namespace
   [file namespace]
   (->
@@ -196,11 +85,26 @@
      (load-and-adjust-namespace "jitsi/web-config-init-cm.yaml" namespace)
      (-> 
       (load-and-adjust-namespace "jitsi/web-config-envs-cm.yaml" namespace)
-      (cm/replace-key-value :XMPP_BOSH_URL_BASE (str "http://prosody." namespace ".svc.cluster.local:5280")))
+      (cm/replace-key-value :XMPP_BOSH_URL_BASE (str "http://prosody." namespace ".svc.cluster.local:5280"))
+      (cm/replace-key-value :ETHERPAD_PUBLIC_URL (str "https://etherpad." fqdn "/p/"))
+      (cm/replace-key-value :WHITEBOARD_COLLAB_SERVER_PUBLIC_URL (str "https://excalidraw." fqdn))
+      )
      (load-and-adjust-namespace "jitsi/web-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/web-config-deployment.yaml" namespace)
      (load-and-adjust-namespace "jitsi/web-config-test-deployment.yaml" namespace)]))
 
+(defn-spec jvb-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    [(-> 
+      (load-and-adjust-namespace "jitsi/jvb-config-envs-cm.yaml" namespace)
+      (cm/replace-key-value :XMPP_SERVER (str "prosody." namespace ".svc.cluster.local")))
+     (load-and-adjust-namespace "jitsi/jvb-config-service.yaml" namespace)
+     (->
+      (load-and-adjust-namespace "jitsi/jvb-config-deployment.yaml" namespace)
+      (cm/replace-all-matching "REPLACE_JITSI_FQDN" fqdn)
+      )]))
+
 (defn-spec jibri-config cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
@@ -212,3 +116,37 @@
      (load-and-adjust-namespace "jitsi/jibri-config-init-cm.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-deployment.yaml" namespace)]))
+
+(defn-spec etherpad-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace]} config]
+    [(load-and-adjust-namespace "jitsi/etherpad-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/etherpad-config-deployment.yaml" namespace)]))
+
+(defn-spec generate-excalidraw-backend-service cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace]} config]
+    (->
+     (yaml/load-as-edn "jitsi/excalidraw-backend-service.yaml")
+     (cm/replace-all-matching "NAMESPACE" namespace))))
+
+(defn-spec generate-modelector-service cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace]} config]
+    (->
+     (yaml/load-as-edn "jitsi/modelector-service.yaml")
+     (cm/replace-all-matching "NAMESPACE" namespace))))
+
+(defn-spec generate-excalidraw-deployment cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    (->
+     (yaml/load-as-edn "jitsi/excalidraw-deployment.yaml")
+     (cm/replace-all-matching "NAMESPACE" namespace))))
+
+(defn-spec generate-modelector-deployment cp/map-or-seq?
+  [config config?]
+  (let [{:keys [fqdn namespace]} config]
+    (->
+     (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
+     (cm/replace-all-matching "NAMESPACE" namespace))))
diff --git a/src/main/resources/jitsi/etherpad-config-deployment.yaml b/src/main/resources/jitsi/etherpad-config-deployment.yaml
new file mode 100644
index 0000000..4b75072
--- /dev/null
+++ b/src/main/resources/jitsi/etherpad-config-deployment.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: etherpad
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: etherpad
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: etherpad
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: etherpad
+    spec:
+      containers:
+        - name: etherpad
+          image: etherpad/etherpad:2
\ No newline at end of file
diff --git a/src/main/resources/jitsi/etherpad-config-service.yaml b/src/main/resources/jitsi/etherpad-config-service.yaml
new file mode 100644
index 0000000..827e064
--- /dev/null
+++ b/src/main/resources/jitsi/etherpad-config-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: etherpad
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: etherpad
+spec:
+  ports:
+  - name: etherpad
+    port: 9001
+    targetPort: 9001
+  selector:
+    app.kubernetes.io/name: etherpad
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jvb-config-deployment.yaml b/src/main/resources/jitsi/jvb-config-deployment.yaml
new file mode 100644
index 0000000..cc3954e
--- /dev/null
+++ b/src/main/resources/jitsi/jvb-config-deployment.yaml
@@ -0,0 +1,62 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-jvb
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jvb
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: jitsi-meet
+      app.kubernetes.io/component: jvb
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: jitsi-meet
+        app.kubernetes.io/component: jvb
+    spec:
+      serviceAccountName: jitsi-meet
+      securityContext:
+        {}
+      containers:
+        - name: jitsi-meet
+          securityContext:
+            {}
+          image: "jitsi/jvb:stable-9646"
+          imagePullPolicy: IfNotPresent
+          envFrom:
+          - secretRef:
+              name: prosody-jvb
+          - configMapRef:
+              name: prosody-common
+          - configMapRef:
+              name: jitsi-meet-jvb
+          env:
+          - name: DOCKER_HOST_ADDRESS
+            value: REPLACE_JITSI_FQDN
+          - name: JVB_ADVERTISE_IPS
+            value: REPLACE_JITSI_FQDN
+          - name: JVB_WS_SERVER_ID
+            valueFrom:
+              fieldRef:
+                fieldPath: status.podIP
+          ports:
+            - name: rtp-udp
+              containerPort: 10000
+              protocol: UDP
+            - name: colibri-ws-tcp
+              containerPort: 9090
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              path: /about/health
+              port: 8080
+          readinessProbe:
+            httpGet:
+              path: /about/health
+              port: 8080
+          resources:
+            {}
diff --git a/src/main/resources/jitsi/jvb-config-envs-cm.yaml b/src/main/resources/jitsi/jvb-config-envs-cm.yaml
new file mode 100644
index 0000000..17602ea
--- /dev/null
+++ b/src/main/resources/jitsi/jvb-config-envs-cm.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-jvb
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jvb
+data:
+  JVB_BREWERY_MUC: 'jvbbrewery'
+  JVB_PORT: '10000'
+  JVB_STUN_SERVERS: 'meet-jit-si-turnrelay.jitsi.net:443'
+  JVB_TCP_HARVESTER_DISABLED: '1'
+  XMPP_SERVER: REPLACE_ME
+  COLIBRI_REST_ENABLED: 'true'
diff --git a/src/main/resources/jitsi/jvb-config-service.yaml b/src/main/resources/jitsi/jvb-config-service.yaml
new file mode 100644
index 0000000..fb5f0f6
--- /dev/null
+++ b/src/main/resources/jitsi/jvb-config-service.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Service
+metadata:
+  namespace: NAMESPACE
+  name: jitsi-meet-jvb
+  labels:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jvb
+  annotations:
+    metallb.universe.tf/allow-shared-ip: "shared-ip-service-group"
+    metallb.universe.tf/address-pool: public
+spec:
+  type: LoadBalancer
+  ports:
+    - port: 10000
+      protocol: UDP
+      name: rtp-udp
+  externalTrafficPolicy: Cluster
+  selector:
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: jvb
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-deployment.yaml b/src/main/resources/jitsi/web-config-deployment.yaml
index d6c9779..eef7f25 100644
--- a/src/main/resources/jitsi/web-config-deployment.yaml
+++ b/src/main/resources/jitsi/web-config-deployment.yaml
@@ -25,7 +25,7 @@ spec:
         - name: jitsi-meet
           securityContext:
             {}
-          image: "jitsi/web:stable-9646"
+          image: domaindrivenarchitecture/c4k-jitsi-web
           imagePullPolicy: IfNotPresent
           envFrom:
           - configMapRef:
diff --git a/src/main/resources/jitsi/web-config-envs-cm.yaml b/src/main/resources/jitsi/web-config-envs-cm.yaml
index 5b36ccf..aa380f0 100644
--- a/src/main/resources/jitsi/web-config-envs-cm.yaml
+++ b/src/main/resources/jitsi/web-config-envs-cm.yaml
@@ -10,4 +10,13 @@ data:
   DISABLE_HTTPS: "1"
   ENABLE_HTTP_REDIRECT: "0"
   JICOFO_AUTH_USER: focus
-  XMPP_BOSH_URL_BASE: 'http://prosody.NAMESPACE.svc.cluster.local:5280'
\ No newline at end of file
+  XMPP_BOSH_URL_BASE: REPLACE_ME
+  DEFAULT_LANGUAGE: de
+  RESOLUTION: "480"
+  RESOLUTION_MIN: "240"
+  RESOLUTION_WIDTH: "853"
+  RESOLUTION_WIDTH_MIN: "427"
+  DISABLE_AUDIO_LEVELS: "true"
+  ETHERPAD_PUBLIC_URL: REPLACE_ME
+  WHITEBOARD_ENABLED: "true"
+  WHITEBOARD_COLLAB_SERVER_PUBLIC_URL: REPLACE_ME
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-config-test-deployment.yaml b/src/main/resources/jitsi/web-config-test-deployment.yaml
index 6ea9c08..95a8f32 100644
--- a/src/main/resources/jitsi/web-config-test-deployment.yaml
+++ b/src/main/resources/jitsi/web-config-test-deployment.yaml
@@ -1,25 +1,25 @@
 apiVersion: apps/v1
 kind: Deployment
 metadata:
-  name: "prosody-test-connection"
+  name: "jitsi-meet-web-test-connection"
   namespace: NAMESPACE
   labels:
-    app.kubernetes.io/name: "prosody-test-connection"
-    app.kubernetes.io/component: prosody
+    app.kubernetes.io/name: jitsi-meet
+    app.kubernetes.io/component: web
 spec:
   replicas: 0
   strategy:
     type: Recreate
   selector:
     matchLabels:
-      app.kubernetes.io/name: "prosody-test-connection"
+      app.kubernetes.io/name: "jitsi-meet-web-test-connection"
   template:
     metadata:
       labels:
-        app.kubernetes.io/name: "prosody-test-connection"
+        app.kubernetes.io/name: "jitsi-meet-web-test-connection"
     spec:
       containers:
         - name: wget
           image: busybox
           command: ['wget']
-          args: ['prosody:5280/http-bind']
\ No newline at end of file
+          args: ['jitsi-meet-web:80']
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index a2f8acd..074ea09 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -9,18 +9,9 @@
 (st/instrument `cut/prosody-auth)
 (st/instrument `cut/jitsi-config)
 (st/instrument `cut/jibri-config)
-
-(deftest should-generate-etherpad-service
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata
-          {:labels {:service "etherpad"}, :name "etherpad", :namespace "jitsi"},
-          :spec
-          {:ports [{:name "etherpad", :port 9001, :targetPort 9001}],
-           :selector {:app "jitsi"}}}
-         (cut/generate-etherpad-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
+(st/instrument `cut/web-config)
+(st/instrument `cut/jvb-config)
+(st/instrument `cut/etherpad-config)
 
 (deftest should-generate-excalidraw-backend-service
   (is (= {:apiVersion "v1",
@@ -162,3 +153,15 @@
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
 
+(deftest should-generate-jvb
+  (is (= 3
+         (count (cut/jvb-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+
+(deftest should-generate-etherpad
+  (is (= 2
+         (count (cut/etherpad-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+

From 0fa71e48403519e2383ad7d8b1367df5ad833619 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 15:51:17 +0100
Subject: [PATCH 14/33] add excalidraw

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  3 +-
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 14 +---
 .../jitsi/excalidraw-config-deployment.yaml   | 20 +++++
 .../jitsi/excalidraw-config-service.yaml      | 14 ++++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   | 74 ++-----------------
 5 files changed, 46 insertions(+), 79 deletions(-)
 create mode 100644 src/main/resources/jitsi/excalidraw-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/excalidraw-config-service.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 535cb7b..91cb32e 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -40,7 +40,8 @@
            (jitsi/web-config resolved-config)
            (jitsi/jvb-config resolved-config)
            (jitsi/jibri-config resolved-config)
-           (jitsi/etherpad resolved-config)
+           (jitsi/etherpad-config resolved-config)
+           (jitsi/excalidraw-config resolved-config)
            (ing/generate-ingress-and-cert (merge
                                            {:service-name "jitsi-meet-web"
                                             :service-port 80
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 6d0e39b..9545d16 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -123,12 +123,11 @@
     [(load-and-adjust-namespace "jitsi/etherpad-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/etherpad-config-deployment.yaml" namespace)]))
 
-(defn-spec generate-excalidraw-backend-service cp/map-or-seq?
+(defn-spec excalidraw-config cp/map-or-seq?
   [config config?]
   (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/excalidraw-backend-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
+    [(load-and-adjust-namespace "jitsi/excalidraw-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/excalidraw-config-deployment.yaml" namespace)]))
 
 (defn-spec generate-modelector-service cp/map-or-seq?
   [config config?]
@@ -137,13 +136,6 @@
      (yaml/load-as-edn "jitsi/modelector-service.yaml")
      (cm/replace-all-matching "NAMESPACE" namespace))))
 
-(defn-spec generate-excalidraw-deployment cp/map-or-seq?
-  [config config?]
-  (let [{:keys [fqdn namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/excalidraw-deployment.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
 (defn-spec generate-modelector-deployment cp/map-or-seq?
   [config config?]
   (let [{:keys [fqdn namespace]} config]
diff --git a/src/main/resources/jitsi/excalidraw-config-deployment.yaml b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
new file mode 100644
index 0000000..54a65ca
--- /dev/null
+++ b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: excalidraw
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: excalidraw
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: excalidraw
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: excalidraw
+    spec:
+      containers:
+        - name: excalidraw-backend
+          image: domaindrivenarchitecture/c4k-jitsi-excalidraw-backend
\ No newline at end of file
diff --git a/src/main/resources/jitsi/excalidraw-config-service.yaml b/src/main/resources/jitsi/excalidraw-config-service.yaml
new file mode 100644
index 0000000..0ac4be3
--- /dev/null
+++ b/src/main/resources/jitsi/excalidraw-config-service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: excalidraw-backend
+  namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: excalidraw  
+spec:
+  ports:
+  - name: excalidraw-backend
+    port: 3002
+    targetPort: 80
+  selector:
+    app.kubernetes.io/name: excalidraw 
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 074ea09..d99f446 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -12,73 +12,7 @@
 (st/instrument `cut/web-config)
 (st/instrument `cut/jvb-config)
 (st/instrument `cut/etherpad-config)
-
-(deftest should-generate-excalidraw-backend-service
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata
-          {:labels {:service "excalidraw-backend"},
-           :name "excalidraw-backend",
-           :namespace "jitsi"},
-          :spec
-          {:ports [{:name "excalidraw-backend", :port 3002, :targetPort 80}],
-           :selector {:app "excalidraw-backend"}}}
-         (cut/generate-excalidraw-backend-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
-
-(deftest should-generate-modelector-service
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata
-          {:labels {:service "modelector"},
-           :name "modelector",
-           :namespace "jitsi"},
-          :spec
-          {:ports [{:name "http", :port 80, :targetPort 8080}],
-           :selector {:app "modelector"}}}
-         (cut/generate-modelector-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
-
-(deftest should-generate-modelector-deployment
-  (is (= {:apiVersion "apps/v1",
-          :kind "Deployment",
-          :metadata
-          {:labels {:app "modelector"},
-           :name "modelector",
-           :namespace "jitsi"},
-          :spec
-          {:selector {:matchLabels {:app "modelector"}},
-           :replicas 1,
-           :strategy {:type "Recreate"},
-           :template
-           {:metadata {:labels {:app "modelector"}},
-            :spec
-            {:containers
-             [{:name "modelector",
-               :image "domaindrivenarchitecture/moderator-election-vaadin_fullstack",
-               :imagePullPolicy "IfNotPresent",
-               :env
-               [{:name "MEMBERNAMES",
-                 :value "Micha,Ansgar,Erik,Mirco"}]}]}}}}
-          (cut/generate-modelector-deployment
-           {:fqdn "xy.xy.xy"
-            :namespace "jitsi"}))))
-
-(deftest should-generate-excalidraw-deployment
-  (is (= {:apiVersion "v1",
-          :kind "Service",
-          :metadata
-          {:labels {:service "excalidraw-backend"},
-           :name "excalidraw-backend",
-           :namespace "jitsi"},
-          :spec
-          {:ports [{:name "excalidraw-backend", :port 3002, :targetPort 80}],
-           :selector {:app "excalidraw-backend"}}}
-         (cut/generate-excalidraw-backend-service
-          {:fqdn "xy.xy.xy"
-           :namespace "jitsi"}))))
+(st/instrument `cut/excalidraw-config)
 
 (deftest should-generate-prosody
   (is (= {:apiVersion "v1",
@@ -165,3 +99,9 @@
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
 
+(deftest should-generate-excalidraw
+  (is (= 2
+         (count (cut/excalidraw-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))
+

From c2eb0e96ba7cfdc56098f1b53f6386e35c7feacf Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 15:59:23 +0100
Subject: [PATCH 15/33] add moderator election

---
 src/main/cljc/dda/c4k_jitsi/core.cljc              |  1 +
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc             | 14 +++-----------
 ...ment.yaml => modelector-config-deployment.yaml} | 14 ++++++--------
 ...service.yaml => modelector-config-service.yaml} |  8 ++++----
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc        |  5 +++++
 5 files changed, 19 insertions(+), 23 deletions(-)
 rename src/main/resources/jitsi/{modelector-deployment.yaml => modelector-config-deployment.yaml} (66%)
 rename src/main/resources/jitsi/{modelector-service.yaml => modelector-config-service.yaml} (57%)

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 91cb32e..5ab6ffb 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -42,6 +42,7 @@
            (jitsi/jibri-config resolved-config)
            (jitsi/etherpad-config resolved-config)
            (jitsi/excalidraw-config resolved-config)
+           (jitsi/moderator-elector-config resolved-config)
            (ing/generate-ingress-and-cert (merge
                                            {:service-name "jitsi-meet-web"
                                             :service-port 80
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 9545d16..4a12889 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -129,16 +129,8 @@
     [(load-and-adjust-namespace "jitsi/excalidraw-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/excalidraw-config-deployment.yaml" namespace)]))
 
-(defn-spec generate-modelector-service cp/map-or-seq?
+(defn-spec moderator-elector-config cp/map-or-seq?
   [config config?]
   (let [{:keys [namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/modelector-service.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
-
-(defn-spec generate-modelector-deployment cp/map-or-seq?
-  [config config?]
-  (let [{:keys [fqdn namespace]} config]
-    (->
-     (yaml/load-as-edn "jitsi/modelector-deployment.yaml")
-     (cm/replace-all-matching "NAMESPACE" namespace))))
+    [(load-and-adjust-namespace "jitsi/modelector-config-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/modelector-config-deployment.yaml" namespace)]))
diff --git a/src/main/resources/jitsi/modelector-deployment.yaml b/src/main/resources/jitsi/modelector-config-deployment.yaml
similarity index 66%
rename from src/main/resources/jitsi/modelector-deployment.yaml
rename to src/main/resources/jitsi/modelector-config-deployment.yaml
index 4e0d571..8c73c1a 100644
--- a/src/main/resources/jitsi/modelector-deployment.yaml
+++ b/src/main/resources/jitsi/modelector-config-deployment.yaml
@@ -1,24 +1,22 @@
 apiVersion: apps/v1
 kind: Deployment
 metadata:
-  labels:
-    app: modelector
-  name: modelector
+  name: moderator-elector
   namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: moderator-elector
 spec:
   replicas: 1
-  strategy:
-    type: Recreate
   selector:
     matchLabels:
-      app: modelector
+      app.kubernetes.io/name: moderator-elector
   template:
     metadata:
       labels:
-        app: modelector
+        app.kubernetes.io/name: moderator-elector
     spec:
       containers:
-        - name: modelector
+        - name: moderator-elector
           image: domaindrivenarchitecture/moderator-election-vaadin_fullstack
           imagePullPolicy: IfNotPresent
           env:
diff --git a/src/main/resources/jitsi/modelector-service.yaml b/src/main/resources/jitsi/modelector-config-service.yaml
similarity index 57%
rename from src/main/resources/jitsi/modelector-service.yaml
rename to src/main/resources/jitsi/modelector-config-service.yaml
index 8d84789..bd65061 100644
--- a/src/main/resources/jitsi/modelector-service.yaml
+++ b/src/main/resources/jitsi/modelector-config-service.yaml
@@ -1,14 +1,14 @@
 apiVersion: v1
 kind: Service
 metadata:
-  labels:
-    service: modelector
-  name: modelector
+  name: moderator-elector
   namespace: NAMESPACE
+  labels:
+    app.kubernetes.io/name: moderator-elector
 spec:
   ports:
     - name: "http"
       port: 80
       targetPort: 8080
   selector:
-    app: modelector
\ No newline at end of file
+    app.kubernetes.io/name: moderator-elector
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index d99f446..d4dd47f 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -105,3 +105,8 @@
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
 
+(deftest should-generate-moderator-elector
+  (is (= 2
+         (count (cut/moderator-elector-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))

From 9c2bf471e85f10f93c1556c8eeac4ce5b74ff853 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Mon, 17 Feb 2025 16:28:01 +0100
Subject: [PATCH 16/33] jibri needs some debugging

---
 src/main/resources/jitsi/jibri-config-deployment.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/resources/jitsi/jibri-config-deployment.yaml b/src/main/resources/jitsi/jibri-config-deployment.yaml
index 5e12829..cc72bad 100644
--- a/src/main/resources/jitsi/jibri-config-deployment.yaml
+++ b/src/main/resources/jitsi/jibri-config-deployment.yaml
@@ -7,7 +7,7 @@ metadata:
     app.kubernetes.io/name: jitsi-meet
     app.kubernetes.io/component: jibri
 spec:
-  replicas: 1
+  replicas: 0
   selector:
     matchLabels:
       app.kubernetes.io/name: jitsi-meet

From 0a74b9cf6d76019e88aa637b0e075b1b8db58d8d Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 08:54:28 +0100
Subject: [PATCH 17/33] renew settings

---
 .../settings-config-stable-10008.orig         | 630 ++++++++++++++++++
 .../web/image/resources/settings-config.js    | 103 ++-
 2 files changed, 715 insertions(+), 18 deletions(-)
 create mode 100644 infrastructure/web/image/resources/settings-config-stable-10008.orig

diff --git a/infrastructure/web/image/resources/settings-config-stable-10008.orig b/infrastructure/web/image/resources/settings-config-stable-10008.orig
new file mode 100644
index 0000000..da286f9
--- /dev/null
+++ b/infrastructure/web/image/resources/settings-config-stable-10008.orig
@@ -0,0 +1,630 @@
+{{ $ENABLE_ADAPTIVE_MODE := .Env.ENABLE_ADAPTIVE_MODE | default "true" | toBool -}}
+{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
+{{ $ENABLE_AUTOMATIC_GAIN_CONTROL := .Env.ENABLE_AUTOMATIC_GAIN_CONTROL | default "true" | toBool -}}
+{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
+{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
+{{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}}
+{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "true" | toBool -}}
+{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}}
+{{ $ENABLE_PREJOIN_PAGE := .Env.ENABLE_PREJOIN_PAGE | default "true" | toBool -}}
+{{ $ENABLE_WELCOME_PAGE := .Env.ENABLE_WELCOME_PAGE | default "true" | toBool -}}
+{{ $ENABLE_CLOSE_PAGE := .Env.ENABLE_CLOSE_PAGE | default "false" | toBool -}}
+{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}}
+{{ $ENABLE_SERVICE_RECORDING := .Env.ENABLE_SERVICE_RECORDING | default ($ENABLE_RECORDING | printf "%t") | toBool -}}
+{{ $ENABLE_LIVESTREAMING := .Env.ENABLE_LIVESTREAMING | default "false" | toBool -}}
+{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK := .Env.ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK | default "https://policies.google.com/privacy" -}}
+{{ $ENABLE_LIVESTREAMING_HELP_LINK := .Env.ENABLE_LIVESTREAMING_HELP_LINK | default "https://jitsi.org/live" -}}
+{{ $ENABLE_LIVESTREAMING_TERMS_LINK := .Env.ENABLE_LIVESTREAMING_TERMS_LINK | default "https://www.youtube.com/t/terms" -}}
+{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING := .Env.ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING | default "^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}" -}}
+{{ $ENABLE_REMB := .Env.ENABLE_REMB | default "true" | toBool -}}
+{{ $ENABLE_REQUIRE_DISPLAY_NAME := .Env.ENABLE_REQUIRE_DISPLAY_NAME | default "false" | toBool -}}
+{{ $ENABLE_SIMULCAST := .Env.ENABLE_SIMULCAST | default "true" | toBool -}}
+{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | default "false" | toBool -}}
+{{ $ENABLE_OPUS_RED := .Env.ENABLE_OPUS_RED | default "false" | toBool -}}
+{{ $ENABLE_TALK_WHILE_MUTED := .Env.ENABLE_TALK_WHILE_MUTED | default "false" | toBool -}}
+{{ $ENABLE_TCC := .Env.ENABLE_TCC | default "true" | toBool -}}
+{{ $ENABLE_TRANSCRIPTIONS := .Env.ENABLE_TRANSCRIPTIONS | default "false" | toBool -}}
+{{ $TRANSLATION_LANGUAGES := .Env.TRANSLATION_LANGUAGES | default "[]" -}}
+{{ $TRANSLATION_LANGUAGES_HEAD := .Env.TRANSLATION_LANGUAGES_HEAD | default "['en']" -}}
+{{ $USE_APP_LANGUAGE := .Env.USE_APP_LANGUAGE | default "true" | toBool -}}
+{{ $PREFERRED_LANGUAGE := .Env.PREFERRED_LANGUAGE | default "en-US" -}}
+{{ $DISABLE_START_FOR_ALL := .Env.DISABLE_START_FOR_ALL | default "false" | toBool -}}
+{{ $AUTO_CAPTION_ON_RECORD := .Env.AUTO_CAPTION_ON_RECORD | default "false" | toBool -}}
+{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }}
+{{ $HIDE_PREJOIN_DISPLAY_NAME := .Env.HIDE_PREJOIN_DISPLAY_NAME | default "false" | toBool -}}
+{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}}
+{{ $RESOLUTION := .Env.RESOLUTION | default "720" -}}
+{{ $RESOLUTION_MIN := .Env.RESOLUTION_MIN | default "180" -}}
+{{ $RESOLUTION_WIDTH := .Env.RESOLUTION_WIDTH | default "1280" -}}
+{{ $RESOLUTION_WIDTH_MIN := .Env.RESOLUTION_WIDTH_MIN | default "320" -}}
+{{ $START_AUDIO_ONLY := .Env.START_AUDIO_ONLY | default "false" | toBool -}}
+{{ $START_AUDIO_MUTED := .Env.START_AUDIO_MUTED | default 10 -}}
+{{ $START_WITH_AUDIO_MUTED := .Env.START_WITH_AUDIO_MUTED | default "false" | toBool -}}
+{{ $START_SILENT := .Env.START_SILENT | default "false" | toBool -}}
+{{ $DISABLE_AUDIO_LEVELS := .Env.DISABLE_AUDIO_LEVELS | default "false" | toBool -}}
+{{ $ENABLE_NOISY_MIC_DETECTION := .Env.ENABLE_NOISY_MIC_DETECTION | default "true" | toBool -}}
+{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}}
+{{ $START_WITH_VIDEO_MUTED := .Env.START_WITH_VIDEO_MUTED | default "false" | toBool -}}
+{{ $DESKTOP_SHARING_FRAMERATE_AUTO := .Env.DESKTOP_SHARING_FRAMERATE_AUTO | default "true" | toBool -}}
+{{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}}
+{{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}}
+{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
+{{ $XMPP_HIDDEN_DOMAIN := .Env.XMPP_HIDDEN_DOMAIN | default "hidden.meet.jitsi" -}}
+{{ $DISABLE_DEEP_LINKING  := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}}
+{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
+{{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}}
+{{ $DISABLE_REMOTE_VIDEO_MENU := .Env.DISABLE_REMOTE_VIDEO_MENU | default "false" | toBool -}}
+{{ $DISABLE_PRIVATE_CHAT:= .Env.DISABLE_PRIVATE_CHAT | default "false" | toBool -}}
+{{ $DISABLE_KICKOUT := .Env.DISABLE_KICKOUT | default "false" | toBool -}}
+{{ $DISABLE_GRANT_MODERATOR := .Env.DISABLE_GRANT_MODERATOR | default "false" | toBool -}}
+{{ $ENABLE_E2EPING := .Env.ENABLE_E2EPING | default "false" | toBool -}}
+{{ $DISABLE_LOCAL_RECORDING := .Env.DISABLE_LOCAL_RECORDING | default "false" | toBool -}}
+{{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT := .Env.ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT | default "false" | toBool -}}
+{{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}}
+{{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}}
+{{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}}
+{{ $WHITEBOARD_ENABLED := or (.Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" | toBool) (.Env.WHITEBOARD_COLLAB_SERVER_URL_BASE | default "" | toBool) }}
+{{ $CODEC_ORDER_JVB := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
+{{ $CODEC_ORDER_JVB_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
+{{ $CODEC_ORDER_P2P := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
+{{ $CODEC_ORDER_P2P_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
+
+// Video configuration.
+//
+
+config.resolution = {{ $RESOLUTION }};
+config.constraints = {
+    video: {
+        height: { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} },
+        width: { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}},
+    }
+};
+
+{{ if not $ENABLE_SIMULCAST -}}
+config.disableSimulcast = true;
+{{ end -}}
+config.startVideoMuted = {{ $START_VIDEO_MUTED }};
+config.startWithVideoMuted = {{ $START_WITH_VIDEO_MUTED }};
+
+config.flags = {
+    sourceNameSignaling: true,
+    sendMultipleVideoStreams: true,
+    receiveMultipleVideoStreams: true
+};
+
+// ScreenShare Configuration.
+//
+
+{{ if not $DESKTOP_SHARING_FRAMERATE_AUTO -}}
+config.desktopSharingFrameRate = {
+    min: {{ $DESKTOP_SHARING_FRAMERATE_MIN }},
+    max: {{ $DESKTOP_SHARING_FRAMERATE_MAX }}
+};
+{{ end -}}
+
+// Audio configuration.
+//
+
+config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
+config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
+config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
+config.disableAGC = {{ not $ENABLE_AUTOMATIC_GAIN_CONTROL }};
+
+config.audioQuality = {
+    stereo: {{ $ENABLE_STEREO }}
+};
+
+{{ if .Env.AUDIO_QUALITY_OPUS_BITRATE -}}
+config.audioQuality.opusMaxAverageBitrate = '{{ .Env.AUDIO_QUALITY_OPUS_BITRATE }}';
+{{ end -}}
+
+config.startAudioOnly = {{ $START_AUDIO_ONLY }};
+config.startAudioMuted = {{ $START_AUDIO_MUTED }};
+config.startWithAudioMuted = {{ $START_WITH_AUDIO_MUTED }};
+config.startSilent = {{ $START_SILENT }};
+config.enableOpusRed = {{ $ENABLE_OPUS_RED }};
+config.disableAudioLevels = {{ $DISABLE_AUDIO_LEVELS }};
+config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }};
+
+
+// Peer-to-Peer options.
+//
+
+config.p2p = {
+    enabled: {{ $ENABLE_P2P }},
+    codecPreferenceOrder: {{ $CODEC_ORDER_P2P }},
+    mobileCodecPreferenceOrder: {{ $CODEC_ORDER_P2P_MOBILE }}
+};
+
+{{ if .Env.P2P_STUN_SERVERS -}}
+config.p2p.stunServers = '{{ .Env.P2P_STUN_SERVERS }}'.split(',').map(url => ({ urls: 'stun:' + url }));
+
+{{ end -}}
+
+// Breakout Rooms
+//
+
+config.hideAddRoomButton = {{ $ENABLE_BREAKOUT_ROOMS | not }};
+
+
+// Etherpad
+//
+
+{{ if .Env.ETHERPAD_PUBLIC_URL -}}
+config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}';
+{{ else if .Env.ETHERPAD_URL_BASE -}}
+config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/';
+{{ end -}}
+
+
+// Recording.
+//
+
+{{ if or $ENABLE_RECORDING $ENABLE_TRANSCRIPTIONS  -}}
+
+config.hiddenDomain = '{{ $XMPP_HIDDEN_DOMAIN }}';
+{{ end -}}
+
+{{ if $ENABLE_RECORDING -}}
+
+config.recordingService = {
+    // Whether to enable file recording or not using the "service" defined by the finalizer in Jibri
+    enabled: {{ $ENABLE_SERVICE_RECORDING }},
+
+    // Whether to show the possibility to share file recording with other people
+    // (e.g. meeting participants), based on the actual implementation
+    // on the backend.
+    sharingEnabled: {{ $ENABLE_FILE_RECORDING_SHARING }}
+};
+
+// Live streaming configuration.
+config.liveStreaming = {
+    enabled: {{ $ENABLE_LIVESTREAMING }},
+    dataPrivacyLink: '{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK }}',
+    helpLink: '{{ $ENABLE_LIVESTREAMING_HELP_LINK }}',
+    termsLink: '{{ $ENABLE_LIVESTREAMING_TERMS_LINK }}',
+    validatorRegExpString: '{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING }}'
+};
+
+
+{{ if .Env.DROPBOX_APPKEY -}}
+// Enable the dropbox integration.
+config.dropbox = {
+    appKey: '{{ .Env.DROPBOX_APPKEY }}'
+};
+
+{{ if .Env.DROPBOX_REDIRECT_URI -}}
+// A URL to redirect the user to, after authenticating
+// by default uses:
+// 'https://jitsi-meet.example.com/static/oauth.html'
+config.dropbox.redirectURI = '{{ .Env.DROPBOX_REDIRECT_URI }}';
+{{ end -}}
+{{ end -}}
+
+{{ end -}}
+
+// Local recording configuration.
+config.localRecording = {
+    disable: {{ $DISABLE_LOCAL_RECORDING }},
+    notifyAllParticipants: {{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT }},
+    disableSelfRecording: {{ $ENABLE_LOCAL_RECORDING_SELF_START }}
+};
+
+
+// Analytics.
+//
+
+config.analytics = {};
+
+{{ if .Env.AMPLITUDE_ID -}}
+// The Amplitude APP Key:
+config.analytics.amplitudeAPPKey = '{{ .Env.AMPLITUDE_ID }}';
+{{ end -}}
+
+{{ if .Env.GOOGLE_ANALYTICS_ID -}}
+// The Google Analytics Tracking ID:
+config.analytics.googleAnalyticsTrackingId = '{{ .Env.GOOGLE_ANALYTICS_ID }}';
+{{ end -}}
+
+{{ if .Env.MATOMO_ENDPOINT -}}
+// Matomo endpoint:
+config.analytics.matomoEndpoint = '{{ .Env.MATOMO_ENDPOINT }}';
+{{ end -}}
+
+{{ if .Env.MATOMO_SITE_ID -}}
+// Matomo site ID:
+config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}';
+{{ end -}}
+
+{{ if .Env.ANALYTICS_SCRIPT_URLS -}}
+// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
+config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS | compact) }}' ];
+{{ end -}}
+
+{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
+config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS | compact) }}' ];
+{{ end -}}
+
+
+// Dial in/out services.
+//
+
+{{ if $ENABLE_JAAS_COMPONENTS }}
+config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';
+config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';
+{{ else }}
+{{ if .Env.CONFCODE_URL -}}
+config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}';
+{{ end -}}
+{{ if .Env.DIALIN_NUMBERS_URL -}}
+config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}';
+{{ end -}}
+{{ end -}}
+
+{{ if .Env.DIALOUT_AUTH_URL -}}
+config.dialOutAuthUrl = '{{ .Env.DIALOUT_AUTH_URL }}';
+{{ end -}}
+
+{{ if .Env.DIALOUT_CODES_URL -}}
+config.dialOutCodesUrl = '{{ .Env.DIALOUT_CODES_URL }}';
+{{ end -}}
+
+
+// Calendar service integration.
+//
+
+config.enableCalendarIntegration = {{ $ENABLE_CALENDAR }};
+
+{{ if .Env.GOOGLE_API_APP_CLIENT_ID -}}
+config.googleApiApplicationClientID = '{{ .Env.GOOGLE_API_APP_CLIENT_ID }}';
+{{ end -}}
+
+{{ if .Env.MICROSOFT_API_APP_CLIENT_ID -}}
+config.microsoftApiApplicationClientID = '{{ .Env.MICROSOFT_API_APP_CLIENT_ID }}';
+{{ end -}}
+
+
+// Invitation service.
+//
+
+{{ if .Env.INVITE_SERVICE_URL -}}
+config.inviteServiceUrl = '{{ .Env.INVITE_SERVICE_URL }}';
+{{ end -}}
+
+{{ if .Env.PEOPLE_SEARCH_URL -}}
+config.peopleSearchUrl = '{{ .Env.PEOPLE_SEARCH_URL }}';
+config.peopleSearchQueryTypes = ['user','conferenceRooms'];
+{{ end -}}
+
+
+// Miscellaneous.
+//
+
+// Prejoin page.
+config.prejoinConfig = {
+    enabled: {{ $ENABLE_PREJOIN_PAGE }},
+
+    // Hides the participant name editing field in the prejoin screen.
+    hideDisplayName: {{ $HIDE_PREJOIN_DISPLAY_NAME }}
+};
+
+// List of buttons to hide from the extra join options dropdown on prejoin screen.
+{{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}}
+config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS | compact) }}' ];
+{{ end -}}
+
+// Welcome page.
+config.welcomePage = {
+    disabled: {{ not $ENABLE_WELCOME_PAGE }}
+};
+
+// Close page.
+config.enableClosePage = {{ $ENABLE_CLOSE_PAGE }};
+
+// Default language.
+{{ if .Env.DEFAULT_LANGUAGE -}}
+config.defaultLanguage = '{{ .Env.DEFAULT_LANGUAGE }}';
+{{ end -}}
+
+// Require users to always specify a display name.
+config.requireDisplayName = {{ $ENABLE_REQUIRE_DISPLAY_NAME }};
+
+// Chrome extension banner.
+{{ if .Env.CHROME_EXTENSION_BANNER_JSON -}}
+config.chromeExtensionBanner = {{ .Env.CHROME_EXTENSION_BANNER_JSON }};
+{{ end -}}
+
+// Disables profile and the edit of all fields from the profile settings (display name and email)
+config.disableProfile = {{ $DISABLE_PROFILE }};
+
+// Room password (false for anything, number for max digits)
+{{ if $ENABLE_JAAS_COMPONENTS -}}
+config.roomPasswordNumberOfDigits = 10;
+{{ else -}}
+config.roomPasswordNumberOfDigits = {{ $ROOM_PASSWORD_DIGITS }};
+{{ end -}}
+
+// Advanced.
+//
+
+{{ if not $ENABLE_REMB -}}
+config.enableRemb = false;
+{{ end -}}
+{{ if not $ENABLE_TCC -}}
+config.enableTcc = false;
+{{ end -}}
+
+
+// Transcriptions (subtitles and buttons can be configured in interface_config)
+config.transcription = {
+    enabled: {{ $ENABLE_TRANSCRIPTIONS }},
+    translationLanguages: {{ $TRANSLATION_LANGUAGES }},
+    translationLanguagesHead: {{ $TRANSLATION_LANGUAGES_HEAD }},
+    useAppLanguage: {{ $USE_APP_LANGUAGE }},
+    preferredLanguage: '{{ $PREFERRED_LANGUAGE }}',
+    disableStartForAll: {{ $DISABLE_START_FOR_ALL }},
+    autoCaptionOnRecord: {{ $AUTO_CAPTION_ON_RECORD }},
+};
+
+// Dynamic branding
+{{ if .Env.DYNAMIC_BRANDING_URL -}}
+// External API url used to receive branding specific information.
+config.dynamicBrandingUrl = '{{ .Env.DYNAMIC_BRANDING_URL }}';
+{{ else if .Env.BRANDING_DATA_URL  -}}
+config.brandingDataUrl = '{{ .Env.BRANDING_DATA_URL }}';
+{{ end -}}
+
+{{ if .Env.TOKEN_AUTH_URL -}}
+// Authenticate using external service
+config.tokenAuthUrl = '{{ .Env.TOKEN_AUTH_URL }}';
+{{ end -}}
+
+
+// Deployment information.
+//
+
+config.deploymentInfo = {};
+
+{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}}
+config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}';
+{{ end -}}
+
+{{ if .Env.DEPLOYMENTINFO_SHARD -}}
+config.deploymentInfo.shard = '{{ .Env.DEPLOYMENTINFO_SHARD }}';
+{{ end -}}
+
+{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}}
+config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
+{{ end -}}
+
+{{ if .Env.DEPLOYMENTINFO_REGION -}}
+config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}';
+{{ end -}}
+
+// Deep Linking
+config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }};
+
+// P2P preferred codec
+{{ if .Env.P2P_PREFERRED_CODEC -}}
+config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}';
+{{ end -}}
+
+// Video quality settings.
+//
+
+config.videoQuality = {};
+config.videoQuality.codecPreferenceOrder = {{ $CODEC_ORDER_JVB }};
+config.videoQuality.mobileCodecPreferenceOrder = {{ $CODEC_ORDER_JVB_MOBILE }};
+config.videoQuality.enableAdaptiveMode = {{ $ENABLE_ADAPTIVE_MODE }};
+
+{{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}}
+config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}';
+{{ end -}}
+
+config.videoQuality.av1 = {};
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_LOW }}
+config.videoQuality.av1.low = {{ .Env.VIDEOQUALITY_BITRATE_AV1_LOW }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }}
+config.videoQuality.av1.standard = {{ .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }}
+config.videoQuality.av1.high = {{ .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_FULL }}
+config.videoQuality.av1.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_FULL }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }}
+config.videoQuality.av1.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }}
+config.videoQuality.av1.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }};
+{{ end -}}
+
+config.videoQuality.h264 = {};
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_LOW }}
+config.videoQuality.h264.low = {{ .Env.VIDEOQUALITY_BITRATE_H264_LOW }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }}
+config.videoQuality.h264.standard = {{ .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_HIGH }}
+config.videoQuality.h264.high = {{ .Env.VIDEOQUALITY_BITRATE_H264_HIGH }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_FULL }}
+config.videoQuality.h264.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_FULL }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }}
+config.videoQuality.h264.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }}
+config.videoQuality.h264.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }};
+{{ end -}}
+
+config.videoQuality.vp8 = {};
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_LOW }}
+config.videoQuality.vp8.low = {{ .Env.VIDEOQUALITY_BITRATE_VP8_LOW }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }}
+config.videoQuality.vp8.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }}
+config.videoQuality.vp8.high = {{ .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_FULL }}
+config.videoQuality.vp8.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_FULL }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }}
+config.videoQuality.vp8.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }}
+config.videoQuality.vp8.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }};
+{{ end -}}
+
+config.videoQuality.vp9 = {};
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_LOW }}
+config.videoQuality.vp9.low = {{ .Env.VIDEOQUALITY_BITRATE_VP9_LOW }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }}
+config.videoQuality.vp9.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }}
+config.videoQuality.vp9.high = {{ .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_FULL }}
+config.videoQuality.vp9.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_FULL }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }}
+config.videoQuality.vp9.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }};
+{{ end -}}
+
+{{ if .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }}
+config.videoQuality.vp9.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }};
+{{ end -}}
+
+ // Reactions
+config.disableReactions = {{ $DISABLE_REACTIONS }};
+
+// Polls
+config.disablePolls = {{ $DISABLE_POLLS }};
+
+// Configure toolbar buttons
+{{ if .Env.TOOLBAR_BUTTONS -}}
+config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS | compact) }}' ];
+{{ end -}}
+
+// Hides the buttons at pre-join screen
+{{ if .Env.HIDE_PREMEETING_BUTTONS -}}
+config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS | compact) }}' ];
+{{ end -}}
+
+// Configure remote participant video menu
+config.remoteVideoMenu = {
+    disabled: {{ $DISABLE_REMOTE_VIDEO_MENU }},
+    disableKick: {{ $DISABLE_KICKOUT }},
+    disableGrantModerator: {{ $DISABLE_GRANT_MODERATOR }},
+    disablePrivateChat: {{ $DISABLE_PRIVATE_CHAT }}
+};
+
+// Configure e2eping
+config.e2eping = {
+    enabled: {{ $ENABLE_E2EPING }}
+};
+
+{{ if .Env.E2EPING_NUM_REQUESTS -}}
+config.e2eping.numRequests = {{ .Env.E2EPING_NUM_REQUESTS }};
+{{ end -}}
+{{ if .Env.E2EPING_MAX_CONFERENCE_SIZE -}}
+config.e2eping.maxConferenceSize = {{ .Env.E2EPING_MAX_CONFERENCE_SIZE }};
+{{ end -}}
+{{ if .Env.E2EPING_MAX_MESSAGE_PER_SECOND -}}
+config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }};
+{{ end }}
+
+// Settings for the Excalidraw whiteboard integration.
+config.whiteboard = {
+    enabled: {{ $WHITEBOARD_ENABLED }},
+{{ if .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL -}}
+    collabServerBaseUrl: '{{ .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
+{{ else if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE -}}
+    collabServerBaseUrl: '{{ $PUBLIC_URL }}'
+{{ end -}}
+};
+
+// JaaS support: pre-configure image if JAAS_APP_ID was set.
+{{ if .Env.JAAS_APP_ID -}}
+{{ $JAAS_USE_STAGING := .Env.JAAS_USE_STAGING | default "false" | toBool -}}
+{{ $JAAS_DOMAIN := $JAAS_USE_STAGING | ternary "stage.8x8.vc" "8x8.vc" -}}
+
+config.hosts.domain = '{{ $JAAS_DOMAIN }}';
+config.hosts.muc = 'conference.{{ .Env.JAAS_APP_ID }}.{{ $JAAS_DOMAIN }}';
+config.hosts.focus = 'focus.{{ $JAAS_DOMAIN }}';
+
+config.analytics.rtcstatsEnabled = true;
+config.analytics.rtcstatsStoreLogs = true;
+config.analytics.rtcstatsUseLegacy = false;
+config.analytics.rtcstatsEndpoint = 'wss://rtcstats-server-8x8.jitsi.net/';
+config.analytics.rtcstatsPollInterval = 10000;
+config.analytics.rtcstatsSendSdp = true;
+
+config.bosh = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/http-bind';
+config.websocket = 'wss://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/xmpp-websocket';
+config.websocketKeepAliveUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/_unlock';
+config.conferenceRequestUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/conference-request/v1';
+
+config.hiddenDomain = 'recorder.{{ $JAAS_DOMAIN }}';
+config.hiddenFromRecorderFeatureEnabled = true;
+config.enableEmailInStats = true;
+
+config.jaasActuatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-actuator';
+config.jaasTokenUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/token-mapping';
+config.jaasConferenceCreatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access/conference-creator';
+config.webhookProxyUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy';
+config.billingCounterUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/billing-counter/v1/connection';
+config.brandingDataUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/branding/public/v1/conferences';
+config.dialInNumbersUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/access/v1/dids';
+config.dialInConfCodeUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access';
+config.dialOutAuthUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/phone-authorize';
+config.dialOutRegionUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/customer-configs/v1/outbound-destination';
+config.peopleSearchUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/directory/search';
+config.inviteServiceUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/meeting/invite';
+config.recordingSharingUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-recordings/link';
+config.peopleSearchQueryTypes = ['user','conferenceRooms'];
+config.sipInviteUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/sip-jibri-gateway/jibris/invite';
+config.jaasFeedbackMetadataURL = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy/feedback';
+
+{{ if $JAAS_USE_STAGING -}}
+config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend-pilot.cloudflare.jitsi.net';
+{{ else -}}
+config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend.cloudflare.jitsi.net';
+{{ end -}}
+config.whiteboard.userLimit = 25;
+{{ end -}}
+
+// Testing
+config.testing = {
+    enableCodecSelectionAPI: true
+};
diff --git a/infrastructure/web/image/resources/settings-config.js b/infrastructure/web/image/resources/settings-config.js
index 4080268..3334b24 100644
--- a/infrastructure/web/image/resources/settings-config.js
+++ b/infrastructure/web/image/resources/settings-config.js
@@ -1,7 +1,8 @@
 //https://github.com/jitsi/docker-jitsi-meet/blob/master/web/rootfs/defaults/settings-config.js
 
-{{ $DEPLOYMENTINFO_USERREGION := .Env.DEPLOYMENTINFO_USERREGION | default "" -}}
+{{ $ENABLE_ADAPTIVE_MODE := .Env.ENABLE_ADAPTIVE_MODE | default "true" | toBool -}}
 {{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
+{{ $ENABLE_AUTOMATIC_GAIN_CONTROL := .Env.ENABLE_AUTOMATIC_GAIN_CONTROL | default "true" | toBool -}}
 {{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
 {{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
 {{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}}
@@ -50,7 +51,7 @@
 {{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}}
 {{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}}
 {{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
-{{ $XMPP_RECORDER_DOMAIN := .Env.XMPP_RECORDER_DOMAIN | default "recorder.meet.jitsi" -}}
+{{ $XMPP_HIDDEN_DOMAIN := .Env.XMPP_HIDDEN_DOMAIN | default "hidden.meet.jitsi" -}}
 {{ $DISABLE_DEEP_LINKING  := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}}
 {{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
 {{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}}
@@ -64,9 +65,11 @@
 {{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}}
 {{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}}
 {{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}}
-{{ $WHITEBOARD_COLLAB_SERVER_PUBLIC_URL := .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" -}}
-{{ $WHITEBOARD_ENABLED := .Env.WHITEBOARD_ENABLED | default "false" | toBool -}}
-{{ $TESTING_AV1_SUPPORT := .Env.TESTING_AV1_SUPPORT | default "false" | toBool -}}
+{{ $WHITEBOARD_ENABLED := or (.Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" | toBool) (.Env.WHITEBOARD_COLLAB_SERVER_URL_BASE | default "" | toBool) }}
+{{ $CODEC_ORDER_JVB := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
+{{ $CODEC_ORDER_JVB_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
+{{ $CODEC_ORDER_P2P := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
+{{ $CODEC_ORDER_P2P_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
 
 // Video configuration.
 //
@@ -107,6 +110,7 @@ config.desktopSharingFrameRate = {
 config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
 config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
 config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
+config.disableAGC = {{ not $ENABLE_AUTOMATIC_GAIN_CONTROL }};
 
 config.audioQuality = {
     stereo: {{ $ENABLE_STEREO }}
@@ -129,9 +133,15 @@ config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }};
 //
 
 config.p2p = {
-    enabled: {{ $ENABLE_P2P }}
+    enabled: {{ $ENABLE_P2P }},
+    codecPreferenceOrder: {{ $CODEC_ORDER_P2P }},
+    mobileCodecPreferenceOrder: {{ $CODEC_ORDER_P2P_MOBILE }}
 };
 
+{{ if .Env.P2P_STUN_SERVERS -}}
+config.p2p.stunServers = '{{ .Env.P2P_STUN_SERVERS }}'.split(',').map(url => ({ urls: 'stun:' + url }));
+
+{{ end -}}
 
 // Breakout Rooms
 //
@@ -152,9 +162,12 @@ config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/';
 // Recording.
 //
 
-{{ if $ENABLE_RECORDING  -}}
+{{ if or $ENABLE_RECORDING $ENABLE_TRANSCRIPTIONS  -}}
 
-config.hiddenDomain = '{{ $XMPP_RECORDER_DOMAIN }}';
+config.hiddenDomain = '{{ $XMPP_HIDDEN_DOMAIN }}';
+{{ end -}}
+
+{{ if $ENABLE_RECORDING -}}
 
 config.recordingService = {
     // Whether to enable file recording or not using the "service" defined by the finalizer in Jibri
@@ -227,11 +240,11 @@ config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}';
 
 {{ if .Env.ANALYTICS_SCRIPT_URLS -}}
 // Array of script URLs to load as lib-jitsi-meet "analytics handlers".
-config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS) }}' ];
+config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS | compact) }}' ];
 {{ end -}}
 
 {{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
-config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS) }}' ];
+config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS | compact) }}' ];
 {{ end -}}
 
 
@@ -299,7 +312,7 @@ config.prejoinConfig = {
 
 // List of buttons to hide from the extra join options dropdown on prejoin screen.
 {{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}}
-config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS) }}' ];
+config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS | compact) }}' ];
 {{ end -}}
 
 // Welcome page.
@@ -390,10 +403,6 @@ config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
 config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}';
 {{ end -}}
 
-{{ if $DEPLOYMENTINFO_USERREGION -}}
-config.deploymentInfo.userRegion = '{{ $DEPLOYMENTINFO_USERREGION }}';
-{{ end -}}
-
 // Deep Linking
 config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }};
 
@@ -406,6 +415,10 @@ config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}';
 //
 
 config.videoQuality = {};
+config.videoQuality.codecPreferenceOrder = {{ $CODEC_ORDER_JVB }};
+config.videoQuality.mobileCodecPreferenceOrder = {{ $CODEC_ORDER_JVB_MOBILE }};
+config.videoQuality.enableAdaptiveMode = {{ $ENABLE_ADAPTIVE_MODE }};
+
 {{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}}
 config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}';
 {{ end -}}
@@ -522,12 +535,12 @@ config.disablePolls = {{ $DISABLE_POLLS }};
 
 // Configure toolbar buttons
 {{ if .Env.TOOLBAR_BUTTONS -}}
-config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS) }}' ];
+config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS | compact) }}' ];
 {{ end -}}
 
 // Hides the buttons at pre-join screen
 {{ if .Env.HIDE_PREMEETING_BUTTONS -}}
-config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS) }}' ];
+config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS | compact) }}' ];
 {{ end -}}
 
 // Configure remote participant video menu
@@ -556,9 +569,63 @@ config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }};
 // Settings for the Excalidraw whiteboard integration.
 config.whiteboard = {
     enabled: {{ $WHITEBOARD_ENABLED }},
-    collabServerBaseUrl: '{{ $WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
+{{ if .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL -}}
+    collabServerBaseUrl: '{{ .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
+{{ else if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE -}}
+    collabServerBaseUrl: '{{ $PUBLIC_URL }}'
+{{ end -}}
 };
 
+// JaaS support: pre-configure image if JAAS_APP_ID was set.
+{{ if .Env.JAAS_APP_ID -}}
+{{ $JAAS_USE_STAGING := .Env.JAAS_USE_STAGING | default "false" | toBool -}}
+{{ $JAAS_DOMAIN := $JAAS_USE_STAGING | ternary "stage.8x8.vc" "8x8.vc" -}}
+
+config.hosts.domain = '{{ $JAAS_DOMAIN }}';
+config.hosts.muc = 'conference.{{ .Env.JAAS_APP_ID }}.{{ $JAAS_DOMAIN }}';
+config.hosts.focus = 'focus.{{ $JAAS_DOMAIN }}';
+
+config.analytics.rtcstatsEnabled = true;
+config.analytics.rtcstatsStoreLogs = true;
+config.analytics.rtcstatsUseLegacy = false;
+config.analytics.rtcstatsEndpoint = 'wss://rtcstats-server-8x8.jitsi.net/';
+config.analytics.rtcstatsPollInterval = 10000;
+config.analytics.rtcstatsSendSdp = true;
+
+config.bosh = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/http-bind';
+config.websocket = 'wss://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/xmpp-websocket';
+config.websocketKeepAliveUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/_unlock';
+config.conferenceRequestUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/conference-request/v1';
+
+config.hiddenDomain = 'recorder.{{ $JAAS_DOMAIN }}';
+config.hiddenFromRecorderFeatureEnabled = true;
+config.enableEmailInStats = true;
+
+config.jaasActuatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-actuator';
+config.jaasTokenUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/token-mapping';
+config.jaasConferenceCreatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access/conference-creator';
+config.webhookProxyUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy';
+config.billingCounterUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/billing-counter/v1/connection';
+config.brandingDataUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/branding/public/v1/conferences';
+config.dialInNumbersUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/access/v1/dids';
+config.dialInConfCodeUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access';
+config.dialOutAuthUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/phone-authorize';
+config.dialOutRegionUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/customer-configs/v1/outbound-destination';
+config.peopleSearchUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/directory/search';
+config.inviteServiceUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/meeting/invite';
+config.recordingSharingUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-recordings/link';
+config.peopleSearchQueryTypes = ['user','conferenceRooms'];
+config.sipInviteUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/sip-jibri-gateway/jibris/invite';
+config.jaasFeedbackMetadataURL = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy/feedback';
+
+{{ if $JAAS_USE_STAGING -}}
+config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend-pilot.cloudflare.jitsi.net';
+{{ else -}}
+config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend.cloudflare.jitsi.net';
+{{ end -}}
+config.whiteboard.userLimit = 25;
+{{ end -}}
+
 // Testing
 config.testing = {
     enableAv1Support: {{ $TESTING_AV1_SUPPORT }}

From 68442d9e21c2f6c3975348f60a99a7a4d2d5723b Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 08:55:01 +0100
Subject: [PATCH 18/33] use official web

---
 src/main/resources/jitsi/web-config-deployment.yaml | 2 +-
 src/main/resources/jitsi/web-config-envs-cm.yaml    | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/main/resources/jitsi/web-config-deployment.yaml b/src/main/resources/jitsi/web-config-deployment.yaml
index eef7f25..a7996cf 100644
--- a/src/main/resources/jitsi/web-config-deployment.yaml
+++ b/src/main/resources/jitsi/web-config-deployment.yaml
@@ -25,7 +25,7 @@ spec:
         - name: jitsi-meet
           securityContext:
             {}
-          image: domaindrivenarchitecture/c4k-jitsi-web
+          image: jitsi/web:stable-10008
           imagePullPolicy: IfNotPresent
           envFrom:
           - configMapRef:
diff --git a/src/main/resources/jitsi/web-config-envs-cm.yaml b/src/main/resources/jitsi/web-config-envs-cm.yaml
index aa380f0..0e78825 100644
--- a/src/main/resources/jitsi/web-config-envs-cm.yaml
+++ b/src/main/resources/jitsi/web-config-envs-cm.yaml
@@ -16,7 +16,6 @@ data:
   RESOLUTION_MIN: "240"
   RESOLUTION_WIDTH: "853"
   RESOLUTION_WIDTH_MIN: "427"
-  DISABLE_AUDIO_LEVELS: "true"
+  DISABLE_AUDIO_LEVELS: true
   ETHERPAD_PUBLIC_URL: REPLACE_ME
-  WHITEBOARD_ENABLED: "true"
   WHITEBOARD_COLLAB_SERVER_PUBLIC_URL: REPLACE_ME
\ No newline at end of file

From 0226187fc3e61c7d9be17d5b87384aa34d45ce84 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 09:24:30 +0100
Subject: [PATCH 19/33] do we need audio levels disabled?

---
 src/main/resources/jitsi/web-config-envs-cm.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/main/resources/jitsi/web-config-envs-cm.yaml b/src/main/resources/jitsi/web-config-envs-cm.yaml
index 0e78825..b8386cb 100644
--- a/src/main/resources/jitsi/web-config-envs-cm.yaml
+++ b/src/main/resources/jitsi/web-config-envs-cm.yaml
@@ -16,6 +16,5 @@ data:
   RESOLUTION_MIN: "240"
   RESOLUTION_WIDTH: "853"
   RESOLUTION_WIDTH_MIN: "427"
-  DISABLE_AUDIO_LEVELS: true
   ETHERPAD_PUBLIC_URL: REPLACE_ME
   WHITEBOARD_COLLAB_SERVER_PUBLIC_URL: REPLACE_ME
\ No newline at end of file

From af20e09d3e5f7b8a1ec47e5d392e5233d76dcd29 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 09:24:48 +0100
Subject: [PATCH 20/33] fix excalidraw service

---
 src/main/resources/jitsi/excalidraw-config-service.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/resources/jitsi/excalidraw-config-service.yaml b/src/main/resources/jitsi/excalidraw-config-service.yaml
index 0ac4be3..a1613d2 100644
--- a/src/main/resources/jitsi/excalidraw-config-service.yaml
+++ b/src/main/resources/jitsi/excalidraw-config-service.yaml
@@ -1,7 +1,7 @@
 apiVersion: v1
 kind: Service
 metadata:
-  name: excalidraw-backend
+  name: excalidraw
   namespace: NAMESPACE
   labels:
     app.kubernetes.io/name: excalidraw  

From be11bbd4331f9f9a1b3a0f15f4f36b2a3e7311c2 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 09:25:26 +0100
Subject: [PATCH 21/33] remove the old

---
 src/main/resources/jitsi/deployment.yaml      | 124 ------------------
 .../resources/jitsi/etherpad-service.yaml     |  14 --
 .../jitsi/excalidraw-backend-service.yaml     |  14 --
 .../jitsi/excalidraw-deployment.yaml          |  21 ---
 src/main/resources/jitsi/jvb-service.yaml     |  19 ---
 src/main/resources/jitsi/web-service.yaml     |  17 ---
 6 files changed, 209 deletions(-)
 delete mode 100644 src/main/resources/jitsi/deployment.yaml
 delete mode 100644 src/main/resources/jitsi/etherpad-service.yaml
 delete mode 100644 src/main/resources/jitsi/excalidraw-backend-service.yaml
 delete mode 100644 src/main/resources/jitsi/excalidraw-deployment.yaml
 delete mode 100644 src/main/resources/jitsi/jvb-service.yaml
 delete mode 100644 src/main/resources/jitsi/web-service.yaml

diff --git a/src/main/resources/jitsi/deployment.yaml b/src/main/resources/jitsi/deployment.yaml
deleted file mode 100644
index 60ce776..0000000
--- a/src/main/resources/jitsi/deployment.yaml
+++ /dev/null
@@ -1,124 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  labels:
-    app: jitsi
-  name: jitsi
-  namespace: NAMESPACE
-spec:
-  strategy:
-    type: Recreate
-  selector:
-    matchLabels:
-      app: jitsi
-  template:
-    metadata:
-      labels:
-        app: jitsi
-    spec:
-      containers:
-        - name: jicofo
-          image: jitsi/jicofo:stable-9646
-          imagePullPolicy: IfNotPresent
-          env:
-            - name: XMPP_SERVER
-              value: localhost
-            - name: JICOFO_COMPONENT_SECRET
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_COMPONENT_SECRET
-            - name: JICOFO_AUTH_USER
-              value: focus
-            - name: JICOFO_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_AUTH_PASSWORD
-            - name: TZ
-              value: Europe/Berlin
-        - name: web
-          image: domaindrivenarchitecture/c4k-jitsi-web
-          imagePullPolicy: IfNotPresent
-          env:
-            - name: PUBLIC_URL
-              value: REPLACE_JITSI_FQDN
-            - name: XMPP_SERVER
-              value: localhost
-            - name: XMPP_BOSH_URL_BASE
-              value: http://127.0.0.1:5280
-            - name: JICOFO_AUTH_USER
-              value: focus
-            - name: TZ
-              value: Europe/Berlin
-            - name: JVB_TCP_HARVESTER_DISABLED
-              value: "true"
-            - name: DEFAULT_LANGUAGE
-              value: "de"
-            - name: RESOLUTION
-              value: "480"
-            - name: RESOLUTION_MIN
-              value: "240"
-            - name: RESOLUTION_WIDTH
-              value: "853"
-            - name: RESOLUTION_WIDTH_MIN
-              value: "427"
-            - name: DISABLE_AUDIO_LEVELS
-              value: "true"
-            - name: ETHERPAD_PUBLIC_URL
-              value: REPLACE_ETHERPAD_URL
-            - name: WHITEBOARD_ENABLED
-              value: "true"
-            - name: WHITEBOARD_COLLAB_SERVER_PUBLIC_URL
-              value: REPLACE_EXCALIDRAW_BACKEND_URL
-            - name: COLIBRI_WEBSOCKET_REGEX
-              value: "127.0.0.1"
-        - name: jvb
-          image: jitsi/jvb:stable-9646
-          imagePullPolicy: IfNotPresent
-          env:
-            - name: PUBLIC_URL
-              value: REPLACE_JITSI_FQDN
-            - name: XMPP_SERVER
-              value: localhost
-            - name: DOCKER_HOST_ADDRESS
-              value: REPLACE_JITSI_FQDN
-            - name: JICOFO_AUTH_USER
-              value: focus
-            - name: JVB_TCP_HARVESTER_DISABLED
-              value: "true"
-            - name: JVB_AUTH_USER
-              value: jvb
-            - name: JVB_PORT
-              value: "30300"
-            - name: JVB_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JVB_AUTH_PASSWORD
-            - name: JICOFO_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_AUTH_PASSWORD
-            - name: TZ
-              value: Europe/Berlin
-        - name: etherpad
-          image: etherpad/etherpad:2
-          env:
-            - name: XMPP_SERVER
-              value: localhost
-            - name: JICOFO_COMPONENT_SECRET
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_COMPONENT_SECRET
-            - name: JICOFO_AUTH_USER
-              value: focus
-            - name: JICOFO_AUTH_PASSWORD
-              valueFrom:
-                secretKeyRef:
-                  name: jitsi-config
-                  key: JICOFO_AUTH_PASSWORD
-            - name: TZ
-              value: Europe/Berlin
\ No newline at end of file
diff --git a/src/main/resources/jitsi/etherpad-service.yaml b/src/main/resources/jitsi/etherpad-service.yaml
deleted file mode 100644
index 7538aa8..0000000
--- a/src/main/resources/jitsi/etherpad-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  labels:
-    service: etherpad
-  name: etherpad
-  namespace: NAMESPACE
-spec:
-  ports:
-  - name: etherpad
-    port: 9001
-    targetPort: 9001
-  selector:
-    app: jitsi
\ No newline at end of file
diff --git a/src/main/resources/jitsi/excalidraw-backend-service.yaml b/src/main/resources/jitsi/excalidraw-backend-service.yaml
deleted file mode 100644
index d7ab698..0000000
--- a/src/main/resources/jitsi/excalidraw-backend-service.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  labels:
-    service: excalidraw-backend
-  name: excalidraw-backend
-  namespace: NAMESPACE
-spec:
-  ports:
-  - name: excalidraw-backend
-    port: 3002
-    targetPort: 80
-  selector:
-    app: excalidraw-backend
\ No newline at end of file
diff --git a/src/main/resources/jitsi/excalidraw-deployment.yaml b/src/main/resources/jitsi/excalidraw-deployment.yaml
deleted file mode 100644
index e5c3301..0000000
--- a/src/main/resources/jitsi/excalidraw-deployment.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  labels:
-    app: excalidraw-backend
-  name: excalidraw-backend
-  namespace: NAMESPACE
-spec:
-  strategy:
-    type: Recreate
-  selector:
-    matchLabels:
-      app: excalidraw-backend
-  template:
-    metadata:
-      labels:
-        app: excalidraw-backend
-    spec:
-      containers:
-        - name: excalidraw-backend
-          image: domaindrivenarchitecture/c4k-jitsi-excalidraw-backend
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jvb-service.yaml b/src/main/resources/jitsi/jvb-service.yaml
deleted file mode 100644
index 24b4a33..0000000
--- a/src/main/resources/jitsi/jvb-service.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  labels:
-    service: jvb
-  annotations:
-    metallb.universe.tf/allow-shared-ip: "shared-ip-service-group"
-    metallb.universe.tf/address-pool: public
-  name: jvb-udp
-  namespace: NAMESPACE
-spec:
-  type: LoadBalancer
-  ports:
-  - port: 30300
-    protocol: UDP
-    targetPort: 30300
-    nodePort: 30300
-  selector:
-    app: jitsi
\ No newline at end of file
diff --git a/src/main/resources/jitsi/web-service.yaml b/src/main/resources/jitsi/web-service.yaml
deleted file mode 100644
index 0b1ce43..0000000
--- a/src/main/resources/jitsi/web-service.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  labels:
-    service: web
-  name: web
-  namespace: NAMESPACE
-spec:
-  ports:
-  - name: "http"
-    port: 80
-    targetPort: 80
-  - name: "https"
-    port: 443
-    targetPort: 443
-  selector:
-    app: jitsi
\ No newline at end of file

From 3f0906c1d260b71384983585ed61fd5ec14f2ab1 Mon Sep 17 00:00:00 2001
From: zam <mirco.zachmann@meissa.de>
Date: Tue, 18 Feb 2025 09:43:53 +0100
Subject: [PATCH 22/33] [skip ci] stable 10008 versions to all parts

---
 src/main/resources/jitsi/jibri-config-deployment.yaml     | 2 +-
 src/main/resources/jitsi/jicofo-config-deployment.yaml    | 2 +-
 src/main/resources/jitsi/jvb-config-deployment.yaml       | 2 +-
 src/main/resources/jitsi/prosody-config-stateful-set.yaml | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/main/resources/jitsi/jibri-config-deployment.yaml b/src/main/resources/jitsi/jibri-config-deployment.yaml
index cc72bad..5e124fd 100644
--- a/src/main/resources/jitsi/jibri-config-deployment.yaml
+++ b/src/main/resources/jitsi/jibri-config-deployment.yaml
@@ -24,7 +24,7 @@ spec:
         securityContext:
           capabilities:
             add: ["SYS_ADMIN"]
-        image: "jitsi/jibri:stable-9646"
+        image: "jitsi/jibri:stable-10008"
         imagePullPolicy: IfNotPresent
         ports:
         - name: http-internal
diff --git a/src/main/resources/jitsi/jicofo-config-deployment.yaml b/src/main/resources/jitsi/jicofo-config-deployment.yaml
index 7bf78b5..99155ad 100644
--- a/src/main/resources/jitsi/jicofo-config-deployment.yaml
+++ b/src/main/resources/jitsi/jicofo-config-deployment.yaml
@@ -43,7 +43,7 @@ spec:
         - name: jitsi-meet
           securityContext:
             {}
-          image: "jitsi/jicofo:stable-9646"
+          image: "jitsi/jicofo:stable-10008"
           imagePullPolicy: IfNotPresent
           envFrom:
           - secretRef:
diff --git a/src/main/resources/jitsi/jvb-config-deployment.yaml b/src/main/resources/jitsi/jvb-config-deployment.yaml
index cc3954e..28e7311 100644
--- a/src/main/resources/jitsi/jvb-config-deployment.yaml
+++ b/src/main/resources/jitsi/jvb-config-deployment.yaml
@@ -25,7 +25,7 @@ spec:
         - name: jitsi-meet
           securityContext:
             {}
-          image: "jitsi/jvb:stable-9646"
+          image: "jitsi/jvb:stable-10008"
           imagePullPolicy: IfNotPresent
           envFrom:
           - secretRef:
diff --git a/src/main/resources/jitsi/prosody-config-stateful-set.yaml b/src/main/resources/jitsi/prosody-config-stateful-set.yaml
index 7174b05..f3132f9 100644
--- a/src/main/resources/jitsi/prosody-config-stateful-set.yaml
+++ b/src/main/resources/jitsi/prosody-config-stateful-set.yaml
@@ -24,7 +24,7 @@ spec:
         - name: prosody
           securityContext:
             {}
-          image: "jitsi/prosody:stable-9909"
+          image: "jitsi/prosody:stable-10008"
           imagePullPolicy: IfNotPresent
           envFrom:
           - configMapRef:

From 594aca23857d13bf95ae175a7ead0e02b406d444 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 11:36:57 +0100
Subject: [PATCH 23/33] make nicer names

---
 src/main/resources/jitsi/excalidraw-config-deployment.yaml | 2 +-
 src/main/resources/jitsi/excalidraw-config-service.yaml    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/resources/jitsi/excalidraw-config-deployment.yaml b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
index 54a65ca..b3565cf 100644
--- a/src/main/resources/jitsi/excalidraw-config-deployment.yaml
+++ b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
@@ -16,5 +16,5 @@ spec:
         app.kubernetes.io/name: excalidraw
     spec:
       containers:
-        - name: excalidraw-backend
+        - name: excalidraw
           image: domaindrivenarchitecture/c4k-jitsi-excalidraw-backend
\ No newline at end of file
diff --git a/src/main/resources/jitsi/excalidraw-config-service.yaml b/src/main/resources/jitsi/excalidraw-config-service.yaml
index a1613d2..f620a7e 100644
--- a/src/main/resources/jitsi/excalidraw-config-service.yaml
+++ b/src/main/resources/jitsi/excalidraw-config-service.yaml
@@ -7,7 +7,7 @@ metadata:
     app.kubernetes.io/name: excalidraw  
 spec:
   ports:
-  - name: excalidraw-backend
+  - name: excalidraw
     port: 3002
     targetPort: 80
   selector:

From b907485778590e37945fe8caad49eb88d50e1b62 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 12:56:37 +0100
Subject: [PATCH 24/33] web is no longer neded

---
 infrastructure/web/build.py                   |  57 --
 infrastructure/web/image/Dockerfile           |   6 -
 .../web/image/resources/install-debug.sh      |   3 -
 infrastructure/web/image/resources/install.sh |  17 -
 .../settings-config-stable-10008.orig         | 630 -----------------
 .../web/image/resources/settings-config.js    | 637 ------------------
 6 files changed, 1350 deletions(-)
 delete mode 100644 infrastructure/web/build.py
 delete mode 100644 infrastructure/web/image/Dockerfile
 delete mode 100644 infrastructure/web/image/resources/install-debug.sh
 delete mode 100755 infrastructure/web/image/resources/install.sh
 delete mode 100644 infrastructure/web/image/resources/settings-config-stable-10008.orig
 delete mode 100644 infrastructure/web/image/resources/settings-config.js

diff --git a/infrastructure/web/build.py b/infrastructure/web/build.py
deleted file mode 100644
index 7d3b2d5..0000000
--- a/infrastructure/web/build.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from os import environ
-from datetime import datetime
-from pybuilder.core import task, init
-from ddadevops import *
-
-name = "c4k-jitsi"
-MODULE = "web"
-PROJECT_ROOT_PATH = "../.."
-version = "2.2.1-dev"
-
-
-@init
-def initialize(project):
-    image_tag = version
-    if "dev" in image_tag:
-        image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
-
-    input = {
-        "name": name,
-        "module": MODULE,
-        "stage": "notused",
-        "project_root_path": PROJECT_ROOT_PATH,
-        "build_types": ["IMAGE"],
-        "mixin_types": [],
-        "image_naming": "NAME_AND_MODULE",
-        "image_tag": f"{image_tag}",
-    }
-
-    project.build_depends_on("ddadevops>=4.7.0")
-
-    build = DevopsImageBuild(project, input)
-    build.initialize_build_dir()
-
-
-@task
-def image(project):
-    build = get_devops_build(project)
-    build.image()
-
-
-@task
-def drun(project):
-    build = get_devops_build(project)
-    build.drun()
-
-
-@task
-def test(project):
-    build = get_devops_build(project)
-    build.test()
-
-
-@task
-def publish(project):
-    build = get_devops_build(project)
-    build.dockerhub_login()
-    build.dockerhub_publish()
diff --git a/infrastructure/web/image/Dockerfile b/infrastructure/web/image/Dockerfile
deleted file mode 100644
index 221f975..0000000
--- a/infrastructure/web/image/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-# IMPORTANT: In case of base image update, "./resources/settings-config.js" also has to be updated manually!
-FROM jitsi/web:stable-9646
-
-# Prepare Configuration
-ADD resources /tmp
-RUN /tmp/install.sh
diff --git a/infrastructure/web/image/resources/install-debug.sh b/infrastructure/web/image/resources/install-debug.sh
deleted file mode 100644
index a5b8ce8..0000000
--- a/infrastructure/web/image/resources/install-debug.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-
-apt update && apt -qqy install vim bash-completion less
diff --git a/infrastructure/web/image/resources/install.sh b/infrastructure/web/image/resources/install.sh
deleted file mode 100755
index 696a6be..0000000
--- a/infrastructure/web/image/resources/install.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -exo pipefail
-
-function main() {
-    {
-        upgradeSystem
-    } > /dev/null
-
-    install -m 0700 /tmp/install-debug.sh /usr/local/bin/
-    install -m 0644 /tmp/settings-config.js /defaults/settings-config.js
-
-    cleanupDocker
-}
-
-source /tmp/install_functions_debian.sh
-DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
\ No newline at end of file
diff --git a/infrastructure/web/image/resources/settings-config-stable-10008.orig b/infrastructure/web/image/resources/settings-config-stable-10008.orig
deleted file mode 100644
index da286f9..0000000
--- a/infrastructure/web/image/resources/settings-config-stable-10008.orig
+++ /dev/null
@@ -1,630 +0,0 @@
-{{ $ENABLE_ADAPTIVE_MODE := .Env.ENABLE_ADAPTIVE_MODE | default "true" | toBool -}}
-{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
-{{ $ENABLE_AUTOMATIC_GAIN_CONTROL := .Env.ENABLE_AUTOMATIC_GAIN_CONTROL | default "true" | toBool -}}
-{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
-{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
-{{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}}
-{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "true" | toBool -}}
-{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}}
-{{ $ENABLE_PREJOIN_PAGE := .Env.ENABLE_PREJOIN_PAGE | default "true" | toBool -}}
-{{ $ENABLE_WELCOME_PAGE := .Env.ENABLE_WELCOME_PAGE | default "true" | toBool -}}
-{{ $ENABLE_CLOSE_PAGE := .Env.ENABLE_CLOSE_PAGE | default "false" | toBool -}}
-{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}}
-{{ $ENABLE_SERVICE_RECORDING := .Env.ENABLE_SERVICE_RECORDING | default ($ENABLE_RECORDING | printf "%t") | toBool -}}
-{{ $ENABLE_LIVESTREAMING := .Env.ENABLE_LIVESTREAMING | default "false" | toBool -}}
-{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK := .Env.ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK | default "https://policies.google.com/privacy" -}}
-{{ $ENABLE_LIVESTREAMING_HELP_LINK := .Env.ENABLE_LIVESTREAMING_HELP_LINK | default "https://jitsi.org/live" -}}
-{{ $ENABLE_LIVESTREAMING_TERMS_LINK := .Env.ENABLE_LIVESTREAMING_TERMS_LINK | default "https://www.youtube.com/t/terms" -}}
-{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING := .Env.ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING | default "^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}" -}}
-{{ $ENABLE_REMB := .Env.ENABLE_REMB | default "true" | toBool -}}
-{{ $ENABLE_REQUIRE_DISPLAY_NAME := .Env.ENABLE_REQUIRE_DISPLAY_NAME | default "false" | toBool -}}
-{{ $ENABLE_SIMULCAST := .Env.ENABLE_SIMULCAST | default "true" | toBool -}}
-{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | default "false" | toBool -}}
-{{ $ENABLE_OPUS_RED := .Env.ENABLE_OPUS_RED | default "false" | toBool -}}
-{{ $ENABLE_TALK_WHILE_MUTED := .Env.ENABLE_TALK_WHILE_MUTED | default "false" | toBool -}}
-{{ $ENABLE_TCC := .Env.ENABLE_TCC | default "true" | toBool -}}
-{{ $ENABLE_TRANSCRIPTIONS := .Env.ENABLE_TRANSCRIPTIONS | default "false" | toBool -}}
-{{ $TRANSLATION_LANGUAGES := .Env.TRANSLATION_LANGUAGES | default "[]" -}}
-{{ $TRANSLATION_LANGUAGES_HEAD := .Env.TRANSLATION_LANGUAGES_HEAD | default "['en']" -}}
-{{ $USE_APP_LANGUAGE := .Env.USE_APP_LANGUAGE | default "true" | toBool -}}
-{{ $PREFERRED_LANGUAGE := .Env.PREFERRED_LANGUAGE | default "en-US" -}}
-{{ $DISABLE_START_FOR_ALL := .Env.DISABLE_START_FOR_ALL | default "false" | toBool -}}
-{{ $AUTO_CAPTION_ON_RECORD := .Env.AUTO_CAPTION_ON_RECORD | default "false" | toBool -}}
-{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }}
-{{ $HIDE_PREJOIN_DISPLAY_NAME := .Env.HIDE_PREJOIN_DISPLAY_NAME | default "false" | toBool -}}
-{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}}
-{{ $RESOLUTION := .Env.RESOLUTION | default "720" -}}
-{{ $RESOLUTION_MIN := .Env.RESOLUTION_MIN | default "180" -}}
-{{ $RESOLUTION_WIDTH := .Env.RESOLUTION_WIDTH | default "1280" -}}
-{{ $RESOLUTION_WIDTH_MIN := .Env.RESOLUTION_WIDTH_MIN | default "320" -}}
-{{ $START_AUDIO_ONLY := .Env.START_AUDIO_ONLY | default "false" | toBool -}}
-{{ $START_AUDIO_MUTED := .Env.START_AUDIO_MUTED | default 10 -}}
-{{ $START_WITH_AUDIO_MUTED := .Env.START_WITH_AUDIO_MUTED | default "false" | toBool -}}
-{{ $START_SILENT := .Env.START_SILENT | default "false" | toBool -}}
-{{ $DISABLE_AUDIO_LEVELS := .Env.DISABLE_AUDIO_LEVELS | default "false" | toBool -}}
-{{ $ENABLE_NOISY_MIC_DETECTION := .Env.ENABLE_NOISY_MIC_DETECTION | default "true" | toBool -}}
-{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}}
-{{ $START_WITH_VIDEO_MUTED := .Env.START_WITH_VIDEO_MUTED | default "false" | toBool -}}
-{{ $DESKTOP_SHARING_FRAMERATE_AUTO := .Env.DESKTOP_SHARING_FRAMERATE_AUTO | default "true" | toBool -}}
-{{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}}
-{{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}}
-{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
-{{ $XMPP_HIDDEN_DOMAIN := .Env.XMPP_HIDDEN_DOMAIN | default "hidden.meet.jitsi" -}}
-{{ $DISABLE_DEEP_LINKING  := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}}
-{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
-{{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}}
-{{ $DISABLE_REMOTE_VIDEO_MENU := .Env.DISABLE_REMOTE_VIDEO_MENU | default "false" | toBool -}}
-{{ $DISABLE_PRIVATE_CHAT:= .Env.DISABLE_PRIVATE_CHAT | default "false" | toBool -}}
-{{ $DISABLE_KICKOUT := .Env.DISABLE_KICKOUT | default "false" | toBool -}}
-{{ $DISABLE_GRANT_MODERATOR := .Env.DISABLE_GRANT_MODERATOR | default "false" | toBool -}}
-{{ $ENABLE_E2EPING := .Env.ENABLE_E2EPING | default "false" | toBool -}}
-{{ $DISABLE_LOCAL_RECORDING := .Env.DISABLE_LOCAL_RECORDING | default "false" | toBool -}}
-{{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT := .Env.ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT | default "false" | toBool -}}
-{{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}}
-{{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}}
-{{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}}
-{{ $WHITEBOARD_ENABLED := or (.Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" | toBool) (.Env.WHITEBOARD_COLLAB_SERVER_URL_BASE | default "" | toBool) }}
-{{ $CODEC_ORDER_JVB := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
-{{ $CODEC_ORDER_JVB_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
-{{ $CODEC_ORDER_P2P := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
-{{ $CODEC_ORDER_P2P_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
-
-// Video configuration.
-//
-
-config.resolution = {{ $RESOLUTION }};
-config.constraints = {
-    video: {
-        height: { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} },
-        width: { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}},
-    }
-};
-
-{{ if not $ENABLE_SIMULCAST -}}
-config.disableSimulcast = true;
-{{ end -}}
-config.startVideoMuted = {{ $START_VIDEO_MUTED }};
-config.startWithVideoMuted = {{ $START_WITH_VIDEO_MUTED }};
-
-config.flags = {
-    sourceNameSignaling: true,
-    sendMultipleVideoStreams: true,
-    receiveMultipleVideoStreams: true
-};
-
-// ScreenShare Configuration.
-//
-
-{{ if not $DESKTOP_SHARING_FRAMERATE_AUTO -}}
-config.desktopSharingFrameRate = {
-    min: {{ $DESKTOP_SHARING_FRAMERATE_MIN }},
-    max: {{ $DESKTOP_SHARING_FRAMERATE_MAX }}
-};
-{{ end -}}
-
-// Audio configuration.
-//
-
-config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
-config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
-config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
-config.disableAGC = {{ not $ENABLE_AUTOMATIC_GAIN_CONTROL }};
-
-config.audioQuality = {
-    stereo: {{ $ENABLE_STEREO }}
-};
-
-{{ if .Env.AUDIO_QUALITY_OPUS_BITRATE -}}
-config.audioQuality.opusMaxAverageBitrate = '{{ .Env.AUDIO_QUALITY_OPUS_BITRATE }}';
-{{ end -}}
-
-config.startAudioOnly = {{ $START_AUDIO_ONLY }};
-config.startAudioMuted = {{ $START_AUDIO_MUTED }};
-config.startWithAudioMuted = {{ $START_WITH_AUDIO_MUTED }};
-config.startSilent = {{ $START_SILENT }};
-config.enableOpusRed = {{ $ENABLE_OPUS_RED }};
-config.disableAudioLevels = {{ $DISABLE_AUDIO_LEVELS }};
-config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }};
-
-
-// Peer-to-Peer options.
-//
-
-config.p2p = {
-    enabled: {{ $ENABLE_P2P }},
-    codecPreferenceOrder: {{ $CODEC_ORDER_P2P }},
-    mobileCodecPreferenceOrder: {{ $CODEC_ORDER_P2P_MOBILE }}
-};
-
-{{ if .Env.P2P_STUN_SERVERS -}}
-config.p2p.stunServers = '{{ .Env.P2P_STUN_SERVERS }}'.split(',').map(url => ({ urls: 'stun:' + url }));
-
-{{ end -}}
-
-// Breakout Rooms
-//
-
-config.hideAddRoomButton = {{ $ENABLE_BREAKOUT_ROOMS | not }};
-
-
-// Etherpad
-//
-
-{{ if .Env.ETHERPAD_PUBLIC_URL -}}
-config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}';
-{{ else if .Env.ETHERPAD_URL_BASE -}}
-config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/';
-{{ end -}}
-
-
-// Recording.
-//
-
-{{ if or $ENABLE_RECORDING $ENABLE_TRANSCRIPTIONS  -}}
-
-config.hiddenDomain = '{{ $XMPP_HIDDEN_DOMAIN }}';
-{{ end -}}
-
-{{ if $ENABLE_RECORDING -}}
-
-config.recordingService = {
-    // Whether to enable file recording or not using the "service" defined by the finalizer in Jibri
-    enabled: {{ $ENABLE_SERVICE_RECORDING }},
-
-    // Whether to show the possibility to share file recording with other people
-    // (e.g. meeting participants), based on the actual implementation
-    // on the backend.
-    sharingEnabled: {{ $ENABLE_FILE_RECORDING_SHARING }}
-};
-
-// Live streaming configuration.
-config.liveStreaming = {
-    enabled: {{ $ENABLE_LIVESTREAMING }},
-    dataPrivacyLink: '{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK }}',
-    helpLink: '{{ $ENABLE_LIVESTREAMING_HELP_LINK }}',
-    termsLink: '{{ $ENABLE_LIVESTREAMING_TERMS_LINK }}',
-    validatorRegExpString: '{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING }}'
-};
-
-
-{{ if .Env.DROPBOX_APPKEY -}}
-// Enable the dropbox integration.
-config.dropbox = {
-    appKey: '{{ .Env.DROPBOX_APPKEY }}'
-};
-
-{{ if .Env.DROPBOX_REDIRECT_URI -}}
-// A URL to redirect the user to, after authenticating
-// by default uses:
-// 'https://jitsi-meet.example.com/static/oauth.html'
-config.dropbox.redirectURI = '{{ .Env.DROPBOX_REDIRECT_URI }}';
-{{ end -}}
-{{ end -}}
-
-{{ end -}}
-
-// Local recording configuration.
-config.localRecording = {
-    disable: {{ $DISABLE_LOCAL_RECORDING }},
-    notifyAllParticipants: {{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT }},
-    disableSelfRecording: {{ $ENABLE_LOCAL_RECORDING_SELF_START }}
-};
-
-
-// Analytics.
-//
-
-config.analytics = {};
-
-{{ if .Env.AMPLITUDE_ID -}}
-// The Amplitude APP Key:
-config.analytics.amplitudeAPPKey = '{{ .Env.AMPLITUDE_ID }}';
-{{ end -}}
-
-{{ if .Env.GOOGLE_ANALYTICS_ID -}}
-// The Google Analytics Tracking ID:
-config.analytics.googleAnalyticsTrackingId = '{{ .Env.GOOGLE_ANALYTICS_ID }}';
-{{ end -}}
-
-{{ if .Env.MATOMO_ENDPOINT -}}
-// Matomo endpoint:
-config.analytics.matomoEndpoint = '{{ .Env.MATOMO_ENDPOINT }}';
-{{ end -}}
-
-{{ if .Env.MATOMO_SITE_ID -}}
-// Matomo site ID:
-config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}';
-{{ end -}}
-
-{{ if .Env.ANALYTICS_SCRIPT_URLS -}}
-// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
-config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS | compact) }}' ];
-{{ end -}}
-
-{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
-config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS | compact) }}' ];
-{{ end -}}
-
-
-// Dial in/out services.
-//
-
-{{ if $ENABLE_JAAS_COMPONENTS }}
-config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';
-config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';
-{{ else }}
-{{ if .Env.CONFCODE_URL -}}
-config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}';
-{{ end -}}
-{{ if .Env.DIALIN_NUMBERS_URL -}}
-config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}';
-{{ end -}}
-{{ end -}}
-
-{{ if .Env.DIALOUT_AUTH_URL -}}
-config.dialOutAuthUrl = '{{ .Env.DIALOUT_AUTH_URL }}';
-{{ end -}}
-
-{{ if .Env.DIALOUT_CODES_URL -}}
-config.dialOutCodesUrl = '{{ .Env.DIALOUT_CODES_URL }}';
-{{ end -}}
-
-
-// Calendar service integration.
-//
-
-config.enableCalendarIntegration = {{ $ENABLE_CALENDAR }};
-
-{{ if .Env.GOOGLE_API_APP_CLIENT_ID -}}
-config.googleApiApplicationClientID = '{{ .Env.GOOGLE_API_APP_CLIENT_ID }}';
-{{ end -}}
-
-{{ if .Env.MICROSOFT_API_APP_CLIENT_ID -}}
-config.microsoftApiApplicationClientID = '{{ .Env.MICROSOFT_API_APP_CLIENT_ID }}';
-{{ end -}}
-
-
-// Invitation service.
-//
-
-{{ if .Env.INVITE_SERVICE_URL -}}
-config.inviteServiceUrl = '{{ .Env.INVITE_SERVICE_URL }}';
-{{ end -}}
-
-{{ if .Env.PEOPLE_SEARCH_URL -}}
-config.peopleSearchUrl = '{{ .Env.PEOPLE_SEARCH_URL }}';
-config.peopleSearchQueryTypes = ['user','conferenceRooms'];
-{{ end -}}
-
-
-// Miscellaneous.
-//
-
-// Prejoin page.
-config.prejoinConfig = {
-    enabled: {{ $ENABLE_PREJOIN_PAGE }},
-
-    // Hides the participant name editing field in the prejoin screen.
-    hideDisplayName: {{ $HIDE_PREJOIN_DISPLAY_NAME }}
-};
-
-// List of buttons to hide from the extra join options dropdown on prejoin screen.
-{{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}}
-config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Welcome page.
-config.welcomePage = {
-    disabled: {{ not $ENABLE_WELCOME_PAGE }}
-};
-
-// Close page.
-config.enableClosePage = {{ $ENABLE_CLOSE_PAGE }};
-
-// Default language.
-{{ if .Env.DEFAULT_LANGUAGE -}}
-config.defaultLanguage = '{{ .Env.DEFAULT_LANGUAGE }}';
-{{ end -}}
-
-// Require users to always specify a display name.
-config.requireDisplayName = {{ $ENABLE_REQUIRE_DISPLAY_NAME }};
-
-// Chrome extension banner.
-{{ if .Env.CHROME_EXTENSION_BANNER_JSON -}}
-config.chromeExtensionBanner = {{ .Env.CHROME_EXTENSION_BANNER_JSON }};
-{{ end -}}
-
-// Disables profile and the edit of all fields from the profile settings (display name and email)
-config.disableProfile = {{ $DISABLE_PROFILE }};
-
-// Room password (false for anything, number for max digits)
-{{ if $ENABLE_JAAS_COMPONENTS -}}
-config.roomPasswordNumberOfDigits = 10;
-{{ else -}}
-config.roomPasswordNumberOfDigits = {{ $ROOM_PASSWORD_DIGITS }};
-{{ end -}}
-
-// Advanced.
-//
-
-{{ if not $ENABLE_REMB -}}
-config.enableRemb = false;
-{{ end -}}
-{{ if not $ENABLE_TCC -}}
-config.enableTcc = false;
-{{ end -}}
-
-
-// Transcriptions (subtitles and buttons can be configured in interface_config)
-config.transcription = {
-    enabled: {{ $ENABLE_TRANSCRIPTIONS }},
-    translationLanguages: {{ $TRANSLATION_LANGUAGES }},
-    translationLanguagesHead: {{ $TRANSLATION_LANGUAGES_HEAD }},
-    useAppLanguage: {{ $USE_APP_LANGUAGE }},
-    preferredLanguage: '{{ $PREFERRED_LANGUAGE }}',
-    disableStartForAll: {{ $DISABLE_START_FOR_ALL }},
-    autoCaptionOnRecord: {{ $AUTO_CAPTION_ON_RECORD }},
-};
-
-// Dynamic branding
-{{ if .Env.DYNAMIC_BRANDING_URL -}}
-// External API url used to receive branding specific information.
-config.dynamicBrandingUrl = '{{ .Env.DYNAMIC_BRANDING_URL }}';
-{{ else if .Env.BRANDING_DATA_URL  -}}
-config.brandingDataUrl = '{{ .Env.BRANDING_DATA_URL }}';
-{{ end -}}
-
-{{ if .Env.TOKEN_AUTH_URL -}}
-// Authenticate using external service
-config.tokenAuthUrl = '{{ .Env.TOKEN_AUTH_URL }}';
-{{ end -}}
-
-
-// Deployment information.
-//
-
-config.deploymentInfo = {};
-
-{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}}
-config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_SHARD -}}
-config.deploymentInfo.shard = '{{ .Env.DEPLOYMENTINFO_SHARD }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}}
-config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_REGION -}}
-config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}';
-{{ end -}}
-
-// Deep Linking
-config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }};
-
-// P2P preferred codec
-{{ if .Env.P2P_PREFERRED_CODEC -}}
-config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}';
-{{ end -}}
-
-// Video quality settings.
-//
-
-config.videoQuality = {};
-config.videoQuality.codecPreferenceOrder = {{ $CODEC_ORDER_JVB }};
-config.videoQuality.mobileCodecPreferenceOrder = {{ $CODEC_ORDER_JVB_MOBILE }};
-config.videoQuality.enableAdaptiveMode = {{ $ENABLE_ADAPTIVE_MODE }};
-
-{{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}}
-config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}';
-{{ end -}}
-
-config.videoQuality.av1 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_LOW }}
-config.videoQuality.av1.low = {{ .Env.VIDEOQUALITY_BITRATE_AV1_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }}
-config.videoQuality.av1.standard = {{ .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }}
-config.videoQuality.av1.high = {{ .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_FULL }}
-config.videoQuality.av1.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }}
-config.videoQuality.av1.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }}
-config.videoQuality.av1.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.h264 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_LOW }}
-config.videoQuality.h264.low = {{ .Env.VIDEOQUALITY_BITRATE_H264_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }}
-config.videoQuality.h264.standard = {{ .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_HIGH }}
-config.videoQuality.h264.high = {{ .Env.VIDEOQUALITY_BITRATE_H264_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_FULL }}
-config.videoQuality.h264.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }}
-config.videoQuality.h264.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }}
-config.videoQuality.h264.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.vp8 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_LOW }}
-config.videoQuality.vp8.low = {{ .Env.VIDEOQUALITY_BITRATE_VP8_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }}
-config.videoQuality.vp8.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }}
-config.videoQuality.vp8.high = {{ .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_FULL }}
-config.videoQuality.vp8.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }}
-config.videoQuality.vp8.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }}
-config.videoQuality.vp8.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.vp9 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_LOW }}
-config.videoQuality.vp9.low = {{ .Env.VIDEOQUALITY_BITRATE_VP9_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }}
-config.videoQuality.vp9.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }}
-config.videoQuality.vp9.high = {{ .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_FULL }}
-config.videoQuality.vp9.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }}
-config.videoQuality.vp9.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }}
-config.videoQuality.vp9.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }};
-{{ end -}}
-
- // Reactions
-config.disableReactions = {{ $DISABLE_REACTIONS }};
-
-// Polls
-config.disablePolls = {{ $DISABLE_POLLS }};
-
-// Configure toolbar buttons
-{{ if .Env.TOOLBAR_BUTTONS -}}
-config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Hides the buttons at pre-join screen
-{{ if .Env.HIDE_PREMEETING_BUTTONS -}}
-config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Configure remote participant video menu
-config.remoteVideoMenu = {
-    disabled: {{ $DISABLE_REMOTE_VIDEO_MENU }},
-    disableKick: {{ $DISABLE_KICKOUT }},
-    disableGrantModerator: {{ $DISABLE_GRANT_MODERATOR }},
-    disablePrivateChat: {{ $DISABLE_PRIVATE_CHAT }}
-};
-
-// Configure e2eping
-config.e2eping = {
-    enabled: {{ $ENABLE_E2EPING }}
-};
-
-{{ if .Env.E2EPING_NUM_REQUESTS -}}
-config.e2eping.numRequests = {{ .Env.E2EPING_NUM_REQUESTS }};
-{{ end -}}
-{{ if .Env.E2EPING_MAX_CONFERENCE_SIZE -}}
-config.e2eping.maxConferenceSize = {{ .Env.E2EPING_MAX_CONFERENCE_SIZE }};
-{{ end -}}
-{{ if .Env.E2EPING_MAX_MESSAGE_PER_SECOND -}}
-config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }};
-{{ end }}
-
-// Settings for the Excalidraw whiteboard integration.
-config.whiteboard = {
-    enabled: {{ $WHITEBOARD_ENABLED }},
-{{ if .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL -}}
-    collabServerBaseUrl: '{{ .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
-{{ else if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE -}}
-    collabServerBaseUrl: '{{ $PUBLIC_URL }}'
-{{ end -}}
-};
-
-// JaaS support: pre-configure image if JAAS_APP_ID was set.
-{{ if .Env.JAAS_APP_ID -}}
-{{ $JAAS_USE_STAGING := .Env.JAAS_USE_STAGING | default "false" | toBool -}}
-{{ $JAAS_DOMAIN := $JAAS_USE_STAGING | ternary "stage.8x8.vc" "8x8.vc" -}}
-
-config.hosts.domain = '{{ $JAAS_DOMAIN }}';
-config.hosts.muc = 'conference.{{ .Env.JAAS_APP_ID }}.{{ $JAAS_DOMAIN }}';
-config.hosts.focus = 'focus.{{ $JAAS_DOMAIN }}';
-
-config.analytics.rtcstatsEnabled = true;
-config.analytics.rtcstatsStoreLogs = true;
-config.analytics.rtcstatsUseLegacy = false;
-config.analytics.rtcstatsEndpoint = 'wss://rtcstats-server-8x8.jitsi.net/';
-config.analytics.rtcstatsPollInterval = 10000;
-config.analytics.rtcstatsSendSdp = true;
-
-config.bosh = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/http-bind';
-config.websocket = 'wss://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/xmpp-websocket';
-config.websocketKeepAliveUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/_unlock';
-config.conferenceRequestUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/conference-request/v1';
-
-config.hiddenDomain = 'recorder.{{ $JAAS_DOMAIN }}';
-config.hiddenFromRecorderFeatureEnabled = true;
-config.enableEmailInStats = true;
-
-config.jaasActuatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-actuator';
-config.jaasTokenUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/token-mapping';
-config.jaasConferenceCreatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access/conference-creator';
-config.webhookProxyUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy';
-config.billingCounterUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/billing-counter/v1/connection';
-config.brandingDataUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/branding/public/v1/conferences';
-config.dialInNumbersUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/access/v1/dids';
-config.dialInConfCodeUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access';
-config.dialOutAuthUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/phone-authorize';
-config.dialOutRegionUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/customer-configs/v1/outbound-destination';
-config.peopleSearchUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/directory/search';
-config.inviteServiceUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/meeting/invite';
-config.recordingSharingUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-recordings/link';
-config.peopleSearchQueryTypes = ['user','conferenceRooms'];
-config.sipInviteUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/sip-jibri-gateway/jibris/invite';
-config.jaasFeedbackMetadataURL = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy/feedback';
-
-{{ if $JAAS_USE_STAGING -}}
-config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend-pilot.cloudflare.jitsi.net';
-{{ else -}}
-config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend.cloudflare.jitsi.net';
-{{ end -}}
-config.whiteboard.userLimit = 25;
-{{ end -}}
-
-// Testing
-config.testing = {
-    enableCodecSelectionAPI: true
-};
diff --git a/infrastructure/web/image/resources/settings-config.js b/infrastructure/web/image/resources/settings-config.js
deleted file mode 100644
index 3334b24..0000000
--- a/infrastructure/web/image/resources/settings-config.js
+++ /dev/null
@@ -1,637 +0,0 @@
-//https://github.com/jitsi/docker-jitsi-meet/blob/master/web/rootfs/defaults/settings-config.js
-
-{{ $ENABLE_ADAPTIVE_MODE := .Env.ENABLE_ADAPTIVE_MODE | default "true" | toBool -}}
-{{ $ENABLE_AUDIO_PROCESSING := .Env.ENABLE_AUDIO_PROCESSING | default "true" | toBool -}}
-{{ $ENABLE_AUTOMATIC_GAIN_CONTROL := .Env.ENABLE_AUTOMATIC_GAIN_CONTROL | default "true" | toBool -}}
-{{ $ENABLE_BREAKOUT_ROOMS := .Env.ENABLE_BREAKOUT_ROOMS | default "true" | toBool -}}
-{{ $ENABLE_CALENDAR := .Env.ENABLE_CALENDAR | default "false" | toBool -}}
-{{ $ENABLE_FILE_RECORDING_SHARING := .Env.ENABLE_FILE_RECORDING_SHARING | default "false" | toBool -}}
-{{ $ENABLE_NO_AUDIO_DETECTION := .Env.ENABLE_NO_AUDIO_DETECTION | default "true" | toBool -}}
-{{ $ENABLE_P2P := .Env.ENABLE_P2P | default "true" | toBool -}}
-{{ $ENABLE_PREJOIN_PAGE := .Env.ENABLE_PREJOIN_PAGE | default "true" | toBool -}}
-{{ $ENABLE_WELCOME_PAGE := .Env.ENABLE_WELCOME_PAGE | default "true" | toBool -}}
-{{ $ENABLE_CLOSE_PAGE := .Env.ENABLE_CLOSE_PAGE | default "false" | toBool -}}
-{{ $ENABLE_RECORDING := .Env.ENABLE_RECORDING | default "false" | toBool -}}
-{{ $ENABLE_SERVICE_RECORDING := .Env.ENABLE_SERVICE_RECORDING | default ($ENABLE_RECORDING | printf "%t") | toBool -}}
-{{ $ENABLE_LIVESTREAMING := .Env.ENABLE_LIVESTREAMING | default "false" | toBool -}}
-{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK := .Env.ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK | default "https://policies.google.com/privacy" -}}
-{{ $ENABLE_LIVESTREAMING_HELP_LINK := .Env.ENABLE_LIVESTREAMING_HELP_LINK | default "https://jitsi.org/live" -}}
-{{ $ENABLE_LIVESTREAMING_TERMS_LINK := .Env.ENABLE_LIVESTREAMING_TERMS_LINK | default "https://www.youtube.com/t/terms" -}}
-{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING := .Env.ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING | default "^(?:[a-zA-Z0-9]{4}(?:-(?!$)|$)){4}" -}}
-{{ $ENABLE_REMB := .Env.ENABLE_REMB | default "true" | toBool -}}
-{{ $ENABLE_REQUIRE_DISPLAY_NAME := .Env.ENABLE_REQUIRE_DISPLAY_NAME | default "false" | toBool -}}
-{{ $ENABLE_SIMULCAST := .Env.ENABLE_SIMULCAST | default "true" | toBool -}}
-{{ $ENABLE_STEREO := .Env.ENABLE_STEREO | default "false" | toBool -}}
-{{ $ENABLE_OPUS_RED := .Env.ENABLE_OPUS_RED | default "false" | toBool -}}
-{{ $ENABLE_TALK_WHILE_MUTED := .Env.ENABLE_TALK_WHILE_MUTED | default "false" | toBool -}}
-{{ $ENABLE_TCC := .Env.ENABLE_TCC | default "true" | toBool -}}
-{{ $ENABLE_TRANSCRIPTIONS := .Env.ENABLE_TRANSCRIPTIONS | default "false" | toBool -}}
-{{ $TRANSLATION_LANGUAGES := .Env.TRANSLATION_LANGUAGES | default "[]" -}}
-{{ $TRANSLATION_LANGUAGES_HEAD := .Env.TRANSLATION_LANGUAGES_HEAD | default "['en']" -}}
-{{ $USE_APP_LANGUAGE := .Env.USE_APP_LANGUAGE | default "true" | toBool -}}
-{{ $PREFERRED_LANGUAGE := .Env.PREFERRED_LANGUAGE | default "en-US" -}}
-{{ $DISABLE_START_FOR_ALL := .Env.DISABLE_START_FOR_ALL | default "false" | toBool -}}
-{{ $AUTO_CAPTION_ON_RECORD := .Env.AUTO_CAPTION_ON_RECORD | default "false" | toBool -}}
-{{ $ENABLE_JAAS_COMPONENTS := .Env.ENABLE_JAAS_COMPONENTS | default "0" | toBool }}
-{{ $HIDE_PREJOIN_DISPLAY_NAME := .Env.HIDE_PREJOIN_DISPLAY_NAME | default "false" | toBool -}}
-{{ $PUBLIC_URL := .Env.PUBLIC_URL | default "https://localhost:8443" -}}
-{{ $RESOLUTION := .Env.RESOLUTION | default "720" -}}
-{{ $RESOLUTION_MIN := .Env.RESOLUTION_MIN | default "180" -}}
-{{ $RESOLUTION_WIDTH := .Env.RESOLUTION_WIDTH | default "1280" -}}
-{{ $RESOLUTION_WIDTH_MIN := .Env.RESOLUTION_WIDTH_MIN | default "320" -}}
-{{ $START_AUDIO_ONLY := .Env.START_AUDIO_ONLY | default "false" | toBool -}}
-{{ $START_AUDIO_MUTED := .Env.START_AUDIO_MUTED | default 10 -}}
-{{ $START_WITH_AUDIO_MUTED := .Env.START_WITH_AUDIO_MUTED | default "false" | toBool -}}
-{{ $START_SILENT := .Env.START_SILENT | default "false" | toBool -}}
-{{ $DISABLE_AUDIO_LEVELS := .Env.DISABLE_AUDIO_LEVELS | default "false" | toBool -}}
-{{ $ENABLE_NOISY_MIC_DETECTION := .Env.ENABLE_NOISY_MIC_DETECTION | default "true" | toBool -}}
-{{ $START_VIDEO_MUTED := .Env.START_VIDEO_MUTED | default 10 -}}
-{{ $START_WITH_VIDEO_MUTED := .Env.START_WITH_VIDEO_MUTED | default "false" | toBool -}}
-{{ $DESKTOP_SHARING_FRAMERATE_AUTO := .Env.DESKTOP_SHARING_FRAMERATE_AUTO | default "true" | toBool -}}
-{{ $DESKTOP_SHARING_FRAMERATE_MIN := .Env.DESKTOP_SHARING_FRAMERATE_MIN | default 5 -}}
-{{ $DESKTOP_SHARING_FRAMERATE_MAX := .Env.DESKTOP_SHARING_FRAMERATE_MAX | default 5 -}}
-{{ $XMPP_DOMAIN := .Env.XMPP_DOMAIN | default "meet.jitsi" -}}
-{{ $XMPP_HIDDEN_DOMAIN := .Env.XMPP_HIDDEN_DOMAIN | default "hidden.meet.jitsi" -}}
-{{ $DISABLE_DEEP_LINKING  := .Env.DISABLE_DEEP_LINKING | default "false" | toBool -}}
-{{ $DISABLE_POLLS := .Env.DISABLE_POLLS | default "false" | toBool -}}
-{{ $DISABLE_REACTIONS := .Env.DISABLE_REACTIONS | default "false" | toBool -}}
-{{ $DISABLE_REMOTE_VIDEO_MENU := .Env.DISABLE_REMOTE_VIDEO_MENU | default "false" | toBool -}}
-{{ $DISABLE_PRIVATE_CHAT:= .Env.DISABLE_PRIVATE_CHAT | default "false" | toBool -}}
-{{ $DISABLE_KICKOUT := .Env.DISABLE_KICKOUT | default "false" | toBool -}}
-{{ $DISABLE_GRANT_MODERATOR := .Env.DISABLE_GRANT_MODERATOR | default "false" | toBool -}}
-{{ $ENABLE_E2EPING := .Env.ENABLE_E2EPING | default "false" | toBool -}}
-{{ $DISABLE_LOCAL_RECORDING := .Env.DISABLE_LOCAL_RECORDING | default "false" | toBool -}}
-{{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT := .Env.ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT | default "false" | toBool -}}
-{{ $ENABLE_LOCAL_RECORDING_SELF_START := .Env.ENABLE_LOCAL_RECORDING_SELF_START | default "false" | toBool -}}
-{{ $DISABLE_PROFILE := .Env.DISABLE_PROFILE | default "false" | toBool -}}
-{{ $ROOM_PASSWORD_DIGITS := .Env.ROOM_PASSWORD_DIGITS | default "false" -}}
-{{ $WHITEBOARD_ENABLED := or (.Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL | default "" | toBool) (.Env.WHITEBOARD_COLLAB_SERVER_URL_BASE | default "" | toBool) }}
-{{ $CODEC_ORDER_JVB := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
-{{ $CODEC_ORDER_JVB_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
-{{ $CODEC_ORDER_P2P := .Env.CODEC_ORDER_JVB | default "[\"AV1\", \"VP9\", \"VP8\", \"H264\"]" -}}
-{{ $CODEC_ORDER_P2P_MOBILE := .Env.CODEC_ORDER_JVB_MOBILE | default "[\"VP8\", \"VP9\", \"H264\", \"AV1\"]" -}}
-
-// Video configuration.
-//
-
-config.resolution = {{ $RESOLUTION }};
-config.constraints = {
-    video: {
-        height: { ideal: {{ $RESOLUTION }}, max: {{ $RESOLUTION }}, min: {{ $RESOLUTION_MIN }} },
-        width: { ideal: {{ $RESOLUTION_WIDTH }}, max: {{ $RESOLUTION_WIDTH }}, min: {{ $RESOLUTION_WIDTH_MIN }}},
-    }
-};
-
-{{ if not $ENABLE_SIMULCAST -}}
-config.disableSimulcast = true;
-{{ end -}}
-config.startVideoMuted = {{ $START_VIDEO_MUTED }};
-config.startWithVideoMuted = {{ $START_WITH_VIDEO_MUTED }};
-
-config.flags = {
-    sourceNameSignaling: true,
-    sendMultipleVideoStreams: true,
-    receiveMultipleVideoStreams: true
-};
-
-// ScreenShare Configuration.
-//
-
-{{ if not $DESKTOP_SHARING_FRAMERATE_AUTO -}}
-config.desktopSharingFrameRate = {
-    min: {{ $DESKTOP_SHARING_FRAMERATE_MIN }},
-    max: {{ $DESKTOP_SHARING_FRAMERATE_MAX }}
-};
-{{ end -}}
-
-// Audio configuration.
-//
-
-config.enableNoAudioDetection = {{ $ENABLE_NO_AUDIO_DETECTION }};
-config.enableTalkWhileMuted = {{ $ENABLE_TALK_WHILE_MUTED }};
-config.disableAP = {{ not $ENABLE_AUDIO_PROCESSING }};
-config.disableAGC = {{ not $ENABLE_AUTOMATIC_GAIN_CONTROL }};
-
-config.audioQuality = {
-    stereo: {{ $ENABLE_STEREO }}
-};
-
-{{ if .Env.AUDIO_QUALITY_OPUS_BITRATE -}}
-config.audioQuality.opusMaxAverageBitrate = '{{ .Env.AUDIO_QUALITY_OPUS_BITRATE }}';
-{{ end -}}
-
-config.startAudioOnly = {{ $START_AUDIO_ONLY }};
-config.startAudioMuted = {{ $START_AUDIO_MUTED }};
-config.startWithAudioMuted = {{ $START_WITH_AUDIO_MUTED }};
-config.startSilent = {{ $START_SILENT }};
-config.enableOpusRed = {{ $ENABLE_OPUS_RED }};
-config.disableAudioLevels = {{ $DISABLE_AUDIO_LEVELS }};
-config.enableNoisyMicDetection = {{ $ENABLE_NOISY_MIC_DETECTION }};
-
-
-// Peer-to-Peer options.
-//
-
-config.p2p = {
-    enabled: {{ $ENABLE_P2P }},
-    codecPreferenceOrder: {{ $CODEC_ORDER_P2P }},
-    mobileCodecPreferenceOrder: {{ $CODEC_ORDER_P2P_MOBILE }}
-};
-
-{{ if .Env.P2P_STUN_SERVERS -}}
-config.p2p.stunServers = '{{ .Env.P2P_STUN_SERVERS }}'.split(',').map(url => ({ urls: 'stun:' + url }));
-
-{{ end -}}
-
-// Breakout Rooms
-//
-
-config.hideAddRoomButton = {{ $ENABLE_BREAKOUT_ROOMS | not }};
-
-
-// Etherpad
-//
-
-{{ if .Env.ETHERPAD_PUBLIC_URL -}}
-config.etherpad_base = '{{ .Env.ETHERPAD_PUBLIC_URL }}';
-{{ else if .Env.ETHERPAD_URL_BASE -}}
-config.etherpad_base = '{{ $PUBLIC_URL }}/etherpad/p/';
-{{ end -}}
-
-
-// Recording.
-//
-
-{{ if or $ENABLE_RECORDING $ENABLE_TRANSCRIPTIONS  -}}
-
-config.hiddenDomain = '{{ $XMPP_HIDDEN_DOMAIN }}';
-{{ end -}}
-
-{{ if $ENABLE_RECORDING -}}
-
-config.recordingService = {
-    // Whether to enable file recording or not using the "service" defined by the finalizer in Jibri
-    enabled: {{ $ENABLE_SERVICE_RECORDING }},
-
-    // Whether to show the possibility to share file recording with other people
-    // (e.g. meeting participants), based on the actual implementation
-    // on the backend.
-    sharingEnabled: {{ $ENABLE_FILE_RECORDING_SHARING }}
-};
-
-// Live streaming configuration.
-config.liveStreaming = {
-    enabled: {{ $ENABLE_LIVESTREAMING }},
-    dataPrivacyLink: '{{ $ENABLE_LIVESTREAMING_DATA_PRIVACY_LINK }}',
-    helpLink: '{{ $ENABLE_LIVESTREAMING_HELP_LINK }}',
-    termsLink: '{{ $ENABLE_LIVESTREAMING_TERMS_LINK }}',
-    validatorRegExpString: '{{ $ENABLE_LIVESTREAMING_VALIDATOR_REGEXP_STRING }}'
-};
-
-
-{{ if .Env.DROPBOX_APPKEY -}}
-// Enable the dropbox integration.
-config.dropbox = {
-    appKey: '{{ .Env.DROPBOX_APPKEY }}'
-};
-
-{{ if .Env.DROPBOX_REDIRECT_URI -}}
-// A URL to redirect the user to, after authenticating
-// by default uses:
-// 'https://jitsi-meet.example.com/static/oauth.html'
-config.dropbox.redirectURI = '{{ .Env.DROPBOX_REDIRECT_URI }}';
-{{ end -}}
-{{ end -}}
-
-{{ end -}}
-
-// Local recording configuration.
-config.localRecording = {
-    disable: {{ $DISABLE_LOCAL_RECORDING }},
-    notifyAllParticipants: {{ $ENABLE_LOCAL_RECORDING_NOTIFY_ALL_PARTICIPANT }},
-    disableSelfRecording: {{ $ENABLE_LOCAL_RECORDING_SELF_START }}
-};
-
-
-// Analytics.
-//
-
-config.analytics = {};
-
-{{ if .Env.AMPLITUDE_ID -}}
-// The Amplitude APP Key:
-config.analytics.amplitudeAPPKey = '{{ .Env.AMPLITUDE_ID }}';
-{{ end -}}
-
-{{ if .Env.GOOGLE_ANALYTICS_ID -}}
-// The Google Analytics Tracking ID:
-config.analytics.googleAnalyticsTrackingId = '{{ .Env.GOOGLE_ANALYTICS_ID }}';
-{{ end -}}
-
-{{ if .Env.MATOMO_ENDPOINT -}}
-// Matomo endpoint:
-config.analytics.matomoEndpoint = '{{ .Env.MATOMO_ENDPOINT }}';
-{{ end -}}
-
-{{ if .Env.MATOMO_SITE_ID -}}
-// Matomo site ID:
-config.analytics.matomoSiteID = '{{ .Env.MATOMO_SITE_ID }}';
-{{ end -}}
-
-{{ if .Env.ANALYTICS_SCRIPT_URLS -}}
-// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
-config.analytics.scriptURLs = [ '{{ join "','" (splitList "," .Env.ANALYTICS_SCRIPT_URLS | compact) }}' ];
-{{ end -}}
-
-{{ if .Env.ANALYTICS_WHITELISTED_EVENTS -}}
-config.analytics.whiteListedEvents = [ '{{ join "','" (splitList "," .Env.ANALYTICS_WHITELISTED_EVENTS | compact) }}' ];
-{{ end -}}
-
-
-// Dial in/out services.
-//
-
-{{ if $ENABLE_JAAS_COMPONENTS }}
-config.dialInConfCodeUrl = 'https://conference-mapper.jitsi.net/v1/access';
-config.dialInNumbersUrl = 'https://conference-mapper.jitsi.net/v1/access/dids';
-{{ else }}
-{{ if .Env.CONFCODE_URL -}}
-config.dialInConfCodeUrl = '{{ .Env.CONFCODE_URL }}';
-{{ end -}}
-{{ if .Env.DIALIN_NUMBERS_URL -}}
-config.dialInNumbersUrl = '{{ .Env.DIALIN_NUMBERS_URL }}';
-{{ end -}}
-{{ end -}}
-
-{{ if .Env.DIALOUT_AUTH_URL -}}
-config.dialOutAuthUrl = '{{ .Env.DIALOUT_AUTH_URL }}';
-{{ end -}}
-
-{{ if .Env.DIALOUT_CODES_URL -}}
-config.dialOutCodesUrl = '{{ .Env.DIALOUT_CODES_URL }}';
-{{ end -}}
-
-
-// Calendar service integration.
-//
-
-config.enableCalendarIntegration = {{ $ENABLE_CALENDAR }};
-
-{{ if .Env.GOOGLE_API_APP_CLIENT_ID -}}
-config.googleApiApplicationClientID = '{{ .Env.GOOGLE_API_APP_CLIENT_ID }}';
-{{ end -}}
-
-{{ if .Env.MICROSOFT_API_APP_CLIENT_ID -}}
-config.microsoftApiApplicationClientID = '{{ .Env.MICROSOFT_API_APP_CLIENT_ID }}';
-{{ end -}}
-
-
-// Invitation service.
-//
-
-{{ if .Env.INVITE_SERVICE_URL -}}
-config.inviteServiceUrl = '{{ .Env.INVITE_SERVICE_URL }}';
-{{ end -}}
-
-{{ if .Env.PEOPLE_SEARCH_URL -}}
-config.peopleSearchUrl = '{{ .Env.PEOPLE_SEARCH_URL }}';
-config.peopleSearchQueryTypes = ['user','conferenceRooms'];
-{{ end -}}
-
-
-// Miscellaneous.
-//
-
-// Prejoin page.
-config.prejoinConfig = {
-    enabled: {{ $ENABLE_PREJOIN_PAGE }},
-
-    // Hides the participant name editing field in the prejoin screen.
-    hideDisplayName: {{ $HIDE_PREJOIN_DISPLAY_NAME }}
-};
-
-// List of buttons to hide from the extra join options dropdown on prejoin screen.
-{{ if .Env.HIDE_PREJOIN_EXTRA_BUTTONS -}}
-config.prejoinConfig.hideExtraJoinButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREJOIN_EXTRA_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Welcome page.
-config.welcomePage = {
-    disabled: {{ not $ENABLE_WELCOME_PAGE }}
-};
-
-// Close page.
-config.enableClosePage = {{ $ENABLE_CLOSE_PAGE }};
-
-// Default language.
-{{ if .Env.DEFAULT_LANGUAGE -}}
-config.defaultLanguage = '{{ .Env.DEFAULT_LANGUAGE }}';
-{{ end -}}
-
-// Require users to always specify a display name.
-config.requireDisplayName = {{ $ENABLE_REQUIRE_DISPLAY_NAME }};
-
-// Chrome extension banner.
-{{ if .Env.CHROME_EXTENSION_BANNER_JSON -}}
-config.chromeExtensionBanner = {{ .Env.CHROME_EXTENSION_BANNER_JSON }};
-{{ end -}}
-
-// Disables profile and the edit of all fields from the profile settings (display name and email)
-config.disableProfile = {{ $DISABLE_PROFILE }};
-
-// Room password (false for anything, number for max digits)
-{{ if $ENABLE_JAAS_COMPONENTS -}}
-config.roomPasswordNumberOfDigits = 10;
-{{ else -}}
-config.roomPasswordNumberOfDigits = {{ $ROOM_PASSWORD_DIGITS }};
-{{ end -}}
-
-// Advanced.
-//
-
-{{ if not $ENABLE_REMB -}}
-config.enableRemb = false;
-{{ end -}}
-{{ if not $ENABLE_TCC -}}
-config.enableTcc = false;
-{{ end -}}
-
-
-// Transcriptions (subtitles and buttons can be configured in interface_config)
-config.transcription = {
-    enabled: {{ $ENABLE_TRANSCRIPTIONS }},
-    translationLanguages: {{ $TRANSLATION_LANGUAGES }},
-    translationLanguagesHead: {{ $TRANSLATION_LANGUAGES_HEAD }},
-    useAppLanguage: {{ $USE_APP_LANGUAGE }},
-    preferredLanguage: '{{ $PREFERRED_LANGUAGE }}',
-    disableStartForAll: {{ $DISABLE_START_FOR_ALL }},
-    autoCaptionOnRecord: {{ $AUTO_CAPTION_ON_RECORD }},
-};
-
-// Dynamic branding
-{{ if .Env.DYNAMIC_BRANDING_URL -}}
-// External API url used to receive branding specific information.
-config.dynamicBrandingUrl = '{{ .Env.DYNAMIC_BRANDING_URL }}';
-{{ else if .Env.BRANDING_DATA_URL  -}}
-config.brandingDataUrl = '{{ .Env.BRANDING_DATA_URL }}';
-{{ end -}}
-
-{{ if .Env.TOKEN_AUTH_URL -}}
-// Authenticate using external service
-config.tokenAuthUrl = '{{ .Env.TOKEN_AUTH_URL }}';
-{{ end -}}
-
-
-// Deployment information.
-//
-
-config.deploymentInfo = {};
-
-{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT -}}
-config.deploymentInfo.environment = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_SHARD -}}
-config.deploymentInfo.shard = '{{ .Env.DEPLOYMENTINFO_SHARD }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE -}}
-config.deploymentInfo.envType = '{{ .Env.DEPLOYMENTINFO_ENVIRONMENT_TYPE }}';
-{{ end -}}
-
-{{ if .Env.DEPLOYMENTINFO_REGION -}}
-config.deploymentInfo.region = '{{ .Env.DEPLOYMENTINFO_REGION }}';
-{{ end -}}
-
-// Deep Linking
-config.disableDeepLinking = {{ $DISABLE_DEEP_LINKING }};
-
-// P2P preferred codec
-{{ if .Env.P2P_PREFERRED_CODEC -}}
-config.p2p.preferredCodec = '{{ .Env.P2P_PREFERRED_CODEC }}';
-{{ end -}}
-
-// Video quality settings.
-//
-
-config.videoQuality = {};
-config.videoQuality.codecPreferenceOrder = {{ $CODEC_ORDER_JVB }};
-config.videoQuality.mobileCodecPreferenceOrder = {{ $CODEC_ORDER_JVB_MOBILE }};
-config.videoQuality.enableAdaptiveMode = {{ $ENABLE_ADAPTIVE_MODE }};
-
-{{ if .Env.VIDEOQUALITY_PREFERRED_CODEC -}}
-config.videoQuality.preferredCodec = '{{ .Env.VIDEOQUALITY_PREFERRED_CODEC }}';
-{{ end -}}
-
-config.videoQuality.av1 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_LOW }}
-config.videoQuality.av1.low = {{ .Env.VIDEOQUALITY_BITRATE_AV1_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }}
-config.videoQuality.av1.standard = {{ .Env.VIDEOQUALITY_BITRATE_AV1_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }}
-config.videoQuality.av1.high = {{ .Env.VIDEOQUALITY_BITRATE_AV1_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_FULL }}
-config.videoQuality.av1.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }}
-config.videoQuality.av1.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_AV1_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }}
-config.videoQuality.av1.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_AV1_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.h264 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_LOW }}
-config.videoQuality.h264.low = {{ .Env.VIDEOQUALITY_BITRATE_H264_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }}
-config.videoQuality.h264.standard = {{ .Env.VIDEOQUALITY_BITRATE_H264_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_HIGH }}
-config.videoQuality.h264.high = {{ .Env.VIDEOQUALITY_BITRATE_H264_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_FULL }}
-config.videoQuality.h264.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }}
-config.videoQuality.h264.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_H264_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }}
-config.videoQuality.h264.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_H264_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.vp8 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_LOW }}
-config.videoQuality.vp8.low = {{ .Env.VIDEOQUALITY_BITRATE_VP8_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }}
-config.videoQuality.vp8.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP8_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }}
-config.videoQuality.vp8.high = {{ .Env.VIDEOQUALITY_BITRATE_VP8_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_FULL }}
-config.videoQuality.vp8.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }}
-config.videoQuality.vp8.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP8_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }}
-config.videoQuality.vp8.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP8_SS_HIGH }};
-{{ end -}}
-
-config.videoQuality.vp9 = {};
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_LOW }}
-config.videoQuality.vp9.low = {{ .Env.VIDEOQUALITY_BITRATE_VP9_LOW }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }}
-config.videoQuality.vp9.standard = {{ .Env.VIDEOQUALITY_BITRATE_VP9_STANDARD }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }}
-config.videoQuality.vp9.high = {{ .Env.VIDEOQUALITY_BITRATE_VP9_HIGH }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_FULL }}
-config.videoQuality.vp9.fullHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_FULL }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }}
-config.videoQuality.vp9.ultraHd = {{ .Env.VIDEOQUALITY_BITRATE_VP9_ULTRA }};
-{{ end -}}
-
-{{ if .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }}
-config.videoQuality.vp9.ssHigh = {{ .Env.VIDEOQUALITY_BITRATE_VP9_SS_HIGH }};
-{{ end -}}
-
- // Reactions
-config.disableReactions = {{ $DISABLE_REACTIONS }};
-
-// Polls
-config.disablePolls = {{ $DISABLE_POLLS }};
-
-// Configure toolbar buttons
-{{ if .Env.TOOLBAR_BUTTONS -}}
-config.toolbarButtons = [ '{{ join "','" (splitList "," .Env.TOOLBAR_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Hides the buttons at pre-join screen
-{{ if .Env.HIDE_PREMEETING_BUTTONS -}}
-config.hiddenPremeetingButtons = [ '{{ join "','" (splitList "," .Env.HIDE_PREMEETING_BUTTONS | compact) }}' ];
-{{ end -}}
-
-// Configure remote participant video menu
-config.remoteVideoMenu = {
-    disabled: {{ $DISABLE_REMOTE_VIDEO_MENU }},
-    disableKick: {{ $DISABLE_KICKOUT }},
-    disableGrantModerator: {{ $DISABLE_GRANT_MODERATOR }},
-    disablePrivateChat: {{ $DISABLE_PRIVATE_CHAT }}
-};
-
-// Configure e2eping
-config.e2eping = {
-    enabled: {{ $ENABLE_E2EPING }}
-};
-
-{{ if .Env.E2EPING_NUM_REQUESTS -}}
-config.e2eping.numRequests = {{ .Env.E2EPING_NUM_REQUESTS }};
-{{ end -}}
-{{ if .Env.E2EPING_MAX_CONFERENCE_SIZE -}}
-config.e2eping.maxConferenceSize = {{ .Env.E2EPING_MAX_CONFERENCE_SIZE }};
-{{ end -}}
-{{ if .Env.E2EPING_MAX_MESSAGE_PER_SECOND -}}
-config.e2eping.maxMessagePerSecond = {{ .Env.E2EPING_MAX_MESSAGE_PER_SECOND }};
-{{ end }}
-
-// Settings for the Excalidraw whiteboard integration.
-config.whiteboard = {
-    enabled: {{ $WHITEBOARD_ENABLED }},
-{{ if .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL -}}
-    collabServerBaseUrl: '{{ .Env.WHITEBOARD_COLLAB_SERVER_PUBLIC_URL }}'
-{{ else if .Env.WHITEBOARD_COLLAB_SERVER_URL_BASE -}}
-    collabServerBaseUrl: '{{ $PUBLIC_URL }}'
-{{ end -}}
-};
-
-// JaaS support: pre-configure image if JAAS_APP_ID was set.
-{{ if .Env.JAAS_APP_ID -}}
-{{ $JAAS_USE_STAGING := .Env.JAAS_USE_STAGING | default "false" | toBool -}}
-{{ $JAAS_DOMAIN := $JAAS_USE_STAGING | ternary "stage.8x8.vc" "8x8.vc" -}}
-
-config.hosts.domain = '{{ $JAAS_DOMAIN }}';
-config.hosts.muc = 'conference.{{ .Env.JAAS_APP_ID }}.{{ $JAAS_DOMAIN }}';
-config.hosts.focus = 'focus.{{ $JAAS_DOMAIN }}';
-
-config.analytics.rtcstatsEnabled = true;
-config.analytics.rtcstatsStoreLogs = true;
-config.analytics.rtcstatsUseLegacy = false;
-config.analytics.rtcstatsEndpoint = 'wss://rtcstats-server-8x8.jitsi.net/';
-config.analytics.rtcstatsPollInterval = 10000;
-config.analytics.rtcstatsSendSdp = true;
-
-config.bosh = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/http-bind';
-config.websocket = 'wss://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/xmpp-websocket';
-config.websocketKeepAliveUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/_unlock';
-config.conferenceRequestUrl = 'https://{{ $JAAS_DOMAIN }}/{{ .Env.JAAS_APP_ID }}/conference-request/v1';
-
-config.hiddenDomain = 'recorder.{{ $JAAS_DOMAIN }}';
-config.hiddenFromRecorderFeatureEnabled = true;
-config.enableEmailInStats = true;
-
-config.jaasActuatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-actuator';
-config.jaasTokenUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/token-mapping';
-config.jaasConferenceCreatorUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access/conference-creator';
-config.webhookProxyUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy';
-config.billingCounterUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/billing-counter/v1/connection';
-config.brandingDataUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/branding/public/v1/conferences';
-config.dialInNumbersUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/access/v1/dids';
-config.dialInConfCodeUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/vmms-conference-mapper/v1/access';
-config.dialOutAuthUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/phone-authorize';
-config.dialOutRegionUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/customer-configs/v1/outbound-destination';
-config.peopleSearchUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/directory/search';
-config.inviteServiceUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/v1/meeting/invite';
-config.recordingSharingUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/jaas-recordings/link';
-config.peopleSearchQueryTypes = ['user','conferenceRooms'];
-config.sipInviteUrl = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/sip-jibri-gateway/jibris/invite';
-config.jaasFeedbackMetadataURL = 'https://{{ $JAAS_DOMAIN }}/v1/_jaas/webhook-proxy/feedback';
-
-{{ if $JAAS_USE_STAGING -}}
-config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend-pilot.cloudflare.jitsi.net';
-{{ else -}}
-config.whiteboard.collabServerBaseUrl = 'https://eght-excalidraw-backend.cloudflare.jitsi.net';
-{{ end -}}
-config.whiteboard.userLimit = 25;
-{{ end -}}
-
-// Testing
-config.testing = {
-    enableAv1Support: {{ $TESTING_AV1_SUPPORT }}
-};
-
-// CUSTOM ADJUSTMENTS
-config.disableThirdPartyRequests = true;
-config.channelLastN = 8;
-config.enableLayerSuspension = true;
\ No newline at end of file

From c14ef6028bc0a2bb85b432eec10461b8731711b3 Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 12:57:12 +0100
Subject: [PATCH 25/33] rename to excalidraw

---
 build.py                                      |    3 +-
 .../image/resources/package-lock.json         | 5325 -----------------
 .../build.py                                  |    2 +-
 .../image/Dockerfile                          |    0
 .../image/resources/install.sh                |    0
 .../image/resources/package.json              |    0
 .../image/resources/src/.eslintrc.js          |    0
 .../image/resources/src/index.ts              |    0
 .../image/resources/tsconfig.json             |    0
 9 files changed, 2 insertions(+), 5328 deletions(-)
 delete mode 100644 infrastructure/excalidraw-backend/image/resources/package-lock.json
 rename infrastructure/{excalidraw-backend => excalidraw}/build.py (97%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/Dockerfile (100%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/resources/install.sh (100%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/resources/package.json (100%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/resources/src/.eslintrc.js (100%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/resources/src/index.ts (100%)
 rename infrastructure/{excalidraw-backend => excalidraw}/image/resources/tsconfig.json (100%)

diff --git a/build.py b/build.py
index 1500086..520ae3a 100644
--- a/build.py
+++ b/build.py
@@ -23,8 +23,7 @@ def initialize(project):
         "release_primary_build_file": "project.clj",
         "release_secondary_build_files": [
             "package.json",
-            "infrastructure/web/build.py",
-            "infrastructure/excalidraw-backend/build.py",
+            "infrastructure/excalidraw/build.py",
         ],
         "release_artifact_server_url": "https://repo.prod.meissa.de",
         "release_organisation": "meissa",
diff --git a/infrastructure/excalidraw-backend/image/resources/package-lock.json b/infrastructure/excalidraw-backend/image/resources/package-lock.json
deleted file mode 100644
index e25aac9..0000000
--- a/infrastructure/excalidraw-backend/image/resources/package-lock.json
+++ /dev/null
@@ -1,5325 +0,0 @@
-{
-    "name": "excalidraw-backend",
-    "version": "1.1.0",
-    "lockfileVersion": 3,
-    "requires": true,
-    "packages": {
-        "": {
-            "name": "excalidraw-backend",
-            "version": "1.1.0",
-            "license": "MIT",
-            "dependencies": {
-                "@types/debug": "4.1.10",
-                "@types/express": "4.17.20",
-                "@types/ms": "0.7.33",
-                "@types/node": "20.8.7",
-                "cross-env": "^7.0.3",
-                "debug": "4.3.4",
-                "dotenv": "^16.0.0",
-                "express": "^4.19.2",
-                "prom-client": "^15.0.0",
-                "socket.io": "^4.7.2",
-                "ts-node-dev": "^2.0.0",
-                "typescript": "5.2.2"
-            },
-            "devDependencies": {
-                "@jitsi/eslint-config": "^4.1.0",
-                "@typescript-eslint/eslint-plugin": "6.8.0",
-                "@typescript-eslint/parser": "6.8.0",
-                "eslint": "^8.1.0",
-                "eslint-plugin-import": "2.28.1",
-                "eslint-plugin-jsdoc": "46.8.2",
-                "eslint-plugin-typescript-sort-keys": "^3.1.0"
-            },
-            "engines": {
-                "node": ">=18.0.0",
-                "npm": ">=10.0.0"
-            },
-            "optionalDependencies": {
-                "bufferutil": "^4.0.6",
-                "utf-8-validate": "^6.0.3"
-            }
-        },
-        "node_modules/@aashutoshrathi/word-wrap": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-            "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/@ampproject/remapping": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
-            "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@jridgewell/gen-mapping": "^0.3.0",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@babel/code-frame": {
-            "version": "7.22.13",
-            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
-            "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/highlight": "^7.22.13",
-                "chalk": "^2.4.2"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/compat-data": {
-            "version": "7.23.2",
-            "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz",
-            "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/core": {
-            "version": "7.23.2",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
-            "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@ampproject/remapping": "^2.2.0",
-                "@babel/code-frame": "^7.22.13",
-                "@babel/generator": "^7.23.0",
-                "@babel/helper-compilation-targets": "^7.22.15",
-                "@babel/helper-module-transforms": "^7.23.0",
-                "@babel/helpers": "^7.23.2",
-                "@babel/parser": "^7.23.0",
-                "@babel/template": "^7.22.15",
-                "@babel/traverse": "^7.23.2",
-                "@babel/types": "^7.23.0",
-                "convert-source-map": "^2.0.0",
-                "debug": "^4.1.0",
-                "gensync": "^1.0.0-beta.2",
-                "json5": "^2.2.3",
-                "semver": "^6.3.1"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/babel"
-            }
-        },
-        "node_modules/@babel/eslint-parser": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz",
-            "integrity": "sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
-                "eslint-visitor-keys": "^2.1.0",
-                "semver": "^6.3.1"
-            },
-            "engines": {
-                "node": "^10.13.0 || ^12.13.0 || >=14.0.0"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.11.0",
-                "eslint": "^7.5.0 || ^8.0.0"
-            }
-        },
-        "node_modules/@babel/generator": {
-            "version": "7.23.0",
-            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
-            "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/types": "^7.23.0",
-                "@jridgewell/gen-mapping": "^0.3.2",
-                "@jridgewell/trace-mapping": "^0.3.17",
-                "jsesc": "^2.5.1"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-compilation-targets": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
-            "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/compat-data": "^7.22.9",
-                "@babel/helper-validator-option": "^7.22.15",
-                "browserslist": "^4.21.9",
-                "lru-cache": "^5.1.1",
-                "semver": "^6.3.1"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-environment-visitor": {
-            "version": "7.22.20",
-            "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
-            "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-function-name": {
-            "version": "7.23.0",
-            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
-            "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/template": "^7.22.15",
-                "@babel/types": "^7.23.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-hoist-variables": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
-            "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/types": "^7.22.5"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-module-imports": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
-            "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/types": "^7.22.15"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-module-transforms": {
-            "version": "7.23.0",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
-            "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/helper-environment-visitor": "^7.22.20",
-                "@babel/helper-module-imports": "^7.22.15",
-                "@babel/helper-simple-access": "^7.22.5",
-                "@babel/helper-split-export-declaration": "^7.22.6",
-                "@babel/helper-validator-identifier": "^7.22.20"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            },
-            "peerDependencies": {
-                "@babel/core": "^7.0.0"
-            }
-        },
-        "node_modules/@babel/helper-simple-access": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
-            "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/types": "^7.22.5"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-split-export-declaration": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
-            "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/types": "^7.22.5"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-string-parser": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
-            "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-validator-identifier": {
-            "version": "7.22.20",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
-            "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helper-validator-option": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
-            "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/helpers": {
-            "version": "7.23.2",
-            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
-            "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/template": "^7.22.15",
-                "@babel/traverse": "^7.23.2",
-                "@babel/types": "^7.23.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/highlight": {
-            "version": "7.22.20",
-            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
-            "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/helper-validator-identifier": "^7.22.20",
-                "chalk": "^2.4.2",
-                "js-tokens": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/parser": {
-            "version": "7.23.0",
-            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
-            "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
-            "dev": true,
-            "peer": true,
-            "bin": {
-                "parser": "bin/babel-parser.js"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@babel/template": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
-            "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.22.13",
-                "@babel/parser": "^7.22.15",
-                "@babel/types": "^7.22.15"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/traverse": {
-            "version": "7.23.2",
-            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
-            "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/code-frame": "^7.22.13",
-                "@babel/generator": "^7.23.0",
-                "@babel/helper-environment-visitor": "^7.22.20",
-                "@babel/helper-function-name": "^7.23.0",
-                "@babel/helper-hoist-variables": "^7.22.5",
-                "@babel/helper-split-export-declaration": "^7.22.6",
-                "@babel/parser": "^7.23.0",
-                "@babel/types": "^7.23.0",
-                "debug": "^4.1.0",
-                "globals": "^11.1.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@babel/types": {
-            "version": "7.23.0",
-            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
-            "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@babel/helper-string-parser": "^7.22.5",
-                "@babel/helper-validator-identifier": "^7.22.20",
-                "to-fast-properties": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/@cspotcode/source-map-support": {
-            "version": "0.8.1",
-            "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-            "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-            "dependencies": {
-                "@jridgewell/trace-mapping": "0.3.9"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
-        "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.9",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-            "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-            "dependencies": {
-                "@jridgewell/resolve-uri": "^3.0.3",
-                "@jridgewell/sourcemap-codec": "^1.4.10"
-            }
-        },
-        "node_modules/@es-joy/jsdoccomment": {
-            "version": "0.40.1",
-            "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz",
-            "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==",
-            "dev": true,
-            "dependencies": {
-                "comment-parser": "1.4.0",
-                "esquery": "^1.5.0",
-                "jsdoc-type-pratt-parser": "~4.0.0"
-            },
-            "engines": {
-                "node": ">=16"
-            }
-        },
-        "node_modules/@eslint-community/eslint-utils": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-            "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
-            "dev": true,
-            "dependencies": {
-                "eslint-visitor-keys": "^3.3.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
-            }
-        },
-        "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
-            "version": "3.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/@eslint-community/regexpp": {
-            "version": "4.9.1",
-            "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz",
-            "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==",
-            "dev": true,
-            "engines": {
-                "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@eslint/eslintrc": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz",
-            "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==",
-            "dev": true,
-            "dependencies": {
-                "ajv": "^6.12.4",
-                "debug": "^4.3.2",
-                "espree": "^9.6.0",
-                "globals": "^13.19.0",
-                "ignore": "^5.2.0",
-                "import-fresh": "^3.2.1",
-                "js-yaml": "^4.1.0",
-                "minimatch": "^3.1.2",
-                "strip-json-comments": "^3.1.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/@eslint/eslintrc/node_modules/globals": {
-            "version": "13.23.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
-            "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/@eslint/js": {
-            "version": "8.51.0",
-            "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz",
-            "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@humanwhocodes/config-array": {
-            "version": "0.11.12",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.12.tgz",
-            "integrity": "sha512-NlGesA1usRNn6ctHCZ21M4/dKPgW9Nn1FypRdIKKgZOKzkVV4T1FlK5mBiLhHBCDmEbdQG0idrcXlbZfksJ+RA==",
-            "dev": true,
-            "dependencies": {
-                "@humanwhocodes/object-schema": "^2.0.0",
-                "debug": "^4.1.1",
-                "minimatch": "^3.0.5"
-            },
-            "engines": {
-                "node": ">=10.10.0"
-            }
-        },
-        "node_modules/@humanwhocodes/module-importer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-            "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-            "dev": true,
-            "engines": {
-                "node": ">=12.22"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/nzakas"
-            }
-        },
-        "node_modules/@humanwhocodes/object-schema": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.0.tgz",
-            "integrity": "sha512-9S9QrXY2K0L4AGDcSgTi9vgiCcG8VcBv4Mp7/1hDPYoswIy6Z6KO5blYto82BT8M0MZNRWmCFLpCs3HlpYGGdw==",
-            "dev": true
-        },
-        "node_modules/@jitsi/eslint-config": {
-            "version": "4.1.12",
-            "resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-4.1.12.tgz",
-            "integrity": "sha512-2/PfpxLyP1IBYZbHRJo24WWvxfcuO4b4ib6Js9zToKWT53ap1Y7bhrCVVnFdF9VRqd6xVB/PJAQ+LAR4f/xKNw==",
-            "dev": true,
-            "peerDependencies": {
-                "@babel/eslint-parser": ">= 7",
-                "eslint": ">= 8"
-            }
-        },
-        "node_modules/@jridgewell/gen-mapping": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
-            "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@jridgewell/set-array": "^1.0.1",
-                "@jridgewell/sourcemap-codec": "^1.4.10",
-                "@jridgewell/trace-mapping": "^0.3.9"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/resolve-uri": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
-            "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/set-array": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
-            "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/@jridgewell/sourcemap-codec": {
-            "version": "1.4.15",
-            "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
-            "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
-        },
-        "node_modules/@jridgewell/trace-mapping": {
-            "version": "0.3.20",
-            "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
-            "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "@jridgewell/resolve-uri": "^3.1.0",
-                "@jridgewell/sourcemap-codec": "^1.4.14"
-            }
-        },
-        "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
-            "version": "5.1.1-v1",
-            "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
-            "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "eslint-scope": "5.1.1"
-            }
-        },
-        "node_modules/@nodelib/fs.scandir": {
-            "version": "2.1.5",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-            "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-            "dev": true,
-            "dependencies": {
-                "@nodelib/fs.stat": "2.0.5",
-                "run-parallel": "^1.1.9"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@nodelib/fs.stat": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-            "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-            "dev": true,
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@nodelib/fs.walk": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-            "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-            "dev": true,
-            "dependencies": {
-                "@nodelib/fs.scandir": "2.1.5",
-                "fastq": "^1.6.0"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/@opentelemetry/api": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.6.0.tgz",
-            "integrity": "sha512-OWlrQAnWn9577PhVgqjUvMr1pg57Bc4jv0iL4w0PRuOSRvq67rvHW9Ie/dZVMvCzhSCB+UxhcY/PmCmFj33Q+g==",
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/@socket.io/component-emitter": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
-            "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
-        },
-        "node_modules/@tsconfig/node10": {
-            "version": "1.0.9",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
-            "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA=="
-        },
-        "node_modules/@tsconfig/node12": {
-            "version": "1.0.11",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-            "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag=="
-        },
-        "node_modules/@tsconfig/node14": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-            "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow=="
-        },
-        "node_modules/@tsconfig/node16": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
-            "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA=="
-        },
-        "node_modules/@types/body-parser": {
-            "version": "1.19.4",
-            "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz",
-            "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==",
-            "dependencies": {
-                "@types/connect": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/connect": {
-            "version": "3.4.37",
-            "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz",
-            "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/cookie": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
-            "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
-        },
-        "node_modules/@types/cors": {
-            "version": "2.8.15",
-            "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.15.tgz",
-            "integrity": "sha512-n91JxbNLD8eQIuXDIChAN1tCKNWCEgpceU9b7ZMbFA+P+Q4yIeh80jizFLEvolRPc1ES0VdwFlGv+kJTSirogw==",
-            "dependencies": {
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/debug": {
-            "version": "4.1.10",
-            "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz",
-            "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==",
-            "dependencies": {
-                "@types/ms": "*"
-            }
-        },
-        "node_modules/@types/express": {
-            "version": "4.17.20",
-            "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz",
-            "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==",
-            "dependencies": {
-                "@types/body-parser": "*",
-                "@types/express-serve-static-core": "^4.17.33",
-                "@types/qs": "*",
-                "@types/serve-static": "*"
-            }
-        },
-        "node_modules/@types/express-serve-static-core": {
-            "version": "4.17.39",
-            "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz",
-            "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==",
-            "dependencies": {
-                "@types/node": "*",
-                "@types/qs": "*",
-                "@types/range-parser": "*",
-                "@types/send": "*"
-            }
-        },
-        "node_modules/@types/http-errors": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz",
-            "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA=="
-        },
-        "node_modules/@types/json-schema": {
-            "version": "7.0.14",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
-            "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
-            "dev": true
-        },
-        "node_modules/@types/json5": {
-            "version": "0.0.29",
-            "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
-            "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
-            "dev": true
-        },
-        "node_modules/@types/mime": {
-            "version": "1.3.4",
-            "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz",
-            "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw=="
-        },
-        "node_modules/@types/ms": {
-            "version": "0.7.33",
-            "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.33.tgz",
-            "integrity": "sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ=="
-        },
-        "node_modules/@types/node": {
-            "version": "20.8.7",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz",
-            "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==",
-            "dependencies": {
-                "undici-types": "~5.25.1"
-            }
-        },
-        "node_modules/@types/qs": {
-            "version": "6.9.9",
-            "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz",
-            "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg=="
-        },
-        "node_modules/@types/range-parser": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz",
-            "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA=="
-        },
-        "node_modules/@types/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
-            "dev": true
-        },
-        "node_modules/@types/send": {
-            "version": "0.17.3",
-            "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz",
-            "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==",
-            "dependencies": {
-                "@types/mime": "^1",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/serve-static": {
-            "version": "1.15.4",
-            "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz",
-            "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==",
-            "dependencies": {
-                "@types/http-errors": "*",
-                "@types/mime": "*",
-                "@types/node": "*"
-            }
-        },
-        "node_modules/@types/strip-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ=="
-        },
-        "node_modules/@types/strip-json-comments": {
-            "version": "0.0.30",
-            "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
-            "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ=="
-        },
-        "node_modules/@typescript-eslint/eslint-plugin": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz",
-            "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==",
-            "dev": true,
-            "dependencies": {
-                "@eslint-community/regexpp": "^4.5.1",
-                "@typescript-eslint/scope-manager": "6.8.0",
-                "@typescript-eslint/type-utils": "6.8.0",
-                "@typescript-eslint/utils": "6.8.0",
-                "@typescript-eslint/visitor-keys": "6.8.0",
-                "debug": "^4.3.4",
-                "graphemer": "^1.4.0",
-                "ignore": "^5.2.4",
-                "natural-compare": "^1.4.0",
-                "semver": "^7.5.4",
-                "ts-api-utils": "^1.0.1"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dev": true,
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dev": true,
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-            "dev": true
-        },
-        "node_modules/@typescript-eslint/experimental-utils": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz",
-            "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/utils": "5.62.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
-            "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "5.62.0",
-                "@typescript-eslint/visitor-keys": "5.62.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
-            "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
-            "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "5.62.0",
-                "@typescript-eslint/visitor-keys": "5.62.0",
-                "debug": "^4.3.4",
-                "globby": "^11.1.0",
-                "is-glob": "^4.0.3",
-                "semver": "^7.3.7",
-                "tsutils": "^3.21.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
-            "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
-            "dev": true,
-            "dependencies": {
-                "@eslint-community/eslint-utils": "^4.2.0",
-                "@types/json-schema": "^7.0.9",
-                "@types/semver": "^7.3.12",
-                "@typescript-eslint/scope-manager": "5.62.0",
-                "@typescript-eslint/types": "5.62.0",
-                "@typescript-eslint/typescript-estree": "5.62.0",
-                "eslint-scope": "^5.1.1",
-                "semver": "^7.3.7"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": {
-            "version": "5.62.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
-            "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "5.62.0",
-                "eslint-visitor-keys": "^3.3.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": {
-            "version": "3.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dev": true,
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dev": true,
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/experimental-utils/node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-            "dev": true
-        },
-        "node_modules/@typescript-eslint/parser": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz",
-            "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/scope-manager": "6.8.0",
-                "@typescript-eslint/types": "6.8.0",
-                "@typescript-eslint/typescript-estree": "6.8.0",
-                "@typescript-eslint/visitor-keys": "6.8.0",
-                "debug": "^4.3.4"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/scope-manager": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz",
-            "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "6.8.0",
-                "@typescript-eslint/visitor-keys": "6.8.0"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/type-utils": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz",
-            "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/typescript-estree": "6.8.0",
-                "@typescript-eslint/utils": "6.8.0",
-                "debug": "^4.3.4",
-                "ts-api-utils": "^1.0.1"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/types": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz",
-            "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==",
-            "dev": true,
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/typescript-estree": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz",
-            "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "6.8.0",
-                "@typescript-eslint/visitor-keys": "6.8.0",
-                "debug": "^4.3.4",
-                "globby": "^11.1.0",
-                "is-glob": "^4.0.3",
-                "semver": "^7.5.4",
-                "ts-api-utils": "^1.0.1"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dev": true,
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dev": true,
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-            "dev": true
-        },
-        "node_modules/@typescript-eslint/utils": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz",
-            "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==",
-            "dev": true,
-            "dependencies": {
-                "@eslint-community/eslint-utils": "^4.4.0",
-                "@types/json-schema": "^7.0.12",
-                "@types/semver": "^7.5.0",
-                "@typescript-eslint/scope-manager": "6.8.0",
-                "@typescript-eslint/types": "6.8.0",
-                "@typescript-eslint/typescript-estree": "6.8.0",
-                "semver": "^7.5.4"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            },
-            "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/@typescript-eslint/utils/node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dev": true,
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/utils/node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dev": true,
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/@typescript-eslint/utils/node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-            "dev": true
-        },
-        "node_modules/@typescript-eslint/visitor-keys": {
-            "version": "6.8.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz",
-            "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/types": "6.8.0",
-                "eslint-visitor-keys": "^3.4.1"
-            },
-            "engines": {
-                "node": "^16.0.0 || >=18.0.0"
-            },
-            "funding": {
-                "type": "opencollective",
-                "url": "https://opencollective.com/typescript-eslint"
-            }
-        },
-        "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
-            "version": "3.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/accepts": {
-            "version": "1.3.8",
-            "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-            "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-            "dependencies": {
-                "mime-types": "~2.1.34",
-                "negotiator": "0.6.3"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/acorn": {
-            "version": "8.10.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
-            "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
-            "bin": {
-                "acorn": "bin/acorn"
-            },
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/acorn-jsx": {
-            "version": "5.3.2",
-            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-            "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-            "dev": true,
-            "peerDependencies": {
-                "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/acorn-walk": {
-            "version": "8.2.0",
-            "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
-            "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
-            "engines": {
-                "node": ">=0.4.0"
-            }
-        },
-        "node_modules/ajv": {
-            "version": "6.12.6",
-            "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-            "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-            "dev": true,
-            "dependencies": {
-                "fast-deep-equal": "^3.1.1",
-                "fast-json-stable-stringify": "^2.0.0",
-                "json-schema-traverse": "^0.4.1",
-                "uri-js": "^4.2.2"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/epoberezkin"
-            }
-        },
-        "node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/ansi-styles": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "color-convert": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/anymatch": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-            "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-            "dependencies": {
-                "normalize-path": "^3.0.0",
-                "picomatch": "^2.0.4"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/are-docs-informative": {
-            "version": "0.0.2",
-            "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
-            "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
-            "dev": true,
-            "engines": {
-                "node": ">=14"
-            }
-        },
-        "node_modules/arg": {
-            "version": "4.1.3",
-            "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-            "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
-        },
-        "node_modules/argparse": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-            "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-            "dev": true
-        },
-        "node_modules/array-buffer-byte-length": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
-            "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "is-array-buffer": "^3.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array-flatten": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-            "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
-        },
-        "node_modules/array-includes": {
-            "version": "3.1.7",
-            "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
-            "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "get-intrinsic": "^1.2.1",
-                "is-string": "^1.0.7"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array-union": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-            "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/array.prototype.findlastindex": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
-            "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "es-shim-unscopables": "^1.0.0",
-                "get-intrinsic": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array.prototype.flat": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
-            "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/array.prototype.flatmap": {
-            "version": "1.3.2",
-            "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
-            "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "es-shim-unscopables": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/arraybuffer.prototype.slice": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
-            "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
-            "dev": true,
-            "dependencies": {
-                "array-buffer-byte-length": "^1.0.0",
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "get-intrinsic": "^1.2.1",
-                "is-array-buffer": "^3.0.2",
-                "is-shared-array-buffer": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/available-typed-arrays": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
-            "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/balanced-match": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-        },
-        "node_modules/base64id": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
-            "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
-            "engines": {
-                "node": "^4.5.0 || >= 5.9"
-            }
-        },
-        "node_modules/binary-extensions": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-            "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/bintrees": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz",
-            "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw=="
-        },
-        "node_modules/body-parser": {
-            "version": "1.20.3",
-            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
-            "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
-            "license": "MIT",
-            "dependencies": {
-                "bytes": "3.1.2",
-                "content-type": "~1.0.5",
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "destroy": "1.2.0",
-                "http-errors": "2.0.0",
-                "iconv-lite": "0.4.24",
-                "on-finished": "2.4.1",
-                "qs": "6.13.0",
-                "raw-body": "2.5.2",
-                "type-is": "~1.6.18",
-                "unpipe": "1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8",
-                "npm": "1.2.8000 || >= 1.4.16"
-            }
-        },
-        "node_modules/body-parser/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "license": "MIT",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/body-parser/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-            "license": "MIT"
-        },
-        "node_modules/brace-expansion": {
-            "version": "1.1.11",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-            "dependencies": {
-                "balanced-match": "^1.0.0",
-                "concat-map": "0.0.1"
-            }
-        },
-        "node_modules/braces": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-            "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-            "dependencies": {
-                "fill-range": "^7.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/browserslist": {
-            "version": "4.22.1",
-            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
-            "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/browserslist"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/browserslist"
-                },
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/ai"
-                }
-            ],
-            "peer": true,
-            "dependencies": {
-                "caniuse-lite": "^1.0.30001541",
-                "electron-to-chromium": "^1.4.535",
-                "node-releases": "^2.0.13",
-                "update-browserslist-db": "^1.0.13"
-            },
-            "bin": {
-                "browserslist": "cli.js"
-            },
-            "engines": {
-                "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-            }
-        },
-        "node_modules/buffer-from": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-            "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
-        },
-        "node_modules/bufferutil": {
-            "version": "4.0.8",
-            "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.8.tgz",
-            "integrity": "sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==",
-            "hasInstallScript": true,
-            "optional": true,
-            "dependencies": {
-                "node-gyp-build": "^4.3.0"
-            },
-            "engines": {
-                "node": ">=6.14.2"
-            }
-        },
-        "node_modules/builtin-modules": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
-            "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/bytes": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-            "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/call-bind": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
-            "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
-            "license": "MIT",
-            "dependencies": {
-                "es-define-property": "^1.0.0",
-                "es-errors": "^1.3.0",
-                "function-bind": "^1.1.2",
-                "get-intrinsic": "^1.2.4",
-                "set-function-length": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/callsites": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-            "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/caniuse-lite": {
-            "version": "1.0.30001551",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz",
-            "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/browserslist"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
-                },
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/ai"
-                }
-            ],
-            "peer": true
-        },
-        "node_modules/chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/chokidar": {
-            "version": "3.5.3",
-            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-            "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-            "funding": [
-                {
-                    "type": "individual",
-                    "url": "https://paulmillr.com/funding/"
-                }
-            ],
-            "dependencies": {
-                "anymatch": "~3.1.2",
-                "braces": "~3.0.2",
-                "glob-parent": "~5.1.2",
-                "is-binary-path": "~2.1.0",
-                "is-glob": "~4.0.1",
-                "normalize-path": "~3.0.0",
-                "readdirp": "~3.6.0"
-            },
-            "engines": {
-                "node": ">= 8.10.0"
-            },
-            "optionalDependencies": {
-                "fsevents": "~2.3.2"
-            }
-        },
-        "node_modules/chokidar/node_modules/glob-parent": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-            "dependencies": {
-                "is-glob": "^4.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/color-convert": {
-            "version": "1.9.3",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "color-name": "1.1.3"
-            }
-        },
-        "node_modules/color-name": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/comment-parser": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz",
-            "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==",
-            "dev": true,
-            "engines": {
-                "node": ">= 12.0.0"
-            }
-        },
-        "node_modules/concat-map": {
-            "version": "0.0.1",
-            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-            "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
-        },
-        "node_modules/content-disposition": {
-            "version": "0.5.4",
-            "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-            "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-            "dependencies": {
-                "safe-buffer": "5.2.1"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/content-type": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
-            "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/convert-source-map": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
-            "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/cookie": {
-            "version": "0.7.1",
-            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
-            "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/cookie-signature": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-            "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
-        },
-        "node_modules/cors": {
-            "version": "2.8.5",
-            "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
-            "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
-            "dependencies": {
-                "object-assign": "^4",
-                "vary": "^1"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/create-require": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-            "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="
-        },
-        "node_modules/cross-env": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
-            "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
-            "dependencies": {
-                "cross-spawn": "^7.0.1"
-            },
-            "bin": {
-                "cross-env": "src/bin/cross-env.js",
-                "cross-env-shell": "src/bin/cross-env-shell.js"
-            },
-            "engines": {
-                "node": ">=10.14",
-                "npm": ">=6",
-                "yarn": ">=1"
-            }
-        },
-        "node_modules/cross-spawn": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-            "dependencies": {
-                "path-key": "^3.1.0",
-                "shebang-command": "^2.0.0",
-                "which": "^2.0.1"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-            "dependencies": {
-                "ms": "2.1.2"
-            },
-            "engines": {
-                "node": ">=6.0"
-            },
-            "peerDependenciesMeta": {
-                "supports-color": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/deep-is": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-            "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-            "dev": true
-        },
-        "node_modules/define-data-property": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
-            "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
-            "license": "MIT",
-            "dependencies": {
-                "es-define-property": "^1.0.0",
-                "es-errors": "^1.3.0",
-                "gopd": "^1.0.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/define-properties": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
-            "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
-            "dev": true,
-            "dependencies": {
-                "define-data-property": "^1.0.1",
-                "has-property-descriptors": "^1.0.0",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/depd": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-            "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/destroy": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-            "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8",
-                "npm": "1.2.8000 || >= 1.4.16"
-            }
-        },
-        "node_modules/diff": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-            "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-            "engines": {
-                "node": ">=0.3.1"
-            }
-        },
-        "node_modules/dir-glob": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-            "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-            "dev": true,
-            "dependencies": {
-                "path-type": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/doctrine": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
-        "node_modules/dotenv": {
-            "version": "16.3.1",
-            "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
-            "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
-            "engines": {
-                "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/motdotla/dotenv?sponsor=1"
-            }
-        },
-        "node_modules/dynamic-dedupe": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
-            "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
-            "dependencies": {
-                "xtend": "^4.0.0"
-            }
-        },
-        "node_modules/ee-first": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-            "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-            "license": "MIT"
-        },
-        "node_modules/electron-to-chromium": {
-            "version": "1.4.560",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.560.tgz",
-            "integrity": "sha512-HhJH/pWAxTaPZl7R3mJ6gCd8MfjQdil9RAWk84qHaLsmPTadydfAmq0a1x8kZtOGQ6pZrWhOYj5uZ8I0meZIgg==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/encodeurl": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
-            "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/engine.io": {
-            "version": "6.5.3",
-            "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.3.tgz",
-            "integrity": "sha512-IML/R4eG/pUS5w7OfcDE0jKrljWS9nwnEfsxWCIJF5eO6AHo6+Hlv+lQbdlAYsiJPHzUthLm1RUjnBzWOs45cw==",
-            "dependencies": {
-                "@types/cookie": "^0.4.1",
-                "@types/cors": "^2.8.12",
-                "@types/node": ">=10.0.0",
-                "accepts": "~1.3.4",
-                "base64id": "2.0.0",
-                "cookie": "~0.4.1",
-                "cors": "~2.8.5",
-                "debug": "~4.3.1",
-                "engine.io-parser": "~5.2.1",
-                "ws": "~8.11.0"
-            },
-            "engines": {
-                "node": ">=10.2.0"
-            }
-        },
-        "node_modules/engine.io-parser": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
-            "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
-            "engines": {
-                "node": ">=10.0.0"
-            }
-        },
-        "node_modules/engine.io/node_modules/cookie": {
-            "version": "0.4.2",
-            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
-            "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/engine.io/node_modules/utf-8-validate": {
-            "version": "5.0.10",
-            "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
-            "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
-            "hasInstallScript": true,
-            "optional": true,
-            "peer": true,
-            "dependencies": {
-                "node-gyp-build": "^4.3.0"
-            },
-            "engines": {
-                "node": ">=6.14.2"
-            }
-        },
-        "node_modules/engine.io/node_modules/ws": {
-            "version": "8.11.0",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
-            "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
-            "engines": {
-                "node": ">=10.0.0"
-            },
-            "peerDependencies": {
-                "bufferutil": "^4.0.1",
-                "utf-8-validate": "^5.0.2"
-            },
-            "peerDependenciesMeta": {
-                "bufferutil": {
-                    "optional": true
-                },
-                "utf-8-validate": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/es-abstract": {
-            "version": "1.22.2",
-            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
-            "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==",
-            "dev": true,
-            "dependencies": {
-                "array-buffer-byte-length": "^1.0.0",
-                "arraybuffer.prototype.slice": "^1.0.2",
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "es-set-tostringtag": "^2.0.1",
-                "es-to-primitive": "^1.2.1",
-                "function.prototype.name": "^1.1.6",
-                "get-intrinsic": "^1.2.1",
-                "get-symbol-description": "^1.0.0",
-                "globalthis": "^1.0.3",
-                "gopd": "^1.0.1",
-                "has": "^1.0.3",
-                "has-property-descriptors": "^1.0.0",
-                "has-proto": "^1.0.1",
-                "has-symbols": "^1.0.3",
-                "internal-slot": "^1.0.5",
-                "is-array-buffer": "^3.0.2",
-                "is-callable": "^1.2.7",
-                "is-negative-zero": "^2.0.2",
-                "is-regex": "^1.1.4",
-                "is-shared-array-buffer": "^1.0.2",
-                "is-string": "^1.0.7",
-                "is-typed-array": "^1.1.12",
-                "is-weakref": "^1.0.2",
-                "object-inspect": "^1.12.3",
-                "object-keys": "^1.1.1",
-                "object.assign": "^4.1.4",
-                "regexp.prototype.flags": "^1.5.1",
-                "safe-array-concat": "^1.0.1",
-                "safe-regex-test": "^1.0.0",
-                "string.prototype.trim": "^1.2.8",
-                "string.prototype.trimend": "^1.0.7",
-                "string.prototype.trimstart": "^1.0.7",
-                "typed-array-buffer": "^1.0.0",
-                "typed-array-byte-length": "^1.0.0",
-                "typed-array-byte-offset": "^1.0.0",
-                "typed-array-length": "^1.0.4",
-                "unbox-primitive": "^1.0.2",
-                "which-typed-array": "^1.1.11"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/es-define-property": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
-            "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
-            "license": "MIT",
-            "dependencies": {
-                "get-intrinsic": "^1.2.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/es-errors": {
-            "version": "1.3.0",
-            "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
-            "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/es-set-tostringtag": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
-            "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
-            "dev": true,
-            "dependencies": {
-                "get-intrinsic": "^1.1.3",
-                "has": "^1.0.3",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/es-shim-unscopables": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
-            "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
-            "dev": true,
-            "dependencies": {
-                "has": "^1.0.3"
-            }
-        },
-        "node_modules/es-to-primitive": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-            "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-            "dev": true,
-            "dependencies": {
-                "is-callable": "^1.1.4",
-                "is-date-object": "^1.0.1",
-                "is-symbol": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/escalade": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-            "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/escape-html": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-            "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
-            "license": "MIT"
-        },
-        "node_modules/escape-string-regexp": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/eslint": {
-            "version": "8.51.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz",
-            "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==",
-            "dev": true,
-            "dependencies": {
-                "@eslint-community/eslint-utils": "^4.2.0",
-                "@eslint-community/regexpp": "^4.6.1",
-                "@eslint/eslintrc": "^2.1.2",
-                "@eslint/js": "8.51.0",
-                "@humanwhocodes/config-array": "^0.11.11",
-                "@humanwhocodes/module-importer": "^1.0.1",
-                "@nodelib/fs.walk": "^1.2.8",
-                "ajv": "^6.12.4",
-                "chalk": "^4.0.0",
-                "cross-spawn": "^7.0.2",
-                "debug": "^4.3.2",
-                "doctrine": "^3.0.0",
-                "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.2.2",
-                "eslint-visitor-keys": "^3.4.3",
-                "espree": "^9.6.1",
-                "esquery": "^1.4.2",
-                "esutils": "^2.0.2",
-                "fast-deep-equal": "^3.1.3",
-                "file-entry-cache": "^6.0.1",
-                "find-up": "^5.0.0",
-                "glob-parent": "^6.0.2",
-                "globals": "^13.19.0",
-                "graphemer": "^1.4.0",
-                "ignore": "^5.2.0",
-                "imurmurhash": "^0.1.4",
-                "is-glob": "^4.0.0",
-                "is-path-inside": "^3.0.3",
-                "js-yaml": "^4.1.0",
-                "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.4.1",
-                "lodash.merge": "^4.6.2",
-                "minimatch": "^3.1.2",
-                "natural-compare": "^1.4.0",
-                "optionator": "^0.9.3",
-                "strip-ansi": "^6.0.1",
-                "text-table": "^0.2.0"
-            },
-            "bin": {
-                "eslint": "bin/eslint.js"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint-import-resolver-node": {
-            "version": "0.3.9",
-            "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
-            "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^3.2.7",
-                "is-core-module": "^2.13.0",
-                "resolve": "^1.22.4"
-            }
-        },
-        "node_modules/eslint-import-resolver-node/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/eslint-module-utils": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
-            "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
-            "dev": true,
-            "dependencies": {
-                "debug": "^3.2.7"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependenciesMeta": {
-                "eslint": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/eslint-module-utils/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/eslint-plugin-import": {
-            "version": "2.28.1",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz",
-            "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==",
-            "dev": true,
-            "dependencies": {
-                "array-includes": "^3.1.6",
-                "array.prototype.findlastindex": "^1.2.2",
-                "array.prototype.flat": "^1.3.1",
-                "array.prototype.flatmap": "^1.3.1",
-                "debug": "^3.2.7",
-                "doctrine": "^2.1.0",
-                "eslint-import-resolver-node": "^0.3.7",
-                "eslint-module-utils": "^2.8.0",
-                "has": "^1.0.3",
-                "is-core-module": "^2.13.0",
-                "is-glob": "^4.0.3",
-                "minimatch": "^3.1.2",
-                "object.fromentries": "^2.0.6",
-                "object.groupby": "^1.0.0",
-                "object.values": "^1.1.6",
-                "semver": "^6.3.1",
-                "tsconfig-paths": "^3.14.2"
-            },
-            "engines": {
-                "node": ">=4"
-            },
-            "peerDependencies": {
-                "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
-            }
-        },
-        "node_modules/eslint-plugin-import/node_modules/debug": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
-            "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
-            "dev": true,
-            "dependencies": {
-                "ms": "^2.1.1"
-            }
-        },
-        "node_modules/eslint-plugin-import/node_modules/doctrine": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
-            "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/eslint-plugin-jsdoc": {
-            "version": "46.8.2",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.8.2.tgz",
-            "integrity": "sha512-5TSnD018f3tUJNne4s4gDWQflbsgOycIKEUBoCLn6XtBMgNHxQFmV8vVxUtiPxAQq8lrX85OaSG/2gnctxw9uQ==",
-            "dev": true,
-            "dependencies": {
-                "@es-joy/jsdoccomment": "~0.40.1",
-                "are-docs-informative": "^0.0.2",
-                "comment-parser": "1.4.0",
-                "debug": "^4.3.4",
-                "escape-string-regexp": "^4.0.0",
-                "esquery": "^1.5.0",
-                "is-builtin-module": "^3.2.1",
-                "semver": "^7.5.4",
-                "spdx-expression-parse": "^3.0.1"
-            },
-            "engines": {
-                "node": ">=16"
-            },
-            "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            }
-        },
-        "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint-plugin-jsdoc/node_modules/lru-cache": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-            "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-            "dev": true,
-            "dependencies": {
-                "yallist": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/eslint-plugin-jsdoc/node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dev": true,
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
-            "bin": {
-                "semver": "bin/semver.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/eslint-plugin-jsdoc/node_modules/yallist": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-            "dev": true
-        },
-        "node_modules/eslint-plugin-typescript-sort-keys": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-typescript-sort-keys/-/eslint-plugin-typescript-sort-keys-3.1.0.tgz",
-            "integrity": "sha512-rgZeYfEguqKni/V7sbmgFu9/94UDAQd7YqNd0J7Qhw7SdLIGd0iBk2KgpjhRhe2ge4rPSLDIdFWwUiDqBOst6Q==",
-            "dev": true,
-            "dependencies": {
-                "@typescript-eslint/experimental-utils": "^5.0.0",
-                "json-schema": "^0.4.0",
-                "natural-compare-lite": "^1.4.0"
-            },
-            "engines": {
-                "node": ">= 16"
-            },
-            "peerDependencies": {
-                "@typescript-eslint/parser": "^6",
-                "eslint": "^7 || ^8",
-                "typescript": "^3 || ^4 || ^5"
-            }
-        },
-        "node_modules/eslint-scope": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-            "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-            "dev": true,
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^4.1.1"
-            },
-            "engines": {
-                "node": ">=8.0.0"
-            }
-        },
-        "node_modules/eslint-visitor-keys": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
-            "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/eslint/node_modules/ansi-styles": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-            "dev": true,
-            "dependencies": {
-                "color-convert": "^2.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-            }
-        },
-        "node_modules/eslint/node_modules/chalk": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^4.1.0",
-                "supports-color": "^7.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/chalk?sponsor=1"
-            }
-        },
-        "node_modules/eslint/node_modules/color-convert": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-            "dev": true,
-            "dependencies": {
-                "color-name": "~1.1.4"
-            },
-            "engines": {
-                "node": ">=7.0.0"
-            }
-        },
-        "node_modules/eslint/node_modules/color-name": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-            "dev": true
-        },
-        "node_modules/eslint/node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint/node_modules/eslint-scope": {
-            "version": "7.2.2",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-            "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-            "dev": true,
-            "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint/node_modules/eslint-visitor-keys": {
-            "version": "3.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/eslint/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/eslint/node_modules/globals": {
-            "version": "13.23.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
-            "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
-            "dev": true,
-            "dependencies": {
-                "type-fest": "^0.20.2"
-            },
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/eslint/node_modules/has-flag": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/eslint/node_modules/supports-color": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/espree": {
-            "version": "9.6.1",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-            "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-            "dev": true,
-            "dependencies": {
-                "acorn": "^8.9.0",
-                "acorn-jsx": "^5.3.2",
-                "eslint-visitor-keys": "^3.4.1"
-            },
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/espree/node_modules/eslint-visitor-keys": {
-            "version": "3.4.3",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-            "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            },
-            "funding": {
-                "url": "https://opencollective.com/eslint"
-            }
-        },
-        "node_modules/esquery": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-            "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
-            "dev": true,
-            "dependencies": {
-                "estraverse": "^5.1.0"
-            },
-            "engines": {
-                "node": ">=0.10"
-            }
-        },
-        "node_modules/esquery/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esrecurse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-            "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-            "dev": true,
-            "dependencies": {
-                "estraverse": "^5.2.0"
-            },
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esrecurse/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/estraverse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/esutils": {
-            "version": "2.0.3",
-            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/etag": {
-            "version": "1.8.1",
-            "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-            "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/express": {
-            "version": "4.21.1",
-            "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
-            "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
-            "license": "MIT",
-            "dependencies": {
-                "accepts": "~1.3.8",
-                "array-flatten": "1.1.1",
-                "body-parser": "1.20.3",
-                "content-disposition": "0.5.4",
-                "content-type": "~1.0.4",
-                "cookie": "0.7.1",
-                "cookie-signature": "1.0.6",
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "encodeurl": "~2.0.0",
-                "escape-html": "~1.0.3",
-                "etag": "~1.8.1",
-                "finalhandler": "1.3.1",
-                "fresh": "0.5.2",
-                "http-errors": "2.0.0",
-                "merge-descriptors": "1.0.3",
-                "methods": "~1.1.2",
-                "on-finished": "2.4.1",
-                "parseurl": "~1.3.3",
-                "path-to-regexp": "0.1.10",
-                "proxy-addr": "~2.0.7",
-                "qs": "6.13.0",
-                "range-parser": "~1.2.1",
-                "safe-buffer": "5.2.1",
-                "send": "0.19.0",
-                "serve-static": "1.16.2",
-                "setprototypeof": "1.2.0",
-                "statuses": "2.0.1",
-                "type-is": "~1.6.18",
-                "utils-merge": "1.0.1",
-                "vary": "~1.1.2"
-            },
-            "engines": {
-                "node": ">= 0.10.0"
-            }
-        },
-        "node_modules/express/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/express/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
-        },
-        "node_modules/fast-deep-equal": {
-            "version": "3.1.3",
-            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-            "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-            "dev": true
-        },
-        "node_modules/fast-glob": {
-            "version": "3.3.1",
-            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
-            "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
-            "dev": true,
-            "dependencies": {
-                "@nodelib/fs.stat": "^2.0.2",
-                "@nodelib/fs.walk": "^1.2.3",
-                "glob-parent": "^5.1.2",
-                "merge2": "^1.3.0",
-                "micromatch": "^4.0.4"
-            },
-            "engines": {
-                "node": ">=8.6.0"
-            }
-        },
-        "node_modules/fast-glob/node_modules/glob-parent": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-            "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/fast-json-stable-stringify": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-            "dev": true
-        },
-        "node_modules/fast-levenshtein": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-            "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-            "dev": true
-        },
-        "node_modules/fastq": {
-            "version": "1.15.0",
-            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
-            "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
-            "dev": true,
-            "dependencies": {
-                "reusify": "^1.0.4"
-            }
-        },
-        "node_modules/file-entry-cache": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-            "dev": true,
-            "dependencies": {
-                "flat-cache": "^3.0.4"
-            },
-            "engines": {
-                "node": "^10.12.0 || >=12.0.0"
-            }
-        },
-        "node_modules/fill-range": {
-            "version": "7.0.1",
-            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-            "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-            "dependencies": {
-                "to-regex-range": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/finalhandler": {
-            "version": "1.3.1",
-            "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
-            "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
-            "license": "MIT",
-            "dependencies": {
-                "debug": "2.6.9",
-                "encodeurl": "~2.0.0",
-                "escape-html": "~1.0.3",
-                "on-finished": "2.4.1",
-                "parseurl": "~1.3.3",
-                "statuses": "2.0.1",
-                "unpipe": "~1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/finalhandler/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "license": "MIT",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/finalhandler/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-            "license": "MIT"
-        },
-        "node_modules/find-up": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-            "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-            "dev": true,
-            "dependencies": {
-                "locate-path": "^6.0.0",
-                "path-exists": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/flat-cache": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
-            "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
-            "dev": true,
-            "dependencies": {
-                "flatted": "^3.2.9",
-                "keyv": "^4.5.3",
-                "rimraf": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=12.0.0"
-            }
-        },
-        "node_modules/flatted": {
-            "version": "3.2.9",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
-            "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
-            "dev": true
-        },
-        "node_modules/for-each": {
-            "version": "0.3.3",
-            "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-            "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
-            "dev": true,
-            "dependencies": {
-                "is-callable": "^1.1.3"
-            }
-        },
-        "node_modules/forwarded": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-            "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/fresh": {
-            "version": "0.5.2",
-            "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-            "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/fs.realpath": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
-        },
-        "node_modules/fsevents": {
-            "version": "2.3.3",
-            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-            "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-            "hasInstallScript": true,
-            "optional": true,
-            "os": [
-                "darwin"
-            ],
-            "engines": {
-                "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-            }
-        },
-        "node_modules/function-bind": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-            "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/function.prototype.name": {
-            "version": "1.1.6",
-            "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
-            "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "functions-have-names": "^1.2.3"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/functions-have-names": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
-            "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
-            "dev": true,
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/gensync": {
-            "version": "1.0.0-beta.2",
-            "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
-            "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=6.9.0"
-            }
-        },
-        "node_modules/get-intrinsic": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
-            "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
-            "license": "MIT",
-            "dependencies": {
-                "es-errors": "^1.3.0",
-                "function-bind": "^1.1.2",
-                "has-proto": "^1.0.1",
-                "has-symbols": "^1.0.3",
-                "hasown": "^2.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/get-symbol-description": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
-            "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/glob": {
-            "version": "7.2.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-            "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.1.1",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-            },
-            "engines": {
-                "node": "*"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/glob-parent": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-            "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-            "dev": true,
-            "dependencies": {
-                "is-glob": "^4.0.3"
-            },
-            "engines": {
-                "node": ">=10.13.0"
-            }
-        },
-        "node_modules/globals": {
-            "version": "11.12.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-            "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/globalthis": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
-            "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
-            "dev": true,
-            "dependencies": {
-                "define-properties": "^1.1.3"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/globby": {
-            "version": "11.1.0",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-            "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-            "dev": true,
-            "dependencies": {
-                "array-union": "^2.1.0",
-                "dir-glob": "^3.0.1",
-                "fast-glob": "^3.2.9",
-                "ignore": "^5.2.0",
-                "merge2": "^1.4.1",
-                "slash": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/gopd": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
-            "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
-            "dependencies": {
-                "get-intrinsic": "^1.1.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/graphemer": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
-            "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-            "dev": true
-        },
-        "node_modules/has": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
-            "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/has-bigints": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
-            "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
-            "dev": true,
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-flag": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/has-property-descriptors": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
-            "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
-            "license": "MIT",
-            "dependencies": {
-                "es-define-property": "^1.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-proto": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
-            "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-symbols": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-            "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/has-tostringtag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-            "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
-            "dev": true,
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/hasown": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-            "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-            "license": "MIT",
-            "dependencies": {
-                "function-bind": "^1.1.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/http-errors": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
-            "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-            "license": "MIT",
-            "dependencies": {
-                "depd": "2.0.0",
-                "inherits": "2.0.4",
-                "setprototypeof": "1.2.0",
-                "statuses": "2.0.1",
-                "toidentifier": "1.0.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/iconv-lite": {
-            "version": "0.4.24",
-            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-            "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-            "license": "MIT",
-            "dependencies": {
-                "safer-buffer": ">= 2.1.2 < 3"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/ignore": {
-            "version": "5.2.4",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-            "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
-            "dev": true,
-            "engines": {
-                "node": ">= 4"
-            }
-        },
-        "node_modules/import-fresh": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-            "dev": true,
-            "dependencies": {
-                "parent-module": "^1.0.0",
-                "resolve-from": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/imurmurhash": {
-            "version": "0.1.4",
-            "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-            "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.8.19"
-            }
-        },
-        "node_modules/inflight": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-            "dependencies": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-            }
-        },
-        "node_modules/inherits": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-        },
-        "node_modules/internal-slot": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
-            "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
-            "dev": true,
-            "dependencies": {
-                "get-intrinsic": "^1.2.0",
-                "has": "^1.0.3",
-                "side-channel": "^1.0.4"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/ipaddr.js": {
-            "version": "1.9.1",
-            "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-            "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/is-array-buffer": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
-            "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.2.0",
-                "is-typed-array": "^1.1.10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-bigint": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
-            "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
-            "dev": true,
-            "dependencies": {
-                "has-bigints": "^1.0.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-binary-path": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-            "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-            "dependencies": {
-                "binary-extensions": "^2.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/is-boolean-object": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
-            "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-builtin-module": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
-            "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
-            "dev": true,
-            "dependencies": {
-                "builtin-modules": "^3.3.0"
-            },
-            "engines": {
-                "node": ">=6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/is-callable": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
-            "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-core-module": {
-            "version": "2.13.0",
-            "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
-            "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
-            "dependencies": {
-                "has": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-date-object": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
-            "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-            "dev": true,
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-extglob": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-            "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-glob": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-            "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-            "dependencies": {
-                "is-extglob": "^2.1.1"
-            },
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/is-negative-zero": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
-            "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-number": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-            "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-            "engines": {
-                "node": ">=0.12.0"
-            }
-        },
-        "node_modules/is-number-object": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
-            "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
-            "dev": true,
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-path-inside": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
-            "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/is-regex": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
-            "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-shared-array-buffer": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
-            "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-string": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
-            "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
-            "dev": true,
-            "dependencies": {
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-symbol": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-            "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-            "dev": true,
-            "dependencies": {
-                "has-symbols": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-typed-array": {
-            "version": "1.1.12",
-            "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
-            "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
-            "dev": true,
-            "dependencies": {
-                "which-typed-array": "^1.1.11"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/is-weakref": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
-            "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/isarray": {
-            "version": "2.0.5",
-            "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
-            "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
-            "dev": true
-        },
-        "node_modules/isexe": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-            "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
-        },
-        "node_modules/js-tokens": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-            "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/js-yaml": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-            "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-            "dev": true,
-            "dependencies": {
-                "argparse": "^2.0.1"
-            },
-            "bin": {
-                "js-yaml": "bin/js-yaml.js"
-            }
-        },
-        "node_modules/jsdoc-type-pratt-parser": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
-            "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=12.0.0"
-            }
-        },
-        "node_modules/jsesc": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-            "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-            "dev": true,
-            "peer": true,
-            "bin": {
-                "jsesc": "bin/jsesc"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/json-buffer": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-            "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
-            "dev": true
-        },
-        "node_modules/json-schema": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
-            "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
-            "dev": true
-        },
-        "node_modules/json-schema-traverse": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-            "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-            "dev": true
-        },
-        "node_modules/json-stable-stringify-without-jsonify": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-            "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-            "dev": true
-        },
-        "node_modules/json5": {
-            "version": "2.2.3",
-            "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
-            "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
-            "dev": true,
-            "peer": true,
-            "bin": {
-                "json5": "lib/cli.js"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/keyv": {
-            "version": "4.5.4",
-            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
-            "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
-            "dev": true,
-            "dependencies": {
-                "json-buffer": "3.0.1"
-            }
-        },
-        "node_modules/levn": {
-            "version": "0.4.1",
-            "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-            "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "^1.2.1",
-                "type-check": "~0.4.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/locate-path": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-            "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-            "dev": true,
-            "dependencies": {
-                "p-locate": "^5.0.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/lodash.merge": {
-            "version": "4.6.2",
-            "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-            "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-            "dev": true
-        },
-        "node_modules/lru-cache": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-            "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "yallist": "^3.0.2"
-            }
-        },
-        "node_modules/make-error": {
-            "version": "1.3.6",
-            "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-            "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
-        },
-        "node_modules/media-typer": {
-            "version": "0.3.0",
-            "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-            "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/merge-descriptors": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
-            "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
-            "license": "MIT",
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/merge2": {
-            "version": "1.4.1",
-            "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-            "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-            "dev": true,
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/methods": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-            "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/micromatch": {
-            "version": "4.0.5",
-            "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-            "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
-            "dev": true,
-            "dependencies": {
-                "braces": "^3.0.2",
-                "picomatch": "^2.3.1"
-            },
-            "engines": {
-                "node": ">=8.6"
-            }
-        },
-        "node_modules/mime": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-            "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-            "license": "MIT",
-            "bin": {
-                "mime": "cli.js"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/mime-db": {
-            "version": "1.52.0",
-            "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-            "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/mime-types": {
-            "version": "2.1.35",
-            "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-            "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-            "dependencies": {
-                "mime-db": "1.52.0"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/minimatch": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-            "dependencies": {
-                "brace-expansion": "^1.1.7"
-            },
-            "engines": {
-                "node": "*"
-            }
-        },
-        "node_modules/minimist": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-            "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/mkdirp": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-            "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
-            "bin": {
-                "mkdirp": "bin/cmd.js"
-            },
-            "engines": {
-                "node": ">=10"
-            }
-        },
-        "node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        },
-        "node_modules/natural-compare": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-            "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-            "dev": true
-        },
-        "node_modules/natural-compare-lite": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
-            "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
-            "dev": true
-        },
-        "node_modules/negotiator": {
-            "version": "0.6.3",
-            "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-            "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/node-gyp-build": {
-            "version": "4.6.1",
-            "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz",
-            "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==",
-            "optional": true,
-            "bin": {
-                "node-gyp-build": "bin.js",
-                "node-gyp-build-optional": "optional.js",
-                "node-gyp-build-test": "build-test.js"
-            }
-        },
-        "node_modules/node-releases": {
-            "version": "2.0.13",
-            "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
-            "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/normalize-path": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-            "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-assign": {
-            "version": "4.1.1",
-            "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-            "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/object-inspect": {
-            "version": "1.13.1",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
-            "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object-keys": {
-            "version": "1.1.1",
-            "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-            "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/object.assign": {
-            "version": "4.1.4",
-            "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
-            "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.1.4",
-                "has-symbols": "^1.0.3",
-                "object-keys": "^1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.fromentries": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
-            "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/object.groupby": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
-            "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1",
-                "get-intrinsic": "^1.2.1"
-            }
-        },
-        "node_modules/object.values": {
-            "version": "1.1.7",
-            "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
-            "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/on-finished": {
-            "version": "2.4.1",
-            "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-            "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-            "license": "MIT",
-            "dependencies": {
-                "ee-first": "1.1.1"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/once": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-            "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-            "dependencies": {
-                "wrappy": "1"
-            }
-        },
-        "node_modules/optionator": {
-            "version": "0.9.3",
-            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-            "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
-            "dev": true,
-            "dependencies": {
-                "@aashutoshrathi/word-wrap": "^1.2.3",
-                "deep-is": "^0.1.3",
-                "fast-levenshtein": "^2.0.6",
-                "levn": "^0.4.1",
-                "prelude-ls": "^1.2.1",
-                "type-check": "^0.4.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/p-limit": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-            "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-            "dev": true,
-            "dependencies": {
-                "yocto-queue": "^0.1.0"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/p-locate": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-            "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-            "dev": true,
-            "dependencies": {
-                "p-limit": "^3.0.2"
-            },
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/parent-module": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-            "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-            "dev": true,
-            "dependencies": {
-                "callsites": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/parseurl": {
-            "version": "1.3.3",
-            "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-            "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/path-exists": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-            "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/path-is-absolute": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/path-key": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-            "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/path-parse": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-            "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
-        },
-        "node_modules/path-to-regexp": {
-            "version": "0.1.10",
-            "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
-            "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
-            "license": "MIT"
-        },
-        "node_modules/path-type": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/picocolors": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
-            "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/picomatch": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-            "engines": {
-                "node": ">=8.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/jonschlinkert"
-            }
-        },
-        "node_modules/prelude-ls": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-            "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-            "dev": true,
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/prom-client": {
-            "version": "15.0.0",
-            "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.0.0.tgz",
-            "integrity": "sha512-UocpgIrKyA2TKLVZDSfm8rGkL13C19YrQBAiG3xo3aDFWcHedxRxI3z+cIcucoxpSO0h5lff5iv/SXoxyeopeA==",
-            "dependencies": {
-                "@opentelemetry/api": "^1.4.0",
-                "tdigest": "^0.1.1"
-            },
-            "engines": {
-                "node": "^16 || ^18 || >=20"
-            }
-        },
-        "node_modules/proxy-addr": {
-            "version": "2.0.7",
-            "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-            "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-            "dependencies": {
-                "forwarded": "0.2.0",
-                "ipaddr.js": "1.9.1"
-            },
-            "engines": {
-                "node": ">= 0.10"
-            }
-        },
-        "node_modules/punycode": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
-            "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
-            "dev": true,
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/qs": {
-            "version": "6.13.0",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
-            "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
-            "license": "BSD-3-Clause",
-            "dependencies": {
-                "side-channel": "^1.0.6"
-            },
-            "engines": {
-                "node": ">=0.6"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/queue-microtask": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-            "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/range-parser": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-            "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/raw-body": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
-            "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
-            "license": "MIT",
-            "dependencies": {
-                "bytes": "3.1.2",
-                "http-errors": "2.0.0",
-                "iconv-lite": "0.4.24",
-                "unpipe": "1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/readdirp": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-            "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-            "dependencies": {
-                "picomatch": "^2.2.1"
-            },
-            "engines": {
-                "node": ">=8.10.0"
-            }
-        },
-        "node_modules/regexp.prototype.flags": {
-            "version": "1.5.1",
-            "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
-            "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "set-function-name": "^2.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/resolve": {
-            "version": "1.22.8",
-            "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
-            "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
-            "dependencies": {
-                "is-core-module": "^2.13.0",
-                "path-parse": "^1.0.7",
-                "supports-preserve-symlinks-flag": "^1.0.0"
-            },
-            "bin": {
-                "resolve": "bin/resolve"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/resolve-from": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-            "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/reusify": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-            "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-            "dev": true,
-            "engines": {
-                "iojs": ">=1.0.0",
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/rimraf": {
-            "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-            "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/run-parallel": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-            "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "dependencies": {
-                "queue-microtask": "^1.2.2"
-            }
-        },
-        "node_modules/safe-array-concat": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
-            "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.2.1",
-                "has-symbols": "^1.0.3",
-                "isarray": "^2.0.5"
-            },
-            "engines": {
-                "node": ">=0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/safe-buffer": {
-            "version": "5.2.1",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ]
-        },
-        "node_modules/safe-regex-test": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
-            "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.1.3",
-                "is-regex": "^1.1.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/safer-buffer": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-            "license": "MIT"
-        },
-        "node_modules/semver": {
-            "version": "6.3.1",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-            "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-            "dev": true,
-            "bin": {
-                "semver": "bin/semver.js"
-            }
-        },
-        "node_modules/send": {
-            "version": "0.19.0",
-            "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
-            "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
-            "license": "MIT",
-            "dependencies": {
-                "debug": "2.6.9",
-                "depd": "2.0.0",
-                "destroy": "1.2.0",
-                "encodeurl": "~1.0.2",
-                "escape-html": "~1.0.3",
-                "etag": "~1.8.1",
-                "fresh": "0.5.2",
-                "http-errors": "2.0.0",
-                "mime": "1.6.0",
-                "ms": "2.1.3",
-                "on-finished": "2.4.1",
-                "range-parser": "~1.2.1",
-                "statuses": "2.0.1"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/send/node_modules/debug": {
-            "version": "2.6.9",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-            "license": "MIT",
-            "dependencies": {
-                "ms": "2.0.0"
-            }
-        },
-        "node_modules/send/node_modules/debug/node_modules/ms": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-            "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-            "license": "MIT"
-        },
-        "node_modules/send/node_modules/encodeurl": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-            "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/send/node_modules/ms": {
-            "version": "2.1.3",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-            "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-            "license": "MIT"
-        },
-        "node_modules/serve-static": {
-            "version": "1.16.2",
-            "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
-            "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
-            "license": "MIT",
-            "dependencies": {
-                "encodeurl": "~2.0.0",
-                "escape-html": "~1.0.3",
-                "parseurl": "~1.3.3",
-                "send": "0.19.0"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/set-function-length": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
-            "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
-            "license": "MIT",
-            "dependencies": {
-                "define-data-property": "^1.1.4",
-                "es-errors": "^1.3.0",
-                "function-bind": "^1.1.2",
-                "get-intrinsic": "^1.2.4",
-                "gopd": "^1.0.1",
-                "has-property-descriptors": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/set-function-name": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
-            "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
-            "dev": true,
-            "dependencies": {
-                "define-data-property": "^1.0.1",
-                "functions-have-names": "^1.2.3",
-                "has-property-descriptors": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/setprototypeof": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-            "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-            "license": "ISC"
-        },
-        "node_modules/shebang-command": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-            "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-            "dependencies": {
-                "shebang-regex": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/shebang-regex": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-            "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/side-channel": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
-            "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
-            "license": "MIT",
-            "dependencies": {
-                "call-bind": "^1.0.7",
-                "es-errors": "^1.3.0",
-                "get-intrinsic": "^1.2.4",
-                "object-inspect": "^1.13.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/slash": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-            "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/socket.io": {
-            "version": "4.7.2",
-            "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz",
-            "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==",
-            "dependencies": {
-                "accepts": "~1.3.4",
-                "base64id": "~2.0.0",
-                "cors": "~2.8.5",
-                "debug": "~4.3.2",
-                "engine.io": "~6.5.2",
-                "socket.io-adapter": "~2.5.2",
-                "socket.io-parser": "~4.2.4"
-            },
-            "engines": {
-                "node": ">=10.2.0"
-            }
-        },
-        "node_modules/socket.io-adapter": {
-            "version": "2.5.2",
-            "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz",
-            "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==",
-            "dependencies": {
-                "ws": "~8.11.0"
-            }
-        },
-        "node_modules/socket.io-adapter/node_modules/utf-8-validate": {
-            "version": "5.0.10",
-            "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz",
-            "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==",
-            "hasInstallScript": true,
-            "optional": true,
-            "peer": true,
-            "dependencies": {
-                "node-gyp-build": "^4.3.0"
-            },
-            "engines": {
-                "node": ">=6.14.2"
-            }
-        },
-        "node_modules/socket.io-adapter/node_modules/ws": {
-            "version": "8.11.0",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
-            "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
-            "engines": {
-                "node": ">=10.0.0"
-            },
-            "peerDependencies": {
-                "bufferutil": "^4.0.1",
-                "utf-8-validate": "^5.0.2"
-            },
-            "peerDependenciesMeta": {
-                "bufferutil": {
-                    "optional": true
-                },
-                "utf-8-validate": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/socket.io-parser": {
-            "version": "4.2.4",
-            "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
-            "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
-            "dependencies": {
-                "@socket.io/component-emitter": "~3.1.0",
-                "debug": "~4.3.1"
-            },
-            "engines": {
-                "node": ">=10.0.0"
-            }
-        },
-        "node_modules/source-map": {
-            "version": "0.6.1",
-            "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-            "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/source-map-support": {
-            "version": "0.5.21",
-            "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-            "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-            "dependencies": {
-                "buffer-from": "^1.0.0",
-                "source-map": "^0.6.0"
-            }
-        },
-        "node_modules/spdx-exceptions": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-            "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
-            "dev": true
-        },
-        "node_modules/spdx-expression-parse": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-            "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
-            "dev": true,
-            "dependencies": {
-                "spdx-exceptions": "^2.1.0",
-                "spdx-license-ids": "^3.0.0"
-            }
-        },
-        "node_modules/spdx-license-ids": {
-            "version": "3.0.16",
-            "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
-            "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
-            "dev": true
-        },
-        "node_modules/statuses": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
-            "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/string.prototype.trim": {
-            "version": "1.2.8",
-            "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
-            "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimend": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
-            "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/string.prototype.trimstart": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
-            "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "define-properties": "^1.2.0",
-                "es-abstract": "^1.22.1"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/strip-ansi": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-            "dev": true,
-            "dependencies": {
-                "ansi-regex": "^5.0.1"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/strip-bom": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
-            "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/strip-json-comments": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-            "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/supports-color": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-            "dev": true,
-            "peer": true,
-            "dependencies": {
-                "has-flag": "^3.0.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/supports-preserve-symlinks-flag": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-            "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/tdigest": {
-            "version": "0.1.2",
-            "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz",
-            "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==",
-            "dependencies": {
-                "bintrees": "1.0.2"
-            }
-        },
-        "node_modules/text-table": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-            "dev": true
-        },
-        "node_modules/to-fast-properties": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-            "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
-            "dev": true,
-            "peer": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/to-regex-range": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-            "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-            "dependencies": {
-                "is-number": "^7.0.0"
-            },
-            "engines": {
-                "node": ">=8.0"
-            }
-        },
-        "node_modules/toidentifier": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-            "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.6"
-            }
-        },
-        "node_modules/tree-kill": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
-            "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
-            "bin": {
-                "tree-kill": "cli.js"
-            }
-        },
-        "node_modules/ts-api-utils": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
-            "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
-            "dev": true,
-            "engines": {
-                "node": ">=16.13.0"
-            },
-            "peerDependencies": {
-                "typescript": ">=4.2.0"
-            }
-        },
-        "node_modules/ts-node": {
-            "version": "10.9.1",
-            "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
-            "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
-            "dependencies": {
-                "@cspotcode/source-map-support": "^0.8.0",
-                "@tsconfig/node10": "^1.0.7",
-                "@tsconfig/node12": "^1.0.7",
-                "@tsconfig/node14": "^1.0.0",
-                "@tsconfig/node16": "^1.0.2",
-                "acorn": "^8.4.1",
-                "acorn-walk": "^8.1.1",
-                "arg": "^4.1.0",
-                "create-require": "^1.1.0",
-                "diff": "^4.0.1",
-                "make-error": "^1.1.1",
-                "v8-compile-cache-lib": "^3.0.1",
-                "yn": "3.1.1"
-            },
-            "bin": {
-                "ts-node": "dist/bin.js",
-                "ts-node-cwd": "dist/bin-cwd.js",
-                "ts-node-esm": "dist/bin-esm.js",
-                "ts-node-script": "dist/bin-script.js",
-                "ts-node-transpile-only": "dist/bin-transpile.js",
-                "ts-script": "dist/bin-script-deprecated.js"
-            },
-            "peerDependencies": {
-                "@swc/core": ">=1.2.50",
-                "@swc/wasm": ">=1.2.50",
-                "@types/node": "*",
-                "typescript": ">=2.7"
-            },
-            "peerDependenciesMeta": {
-                "@swc/core": {
-                    "optional": true
-                },
-                "@swc/wasm": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/ts-node-dev": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
-            "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
-            "dependencies": {
-                "chokidar": "^3.5.1",
-                "dynamic-dedupe": "^0.3.0",
-                "minimist": "^1.2.6",
-                "mkdirp": "^1.0.4",
-                "resolve": "^1.0.0",
-                "rimraf": "^2.6.1",
-                "source-map-support": "^0.5.12",
-                "tree-kill": "^1.2.2",
-                "ts-node": "^10.4.0",
-                "tsconfig": "^7.0.0"
-            },
-            "bin": {
-                "ts-node-dev": "lib/bin.js",
-                "tsnd": "lib/bin.js"
-            },
-            "engines": {
-                "node": ">=0.8.0"
-            },
-            "peerDependencies": {
-                "node-notifier": "*",
-                "typescript": "*"
-            },
-            "peerDependenciesMeta": {
-                "node-notifier": {
-                    "optional": true
-                }
-            }
-        },
-        "node_modules/ts-node-dev/node_modules/rimraf": {
-            "version": "2.7.1",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-            "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
-            }
-        },
-        "node_modules/tsconfig": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
-            "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
-            "dependencies": {
-                "@types/strip-bom": "^3.0.0",
-                "@types/strip-json-comments": "0.0.30",
-                "strip-bom": "^3.0.0",
-                "strip-json-comments": "^2.0.0"
-            }
-        },
-        "node_modules/tsconfig-paths": {
-            "version": "3.14.2",
-            "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
-            "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
-            "dev": true,
-            "dependencies": {
-                "@types/json5": "^0.0.29",
-                "json5": "^1.0.2",
-                "minimist": "^1.2.6",
-                "strip-bom": "^3.0.0"
-            }
-        },
-        "node_modules/tsconfig-paths/node_modules/json5": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
-            "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
-            "dev": true,
-            "dependencies": {
-                "minimist": "^1.2.0"
-            },
-            "bin": {
-                "json5": "lib/cli.js"
-            }
-        },
-        "node_modules/tsconfig/node_modules/strip-json-comments": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-            "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
-        "node_modules/tslib": {
-            "version": "1.14.1",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-            "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-            "dev": true
-        },
-        "node_modules/tsutils": {
-            "version": "3.21.0",
-            "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
-            "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
-            "dev": true,
-            "dependencies": {
-                "tslib": "^1.8.1"
-            },
-            "engines": {
-                "node": ">= 6"
-            },
-            "peerDependencies": {
-                "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
-            }
-        },
-        "node_modules/type-check": {
-            "version": "0.4.0",
-            "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-            "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-            "dev": true,
-            "dependencies": {
-                "prelude-ls": "^1.2.1"
-            },
-            "engines": {
-                "node": ">= 0.8.0"
-            }
-        },
-        "node_modules/type-fest": {
-            "version": "0.20.2",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
-        "node_modules/type-is": {
-            "version": "1.6.18",
-            "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-            "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-            "license": "MIT",
-            "dependencies": {
-                "media-typer": "0.3.0",
-                "mime-types": "~2.1.24"
-            },
-            "engines": {
-                "node": ">= 0.6"
-            }
-        },
-        "node_modules/typed-array-buffer": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
-            "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "get-intrinsic": "^1.2.1",
-                "is-typed-array": "^1.1.10"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
-        "node_modules/typed-array-byte-length": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
-            "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "has-proto": "^1.0.1",
-                "is-typed-array": "^1.1.10"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/typed-array-byte-offset": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
-            "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
-            "dev": true,
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "has-proto": "^1.0.1",
-                "is-typed-array": "^1.1.10"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/typed-array-length": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
-            "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "is-typed-array": "^1.1.9"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/typescript": {
-            "version": "5.2.2",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
-            "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
-            "bin": {
-                "tsc": "bin/tsc",
-                "tsserver": "bin/tsserver"
-            },
-            "engines": {
-                "node": ">=14.17"
-            }
-        },
-        "node_modules/unbox-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
-            "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
-            "dev": true,
-            "dependencies": {
-                "call-bind": "^1.0.2",
-                "has-bigints": "^1.0.2",
-                "has-symbols": "^1.0.3",
-                "which-boxed-primitive": "^1.0.2"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/undici-types": {
-            "version": "5.25.3",
-            "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz",
-            "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA=="
-        },
-        "node_modules/unpipe": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-            "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
-            "license": "MIT",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/update-browserslist-db": {
-            "version": "1.0.13",
-            "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
-            "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
-            "dev": true,
-            "funding": [
-                {
-                    "type": "opencollective",
-                    "url": "https://opencollective.com/browserslist"
-                },
-                {
-                    "type": "tidelift",
-                    "url": "https://tidelift.com/funding/github/npm/browserslist"
-                },
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/ai"
-                }
-            ],
-            "peer": true,
-            "dependencies": {
-                "escalade": "^3.1.1",
-                "picocolors": "^1.0.0"
-            },
-            "bin": {
-                "update-browserslist-db": "cli.js"
-            },
-            "peerDependencies": {
-                "browserslist": ">= 4.21.0"
-            }
-        },
-        "node_modules/uri-js": {
-            "version": "4.4.1",
-            "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-            "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-            "dev": true,
-            "dependencies": {
-                "punycode": "^2.1.0"
-            }
-        },
-        "node_modules/utf-8-validate": {
-            "version": "6.0.3",
-            "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.3.tgz",
-            "integrity": "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==",
-            "hasInstallScript": true,
-            "optional": true,
-            "dependencies": {
-                "node-gyp-build": "^4.3.0"
-            },
-            "engines": {
-                "node": ">=6.14.2"
-            }
-        },
-        "node_modules/utils-merge": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-            "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
-            "engines": {
-                "node": ">= 0.4.0"
-            }
-        },
-        "node_modules/v8-compile-cache-lib": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-            "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="
-        },
-        "node_modules/vary": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-            "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
-            "engines": {
-                "node": ">= 0.8"
-            }
-        },
-        "node_modules/which": {
-            "version": "2.0.2",
-            "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-            "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-            "dependencies": {
-                "isexe": "^2.0.0"
-            },
-            "bin": {
-                "node-which": "bin/node-which"
-            },
-            "engines": {
-                "node": ">= 8"
-            }
-        },
-        "node_modules/which-boxed-primitive": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-            "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-            "dev": true,
-            "dependencies": {
-                "is-bigint": "^1.0.1",
-                "is-boolean-object": "^1.1.0",
-                "is-number-object": "^1.0.4",
-                "is-string": "^1.0.5",
-                "is-symbol": "^1.0.3"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/which-typed-array": {
-            "version": "1.1.11",
-            "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
-            "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
-            "dev": true,
-            "dependencies": {
-                "available-typed-arrays": "^1.0.5",
-                "call-bind": "^1.0.2",
-                "for-each": "^0.3.3",
-                "gopd": "^1.0.1",
-                "has-tostringtag": "^1.0.0"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
-            }
-        },
-        "node_modules/wrappy": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-            "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
-        },
-        "node_modules/xtend": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
-            "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
-            "engines": {
-                "node": ">=0.4"
-            }
-        },
-        "node_modules/yallist": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-            "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-            "dev": true,
-            "peer": true
-        },
-        "node_modules/yn": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-            "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-            "engines": {
-                "node": ">=6"
-            }
-        },
-        "node_modules/yocto-queue": {
-            "version": "0.1.0",
-            "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-            "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        }
-    }
-}
diff --git a/infrastructure/excalidraw-backend/build.py b/infrastructure/excalidraw/build.py
similarity index 97%
rename from infrastructure/excalidraw-backend/build.py
rename to infrastructure/excalidraw/build.py
index 6dcb8b9..40e5f08 100644
--- a/infrastructure/excalidraw-backend/build.py
+++ b/infrastructure/excalidraw/build.py
@@ -4,7 +4,7 @@ from pybuilder.core import task, init
 from ddadevops import *
 
 name = "c4k-jitsi"
-MODULE = "excalidraw-backend"
+MODULE = "excalidraw"
 PROJECT_ROOT_PATH = "../.."
 version = "2.2.1-dev"
 
diff --git a/infrastructure/excalidraw-backend/image/Dockerfile b/infrastructure/excalidraw/image/Dockerfile
similarity index 100%
rename from infrastructure/excalidraw-backend/image/Dockerfile
rename to infrastructure/excalidraw/image/Dockerfile
diff --git a/infrastructure/excalidraw-backend/image/resources/install.sh b/infrastructure/excalidraw/image/resources/install.sh
similarity index 100%
rename from infrastructure/excalidraw-backend/image/resources/install.sh
rename to infrastructure/excalidraw/image/resources/install.sh
diff --git a/infrastructure/excalidraw-backend/image/resources/package.json b/infrastructure/excalidraw/image/resources/package.json
similarity index 100%
rename from infrastructure/excalidraw-backend/image/resources/package.json
rename to infrastructure/excalidraw/image/resources/package.json
diff --git a/infrastructure/excalidraw-backend/image/resources/src/.eslintrc.js b/infrastructure/excalidraw/image/resources/src/.eslintrc.js
similarity index 100%
rename from infrastructure/excalidraw-backend/image/resources/src/.eslintrc.js
rename to infrastructure/excalidraw/image/resources/src/.eslintrc.js
diff --git a/infrastructure/excalidraw-backend/image/resources/src/index.ts b/infrastructure/excalidraw/image/resources/src/index.ts
similarity index 100%
rename from infrastructure/excalidraw-backend/image/resources/src/index.ts
rename to infrastructure/excalidraw/image/resources/src/index.ts
diff --git a/infrastructure/excalidraw-backend/image/resources/tsconfig.json b/infrastructure/excalidraw/image/resources/tsconfig.json
similarity index 100%
rename from infrastructure/excalidraw-backend/image/resources/tsconfig.json
rename to infrastructure/excalidraw/image/resources/tsconfig.json

From 2d16564b9c5bfd316d391913ef6e18b93d5fac7d Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 12:57:29 +0100
Subject: [PATCH 26/33] add image build to pipeline

---
 .gitlab-ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index add1a92..6890274 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -116,9 +116,9 @@ release-to-forgejo:
   script:
     - pyb publish_artifacts
 
-jitsi-web-image-publish:
+jitsi-excalidraw-image-publish:
   <<: *img
   <<: *tag_only
   stage: image
   script:
-    - cd infrastructure/web && pyb image publish
+    - cd infrastructure/excalidraw && pyb image publish

From a00b4e2732b9f58ad503655b984baee9c154b1dc Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 13:06:00 +0100
Subject: [PATCH 27/33] finish rename

---
 .gitignore                                                 | 1 +
 src/main/resources/jitsi/excalidraw-config-deployment.yaml | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index bb41ea4..3c6cc35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ config.edn
 out.yaml
 .eastwood
 tmp/
+.envrc
diff --git a/src/main/resources/jitsi/excalidraw-config-deployment.yaml b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
index b3565cf..80bf62b 100644
--- a/src/main/resources/jitsi/excalidraw-config-deployment.yaml
+++ b/src/main/resources/jitsi/excalidraw-config-deployment.yaml
@@ -17,4 +17,4 @@ spec:
     spec:
       containers:
         - name: excalidraw
-          image: domaindrivenarchitecture/c4k-jitsi-excalidraw-backend
\ No newline at end of file
+          image: domaindrivenarchitecture/c4k-jitsi-excalidraw
\ No newline at end of file

From 67acfef5638a9ed1832492baa74f8ce02e0fd82b Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 14:39:09 +0100
Subject: [PATCH 28/33] add restart ability - wip

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  1 +
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        |  9 ++++++
 .../jitsi/restart-config-authorization.yaml   | 11 +++++++
 .../resources/jitsi/restart-config-cron.yaml  | 25 +++++++++++++++
 .../jitsi/restart-config-rolebinding.yaml     | 13 ++++++++
 .../jitsi/restart-config-serviceaccount.yaml  |  5 +++
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   | 32 +++++++++++++++++++
 7 files changed, 96 insertions(+)
 create mode 100644 src/main/resources/jitsi/restart-config-authorization.yaml
 create mode 100644 src/main/resources/jitsi/restart-config-cron.yaml
 create mode 100644 src/main/resources/jitsi/restart-config-rolebinding.yaml
 create mode 100644 src/main/resources/jitsi/restart-config-serviceaccount.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 5ab6ffb..9eb7149 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -40,6 +40,7 @@
            (jitsi/web-config resolved-config)
            (jitsi/jvb-config resolved-config)
            (jitsi/jibri-config resolved-config)
+           (jitsi/restart-config resolved-config)
            (jitsi/etherpad-config resolved-config)
            (jitsi/excalidraw-config resolved-config)
            (jitsi/moderator-elector-config resolved-config)
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 4a12889..bdaba1d 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -117,6 +117,15 @@
      (load-and-adjust-namespace "jitsi/jibri-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/jibri-config-deployment.yaml" namespace)]))
 
+(defn-spec restart-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace]} config]
+    [(load-and-adjust-namespace "jitsi/restart-config-serviceaccount.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/restart-config-rolebinding.yaml" namespace)
+     (-> 
+      (load-and-adjust-namespace "jitsi/restart-config-authorization.yaml" namespace)
+      (cm/replace-key-value :resourceNames ["etherpad", "excalidraw"]))]))
+
 (defn-spec etherpad-config cp/map-or-seq?
   [config config?]
   (let [{:keys [namespace]} config]
diff --git a/src/main/resources/jitsi/restart-config-authorization.yaml b/src/main/resources/jitsi/restart-config-authorization.yaml
new file mode 100644
index 0000000..e414cef
--- /dev/null
+++ b/src/main/resources/jitsi/restart-config-authorization.yaml
@@ -0,0 +1,11 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: deployment-restart
+  namespace: NAMESPACE
+rules:
+  - apiGroups: ["apps", "extensions"]
+    resources: ["deployments"]
+    resourceNames: REPLACE_ME
+    verbs: ["get", "patch", "list", "watch"] # "list" and "watch" are only needed
+                                             # if you want to use `rollout status
\ No newline at end of file
diff --git a/src/main/resources/jitsi/restart-config-cron.yaml b/src/main/resources/jitsi/restart-config-cron.yaml
new file mode 100644
index 0000000..a96b3c4
--- /dev/null
+++ b/src/main/resources/jitsi/restart-config-cron.yaml
@@ -0,0 +1,25 @@
+apiVersion: batch/v1
+kind: CronJob
+metadata:
+  name: deployment-restart
+  namespace: NAMESPACE
+spec:
+  concurrencyPolicy: Forbid
+  schedule: SCHEDULE_REPLACE_Me
+  jobTemplate:
+    spec:
+      backoffLimit: 2
+      activeDeadlineSeconds: 600
+      template:
+        spec:
+          serviceAccountName: deployment-restart
+          restartPolicy: Never
+          containers:
+            - name: kubectl
+              image: bitnami/kubectl
+          command:
+          - bash
+          - -c
+          - >-
+            kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> &&
+            kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>
diff --git a/src/main/resources/jitsi/restart-config-rolebinding.yaml b/src/main/resources/jitsi/restart-config-rolebinding.yaml
new file mode 100644
index 0000000..c02b472
--- /dev/null
+++ b/src/main/resources/jitsi/restart-config-rolebinding.yaml
@@ -0,0 +1,13 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: deployment-restart
+  namespace: NAMESPACE
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: deployment-restart
+subjects:
+  - kind: ServiceAccount
+    name: deployment-restart
+    namespace: NAMESPACE
\ No newline at end of file
diff --git a/src/main/resources/jitsi/restart-config-serviceaccount.yaml b/src/main/resources/jitsi/restart-config-serviceaccount.yaml
new file mode 100644
index 0000000..2a6c665
--- /dev/null
+++ b/src/main/resources/jitsi/restart-config-serviceaccount.yaml
@@ -0,0 +1,5 @@
+kind: ServiceAccount
+apiVersion: v1
+metadata:
+  name: deployment-restart
+  namespace: NAMESPACE
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index d4dd47f..071e4bc 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -110,3 +110,35 @@
          (count (cut/moderator-elector-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
+
+(deftest should-generate-restart
+  (is (= {:apiVersion "rbac.authorization.k8s.io/v1",
+          :kind "RoleBinding",
+          :metadata {:name "deployment-restart", :namespace "jitsi"},
+          :roleRef
+          {:apiGroup "rbac.authorization.k8s.io",
+           :kind "Role",
+           :name "deployment-restart"},
+          :subjects
+          [{:kind "ServiceAccount",
+            :name "deployment-restart",
+            :namespace "jitsi"}]}
+         (second (cut/restart-config
+                  {:fqdn "xy.xy.xy"
+                   :namespace "jitsi"}))))
+  (is (= {:apiVersion "rbac.authorization.k8s.io/v1",
+          :kind "Role",
+          :metadata {:name "deployment-restart", :namespace "jitsi"},
+          :rules
+          [{:apiGroups ["apps" "extensions"],
+            :resources ["deployments"],
+            :resourceNames ["etherpad" "excalidraw"],
+            :verbs ["get" "patch" "list" "watch"]}]}
+         (nth (cut/restart-config
+               {:fqdn "xy.xy.xy"
+                :namespace "jitsi"})
+              2)))
+  (is (= 3
+         (count (cut/restart-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"})))))

From 8159f85158358a5169514163999a8c96a1da10d8 Mon Sep 17 00:00:00 2001
From: zam <mirco.zachmann@meissa.de>
Date: Tue, 18 Feb 2025 14:59:13 +0100
Subject: [PATCH 29/33] restart-config-cron

---
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc      |  7 ++++--
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc | 25 ++++++++++++++++++++-
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index bdaba1d..7841dea 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -122,9 +122,12 @@
   (let [{:keys [namespace]} config]
     [(load-and-adjust-namespace "jitsi/restart-config-serviceaccount.yaml" namespace)
      (load-and-adjust-namespace "jitsi/restart-config-rolebinding.yaml" namespace)
-     (-> 
+     (->
       (load-and-adjust-namespace "jitsi/restart-config-authorization.yaml" namespace)
-      (cm/replace-key-value :resourceNames ["etherpad", "excalidraw"]))]))
+      (cm/replace-key-value :resourceNames ["etherpad", "excalidraw"]))
+     (->
+      (load-and-adjust-namespace "jitsi/restart-config-cron.yaml" namespace)
+      (cm/replace-key-value :resourceNames))]))
 
 (defn-spec etherpad-config cp/map-or-seq?
   [config config?]
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 071e4bc..252fef0 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -138,7 +138,30 @@
                {:fqdn "xy.xy.xy"
                 :namespace "jitsi"})
               2)))
-  (is (= 3
+  (is (= {:apiVersion "batch/v1",
+          :kind "CronJob",
+          :metadata {:name "deployment-restart", :namespace "jitsi"},
+          :spec
+          {:concurrencyPolicy "Forbid",
+           :schedule "SCHEDULE_REPLACE_Me",
+           :jobTemplate
+           {:spec
+            {:backoffLimit 2,
+             :activeDeadlineSeconds 600,
+             :template
+             {:spec
+              {:serviceAccountName "deployment-restart",
+               :restartPolicy "Never",
+               :containers [{:name "kubectl", :image "bitnami/kubectl"}],
+               :command
+               ["bash"
+                "-c"
+                "kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> && kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>"]}}}}}}
+         (nth (cut/restart-config
+               {:fqdn "xy.xy.xy"
+                :namespace "jitsi"})
+              3)))
+  (is (= 4
          (count (cut/restart-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))

From 80acabff9ba56fe0d6624b67ba1b9c136244b22d Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 15:13:05 +0100
Subject: [PATCH 30/33] restart cron now might work

---
 src/main/cljc/dda/c4k_jitsi/core.cljc           |  2 +-
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc          | 17 ++++++++++++++++-
 .../resources/jitsi/restart-config-cron.yaml    | 11 +++--------
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc     |  8 ++++----
 4 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 9eb7149..a7c92ee 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -39,7 +39,7 @@
            (jitsi/jicofo-config resolved-config)
            (jitsi/web-config resolved-config)
            (jitsi/jvb-config resolved-config)
-           (jitsi/jibri-config resolved-config)
+           ;(jitsi/jibri-config resolved-config)
            (jitsi/restart-config resolved-config)
            (jitsi/etherpad-config resolved-config)
            (jitsi/excalidraw-config resolved-config)
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index 7841dea..d8f0f8f 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -127,7 +127,22 @@
       (cm/replace-key-value :resourceNames ["etherpad", "excalidraw"]))
      (->
       (load-and-adjust-namespace "jitsi/restart-config-cron.yaml" namespace)
-      (cm/replace-key-value :resourceNames))]))
+      (cm/replace-all-matching "CRON_NAME" "restart-etherpad")
+      (cm/replace-key-value :schedule "0 2 * * *")
+      (cm/replace-key-value 
+       :command 
+       ["bash"
+        "-c"
+        "kubectl rollout restart deployment/etherpad && kubectl rollout status deployment/etherpad"]))
+     (->
+      (load-and-adjust-namespace "jitsi/restart-config-cron.yaml" namespace)
+      (cm/replace-all-matching "CRON_NAME" "restart-excalidraw")
+      (cm/replace-key-value :schedule "0 1 * * *")
+      (cm/replace-key-value
+       :command
+       ["bash"
+        "-c"
+        "kubectl rollout restart deployment/excalidraw && kubectl rollout status deployment/excalidraw"]))]))
 
 (defn-spec etherpad-config cp/map-or-seq?
   [config config?]
diff --git a/src/main/resources/jitsi/restart-config-cron.yaml b/src/main/resources/jitsi/restart-config-cron.yaml
index a96b3c4..2df74a9 100644
--- a/src/main/resources/jitsi/restart-config-cron.yaml
+++ b/src/main/resources/jitsi/restart-config-cron.yaml
@@ -1,11 +1,11 @@
 apiVersion: batch/v1
 kind: CronJob
 metadata:
-  name: deployment-restart
+  name: CRON_NAME
   namespace: NAMESPACE
 spec:
   concurrencyPolicy: Forbid
-  schedule: SCHEDULE_REPLACE_Me
+  schedule: SCHEDULE_REPLACE_ME
   jobTemplate:
     spec:
       backoffLimit: 2
@@ -17,9 +17,4 @@ spec:
           containers:
             - name: kubectl
               image: bitnami/kubectl
-          command:
-          - bash
-          - -c
-          - >-
-            kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> &&
-            kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>
+          command: COMMAND_REPLACE_ME
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 252fef0..8a65e0d 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -140,10 +140,10 @@
               2)))
   (is (= {:apiVersion "batch/v1",
           :kind "CronJob",
-          :metadata {:name "deployment-restart", :namespace "jitsi"},
+          :metadata {:name "restart-etherpad", :namespace "jitsi"},
           :spec
           {:concurrencyPolicy "Forbid",
-           :schedule "SCHEDULE_REPLACE_Me",
+           :schedule "0 2 * * *",
            :jobTemplate
            {:spec
             {:backoffLimit 2,
@@ -156,12 +156,12 @@
                :command
                ["bash"
                 "-c"
-                "kubectl rollout restart deployment/<YOUR DEPLOYMENT NAME> && kubectl rollout status deployment/<YOUR DEPLOYMENT NAME>"]}}}}}}
+                "kubectl rollout restart deployment/etherpad && kubectl rollout status deployment/etherpad"]}}}}}}
          (nth (cut/restart-config
                {:fqdn "xy.xy.xy"
                 :namespace "jitsi"})
               3)))
-  (is (= 4
+  (is (= 5
          (count (cut/restart-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))

From b274335d629541958425efca5aa7990c9d1f33dc Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Tue, 18 Feb 2025 15:27:54 +0100
Subject: [PATCH 31/33] fix command

---
 src/main/resources/jitsi/restart-config-cron.yaml |  2 +-
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc       | 11 ++++++-----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/main/resources/jitsi/restart-config-cron.yaml b/src/main/resources/jitsi/restart-config-cron.yaml
index 2df74a9..72f1b28 100644
--- a/src/main/resources/jitsi/restart-config-cron.yaml
+++ b/src/main/resources/jitsi/restart-config-cron.yaml
@@ -17,4 +17,4 @@ spec:
           containers:
             - name: kubectl
               image: bitnami/kubectl
-          command: COMMAND_REPLACE_ME
+              command: COMMAND_REPLACE_ME
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 8a65e0d..04d31d3 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -152,11 +152,12 @@
              {:spec
               {:serviceAccountName "deployment-restart",
                :restartPolicy "Never",
-               :containers [{:name "kubectl", :image "bitnami/kubectl"}],
-               :command
-               ["bash"
-                "-c"
-                "kubectl rollout restart deployment/etherpad && kubectl rollout status deployment/etherpad"]}}}}}}
+               :containers 
+               [{:name "kubectl", :image "bitnami/kubectl",
+                 :command
+                 ["bash"
+                  "-c"
+                  "kubectl rollout restart deployment/etherpad && kubectl rollout status deployment/etherpad"]}]}}}}}}
          (nth (cut/restart-config
                {:fqdn "xy.xy.xy"
                 :namespace "jitsi"})

From 56366785aa196340dc8cccee43d0d11262a0e34b Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 20 Feb 2025 15:23:16 +0100
Subject: [PATCH 32/33] add stun server

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  2 +
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        | 35 ++++++++-
 .../resources/jitsi/coturn-auth-secret.yaml   | 10 +++
 .../jitsi/coturn-config-default-cm.yaml       | 10 +++
 .../jitsi/coturn-config-deployment.yaml       | 72 +++++++++++++++++++
 .../jitsi/coturn-config-init-cm.yaml          | 20 ++++++
 .../jitsi/coturn-config-tcp-service.yaml      | 23 ++++++
 .../jitsi/coturn-config-udp-service.yaml      | 23 ++++++
 .../resources/jitsi/jvb-config-envs-cm.yaml   |  2 +-
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   | 25 +++++++
 10 files changed, 220 insertions(+), 2 deletions(-)
 create mode 100644 src/main/resources/jitsi/coturn-auth-secret.yaml
 create mode 100644 src/main/resources/jitsi/coturn-config-default-cm.yaml
 create mode 100644 src/main/resources/jitsi/coturn-config-deployment.yaml
 create mode 100644 src/main/resources/jitsi/coturn-config-init-cm.yaml
 create mode 100644 src/main/resources/jitsi/coturn-config-tcp-service.yaml
 create mode 100644 src/main/resources/jitsi/coturn-config-udp-service.yaml

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index a7c92ee..1f09cd9 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -44,6 +44,7 @@
            (jitsi/etherpad-config resolved-config)
            (jitsi/excalidraw-config resolved-config)
            (jitsi/moderator-elector-config resolved-config)
+           (jitsi/coturn-config resolved-config)
            (ing/generate-ingress-and-cert (merge
                                            {:service-name "jitsi-meet-web"
                                             :service-port 80
@@ -76,5 +77,6 @@
         #(not (nil? %))
         (cm/concat-vec
          (jitsi/prosody-auth config auth)
+         (jitsi/coturn-auth config auth)
          (when (:contains? config :mon-cfg)
            (mon/generate-auth (:mon-cfg config) (:mon-auth auth))))))))
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index d8f0f8f..b59c9af 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -3,6 +3,7 @@
    [clojure.spec.alpha :as s]
    #?(:clj [orchestra.core :refer [defn-spec]]
       :cljs [orchestra.core :refer-macros [defn-spec]])
+   [clojure.string :as st]
    [dda.c4k-common.yaml :as yaml]
    [dda.c4k-common.common :as cm]
    [dda.c4k-common.base64 :as b64]
@@ -98,7 +99,8 @@
   (let [{:keys [fqdn namespace]} config]
     [(-> 
       (load-and-adjust-namespace "jitsi/jvb-config-envs-cm.yaml" namespace)
-      (cm/replace-key-value :XMPP_SERVER (str "prosody." namespace ".svc.cluster.local")))
+      (cm/replace-key-value :XMPP_SERVER (str "prosody." namespace ".svc.cluster.local"))
+      (cm/replace-key-value :JVB_STUN_SERVERS (str "stun." fqdn ":443")))
      (load-and-adjust-namespace "jitsi/jvb-config-service.yaml" namespace)
      (->
       (load-and-adjust-namespace "jitsi/jvb-config-deployment.yaml" namespace)
@@ -161,3 +163,34 @@
   (let [{:keys [namespace]} config]
     [(load-and-adjust-namespace "jitsi/modelector-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/modelector-config-deployment.yaml" namespace)]))
+
+(defn-spec coturn-auth cp/map-or-seq?
+  [config config?
+   auth auth?]
+  (let [{:keys [namespace]} config
+        {:keys []} auth]
+    [(load-and-adjust-namespace "jitsi/coturn-auth-secret.yaml" namespace)]))
+  
+(defn-spec coturn-config cp/map-or-seq?
+  [config config?]
+  (let [{:keys [namespace fqdn]} config]
+    [(load-and-adjust-namespace "jitsi/coturn-config-default-cm.yaml" namespace)
+     (-> 
+      (load-and-adjust-namespace "jitsi/coturn-config-init-cm.yaml" namespace)
+      (cm/replace-key-value
+       :data
+       {:turnserver.conf
+        (st/join "\n" [(str "realm: stun." fqdn)
+                       "listening-ip: 0.0.0.0"
+                       "listening-port: 3478"
+                       "tls-listening-port: 5349"
+                       "min-port: 49152"
+                       "max-port: 65535"
+                       "log-file: stdout"
+                       "pidfile: \"/var/tmp/turnserver.pid\""
+                       "pkey: \"/tls/tls.key\""
+                       "cert: \"/tls/tls.crt\""
+                       "userdb: \"/var/db/turndb\""])}))
+     (load-and-adjust-namespace "jitsi/coturn-config-tcp-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/coturn-config-udp-service.yaml" namespace)
+     (load-and-adjust-namespace "jitsi/coturn-config-deployment.yaml" namespace)]))
diff --git a/src/main/resources/jitsi/coturn-auth-secret.yaml b/src/main/resources/jitsi/coturn-auth-secret.yaml
new file mode 100644
index 0000000..93223f2
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-auth-secret.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  namespace: NAMESPACE
+  name: coturn-auth-secret
+  labels:
+    app.kubernetes.io/name: "coturn"
+data:
+  username: ""
+  password: ""
\ No newline at end of file
diff --git a/src/main/resources/jitsi/coturn-config-default-cm.yaml b/src/main/resources/jitsi/coturn-config-default-cm.yaml
new file mode 100644
index 0000000..677a970
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-config-default-cm.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: NAMESPACE
+  name: coturn-extra-config
+  labels:
+    app.kubernetes.io/name: "coturn"
+data:
+  turnserver.conf: |
+      verbose
diff --git a/src/main/resources/jitsi/coturn-config-deployment.yaml b/src/main/resources/jitsi/coturn-config-deployment.yaml
new file mode 100644
index 0000000..f8379fe
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-config-deployment.yaml
@@ -0,0 +1,72 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  namespace: NAMESPACE
+  name: coturn-coturn
+  labels:
+    app.kubernetes.io/name: "coturn"
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: coturn
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: coturn
+    spec:
+      securityContext:
+        runAsNonRoot: true
+        runAsUser: 1000
+        runAsGroup: 1000
+        fsGroup: 1000
+        seccompProfile:
+          type: RuntimeDefault
+      containers:
+        - name: "coturn"
+          image: coturn/coturn:4.6.3
+          imagePullPolicy: IfNotPresent
+          args: ["-c", "/turnserver.conf"]
+          ports:
+            - name: turn-udp
+              containerPort: 3478
+              protocol: UDP
+            - name: turn-tcp
+              containerPort: 3478
+              protocol: TCP
+            - name: turn-tcp-tls
+              containerPort: 5349
+              protocol: TCP
+            - name: turn-udp-dtls
+              containerPort: 5349
+              protocol: UDP
+          volumeMounts:
+            - name: coturn-config
+              mountPath: "/turnserver.conf"
+              subPath: turnserver.conf
+              readOnly: true
+            - name: var-tmp
+              mountPath: /var/tmp
+            - name: sqllite
+              mountPath: /var/db
+          securityContext:
+            capabilities:
+              add:
+                - NET_BIND_SERVICE
+              drop:
+                - ALL
+            readOnlyRootFilesystem: false
+            allowPrivilegeEscalation: false
+      volumes:
+        - name: coturn-initial-config
+          configMap:
+            name: coturn-initial-config
+        - name: coturn-extra-config
+          configMap:
+            name: coturn-extra-config
+        - name: coturn-config
+          emptyDir: {}
+        - name: var-tmp
+          emptyDir: {}
+        - name: sqllite
+          emptyDir: {}
diff --git a/src/main/resources/jitsi/coturn-config-init-cm.yaml b/src/main/resources/jitsi/coturn-config-init-cm.yaml
new file mode 100644
index 0000000..c3f8504
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-config-init-cm.yaml
@@ -0,0 +1,20 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: NAMESPACE
+  name: coturn-initial-config
+  labels:
+    app.kubernetes.io/name: "coturn"
+data:
+  turnserver.conf: |-
+    realm: REPLACE_COTURN_FQDN
+    listening-ip: 0.0.0.0
+    listening-port: 3478
+    tls-listening-port: 5349
+    min-port: 49152
+    max-port: 65535
+    log-file: stdout
+    pidfile: "/var/tmp/turnserver.pid"
+    pkey: "/tls/tls.key"
+    cert: "/tls/tls.crt"
+    userdb: "/var/db/turndb"
\ No newline at end of file
diff --git a/src/main/resources/jitsi/coturn-config-tcp-service.yaml b/src/main/resources/jitsi/coturn-config-tcp-service.yaml
new file mode 100644
index 0000000..c255a57
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-config-tcp-service.yaml
@@ -0,0 +1,23 @@
+apiVersion: v1
+kind: Service
+metadata:
+  namespace: NAMESPACE
+  name: coturn-turn-tcp
+  labels:
+    app.kubernetes.io/name: "coturn"
+  annotations:
+    metallb.universe.tf/allow-shared-ip: "shared-ip-service-group"
+    metallb.universe.tf/address-pool: public
+spec:
+  type: LoadBalancer
+  ports:
+    - name: turn-tcp
+      port: 3478
+      protocol: TCP
+      targetPort: 3478
+    - name: turn-tcp-tls
+      port: 5349
+      protocol: TCP
+      targetPort: 5349
+  selector:
+    app.kubernetes.io/name: coturn-coturn
\ No newline at end of file
diff --git a/src/main/resources/jitsi/coturn-config-udp-service.yaml b/src/main/resources/jitsi/coturn-config-udp-service.yaml
new file mode 100644
index 0000000..f394094
--- /dev/null
+++ b/src/main/resources/jitsi/coturn-config-udp-service.yaml
@@ -0,0 +1,23 @@
+apiVersion: v1
+kind: Service
+metadata:
+  namespace: NAMESPACE
+  name: coturn-turn-udp
+  labels:
+    app.kubernetes.io/name: "coturn"
+  annotations:
+    metallb.universe.tf/allow-shared-ip: "shared-ip-service-group"
+    metallb.universe.tf/address-pool: public
+spec:
+  type: LoadBalancer
+  ports:
+    - name: turn-udp
+      port: 3478
+      protocol: UDP
+      targetPort: 3478
+    - name: turn-udp-dtls
+      port: 5349
+      protocol: UDP
+      targetPort: 5349
+  selector:
+    app.kubernetes.io/name: coturn-coturn
\ No newline at end of file
diff --git a/src/main/resources/jitsi/jvb-config-envs-cm.yaml b/src/main/resources/jitsi/jvb-config-envs-cm.yaml
index 17602ea..93faa8c 100644
--- a/src/main/resources/jitsi/jvb-config-envs-cm.yaml
+++ b/src/main/resources/jitsi/jvb-config-envs-cm.yaml
@@ -9,7 +9,7 @@ metadata:
 data:
   JVB_BREWERY_MUC: 'jvbbrewery'
   JVB_PORT: '10000'
-  JVB_STUN_SERVERS: 'meet-jit-si-turnrelay.jitsi.net:443'
+  JVB_STUN_SERVERS: REPLACE_ME
   JVB_TCP_HARVESTER_DISABLED: '1'
   XMPP_SERVER: REPLACE_ME
   COLIBRI_REST_ENABLED: 'true'
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index 04d31d3..b3ba9d4 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -166,3 +166,28 @@
          (count (cut/restart-config
                  {:fqdn "xy.xy.xy"
                   :namespace "jitsi"})))))
+
+(deftest should-generate-coturn
+  (is (= 1
+         (count (cut/coturn-auth
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"}
+                 {:jvb-auth-password "jvb-auth"
+                  :jicofo-auth-password "jicofo-auth"
+                  :jicofo-component-secret "jicofo-comp"}))))
+   (is (= 5
+         (count (cut/coturn-config
+                 {:fqdn "xy.xy.xy"
+                  :namespace "jitsi"}))))
+  (is (= {:apiVersion "v1",
+           :kind "ConfigMap",
+           :metadata
+           {:namespace "jitsi",
+            :name "coturn-initial-config",
+            :labels #:app.kubernetes.io{:name "coturn"}},
+           :data
+           {:turnserver.conf
+            "realm: stun.xy.xy.xy\nlistening-ip: 0.0.0.0\nlistening-port: 3478\ntls-listening-port: 5349\nmin-port: 49152\nmax-port: 65535\nlog-file: stdout\npidfile: \"/var/tmp/turnserver.pid\"\npkey: \"/tls/tls.key\"\ncert: \"/tls/tls.crt\"\nuserdb: \"/var/db/turndb\""}}
+         (second (cut/coturn-config
+                  {:fqdn "xy.xy.xy"
+                   :namespace "jitsi"})))))
\ No newline at end of file

From 80ad4b720dd879134f11579e091356a1abd031dc Mon Sep 17 00:00:00 2001
From: Michael Jerger <michael.jerger@meissa-gmbh.de>
Date: Thu, 20 Feb 2025 16:29:45 +0100
Subject: [PATCH 33/33] clean up coturn & add over all test

---
 src/main/cljc/dda/c4k_jitsi/core.cljc         |  1 -
 src/main/cljc/dda/c4k_jitsi/jitsi.cljc        |  9 +------
 .../resources/jitsi/coturn-auth-secret.yaml   | 10 --------
 ...lt-cm.yaml => coturn-config-extra-cm.yaml} |  0
 src/test/cljc/dda/c4k_jitsi/core_test.cljc    | 24 ++++++++++++-------
 src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc   |  7 ------
 6 files changed, 17 insertions(+), 34 deletions(-)
 delete mode 100644 src/main/resources/jitsi/coturn-auth-secret.yaml
 rename src/main/resources/jitsi/{coturn-config-default-cm.yaml => coturn-config-extra-cm.yaml} (100%)

diff --git a/src/main/cljc/dda/c4k_jitsi/core.cljc b/src/main/cljc/dda/c4k_jitsi/core.cljc
index 1f09cd9..3202e6e 100644
--- a/src/main/cljc/dda/c4k_jitsi/core.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/core.cljc
@@ -77,6 +77,5 @@
         #(not (nil? %))
         (cm/concat-vec
          (jitsi/prosody-auth config auth)
-         (jitsi/coturn-auth config auth)
          (when (:contains? config :mon-cfg)
            (mon/generate-auth (:mon-cfg config) (:mon-auth auth))))))))
diff --git a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
index b59c9af..e62f6f9 100644
--- a/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
+++ b/src/main/cljc/dda/c4k_jitsi/jitsi.cljc
@@ -163,18 +163,11 @@
   (let [{:keys [namespace]} config]
     [(load-and-adjust-namespace "jitsi/modelector-config-service.yaml" namespace)
      (load-and-adjust-namespace "jitsi/modelector-config-deployment.yaml" namespace)]))
-
-(defn-spec coturn-auth cp/map-or-seq?
-  [config config?
-   auth auth?]
-  (let [{:keys [namespace]} config
-        {:keys []} auth]
-    [(load-and-adjust-namespace "jitsi/coturn-auth-secret.yaml" namespace)]))
   
 (defn-spec coturn-config cp/map-or-seq?
   [config config?]
   (let [{:keys [namespace fqdn]} config]
-    [(load-and-adjust-namespace "jitsi/coturn-config-default-cm.yaml" namespace)
+    [(load-and-adjust-namespace "jitsi/coturn-config-extra-cm.yaml" namespace)
      (-> 
       (load-and-adjust-namespace "jitsi/coturn-config-init-cm.yaml" namespace)
       (cm/replace-key-value
diff --git a/src/main/resources/jitsi/coturn-auth-secret.yaml b/src/main/resources/jitsi/coturn-auth-secret.yaml
deleted file mode 100644
index 93223f2..0000000
--- a/src/main/resources/jitsi/coturn-auth-secret.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
-  namespace: NAMESPACE
-  name: coturn-auth-secret
-  labels:
-    app.kubernetes.io/name: "coturn"
-data:
-  username: ""
-  password: ""
\ No newline at end of file
diff --git a/src/main/resources/jitsi/coturn-config-default-cm.yaml b/src/main/resources/jitsi/coturn-config-extra-cm.yaml
similarity index 100%
rename from src/main/resources/jitsi/coturn-config-default-cm.yaml
rename to src/main/resources/jitsi/coturn-config-extra-cm.yaml
diff --git a/src/test/cljc/dda/c4k_jitsi/core_test.cljc b/src/test/cljc/dda/c4k_jitsi/core_test.cljc
index e77e1f2..2c9067a 100644
--- a/src/test/cljc/dda/c4k_jitsi/core_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/core_test.cljc
@@ -1,20 +1,28 @@
 (ns dda.c4k-jitsi.core-test
   (:require
-   #?(:cljs [shadow.resource :as rc])
    #?(:clj [clojure.test :refer [deftest is are testing run-tests]]
       :cljs [cljs.test :refer-macros [deftest is are testing run-tests]])
    [clojure.spec.alpha :as s]
    [dda.c4k-common.yaml :as yaml]
-   [dda.c4k-jitsi.core :as cut]))
+   [dda.c4k-jitsi.core :as cut]
+   #?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
+
 
 #?(:cljs
    (defmethod yaml/load-resource :jitsi-test [resource-name]
-     (case resource-name
-       "jitsi-test/valid-auth.yaml"   (rc/inline "jitsi-test/valid-auth.yaml")
-       "jitsi-test/valid-config.yaml" (rc/inline "jitsi-test/valid-config.yaml")
-       (throw (js/Error. "Undefined Resource!")))))
+     (get (inline-resources "jitsi-test") resource-name)))
 
 (deftest validate-valid-resources
   (is (s/valid? cut/config? (yaml/load-as-edn "jitsi-test/valid-config.yaml")))
-  (is (s/valid? cut/auth? (yaml/load-as-edn "jitsi-test/valid-auth.yaml")))
-  )
\ No newline at end of file
+  (is (s/valid? cut/auth? (yaml/load-as-edn "jitsi-test/valid-auth.yaml"))))
+
+(deftest test-whole-generation
+  (is (= 63
+         (count
+          (cut/config-objects
+           (yaml/load-as-edn "jitsi-test/valid-config.yaml")))))
+  (is (= 6
+         (count
+          (cut/auth-objects
+           (yaml/load-as-edn "jitsi-test/valid-config.yaml")
+           (yaml/load-as-edn "jitsi-test/valid-auth.yaml"))))))
\ No newline at end of file
diff --git a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
index b3ba9d4..364d778 100644
--- a/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
+++ b/src/test/cljc/dda/c4k_jitsi/jitsi_test.cljc
@@ -168,13 +168,6 @@
                   :namespace "jitsi"})))))
 
 (deftest should-generate-coturn
-  (is (= 1
-         (count (cut/coturn-auth
-                 {:fqdn "xy.xy.xy"
-                  :namespace "jitsi"}
-                 {:jvb-auth-password "jvb-auth"
-                  :jicofo-auth-password "jicofo-auth"
-                  :jicofo-component-secret "jicofo-comp"}))))
    (is (= 5
          (count (cut/coturn-config
                  {:fqdn "xy.xy.xy"