├── src
├── views
│ ├── index.hbs
│ ├── layouts
│ │ └── default.hbs
│ └── home
│ │ └── index.hbs
├── public
│ └── styles.css
├── service
│ └── redisClient.js
└── index.js
├── .dockerignore
├── redis-cluster-demo.jpg
├── .env.example
├── redis
├── Dockerfile
├── redis.conf
└── entrypoint.sh
├── renovate.json
├── Dockerfile
├── .gitignore
├── README.md
├── package.json
├── docker-compose.yml
└── pnpm-lock.yaml
/src/views/index.hbs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/redis-cluster-demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brunojppb/redis-cluster-demo/HEAD/redis-cluster-demo.jpg
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # Duplicate this file and name it `.env`
2 | # Now configure your environment variables :)
3 | PORT=4000
--------------------------------------------------------------------------------
/redis/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM redis:latest
2 |
3 | COPY ./entrypoint.sh /entrypoint.sh
4 | RUN chmod 755 /entrypoint.sh
5 |
6 | ENTRYPOINT ["/entrypoint.sh"]
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:recommended"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:24-slim as build
2 |
3 | RUN mkdir -p /app
4 | WORKDIR /app
5 | COPY . /app
6 |
7 | # Install all dependencies
8 | RUN npm install
9 |
--------------------------------------------------------------------------------
/redis/redis.conf:
--------------------------------------------------------------------------------
1 | # Custom config file to enable cluster mode
2 | # on all Redis instances started via Docker
3 | port 6379
4 | cluster-enabled yes
5 | # The cluster file is created and managed by Redis
6 | # We just need to declare it here
7 | cluster-config-file nodes.conf
8 | cluster-node-timeout 5000
9 | appendonly yes
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store*
3 | Icon?
4 | ._*
5 |
6 | # Windows
7 | Thumbs.db
8 | ehthumbs.db
9 | Desktop.ini
10 |
11 | # Linux
12 | .directory
13 | *~
14 |
15 | # IDE
16 | .vscode
17 | .idea
18 |
19 | # npm
20 | node_modules
21 | package-lock.json
22 | *.log
23 | *.gz
24 | coverage
25 | .env
26 |
27 | # Benchmarking
28 | benchmarks/graphs
--------------------------------------------------------------------------------
/src/views/layouts/default.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
2 |
Redis Cluster Demo
3 | {{#if dataSaved}}
4 |
Data saved successfuly
5 | {{/if}}
6 |
7 |
18 |
19 |
20 |
Search for data
21 |
26 |
27 |
28 | {{#if value}}
29 |
30 |
Value stored in Redis:
31 | {{ value }}
32 |
--------------------------------------------------------------------------------
/src/service/redisClient.js:
--------------------------------------------------------------------------------
1 | const Redis = require('ioredis')
2 |
3 | /**
4 | * Get an existing Redis client instance. Build one if necessary
5 | * @return {Cluster|null} redis client
6 | * */
7 | function buildRedisClient() {
8 |
9 | try {
10 | // cluster URLs should be passed in with the following format:
11 | // REDIS_CLUSTER_URLS=10.0.0.1:6379,10.0.0.2:6379,10.0.0.3:6379
12 | const nodes = process.env.REDIS_CLUSTER_URLS.split(',').map(url => {
13 | const [host, port] = url.split(':')
14 | return { host, port }
15 | })
16 |
17 | const client = new Redis.Cluster(nodes, {
18 | redisOptions: {
19 | enableAutoPipelining: true,
20 | },
21 | })
22 |
23 | client.on('error', error => {
24 | console.error('Redis Error', error)
25 | })
26 |
27 | client.on('connect', () => {
28 | console.log('Redis Connection stablished')
29 | })
30 |
31 | client.on('ready', () => {
32 | console.log('Redis client ready')
33 | })
34 |
35 | client.on('end', () => {
36 | console.log('Redis client connection ended')
37 | })
38 |
39 | // Emits when an error occurs when connecting
40 | // to a node when using Redis in Cluster mode
41 | client.on('node error', (error, node) => {
42 | console.error(`Redis error in node ${node}`, error)
43 | })
44 |
45 | return client
46 | } catch (error) {
47 | console.error('Could not create a Redis cluster client', error)
48 |
49 | return null
50 | }
51 | }
52 |
53 | module.exports = buildRedisClient
54 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config()
2 | const path = require('path')
3 | const express = require('express')
4 | const { engine } = require('express-handlebars')
5 | const buildRedisClient = require('./service/redisClient')
6 |
7 |
8 | const app = express()
9 | const port = process.env.PORT || 3000
10 |
11 | const redis = buildRedisClient()
12 |
13 | app.use(express.urlencoded({ extended: true }))
14 |
15 | /** A rough debugging middleware */
16 | app.use((req, resp, next) => {
17 | console.log(`${req.method} | URL=${req.url}`)
18 | return next()
19 | })
20 |
21 | /** handlebars template engine */
22 | const VIEWS_PATH = `${__dirname}/views`
23 | app.engine('.hbs', engine({
24 | extname: '.hbs'
25 | }));
26 | app.set('view engine', '.hbs');
27 | app.set('views', VIEWS_PATH)
28 |
29 | app.use(
30 | '/static', express.static(path.join(__dirname, '/public'))
31 | )
32 |
33 | app.get('/', async (request, response) => {
34 | return response.render('home/index', {
35 | layout: 'default',
36 | })
37 | })
38 |
39 | app.post('/save-data', async (request, response) => {
40 | const { key, value } = request.body
41 | await redis.set(key, value)
42 | return response.status(201).render('home/index', {
43 | layout: 'default',
44 | dataSaved: true,
45 | })
46 | })
47 |
48 | app.post('/search', async (request, response) => {
49 | const { key } = request.body
50 | const value = await redis.get(key)
51 | return response.status(200).render('home/index', {
52 | layout: 'default',
53 | value,
54 | })
55 | })
56 |
57 | app.listen(port, () => {
58 | console.log(`App listening on port ${port}`)
59 | })
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | volumes:
2 | redis_1_data: {}
3 | redis_2_data: {}
4 | redis_3_data: {}
5 | redis_4_data: {}
6 | redis_5_data: {}
7 | redis_6_data: {}
8 | # This volume is specific for the demo Express application
9 | # built in this repo. You probably won't need that on your own setup.
10 | node_modules: {}
11 |
12 | services:
13 | app:
14 | container_name: express_app
15 | build:
16 | context: .
17 | environment:
18 | PORT: 4000
19 | NODE_ENV: production
20 | REDIS_CLUSTER_URLS: "redis_1:6379,redis_2:6379,redis_3:6379,redis_4:6379,redis_5:6379,redis_6:6379"
21 | volumes:
22 | - .:/app
23 | - node_modules:/app/node_modules
24 | command: ["npm", "run", "dev"]
25 | depends_on:
26 | - redis_1
27 | - redis_2
28 | - redis_3
29 | - redis_4
30 | - redis_5
31 | - redis_6
32 | - cluster_initiator
33 | ports:
34 | - "4000:4000"
35 | stdin_open: true
36 | networks:
37 | redis_cluster_net:
38 | ipv4_address: 173.18.0.10
39 |
40 | # Here we have six Redis containers with Cluster mode enabled,
41 | # three of them will work as master nodes and each one of
42 | # will have a replica, so in case of failures, the replica becomes the master.
43 | # They are configured by the `cluster_initiator` container.
44 | redis_1:
45 | image: "redis:latest"
46 | container_name: redis_1
47 | ports:
48 | - "6379"
49 | volumes:
50 | - redis_1_data:/data
51 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
52 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
53 | networks:
54 | redis_cluster_net:
55 | ipv4_address: 173.18.0.2
56 |
57 | redis_2:
58 | image: "redis:latest"
59 | container_name: redis_2
60 | ports:
61 | - "6379"
62 | volumes:
63 | - redis_2_data:/data
64 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
65 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
66 | networks:
67 | redis_cluster_net:
68 | ipv4_address: 173.18.0.3
69 |
70 | redis_3:
71 | image: "redis:latest"
72 | container_name: redis_3
73 | ports:
74 | - "6379"
75 | volumes:
76 | - redis_3_data:/data
77 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
78 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
79 | networks:
80 | redis_cluster_net:
81 | ipv4_address: 173.18.0.4
82 |
83 | redis_4:
84 | image: "redis:latest"
85 | container_name: redis_4
86 | ports:
87 | - "6379"
88 | volumes:
89 | - redis_4_data:/data
90 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
91 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
92 | networks:
93 | redis_cluster_net:
94 | ipv4_address: 173.18.0.5
95 |
96 | redis_5:
97 | image: "redis:latest"
98 | container_name: redis_5
99 | ports:
100 | - "6379"
101 | volumes:
102 | - redis_5_data:/data
103 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
104 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
105 | networks:
106 | redis_cluster_net:
107 | ipv4_address: 173.18.0.6
108 |
109 | redis_6:
110 | image: "redis:latest"
111 | container_name: redis_6
112 | ports:
113 | - "6379"
114 | volumes:
115 | - redis_6_data:/data
116 | - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
117 | command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
118 | networks:
119 | redis_cluster_net:
120 | ipv4_address: 173.18.0.7
121 |
122 | # Ephemeral container to create the Redis cluster connections.
123 | # Once the setup is done, this container shuts down
124 | # and the cluster can be used by the service app container
125 | cluster_initiator:
126 | container_name: cluster_initiator
127 | build:
128 | context: redis
129 | dockerfile: Dockerfile
130 | tty: true
131 | depends_on:
132 | - redis_1
133 | - redis_2
134 | - redis_3
135 | - redis_4
136 | - redis_5
137 | - redis_6
138 | networks:
139 | redis_cluster_net:
140 | ipv4_address: 173.18.0.8
141 |
142 | # Web UI to browse through our Redis data across all nodes
143 | redis_commander:
144 | image: rediscommander/redis-commander:latest
145 | container_name: redis_web
146 | environment:
147 | REDIS_HOSTS: "local:redis_1:6379,local:redis_2:6379,local:redis_3:6379"
148 | ports:
149 | - "5050:8081"
150 | depends_on:
151 | - redis_1
152 | - redis_2
153 | - redis_3
154 | - redis_4
155 | - redis_5
156 | - redis_6
157 | - cluster_initiator
158 | networks:
159 | redis_cluster_net:
160 | ipv4_address: 173.18.0.9
161 |
162 | # Rename the default network so we can easily identify it
163 | # Across all containers
164 | networks:
165 | redis_cluster_net:
166 | driver: bridge
167 | ipam:
168 | driver: default
169 | config:
170 | - subnet: 173.18.0.0/16
171 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | dotenv:
9 | specifier: 17.2.3
10 | version: 17.2.3
11 | express:
12 | specifier: 5.1.0
13 | version: 5.1.0
14 | express-handlebars:
15 | specifier: 8.0.4
16 | version: 8.0.4
17 | ioredis:
18 | specifier: 5.8.2
19 | version: 5.8.2
20 |
21 | devDependencies:
22 | nodemon:
23 | specifier: 3.1.10
24 | version: 3.1.10
25 |
26 | packages:
27 |
28 | /@ioredis/commands@1.4.0:
29 | resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==}
30 | dev: false
31 |
32 | /@isaacs/balanced-match@4.0.1:
33 | resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
34 | engines: {node: 20 || >=22}
35 | dev: false
36 |
37 | /@isaacs/brace-expansion@5.0.0:
38 | resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==}
39 | engines: {node: 20 || >=22}
40 | dependencies:
41 | '@isaacs/balanced-match': 4.0.1
42 | dev: false
43 |
44 | /@isaacs/cliui@8.0.2:
45 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
46 | engines: {node: '>=12'}
47 | dependencies:
48 | string-width: 5.1.2
49 | string-width-cjs: /string-width@4.2.3
50 | strip-ansi: 7.1.0
51 | strip-ansi-cjs: /strip-ansi@6.0.1
52 | wrap-ansi: 8.1.0
53 | wrap-ansi-cjs: /wrap-ansi@7.0.0
54 | dev: false
55 |
56 | /accepts@2.0.0:
57 | resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
58 | engines: {node: '>= 0.6'}
59 | dependencies:
60 | mime-types: 3.0.1
61 | negotiator: 1.0.0
62 | dev: false
63 |
64 | /ansi-regex@5.0.1:
65 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
66 | engines: {node: '>=8'}
67 | dev: false
68 |
69 | /ansi-regex@6.0.1:
70 | resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
71 | engines: {node: '>=12'}
72 | dev: false
73 |
74 | /ansi-styles@4.3.0:
75 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
76 | engines: {node: '>=8'}
77 | dependencies:
78 | color-convert: 2.0.1
79 | dev: false
80 |
81 | /ansi-styles@6.2.1:
82 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
83 | engines: {node: '>=12'}
84 | dev: false
85 |
86 | /anymatch@3.1.3:
87 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
88 | engines: {node: '>= 8'}
89 | dependencies:
90 | normalize-path: 3.0.0
91 | picomatch: 2.3.1
92 | dev: true
93 |
94 | /balanced-match@1.0.2:
95 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
96 | dev: true
97 |
98 | /binary-extensions@2.3.0:
99 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
100 | engines: {node: '>=8'}
101 | dev: true
102 |
103 | /body-parser@2.2.0:
104 | resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
105 | engines: {node: '>=18'}
106 | dependencies:
107 | bytes: 3.1.2
108 | content-type: 1.0.5
109 | debug: 4.4.0(supports-color@5.5.0)
110 | http-errors: 2.0.0
111 | iconv-lite: 0.6.3
112 | on-finished: 2.4.1
113 | qs: 6.14.0
114 | raw-body: 3.0.0
115 | type-is: 2.0.1
116 | transitivePeerDependencies:
117 | - supports-color
118 | dev: false
119 |
120 | /brace-expansion@1.1.11:
121 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
122 | dependencies:
123 | balanced-match: 1.0.2
124 | concat-map: 0.0.1
125 | dev: true
126 |
127 | /braces@3.0.3:
128 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
129 | engines: {node: '>=8'}
130 | dependencies:
131 | fill-range: 7.1.1
132 | dev: true
133 |
134 | /bytes@3.1.2:
135 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
136 | engines: {node: '>= 0.8'}
137 | dev: false
138 |
139 | /call-bind-apply-helpers@1.0.2:
140 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
141 | engines: {node: '>= 0.4'}
142 | dependencies:
143 | es-errors: 1.3.0
144 | function-bind: 1.1.2
145 | dev: false
146 |
147 | /call-bound@1.0.4:
148 | resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
149 | engines: {node: '>= 0.4'}
150 | dependencies:
151 | call-bind-apply-helpers: 1.0.2
152 | get-intrinsic: 1.3.0
153 | dev: false
154 |
155 | /chokidar@3.6.0:
156 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
157 | engines: {node: '>= 8.10.0'}
158 | dependencies:
159 | anymatch: 3.1.3
160 | braces: 3.0.3
161 | glob-parent: 5.1.2
162 | is-binary-path: 2.1.0
163 | is-glob: 4.0.3
164 | normalize-path: 3.0.0
165 | readdirp: 3.6.0
166 | optionalDependencies:
167 | fsevents: 2.3.3
168 | dev: true
169 |
170 | /cluster-key-slot@1.1.2:
171 | resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
172 | engines: {node: '>=0.10.0'}
173 | dev: false
174 |
175 | /color-convert@2.0.1:
176 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
177 | engines: {node: '>=7.0.0'}
178 | dependencies:
179 | color-name: 1.1.4
180 | dev: false
181 |
182 | /color-name@1.1.4:
183 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
184 | dev: false
185 |
186 | /concat-map@0.0.1:
187 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
188 | dev: true
189 |
190 | /content-disposition@1.0.0:
191 | resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
192 | engines: {node: '>= 0.6'}
193 | dependencies:
194 | safe-buffer: 5.2.1
195 | dev: false
196 |
197 | /content-type@1.0.5:
198 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
199 | engines: {node: '>= 0.6'}
200 | dev: false
201 |
202 | /cookie-signature@1.2.2:
203 | resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
204 | engines: {node: '>=6.6.0'}
205 | dev: false
206 |
207 | /cookie@0.7.1:
208 | resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
209 | engines: {node: '>= 0.6'}
210 | dev: false
211 |
212 | /cross-spawn@7.0.6:
213 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
214 | engines: {node: '>= 8'}
215 | dependencies:
216 | path-key: 3.1.1
217 | shebang-command: 2.0.0
218 | which: 2.0.2
219 | dev: false
220 |
221 | /debug@4.4.0(supports-color@5.5.0):
222 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
223 | engines: {node: '>=6.0'}
224 | peerDependencies:
225 | supports-color: '*'
226 | peerDependenciesMeta:
227 | supports-color:
228 | optional: true
229 | dependencies:
230 | ms: 2.1.3
231 | supports-color: 5.5.0
232 |
233 | /denque@2.1.0:
234 | resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
235 | engines: {node: '>=0.10'}
236 | dev: false
237 |
238 | /depd@2.0.0:
239 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
240 | engines: {node: '>= 0.8'}
241 | dev: false
242 |
243 | /dotenv@17.2.3:
244 | resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==}
245 | engines: {node: '>=12'}
246 | dev: false
247 |
248 | /dunder-proto@1.0.1:
249 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
250 | engines: {node: '>= 0.4'}
251 | dependencies:
252 | call-bind-apply-helpers: 1.0.2
253 | es-errors: 1.3.0
254 | gopd: 1.2.0
255 | dev: false
256 |
257 | /eastasianwidth@0.2.0:
258 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
259 | dev: false
260 |
261 | /ee-first@1.1.1:
262 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
263 | dev: false
264 |
265 | /emoji-regex@8.0.0:
266 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
267 | dev: false
268 |
269 | /emoji-regex@9.2.2:
270 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
271 | dev: false
272 |
273 | /encodeurl@2.0.0:
274 | resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
275 | engines: {node: '>= 0.8'}
276 | dev: false
277 |
278 | /es-define-property@1.0.1:
279 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
280 | engines: {node: '>= 0.4'}
281 | dev: false
282 |
283 | /es-errors@1.3.0:
284 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
285 | engines: {node: '>= 0.4'}
286 | dev: false
287 |
288 | /es-object-atoms@1.1.1:
289 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
290 | engines: {node: '>= 0.4'}
291 | dependencies:
292 | es-errors: 1.3.0
293 | dev: false
294 |
295 | /escape-html@1.0.3:
296 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
297 | dev: false
298 |
299 | /etag@1.8.1:
300 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
301 | engines: {node: '>= 0.6'}
302 | dev: false
303 |
304 | /express-handlebars@8.0.4:
305 | resolution: {integrity: sha512-1mXd9jxLfZgFjpPGamAizVhwukvwLlXRV0dPcsEvW2hqUlYICMtJAQrqFSmgwHFvbVeIA/afPOtmHtNF516pmQ==}
306 | engines: {node: '>=22.21.0'}
307 | dependencies:
308 | glob: 12.0.0
309 | graceful-fs: 4.2.11
310 | handlebars: 4.7.8
311 | dev: false
312 |
313 | /express@5.1.0:
314 | resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
315 | engines: {node: '>= 18'}
316 | dependencies:
317 | accepts: 2.0.0
318 | body-parser: 2.2.0
319 | content-disposition: 1.0.0
320 | content-type: 1.0.5
321 | cookie: 0.7.1
322 | cookie-signature: 1.2.2
323 | debug: 4.4.0(supports-color@5.5.0)
324 | encodeurl: 2.0.0
325 | escape-html: 1.0.3
326 | etag: 1.8.1
327 | finalhandler: 2.1.0
328 | fresh: 2.0.0
329 | http-errors: 2.0.0
330 | merge-descriptors: 2.0.0
331 | mime-types: 3.0.1
332 | on-finished: 2.4.1
333 | once: 1.4.0
334 | parseurl: 1.3.3
335 | proxy-addr: 2.0.7
336 | qs: 6.14.0
337 | range-parser: 1.2.1
338 | router: 2.2.0
339 | send: 1.2.0
340 | serve-static: 2.2.0
341 | statuses: 2.0.1
342 | type-is: 2.0.1
343 | vary: 1.1.2
344 | transitivePeerDependencies:
345 | - supports-color
346 | dev: false
347 |
348 | /fill-range@7.1.1:
349 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
350 | engines: {node: '>=8'}
351 | dependencies:
352 | to-regex-range: 5.0.1
353 | dev: true
354 |
355 | /finalhandler@2.1.0:
356 | resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
357 | engines: {node: '>= 0.8'}
358 | dependencies:
359 | debug: 4.4.0(supports-color@5.5.0)
360 | encodeurl: 2.0.0
361 | escape-html: 1.0.3
362 | on-finished: 2.4.1
363 | parseurl: 1.3.3
364 | statuses: 2.0.1
365 | transitivePeerDependencies:
366 | - supports-color
367 | dev: false
368 |
369 | /foreground-child@3.3.1:
370 | resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
371 | engines: {node: '>=14'}
372 | dependencies:
373 | cross-spawn: 7.0.6
374 | signal-exit: 4.1.0
375 | dev: false
376 |
377 | /forwarded@0.2.0:
378 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
379 | engines: {node: '>= 0.6'}
380 | dev: false
381 |
382 | /fresh@2.0.0:
383 | resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
384 | engines: {node: '>= 0.8'}
385 | dev: false
386 |
387 | /fsevents@2.3.3:
388 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
389 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
390 | os: [darwin]
391 | requiresBuild: true
392 | dev: true
393 | optional: true
394 |
395 | /function-bind@1.1.2:
396 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
397 | dev: false
398 |
399 | /get-intrinsic@1.3.0:
400 | resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
401 | engines: {node: '>= 0.4'}
402 | dependencies:
403 | call-bind-apply-helpers: 1.0.2
404 | es-define-property: 1.0.1
405 | es-errors: 1.3.0
406 | es-object-atoms: 1.1.1
407 | function-bind: 1.1.2
408 | get-proto: 1.0.1
409 | gopd: 1.2.0
410 | has-symbols: 1.1.0
411 | hasown: 2.0.2
412 | math-intrinsics: 1.1.0
413 | dev: false
414 |
415 | /get-proto@1.0.1:
416 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
417 | engines: {node: '>= 0.4'}
418 | dependencies:
419 | dunder-proto: 1.0.1
420 | es-object-atoms: 1.1.1
421 | dev: false
422 |
423 | /glob-parent@5.1.2:
424 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
425 | engines: {node: '>= 6'}
426 | dependencies:
427 | is-glob: 4.0.3
428 | dev: true
429 |
430 | /glob@12.0.0:
431 | resolution: {integrity: sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==}
432 | engines: {node: 20 || >=22}
433 | hasBin: true
434 | dependencies:
435 | foreground-child: 3.3.1
436 | jackspeak: 4.1.1
437 | minimatch: 10.1.1
438 | minipass: 7.1.2
439 | package-json-from-dist: 1.0.1
440 | path-scurry: 2.0.0
441 | dev: false
442 |
443 | /gopd@1.2.0:
444 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
445 | engines: {node: '>= 0.4'}
446 | dev: false
447 |
448 | /graceful-fs@4.2.11:
449 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
450 | dev: false
451 |
452 | /handlebars@4.7.8:
453 | resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
454 | engines: {node: '>=0.4.7'}
455 | hasBin: true
456 | dependencies:
457 | minimist: 1.2.8
458 | neo-async: 2.6.2
459 | source-map: 0.6.1
460 | wordwrap: 1.0.0
461 | optionalDependencies:
462 | uglify-js: 3.18.0
463 | dev: false
464 |
465 | /has-flag@3.0.0:
466 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
467 | engines: {node: '>=4'}
468 |
469 | /has-symbols@1.1.0:
470 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
471 | engines: {node: '>= 0.4'}
472 | dev: false
473 |
474 | /hasown@2.0.2:
475 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
476 | engines: {node: '>= 0.4'}
477 | dependencies:
478 | function-bind: 1.1.2
479 | dev: false
480 |
481 | /http-errors@2.0.0:
482 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
483 | engines: {node: '>= 0.8'}
484 | dependencies:
485 | depd: 2.0.0
486 | inherits: 2.0.4
487 | setprototypeof: 1.2.0
488 | statuses: 2.0.1
489 | toidentifier: 1.0.1
490 | dev: false
491 |
492 | /iconv-lite@0.6.3:
493 | resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
494 | engines: {node: '>=0.10.0'}
495 | dependencies:
496 | safer-buffer: 2.1.2
497 | dev: false
498 |
499 | /ignore-by-default@1.0.1:
500 | resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
501 | dev: true
502 |
503 | /inherits@2.0.4:
504 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
505 | dev: false
506 |
507 | /ioredis@5.8.2:
508 | resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==}
509 | engines: {node: '>=12.22.0'}
510 | dependencies:
511 | '@ioredis/commands': 1.4.0
512 | cluster-key-slot: 1.1.2
513 | debug: 4.4.0(supports-color@5.5.0)
514 | denque: 2.1.0
515 | lodash.defaults: 4.2.0
516 | lodash.isarguments: 3.1.0
517 | redis-errors: 1.2.0
518 | redis-parser: 3.0.0
519 | standard-as-callback: 2.1.0
520 | transitivePeerDependencies:
521 | - supports-color
522 | dev: false
523 |
524 | /ipaddr.js@1.9.1:
525 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
526 | engines: {node: '>= 0.10'}
527 | dev: false
528 |
529 | /is-binary-path@2.1.0:
530 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
531 | engines: {node: '>=8'}
532 | dependencies:
533 | binary-extensions: 2.3.0
534 | dev: true
535 |
536 | /is-extglob@2.1.1:
537 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
538 | engines: {node: '>=0.10.0'}
539 | dev: true
540 |
541 | /is-fullwidth-code-point@3.0.0:
542 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
543 | engines: {node: '>=8'}
544 | dev: false
545 |
546 | /is-glob@4.0.3:
547 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
548 | engines: {node: '>=0.10.0'}
549 | dependencies:
550 | is-extglob: 2.1.1
551 | dev: true
552 |
553 | /is-number@7.0.0:
554 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
555 | engines: {node: '>=0.12.0'}
556 | dev: true
557 |
558 | /is-promise@4.0.0:
559 | resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
560 | dev: false
561 |
562 | /isexe@2.0.0:
563 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
564 | dev: false
565 |
566 | /jackspeak@4.1.1:
567 | resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==}
568 | engines: {node: 20 || >=22}
569 | dependencies:
570 | '@isaacs/cliui': 8.0.2
571 | dev: false
572 |
573 | /lodash.defaults@4.2.0:
574 | resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
575 | dev: false
576 |
577 | /lodash.isarguments@3.1.0:
578 | resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
579 | dev: false
580 |
581 | /lru-cache@11.0.2:
582 | resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==}
583 | engines: {node: 20 || >=22}
584 | dev: false
585 |
586 | /math-intrinsics@1.1.0:
587 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
588 | engines: {node: '>= 0.4'}
589 | dev: false
590 |
591 | /media-typer@1.1.0:
592 | resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
593 | engines: {node: '>= 0.8'}
594 | dev: false
595 |
596 | /merge-descriptors@2.0.0:
597 | resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
598 | engines: {node: '>=18'}
599 | dev: false
600 |
601 | /mime-db@1.54.0:
602 | resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
603 | engines: {node: '>= 0.6'}
604 | dev: false
605 |
606 | /mime-types@3.0.1:
607 | resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
608 | engines: {node: '>= 0.6'}
609 | dependencies:
610 | mime-db: 1.54.0
611 | dev: false
612 |
613 | /minimatch@10.1.1:
614 | resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
615 | engines: {node: 20 || >=22}
616 | dependencies:
617 | '@isaacs/brace-expansion': 5.0.0
618 | dev: false
619 |
620 | /minimatch@3.1.2:
621 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
622 | dependencies:
623 | brace-expansion: 1.1.11
624 | dev: true
625 |
626 | /minimist@1.2.8:
627 | resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
628 | dev: false
629 |
630 | /minipass@7.1.2:
631 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
632 | engines: {node: '>=16 || 14 >=14.17'}
633 | dev: false
634 |
635 | /ms@2.1.3:
636 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
637 |
638 | /negotiator@1.0.0:
639 | resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
640 | engines: {node: '>= 0.6'}
641 | dev: false
642 |
643 | /neo-async@2.6.2:
644 | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
645 | dev: false
646 |
647 | /nodemon@3.1.10:
648 | resolution: {integrity: sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==}
649 | engines: {node: '>=10'}
650 | hasBin: true
651 | dependencies:
652 | chokidar: 3.6.0
653 | debug: 4.4.0(supports-color@5.5.0)
654 | ignore-by-default: 1.0.1
655 | minimatch: 3.1.2
656 | pstree.remy: 1.1.8
657 | semver: 7.6.2
658 | simple-update-notifier: 2.0.0
659 | supports-color: 5.5.0
660 | touch: 3.1.1
661 | undefsafe: 2.0.5
662 | dev: true
663 |
664 | /normalize-path@3.0.0:
665 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
666 | engines: {node: '>=0.10.0'}
667 | dev: true
668 |
669 | /object-inspect@1.13.4:
670 | resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
671 | engines: {node: '>= 0.4'}
672 | dev: false
673 |
674 | /on-finished@2.4.1:
675 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
676 | engines: {node: '>= 0.8'}
677 | dependencies:
678 | ee-first: 1.1.1
679 | dev: false
680 |
681 | /once@1.4.0:
682 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
683 | dependencies:
684 | wrappy: 1.0.2
685 | dev: false
686 |
687 | /package-json-from-dist@1.0.1:
688 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
689 | dev: false
690 |
691 | /parseurl@1.3.3:
692 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
693 | engines: {node: '>= 0.8'}
694 | dev: false
695 |
696 | /path-key@3.1.1:
697 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
698 | engines: {node: '>=8'}
699 | dev: false
700 |
701 | /path-scurry@2.0.0:
702 | resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==}
703 | engines: {node: 20 || >=22}
704 | dependencies:
705 | lru-cache: 11.0.2
706 | minipass: 7.1.2
707 | dev: false
708 |
709 | /path-to-regexp@8.2.0:
710 | resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==}
711 | engines: {node: '>=16'}
712 | dev: false
713 |
714 | /picomatch@2.3.1:
715 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
716 | engines: {node: '>=8.6'}
717 | dev: true
718 |
719 | /proxy-addr@2.0.7:
720 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
721 | engines: {node: '>= 0.10'}
722 | dependencies:
723 | forwarded: 0.2.0
724 | ipaddr.js: 1.9.1
725 | dev: false
726 |
727 | /pstree.remy@1.1.8:
728 | resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
729 | dev: true
730 |
731 | /qs@6.14.0:
732 | resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
733 | engines: {node: '>=0.6'}
734 | dependencies:
735 | side-channel: 1.1.0
736 | dev: false
737 |
738 | /range-parser@1.2.1:
739 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
740 | engines: {node: '>= 0.6'}
741 | dev: false
742 |
743 | /raw-body@3.0.0:
744 | resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
745 | engines: {node: '>= 0.8'}
746 | dependencies:
747 | bytes: 3.1.2
748 | http-errors: 2.0.0
749 | iconv-lite: 0.6.3
750 | unpipe: 1.0.0
751 | dev: false
752 |
753 | /readdirp@3.6.0:
754 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
755 | engines: {node: '>=8.10.0'}
756 | dependencies:
757 | picomatch: 2.3.1
758 | dev: true
759 |
760 | /redis-errors@1.2.0:
761 | resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
762 | engines: {node: '>=4'}
763 | dev: false
764 |
765 | /redis-parser@3.0.0:
766 | resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
767 | engines: {node: '>=4'}
768 | dependencies:
769 | redis-errors: 1.2.0
770 | dev: false
771 |
772 | /router@2.2.0:
773 | resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
774 | engines: {node: '>= 18'}
775 | dependencies:
776 | debug: 4.4.0(supports-color@5.5.0)
777 | depd: 2.0.0
778 | is-promise: 4.0.0
779 | parseurl: 1.3.3
780 | path-to-regexp: 8.2.0
781 | transitivePeerDependencies:
782 | - supports-color
783 | dev: false
784 |
785 | /safe-buffer@5.2.1:
786 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
787 | dev: false
788 |
789 | /safer-buffer@2.1.2:
790 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
791 | dev: false
792 |
793 | /semver@7.6.2:
794 | resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
795 | engines: {node: '>=10'}
796 | hasBin: true
797 | dev: true
798 |
799 | /send@1.2.0:
800 | resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
801 | engines: {node: '>= 18'}
802 | dependencies:
803 | debug: 4.4.0(supports-color@5.5.0)
804 | encodeurl: 2.0.0
805 | escape-html: 1.0.3
806 | etag: 1.8.1
807 | fresh: 2.0.0
808 | http-errors: 2.0.0
809 | mime-types: 3.0.1
810 | ms: 2.1.3
811 | on-finished: 2.4.1
812 | range-parser: 1.2.1
813 | statuses: 2.0.1
814 | transitivePeerDependencies:
815 | - supports-color
816 | dev: false
817 |
818 | /serve-static@2.2.0:
819 | resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
820 | engines: {node: '>= 18'}
821 | dependencies:
822 | encodeurl: 2.0.0
823 | escape-html: 1.0.3
824 | parseurl: 1.3.3
825 | send: 1.2.0
826 | transitivePeerDependencies:
827 | - supports-color
828 | dev: false
829 |
830 | /setprototypeof@1.2.0:
831 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
832 | dev: false
833 |
834 | /shebang-command@2.0.0:
835 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
836 | engines: {node: '>=8'}
837 | dependencies:
838 | shebang-regex: 3.0.0
839 | dev: false
840 |
841 | /shebang-regex@3.0.0:
842 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
843 | engines: {node: '>=8'}
844 | dev: false
845 |
846 | /side-channel-list@1.0.0:
847 | resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
848 | engines: {node: '>= 0.4'}
849 | dependencies:
850 | es-errors: 1.3.0
851 | object-inspect: 1.13.4
852 | dev: false
853 |
854 | /side-channel-map@1.0.1:
855 | resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
856 | engines: {node: '>= 0.4'}
857 | dependencies:
858 | call-bound: 1.0.4
859 | es-errors: 1.3.0
860 | get-intrinsic: 1.3.0
861 | object-inspect: 1.13.4
862 | dev: false
863 |
864 | /side-channel-weakmap@1.0.2:
865 | resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
866 | engines: {node: '>= 0.4'}
867 | dependencies:
868 | call-bound: 1.0.4
869 | es-errors: 1.3.0
870 | get-intrinsic: 1.3.0
871 | object-inspect: 1.13.4
872 | side-channel-map: 1.0.1
873 | dev: false
874 |
875 | /side-channel@1.1.0:
876 | resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
877 | engines: {node: '>= 0.4'}
878 | dependencies:
879 | es-errors: 1.3.0
880 | object-inspect: 1.13.4
881 | side-channel-list: 1.0.0
882 | side-channel-map: 1.0.1
883 | side-channel-weakmap: 1.0.2
884 | dev: false
885 |
886 | /signal-exit@4.1.0:
887 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
888 | engines: {node: '>=14'}
889 | dev: false
890 |
891 | /simple-update-notifier@2.0.0:
892 | resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
893 | engines: {node: '>=10'}
894 | dependencies:
895 | semver: 7.6.2
896 | dev: true
897 |
898 | /source-map@0.6.1:
899 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
900 | engines: {node: '>=0.10.0'}
901 | dev: false
902 |
903 | /standard-as-callback@2.1.0:
904 | resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
905 | dev: false
906 |
907 | /statuses@2.0.1:
908 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
909 | engines: {node: '>= 0.8'}
910 | dev: false
911 |
912 | /string-width@4.2.3:
913 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
914 | engines: {node: '>=8'}
915 | dependencies:
916 | emoji-regex: 8.0.0
917 | is-fullwidth-code-point: 3.0.0
918 | strip-ansi: 6.0.1
919 | dev: false
920 |
921 | /string-width@5.1.2:
922 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
923 | engines: {node: '>=12'}
924 | dependencies:
925 | eastasianwidth: 0.2.0
926 | emoji-regex: 9.2.2
927 | strip-ansi: 7.1.0
928 | dev: false
929 |
930 | /strip-ansi@6.0.1:
931 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
932 | engines: {node: '>=8'}
933 | dependencies:
934 | ansi-regex: 5.0.1
935 | dev: false
936 |
937 | /strip-ansi@7.1.0:
938 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
939 | engines: {node: '>=12'}
940 | dependencies:
941 | ansi-regex: 6.0.1
942 | dev: false
943 |
944 | /supports-color@5.5.0:
945 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
946 | engines: {node: '>=4'}
947 | dependencies:
948 | has-flag: 3.0.0
949 |
950 | /to-regex-range@5.0.1:
951 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
952 | engines: {node: '>=8.0'}
953 | dependencies:
954 | is-number: 7.0.0
955 | dev: true
956 |
957 | /toidentifier@1.0.1:
958 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
959 | engines: {node: '>=0.6'}
960 | dev: false
961 |
962 | /touch@3.1.1:
963 | resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==}
964 | hasBin: true
965 | dev: true
966 |
967 | /type-is@2.0.1:
968 | resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
969 | engines: {node: '>= 0.6'}
970 | dependencies:
971 | content-type: 1.0.5
972 | media-typer: 1.1.0
973 | mime-types: 3.0.1
974 | dev: false
975 |
976 | /uglify-js@3.18.0:
977 | resolution: {integrity: sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==}
978 | engines: {node: '>=0.8.0'}
979 | hasBin: true
980 | requiresBuild: true
981 | dev: false
982 | optional: true
983 |
984 | /undefsafe@2.0.5:
985 | resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
986 | dev: true
987 |
988 | /unpipe@1.0.0:
989 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
990 | engines: {node: '>= 0.8'}
991 | dev: false
992 |
993 | /vary@1.1.2:
994 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
995 | engines: {node: '>= 0.8'}
996 | dev: false
997 |
998 | /which@2.0.2:
999 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1000 | engines: {node: '>= 8'}
1001 | hasBin: true
1002 | dependencies:
1003 | isexe: 2.0.0
1004 | dev: false
1005 |
1006 | /wordwrap@1.0.0:
1007 | resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
1008 | dev: false
1009 |
1010 | /wrap-ansi@7.0.0:
1011 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1012 | engines: {node: '>=10'}
1013 | dependencies:
1014 | ansi-styles: 4.3.0
1015 | string-width: 4.2.3
1016 | strip-ansi: 6.0.1
1017 | dev: false
1018 |
1019 | /wrap-ansi@8.1.0:
1020 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
1021 | engines: {node: '>=12'}
1022 | dependencies:
1023 | ansi-styles: 6.2.1
1024 | string-width: 5.1.2
1025 | strip-ansi: 7.1.0
1026 | dev: false
1027 |
1028 | /wrappy@1.0.2:
1029 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
1030 | dev: false
1031 |
--------------------------------------------------------------------------------