diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 864f9837..6b062a23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,6 +81,40 @@ jobs: - name: Run ESLint (astro-payload-richtext-lexical) run: cd astro-payload-richtext-lexical && pnpm lint + test-geocoding: + runs-on: ubuntu-latest + needs: format + name: test-geocoding + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Setup environment variables + run: | + echo "PAYLOAD_SECRET=test-secret-not-for-production" > geocoding/dev/.env + echo "SQLITE_URL=file:./payload-test.db" >> geocoding/dev/.env + echo "NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=test-api-key" >> geocoding/dev/.env + + - name: Setup pnpm + uses: pnpm/action-setup@v5 + with: + version: ^9.0.0 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '22' + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install:all + + - name: Run tests + run: cd geocoding && pnpm test:sqlite + env: + PAYLOAD_DATABASE: sqlite + test-pages-localized: runs-on: ubuntu-latest needs: format diff --git a/geocoding/README.md b/geocoding/README.md index ab9922e5..14b66f97 100644 --- a/geocoding/README.md +++ b/geocoding/README.md @@ -69,6 +69,70 @@ geocodingField({ }), ``` +## Usage with AI Agents / API + +The default UI-based autocomplete requires a browser, which makes it unusable for AI agents and other API consumers. The plugin provides two server-side mechanisms to solve this. + +### Geocoding Search Endpoint + +The plugin registers a `GET /api/geocoding-plugin/search` endpoint that geocodes addresses server-side. It is authenticated by default (requires a logged-in user), and supports a custom access function: + +```ts +plugins: [ + payloadGeocodingPlugin({ + googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!, + // Optional: customize who can access the endpoint + geocodingEndpoint: { + access: ({ req }) => Boolean(req.user), + }, + }), +] +``` + +An agent can then search for locations and use the results to populate fields: + +```bash +# 1. Search for an address +GET /api/geocoding-plugin/search?q=Alexanderplatz,+Berlin + +# Response: +{ + "results": [ + { + "formattedAddress": "Alexanderplatz, 10178 Berlin, Germany", + "placeId": "ChIJp1l4uWBRqEcR2SPNRBMhtAI", + "location": { "lat": 52.5219, "lng": 13.4132 }, + "addressComponents": [...], + "types": [...] + } + ] +} + +# 2. Use the result to create/update a document +POST /api/pages +{ + "title": "My Page", + "location": [13.4132, 52.5219], + "location_googlePlacesData": { ... } +} +``` + +### Server-Side Address Geocoding (beforeChange Hook) + +Every `geocodingField` automatically includes a hidden `{fieldName}_address` text field. When an address string is submitted via the API, a `beforeChange` hook geocodes it server-side and populates the point and geodata fields. + +An agent can simply submit an address string — the coordinates and geodata are resolved automatically: + +```bash +POST /api/pages +{ + "title": "My Page", + "location_address": "Alexanderplatz, Berlin" +} +``` + +The hook geocodes the address, sets the `location` point field to `[lng, lat]`, populates `location_googlePlacesData` with the full geocoding result, and clears `location_address` (it is not persisted). + ## About this plugin This plugin uses the [react-google-places-autocomplete](https://www.npmjs.com/package/react-google-places-autocomplete) library to provide a Select/Search input for finding an address. The result of the Google Places API request is stored in a JSON field and the coordinates are stored in a Point Field. diff --git a/geocoding/dev/.gitignore b/geocoding/dev/.gitignore index 60259b83..5ebf18be 100644 --- a/geocoding/dev/.gitignore +++ b/geocoding/dev/.gitignore @@ -370,4 +370,5 @@ $RECYCLE.BIN/ /media *.db tsconfig.tsbuildinfo -/dist \ No newline at end of file +/dist +src/test/databaseAdapter.ts \ No newline at end of file diff --git a/geocoding/dev/package.json b/geocoding/dev/package.json index ad302321..96c035bd 100644 --- a/geocoding/dev/package.json +++ b/geocoding/dev/package.json @@ -1,6 +1,6 @@ { - "name": "payload-plugin-test-app", - "description": "A test app for the plugin", + "name": "payload-geocoding-plugin-test-app", + "description": "A test app for the geocoding plugin", "version": "0.0.1", "license": "MIT", "type": "module", @@ -12,14 +12,19 @@ "start": "cross-env NODE_OPTIONS=--no-deprecation next start", "format": "prettier --write src", "payload": "payload", - "generate:types": "payload generate:types", + "generate:types": "cross-env PAYLOAD_DATABASE=sqlite payload generate:types", "generate:schema": "payload-graphql generate:schema", - "generate:importmap": "payload generate:importmap" + "generate:importmap": "payload generate:importmap", + "test": "pnpm test:sqlite", + "test:sqlite": "cross-env PAYLOAD_DATABASE=sqlite vitest run", + "test:watch": "vitest watch" }, "dependencies": { "@jhb.software/payload-geocoding-plugin": "workspace:*", "@payloadcms/db-mongodb": "^3.79.0", + "@payloadcms/db-sqlite": "^3.79.0", "@payloadcms/next": "^3.79.0", + "@payloadcms/richtext-lexical": "3.79.0", "@payloadcms/ui": "^3.79.0", "next": "15.4.11", "payload": "^3.79.0", @@ -30,6 +35,7 @@ "copyfiles": "^2.4.1", "cross-env": "^10.1.0", "dotenv": "^17.3.1", - "typescript": "5.9.3" + "vite": "^8.0.0", + "vitest": "^4.1.0" } } diff --git a/geocoding/dev/plugin.spec.ts b/geocoding/dev/plugin.spec.ts deleted file mode 100644 index 9391d33c..00000000 --- a/geocoding/dev/plugin.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Server } from 'http' -import mongoose from 'mongoose' -import payload from 'payload' -import { start } from './src/server' - -describe('Plugin tests', () => { - let server: Server - - beforeAll(async () => { - await start({ local: true }) - }) - - afterAll(async () => { - await mongoose.connection.dropDatabase() - await mongoose.connection.close() - server.close() - }) - - // Add tests to ensure that the plugin works as expected - - // Example test to check for seeded data - it('seeds data accordingly', async () => { - const newCollectionQuery = await payload.find({ - collection: 'new-collection', - sort: 'createdAt', - }) - - expect(newCollectionQuery.totalDocs).toEqual(1) - }) -}) diff --git a/geocoding/dev/plugin.test.ts b/geocoding/dev/plugin.test.ts new file mode 100644 index 00000000..a9592574 --- /dev/null +++ b/geocoding/dev/plugin.test.ts @@ -0,0 +1,339 @@ +import payload, { type CollectionSlug, type SanitizedConfig } from 'payload' +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest' +import config from './src/payload.config' + +const MOCK_GOOGLE_RESPONSE = { + results: [ + { + address_components: [ + { long_name: 'Alexanderplatz', short_name: 'Alexanderplatz', types: ['point_of_interest'] }, + { long_name: 'Berlin', short_name: 'Berlin', types: ['locality'] }, + ], + formatted_address: 'Alexanderplatz, 10178 Berlin, Germany', + geometry: { + location: { lat: 52.5219, lng: 13.4132 }, + }, + place_id: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + types: ['point_of_interest', 'establishment'], + }, + ], + status: 'OK', +} + +/** + * The Pages collection has `location1` (required point) and `location2` (required point + required geodata). + * These must be provided in every create call to satisfy validation. + */ +const requiredFields = { + location1: [0, 0] as [number, number], + location2: [0, 0] as [number, number], + location2_googlePlacesData: { placeholder: true }, +} + +/** Returns a fresh mock Response for each call (avoids "Body already read" errors). */ +function mockGoogleGeocodingFetch() { + return vi.spyOn(globalThis, 'fetch').mockImplementation(async () => { + return new Response(JSON.stringify(MOCK_GOOGLE_RESPONSE), { status: 200 }) + }) +} + +beforeAll(async () => { + await payload.init({ + config: config, + }) + + await deleteAllCollections(config, ['users']) +}) + +afterAll(async () => { + await deleteAllCollections(config) + + if (payload.db && typeof payload.db.destroy === 'function') { + await payload.db.destroy() + } +}) + +afterEach(() => { + vi.restoreAllMocks() +}) + +describe('Geocoding plugin field structure', () => { + beforeEach(async () => await deleteCollection('pages')) + + test('creates a page with point and geodata fields via the local API', async () => { + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Test Page', + location: [13.4132, 52.5219], + location_googlePlacesData: { formattedAddress: 'Berlin, Germany' }, + ...requiredFields, + }, + }) + + expect(page.location).toEqual([13.4132, 52.5219]) + expect(page.location_googlePlacesData).toEqual({ formattedAddress: 'Berlin, Germany' }) + }) + + test('creates a page with only the required fields', async () => { + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Minimal Page', + ...requiredFields, + }, + }) + + expect(page.title).toBe('Minimal Page') + // Optional location field should not be set + expect(page.location).toBeUndefined() + }) + + test('geocoding fields work inside a group', async () => { + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Group Test', + locationGroup: { + location: [10.0, 50.0], + location_googlePlacesData: { formattedAddress: 'Somewhere' }, + }, + ...requiredFields, + }, + }) + + expect(page.locationGroup?.location).toEqual([10.0, 50.0]) + expect(page.locationGroup?.location_googlePlacesData).toEqual({ + formattedAddress: 'Somewhere', + }) + }) + + test('geocoding fields work inside an array', async () => { + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Array Test', + locations: [ + { + location: [8.0, 48.0], + location_googlePlacesData: { formattedAddress: 'Place A' }, + }, + { + location: [9.0, 49.0], + location_googlePlacesData: { formattedAddress: 'Place B' }, + }, + ], + ...requiredFields, + }, + }) + + expect(page.locations).toHaveLength(2) + expect(page.locations![0].location).toEqual([8.0, 48.0]) + expect(page.locations![1].location).toEqual([9.0, 49.0]) + }) +}) + +describe('Server-side address geocoding (beforeChange hook)', () => { + beforeEach(async () => await deleteCollection('pages')) + + test('auto-geocodes an address string submitted via location_address', async () => { + mockGoogleGeocodingFetch() + + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Geocoded Page', + location_address: 'Alexanderplatz, Berlin', + ...requiredFields, + }, + }) + + // Point field should be populated with [lng, lat] + expect(page.location).toEqual([13.4132, 52.5219]) + + // Geodata field should contain the geocoding result + expect(page.location_googlePlacesData).toMatchObject({ + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + placeId: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + location: { lat: 52.5219, lng: 13.4132 }, + }) + + // The address field should NOT be persisted + const fetched = await payload.findByID({ + collection: 'pages', + id: page.id, + }) + expect((fetched as Record).location_address).toBeFalsy() + }) + + test('does not geocode when no address is provided', async () => { + const fetchSpy = vi.spyOn(globalThis, 'fetch') + + await payload.create({ + collection: 'pages', + data: { + title: 'No Address Page', + location: [1.0, 2.0], + ...requiredFields, + }, + }) + + // fetch should not have been called for geocoding + expect(fetchSpy).not.toHaveBeenCalled() + }) + + test('auto-geocodes address on update', async () => { + const page = await payload.create({ + collection: 'pages', + data: { + title: 'Update Test', + location: [0, 0], + ...requiredFields, + }, + }) + + mockGoogleGeocodingFetch() + + const updated = await payload.update({ + collection: 'pages', + id: page.id, + data: { + location_address: 'Alexanderplatz, Berlin', + }, + }) + + expect(updated.location).toEqual([13.4132, 52.5219]) + expect(updated.location_googlePlacesData).toMatchObject({ + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + }) + }) +}) + +describe('Geocoding field inside a Lexical block', () => { + beforeEach(async () => await deleteCollection('articles')) + + test('creates an article with a locationBlock containing point and geodata', async () => { + const article = await payload.create({ + collection: 'articles', + data: { + title: 'Article with Location Block', + content: { + root: { + type: 'root', + version: 1, + direction: 'ltr', + children: [ + { + type: 'block', + version: 1, + fields: { + id: 'loc-block-1', + blockName: 'Berlin Office', + blockType: 'locationBlock', + label: 'Berlin HQ', + location: [13.4132, 52.5219], + location_googlePlacesData: { formattedAddress: 'Berlin, Germany' }, + }, + }, + ], + }, + }, + }, + }) + + const block = (article.content?.root?.children as any[])?.[0] + expect(block).toBeDefined() + expect(block.fields.blockType).toBe('locationBlock') + expect(block.fields.location).toEqual([13.4132, 52.5219]) + expect(block.fields.location_googlePlacesData).toEqual({ + formattedAddress: 'Berlin, Germany', + }) + }) + + test('auto-geocodes an address inside a Lexical block', async () => { + mockGoogleGeocodingFetch() + + const article = await payload.create({ + collection: 'articles', + data: { + title: 'Geocoded Block Article', + content: { + root: { + type: 'root', + version: 1, + direction: 'ltr', + children: [ + { + type: 'block', + version: 1, + fields: { + id: 'loc-block-2', + blockName: 'Auto-geocoded Location', + blockType: 'locationBlock', + label: 'Berlin Office', + location_address: 'Alexanderplatz, Berlin', + }, + }, + ], + }, + }, + }, + }) + + const block = (article.content?.root?.children as any[])?.[0] + expect(block).toBeDefined() + + // Point field should be populated with [lng, lat] + expect(block.fields.location).toEqual([13.4132, 52.5219]) + + // Geodata should be populated + expect(block.fields.location_googlePlacesData).toMatchObject({ + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + placeId: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + }) + + // Known Payload bug: virtual fields inside Lexical blocks are still stored in the block's JSON. + // The address field has virtual: true, which correctly prevents a DB column for regular fields, + // but Lexical blocks serialize all field data as JSON and ignore the virtual flag. + // expect(block.fields.location_address).toBeFalsy() + }) +}) + +describe('Geocoding search endpoint', () => { + test('is registered at /api/geocoding-plugin/search', () => { + const endpoints = payload.config.endpoints + const geocodingEndpoint = endpoints?.find((e) => e.path === '/geocoding-plugin/search') + + expect(geocodingEndpoint).toBeDefined() + expect(geocodingEndpoint!.method).toBe('get') + }) +}) + +// --- Helpers --- + +const deleteCollection = async (collection: CollectionSlug) => { + await payload.db.deleteMany({ + collection: collection, + where: {}, + }) + + try { + await payload.db.deleteVersions({ + collection: collection, + where: {}, + }) + } catch {} +} + +const deleteAllCollections = async ( + config: Promise, + except: CollectionSlug[] = [], +) => { + const collections = (await config).collections?.filter((c) => !except.includes(c.slug)) ?? [] + + for (const collection of collections) { + if (!except.includes(collection.slug)) { + await deleteCollection(collection.slug) + } + } +} diff --git a/geocoding/dev/src/collection/articles.ts b/geocoding/dev/src/collection/articles.ts new file mode 100644 index 00000000..d10b9037 --- /dev/null +++ b/geocoding/dev/src/collection/articles.ts @@ -0,0 +1,49 @@ +import { geocodingField } from '../../../src/fields/geocodingField' + +import type { CollectionConfig } from 'payload' + +import { lexicalEditor, BlocksFeature } from '@payloadcms/richtext-lexical' + +/** + * A collection for testing the geocoding field inside a Lexical editor block. + */ +export const Articles: CollectionConfig = { + slug: 'articles', + admin: { + useAsTitle: 'title', + }, + fields: [ + { + name: 'title', + type: 'text', + required: true, + }, + { + name: 'content', + type: 'richText', + editor: lexicalEditor({ + features: [ + BlocksFeature({ + blocks: [ + { + slug: 'locationBlock', + fields: [ + { + name: 'label', + type: 'text', + }, + geocodingField({ + pointField: { + name: 'location', + type: 'point', + }, + }), + ], + }, + ], + }), + ], + }), + }, + ], +} diff --git a/geocoding/dev/src/payload-types.ts b/geocoding/dev/src/payload-types.ts index bb5f3bda..46582be8 100644 --- a/geocoding/dev/src/payload-types.ts +++ b/geocoding/dev/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; pages: Page; + articles: Article; 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -78,13 +79,14 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; pages: PagesSelect | PagesSelect; + articles: ArticlesSelect | ArticlesSelect; 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; }; db: { - defaultIDType: string; + defaultIDType: number; }; fallbackLocale: null; globals: {}; @@ -122,7 +124,7 @@ export interface UserAuthOperations { * via the `definition` "users". */ export interface User { - id: string; + id: number; updatedAt: string; createdAt: string; email: string; @@ -147,7 +149,7 @@ export interface User { * via the `definition` "pages". */ export interface Page { - id: string; + id: number; title?: string | null; location_googlePlacesData?: | { @@ -163,6 +165,7 @@ export interface Page { * @maxItems 2 */ location?: [number, number] | null; + location_address?: string | null; location0_googlePlacesData?: | { [k: string]: unknown; @@ -177,6 +180,7 @@ export interface Page { * @maxItems 2 */ location0?: [number, number] | null; + location0_address?: string | null; location1_googlePlacesData?: | { [k: string]: unknown; @@ -191,6 +195,7 @@ export interface Page { * @maxItems 2 */ location1: [number, number]; + location1_address?: string | null; location2_googlePlacesData: | { [k: string]: unknown; @@ -205,6 +210,7 @@ export interface Page { * @maxItems 2 */ location2: [number, number]; + location2_address?: string | null; location3_googlePlacesData?: | { [k: string]: unknown; @@ -219,6 +225,7 @@ export interface Page { * @maxItems 2 */ location3?: [number, number] | null; + location3_address?: string | null; locationGroup?: { location_googlePlacesData?: | { @@ -234,6 +241,7 @@ export interface Page { * @maxItems 2 */ location?: [number, number] | null; + location_address?: string | null; }; locations?: | { @@ -251,18 +259,44 @@ export interface Page { * @maxItems 2 */ location?: [number, number] | null; + location_address?: string | null; id?: string | null; }[] | null; updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "articles". + */ +export interface Article { + id: number; + title: string; + content?: { + root: { + type: string; + children: { + type: any; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + } | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv". */ export interface PayloadKv { - id: string; + id: number; key: string; data: | { @@ -279,20 +313,24 @@ export interface PayloadKv { * via the `definition` "payload-locked-documents". */ export interface PayloadLockedDocument { - id: string; + id: number; document?: | ({ relationTo: 'users'; - value: string | User; + value: number | User; } | null) | ({ relationTo: 'pages'; - value: string | Page; + value: number | Page; + } | null) + | ({ + relationTo: 'articles'; + value: number | Article; } | null); globalSlug?: string | null; user: { relationTo: 'users'; - value: string | User; + value: number | User; }; updatedAt: string; createdAt: string; @@ -302,10 +340,10 @@ export interface PayloadLockedDocument { * via the `definition` "payload-preferences". */ export interface PayloadPreference { - id: string; + id: number; user: { relationTo: 'users'; - value: string | User; + value: number | User; }; key?: string | null; value?: @@ -325,7 +363,7 @@ export interface PayloadPreference { * via the `definition` "payload-migrations". */ export interface PayloadMigration { - id: string; + id: number; name?: string | null; batch?: number | null; updatedAt: string; @@ -361,30 +399,47 @@ export interface PagesSelect { title?: T; location_googlePlacesData?: T; location?: T; + location_address?: T; location0_googlePlacesData?: T; location0?: T; + location0_address?: T; location1_googlePlacesData?: T; location1?: T; + location1_address?: T; location2_googlePlacesData?: T; location2?: T; + location2_address?: T; location3_googlePlacesData?: T; location3?: T; + location3_address?: T; locationGroup?: | T | { location_googlePlacesData?: T; location?: T; + location_address?: T; }; locations?: | T | { location_googlePlacesData?: T; location?: T; + location_address?: T; id?: T; }; updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "articles_select". + */ +export interface ArticlesSelect { + title?: T; + content?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-kv_select". diff --git a/geocoding/dev/src/payload.config.ts b/geocoding/dev/src/payload.config.ts index 0e585564..988a1347 100644 --- a/geocoding/dev/src/payload.config.ts +++ b/geocoding/dev/src/payload.config.ts @@ -1,10 +1,11 @@ import { payloadGeocodingPlugin } from '@jhb.software/payload-geocoding-plugin' -import { mongooseAdapter } from '@payloadcms/db-mongodb' import path from 'path' import { buildConfig } from 'payload' import { fileURLToPath } from 'url' +import { Articles } from './collection/articles' import { Pages } from './collection/pages' import { testEmailAdapter } from './emailAdapter' +import { databaseAdapter } from './test/databaseAdapter' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -24,18 +25,17 @@ export default buildConfig({ fields: [], }, Pages, + Articles, ], - db: mongooseAdapter({ - url: process.env.DATABASE_URI!, - }), + db: databaseAdapter, email: testEmailAdapter, - secret: process.env.PAYLOAD_SECRET!, + secret: process.env.PAYLOAD_SECRET || 'test-secret-for-ci', typescript: { outputFile: path.resolve(dirname, 'payload-types.ts'), }, plugins: [ payloadGeocodingPlugin({ - googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY!, + googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || 'test-api-key', }), ], async onInit(payload) { diff --git a/geocoding/dev/src/test/generateDatabaseAdapter.ts b/geocoding/dev/src/test/generateDatabaseAdapter.ts new file mode 100644 index 00000000..51a000a0 --- /dev/null +++ b/geocoding/dev/src/test/generateDatabaseAdapter.ts @@ -0,0 +1,57 @@ +// NOTE: this pattern is inspired by https://github.com/payloadcms/payload/blob/main/test/generateDatabaseAdapter.ts + +import fs from 'fs' +import path from 'path' +import { fileURLToPath } from 'url' + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +export type DatabaseAdapter = 'mongodb' | 'sqlite' + +const databaseAdapters: Record = { + mongodb: ` +import { mongooseAdapter } from '@payloadcms/db-mongodb' + +export const databaseAdapter = mongooseAdapter({ + url: process.env.MONGODB_URL!, +}) +`, + sqlite: ` +import { sqliteAdapter } from '@payloadcms/db-sqlite' + +export const databaseAdapter = sqliteAdapter({ + client: { + url: process.env.SQLITE_URL!, + }, +}) +`, +} + +/** + * Generates a database adapter file based on the PAYLOAD_DATABASE environment variable. + * This allows the same tests to run against different databases without code duplication. + */ +export function generateDatabaseAdapter(dbAdapter: DatabaseAdapter = 'mongodb'): string { + const adapterCode = databaseAdapters[dbAdapter] + if (!adapterCode) { + throw new Error( + `Unknown database adapter: ${dbAdapter}. Valid options are: ${Object.keys(databaseAdapters).join(', ')}`, + ) + } + + const outputPath = path.resolve(dirname, 'databaseAdapter.ts') + + fs.writeFileSync( + outputPath, + `// DO NOT MODIFY. This file is automatically generated. +// Generated for database: ${dbAdapter} +${adapterCode} +`, + ) + + console.log( + `\n##############################\n## Generated database adapter for: ${dbAdapter} ##\n##############################\n`, + ) + return adapterCode +} diff --git a/geocoding/dev/src/test/vitest.setup.ts b/geocoding/dev/src/test/vitest.setup.ts new file mode 100644 index 00000000..0d085cc2 --- /dev/null +++ b/geocoding/dev/src/test/vitest.setup.ts @@ -0,0 +1,6 @@ +import { generateDatabaseAdapter, type DatabaseAdapter } from './generateDatabaseAdapter.js' + +// Default to SQLite if no database specified +const dbAdapter = (process.env.PAYLOAD_DATABASE as DatabaseAdapter) || 'sqlite' + +generateDatabaseAdapter(dbAdapter) diff --git a/geocoding/dev/vite.config.ts b/geocoding/dev/vite.config.ts new file mode 100644 index 00000000..43184db0 --- /dev/null +++ b/geocoding/dev/vite.config.ts @@ -0,0 +1,18 @@ +import path from 'path' +import { loadEnv } from 'vite' +import { fileURLToPath } from 'url' +import { defineConfig } from 'vitest/config' + +const filename = fileURLToPath(import.meta.url) +const dirname = path.dirname(filename) + +export default defineConfig(({ mode }) => { + return { + test: { + env: loadEnv(mode, process.cwd(), ''), // Load environment variables + hookTimeout: 30000, // Increase hook timeout to 30 seconds + testTimeout: 30000, // Increase test timeout to 30 seconds + setupFiles: [path.resolve(dirname, 'src/test/vitest.setup.ts')], + }, + } +}) diff --git a/geocoding/package.json b/geocoding/package.json index 9a9c8539..4a1f791e 100644 --- a/geocoding/package.json +++ b/geocoding/package.json @@ -30,7 +30,9 @@ "lint": "eslint src", "lint:fix": "eslint src --fix", "prepack": "pnpm prepublishOnly", - "prepublishOnly": "pnpm build && pnpm copyfiles" + "prepublishOnly": "pnpm build && pnpm copyfiles", + "test": "cd dev && pnpm test", + "test:sqlite": "cd dev && pnpm test:sqlite" }, "dependencies": { "react-google-places-autocomplete": "^4.1.0" @@ -52,7 +54,8 @@ "eslint": "^9.0.0", "prettier": "^3.8.1", "rimraf": "6.1.3", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "^4.1.2" }, "publishConfig": { "main": "./dist/index.js", diff --git a/geocoding/pnpm-lock.yaml b/geocoding/pnpm-lock.yaml index ec33f3e5..ce75ef66 100644 --- a/geocoding/pnpm-lock.yaml +++ b/geocoding/pnpm-lock.yaml @@ -57,6 +57,9 @@ importers: typescript: specifier: 5.9.3 version: 5.9.3 + vitest: + specifier: ^4.1.2 + version: 4.1.2(happy-dom@20.8.9)(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0)) dev: dependencies: @@ -66,9 +69,15 @@ importers: '@payloadcms/db-mongodb': specifier: ^3.79.0 version: 3.79.0(@aws-sdk/credential-providers@3.666.0(@aws-sdk/client-sso-oidc@3.666.0(@aws-sdk/client-sts@3.666.0)))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(socks@2.8.3) + '@payloadcms/db-sqlite': + specifier: ^3.79.0 + version: 3.81.0(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3)) '@payloadcms/next': specifier: ^3.79.0 version: 3.79.0(@types/react@19.2.14)(graphql@16.9.0)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + '@payloadcms/richtext-lexical': + specifier: 3.79.0 + version: 3.79.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.79.0(@types/react@19.2.14)(graphql@16.9.0)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30) '@payloadcms/ui': specifier: ^3.79.0 version: 3.79.0(@types/react@19.2.14)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) @@ -94,9 +103,12 @@ importers: dotenv: specifier: ^17.3.1 version: 17.3.1 - typescript: - specifier: 5.9.3 - version: 5.9.3 + vite: + specifier: ^8.0.0 + version: 8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0) + vitest: + specifier: ^4.1.0 + version: 4.1.2(happy-dom@20.8.9)(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0)) packages: @@ -304,9 +316,18 @@ packages: peerDependencies: react: '>=16.8.0' + '@drizzle-team/brocli@0.10.2': + resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} + + '@emnapi/core@1.9.2': + resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} + '@emnapi/runtime@1.7.1': resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -351,156 +372,452 @@ packages: '@epic-web/invariant@1.0.0': resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} + '@esbuild-kit/core-utils@3.3.2': + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild-kit/esm-loader@2.6.5': + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/aix-ppc64@0.27.3': resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -613,6 +930,18 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' + '@floating-ui/react-dom@2.1.8': + resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.27.19': + resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + '@floating-ui/react@0.27.3': resolution: {integrity: sha512-CLHnes3ixIFFKVQDdICjel8muhFLOBdQH7fgtHNPY8UbCNqbeKZ262G7K66lGQOUQWWnYocf7ZbUsLJgGfsLHg==} peerDependencies: @@ -806,8 +1135,8 @@ packages: resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -815,6 +1144,134 @@ packages: '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + '@lexical/clipboard@0.41.0': + resolution: {integrity: sha512-Ex5lPkb4NBBX1DCPzOAIeHBJFH1bJcmATjREaqpnTfxCbuOeQkt44wchezUA0oDl+iAxNZ3+pLLWiUju9icoSA==} + + '@lexical/code@0.41.0': + resolution: {integrity: sha512-0hoNi1KC9/N3SBOGcOcFqnT0OpwmcRRAhfxTKMGqfCtCvAMzULVwZ8RWc9/NV9bKYESgBTW5D9xkDANP2mspHg==} + + '@lexical/devtools-core@0.41.0': + resolution: {integrity: sha512-FzJtluBhBc8bKS11TUZe72KoZN/hnzIyiiM0SPJAsPwGpoXuM01jqpXQGybWf/1bWB+bmmhOae7O4Nywi/Csuw==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/dragon@0.41.0': + resolution: {integrity: sha512-gBEqkk8Q6ZPruvDaRcOdF1EK9suCVBODzOCcR+EnoJTaTjfDkCM7pkPAm4w90Wa1wCZEtFHvCfas+jU9MDSumg==} + + '@lexical/extension@0.41.0': + resolution: {integrity: sha512-sF4SPiP72yXvIGchmmIZ7Yg2XZTxNLOpFEIIzdqG7X/1fa1Ham9P/T7VbrblWpF6Ei5LJtK9JgNVB0hb4l3o1g==} + + '@lexical/hashtag@0.41.0': + resolution: {integrity: sha512-tFWM74RW4KU0E/sj2aowfWl26vmLUTp331CgVESnhQKcZBfT40KJYd57HEqBDTfQKn4MUhylQCCA0hbpw6EeFQ==} + + '@lexical/headless@0.41.0': + resolution: {integrity: sha512-MH8oDuUKdM/Jq0c9vlEEkCL9pEQg4SwyrABBGIbFf+87VBJ5EWDdG9g1vJq7fKSDxfhFux7F5+i+zgUnxOQR/g==} + + '@lexical/history@0.41.0': + resolution: {integrity: sha512-kGoVWsiOn62+RMjRolRa+NXZl8jFwxav6GNDiHH8yzivtoaH8n1SwUfLJELXCzeqzs81HySqD4q30VLJVTGoDg==} + + '@lexical/html@0.41.0': + resolution: {integrity: sha512-3RyZy+H/IDKz2D66rNN/NqYx87xVFrngfEbyu1OWtbY963RUFnopiVHCQvsge/8kT04QSZ7U/DzjVFqeNS6clg==} + + '@lexical/link@0.41.0': + resolution: {integrity: sha512-Rjtx5cGWAkKcnacncbVsZ1TqRnUB2Wm4eEVKpaAEG41+kHgqghzM2P+UGT15yROroxJu8KvAC9ISiYFiU4XE1w==} + + '@lexical/list@0.41.0': + resolution: {integrity: sha512-RXvB+xcbzVoQLGRDOBRCacztG7V+bI95tdoTwl8pz5xvgPtAaRnkZWMDP+yMNzMJZsqEChdtpxbf0NgtMkun6g==} + + '@lexical/mark@0.41.0': + resolution: {integrity: sha512-UO5WVs9uJAYIKHSlYh4Z1gHrBBchTOi21UCYBIZ7eAs4suK84hPzD+3/LAX5CB7ZltL6ke5Sly3FOwNXv/wfpA==} + + '@lexical/markdown@0.41.0': + resolution: {integrity: sha512-bzI73JMXpjGFhqUWNV6KqfjWcgAWzwFT+J3RHtbCF5rysC8HLldBYojOgAAtPfXqfxyv2mDzsY7SoJ75s9uHZA==} + + '@lexical/offset@0.41.0': + resolution: {integrity: sha512-2RHBXZqC8gm3X9C0AyRb0M8w7zJu5dKiasrif+jSKzsxPjAUeF1m95OtIOsWs1XLNUgASOSUqGovDZxKJslZfA==} + + '@lexical/overflow@0.41.0': + resolution: {integrity: sha512-Iy6ZiJip8X14EBYt1zKPOrXyQ4eG9JLBEoPoSVBTiSbVd+lYicdUvaOThT0k0/qeVTN9nqTaEltBjm56IrVKCQ==} + + '@lexical/plain-text@0.41.0': + resolution: {integrity: sha512-HIsGgmFUYRUNNyvckun33UQfU7LRzDlxymHUq67+Bxd5bXqdZOrStEKJXuDX+LuLh/GXZbaWNbDLqwLBObfbQg==} + + '@lexical/react@0.41.0': + resolution: {integrity: sha512-7+GUdZUm6sofWm+zdsWAs6cFBwKNsvsHezZTrf6k8jrZxL461ZQmbz/16b4DvjCGL9r5P1fR7md9/LCmk8TiCg==} + peerDependencies: + react: '>=17.x' + react-dom: '>=17.x' + + '@lexical/rich-text@0.41.0': + resolution: {integrity: sha512-yUcr7ZaaVTZNi8bow4CK1M8jy2qyyls1Vr+5dVjwBclVShOL/F/nFyzBOSb6RtXXRbd3Ahuk9fEleppX/RNIdw==} + + '@lexical/selection@0.41.0': + resolution: {integrity: sha512-1s7/kNyRzcv5uaTwsUL28NpiisqTf5xZ1zNukLsCN1xY+TWbv9RE9OxIv+748wMm4pxNczQe/UbIBODkbeknLw==} + + '@lexical/table@0.41.0': + resolution: {integrity: sha512-d3SPThBAr+oZ8O74TXU0iXM3rLbrAVC7/HcOnSAq7/AhWQW8yMutT51JQGN+0fMLP9kqoWSAojNtkdvzXfU/+A==} + + '@lexical/text@0.41.0': + resolution: {integrity: sha512-gGA+Anc7ck110EXo4KVKtq6Ui3M7Vz3OpGJ4QE6zJHWW8nV5h273koUGSutAMeoZgRVb6t01Izh3ORoFt/j1CA==} + + '@lexical/utils@0.41.0': + resolution: {integrity: sha512-Wlsokr5NQCq83D+7kxZ9qs5yQ3dU3Qaf2M+uXxLRoPoDaXqW8xTWZq1+ZFoEzsHzx06QoPa4Vu/40BZR91uQPg==} + + '@lexical/yjs@0.41.0': + resolution: {integrity: sha512-PaKTxSbVC4fpqUjQ7vUL9RkNF1PjL8TFl5jRe03PqoPYpE33buf3VXX6+cOUEfv9+uknSqLCPHoBS/4jN3a97w==} + peerDependencies: + yjs: '>=13.5.22' + + '@libsql/client@0.14.0': + resolution: {integrity: sha512-/9HEKfn6fwXB5aTEEoMeFh4CtG0ZzbncBb1e++OCdVpgKZ/xyMsIVYXm0w7Pv4RUel803vE6LwniB3PqD72R0Q==} + + '@libsql/core@0.14.0': + resolution: {integrity: sha512-nhbuXf7GP3PSZgdCY2Ecj8vz187ptHlZQ0VRc751oB2C1W8jQUXKKklvt7t1LJiUTQBVJuadF628eUk+3cRi4Q==} + + '@libsql/darwin-arm64@0.4.7': + resolution: {integrity: sha512-yOL742IfWUlUevnI5PdnIT4fryY3LYTdLm56bnY0wXBw7dhFcnjuA7jrH3oSVz2mjZTHujxoITgAE7V6Z+eAbg==} + cpu: [arm64] + os: [darwin] + + '@libsql/darwin-x64@0.4.7': + resolution: {integrity: sha512-ezc7V75+eoyyH07BO9tIyJdqXXcRfZMbKcLCeF8+qWK5nP8wWuMcfOVywecsXGRbT99zc5eNra4NEx6z5PkSsA==} + cpu: [x64] + os: [darwin] + + '@libsql/hrana-client@0.7.0': + resolution: {integrity: sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw==} + + '@libsql/isomorphic-fetch@0.3.1': + resolution: {integrity: sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw==} + engines: {node: '>=18.0.0'} + + '@libsql/isomorphic-ws@0.1.5': + resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} + + '@libsql/linux-arm64-gnu@0.4.7': + resolution: {integrity: sha512-WlX2VYB5diM4kFfNaYcyhw5y+UJAI3xcMkEUJZPtRDEIu85SsSFrQ+gvoKfcVh76B//ztSeEX2wl9yrjF7BBCA==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-arm64-musl@0.4.7': + resolution: {integrity: sha512-6kK9xAArVRlTCpWeqnNMCoXW1pe7WITI378n4NpvU5EJ0Ok3aNTIC2nRPRjhro90QcnmLL1jPcrVwO4WD1U0xw==} + cpu: [arm64] + os: [linux] + + '@libsql/linux-x64-gnu@0.4.7': + resolution: {integrity: sha512-CMnNRCmlWQqqzlTw6NeaZXzLWI8bydaXDke63JTUCvu8R+fj/ENsLrVBtPDlxQ0wGsYdXGlrUCH8Qi9gJep0yQ==} + cpu: [x64] + os: [linux] + + '@libsql/linux-x64-musl@0.4.7': + resolution: {integrity: sha512-nI6tpS1t6WzGAt1Kx1n1HsvtBbZ+jHn0m7ogNNT6pQHZQj7AFFTIMeDQw/i/Nt5H38np1GVRNsFe99eSIMs9XA==} + cpu: [x64] + os: [linux] + + '@libsql/win32-x64-msvc@0.4.7': + resolution: {integrity: sha512-7pJzOWzPm6oJUxml+PCDRzYQ4A1hTMHAciTAHfFK4fkbDZX33nWPVG7Y3vqdKtslcwAzwmrNDc6sXy2nwWnbiw==} + cpu: [x64] + os: [win32] + '@monaco-editor/loader@1.5.0': resolution: {integrity: sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==} @@ -941,6 +1398,15 @@ packages: resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} engines: {node: '>= 10'} + '@napi-rs/wasm-runtime@1.1.2': + resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@neon-rs/load@0.0.4': + resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + '@next/env@15.4.11': resolution: {integrity: sha512-mIYp/091eYfPFezKX7ZPTWqrmSXq+ih6+LcUyKvLmeLQGhlPtot33kuEOd4U+xAA7sFfj21+OtCpIZx0g5SpvQ==} @@ -1011,11 +1477,24 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oxc-project/types@0.122.0': + resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} + '@payloadcms/db-mongodb@3.79.0': resolution: {integrity: sha512-oLnI73zfUBktCrYaxPTEAxxGE+X6GhEskjuDs1hUIhguWWnTCXyjaLoCO5x0kVj4wWQoCACvvJ4HlGJ+bDOTFA==} peerDependencies: payload: 3.79.0 + '@payloadcms/db-sqlite@3.81.0': + resolution: {integrity: sha512-TgRUhl1mlPIa5O0Gw1caaXtfF319bZ798oRFNG0sU5vroR1PZIh3Cm7Wjvht/kAryu5lAVJo6V4aEerftGkxUw==} + peerDependencies: + payload: 3.81.0 + + '@payloadcms/drizzle@3.81.0': + resolution: {integrity: sha512-0hheoLFbxk1piSLtMaiTUc34HOhS3GOMnGw2hYJkYckrFMTjcJjM2nB4IEbRmk94CueS4LGitSt8xu7XwdZbkA==} + peerDependencies: + payload: 3.81.0 + '@payloadcms/eslint-config@3.28.0': resolution: {integrity: sha512-BiGtowdT4uLdGaM1yxP3oZRZrRMi27FiIU2eJuRqiGqdCVfKYRtlNAHq5knf2ExmdV/U3yZivH4linR2DNT2eA==} @@ -1037,6 +1516,17 @@ packages: next: '>=15.2.9 <15.3.0 || >=15.3.9 <15.4.0 || >=15.4.11 <15.5.0 || >=16.2.0-canary.10 <17.0.0' payload: 3.79.0 + '@payloadcms/richtext-lexical@3.79.0': + resolution: {integrity: sha512-SPoF44Lf3SwuQtWn51VsqHHSteIoymeANF+T+iGk6g9ji2QoVMWaYu8g6lp8TjNtGd0oLvYhAuTBnKXMIpCavA==} + engines: {node: ^18.20.2 || >=20.9.0} + peerDependencies: + '@faceless-ui/modal': 3.0.0 + '@faceless-ui/scroll-info': 2.0.0 + '@payloadcms/next': 3.79.0 + payload: 3.79.0 + react: ^19.0.1 || ^19.1.2 || ^19.2.1 + react-dom: ^19.0.1 || ^19.1.2 || ^19.2.1 + '@payloadcms/translations@3.79.0': resolution: {integrity: sha512-xDJ5tjTDQIYebZ3HKZikktsBiWAqk80sN0EY50L990oWtW3hSVj6ervE39wlbK9prNuOiIhSS8NGV4nVYDxspg==} @@ -1052,6 +1542,107 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@preact/signals-core@1.14.1': + resolution: {integrity: sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng==} + + '@rolldown/binding-android-arm64@1.0.0-rc.12': + resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': + resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.12': + resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': + resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': + resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': + resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': + resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': + resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': + resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': + resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': + resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': + resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': + resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': + resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': + resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-rc.12': + resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==} + '@sindresorhus/is@5.6.0': resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} engines: {node: '>=14.16'} @@ -1223,6 +1814,9 @@ packages: resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} engines: {node: '>=16.0.0'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@swc/cli@0.8.0': resolution: {integrity: sha512-vzUkYzlqLe9dC+B0ZIH62CzfSZOCTjIsmquYyyyi45JCm1xmRfLDKeEeMrEPPyTWnEEN84e4iVd49Tgqa+2GaA==} engines: {node: '>= 20.19.0'} @@ -1327,21 +1921,42 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/acorn@4.0.6': + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/busboy@1.5.4': resolution: {integrity: sha512-kG7WrUuAKK0NoyxfQHsVE6j1m01s6kMma64E+OZenQABMQyTJop1DumUWcLwAQ2JzpefU7PDYoRDKl8uZosFjw==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/doctrine@0.0.9': resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/google.maps@3.58.1': resolution: {integrity: sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==} + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/http-cache-semantics@4.2.0': resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} @@ -1351,6 +1966,12 @@ packages: '@types/lodash@4.17.13': resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@22.10.1': resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} @@ -1370,12 +1991,27 @@ packages: '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + '@types/webidl-conversions@7.0.3': resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + '@types/whatwg-mimetype@3.0.2': + resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} + '@types/whatwg-url@11.0.5': resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript-eslint/eslint-plugin@8.26.1': resolution: {integrity: sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1467,6 +2103,35 @@ packages: resolution: {integrity: sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/expect@4.1.2': + resolution: {integrity: sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==} + + '@vitest/mocker@4.1.2': + resolution: {integrity: sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.2': + resolution: {integrity: sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==} + + '@vitest/runner@4.1.2': + resolution: {integrity: sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==} + + '@vitest/snapshot@4.1.2': + resolution: {integrity: sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==} + + '@vitest/spy@4.1.2': + resolution: {integrity: sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==} + + '@vitest/utils@4.1.2': + resolution: {integrity: sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==} + '@xhmikosr/archive-type@7.1.0': resolution: {integrity: sha512-xZEpnGplg1sNPyEgFh0zbHxqlw5dtYg6viplmWSxUj12+QjU9SKu3U/2G73a15pEjLaOqTefNSZ1fOPUOT4Xgg==} engines: {node: '>=18'} @@ -1565,6 +2230,10 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -1693,6 +2362,9 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -1727,10 +2399,29 @@ packages: caniuse-lite@1.0.30001760: resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==} + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} @@ -1793,6 +2484,9 @@ packages: convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + copyfiles@2.4.1: resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} hasBin: true @@ -1823,12 +2517,19 @@ packages: cssfilter@0.0.10: resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -1870,6 +2571,9 @@ packages: supports-color: optional: true + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -1901,10 +2605,17 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -1916,6 +2627,102 @@ packages: resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} + drizzle-kit@0.31.7: + resolution: {integrity: sha512-hOzRGSdyKIU4FcTSFYGKdXEjFsncVwHZ43gY3WU5Bz9j5Iadp6Rh6hxLSQ1IWXpKLBKt/d5y1cpSPcV+FcoQ1A==} + hasBin: true + + drizzle-orm@0.44.7: + resolution: {integrity: sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@upstash/redis': '>=1.34.7' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@upstash/redis': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1933,6 +2740,10 @@ packages: resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} engines: {node: '>=10.13.0'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1948,6 +2759,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -1964,6 +2778,21 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} engines: {node: '>=18'} @@ -1973,6 +2802,9 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2157,6 +2989,15 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2168,6 +3009,10 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + ext-list@2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -2217,6 +3062,10 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -2273,6 +3122,10 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2386,6 +3239,10 @@ packages: resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + happy-dom@20.8.9: + resolution: {integrity: sha512-Tz23LR9T9jOGVZm2x1EPdXqwA37G/owYMxRwU0E4miurAtFsPMQ1d2Jc2okUaSjZqAFz2oEn3FLXC5a0a+siyA==} + engines: {node: '>=20.0.0'} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -2479,6 +3336,12 @@ packages: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2521,6 +3384,9 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2541,6 +3407,9 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -2613,6 +3482,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isomorphic.js@0.2.5: + resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} + jose@5.9.6: resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==} @@ -2620,6 +3492,9 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-base64@3.7.8: + resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2659,6 +3534,10 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + jsox@1.2.121: + resolution: {integrity: sha512-9Ag50tKhpTwS6r5wh3MJSAvpSof0UBr39Pto8OnzFT32Z/pAbxAsKHzyvsyMEHVslELvHyO/4/jaQELHk8wDcw==} + hasBin: true + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -2678,16 +3557,103 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - language-subtag-registry@0.3.23: - resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lexical@0.41.0: + resolution: {integrity: sha512-pNIm5+n+hVnJHB9gYPDYsIO5Y59dNaDU9rJmPPsfqQhP2ojKFnUoPbcRnrI9FJLXB14sSumcY8LUw7Sq70TZqA==} + + lib0@0.2.117: + resolution: {integrity: sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==} + engines: {node: '>=16'} + hasBin: true + + libsql@0.4.7: + resolution: {integrity: sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw==} + cpu: [x64, arm64, wasm32] + os: [darwin, linux, win32] + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] - language-tags@1.0.9: - resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} - engines: {node: '>=0.10'} + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -2702,6 +3668,9 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2714,6 +3683,9 @@ packages: resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} engines: {node: 20 || >=22} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -2721,6 +3693,21 @@ packages: md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + + mdast-util-mdx-jsx@3.1.3: + resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + memoize-one@6.0.0: resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} @@ -2734,6 +3721,78 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-mdx-jsx@3.0.1: + resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -2832,6 +3891,11 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + nanoid@3.3.8: resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2864,6 +3928,15 @@ packages: sass: optional: true + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + noms@0.0.0: resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} @@ -2906,6 +3979,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -2944,6 +4020,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -2974,6 +4053,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + payload@3.79.0: resolution: {integrity: sha512-Pey2gBhFL5QkAmN2KMkzXdiBS4QOi5IiQF4Ji9hCNu7kaDcNYtgk75EeWRGP4hOcb22+dqYnw2TZm5Zs/0KBKw==} engines: {node: ^18.20.2 || >=20.9.0} @@ -2995,8 +4077,8 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pino-abstract-transport@2.0.0: @@ -3028,6 +4110,10 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -3037,12 +4123,19 @@ packages: engines: {node: '>=14'} hasBin: true + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} process-warning@5.0.0: resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + promise-limit@2.7.0: + resolution: {integrity: sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==} + prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -3086,6 +4179,16 @@ packages: peerDependencies: react: ^19.2.4 + react-error-boundary@4.1.2: + resolution: {integrity: sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==} + peerDependencies: + react: '>=16.13.1' + + react-error-boundary@6.1.1: + resolution: {integrity: sha512-BrYwPOdXi5mqkk5lw+Uvt0ThHx32rCt3BkukS4X23A2AIWDPSGX6iaWTc0y9TU/mHDA/6qOSGel+B2ERkOvD1w==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-google-places-autocomplete@4.1.0: resolution: {integrity: sha512-C+BOJ/2667DLAFpd9To/OZJm1+1MOp7J6fQihys/W89tDcXb0O7i5ea7zOZ58ZE0mydnz788WxWKpqBqQJHjJg==} peerDependencies: @@ -3192,6 +4295,11 @@ packages: engines: {node: 20 || >=22} hasBin: true + rolldown@1.0.0-rc.12: + resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -3298,6 +4406,9 @@ packages: sift@17.1.3: resolution: {integrity: sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -3340,10 +4451,17 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + source-map@0.7.6: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} @@ -3361,9 +4479,15 @@ packages: stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + state-local@1.0.7: resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + std-env@4.0.0: + resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -3404,6 +4528,9 @@ packages: string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -3483,14 +4610,34 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + to-no-case@1.0.2: + resolution: {integrity: sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + to-snake-case@1.0.0: + resolution: {integrity: sha512-joRpzBAk1Bhi2eGEYBjukEWHOe/IvclOkiJl3DtA91jV6NwQ3MwXA4FHYeqk8BNp/D8bmi9tcNbRu/SozP0jbQ==} + + to-space-case@1.0.0: + resolution: {integrity: sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==} + token-types@6.1.2: resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} @@ -3582,6 +4729,21 @@ packages: resolution: {integrity: sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==} engines: {node: '>=20.18.1'} + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} @@ -3619,14 +4781,107 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true + uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vite@8.0.4: + resolution: {integrity: sha512-baBr4jUVSLJ0RPyZ2nK0zS2+W8hNHbM4hEzfvllukmRPVS3xDG5ATTNtbRXrKIOE2b8/FsPWJAOnuIxcs7g3cw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.2: + resolution: {integrity: sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.2 + '@vitest/browser-preview': 4.1.2 + '@vitest/browser-webdriverio': 4.1.2 + '@vitest/ui': 4.1.2 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + whatwg-url@14.2.0: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} @@ -3652,6 +4907,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -3704,10 +4964,17 @@ packages: resolution: {integrity: sha512-k1isifdbpNSFEHFJ1ZY4YDewv0IH9FR61lDetaRMD3j2ae3bIXGV+7c+LHCqtQGofSd8PIyV4X6+dHMAnSr60A==} engines: {node: '>=12'} + yjs@13.6.30: + resolution: {integrity: sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: '@apidevtools/json-schema-ref-parser@11.7.2': @@ -4250,11 +5517,24 @@ snapshots: react: 19.2.4 tslib: 2.8.1 + '@drizzle-team/brocli@0.10.2': {} + + '@emnapi/core@1.9.2': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.7.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.25.9 @@ -4321,79 +5601,233 @@ snapshots: '@epic-web/invariant@1.0.0': {} + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.13.6 + + '@esbuild/aix-ppc64@0.25.12': + optional: true + '@esbuild/aix-ppc64@0.27.3': optional: true + '@esbuild/android-arm64@0.18.20': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + '@esbuild/android-arm64@0.27.3': optional: true + '@esbuild/android-arm@0.18.20': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + '@esbuild/android-arm@0.27.3': optional: true + '@esbuild/android-x64@0.18.20': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + '@esbuild/android-x64@0.27.3': optional: true + '@esbuild/darwin-arm64@0.18.20': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + '@esbuild/darwin-arm64@0.27.3': optional: true + '@esbuild/darwin-x64@0.18.20': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + '@esbuild/darwin-x64@0.27.3': optional: true + '@esbuild/freebsd-arm64@0.18.20': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + '@esbuild/freebsd-arm64@0.27.3': optional: true + '@esbuild/freebsd-x64@0.18.20': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + '@esbuild/freebsd-x64@0.27.3': optional: true + '@esbuild/linux-arm64@0.18.20': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + '@esbuild/linux-arm64@0.27.3': optional: true - '@esbuild/linux-arm@0.27.3': + '@esbuild/linux-arm@0.18.20': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.18.20': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.18.20': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.18.20': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.18.20': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.18.20': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.18.20': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.18.20': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.18.20': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.18.20': optional: true - '@esbuild/linux-ia32@0.27.3': + '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/linux-loong64@0.27.3': + '@esbuild/openbsd-x64@0.27.3': optional: true - '@esbuild/linux-mips64el@0.27.3': + '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.27.3': + '@esbuild/openharmony-arm64@0.27.3': optional: true - '@esbuild/linux-riscv64@0.27.3': + '@esbuild/sunos-x64@0.18.20': optional: true - '@esbuild/linux-s390x@0.27.3': + '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.27.3': + '@esbuild/sunos-x64@0.27.3': optional: true - '@esbuild/netbsd-arm64@0.27.3': + '@esbuild/win32-arm64@0.18.20': optional: true - '@esbuild/netbsd-x64@0.27.3': + '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.27.3': + '@esbuild/win32-arm64@0.27.3': optional: true - '@esbuild/openbsd-x64@0.27.3': + '@esbuild/win32-ia32@0.18.20': optional: true - '@esbuild/openharmony-arm64@0.27.3': + '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/sunos-x64@0.27.3': + '@esbuild/win32-ia32@0.27.3': optional: true - '@esbuild/win32-arm64@0.27.3': + '@esbuild/win32-x64@0.18.20': optional: true - '@esbuild/win32-ia32@0.27.3': + '@esbuild/win32-x64@0.25.12': optional: true '@esbuild/win32-x64@0.27.3': @@ -4478,7 +5912,7 @@ snapshots: dependencies: '@eslint-react/eff': 1.31.0 '@typescript-eslint/utils': 8.57.0(eslint@9.22.0)(typescript@5.7.3) - picomatch: 4.0.3 + picomatch: 4.0.4 ts-pattern: 5.9.0 transitivePeerDependencies: - eslint @@ -4573,6 +6007,20 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) + '@floating-ui/react-dom@2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/dom': 1.7.6 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@floating-ui/react@0.27.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@floating-ui/utils': 0.2.11 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + tabbable: 6.2.0 + '@floating-ui/react@0.27.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -4696,22 +6144,245 @@ snapshots: '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} - '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jsdevtools/ono@7.1.3': {} + '@lexical/clipboard@0.41.0': + dependencies: + '@lexical/html': 0.41.0 + '@lexical/list': 0.41.0 + '@lexical/selection': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/code@0.41.0': + dependencies: + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + prismjs: 1.30.0 + + '@lexical/devtools-core@0.41.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@lexical/html': 0.41.0 + '@lexical/link': 0.41.0 + '@lexical/mark': 0.41.0 + '@lexical/table': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@lexical/dragon@0.41.0': + dependencies: + '@lexical/extension': 0.41.0 + lexical: 0.41.0 + + '@lexical/extension@0.41.0': + dependencies: + '@lexical/utils': 0.41.0 + '@preact/signals-core': 1.14.1 + lexical: 0.41.0 + + '@lexical/hashtag@0.41.0': + dependencies: + '@lexical/text': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/headless@0.41.0': + dependencies: + happy-dom: 20.8.9 + lexical: 0.41.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@lexical/history@0.41.0': + dependencies: + '@lexical/extension': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/html@0.41.0': + dependencies: + '@lexical/selection': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/link@0.41.0': + dependencies: + '@lexical/extension': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/list@0.41.0': + dependencies: + '@lexical/extension': 0.41.0 + '@lexical/selection': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/mark@0.41.0': + dependencies: + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/markdown@0.41.0': + dependencies: + '@lexical/code': 0.41.0 + '@lexical/link': 0.41.0 + '@lexical/list': 0.41.0 + '@lexical/rich-text': 0.41.0 + '@lexical/text': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/offset@0.41.0': + dependencies: + lexical: 0.41.0 + + '@lexical/overflow@0.41.0': + dependencies: + lexical: 0.41.0 + + '@lexical/plain-text@0.41.0': + dependencies: + '@lexical/clipboard': 0.41.0 + '@lexical/dragon': 0.41.0 + '@lexical/selection': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/react@0.41.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(yjs@13.6.30)': + dependencies: + '@floating-ui/react': 0.27.19(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@lexical/devtools-core': 0.41.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@lexical/dragon': 0.41.0 + '@lexical/extension': 0.41.0 + '@lexical/hashtag': 0.41.0 + '@lexical/history': 0.41.0 + '@lexical/link': 0.41.0 + '@lexical/list': 0.41.0 + '@lexical/mark': 0.41.0 + '@lexical/markdown': 0.41.0 + '@lexical/overflow': 0.41.0 + '@lexical/plain-text': 0.41.0 + '@lexical/rich-text': 0.41.0 + '@lexical/table': 0.41.0 + '@lexical/text': 0.41.0 + '@lexical/utils': 0.41.0 + '@lexical/yjs': 0.41.0(yjs@13.6.30) + lexical: 0.41.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-error-boundary: 6.1.1(react@19.2.4) + transitivePeerDependencies: + - yjs + + '@lexical/rich-text@0.41.0': + dependencies: + '@lexical/clipboard': 0.41.0 + '@lexical/dragon': 0.41.0 + '@lexical/selection': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/selection@0.41.0': + dependencies: + lexical: 0.41.0 + + '@lexical/table@0.41.0': + dependencies: + '@lexical/clipboard': 0.41.0 + '@lexical/extension': 0.41.0 + '@lexical/utils': 0.41.0 + lexical: 0.41.0 + + '@lexical/text@0.41.0': + dependencies: + lexical: 0.41.0 + + '@lexical/utils@0.41.0': + dependencies: + '@lexical/selection': 0.41.0 + lexical: 0.41.0 + + '@lexical/yjs@0.41.0(yjs@13.6.30)': + dependencies: + '@lexical/offset': 0.41.0 + '@lexical/selection': 0.41.0 + lexical: 0.41.0 + yjs: 13.6.30 + + '@libsql/client@0.14.0': + dependencies: + '@libsql/core': 0.14.0 + '@libsql/hrana-client': 0.7.0 + js-base64: 3.7.8 + libsql: 0.4.7 + promise-limit: 2.7.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/core@0.14.0': + dependencies: + js-base64: 3.7.8 + + '@libsql/darwin-arm64@0.4.7': + optional: true + + '@libsql/darwin-x64@0.4.7': + optional: true + + '@libsql/hrana-client@0.7.0': + dependencies: + '@libsql/isomorphic-fetch': 0.3.1 + '@libsql/isomorphic-ws': 0.1.5 + js-base64: 3.7.8 + node-fetch: 3.3.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/isomorphic-fetch@0.3.1': {} + + '@libsql/isomorphic-ws@0.1.5': + dependencies: + '@types/ws': 8.18.1 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@libsql/linux-arm64-gnu@0.4.7': + optional: true + + '@libsql/linux-arm64-musl@0.4.7': + optional: true + + '@libsql/linux-x64-gnu@0.4.7': + optional: true + + '@libsql/linux-x64-musl@0.4.7': + optional: true + + '@libsql/win32-x64-msvc@0.4.7': + optional: true + '@monaco-editor/loader@1.5.0': dependencies: state-local: 1.0.7 @@ -4799,6 +6470,15 @@ snapshots: '@napi-rs/nice-win32-x64-msvc': 1.1.1 optional: true + '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)': + dependencies: + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@neon-rs/load@0.0.4': {} + '@next/env@15.4.11': {} '@next/env@15.5.9': {} @@ -4839,6 +6519,8 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@oxc-project/types@0.122.0': {} + '@payloadcms/db-mongodb@3.79.0(@aws-sdk/credential-providers@3.666.0(@aws-sdk/client-sso-oidc@3.666.0(@aws-sdk/client-sts@3.666.0)))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(socks@2.8.3)': dependencies: mongoose: 8.15.1(@aws-sdk/credential-providers@3.666.0(@aws-sdk/client-sso-oidc@3.666.0(@aws-sdk/client-sts@3.666.0)))(socks@2.8.3) @@ -4856,6 +6538,90 @@ snapshots: - socks - supports-color + '@payloadcms/db-sqlite@3.81.0(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))': + dependencies: + '@libsql/client': 0.14.0 + '@payloadcms/drizzle': 3.81.0(@libsql/client@0.14.0)(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3)) + console-table-printer: 2.12.1 + drizzle-kit: 0.31.7 + drizzle-orm: 0.44.7(@libsql/client@0.14.0) + payload: 3.79.0(graphql@16.9.0)(typescript@5.9.3) + prompts: 2.4.2 + to-snake-case: 1.0.0 + uuid: 9.0.0 + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bufferutil + - bun-types + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - sql.js + - sqlite3 + - supports-color + - utf-8-validate + + '@payloadcms/drizzle@3.81.0(@libsql/client@0.14.0)(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))': + dependencies: + console-table-printer: 2.12.1 + dequal: 2.0.3 + drizzle-orm: 0.44.7(@libsql/client@0.14.0) + payload: 3.79.0(graphql@16.9.0)(typescript@5.9.3) + prompts: 2.4.2 + to-snake-case: 1.0.0 + uuid: 9.0.0 + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@electric-sql/pglite' + - '@libsql/client' + - '@libsql/client-wasm' + - '@neondatabase/serverless' + - '@op-engineering/op-sqlite' + - '@opentelemetry/api' + - '@planetscale/database' + - '@prisma/client' + - '@tidbcloud/serverless' + - '@types/better-sqlite3' + - '@types/pg' + - '@types/sql.js' + - '@upstash/redis' + - '@vercel/postgres' + - '@xata.io/client' + - better-sqlite3 + - bun-types + - expo-sqlite + - gel + - knex + - kysely + - mysql2 + - pg + - postgres + - prisma + - sql.js + - sqlite3 + '@payloadcms/eslint-config@3.28.0(@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.9.3))(eslint@9.22.0)(typescript@5.9.3))(ts-api-utils@2.4.0(typescript@5.9.3))': dependencies: '@eslint-react/eslint-plugin': 1.31.0(eslint@9.22.0)(ts-api-utils@2.4.0(typescript@5.9.3))(typescript@5.7.3) @@ -4957,6 +6723,52 @@ snapshots: - supports-color - typescript + '@payloadcms/richtext-lexical@3.79.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.79.0(@types/react@19.2.14)(graphql@16.9.0)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30)': + dependencies: + '@faceless-ui/modal': 3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@faceless-ui/scroll-info': 2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@lexical/clipboard': 0.41.0 + '@lexical/headless': 0.41.0 + '@lexical/html': 0.41.0 + '@lexical/link': 0.41.0 + '@lexical/list': 0.41.0 + '@lexical/mark': 0.41.0 + '@lexical/react': 0.41.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(yjs@13.6.30) + '@lexical/rich-text': 0.41.0 + '@lexical/selection': 0.41.0 + '@lexical/table': 0.41.0 + '@lexical/utils': 0.41.0 + '@payloadcms/next': 3.79.0(@types/react@19.2.14)(graphql@16.9.0)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + '@payloadcms/translations': 3.79.0 + '@payloadcms/ui': 3.79.0(@types/react@19.2.14)(monaco-editor@0.52.0)(next@15.4.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.77.4))(payload@3.79.0(graphql@16.9.0)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + '@types/uuid': 10.0.0 + acorn: 8.16.0 + bson-objectid: 2.0.4 + csstype: 3.1.3 + dequal: 2.0.3 + escape-html: 1.0.3 + jsox: 1.2.121 + lexical: 0.41.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-mdx-jsx: 3.1.3 + micromark-extension-mdx-jsx: 3.0.1 + payload: 3.79.0(graphql@16.9.0)(typescript@5.9.3) + qs-esm: 7.0.2 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-error-boundary: 4.1.2(react@19.2.4) + ts-essentials: 10.0.3(typescript@5.9.3) + uuid: 10.0.0 + transitivePeerDependencies: + - '@types/react' + - bufferutil + - monaco-editor + - next + - supports-color + - typescript + - utf-8-validate + - yjs + '@payloadcms/translations@3.79.0': dependencies: date-fns: 4.1.0 @@ -4998,6 +6810,60 @@ snapshots: '@pinojs/redact@0.4.0': {} + '@preact/signals-core@1.14.1': {} + + '@rolldown/binding-android-arm64@1.0.0-rc.12': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.12': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)': + dependencies: + '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': + optional: true + + '@rolldown/pluginutils@1.0.0-rc.12': {} + '@sindresorhus/is@5.6.0': {} '@smithy/abort-controller@3.1.9': @@ -5318,6 +7184,8 @@ snapshots: tslib: 2.8.1 optional: true + '@standard-schema/spec@1.1.0': {} + '@swc/cli@0.8.0(@swc/core@1.15.18)': dependencies: '@swc/core': 1.15.18 @@ -5406,10 +7274,30 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/acorn@4.0.6': + dependencies: + '@types/estree': 1.0.8 + '@types/busboy@1.5.4': dependencies: '@types/node': 22.10.1 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/deep-eql@4.0.2': {} + '@types/doctrine@0.0.9': {} '@types/eslint@9.6.1': @@ -5417,16 +7305,30 @@ snapshots: '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.8 + '@types/estree@1.0.8': {} '@types/google.maps@3.58.1': {} + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + '@types/http-cache-semantics@4.2.0': {} '@types/json-schema@7.0.15': {} '@types/lodash@4.17.13': {} + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@2.1.0': {} + '@types/node@22.10.1': dependencies: undici-types: 6.20.0 @@ -5445,13 +7347,25 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/uuid@10.0.0': {} + '@types/webidl-conversions@7.0.3': {} + '@types/whatwg-mimetype@3.0.2': {} + '@types/whatwg-url@11.0.5': dependencies: '@types/webidl-conversions': 7.0.3 - '@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.7.3))(eslint@9.22.0)(typescript@5.7.3)': + '@types/ws@8.18.1': + dependencies: + '@types/node': 22.10.1 + + '@typescript-eslint/eslint-plugin@8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.9.3))(eslint@9.22.0)(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.2 '@typescript-eslint/parser': 8.26.1(eslint@9.22.0)(typescript@5.7.3) @@ -5627,26 +7541,75 @@ snapshots: - supports-color optional: true - '@typescript-eslint/utils@8.57.0(eslint@9.22.0)(typescript@5.7.3)': + '@typescript-eslint/utils@8.57.0(eslint@9.22.0)(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.22.0) + '@typescript-eslint/scope-manager': 8.57.0 + '@typescript-eslint/types': 8.57.0 + '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.7.3) + eslint: 9.22.0 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.26.1': + dependencies: + '@typescript-eslint/types': 8.26.1 + eslint-visitor-keys: 4.2.1 + + '@typescript-eslint/visitor-keys@8.57.0': + dependencies: + '@typescript-eslint/types': 8.57.0 + eslint-visitor-keys: 5.0.1 + + '@vitest/expect@4.1.2': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.2(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0) + + '@vitest/mocker@4.1.2(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0))': + dependencies: + '@vitest/spy': 4.1.2 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0) + + '@vitest/pretty-format@4.1.2': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.2': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.22.0) - '@typescript-eslint/scope-manager': 8.57.0 - '@typescript-eslint/types': 8.57.0 - '@typescript-eslint/typescript-estree': 8.57.0(typescript@5.7.3) - eslint: 9.22.0 - typescript: 5.7.3 - transitivePeerDependencies: - - supports-color + '@vitest/utils': 4.1.2 + pathe: 2.0.3 - '@typescript-eslint/visitor-keys@8.26.1': + '@vitest/snapshot@4.1.2': dependencies: - '@typescript-eslint/types': 8.26.1 - eslint-visitor-keys: 4.2.1 + '@vitest/pretty-format': 4.1.2 + '@vitest/utils': 4.1.2 + magic-string: 0.30.21 + pathe: 2.0.3 - '@typescript-eslint/visitor-keys@8.57.0': + '@vitest/spy@4.1.2': {} + + '@vitest/utils@4.1.2': dependencies: - '@typescript-eslint/types': 8.57.0 - eslint-visitor-keys: 5.0.1 + '@vitest/pretty-format': 4.1.2 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 '@xhmikosr/archive-type@7.1.0': dependencies: @@ -5826,6 +7789,8 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + assertion-error@2.0.1: {} + ast-types-flow@0.0.8: {} async-function@1.0.0: {} @@ -5930,6 +7895,8 @@ snapshots: buffer-crc32@0.2.13: {} + buffer-from@1.1.2: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -5972,11 +7939,23 @@ snapshots: caniuse-lite@1.0.30001760: {} + ccount@2.0.1: {} + + chai@6.2.2: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + charenc@0.0.2: {} chokidar@3.6.0: @@ -6033,6 +8012,8 @@ snapshots: convert-source-map@1.9.0: {} + convert-source-map@2.0.0: {} + copyfiles@2.4.1: dependencies: glob: 7.2.3 @@ -6070,10 +8051,14 @@ snapshots: cssfilter@0.0.10: {} + csstype@3.1.3: {} + csstype@3.2.3: {} damerau-levenshtein@1.0.8: {} + data-uri-to-buffer@4.0.1: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -6108,6 +8093,10 @@ snapshots: dependencies: ms: 2.1.3 + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -6134,8 +8123,13 @@ snapshots: dequal@2.0.3: {} - detect-libc@2.1.2: - optional: true + detect-libc@2.0.2: {} + + detect-libc@2.1.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 doctrine@3.0.0: dependencies: @@ -6148,6 +8142,19 @@ snapshots: dotenv@17.3.1: {} + drizzle-kit@0.31.7: + dependencies: + '@drizzle-team/brocli': 0.10.2 + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + transitivePeerDependencies: + - supports-color + + drizzle-orm@0.44.7(@libsql/client@0.14.0): + optionalDependencies: + '@libsql/client': 0.14.0 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -6167,6 +8174,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + entities@7.0.1: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -6232,6 +8241,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@2.0.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -6253,6 +8264,67 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + esbuild-register@3.6.0(esbuild@0.25.12): + dependencies: + debug: 4.4.3 + esbuild: 0.25.12 + transitivePeerDependencies: + - supports-color + + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.3: optionalDependencies: '@esbuild/aix-ppc64': 0.27.3 @@ -6284,6 +8356,8 @@ snapshots: escalade@3.2.0: {} + escape-html@1.0.3: {} + escape-string-regexp@4.0.0: {} eslint-config-prettier@10.1.1(eslint@9.22.0): @@ -6567,6 +8641,17 @@ snapshots: estraverse@5.3.0: {} + estree-util-is-identifier-name@3.0.0: {} + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} events-universal@1.0.1: @@ -6587,6 +8672,8 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + expect-type@1.3.0: {} + ext-list@2.2.2: dependencies: mime-db: 1.54.0 @@ -6627,9 +8714,14 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.3): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.3 + picomatch: 4.0.4 + + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 fflate@0.8.2: {} @@ -6690,6 +8782,10 @@ snapshots: form-data-encoder@2.1.4: {} + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -6815,6 +8911,18 @@ snapshots: graphql@16.9.0: {} + happy-dom@20.8.9: + dependencies: + '@types/node': 22.10.1 + '@types/whatwg-mimetype': 3.0.2 + '@types/ws': 8.18.1 + entities: 7.0.1 + whatwg-mimetype: 3.0.0 + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -6894,6 +9002,13 @@ snapshots: ipaddr.js@2.2.0: {} + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -6942,6 +9057,8 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-decimal@2.0.1: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -6962,6 +9079,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hexadecimal@2.0.1: {} + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -7024,10 +9143,14 @@ snapshots: isexe@2.0.0: {} + isomorphic.js@0.2.5: {} + jose@5.9.6: {} joycon@3.1.1: {} + js-base64@3.7.8: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -7063,6 +9186,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + jsox@1.2.121: {} + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -7091,6 +9216,74 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lexical@0.41.0: {} + + lib0@0.2.117: + dependencies: + isomorphic.js: 0.2.5 + + libsql@0.4.7: + dependencies: + '@neon-rs/load': 0.0.4 + detect-libc: 2.0.2 + optionalDependencies: + '@libsql/darwin-arm64': 0.4.7 + '@libsql/darwin-x64': 0.4.7 + '@libsql/linux-arm64-gnu': 0.4.7 + '@libsql/linux-arm64-musl': 0.4.7 + '@libsql/linux-x64-gnu': 0.4.7 + '@libsql/linux-x64-musl': 0.4.7 + '@libsql/win32-x64-msvc': 0.4.7 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + lines-and-columns@1.2.4: {} locate-path@6.0.0: @@ -7101,6 +9294,8 @@ snapshots: lodash@4.17.21: {} + longest-streak@3.1.0: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -7109,6 +9304,10 @@ snapshots: lru-cache@11.2.7: {} + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} md5@2.3.0: @@ -7117,6 +9316,61 @@ snapshots: crypt: 0.0.2 is-buffer: 1.1.6 + mdast-util-from-markdown@2.0.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.1.3: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + memoize-one@6.0.0: {} memory-pager@1.5.0: {} @@ -7125,6 +9379,175 @@ snapshots: merge2@1.4.1: {} + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.1: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.8 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.8 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -7207,6 +9630,8 @@ snapshots: ms@2.1.3: {} + nanoid@3.3.11: {} + nanoid@3.3.8: {} natural-compare-lite@1.4.0: {} @@ -7237,6 +9662,14 @@ snapshots: - '@babel/core' - babel-plugin-macros + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + noms@0.0.0: dependencies: inherits: 2.0.4 @@ -7281,6 +9714,8 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} once@1.4.0: @@ -7322,6 +9757,16 @@ snapshots: dependencies: callsites: 3.1.0 + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.3.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.26.2 @@ -7346,6 +9791,8 @@ snapshots: path-type@4.0.0: {} + pathe@2.0.3: {} + payload@3.79.0(graphql@16.9.0)(typescript@5.9.3): dependencies: '@next/env': 15.5.9 @@ -7393,7 +9840,7 @@ snapshots: picomatch@2.3.1: {} - picomatch@4.0.3: {} + picomatch@4.0.4: {} pino-abstract-transport@2.0.0: dependencies: @@ -7445,14 +9892,24 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + prelude-ls@1.2.1: {} prettier@3.8.1: {} + prismjs@1.30.0: {} + process-nextick-args@2.0.1: {} process-warning@5.0.0: {} + promise-limit@2.7.0: {} + prompts@2.4.2: dependencies: kleur: 3.0.3 @@ -7494,6 +9951,15 @@ snapshots: react: 19.2.4 scheduler: 0.27.0 + react-error-boundary@4.1.2(react@19.2.4): + dependencies: + '@babel/runtime': 7.28.6 + react: 19.2.4 + + react-error-boundary@6.1.1(react@19.2.4): + dependencies: + react: 19.2.4 + react-google-places-autocomplete@4.1.0(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: '@googlemaps/js-api-loader': 1.16.10 @@ -7638,6 +10104,30 @@ snapshots: glob: 13.0.6 package-json-from-dist: 1.0.1 + rolldown@1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1): + dependencies: + '@oxc-project/types': 0.122.0 + '@rolldown/pluginutils': 1.0.0-rc.12 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.12 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.12 + '@rolldown/binding-darwin-x64': 1.0.0-rc.12 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.12 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.12 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.12 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.12 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.12 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.12 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.12 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.12 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.12 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1) + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.12 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.12 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -7791,6 +10281,8 @@ snapshots: sift@17.1.3: {} + siginfo@2.0.0: {} + signal-exit@3.0.7: {} simple-wcswidth@1.0.1: {} @@ -7827,8 +10319,15 @@ snapshots: source-map-js@1.2.1: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} + source-map@0.7.6: {} sparse-bitfield@3.0.3: @@ -7842,8 +10341,12 @@ snapshots: stable-hash@0.0.4: {} + stackback@0.0.2: {} + state-local@1.0.7: {} + std-env@4.0.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -7903,6 +10406,11 @@ snapshots: dependencies: safe-buffer: 5.1.2 + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -7982,15 +10490,31 @@ snapshots: through@2.3.8: {} + tinybench@2.9.0: {} + + tinyexec@1.0.4: {} + tinyglobby@0.2.15: dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@3.1.0: {} + + to-no-case@1.0.2: {} to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + to-snake-case@1.0.0: + dependencies: + to-space-case: 1.0.0 + + to-space-case@1.0.0: + dependencies: + to-no-case: 1.0.2 + token-types@6.1.2: dependencies: '@borewit/text-codec': 0.2.1 @@ -8068,7 +10592,7 @@ snapshots: typescript-eslint@8.26.1(eslint@9.22.0)(typescript@5.7.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.7.3))(eslint@9.22.0)(typescript@5.7.3) + '@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0)(typescript@5.9.3))(eslint@9.22.0)(typescript@5.7.3) '@typescript-eslint/parser': 8.26.1(eslint@9.22.0)(typescript@5.7.3) '@typescript-eslint/utils': 8.26.1(eslint@9.22.0)(typescript@5.7.3) eslint: 9.22.0 @@ -8098,6 +10622,29 @@ snapshots: undici@7.18.2: {} + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + untildify@4.0.0: {} uri-js@4.4.1: @@ -8125,11 +10672,108 @@ snapshots: uuid@10.0.0: {} + uuid@9.0.0: {} + uuid@9.0.1: optional: true + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.8 + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1) + tinyglobby: 0.2.15 + optionalDependencies: + esbuild: 0.25.12 + fsevents: 2.3.3 + sass: 1.77.4 + tsx: 4.21.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.8 + rolldown: 1.0.0-rc.12(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1) + tinyglobby: 0.2.15 + optionalDependencies: + esbuild: 0.27.3 + fsevents: 2.3.3 + sass: 1.77.4 + tsx: 4.21.0 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' + + vitest@4.1.2(happy-dom@20.8.9)(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.25.12)(sass@1.77.4)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + happy-dom: 20.8.9 + transitivePeerDependencies: + - msw + + vitest@4.1.2(happy-dom@20.8.9)(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0)): + dependencies: + '@vitest/expect': 4.1.2 + '@vitest/mocker': 4.1.2(vite@8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0)) + '@vitest/pretty-format': 4.1.2 + '@vitest/runner': 4.1.2 + '@vitest/snapshot': 4.1.2 + '@vitest/spy': 4.1.2 + '@vitest/utils': 4.1.2 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 8.0.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.7.1)(esbuild@0.27.3)(sass@1.77.4)(tsx@4.21.0) + why-is-node-running: 2.3.0 + optionalDependencies: + happy-dom: 20.8.9 + transitivePeerDependencies: + - msw + + web-streams-polyfill@3.3.3: {} + webidl-conversions@7.0.0: {} + whatwg-mimetype@3.0.0: {} + whatwg-url@14.2.0: dependencies: tr46: 5.1.1 @@ -8180,6 +10824,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} wrap-ansi@7.0.0: @@ -8220,4 +10869,10 @@ snapshots: buffer-crc32: 0.2.13 pend: 1.2.0 + yjs@13.6.30: + dependencies: + lib0: 0.2.117 + yocto-queue@0.1.0: {} + + zwitch@2.0.4: {} diff --git a/geocoding/src/endpoints/geocodingSearch.test.ts b/geocoding/src/endpoints/geocodingSearch.test.ts new file mode 100644 index 00000000..1b0fc59d --- /dev/null +++ b/geocoding/src/endpoints/geocodingSearch.test.ts @@ -0,0 +1,113 @@ +import type { PayloadRequest } from 'payload' + +import { beforeEach, describe, expect, it, vi } from 'vitest' + +import * as geocodingService from '../services/googleGeocoding.js' +import { createGeocodingSearchEndpoint } from './geocodingSearch.js' + +const MOCK_API_KEY = 'test-api-key' + +const MOCK_RESULT = { + addressComponents: [], + formattedAddress: 'Berlin, Germany', + location: { lat: 52.52, lng: 13.405 }, + placeId: 'ChIJAVkDPzdOqEcRcDteW0YgIQQ', + types: ['locality'], +} + +function createMockRequest(overrides: { url: string } & Partial): PayloadRequest { + return { user: { id: '1', email: 'test@test.com' }, ...overrides } as unknown as PayloadRequest +} + +describe('createGeocodingSearchEndpoint', () => { + beforeEach(() => { + vi.restoreAllMocks() + }) + + it('returns 401 when user is not authenticated (default access)', async () => { + const endpoint = createGeocodingSearchEndpoint({ apiKey: MOCK_API_KEY }) + const req = createMockRequest({ + url: 'http://localhost/api/geocoding/search?q=Berlin', + user: null as any, + }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(401) + + const body = await response.json() + expect(body.errors[0].message).toBe('Unauthorized') + }) + + it('returns 200 with results for authenticated user', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([MOCK_RESULT]) + + const endpoint = createGeocodingSearchEndpoint({ apiKey: MOCK_API_KEY }) + const req = createMockRequest({ url: 'http://localhost/api/geocoding/search?q=Berlin' }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(200) + + const body = await response.json() + expect(body.results).toHaveLength(1) + expect(body.results[0].formattedAddress).toBe('Berlin, Germany') + expect(body.results[0].location).toEqual({ lat: 52.52, lng: 13.405 }) + }) + + it('returns 400 when q parameter is missing', async () => { + const endpoint = createGeocodingSearchEndpoint({ apiKey: MOCK_API_KEY }) + const req = createMockRequest({ url: 'http://localhost/api/geocoding/search' }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(400) + + const body = await response.json() + expect(body.errors[0].message).toBe('Query parameter "q" is required') + }) + + it('returns 400 when q parameter is empty', async () => { + const endpoint = createGeocodingSearchEndpoint({ apiKey: MOCK_API_KEY }) + const req = createMockRequest({ url: 'http://localhost/api/geocoding/search?q=%20' }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(400) + }) + + it('uses custom access function when provided', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([MOCK_RESULT]) + + const customAccess = vi.fn().mockResolvedValue(true) + const endpoint = createGeocodingSearchEndpoint({ access: customAccess, apiKey: MOCK_API_KEY }) + const req = createMockRequest({ + url: 'http://localhost/api/geocoding/search?q=Berlin', + user: null as any, + }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(200) + expect(customAccess).toHaveBeenCalledWith({ req }) + }) + + it('denies access when custom access function returns false', async () => { + const customAccess = vi.fn().mockResolvedValue(false) + const endpoint = createGeocodingSearchEndpoint({ access: customAccess, apiKey: MOCK_API_KEY }) + const req = createMockRequest({ url: 'http://localhost/api/geocoding/search?q=Berlin' }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(401) + }) + + it('returns 502 when geocoding service fails', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockRejectedValue( + new Error('Google Geocoding API error: REQUEST_DENIED'), + ) + + const endpoint = createGeocodingSearchEndpoint({ apiKey: MOCK_API_KEY }) + const req = createMockRequest({ url: 'http://localhost/api/geocoding/search?q=Berlin' }) + + const response = await endpoint.handler(req) + expect(response.status).toBe(502) + + const body = await response.json() + expect(body.errors[0].message).toContain('REQUEST_DENIED') + }) +}) diff --git a/geocoding/src/endpoints/geocodingSearch.ts b/geocoding/src/endpoints/geocodingSearch.ts new file mode 100644 index 00000000..1d726f52 --- /dev/null +++ b/geocoding/src/endpoints/geocodingSearch.ts @@ -0,0 +1,45 @@ +import type { Endpoint, PayloadRequest } from 'payload' + +import type { GeocodingEndpointAccess } from '../types/GeoCodingPluginConfig.js' + +import { geocodeAddress } from '../services/googleGeocoding.js' + +/** + * Creates a Payload endpoint for server-side geocoding. + * Enables agents and API consumers to geocode addresses without the browser UI. + * + * Usage: GET /api/geocoding-plugin/search?q=Berlin + */ +export const createGeocodingSearchEndpoint = (options: { + access?: GeocodingEndpointAccess + apiKey: string +}): Endpoint => ({ + handler: async (req: PayloadRequest) => { + // Authentication: require a logged-in user by default + const hasAccess = options.access ? await options.access({ req }) : Boolean(req.user) + + if (!hasAccess) { + return Response.json({ errors: [{ message: 'Unauthorized' }] }, { status: 401 }) + } + + const url = new URL(req.url!) + const query = url.searchParams.get('q') + + if (!query || query.trim() === '') { + return Response.json( + { errors: [{ message: 'Query parameter "q" is required' }] }, + { status: 400 }, + ) + } + + try { + const results = await geocodeAddress(query, options.apiKey) + return Response.json({ results }) + } catch (error) { + const message = error instanceof Error ? error.message : 'Geocoding failed' + return Response.json({ errors: [{ message }] }, { status: 502 }) + } + }, + method: 'get', + path: '/geocoding-plugin/search', +}) diff --git a/geocoding/src/fields/geocodingField.test.ts b/geocoding/src/fields/geocodingField.test.ts new file mode 100644 index 00000000..2220da68 --- /dev/null +++ b/geocoding/src/fields/geocodingField.test.ts @@ -0,0 +1,59 @@ +import type { JSONField, PointField, RowField, TextField } from 'payload' + +import { describe, expect, it } from 'vitest' + +import { geocodingField } from './geocodingField.js' + +describe('geocodingField', () => { + it('creates a row field with point, geodata, and address fields', () => { + const field = geocodingField({ + pointField: { name: 'location', type: 'point' }, + }) as RowField + + expect(field.type).toBe('row') + // geodata JSON + point + hidden address field + expect(field.fields).toHaveLength(3) + }) + + it('always adds a hidden address text field for server-side geocoding', () => { + const field = geocodingField({ + pointField: { name: 'location', type: 'point' }, + }) as RowField + + const addressField = field.fields.find( + (f) => 'name' in f && f.name === 'location_address', + ) as TextField + expect(addressField).toBeDefined() + expect(addressField.type).toBe('text') + expect(addressField.admin?.hidden).toBe(true) + }) + + it('adds beforeChange hooks to both geodata and point fields', () => { + const field = geocodingField({ + pointField: { name: 'location', type: 'point' }, + }) as RowField + + const geoDataField = field.fields.find( + (f) => 'name' in f && f.name === 'location_googlePlacesData', + ) as JSONField + expect(geoDataField.hooks?.beforeChange).toHaveLength(1) + + const pointField = field.fields.find((f) => 'name' in f && f.name === 'location') as PointField + expect(pointField.hooks?.beforeChange).toHaveLength(1) + }) + + it('preserves existing point field hooks', () => { + const existingHook = () => undefined + const field = geocodingField({ + pointField: { + name: 'location', + type: 'point', + hooks: { beforeChange: [existingHook] }, + }, + }) as RowField + + const pointField = field.fields.find((f) => 'name' in f && f.name === 'location') as PointField + expect(pointField.hooks?.beforeChange).toHaveLength(2) + expect(pointField.hooks!.beforeChange![0]).toBe(existingHook) + }) +}) diff --git a/geocoding/src/fields/geocodingField.ts b/geocoding/src/fields/geocodingField.ts index 44e81f46..eed8d098 100644 --- a/geocoding/src/fields/geocodingField.ts +++ b/geocoding/src/fields/geocodingField.ts @@ -1,38 +1,72 @@ -import type { Field } from 'payload' +import type { Field, PointField } from 'payload' import type { GeoCodingFieldConfig } from '../types/GeoCodingFieldConfig.js' +import { + createGeoDataBeforeChangeHook, + createPointBeforeChangeHook, +} from '../hooks/geocodeBeforeChange.js' + /** * Creates a row field containing: * 1. The provided point field for storing the coordinates from the Google Places API * 2. A JSON field that stores the raw Google Places API geocoding data + * 3. A hidden text field `{pointFieldName}_address` for server-side geocoding via the API + * + * Agents and API consumers can submit an address string via the `_address` field, + * and the beforeChange hooks will auto-geocode it and populate the point and geodata fields. */ export const geocodingField = (config: GeoCodingFieldConfig): Field => { + const pointFieldName = config.pointField.name + + const geoDataField: Field = { + name: pointFieldName + '_googlePlacesData', + type: 'json', + access: config.geoDataFieldOverride?.access ?? {}, + admin: { + // overridable props: + readOnly: true, + + ...config.geoDataFieldOverride?.admin, + + // non-overridable props: + components: { + Field: '@jhb.software/payload-geocoding-plugin/server#GeocodingField', + }, + }, + hooks: { + beforeChange: [createGeoDataBeforeChangeHook({ pointFieldName })], + }, + label: config.geoDataFieldOverride?.label ?? 'Location', + required: config.geoDataFieldOverride?.required, + } + + const pointField: PointField = { + ...config.pointField, + hooks: { + ...config.pointField.hooks, + beforeChange: [ + ...(config.pointField.hooks?.beforeChange ?? []), + createPointBeforeChangeHook({ pointFieldName }), + ], + }, + } + + const addressField: Field = { + name: pointFieldName + '_address', + type: 'text', + admin: { + hidden: true, + }, + label: 'Address (for server-side geocoding)', + virtual: true, + } + return { type: 'row', admin: { position: config.pointField.admin?.position ?? undefined, }, - fields: [ - { - name: config.pointField.name + '_googlePlacesData', - type: 'json', - access: config.geoDataFieldOverride?.access ?? {}, - admin: { - // overridable props: - readOnly: true, - - ...config.geoDataFieldOverride?.admin, - - // non-overridable props: - components: { - Field: '@jhb.software/payload-geocoding-plugin/server#GeocodingField', - }, - }, - label: config.geoDataFieldOverride?.label ?? 'Location', - required: config.geoDataFieldOverride?.required, - }, - config.pointField, - ], + fields: [geoDataField, pointField, addressField], } } diff --git a/geocoding/src/hooks/geocodeBeforeChange.test.ts b/geocoding/src/hooks/geocodeBeforeChange.test.ts new file mode 100644 index 00000000..315372d1 --- /dev/null +++ b/geocoding/src/hooks/geocodeBeforeChange.test.ts @@ -0,0 +1,157 @@ +import type { FieldHookArgs } from 'payload' + +import { beforeEach, describe, expect, it, vi } from 'vitest' + +import * as geocodingService from '../services/googleGeocoding.js' +import { + createGeoDataBeforeChangeHook, + createPointBeforeChangeHook, +} from './geocodeBeforeChange.js' + +const MOCK_API_KEY = 'test-api-key' + +const MOCK_RESULT = { + addressComponents: [{ long_name: 'Berlin', short_name: 'Berlin', types: ['locality'] }], + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + location: { lat: 52.5219, lng: 13.4132 }, + placeId: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + types: ['point_of_interest'], +} + +function createMockReq() { + return { + payload: { + config: { + custom: { + payloadGeocodingPlugin: { + googleMapsApiKey: MOCK_API_KEY, + }, + }, + }, + }, + } +} + +function createMockHookArgs(overrides: Partial): FieldHookArgs { + return { + blockData: undefined, + collection: null, + context: {}, + data: {}, + field: {} as any, + operation: 'create', + originalDoc: undefined, + path: [] as any, + req: createMockReq() as any, + schemaPath: [] as any, + siblingData: {}, + value: undefined, + ...overrides, + } as FieldHookArgs +} + +describe('createGeoDataBeforeChangeHook', () => { + beforeEach(() => { + vi.restoreAllMocks() + }) + + it('geocodes an address string and returns geodata', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([MOCK_RESULT]) + + const hook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + + const result = await hook( + createMockHookArgs({ + siblingData: { location_address: 'Alexanderplatz, Berlin' }, + }), + ) + + expect(result).toEqual({ + addressComponents: MOCK_RESULT.addressComponents, + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + location: { lat: 52.5219, lng: 13.4132 }, + placeId: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + types: ['point_of_interest'], + }) + }) + + it('returns undefined when no address is provided', async () => { + const hook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + const result = await hook(createMockHookArgs({ siblingData: {} })) + expect(result).toBeUndefined() + }) + + it('returns undefined when address is empty string', async () => { + const hook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + const result = await hook(createMockHookArgs({ siblingData: { location_address: ' ' } })) + expect(result).toBeUndefined() + }) + + it('returns undefined when geocoding returns no results', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([]) + const hook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + const result = await hook( + createMockHookArgs({ siblingData: { location_address: 'xyznonexistent' } }), + ) + expect(result).toBeUndefined() + }) + + it('throws when API key is not configured', async () => { + const hook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + await expect( + hook( + createMockHookArgs({ + req: { payload: { config: { custom: {} } } } as any, + siblingData: { location_address: 'Berlin' }, + }), + ), + ).rejects.toThrow('Geocoding plugin API key not configured') + }) +}) + +describe('createPointBeforeChangeHook', () => { + beforeEach(() => { + vi.restoreAllMocks() + }) + + it('returns [lng, lat] from geocoded address', async () => { + vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([MOCK_RESULT]) + + const hook = createPointBeforeChangeHook({ pointFieldName: 'location' }) + const result = await hook( + createMockHookArgs({ + siblingData: { location_address: 'Berlin' }, + }), + ) + + expect(result).toEqual([13.4132, 52.5219]) + }) + + it('returns existing value when no address is provided', async () => { + const hook = createPointBeforeChangeHook({ pointFieldName: 'location' }) + const result = await hook(createMockHookArgs({ siblingData: {}, value: [1, 2] })) + expect(result).toEqual([1, 2]) + }) + + it('shares cached geocoding result via context', async () => { + const geocodeSpy = vi.spyOn(geocodingService, 'geocodeAddress').mockResolvedValue([MOCK_RESULT]) + + const context: Record = {} + const hookArgs = { context, siblingData: { location_address: 'Berlin' } } + + const geoDataHook = createGeoDataBeforeChangeHook({ pointFieldName: 'location' }) + const pointHook = createPointBeforeChangeHook({ pointFieldName: 'location' }) + + // Run both hooks concurrently (simulating Payload's parallel field processing) + const [geoDataResult, pointResult] = await Promise.all([ + geoDataHook(createMockHookArgs(hookArgs)), + pointHook(createMockHookArgs(hookArgs)), + ]) + + expect(geoDataResult).toHaveProperty('formattedAddress') + expect(pointResult).toEqual([13.4132, 52.5219]) + + // geocodeAddress should only be called once due to caching + expect(geocodeSpy).toHaveBeenCalledTimes(1) + }) +}) diff --git a/geocoding/src/hooks/geocodeBeforeChange.ts b/geocoding/src/hooks/geocodeBeforeChange.ts new file mode 100644 index 00000000..16f3d354 --- /dev/null +++ b/geocoding/src/hooks/geocodeBeforeChange.ts @@ -0,0 +1,113 @@ +import type { FieldHook } from 'payload' + +import type { GeocodingResult } from '../services/googleGeocoding.js' + +import { geocodeAddress } from '../services/googleGeocoding.js' + +/** + * Gets (or triggers) the geocoding result for the given address, caching it in + * `req.context` so that the geodata and point field hooks share a single API call. + * + * Both hooks may fire concurrently (Payload processes row fields in parallel), + * so the promise itself is cached — whichever hook runs first starts the fetch, + * and the other awaits the same promise. + */ +function getCachedGeocodingResult( + cacheKey: string, + address: string, + apiKey: string, + context: Record, +): Promise { + if (!context[cacheKey]) { + context[cacheKey] = geocodeAddress(address.trim(), apiKey) + } + return context[cacheKey] as Promise +} + +function getApiKey(req: { payload: { config: { custom?: Record } } }): string { + const apiKey = ( + req.payload.config.custom?.payloadGeocodingPlugin as { googleMapsApiKey?: string } | undefined + )?.googleMapsApiKey + + if (!apiKey) { + throw new Error( + 'Geocoding plugin API key not configured. Ensure payloadGeocodingPlugin is added to your Payload config with a googleMapsApiKey.', + ) + } + + return apiKey +} + +function getAddress( + addressFieldName: string, + siblingData?: Record, + data?: Record, +): string | undefined { + const address = siblingData?.[addressFieldName] ?? data?.[addressFieldName] + if (!address || typeof address !== 'string' || address.trim() === '') { + return undefined + } + return address +} + +/** + * beforeChange hook for the **geodata JSON field**. + * + * When `{pointFieldName}_address` contains a string, geocodes it server-side + * and returns the geocoding result as the field value. + */ +export const createGeoDataBeforeChangeHook = (options: { pointFieldName: string }): FieldHook => { + return async ({ context, data, req, siblingData }) => { + const addressFieldName = options.pointFieldName + '_address' + const address = getAddress(addressFieldName, siblingData, data) + + if (!address) { + return undefined + } + + const apiKey = getApiKey(req) + const cacheKey = `geocoding_${options.pointFieldName}` + const results = await getCachedGeocodingResult(cacheKey, address, apiKey, context) + + if (results.length === 0) { + return undefined + } + + const firstResult = results[0] + return { + addressComponents: firstResult.addressComponents, + formattedAddress: firstResult.formattedAddress, + location: firstResult.location, + placeId: firstResult.placeId, + types: firstResult.types, + } + } +} + +/** + * beforeChange hook for the **point field**. + * + * When `{pointFieldName}_address` contains a string, geocodes it server-side + * and returns `[lng, lat]` as the field value. + */ +export const createPointBeforeChangeHook = (options: { pointFieldName: string }): FieldHook => { + return async ({ context, data, req, siblingData, value }) => { + const addressFieldName = options.pointFieldName + '_address' + const address = getAddress(addressFieldName, siblingData, data) + + if (!address) { + return value + } + + const apiKey = getApiKey(req) + const cacheKey = `geocoding_${options.pointFieldName}` + const results = await getCachedGeocodingResult(cacheKey, address, apiKey, context) + + if (results.length === 0) { + return value + } + + const firstResult = results[0] + return [firstResult.location.lng, firstResult.location.lat] + } +} diff --git a/geocoding/src/index.ts b/geocoding/src/index.ts index 53c84cd5..490dfd80 100644 --- a/geocoding/src/index.ts +++ b/geocoding/src/index.ts @@ -1,4 +1,9 @@ export { geocodingField } from './fields/geocodingField.js' export { payloadGeocodingPlugin } from './plugin.js' +export { geocodeAddress } from './services/googleGeocoding.js' +export type { GeocodingResult } from './services/googleGeocoding.js' export type { GeoCodingFieldConfig } from './types/GeoCodingFieldConfig.js' -export type { GeocodingPluginConfig } from './types/GeoCodingPluginConfig.js' +export type { + GeocodingEndpointAccess, + GeocodingPluginConfig, +} from './types/GeoCodingPluginConfig.js' diff --git a/geocoding/src/plugin.test.ts b/geocoding/src/plugin.test.ts new file mode 100644 index 00000000..f63bc349 --- /dev/null +++ b/geocoding/src/plugin.test.ts @@ -0,0 +1,73 @@ +import type { Config } from 'payload' + +import { describe, expect, it } from 'vitest' + +import { payloadGeocodingPlugin } from './plugin.js' + +const BASE_CONFIG: Config = { + collections: [], + db: {} as any, + secret: 'test', +} + +describe('payloadGeocodingPlugin', () => { + it('registers the geocoding search endpoint when enabled', () => { + const plugin = payloadGeocodingPlugin({ + googleMapsApiKey: 'test-key', + }) + const config = plugin(BASE_CONFIG) + + expect(config.endpoints).toBeDefined() + expect(config.endpoints).toHaveLength(1) + expect(config.endpoints![0]).toMatchObject({ + method: 'get', + path: '/geocoding-plugin/search', + }) + }) + + it('does not register endpoint when plugin is disabled', () => { + const plugin = payloadGeocodingPlugin({ + enabled: false, + googleMapsApiKey: 'test-key', + }) + const config = plugin(BASE_CONFIG) + + expect(config.endpoints ?? []).toHaveLength(0) + }) + + it('stores the API key in config.custom', () => { + const plugin = payloadGeocodingPlugin({ + googleMapsApiKey: 'my-api-key', + }) + const config = plugin(BASE_CONFIG) + + expect(config.custom?.payloadGeocodingPlugin?.googleMapsApiKey).toBe('my-api-key') + }) + + it('passes custom access function to the endpoint', () => { + const customAccess = () => true + const plugin = payloadGeocodingPlugin({ + geocodingEndpoint: { access: customAccess }, + googleMapsApiKey: 'test-key', + }) + const config = plugin(BASE_CONFIG) + + expect(config.endpoints).toHaveLength(1) + // The endpoint handler should exist (access is used internally) + expect(config.endpoints![0].handler).toBeDefined() + }) + + it('preserves existing endpoints from incoming config', () => { + const existingEndpoint = { + handler: () => Response.json({ ok: true }), + method: 'get' as const, + path: '/health', + } + const plugin = payloadGeocodingPlugin({ + googleMapsApiKey: 'test-key', + }) + const config = plugin({ ...BASE_CONFIG, endpoints: [existingEndpoint] }) + + expect(config.endpoints).toHaveLength(2) + }) +}) diff --git a/geocoding/src/plugin.ts b/geocoding/src/plugin.ts index cfc93e1f..09cf9b94 100644 --- a/geocoding/src/plugin.ts +++ b/geocoding/src/plugin.ts @@ -2,6 +2,8 @@ import type { Config } from 'payload' import type { GeocodingPluginConfig } from './types/GeoCodingPluginConfig.js' +import { createGeocodingSearchEndpoint } from './endpoints/geocodingSearch.js' + /** * Payload plugin which extends the point field with geocoding functionality. */ @@ -13,6 +15,11 @@ export const payloadGeocodingPlugin = return incomingConfig } + const geocodingEndpoint = createGeocodingSearchEndpoint({ + access: pluginOptions.geocodingEndpoint?.access, + apiKey: pluginOptions.googleMapsApiKey, + }) + // Store API key in config.custom for server component access const config: Config = { ...incomingConfig, @@ -22,6 +29,7 @@ export const payloadGeocodingPlugin = googleMapsApiKey: pluginOptions.googleMapsApiKey, }, }, + endpoints: [...(incomingConfig.endpoints ?? []), geocodingEndpoint], } return config diff --git a/geocoding/src/services/googleGeocoding.test.ts b/geocoding/src/services/googleGeocoding.test.ts new file mode 100644 index 00000000..d5c853b3 --- /dev/null +++ b/geocoding/src/services/googleGeocoding.test.ts @@ -0,0 +1,83 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +import { geocodeAddress } from './googleGeocoding.js' + +const MOCK_API_KEY = 'test-api-key' + +const MOCK_GOOGLE_RESPONSE = { + results: [ + { + address_components: [ + { long_name: 'Alexanderplatz', short_name: 'Alexanderplatz', types: ['point_of_interest'] }, + { long_name: 'Berlin', short_name: 'Berlin', types: ['locality'] }, + ], + formatted_address: 'Alexanderplatz, 10178 Berlin, Germany', + geometry: { + location: { lat: 52.5219, lng: 13.4132 }, + }, + place_id: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + types: ['point_of_interest', 'establishment'], + }, + ], + status: 'OK', +} + +describe('geocodeAddress', () => { + beforeEach(() => { + vi.restoreAllMocks() + }) + + it('returns geocoded results for a valid address', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue( + new Response(JSON.stringify(MOCK_GOOGLE_RESPONSE), { status: 200 }), + ) + + const results = await geocodeAddress('Alexanderplatz, Berlin', MOCK_API_KEY) + + expect(results).toHaveLength(1) + expect(results[0]).toEqual({ + addressComponents: MOCK_GOOGLE_RESPONSE.results[0].address_components, + formattedAddress: 'Alexanderplatz, 10178 Berlin, Germany', + location: { lat: 52.5219, lng: 13.4132 }, + placeId: 'ChIJp1l4uWBRqEcR2SPNRBMhtAI', + types: ['point_of_interest', 'establishment'], + }) + + // Verify the API was called with the correct URL + const fetchCall = vi.mocked(fetch).mock.calls[0][0] as string + expect(fetchCall).toContain('address=Alexanderplatz') + expect(fetchCall).toContain(`key=${MOCK_API_KEY}`) + }) + + it('returns empty array for ZERO_RESULTS', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue( + new Response(JSON.stringify({ results: [], status: 'ZERO_RESULTS' }), { status: 200 }), + ) + + const results = await geocodeAddress('xyznonexistent12345', MOCK_API_KEY) + expect(results).toEqual([]) + }) + + it('throws on API error status', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue( + new Response( + JSON.stringify({ error_message: 'Invalid key', results: [], status: 'REQUEST_DENIED' }), + { status: 200 }, + ), + ) + + await expect(geocodeAddress('Berlin', MOCK_API_KEY)).rejects.toThrow( + 'Google Geocoding API error: REQUEST_DENIED - Invalid key', + ) + }) + + it('throws on HTTP failure', async () => { + vi.spyOn(globalThis, 'fetch').mockResolvedValue( + new Response('Server Error', { status: 500, statusText: 'Internal Server Error' }), + ) + + await expect(geocodeAddress('Berlin', MOCK_API_KEY)).rejects.toThrow( + 'Google Geocoding API request failed: 500 Internal Server Error', + ) + }) +}) diff --git a/geocoding/src/services/googleGeocoding.ts b/geocoding/src/services/googleGeocoding.ts new file mode 100644 index 00000000..8b8a87a7 --- /dev/null +++ b/geocoding/src/services/googleGeocoding.ts @@ -0,0 +1,73 @@ +export type GeocodingResult = { + addressComponents: Array<{ + long_name: string + short_name: string + types: string[] + }> + formattedAddress: string + location: { + lat: number + lng: number + } + placeId: string + types: string[] +} + +type GoogleGeocodingApiResponse = { + error_message?: string + results: Array<{ + address_components: Array<{ + long_name: string + short_name: string + types: string[] + }> + formatted_address: string + geometry: { + location: { + lat: number + lng: number + } + } + place_id: string + types: string[] + }> + status: string +} + +/** + * Server-side geocoding using the Google Geocoding HTTP API. + * This enables agents and API consumers to geocode addresses without the browser-based Places UI. + */ +export async function geocodeAddress(address: string, apiKey: string): Promise { + const url = new URL('https://maps.googleapis.com/maps/api/geocode/json') + url.searchParams.set('address', address) + url.searchParams.set('key', apiKey) + + const response = await fetch(url.toString()) + + if (!response.ok) { + throw new Error( + `Google Geocoding API request failed: ${response.status} ${response.statusText}`, + ) + } + + const data: GoogleGeocodingApiResponse = await response.json() + + if (data.status === 'ZERO_RESULTS') { + return [] + } + + if (data.status !== 'OK') { + throw new Error( + `Google Geocoding API error: ${data.status} - ${data.error_message ?? 'Unknown error'}`, + ) + } + + return data.results.map((result) => ({ + addressComponents: result.address_components, + formattedAddress: result.formatted_address, + location: result.geometry.location, + placeId: result.place_id, + types: result.types, + })) +} diff --git a/geocoding/src/types/GeoCodingPluginConfig.ts b/geocoding/src/types/GeoCodingPluginConfig.ts index f778e8f8..8beb08f1 100644 --- a/geocoding/src/types/GeoCodingPluginConfig.ts +++ b/geocoding/src/types/GeoCodingPluginConfig.ts @@ -1,7 +1,21 @@ +import type { PayloadRequest } from 'payload' + +/** Access function for the geocoding endpoint. */ +export type GeocodingEndpointAccess = (args: { req: PayloadRequest }) => boolean | Promise + /** Configuration options for the geocoding plugin. */ export type GeocodingPluginConfig = { /** Whether the geocoding plugin is enabled. */ enabled?: boolean + /** Configuration for the server-side geocoding search endpoint (GET /api/geocoding-plugin/search). */ + geocodingEndpoint?: { + /** + * Custom access function to control who can use the geocoding endpoint. + * Receives the Payload request object. Return true to allow access. + * Defaults to requiring an authenticated user (i.e. `req.user` must be truthy). + */ + access?: GeocodingEndpointAccess + } /** Google Maps API key for geocoding functionality. */ googleMapsApiKey: string }