diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c1c6737..a2700131 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,12 +38,6 @@ jobs: run: npm install @rollup/rollup-linux-x64-gnu --no-save working-directory: frontend - # Frontend devDeps do not list @vitest/coverage-v8 (mirrors the - # backend workflow), so install it ad-hoc before coverage runs. - - name: Install Vitest Coverage Provider - run: npm install @vitest/coverage-v8@3.2.7 --no-save - working-directory: frontend - - name: Run Frontend Tests run: npm run test:coverage working-directory: frontend diff --git a/.github/workflows/pr-test-gate.yml b/.github/workflows/pr-test-gate.yml index 529ad8c1..49c97b09 100644 --- a/.github/workflows/pr-test-gate.yml +++ b/.github/workflows/pr-test-gate.yml @@ -61,14 +61,8 @@ jobs: env: DATABASE_URL: postgresql://postgres:password@127.0.0.1:5432/flowfi_test - # mirrors the ci.yml backend job: vitest's coverage provider is - # enabled by default in backend/vitest.config.ts, so the @vitest/ - # coverage-v8 package must be present before `npm test` runs. - # Also installs the rollup native binding into backend/node_modules - # (where vitest actually resolves it from) rather than the root. - - name: Install Vitest + Native Bindings + - name: Install Native Bindings run: | - npm install @vitest/coverage-v8@3.2.7 --no-save npm install @rollup/rollup-linux-x64-gnu --no-save working-directory: backend diff --git a/backend/src/lib/pg-pool.ts b/backend/src/lib/pg-pool.ts index 31337dea..5b592bac 100644 --- a/backend/src/lib/pg-pool.ts +++ b/backend/src/lib/pg-pool.ts @@ -10,15 +10,16 @@ const parsePositiveIntegerEnv = (name: string, defaultValue: number): number => return Number.isInteger(parsedValue) && parsedValue > 0 ? parsedValue : defaultValue; }; -export const createPgPoolConfig = (): pg.PoolConfig => ({ +export const createPgPoolConfig = (overrides?: Partial): pg.PoolConfig => ({ connectionString: process.env.DATABASE_URL, max: parsePositiveIntegerEnv('PG_POOL_MAX', 10), idleTimeoutMillis: parsePositiveIntegerEnv('PG_IDLE_TIMEOUT_MS', 30_000), connectionTimeoutMillis: parsePositiveIntegerEnv('PG_CONNECTION_TIMEOUT_MS', 5_000), statement_timeout: parsePositiveIntegerEnv('PG_STATEMENT_TIMEOUT_MS', 30_000), + ...overrides, }); -export const createPgPool = () => new pg.Pool(createPgPoolConfig()); +export const createPgPool = (overrides?: Partial) => new pg.Pool(createPgPoolConfig(overrides)); export interface PoolMetrics { totalCount: number; diff --git a/backend/tests/integration/admin-metrics.test.ts b/backend/tests/integration/admin-metrics.test.ts index f56fd71d..470706b1 100644 --- a/backend/tests/integration/admin-metrics.test.ts +++ b/backend/tests/integration/admin-metrics.test.ts @@ -83,11 +83,7 @@ vi.mock('../../src/middleware/auth.js', async () => { const actual = await vi.importActual( '../../src/middleware/auth.js', ); - return { - ...actual, - requireAdmin: (_req: unknown, _res: unknown, next: () => void) => next(), - requireAuth: (_req: unknown, _res: unknown, next: () => void) => next(), - }; + return actual; }); vi.mock('../../src/services/indexerService.js', () => ({ @@ -108,13 +104,33 @@ vi.mock('../../src/workers/soroban-event-worker.js', () => ({ SorobanEventWorker: vi.fn(), })); -// ─── Import app after mocks are registered ──────────────────────────────────── +// ─── Import app and auth after mocks are registered ────────────────────────── import app from '../../src/app.js'; import { sorobanEventWorker } from '../../src/workers/soroban-event-worker.js'; +import { signJwt } from '../../src/middleware/auth.js'; +import { + getIndexerStatus, + resetIndexer, + replayFromLedger, +} from '../../src/services/indexerService.js'; // ─── Helpers ────────────────────────────────────────────────────────────────── +const ADMIN_PUBLIC_KEY = 'GADMIN12345678901234567890123456789012345678901234567890'; +const NON_ADMIN_PUBLIC_KEY = 'GUSER12345678901234567890123456789012345678901234567890'; + +function createToken(publicKey: string = ADMIN_PUBLIC_KEY): string { + const now = Math.floor(Date.now() / 1000); + return signJwt({ + sub: publicKey, + iat: now, + exp: now + 3600, + iss: 'flowfi-api', + aud: 'flowfi-api', + }); +} + function setupCounts({ total = 10, active = 6, @@ -136,6 +152,7 @@ function setupCounts({ describe('GET /v1/admin/metrics', () => { beforeEach(() => { vi.clearAllMocks(); + process.env.ADMIN_PUBLIC_KEY = ADMIN_PUBLIC_KEY; mocks.cache.get.mockReturnValue(null); mocks.prisma.streamEvent.count.mockResolvedValue(0); mocks.prisma.streamEvent.findMany.mockResolvedValue([]); @@ -151,7 +168,9 @@ describe('GET /v1/admin/metrics', () => { { withdrawnAmount: '0' }, ]); - const res = await request(app).get('/v1/admin/metrics'); + const res = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(res.status).toBe(200); expect(res.body).toMatchObject({ @@ -173,7 +192,9 @@ describe('GET /v1/admin/metrics', () => { { withdrawnAmount: '9007199254740993' }, ]); - const res = await request(app).get('/v1/admin/metrics'); + const res = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(res.status).toBe(200); expect(res.body.total_volume_streamed).toBe('18014398509481986'); @@ -182,7 +203,9 @@ describe('GET /v1/admin/metrics', () => { it('caches the response for 60 seconds', async () => { setupCounts({ total: 4, active: 4 }); - const first = await request(app).get('/v1/admin/metrics'); + const first = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(first.status).toBe(200); expect(first.headers['x-cache']).toBe('MISS'); @@ -214,7 +237,9 @@ describe('GET /v1/admin/metrics', () => { }; mocks.cache.get.mockReturnValueOnce(cachedPayload); - const res = await request(app).get('/v1/admin/metrics'); + const res = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(res.status).toBe(200); expect(res.headers['x-cache']).toBe('HIT'); @@ -232,7 +257,9 @@ describe('GET /v1/admin/metrics', () => { degraded: true, }); - const res = await request(app).get('/v1/admin/metrics'); + const res = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(res.status).toBe(200); expect(res.body.indexer).toMatchObject({ @@ -263,7 +290,9 @@ describe('GET /v1/admin/metrics', () => { degraded: true, }); - const res = await request(app).get('/v1/admin/metrics'); + const res = await request(app) + .get('/v1/admin/metrics') + .set('Authorization', `Bearer ${createToken()}`); expect(res.status).toBe(200); expect(res.headers['x-cache']).toBe('HIT'); @@ -276,3 +305,192 @@ describe('GET /v1/admin/metrics', () => { }); }); }); + +describe('GET /v1/admin/indexer/status', () => { + beforeEach(() => { + vi.clearAllMocks(); + process.env.ADMIN_PUBLIC_KEY = ADMIN_PUBLIC_KEY; + }); + + it('enforces requireAdmin (401 without token, 403 with non-admin token)', async () => { + const noTokenRes = await request(app).get('/v1/admin/indexer/status'); + expect(noTokenRes.status).toBe(401); + + const nonAdminRes = await request(app) + .get('/v1/admin/indexer/status') + .set('Authorization', `Bearer ${createToken(NON_ADMIN_PUBLIC_KEY)}`); + expect(nonAdminRes.status).toBe(403); + expect(nonAdminRes.body.error).toBe('Forbidden'); + }); + + it('returns status 200 with indexer status data for admin', async () => { + const mockStatus = { + lastLedger: 12345, + lastCursor: 'cursor_abc', + updatedAt: '2026-08-08T00:00:00.000Z', + lagSeconds: 12, + }; + vi.mocked(getIndexerStatus).mockResolvedValueOnce(mockStatus as any); + + const res = await request(app) + .get('/v1/admin/indexer/status') + .set('Authorization', `Bearer ${createToken()}`); + + expect(res.status).toBe(200); + expect(res.body).toEqual(mockStatus); + expect(getIndexerStatus).toHaveBeenCalledTimes(1); + }); + + it('returns status 500 if getIndexerStatus throws', async () => { + vi.mocked(getIndexerStatus).mockRejectedValueOnce(new Error('DB failure')); + + const res = await request(app) + .get('/v1/admin/indexer/status') + .set('Authorization', `Bearer ${createToken()}`); + + expect(res.status).toBe(500); + expect(res.body).toEqual({ error: 'Failed to fetch indexer status' }); + }); +}); + +describe('POST /v1/admin/indexer/reset', () => { + beforeEach(() => { + vi.clearAllMocks(); + process.env.ADMIN_PUBLIC_KEY = ADMIN_PUBLIC_KEY; + vi.mocked(resetIndexer).mockResolvedValue(undefined); + }); + + it('enforces requireAdmin (401 without token, 403 with non-admin token)', async () => { + const noTokenRes = await request(app) + .post('/v1/admin/indexer/reset') + .send({ ledger: 100 }); + expect(noTokenRes.status).toBe(401); + + const nonAdminRes = await request(app) + .post('/v1/admin/indexer/reset') + .set('Authorization', `Bearer ${createToken(NON_ADMIN_PUBLIC_KEY)}`) + .send({ ledger: 100 }); + expect(nonAdminRes.status).toBe(403); + }); + + it('returns 400 when ledger is missing, negative, or non-integer', async () => { + const cases = [ + {}, + { ledger: -1 }, + { ledger: -100 }, + { ledger: 12.34 }, + { ledger: 'not-a-number' }, + ]; + + for (const body of cases) { + const res = await request(app) + .post('/v1/admin/indexer/reset') + .set('Authorization', `Bearer ${createToken()}`) + .send(body); + + expect(res.status).toBe(400); + expect(res.body).toEqual({ error: 'ledger must be a non-negative integer' }); + } + + expect(resetIndexer).not.toHaveBeenCalled(); + }); + + it('returns 200 and calls resetIndexer with parsed ledger for valid requests', async () => { + const validCases = [ + { body: { ledger: 500 }, expected: 500 }, + { body: { ledger: 0 }, expected: 0 }, + { body: { ledger: '123' }, expected: 123 }, + ]; + + for (const { body, expected } of validCases) { + const res = await request(app) + .post('/v1/admin/indexer/reset') + .set('Authorization', `Bearer ${createToken()}`) + .send(body); + + expect(res.status).toBe(200); + expect(res.body).toEqual({ ok: true, lastLedger: expected }); + expect(resetIndexer).toHaveBeenCalledWith(expected); + } + }); + + it('returns 500 when resetIndexer throws an error', async () => { + vi.mocked(resetIndexer).mockRejectedValueOnce(new Error('Reset operation failed')); + + const res = await request(app) + .post('/v1/admin/indexer/reset') + .set('Authorization', `Bearer ${createToken()}`) + .send({ ledger: 100 }); + + expect(res.status).toBe(500); + expect(res.body).toEqual({ error: 'Reset failed' }); + }); +}); + +describe('POST /v1/admin/indexer/replay', () => { + beforeEach(() => { + vi.clearAllMocks(); + process.env.ADMIN_PUBLIC_KEY = ADMIN_PUBLIC_KEY; + vi.mocked(replayFromLedger).mockResolvedValue(undefined as any); + }); + + it('enforces requireAdmin (401 without token, 403 with non-admin token)', async () => { + const noTokenRes = await request(app).post('/v1/admin/indexer/replay?from_ledger=100'); + expect(noTokenRes.status).toBe(401); + + const nonAdminRes = await request(app) + .post('/v1/admin/indexer/replay?from_ledger=100') + .set('Authorization', `Bearer ${createToken(NON_ADMIN_PUBLIC_KEY)}`); + expect(nonAdminRes.status).toBe(403); + }); + + it('returns 400 when from_ledger query parameter is missing, negative, or non-integer', async () => { + const queryUrls = [ + '/v1/admin/indexer/replay', + '/v1/admin/indexer/replay?from_ledger=-1', + '/v1/admin/indexer/replay?from_ledger=-50', + '/v1/admin/indexer/replay?from_ledger=3.14', + '/v1/admin/indexer/replay?from_ledger=invalid', + ]; + + for (const url of queryUrls) { + const res = await request(app) + .post(url) + .set('Authorization', `Bearer ${createToken()}`); + + expect(res.status).toBe(400); + expect(res.body).toEqual({ error: 'from_ledger must be a non-negative integer' }); + } + + expect(replayFromLedger).not.toHaveBeenCalled(); + }); + + it('returns 202 and calls replayFromLedger with parsed from_ledger for valid requests', async () => { + const validCases = [ + { url: '/v1/admin/indexer/replay?from_ledger=200', expected: 200 }, + { url: '/v1/admin/indexer/replay?from_ledger=0', expected: 0 }, + ]; + + for (const { url, expected } of validCases) { + const res = await request(app) + .post(url) + .set('Authorization', `Bearer ${createToken()}`); + + expect(res.status).toBe(202); + expect(res.body).toMatchObject({ ok: true, replayingFrom: expected }); + expect(replayFromLedger).toHaveBeenCalledWith(expected); + } + }); + + it('returns 500 when replayFromLedger throws an error', async () => { + vi.mocked(replayFromLedger).mockRejectedValueOnce(new Error('Replay operation failed')); + + const res = await request(app) + .post('/v1/admin/indexer/replay?from_ledger=200') + .set('Authorization', `Bearer ${createToken()}`); + + expect(res.status).toBe(500); + expect(res.body).toEqual({ error: 'Replay failed' }); + }); +}); + diff --git a/backend/tests/integration/stream-lifecycle.test.ts b/backend/tests/integration/stream-lifecycle.test.ts index 8fcd220a..72f225a3 100644 --- a/backend/tests/integration/stream-lifecycle.test.ts +++ b/backend/tests/integration/stream-lifecycle.test.ts @@ -251,8 +251,9 @@ describe("Stream Lifecycle Integration Tests", () => { const { PrismaClient } = await import( "../../src/generated/prisma/index.js" ); + const { createPgPool } = await import("../../src/lib/pg-pool.js"); const connectionString = resolveTestDatabaseUrl(); - testPool = new pg.Pool({ connectionString }); + testPool = createPgPool({ connectionString }); const testAdapter = new PrismaPg(testPool); testPrisma = new PrismaClient({ adapter: testAdapter, diff --git a/backend/tests/pg-pool.test.ts b/backend/tests/pg-pool.test.ts index d5aa7cfd..443925b2 100644 --- a/backend/tests/pg-pool.test.ts +++ b/backend/tests/pg-pool.test.ts @@ -23,25 +23,71 @@ describe('pg-pool', () => { vi.unstubAllEnvs(); }); - it('createPgPoolConfig reflects an overridden DATABASE_URL', async () => { - vi.stubEnv('DATABASE_URL', 'postgresql://test:test@localhost:5432/test_db'); + it('createPgPoolConfig returns sane default pool settings when env vars are unset', async () => { + const { createPgPoolConfig } = await import('../src/lib/pg-pool.js'); + const config = createPgPoolConfig(); + + expect(config.max).toBe(10); + expect(config.idleTimeoutMillis).toBe(30_000); + expect(config.connectionTimeoutMillis).toBe(5_000); + expect(config.statement_timeout).toBe(30_000); + }); + + it('createPgPoolConfig reflects custom env variable overrides', async () => { + vi.stubEnv('PG_POOL_MAX', '25'); + vi.stubEnv('PG_IDLE_TIMEOUT_MS', '60000'); + vi.stubEnv('PG_CONNECTION_TIMEOUT_MS', '10000'); + vi.stubEnv('PG_STATEMENT_TIMEOUT_MS', '15000'); const { createPgPoolConfig } = await import('../src/lib/pg-pool.js'); + const config = createPgPoolConfig(); - expect(createPgPoolConfig().connectionString).toBe( - 'postgresql://test:test@localhost:5432/test_db', - ); + expect(config.max).toBe(25); + expect(config.idleTimeoutMillis).toBe(60_000); + expect(config.connectionTimeoutMillis).toBe(10_000); + expect(config.statement_timeout).toBe(15_000); + }); + + it('createPgPoolConfig falls back to defaults when env variables are invalid or non-positive', async () => { + vi.stubEnv('PG_POOL_MAX', 'invalid_number'); + vi.stubEnv('PG_IDLE_TIMEOUT_MS', '-5000'); + vi.stubEnv('PG_CONNECTION_TIMEOUT_MS', '0'); + vi.stubEnv('PG_STATEMENT_TIMEOUT_MS', 'abc'); + + const { createPgPoolConfig } = await import('../src/lib/pg-pool.js'); + const config = createPgPoolConfig(); + + expect(config.max).toBe(10); + expect(config.idleTimeoutMillis).toBe(30_000); + expect(config.connectionTimeoutMillis).toBe(5_000); + expect(config.statement_timeout).toBe(30_000); }); - it('createPgPool constructs pg.Pool with the configured DATABASE_URL without opening a real connection', async () => { + it('createPgPool constructs pg.Pool with default pool configuration settings', async () => { vi.stubEnv('DATABASE_URL', 'postgresql://test:test@localhost:5432/test_db'); const { createPgPool } = await import('../src/lib/pg-pool.js'); createPgPool(); + expect(poolCtorSpy).toHaveBeenCalledWith({ + connectionString: 'postgresql://test:test@localhost:5432/test_db', + max: 10, + idleTimeoutMillis: 30_000, + connectionTimeoutMillis: 5_000, + statement_timeout: 30_000, + }); + }); + + it('createPgPool applies config overrides when provided', async () => { + const { createPgPool } = await import('../src/lib/pg-pool.js'); + createPgPool({ max: 5, statement_timeout: 5000 }); + expect(poolCtorSpy).toHaveBeenCalledWith( expect.objectContaining({ - connectionString: 'postgresql://test:test@localhost:5432/test_db', + max: 5, + statement_timeout: 5000, + idleTimeoutMillis: 30_000, + connectionTimeoutMillis: 5_000, }), ); }); diff --git a/package-lock.json b/package-lock.json index 904392f2..fa95940b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -582,7 +582,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@chevrotain/gast": "10.5.0", @@ -594,7 +594,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@chevrotain/types": "10.5.0", @@ -605,14 +605,14 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@chevrotain/utils": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@colors/colors": { @@ -810,7 +810,7 @@ "version": "0.0.20", "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz", "integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "pglite-server": "dist/scripts/server.js" @@ -823,7 +823,7 @@ "version": "0.2.20", "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz", "integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "peerDependencies": { "@electric-sql/pglite": "0.3.15" @@ -1437,7 +1437,7 @@ "version": "1.19.9", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18.14.1" @@ -2043,7 +2043,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz", "integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "chevrotain": "^10.5.0", @@ -2352,7 +2352,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.4.1.tgz", "integrity": "sha512-vteSXm8N46bo3FW9MhPGVHAj+KRgrR6TWtlSk6GqToCKjTnOexXdPZyiDyEsfVW38YhqEmVl6w/6iHN8uYVJcw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "c12": "3.1.0", @@ -2365,14 +2365,14 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.4.1.tgz", "integrity": "sha512-qEtzO8oLouRv18JDQUC3G3Gnv+fGVscHZm/x1DBB/WT+kOvPDQLM2woX6IGgWnSMYYlrxjuALshT7G/blvY0bQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@prisma/dev": { "version": "0.20.0", "resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz", "integrity": "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==", - "devOptional": true, + "dev": true, "license": "ISC", "dependencies": { "@electric-sql/pglite": "0.3.15", @@ -2413,7 +2413,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.4.1.tgz", "integrity": "sha512-BZEBdHvNJx5PzIG37EI/Zi5UUI5hGWjkYsQmKa7OIK6evAvebOTwutjS/VRI6cA6grmA52eLZR+oekGRMqkKxQ==", - "devOptional": true, + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -2427,14 +2427,14 @@ "version": "7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3", "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-4.55ae170b1ced7fc6ed07a15f110549408c501bb3.tgz", "integrity": "sha512-fUxVd1TjOW8K4XsZ8dAm88sDW5Ry7AxWDfsYEWwScS6Fjo3caKC6hgNumUfsmsy0Il9LjDn5X0PpVXNt3iwayw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.1.tgz", "integrity": "sha512-kN4tmkQzlgm/KtE+jTNSYjsDxxe/5i6GApPI32BN9T0tlgsgSBtDJbjGBICttkAIjsh73dXf8raPKxO/2n2UUg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.4.1" @@ -2444,7 +2444,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.4.1.tgz", "integrity": "sha512-Z9kbuxX2bvEsyeS3LZEiEnxG0lVtZbpYgaAnPj69N+A9f2De8Lta0EoFtld9zhfERVPIQWhSWUc8himky3qYdA==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.4.1", @@ -2456,7 +2456,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.4.1.tgz", "integrity": "sha512-kN4tmkQzlgm/KtE+jTNSYjsDxxe/5i6GApPI32BN9T0tlgsgSBtDJbjGBICttkAIjsh73dXf8raPKxO/2n2UUg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.4.1" @@ -2466,7 +2466,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz", "integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.2.0" @@ -2476,21 +2476,21 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz", "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@prisma/query-plan-executor": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@prisma/studio-core": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.13.1.tgz", "integrity": "sha512-agdqaPEePRHcQ7CexEfkX1RvSH9uWDb6pXrZnhCRykhDFAV0/0P3d07WtfiY8hZWb7oRU4v+NkT4cGFHkQJIPg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "peerDependencies": { "@types/react": "^18.0.0 || ^19.0.0", @@ -2959,7 +2959,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@stellar/freighter-api": { @@ -3940,7 +3940,7 @@ "version": "19.2.17", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -5151,7 +5151,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 6.0.0" @@ -5404,7 +5404,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.3", @@ -5433,7 +5433,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -5449,7 +5449,7 @@ "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "devOptional": true, + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -5462,7 +5462,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 14.18.0" @@ -5620,7 +5620,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "@chevrotain/cst-dts-gen": "10.5.0", @@ -5673,7 +5673,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "consola": "^3.2.3" @@ -5818,14 +5818,14 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/consola": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": "^14.18.0 || >=16.10.0" @@ -6106,7 +6106,7 @@ "version": "7.1.5", "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=16.0.0" @@ -6151,7 +6151,7 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/delayed-stream": { @@ -6195,7 +6195,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/detect-libc": { @@ -6292,7 +6292,7 @@ "version": "3.18.4", "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -6317,7 +6317,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -7149,14 +7149,14 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/fast-check": { "version": "3.23.2", "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, + "dev": true, "funding": [ { "type": "individual", @@ -7551,7 +7551,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-property": "^1.0.2" @@ -7605,7 +7605,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/get-proto": { @@ -7656,7 +7656,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "citty": "^0.1.6", @@ -7798,21 +7798,21 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/grammex": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz", "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/graphmatch": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/happy-dom": { @@ -7945,7 +7945,7 @@ "version": "4.11.4", "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=16.9.0" @@ -8009,7 +8009,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/https-proxy-agent": { @@ -8515,7 +8515,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/is-regex": { @@ -8789,7 +8789,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -9061,7 +9061,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9124,7 +9124,7 @@ "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { @@ -9161,7 +9161,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/loose-envify": { @@ -9198,7 +9198,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "bun": ">=1.0.0", @@ -9448,7 +9448,7 @@ "version": "3.15.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "aws-ssl-profiles": "^1.1.1", @@ -9469,7 +9469,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "lru.min": "^1.1.0" @@ -9642,7 +9642,7 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/node-releases": { @@ -9770,7 +9770,7 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "citty": "^0.2.0", @@ -9788,7 +9788,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.1.tgz", "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/object-assign": { @@ -9916,7 +9916,7 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/on-finished": { @@ -10188,7 +10188,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/pathval": { @@ -10205,7 +10205,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/pg": { @@ -10329,7 +10329,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "confbox": "^0.2.2", @@ -10389,7 +10389,7 @@ "version": "3.4.7", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", - "devOptional": true, + "dev": true, "license": "Unlicense", "engines": { "node": ">=12" @@ -10497,7 +10497,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.4.1.tgz", "integrity": "sha512-gDKOXwnPiMdB+uYMhMeN8jj4K7Cu3Q2wB/wUsITOoOk446HtVb8T9BZxFJ1Zop6alc89k6PMNdR2FZCpbXp/jw==", - "devOptional": true, + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -10543,7 +10543,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -10555,7 +10555,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true, + "dev": true, "license": "ISC" }, "node_modules/proxy-addr": { @@ -10601,7 +10601,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "devOptional": true, + "dev": true, "funding": [ { "type": "individual", @@ -10687,7 +10687,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "defu": "^6.1.4", @@ -10828,7 +10828,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/regexp.prototype.flags": { @@ -10856,7 +10856,7 @@ "version": "2.33.4", "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", - "devOptional": true, + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/remeda" @@ -10916,7 +10916,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -11167,7 +11167,7 @@ "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", - "devOptional": true + "dev": true }, "node_modules/serve-static": { "version": "2.2.1", @@ -11480,7 +11480,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11528,7 +11528,7 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/stop-iteration-iterator": { @@ -12208,7 +12208,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -12629,7 +12629,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -12811,7 +12811,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", - "devOptional": true, + "dev": true, "license": "MIT", "peerDependencies": { "typescript": ">=5" @@ -13867,7 +13867,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz", "integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "grammex": "^3.1.11",