See the best posts from any Bluesky account
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add functional tests for ProfileController, SearchController, routes

16 new integration tests covering: landing page, routes and redirects,
handle canonicalization, loading page meta-refresh, 410 gone, ?days=
validation errors, and ClickHouse-backed profile rendering.

Adds @japa/api-client dev dep for HTTP testing and updates
tests/bootstrap.ts to include the apiClient plugin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+922 -2
+5 -1
apps/web/.adonisjs/server/controllers.ts
··· 3 3 * DO NOT EDIT manually 4 4 */ 5 5 6 - export const controllers = {} 6 + export const controllers = { 7 + Landing: () => import('#controllers/landing_controller'), 8 + Profile: () => import('#controllers/profile_controller'), 9 + Search: () => import('#controllers/search_controller'), 10 + }
+1
apps/web/package.json
··· 40 40 "@adonisjs/eslint-config": "^3.0.0", 41 41 "@adonisjs/prettier-config": "^1.4.5", 42 42 "@adonisjs/tsconfig": "^2.0.0", 43 + "@japa/api-client": "^3.2.1", 43 44 "@japa/assert": "^4.2.0", 44 45 "@japa/browser-client": "^2.3.0", 45 46 "@japa/plugin-adonisjs": "^5.2.0",
+7 -1
apps/web/tests/bootstrap.ts
··· 1 1 import { assert } from '@japa/assert' 2 + import { apiClient } from '@japa/api-client' 2 3 import app from '@adonisjs/core/services/app' 3 4 import type { Config } from '@japa/runner/types' 4 5 import { pluginAdonisJS } from '@japa/plugin-adonisjs' ··· 13 14 * Configure Japa plugins in the plugins array. 14 15 * Learn more - https://japa.dev/docs/runner-config#plugins-optional 15 16 */ 16 - export const plugins: Config['plugins'] = [assert(), pluginAdonisJS(app), dbAssertions(app)] 17 + export const plugins: Config['plugins'] = [ 18 + assert(), 19 + apiClient(), 20 + pluginAdonisJS(app), 21 + dbAssertions(app), 22 + ] 17 23 18 24 /** 19 25 * Configure lifecycle function to run before and after all the
+354
apps/web/tests/functional/profile_controller.spec.ts
··· 1 + /** 2 + * Functional tests for ProfileController, SearchController, and LandingController. 3 + * 4 + * Tests 1-10 and 14-16 only need SQLite — no ClickHouse. 5 + * Tests 11-13 require a running ClickHouse instance and are skipped when unavailable. 6 + */ 7 + import { test } from '@japa/runner' 8 + import { createClient } from '@clickhouse/client' 9 + import { readdir, readFile } from 'node:fs/promises' 10 + import { randomBytes } from 'node:crypto' 11 + import { fileURLToPath } from 'node:url' 12 + import { join } from 'node:path' 13 + import testUtils from '@adonisjs/core/services/test_utils' 14 + import { ClickHouseStore } from '@skystar/clickhouse' 15 + import User from '#models/user' 16 + 17 + // --------------------------------------------------------------------------- 18 + // ClickHouse helpers (mirror clickhouse_store.spec.ts) 19 + // --------------------------------------------------------------------------- 20 + 21 + const CLICKHOUSE_URL = process.env.CLICKHOUSE_URL ?? 'http://localhost:8123' 22 + const CLICKHOUSE_USER = process.env.CLICKHOUSE_USER ?? 'default' 23 + const CLICKHOUSE_PASSWORD = process.env.CLICKHOUSE_PASSWORD ?? '' 24 + 25 + const MIGRATIONS_DIR = join( 26 + fileURLToPath(new URL('.', import.meta.url)), 27 + '../../database/clickhouse' 28 + ) 29 + 30 + async function isClickHouseAvailable(): Promise<boolean> { 31 + try { 32 + const client = createClient({ 33 + url: CLICKHOUSE_URL, 34 + username: CLICKHOUSE_USER, 35 + password: CLICKHOUSE_PASSWORD, 36 + }) 37 + await client.query({ query: 'SELECT 1', format: 'JSONEachRow' }) 38 + await client.close() 39 + return true 40 + } catch { 41 + return false 42 + } 43 + } 44 + 45 + async function applyMigrations(dbName: string): Promise<void> { 46 + const adminRoot = createClient({ 47 + url: CLICKHOUSE_URL, 48 + username: CLICKHOUSE_USER, 49 + password: CLICKHOUSE_PASSWORD, 50 + }) 51 + await adminRoot.command({ query: `CREATE DATABASE IF NOT EXISTS \`${dbName}\`` }) 52 + await adminRoot.close() 53 + 54 + const adminDb = createClient({ 55 + url: CLICKHOUSE_URL, 56 + username: CLICKHOUSE_USER, 57 + password: CLICKHOUSE_PASSWORD, 58 + database: dbName, 59 + }) 60 + const entries = await readdir(MIGRATIONS_DIR) 61 + const migrationFiles = entries.filter((f) => f.endsWith('.sql')).sort() 62 + for (const filename of migrationFiles) { 63 + const sql = await readFile(join(MIGRATIONS_DIR, filename), 'utf8') 64 + await adminDb.command({ query: sql }) 65 + } 66 + await adminDb.close() 67 + } 68 + 69 + async function dropDatabase(dbName: string): Promise<void> { 70 + const admin = createClient({ 71 + url: CLICKHOUSE_URL, 72 + username: CLICKHOUSE_USER, 73 + password: CLICKHOUSE_PASSWORD, 74 + }) 75 + await admin.command({ query: `DROP DATABASE IF EXISTS \`${dbName}\`` }) 76 + await admin.close() 77 + } 78 + 79 + // --------------------------------------------------------------------------- 80 + // Routes & redirects (no ClickHouse needed) 81 + // --------------------------------------------------------------------------- 82 + 83 + test.group('Routes & redirects', (group) => { 84 + group.each.setup(() => testUtils.db().withGlobalTransaction()) 85 + 86 + // Test 1: GET / returns 200 and landing page 87 + test('GET / returns 200 with landing page', async ({ client, assert }) => { 88 + const response = await client.get('/') 89 + response.assertStatus(200) 90 + assert.include(response.text(), 'skystar') 91 + }) 92 + 93 + // Test 2: GET /about returns 200 94 + test('GET /about returns 200', async ({ client }) => { 95 + const response = await client.get('/about') 96 + response.assertStatus(200) 97 + }) 98 + 99 + // Test 3: GET /search?q=dril returns 302 → /profile/dril.bsky.social/likes 100 + test('GET /search?q=dril redirects to canonical profile', async ({ client }) => { 101 + const response = await client.get('/search?q=dril').redirects(0) 102 + response.assertStatus(302) 103 + response.assertHeader('location', '/profile/dril.bsky.social/likes') 104 + }) 105 + 106 + // Test 4: GET /search?q=dril.bsky.social returns 302 → /profile/dril.bsky.social/likes 107 + test('GET /search?q=dril.bsky.social redirects without double redirect', async ({ client }) => { 108 + const response = await client.get('/search?q=dril.bsky.social').redirects(0) 109 + response.assertStatus(302) 110 + response.assertHeader('location', '/profile/dril.bsky.social/likes') 111 + }) 112 + 113 + // Test 5: GET /search?q= returns 200 with landing + error 114 + test('GET /search?q= returns 200 with error', async ({ client, assert }) => { 115 + const response = await client.get('/search?q=') 116 + response.assertStatus(200) 117 + assert.include(response.text(), 'Please enter a handle') 118 + }) 119 + 120 + // Test 6: GET /search?q=!!! returns 200 with landing + error (InvalidHandleError) 121 + test('GET /search?q=!!! returns 200 with handle error', async ({ client, assert }) => { 122 + const response = await client.get('/search?q=!!!') 123 + response.assertStatus(200) 124 + assert.include(response.text(), 'valid Bluesky handle') 125 + }) 126 + 127 + // Test 7: GET /profile/dril.bsky.social returns 301 → /profile/dril.bsky.social/likes 128 + test('GET /profile/:handle returns 301 to /likes', async ({ client }) => { 129 + const response = await client.get('/profile/dril.bsky.social').redirects(0) 130 + response.assertStatus(301) 131 + response.assertHeader('location', '/profile/dril.bsky.social/likes') 132 + }) 133 + 134 + // Test 8: GET /profile/dril returns 301 → /profile/dril.bsky.social/likes (suffix appended) 135 + test('GET /profile/dril returns 301 with .bsky.social appended', async ({ client }) => { 136 + const response = await client.get('/profile/dril').redirects(0) 137 + response.assertStatus(301) 138 + response.assertHeader('location', '/profile/dril.bsky.social/likes') 139 + }) 140 + 141 + // Test 9: GET /profile/Dril.bsky.social/likes returns 301 → lowercase 142 + test('GET /profile/Dril.bsky.social/likes returns 301 lowercased', async ({ client }) => { 143 + const response = await client.get('/profile/Dril.bsky.social/likes').redirects(0) 144 + response.assertStatus(301) 145 + response.assertHeader('location', '/profile/dril.bsky.social/likes') 146 + }) 147 + 148 + // Test 10: Unknown user returns 200 with loading page (meta-refresh present) 149 + test('GET /profile/dril.bsky.social/likes for unknown user returns loading page', async ({ 150 + client, 151 + assert, 152 + }) => { 153 + const response = await client.get('/profile/dril.bsky.social/likes?days=30') 154 + response.assertStatus(200) 155 + assert.include(response.text(), 'meta http-equiv="refresh"') 156 + assert.include(response.text(), 'Indexing') 157 + }) 158 + }) 159 + 160 + // --------------------------------------------------------------------------- 161 + // Profile rendering — 404/gone/error cases (no ClickHouse needed) 162 + // --------------------------------------------------------------------------- 163 + 164 + test.group('Profile error cases', (group) => { 165 + group.each.setup(() => testUtils.db().withGlobalTransaction()) 166 + 167 + // Test 14: Deleted user returns 410 168 + test('GET /profile/dril.bsky.social/likes for deleted user returns 410', async ({ 169 + client, 170 + assert, 171 + }) => { 172 + await User.create({ 173 + did: 'did:plc:deleted001', 174 + handle: 'dril.bsky.social', 175 + firstSeenAt: Date.now(), 176 + backfilledAt: Date.now(), 177 + deletedAt: Date.now(), 178 + }) 179 + 180 + const response = await client.get('/profile/dril.bsky.social/likes') 181 + response.assertStatus(410) 182 + assert.include(response.text(), 'no longer available') 183 + }) 184 + 185 + // Test 15: Invalid ?days=abc returns 400 186 + test('GET /profile/dril.bsky.social/likes?days=abc returns 400', async ({ client }) => { 187 + const response = await client.get('/profile/dril.bsky.social/likes?days=abc') 188 + response.assertStatus(400) 189 + }) 190 + 191 + // Test 16: ?days=99999 returns 400 (over cap of 3650) 192 + test('GET /profile/dril.bsky.social/likes?days=99999 returns 400', async ({ client }) => { 193 + const response = await client.get('/profile/dril.bsky.social/likes?days=99999') 194 + response.assertStatus(400) 195 + }) 196 + }) 197 + 198 + // --------------------------------------------------------------------------- 199 + // Profile rendering with real ClickHouse data 200 + // --------------------------------------------------------------------------- 201 + 202 + test.group('Profile rendering with ClickHouse', (group) => { 203 + let testDb: string 204 + let store: ClickHouseStore 205 + 206 + group.setup(async () => { 207 + const available = await isClickHouseAvailable() 208 + if (!available) return 209 + 210 + testDb = `test_profile_ctrl_${randomBytes(4).toString('hex')}` 211 + await applyMigrations(testDb) 212 + 213 + store = new ClickHouseStore({ 214 + url: CLICKHOUSE_URL, 215 + database: testDb, 216 + username: CLICKHOUSE_USER, 217 + password: CLICKHOUSE_PASSWORD, 218 + }) 219 + }) 220 + 221 + group.teardown(async () => { 222 + if (!testDb) return 223 + await store?.close() 224 + await dropDatabase(testDb) 225 + }) 226 + 227 + group.each.setup(() => testUtils.db().withGlobalTransaction()) 228 + 229 + group.each.teardown(async () => { 230 + if (!store) return 231 + await store.client.command({ query: 'TRUNCATE TABLE post_snapshots' }) 232 + await store.client.command({ query: 'TRUNCATE TABLE engagement_events' }) 233 + }) 234 + 235 + // Test 11: Backfilled user with posts renders show page with Cache-Control 236 + test('GET /profile/dril.bsky.social/likes shows profile with Cache-Control', async ({ 237 + client, 238 + assert, 239 + swap, 240 + }) => { 241 + // Swap the container ClickHouseStore with our test instance 242 + swap(ClickHouseStore, store) 243 + 244 + await User.create({ 245 + did: 'did:plc:test001', 246 + handle: 'dril.bsky.social', 247 + firstSeenAt: Date.now(), 248 + backfilledAt: Date.now(), 249 + }) 250 + 251 + await store.insertPostSnapshots([ 252 + { 253 + postUri: 'at://did:plc:test001/app.bsky.feed.post/rkey1', 254 + postAuthorDid: 'did:plc:test001', 255 + postText: 'Hello from dril', 256 + postCreatedAt: new Date('2024-01-15T12:00:00Z'), 257 + snapshotLikes: 42, 258 + snapshotReposts: 7, 259 + snapshotQuotes: 0, 260 + snapshotTakenAt: new Date('2024-01-15T12:00:00Z'), 261 + }, 262 + ]) 263 + 264 + const response = await client.get('/profile/dril.bsky.social/likes') 265 + response.assertStatus(200) 266 + response.assertHeader('cache-control', 'public, max-age=60') 267 + 268 + const html = response.text() 269 + assert.include(html, 'Most liked') 270 + assert.include(html, 'Hello from dril') 271 + }).skip(async () => !(await isClickHouseAvailable()), 'ClickHouse not available') 272 + 273 + // Test 12: ?days=30 windowed query excludes old posts 274 + test('GET /profile/dril.bsky.social/likes?days=30 windowed query', async ({ 275 + client, 276 + assert, 277 + swap, 278 + }) => { 279 + swap(ClickHouseStore, store) 280 + 281 + await User.create({ 282 + did: 'did:plc:test002', 283 + handle: 'dril.bsky.social', 284 + firstSeenAt: Date.now(), 285 + backfilledAt: Date.now(), 286 + }) 287 + 288 + // Recent post (should appear within 30-day window) 289 + await store.insertPostSnapshots([ 290 + { 291 + postUri: 'at://did:plc:test002/app.bsky.feed.post/recent', 292 + postAuthorDid: 'did:plc:test002', 293 + postText: 'Recent post within window', 294 + postCreatedAt: new Date(), // now — within 30 days 295 + snapshotLikes: 10, 296 + snapshotReposts: 2, 297 + snapshotQuotes: 0, 298 + snapshotTakenAt: new Date(), 299 + }, 300 + { 301 + postUri: 'at://did:plc:test002/app.bsky.feed.post/old', 302 + postAuthorDid: 'did:plc:test002', 303 + postText: 'Old post outside window', 304 + postCreatedAt: new Date('2020-01-01T00:00:00Z'), // well outside 30 days 305 + snapshotLikes: 9999, 306 + snapshotReposts: 9999, 307 + snapshotQuotes: 0, 308 + snapshotTakenAt: new Date('2020-01-01T00:00:00Z'), 309 + }, 310 + ]) 311 + 312 + const response = await client.get('/profile/dril.bsky.social/likes?days=30') 313 + response.assertStatus(200) 314 + const html = response.text() 315 + // Recent post should appear, old post should not 316 + assert.include(html, 'Recent post within window') 317 + assert.notInclude(html, 'Old post outside window') 318 + }).skip(async () => !(await isClickHouseAvailable()), 'ClickHouse not available') 319 + 320 + // Test 13: /reposts shows reposts kind toggle active 321 + test('GET /profile/dril.bsky.social/reposts shows reposts toggle as active', async ({ 322 + client, 323 + assert, 324 + swap, 325 + }) => { 326 + swap(ClickHouseStore, store) 327 + 328 + await User.create({ 329 + did: 'did:plc:test003', 330 + handle: 'dril.bsky.social', 331 + firstSeenAt: Date.now(), 332 + backfilledAt: Date.now(), 333 + }) 334 + 335 + await store.insertPostSnapshots([ 336 + { 337 + postUri: 'at://did:plc:test003/app.bsky.feed.post/rk1', 338 + postAuthorDid: 'did:plc:test003', 339 + postText: 'A popular repost', 340 + postCreatedAt: new Date(), 341 + snapshotLikes: 1, 342 + snapshotReposts: 5, 343 + snapshotQuotes: 0, 344 + snapshotTakenAt: new Date(), 345 + }, 346 + ]) 347 + 348 + const response = await client.get('/profile/dril.bsky.social/reposts') 349 + response.assertStatus(200) 350 + const html = response.text() 351 + assert.include(html, 'Most reposted') 352 + assert.include(html, 'A popular repost') 353 + }).skip(async () => !(await isClickHouseAvailable()), 'ClickHouse not available') 354 + })
+555
package-lock.json
··· 43 43 "@adonisjs/eslint-config": "^3.0.0", 44 44 "@adonisjs/prettier-config": "^1.4.5", 45 45 "@adonisjs/tsconfig": "^2.0.0", 46 + "@japa/api-client": "^3.2.1", 46 47 "@japa/assert": "^4.2.0", 47 48 "@japa/browser-client": "^2.3.0", 48 49 "@japa/plugin-adonisjs": "^5.2.0", ··· 1751 1752 "url": "https://github.com/sponsors/nzakas" 1752 1753 } 1753 1754 }, 1755 + "node_modules/@japa/api-client": { 1756 + "version": "3.2.1", 1757 + "resolved": "https://registry.npmjs.org/@japa/api-client/-/api-client-3.2.1.tgz", 1758 + "integrity": "sha512-dICbeEkgGRpjkm3CviOpvPfYMBZddaoW2w20pgNMm3CfvD2bixWOFn6FBRZRq5L+fHYe/O/xfSNGMCQBFy7Zlw==", 1759 + "devOptional": true, 1760 + "license": "MIT", 1761 + "dependencies": { 1762 + "@poppinss/hooks": "^7.3.0", 1763 + "@poppinss/macroable": "^1.1.0", 1764 + "@poppinss/qs": "^6.15.0", 1765 + "@types/superagent": "^8.1.9", 1766 + "cookie-es": "^2.0.0", 1767 + "set-cookie-parser": "^2.7.2", 1768 + "superagent": "^10.3.0" 1769 + }, 1770 + "engines": { 1771 + "node": ">=18.16.0" 1772 + }, 1773 + "peerDependencies": { 1774 + "@japa/assert": "^2.0.0 || ^3.0.0 || ^4.0.0", 1775 + "@japa/openapi-assertions": "^0.1.1", 1776 + "@japa/runner": "^3.1.2 || ^4.0.0 || ^5.0.0" 1777 + }, 1778 + "peerDependenciesMeta": { 1779 + "@japa/assert": { 1780 + "optional": true 1781 + }, 1782 + "@japa/openapi-assertions": { 1783 + "optional": true 1784 + } 1785 + } 1786 + }, 1787 + "node_modules/@japa/api-client/node_modules/cookie-es": { 1788 + "version": "2.0.1", 1789 + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-2.0.1.tgz", 1790 + "integrity": "sha512-aVf4A4hI2w70LnF7GG+7xDQUkliwiXWXFvTjkip4+b64ygDQ2sJPRSKFDHbxn8o0xu9QzPkMuuiWIXyFSE2slA==", 1791 + "devOptional": true, 1792 + "license": "MIT" 1793 + }, 1754 1794 "node_modules/@japa/assert": { 1755 1795 "version": "4.2.0", 1756 1796 "resolved": "https://registry.npmjs.org/@japa/assert/-/assert-4.2.0.tgz", ··· 1916 1956 "node": ">=8" 1917 1957 } 1918 1958 }, 1959 + "node_modules/@noble/hashes": { 1960 + "version": "1.8.0", 1961 + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", 1962 + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", 1963 + "devOptional": true, 1964 + "license": "MIT", 1965 + "engines": { 1966 + "node": "^14.21.3 || >=16" 1967 + }, 1968 + "funding": { 1969 + "url": "https://paulmillr.com/funding/" 1970 + } 1971 + }, 1919 1972 "node_modules/@nodelib/fs.scandir": { 1920 1973 "version": "2.1.5", 1921 1974 "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", ··· 1949 2002 }, 1950 2003 "engines": { 1951 2004 "node": ">= 8" 2005 + } 2006 + }, 2007 + "node_modules/@paralleldrive/cuid2": { 2008 + "version": "2.3.1", 2009 + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", 2010 + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", 2011 + "devOptional": true, 2012 + "license": "MIT", 2013 + "dependencies": { 2014 + "@noble/hashes": "^1.1.5" 1952 2015 } 1953 2016 }, 1954 2017 "node_modules/@phc/format": { ··· 2954 3017 "@types/deep-eql": "*", 2955 3018 "assertion-error": "^2.0.1" 2956 3019 } 3020 + }, 3021 + "node_modules/@types/cookiejar": { 3022 + "version": "2.1.5", 3023 + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", 3024 + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", 3025 + "devOptional": true, 3026 + "license": "MIT" 2957 3027 }, 2958 3028 "node_modules/@types/deep-eql": { 2959 3029 "version": "4.0.2", ··· 2995 3065 "dev": true, 2996 3066 "license": "MIT" 2997 3067 }, 3068 + "node_modules/@types/methods": { 3069 + "version": "1.1.4", 3070 + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", 3071 + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", 3072 + "devOptional": true, 3073 + "license": "MIT" 3074 + }, 2998 3075 "node_modules/@types/node": { 2999 3076 "version": "25.5.2", 3000 3077 "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", ··· 3017 3094 "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.33.tgz", 3018 3095 "integrity": "sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==", 3019 3096 "license": "MIT" 3097 + }, 3098 + "node_modules/@types/superagent": { 3099 + "version": "8.1.9", 3100 + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", 3101 + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", 3102 + "devOptional": true, 3103 + "license": "MIT", 3104 + "dependencies": { 3105 + "@types/cookiejar": "^2.1.5", 3106 + "@types/methods": "^1.1.4", 3107 + "@types/node": "*", 3108 + "form-data": "^4.0.0" 3109 + } 3020 3110 }, 3021 3111 "node_modules/@types/validator": { 3022 3112 "version": "13.15.10", ··· 3418 3508 "url": "https://github.com/chalk/ansi-styles?sponsor=1" 3419 3509 } 3420 3510 }, 3511 + "node_modules/asap": { 3512 + "version": "2.0.6", 3513 + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 3514 + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", 3515 + "devOptional": true, 3516 + "license": "MIT" 3517 + }, 3421 3518 "node_modules/assertion-error": { 3422 3519 "version": "2.0.1", 3423 3520 "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", ··· 3446 3543 "dependencies": { 3447 3544 "retry": "0.13.1" 3448 3545 } 3546 + }, 3547 + "node_modules/asynckit": { 3548 + "version": "0.4.0", 3549 + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 3550 + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 3551 + "devOptional": true, 3552 + "license": "MIT" 3449 3553 }, 3450 3554 "node_modules/atomic-sleep": { 3451 3555 "version": "1.0.0", ··· 3657 3761 "node": ">= 0.8" 3658 3762 } 3659 3763 }, 3764 + "node_modules/call-bind-apply-helpers": { 3765 + "version": "1.0.2", 3766 + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 3767 + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 3768 + "devOptional": true, 3769 + "license": "MIT", 3770 + "dependencies": { 3771 + "es-errors": "^1.3.0", 3772 + "function-bind": "^1.1.2" 3773 + }, 3774 + "engines": { 3775 + "node": ">= 0.4" 3776 + } 3777 + }, 3778 + "node_modules/call-bound": { 3779 + "version": "1.0.4", 3780 + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 3781 + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 3782 + "devOptional": true, 3783 + "license": "MIT", 3784 + "dependencies": { 3785 + "call-bind-apply-helpers": "^1.0.2", 3786 + "get-intrinsic": "^1.3.0" 3787 + }, 3788 + "engines": { 3789 + "node": ">= 0.4" 3790 + }, 3791 + "funding": { 3792 + "url": "https://github.com/sponsors/ljharb" 3793 + } 3794 + }, 3660 3795 "node_modules/camelcase": { 3661 3796 "version": "9.0.0", 3662 3797 "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-9.0.0.tgz", ··· 3947 4082 "devOptional": true, 3948 4083 "license": "MIT" 3949 4084 }, 4085 + "node_modules/combined-stream": { 4086 + "version": "1.0.8", 4087 + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 4088 + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 4089 + "devOptional": true, 4090 + "license": "MIT", 4091 + "dependencies": { 4092 + "delayed-stream": "~1.0.0" 4093 + }, 4094 + "engines": { 4095 + "node": ">= 0.8" 4096 + } 4097 + }, 3950 4098 "node_modules/commander": { 3951 4099 "version": "10.0.1", 3952 4100 "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", ··· 3963 4111 "devOptional": true, 3964 4112 "license": "ISC" 3965 4113 }, 4114 + "node_modules/component-emitter": { 4115 + "version": "1.3.1", 4116 + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", 4117 + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", 4118 + "devOptional": true, 4119 + "license": "MIT", 4120 + "funding": { 4121 + "url": "https://github.com/sponsors/sindresorhus" 4122 + } 4123 + }, 3966 4124 "node_modules/content-disposition": { 3967 4125 "version": "1.1.0", 3968 4126 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", ··· 3989 4147 "version": "3.1.1", 3990 4148 "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", 3991 4149 "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", 4150 + "license": "MIT" 4151 + }, 4152 + "node_modules/cookiejar": { 4153 + "version": "2.1.4", 4154 + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", 4155 + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", 4156 + "devOptional": true, 3992 4157 "license": "MIT" 3993 4158 }, 3994 4159 "node_modules/core-js-compat": { ··· 4172 4337 "url": "https://github.com/sponsors/sindresorhus" 4173 4338 } 4174 4339 }, 4340 + "node_modules/delayed-stream": { 4341 + "version": "1.0.0", 4342 + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 4343 + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 4344 + "devOptional": true, 4345 + "license": "MIT", 4346 + "engines": { 4347 + "node": ">=0.4.0" 4348 + } 4349 + }, 4175 4350 "node_modules/depd": { 4176 4351 "version": "2.0.0", 4177 4352 "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", ··· 4200 4375 "node": ">=8" 4201 4376 } 4202 4377 }, 4378 + "node_modules/dezalgo": { 4379 + "version": "1.0.4", 4380 + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", 4381 + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", 4382 + "devOptional": true, 4383 + "license": "ISC", 4384 + "dependencies": { 4385 + "asap": "^2.0.0", 4386 + "wrappy": "1" 4387 + } 4388 + }, 4203 4389 "node_modules/dlv": { 4204 4390 "version": "1.1.3", 4205 4391 "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 4206 4392 "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 4207 4393 "license": "MIT" 4208 4394 }, 4395 + "node_modules/dunder-proto": { 4396 + "version": "1.0.1", 4397 + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 4398 + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 4399 + "devOptional": true, 4400 + "license": "MIT", 4401 + "dependencies": { 4402 + "call-bind-apply-helpers": "^1.0.1", 4403 + "es-errors": "^1.3.0", 4404 + "gopd": "^1.2.0" 4405 + }, 4406 + "engines": { 4407 + "node": ">= 0.4" 4408 + } 4409 + }, 4209 4410 "node_modules/edge-error": { 4210 4411 "version": "4.0.2", 4211 4412 "resolved": "https://registry.npmjs.org/edge-error/-/edge-error-4.0.2.tgz", ··· 4356 4557 "url": "https://github.com/sponsors/antfu" 4357 4558 } 4358 4559 }, 4560 + "node_modules/es-define-property": { 4561 + "version": "1.0.1", 4562 + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 4563 + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 4564 + "devOptional": true, 4565 + "license": "MIT", 4566 + "engines": { 4567 + "node": ">= 0.4" 4568 + } 4569 + }, 4570 + "node_modules/es-errors": { 4571 + "version": "1.3.0", 4572 + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 4573 + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 4574 + "devOptional": true, 4575 + "license": "MIT", 4576 + "engines": { 4577 + "node": ">= 0.4" 4578 + } 4579 + }, 4359 4580 "node_modules/es-module-lexer": { 4360 4581 "version": "1.7.0", 4361 4582 "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 4362 4583 "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 4363 4584 "license": "MIT" 4585 + }, 4586 + "node_modules/es-object-atoms": { 4587 + "version": "1.1.1", 4588 + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 4589 + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 4590 + "devOptional": true, 4591 + "license": "MIT", 4592 + "dependencies": { 4593 + "es-errors": "^1.3.0" 4594 + }, 4595 + "engines": { 4596 + "node": ">= 0.4" 4597 + } 4598 + }, 4599 + "node_modules/es-set-tostringtag": { 4600 + "version": "2.1.0", 4601 + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 4602 + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 4603 + "devOptional": true, 4604 + "license": "MIT", 4605 + "dependencies": { 4606 + "es-errors": "^1.3.0", 4607 + "get-intrinsic": "^1.2.6", 4608 + "has-tostringtag": "^1.0.2", 4609 + "hasown": "^2.0.2" 4610 + }, 4611 + "engines": { 4612 + "node": ">= 0.4" 4613 + } 4364 4614 }, 4365 4615 "node_modules/esbuild": { 4366 4616 "version": "0.27.7", ··· 5018 5268 "node": ">=8" 5019 5269 } 5020 5270 }, 5271 + "node_modules/form-data": { 5272 + "version": "4.0.5", 5273 + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", 5274 + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", 5275 + "devOptional": true, 5276 + "license": "MIT", 5277 + "dependencies": { 5278 + "asynckit": "^0.4.0", 5279 + "combined-stream": "^1.0.8", 5280 + "es-set-tostringtag": "^2.1.0", 5281 + "hasown": "^2.0.2", 5282 + "mime-types": "^2.1.12" 5283 + }, 5284 + "engines": { 5285 + "node": ">= 6" 5286 + } 5287 + }, 5288 + "node_modules/form-data/node_modules/mime-db": { 5289 + "version": "1.52.0", 5290 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 5291 + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 5292 + "devOptional": true, 5293 + "license": "MIT", 5294 + "engines": { 5295 + "node": ">= 0.6" 5296 + } 5297 + }, 5298 + "node_modules/form-data/node_modules/mime-types": { 5299 + "version": "2.1.35", 5300 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 5301 + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 5302 + "devOptional": true, 5303 + "license": "MIT", 5304 + "dependencies": { 5305 + "mime-db": "1.52.0" 5306 + }, 5307 + "engines": { 5308 + "node": ">= 0.6" 5309 + } 5310 + }, 5311 + "node_modules/formidable": { 5312 + "version": "3.5.4", 5313 + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", 5314 + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", 5315 + "devOptional": true, 5316 + "license": "MIT", 5317 + "dependencies": { 5318 + "@paralleldrive/cuid2": "^2.2.2", 5319 + "dezalgo": "^1.0.4", 5320 + "once": "^1.4.0" 5321 + }, 5322 + "engines": { 5323 + "node": ">=14.0.0" 5324 + }, 5325 + "funding": { 5326 + "url": "https://ko-fi.com/tunnckoCore/commissions" 5327 + } 5328 + }, 5021 5329 "node_modules/forwarded": { 5022 5330 "version": "0.2.0", 5023 5331 "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", ··· 5077 5385 "url": "https://github.com/sponsors/sindresorhus" 5078 5386 } 5079 5387 }, 5388 + "node_modules/get-intrinsic": { 5389 + "version": "1.3.0", 5390 + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 5391 + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 5392 + "devOptional": true, 5393 + "license": "MIT", 5394 + "dependencies": { 5395 + "call-bind-apply-helpers": "^1.0.2", 5396 + "es-define-property": "^1.0.1", 5397 + "es-errors": "^1.3.0", 5398 + "es-object-atoms": "^1.1.1", 5399 + "function-bind": "^1.1.2", 5400 + "get-proto": "^1.0.1", 5401 + "gopd": "^1.2.0", 5402 + "has-symbols": "^1.1.0", 5403 + "hasown": "^2.0.2", 5404 + "math-intrinsics": "^1.1.0" 5405 + }, 5406 + "engines": { 5407 + "node": ">= 0.4" 5408 + }, 5409 + "funding": { 5410 + "url": "https://github.com/sponsors/ljharb" 5411 + } 5412 + }, 5080 5413 "node_modules/get-package-type": { 5081 5414 "version": "0.1.0", 5082 5415 "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", ··· 5098 5431 "url": "https://github.com/sponsors/sindresorhus" 5099 5432 } 5100 5433 }, 5434 + "node_modules/get-proto": { 5435 + "version": "1.0.1", 5436 + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 5437 + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 5438 + "devOptional": true, 5439 + "license": "MIT", 5440 + "dependencies": { 5441 + "dunder-proto": "^1.0.1", 5442 + "es-object-atoms": "^1.0.0" 5443 + }, 5444 + "engines": { 5445 + "node": ">= 0.4" 5446 + } 5447 + }, 5101 5448 "node_modules/get-stream": { 5102 5449 "version": "9.0.1", 5103 5450 "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", ··· 5163 5510 "url": "https://github.com/sponsors/sindresorhus" 5164 5511 } 5165 5512 }, 5513 + "node_modules/gopd": { 5514 + "version": "1.2.0", 5515 + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 5516 + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 5517 + "devOptional": true, 5518 + "license": "MIT", 5519 + "engines": { 5520 + "node": ">= 0.4" 5521 + }, 5522 + "funding": { 5523 + "url": "https://github.com/sponsors/ljharb" 5524 + } 5525 + }, 5166 5526 "node_modules/has-flag": { 5167 5527 "version": "4.0.0", 5168 5528 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ··· 5171 5531 "license": "MIT", 5172 5532 "engines": { 5173 5533 "node": ">=8" 5534 + } 5535 + }, 5536 + "node_modules/has-symbols": { 5537 + "version": "1.1.0", 5538 + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 5539 + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 5540 + "devOptional": true, 5541 + "license": "MIT", 5542 + "engines": { 5543 + "node": ">= 0.4" 5544 + }, 5545 + "funding": { 5546 + "url": "https://github.com/sponsors/ljharb" 5547 + } 5548 + }, 5549 + "node_modules/has-tostringtag": { 5550 + "version": "1.0.2", 5551 + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 5552 + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 5553 + "devOptional": true, 5554 + "license": "MIT", 5555 + "dependencies": { 5556 + "has-symbols": "^1.0.3" 5557 + }, 5558 + "engines": { 5559 + "node": ">= 0.4" 5560 + }, 5561 + "funding": { 5562 + "url": "https://github.com/sponsors/ljharb" 5174 5563 } 5175 5564 }, 5176 5565 "node_modules/hasown": { ··· 5987 6376 "node": ">=12" 5988 6377 } 5989 6378 }, 6379 + "node_modules/math-intrinsics": { 6380 + "version": "1.1.0", 6381 + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 6382 + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 6383 + "devOptional": true, 6384 + "license": "MIT", 6385 + "engines": { 6386 + "node": ">= 0.4" 6387 + } 6388 + }, 5990 6389 "node_modules/media-typer": { 5991 6390 "version": "1.1.0", 5992 6391 "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", ··· 6005 6404 "node": ">= 8" 6006 6405 } 6007 6406 }, 6407 + "node_modules/methods": { 6408 + "version": "1.1.2", 6409 + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 6410 + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 6411 + "devOptional": true, 6412 + "license": "MIT", 6413 + "engines": { 6414 + "node": ">= 0.6" 6415 + } 6416 + }, 6008 6417 "node_modules/micromatch": { 6009 6418 "version": "4.0.8", 6010 6419 "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", ··· 6030 6439 "url": "https://github.com/sponsors/jonschlinkert" 6031 6440 } 6032 6441 }, 6442 + "node_modules/mime": { 6443 + "version": "2.6.0", 6444 + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", 6445 + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", 6446 + "devOptional": true, 6447 + "license": "MIT", 6448 + "bin": { 6449 + "mime": "cli.js" 6450 + }, 6451 + "engines": { 6452 + "node": ">=4.0.0" 6453 + } 6454 + }, 6033 6455 "node_modules/mime-db": { 6034 6456 "version": "1.54.0", 6035 6457 "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", ··· 6224 6646 }, 6225 6647 "funding": { 6226 6648 "url": "https://github.com/sponsors/sindresorhus" 6649 + } 6650 + }, 6651 + "node_modules/object-inspect": { 6652 + "version": "1.13.4", 6653 + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 6654 + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 6655 + "devOptional": true, 6656 + "license": "MIT", 6657 + "engines": { 6658 + "node": ">= 0.4" 6659 + }, 6660 + "funding": { 6661 + "url": "https://github.com/sponsors/ljharb" 6227 6662 } 6228 6663 }, 6229 6664 "node_modules/on-exit-leak-free": { ··· 6821 7256 "node": ">=6" 6822 7257 } 6823 7258 }, 7259 + "node_modules/qs": { 7260 + "version": "6.15.1", 7261 + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", 7262 + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", 7263 + "devOptional": true, 7264 + "license": "BSD-3-Clause", 7265 + "dependencies": { 7266 + "side-channel": "^1.1.0" 7267 + }, 7268 + "engines": { 7269 + "node": ">=0.6" 7270 + }, 7271 + "funding": { 7272 + "url": "https://github.com/sponsors/ljharb" 7273 + } 7274 + }, 6824 7275 "node_modules/queue-microtask": { 6825 7276 "version": "1.2.3", 6826 7277 "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", ··· 7302 7753 "url": "https://opencollective.com/express" 7303 7754 } 7304 7755 }, 7756 + "node_modules/set-cookie-parser": { 7757 + "version": "2.7.2", 7758 + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", 7759 + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", 7760 + "devOptional": true, 7761 + "license": "MIT" 7762 + }, 7305 7763 "node_modules/setprototypeof": { 7306 7764 "version": "1.2.0", 7307 7765 "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", ··· 7329 7787 "node": ">=8" 7330 7788 } 7331 7789 }, 7790 + "node_modules/side-channel": { 7791 + "version": "1.1.0", 7792 + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 7793 + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 7794 + "devOptional": true, 7795 + "license": "MIT", 7796 + "dependencies": { 7797 + "es-errors": "^1.3.0", 7798 + "object-inspect": "^1.13.3", 7799 + "side-channel-list": "^1.0.0", 7800 + "side-channel-map": "^1.0.1", 7801 + "side-channel-weakmap": "^1.0.2" 7802 + }, 7803 + "engines": { 7804 + "node": ">= 0.4" 7805 + }, 7806 + "funding": { 7807 + "url": "https://github.com/sponsors/ljharb" 7808 + } 7809 + }, 7810 + "node_modules/side-channel-list": { 7811 + "version": "1.0.1", 7812 + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", 7813 + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", 7814 + "devOptional": true, 7815 + "license": "MIT", 7816 + "dependencies": { 7817 + "es-errors": "^1.3.0", 7818 + "object-inspect": "^1.13.4" 7819 + }, 7820 + "engines": { 7821 + "node": ">= 0.4" 7822 + }, 7823 + "funding": { 7824 + "url": "https://github.com/sponsors/ljharb" 7825 + } 7826 + }, 7827 + "node_modules/side-channel-map": { 7828 + "version": "1.0.1", 7829 + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 7830 + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 7831 + "devOptional": true, 7832 + "license": "MIT", 7833 + "dependencies": { 7834 + "call-bound": "^1.0.2", 7835 + "es-errors": "^1.3.0", 7836 + "get-intrinsic": "^1.2.5", 7837 + "object-inspect": "^1.13.3" 7838 + }, 7839 + "engines": { 7840 + "node": ">= 0.4" 7841 + }, 7842 + "funding": { 7843 + "url": "https://github.com/sponsors/ljharb" 7844 + } 7845 + }, 7846 + "node_modules/side-channel-weakmap": { 7847 + "version": "1.0.2", 7848 + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 7849 + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 7850 + "devOptional": true, 7851 + "license": "MIT", 7852 + "dependencies": { 7853 + "call-bound": "^1.0.2", 7854 + "es-errors": "^1.3.0", 7855 + "get-intrinsic": "^1.2.5", 7856 + "object-inspect": "^1.13.3", 7857 + "side-channel-map": "^1.0.1" 7858 + }, 7859 + "engines": { 7860 + "node": ">= 0.4" 7861 + }, 7862 + "funding": { 7863 + "url": "https://github.com/sponsors/ljharb" 7864 + } 7865 + }, 7332 7866 "node_modules/signal-exit": { 7333 7867 "version": "4.1.0", 7334 7868 "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", ··· 7676 8210 "funding": { 7677 8211 "type": "github", 7678 8212 "url": "https://github.com/sponsors/Borewit" 8213 + } 8214 + }, 8215 + "node_modules/superagent": { 8216 + "version": "10.3.0", 8217 + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", 8218 + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", 8219 + "devOptional": true, 8220 + "license": "MIT", 8221 + "dependencies": { 8222 + "component-emitter": "^1.3.1", 8223 + "cookiejar": "^2.1.4", 8224 + "debug": "^4.3.7", 8225 + "fast-safe-stringify": "^2.1.1", 8226 + "form-data": "^4.0.5", 8227 + "formidable": "^3.5.4", 8228 + "methods": "^1.1.2", 8229 + "mime": "2.6.0", 8230 + "qs": "^6.14.1" 8231 + }, 8232 + "engines": { 8233 + "node": ">=14.18.0" 7679 8234 } 7680 8235 }, 7681 8236 "node_modules/supports-color": {