diff --git a/packages/pglite-solid/.gitignore b/packages/pglite-solid/.gitignore new file mode 100644 index 000000000..db4c6d9b6 --- /dev/null +++ b/packages/pglite-solid/.gitignore @@ -0,0 +1,2 @@ +dist +node_modules \ No newline at end of file diff --git a/packages/pglite-solid/CHANGELOG.md b/packages/pglite-solid/CHANGELOG.md new file mode 100644 index 000000000..0b6b1c820 --- /dev/null +++ b/packages/pglite-solid/CHANGELOG.md @@ -0,0 +1,6 @@ +# @electric-sql/pglite-solid + +## 0.2.23 + +### Patch Changes +- Add support for solidjs diff --git a/packages/pglite-solid/README.md b/packages/pglite-solid/README.md new file mode 100644 index 000000000..4ee3adc44 --- /dev/null +++ b/packages/pglite-solid/README.md @@ -0,0 +1,17 @@ +# PGlite Solidjs Hooks + +This package implements Solid hooks for [PGLite](https://pglite.dev/) on top of the [live query plugin](https://pglite.dev/docs/live-queries). Full documentation is available at [pglite.dev/docs/framework-hooks](https://pglite.dev/docs/framework-hooks#solid). + +To install: + +```sh +npm install @electric-sql/pglite-solid +``` + +The hooks this package provides are: + +- [PGliteProvider](https://pglite.dev/docs/framework-hooks/solid#pgliteprovider): A Provider component to pass a PGlite instance to all child components for use with the other hooks. +- [usePGlite](https://pglite.dev/docs/framework-hooks/solid#usepglite): Retrieve the provided PGlite instance. +- [makePGliteProvider](https://pglite.dev/docs/framework-hooks/solid#makepgliteprovider): Create typed instances of `PGliteProvider` and `usePGlite`. +- [useLiveQuery](https://pglite.dev/docs/framework-hooks/solid#uselivequery): Reactively re-render your component whenever the results of a live query change +- [useLiveIncrementalQuery](https://pglite.dev/docs/framework-hooks/solid#useliveincrementalquery): Reactively re-render your component whenever the results of a live query change by offloading the diff to PGlite diff --git a/packages/pglite-solid/eslint.config.js b/packages/pglite-solid/eslint.config.js new file mode 100644 index 000000000..fd79c0e7f --- /dev/null +++ b/packages/pglite-solid/eslint.config.js @@ -0,0 +1,23 @@ +import rootConfig from '../../eslint.config.js' +import solid from 'eslint-plugin-solid' +import * as tsParser from '@typescript-eslint/parser' + +export default [ + ...rootConfig, + { + files: ['**/*.{ts,tsx}'], + ...solid, + languageOptions: { + parser: tsParser, + parserOptions: { + project: 'tsconfig.json', + }, + }, + }, + { + files: ['**/test/**'], + rules: { + '@typescript-eslint/no-unnecessary-condition': 'off', + }, + }, +] diff --git a/packages/pglite-solid/package.json b/packages/pglite-solid/package.json new file mode 100644 index 000000000..731eb4121 --- /dev/null +++ b/packages/pglite-solid/package.json @@ -0,0 +1,71 @@ +{ + "name": "@electric-sql/pglite-solid", + "version": "0.2.23", + "description": "Hooks for using PGlite", + "type": "module", + "private": false, + "publishConfig": { + "access": "public" + }, + "keywords": [ + "postgres", + "sql", + "database", + "wasm", + "client", + "pglite", + "solid" + ], + "author": "Electric DB Limited", + "homepage": "https://pglite.dev", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/electric-sql/pglite.git", + "directory": "packages/pglite-solid" + }, + "scripts": { + "build": "tsup", + "check:exports": "attw . --pack --profile node16", + "test": "vitest", + "lint": "eslint ./src ./test", + "format": "prettier --write ./src ./test", + "typecheck": "tsc", + "stylecheck": "eslint ./src ./test && prettier --check ./src ./test", + "prepublishOnly": "pnpm check:exports" + }, + "types": "dist/index.d.ts", + "main": "dist/index.cjs", + "module": "dist/index.js", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } + } + }, + "files": [ + "dist" + ], + "devDependencies": { + "@arethetypeswrong/cli": "^0.18.1", + "@electric-sql/pglite": "workspace:*", + "@solidjs/testing-library": "^0.8.10", + "@testing-library/dom": "^10.4.0", + "eslint-plugin-solid": "^0.14.5", + "globals": "^15.11.0", + "jsdom": "^24.1.3", + "vite-plugin-solid": "^2.11.7", + "solid-js": "^1.9.7", + "vitest": "^2.1.2" + }, + "peerDependencies": { + "@electric-sql/pglite": "workspace:0.3.5", + "solid-js": "^1.8.0 || ^1.9.0" + } +} \ No newline at end of file diff --git a/packages/pglite-solid/src/hooks.ts b/packages/pglite-solid/src/hooks.ts new file mode 100644 index 000000000..d7e757383 --- /dev/null +++ b/packages/pglite-solid/src/hooks.ts @@ -0,0 +1,178 @@ +import type { LiveQuery, LiveQueryResults } from '@electric-sql/pglite/live' +import { query as buildQuery } from '@electric-sql/pglite/template' +import { usePGlite } from './provider' +import { + Accessor, + createComputed, + createMemo, + createResource, + createSignal, + onCleanup, +} from 'solid-js' + +type Params = unknown[] | undefined | null +type Pagination = { limit: number; offset: number } + +function useLiveQueryImpl(opts: { + query: Accessor | Promise>> + params?: Accessor + key?: Accessor + pagination?: Accessor +}): Accessor, 'affectedRows'> | undefined> { + const db = usePGlite() + const liveQuery = createMemo( + () => { + const originalQuery = opts.query() + if ( + !(typeof originalQuery === 'string') && + !(originalQuery instanceof Promise) + ) { + return originalQuery + } + + return undefined + }, + undefined, + { name: 'PGLiteLiveQueryMemo' }, + ) + + const [results, setResults] = createSignal | undefined>( + liveQuery()?.initialResults, + { name: 'PGLiteResultsSignal' }, + ) + + createComputed( + () => { + const query = liveQuery() + if (query) { + setResults(query.initialResults) + } + }, + undefined, + { name: 'PGLiteLiveQueryInitialSyncComputed' }, + ) + + const initialPagination = opts.pagination?.() + const [queryRan] = createResource( + () => ({ query: opts.query(), key: opts.key?.(), params: opts.params?.() }), + async (opts) => { + const query = opts.query + if (typeof query === 'string') { + const key = opts.key + const ret = + key != undefined + ? db.live.incrementalQuery({ + query, + callback: setResults, + params: opts.params, + key, + }) + : db.live.query({ + query, + callback: setResults, + params: opts.params, + ...initialPagination, + }) + + const res = await ret + return res + } else if (query instanceof Promise) { + const res = await query + setResults(res.initialResults) + res.subscribe(setResults) + + return res + } else if (liveQuery()) { + setResults(liveQuery()!.initialResults) + liveQuery()!.subscribe(setResults) + + return liveQuery() + } else { + throw new Error('Should never happen') + } + }, + { name: 'PGLiteLiveQueryResource' }, + ) + + createComputed((oldPagination: Pagination | undefined) => { + const pagination = opts.pagination?.() + + if ( + pagination && + (pagination.limit !== oldPagination?.limit || + pagination.offset !== oldPagination?.offset) + ) { + queryRan()?.refresh(pagination) + return pagination + } + + return undefined + }, opts.pagination?.()) + + onCleanup(() => { + queryRan()?.unsubscribe() + }) + + const aggregatedResult = createMemo( + () => { + queryRan() + const res = results() + if (res) { + return { + rows: res.rows, + fields: res.fields, + totalCount: res.totalCount, + offset: res.offset, + limit: res.limit, + } + } + + return res + }, + undefined, + { name: 'PGLiteLiveQueryResultMemo' }, + ) + + return aggregatedResult +} + +export function useLiveQuery(opts: { + query: Accessor + params?: Accessor + pagination?: Accessor +}): Accessor | undefined> + +export function useLiveQuery(opts: { + query: Accessor> +}): Accessor> + +export function useLiveQuery(opts: { + query: Accessor>> +}): Accessor | undefined> + +export function useLiveQuery(opts: { + query: Accessor | Promise>> + params?: Accessor + pagination?: Accessor +}): Accessor | undefined> { + return useLiveQueryImpl(opts) +} + +useLiveQuery.sql = function ( + strings: TemplateStringsArray, + ...values: any[] +): Accessor | undefined> { + const { query, params } = buildQuery(strings, ...values) + return useLiveQueryImpl({ + params: () => params.map((p) => (typeof p === 'function' ? p() : p)), + query: () => query, + }) +} + +export function useLiveIncrementalQuery(opts: { + query: Accessor | Promise>> + params: Accessor + key?: Accessor +}): Accessor | undefined> { + return useLiveQueryImpl(opts) +} diff --git a/packages/pglite-solid/src/index.ts b/packages/pglite-solid/src/index.ts new file mode 100644 index 000000000..b3355d6b3 --- /dev/null +++ b/packages/pglite-solid/src/index.ts @@ -0,0 +1,2 @@ +export * from './provider' +export * from './hooks' diff --git a/packages/pglite-solid/src/provider.tsx b/packages/pglite-solid/src/provider.tsx new file mode 100644 index 000000000..a6d054ce3 --- /dev/null +++ b/packages/pglite-solid/src/provider.tsx @@ -0,0 +1,42 @@ +import { PGliteWithLive } from '@electric-sql/pglite/live' +import { createContext, ParentProps, useContext } from 'solid-js' +import { JSX } from 'solid-js/jsx-runtime' + +interface Props extends ParentProps<{ db?: T }> {} + +type PGliteProvider = (props: Props) => JSX.Element +type UsePGlite = (db?: T) => T + +interface PGliteProviderSet { + PGliteProvider: PGliteProvider + usePGlite: UsePGlite +} + +/** + * Create a typed set of {@link PGliteProvider} and {@link usePGlite}. + */ +function makePGliteProvider(): PGliteProviderSet { + const ctx = createContext(undefined) + return { + usePGlite: ((db?: T) => { + const dbProvided = useContext(ctx) + + // allow providing a db explicitly + if (db !== undefined) return db + + if (!dbProvided) + throw new Error( + 'No PGlite instance found, use PGliteProvider to provide one', + ) + + return dbProvided + }) as UsePGlite, + PGliteProvider: (props: Props) => { + return {props.children} + }, + } +} + +const { PGliteProvider, usePGlite } = makePGliteProvider() + +export { makePGliteProvider, PGliteProvider, usePGlite } diff --git a/packages/pglite-solid/test-setup.ts b/packages/pglite-solid/test-setup.ts new file mode 100644 index 000000000..97af96040 --- /dev/null +++ b/packages/pglite-solid/test-setup.ts @@ -0,0 +1,5 @@ +import { afterEach } from 'vitest' +import { cleanup } from '@solidjs/testing-library' + +// https://testing-library.com/docs/solid-testing-library/api#cleanup +afterEach(() => cleanup()) diff --git a/packages/pglite-solid/test/hooks.test.tsx b/packages/pglite-solid/test/hooks.test.tsx new file mode 100644 index 000000000..e90e19bd9 --- /dev/null +++ b/packages/pglite-solid/test/hooks.test.tsx @@ -0,0 +1,500 @@ +import { describe, it, expect, beforeEach } from 'vitest' +import { renderHook } from '@solidjs/testing-library' +import { waitFor } from '@testing-library/dom' +import { PGlite } from '@electric-sql/pglite' +import { live, PGliteWithLive } from '@electric-sql/pglite/live' +import { PGliteProvider, useLiveQuery, useLiveIncrementalQuery } from '../src' +import { JSX } from 'solid-js/jsx-runtime' +import { Accessor, createRoot, createSignal } from 'solid-js' + +describe('hooks', () => { + testLiveQuery('useLiveQuery') + + testLiveQuery('useLiveIncrementalQuery') + + describe('useLiveQuery with limit and offset', () => { + let db: PGliteWithLive + let wrapper: (props: { children: JSX.Element }) => JSX.Element + + beforeEach(async () => { + db = await PGlite.create({ + extensions: { + live, + }, + }) + wrapper = (props) => { + return {props.children} + } + + await db.exec(` + CREATE TABLE IF NOT EXISTS test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`TRUNCATE test;`) + }) + + it('query with limit and offset', async () => { + db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const [opts, setOpts] = createSignal({ limit: 1, offset: 0 }) + const { result } = renderHook( + (props: { pagination: Accessor<{ limit: number; offset: number }> }) => + useLiveQuery({ + query: () => `SELECT * FROM test`, + pagination: props.pagination, + }), + { wrapper, initialProps: [{ pagination: opts }] }, + ) + + waitFor(() => expect(result()?.rows).toEqual([{ id: 1, name: 'test1' }])) + + setOpts({ limit: 1, offset: 1 }) + waitFor(() => expect(result()?.rows).toEqual([{ id: 2, name: 'test2' }])) + + setOpts({ limit: 2, offset: 0 }) + waitFor(() => + expect(result()?.rows).toEqual([ + { id: 1, name: 'test1' }, + { id: 2, name: 'test2' }, + ]), + ) + }) + }) + + describe('useLiveQuery.sql', () => { + let db: PGliteWithLive + let wrapper: (props: { children: JSX.Element }) => JSX.Element + + beforeEach(async () => { + db = await PGlite.create({ + extensions: { + live, + }, + }) + wrapper = (props) => { + return {props.children} + } + + await db.exec(` + CREATE TABLE IF NOT EXISTS test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`TRUNCATE test;`) + }) + + it('updates when query parameter changes', async () => { + await db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const [params, setParams] = createSignal(['test1']) + const { result } = renderHook( + (props: { params: Accessor> }) => + useLiveQuery.sql`SELECT * FROM test WHERE name = ${() => props.params()[0]};`, + { wrapper, initialProps: [{ params: params }] }, + ) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 1, + name: 'test1', + }, + ]), + ) + + setParams(['test2']) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 2, + name: 'test2', + }, + ]), + ) + }) + }) +}) + +function testLiveQuery(queryHook: 'useLiveQuery' | 'useLiveIncrementalQuery') { + describe(queryHook, () => { + let db: PGliteWithLive + let wrapper: (props: { children: JSX.Element }) => JSX.Element + const hookFn = + queryHook === 'useLiveQuery' ? useLiveQuery : useLiveIncrementalQuery + const incKey = 'id' + beforeEach(async () => { + db = await PGlite.create({ + extensions: { + live, + }, + }) + wrapper = (props) => { + return {props.children} + } + + await db.exec(` + CREATE TABLE IF NOT EXISTS test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`TRUNCATE test;`) + }) + + it('can receive initial results', async () => { + await db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const { result } = renderHook( + () => + hookFn({ + query: () => `SELECT * FROM test`, + params: () => [], + key: () => incKey, + }), + { wrapper }, + ) + + await waitFor(() => expect(result()).not.toBe(undefined)) + expect(result()).toEqual({ + rows: [ + { + id: 1, + name: 'test1', + }, + { + id: 2, + name: 'test2', + }, + ], + fields: [ + { + name: 'id', + dataTypeID: 23, + }, + { + name: 'name', + dataTypeID: 25, + }, + ], + }) + }) + + it('can receive changes', async () => { + await db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const { result } = renderHook( + () => + hookFn({ + query: () => `SELECT * FROM test`, + params: () => [], + key: () => incKey, + }), + { wrapper }, + ) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 1, + name: 'test1', + }, + { + id: 2, + name: 'test2', + }, + ]), + ) + + // detect new inserts + db.exec(`INSERT INTO test (name) VALUES ('test3');`) + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 1, + name: 'test1', + }, + { + id: 2, + name: 'test2', + }, + { + id: 3, + name: 'test3', + }, + ]), + ) + + // detect deletes + db.exec(`DELETE FROM test WHERE name = 'test1';`) + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 2, + name: 'test2', + }, + { + id: 3, + name: 'test3', + }, + ]), + ) + + // detect updates + db.exec(`UPDATE test SET name = 'foobar' WHERE name = 'test2';`) + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 3, + name: 'test3', + }, + { + id: 2, + name: 'foobar', + }, + ]), + ) + + // // detect truncates + // db.exec(`TRUNCATE test;`) + // await waitFor(() => expect(result.current?.rows).toHaveLength(0)) + }) + + it('updates when query changes', () => + createRoot(async () => { + await db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const [query, setQuery] = createSignal(`SELECT * FROM test`) + const { result } = renderHook( + (props: { query: Accessor }) => { + return hookFn({ + query: () => props.query(), + params: () => [], + key: () => incKey, + }) + }, + { wrapper, initialProps: [{ query }] }, + ) + + await waitFor(() => expect(result()?.rows).toHaveLength(2)) + + setQuery(`SELECT * FROM test WHERE name = 'test1'`) + + await waitFor(() => expect(result()?.rows).toHaveLength(1)) + })) + + it('updates when query parameters change', async () => { + await db.exec(`INSERT INTO test (name) VALUES ('test1'),('test2');`) + + const [paramsArr, setParamsArr] = createSignal(['foo']) + + const { result } = renderHook( + (props: { params: Accessor> }) => + hookFn({ + query: () => `SELECT * FROM test WHERE name = $1;`, + params: () => [props.params()[props.params().length - 1]], + key: () => incKey, + }), + { wrapper, initialProps: [{ params: paramsArr }] }, + ) + + await waitFor(() => expect(result()?.rows).toEqual([])) + + // update when query parameter changes + setParamsArr(['test1']) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 1, + name: 'test1', + }, + ]), + ) + + // update when number of query parameters changes + setParamsArr(['test1', 'test2']) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 2, + name: 'test2', + }, + ]), + ) + }) + + if (queryHook !== 'useLiveQuery') { + return + } + + it('can take a live query return value directly', async () => { + await db.exec(` + CREATE TABLE live_test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`INSERT INTO live_test (name) VALUES ('initial');`) + + const liveQuery = await db.live.query( + `SELECT * FROM live_test ORDER BY id DESC LIMIT 1;`, + ) + const { result } = renderHook( + () => useLiveQuery({ query: () => liveQuery }), + { wrapper }, + ) + + await waitFor(() => expect(result()?.rows).toHaveLength(1)) + expect(result()?.rows[0]).toEqual({ id: 1, name: 'initial' }) + + // Trigger an update + await db.exec(`INSERT INTO live_test (name) VALUES ('updated');`) + await waitFor(() => expect(result()?.rows[0].name).toBe('updated')) + expect(result()?.rows[0]).toEqual({ id: 2, name: 'updated' }) + }) + + it('can take a live query returned promise directly', async () => { + await db.exec(` + CREATE TABLE live_test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`INSERT INTO live_test (name) VALUES ('initial');`) + + const liveQueryPromise = db.live.query( + `SELECT * FROM live_test ORDER BY id DESC LIMIT 1;`, + ) + const { result } = renderHook( + () => useLiveQuery({ query: () => liveQueryPromise }), + { + wrapper, + }, + ) + + expect(result()).toBe(undefined) + + await waitFor(() => expect(result()).not.toBe(undefined)) + + await waitFor(() => expect(result()?.rows).toHaveLength(1)) + expect(result()?.rows[0]).toEqual({ id: 1, name: 'initial' }) + + // Trigger an update + await db.exec(`INSERT INTO live_test (name) VALUES ('updated');`) + await waitFor(() => expect(result()?.rows[0].name).toBe('updated')) + expect(result()?.rows[0]).toEqual({ id: 2, name: 'updated' }) + }) + + it('can take a live incremental query return value directly', async () => { + await db.exec(` + CREATE TABLE live_test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`INSERT INTO live_test (name) VALUES ('initial');`) + + const liveQuery = await db.live.incrementalQuery( + `SELECT * FROM live_test ORDER BY id DESC LIMIT 1;`, + [], + incKey, + ) + const { result } = renderHook( + () => useLiveQuery({ query: () => liveQuery }), + { wrapper }, + ) + + await waitFor(() => expect(result()?.rows).toHaveLength(1)) + expect(result()?.rows[0]).toEqual({ id: 1, name: 'initial' }) + + // Trigger an update + await db.exec(`INSERT INTO live_test (name) VALUES ('updated');`) + await waitFor(() => expect(result()?.rows[0].name).toBe('updated')) + expect(result()?.rows[0]).toEqual({ id: 2, name: 'updated' }) + }) + + it('can take a live incremental query returned promise directly', async () => { + await db.exec(` + CREATE TABLE live_test ( + id SERIAL PRIMARY KEY, + name TEXT + ); + `) + await db.exec(`INSERT INTO live_test (name) VALUES ('initial');`) + + const liveQueryPromise = db.live.incrementalQuery( + `SELECT * FROM live_test ORDER BY id DESC LIMIT 1;`, + [], + incKey, + ) + const { result } = renderHook( + () => useLiveQuery({ query: () => liveQueryPromise }), + { + wrapper, + }, + ) + + expect(result()).toBe(undefined) + + await waitFor(() => expect(result()).not.toBe(undefined)) + + await waitFor(() => expect(result()?.rows).toHaveLength(1)) + expect(result()?.rows[0]).toEqual({ id: 1, name: 'initial' }) + + // Trigger an update + await db.exec(`INSERT INTO live_test (name) VALUES ('updated');`) + await waitFor(() => expect(result()?.rows[0].name).toBe('updated')) + }) + + it('works with pattern matching', async () => { + await db.exec(` + CREATE TABLE pattern_matching ( + id SERIAL PRIMARY KEY, + statement VARCHAR(100) + ); + `) + + await db.exec( + `INSERT INTO pattern_matching (statement) VALUES ('PGlite 4 ever.'),('To not be or not to be.');`, + ) + + const liveQueryPromise = db.live.incrementalQuery( + `SELECT * FROM pattern_matching WHERE statement ILIKE '%pglite%' ORDER BY id DESC LIMIT 1;`, + [], + incKey, + ) + + const { result } = renderHook( + () => useLiveQuery({ query: () => liveQueryPromise }), + { + wrapper, + }, + ) + + await waitFor(() => + expect(result()?.rows).toEqual([ + { + id: 1, + statement: 'PGlite 4 ever.', + }, + ]), + ) + + await db.exec( + `INSERT INTO pattern_matching (statement) VALUES ('should not trigger!');`, + ) + // Trigger an update + await db.exec( + `INSERT INTO pattern_matching (statement) VALUES ('ElectricSQL + pglite = <3');`, + ) + await waitFor(() => + expect(result()?.rows[0].statement).toBe('ElectricSQL + pglite = <3'), + ) + }) + }) +} diff --git a/packages/pglite-solid/test/provider.test-d.tsx b/packages/pglite-solid/test/provider.test-d.tsx new file mode 100644 index 000000000..5f56cd87d --- /dev/null +++ b/packages/pglite-solid/test/provider.test-d.tsx @@ -0,0 +1,38 @@ +import { describe, it, expectTypeOf } from 'vitest' +import { PGlite, PGliteInterfaceExtensions } from '@electric-sql/pglite' +import { live } from '@electric-sql/pglite/live' +import { vector } from '@electric-sql/pglite/vector' +import { makePGliteProvider } from '../src/provider.js' + +describe('provider', () => { + it('provider type respected ', async () => { + const dbLiveVector = await PGlite.create({ + extensions: { + live, + vector, + }, + }) + const dbLive = await PGlite.create({ + extensions: { + live, + }, + }) + + const { PGliteProvider, usePGlite } = makePGliteProvider< + PGlite & + PGliteInterfaceExtensions<{ + live: typeof live + vector: typeof vector + }> + >() + + // @ts-expect-error cannot pass db with just live extension + ;() => + ;() => + + // @ts-expect-error cannot pass wrong type db to typed hook + usePGlite(dbLive) + + expectTypeOf(usePGlite()).toEqualTypeOf() + }) +}) diff --git a/packages/pglite-solid/test/provider.test.tsx b/packages/pglite-solid/test/provider.test.tsx new file mode 100644 index 000000000..7bd3beadd --- /dev/null +++ b/packages/pglite-solid/test/provider.test.tsx @@ -0,0 +1,43 @@ +import { describe, it, expect } from 'vitest' +import { renderHook } from '@solidjs/testing-library' +import { waitFor } from '@testing-library/dom' +import { PGlite } from '@electric-sql/pglite' +import { live, PGliteWithLive } from '@electric-sql/pglite/live' +import { makePGliteProvider, PGliteProvider, usePGlite } from '../src' +import { JSX } from 'solid-js/jsx-runtime' + +describe('provider', () => { + it('can receive PGlite', async () => { + const db = await PGlite.create({ + extensions: { + live, + }, + }) + const wrapper = (props: { children: JSX.Element }) => { + return {props.children} + } + + const { result } = renderHook(() => usePGlite(), { wrapper }) + + await waitFor(() => expect(result).toBe(db)) + }) + + it('can receive PGlite with typed provider', async () => { + const db = await PGlite.create({ + extensions: { + live, + }, + }) + + const { PGliteProvider: PGliteProviderTyped, usePGlite: usePGliteTyped } = + makePGliteProvider() + + const wrapper = (props: { children: JSX.Element }) => { + return {props.children} + } + + const { result } = renderHook(() => usePGliteTyped(), { wrapper }) + + await waitFor(() => expect(result).toBe(db)) + }) +}) diff --git a/packages/pglite-solid/tsconfig.json b/packages/pglite-solid/tsconfig.json new file mode 100644 index 000000000..95da9f0b1 --- /dev/null +++ b/packages/pglite-solid/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "solid-js" + }, + "include": [ + "src", + "test", + "eslint.config.js", + "test-setup.ts", + "tsup.config.js", + "vitest.config.ts" + ] +} \ No newline at end of file diff --git a/packages/pglite-solid/tsup.config.ts b/packages/pglite-solid/tsup.config.ts new file mode 100644 index 000000000..968f299ad --- /dev/null +++ b/packages/pglite-solid/tsup.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'tsup' + +const minify = process.env.DEBUG === 'true' ? false : true + +export default defineConfig([ + { + entry: ['src/index.ts'], + format: ['cjs', 'esm'], + outDir: 'dist', + dts: true, + minify: minify, + sourcemap: true, + clean: true, + }, +]) diff --git a/packages/pglite-solid/vitest.config.ts b/packages/pglite-solid/vitest.config.ts new file mode 100644 index 000000000..9dbfa74d7 --- /dev/null +++ b/packages/pglite-solid/vitest.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vitest/config' +import solid from 'vite-plugin-solid' + +export default defineConfig({ + plugins: [solid()], + test: { + name: 'pglite-solid', + dir: './test', + watch: false, + environment: 'jsdom', + setupFiles: ['test-setup.ts'], + typecheck: { enabled: true }, + restoreMocks: true, + testTimeout: 15000, + testTransformMode: { + ssr: ['**/*'], + }, + }, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3797f2894..a9a3558c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -356,6 +356,39 @@ importers: specifier: ^1.3.1 version: 1.6.0(@types/node@20.16.11)(jsdom@24.1.3)(terser@5.34.1) + packages/pglite-solid: + devDependencies: + '@arethetypeswrong/cli': + specifier: ^0.18.1 + version: 0.18.1 + '@electric-sql/pglite': + specifier: workspace:* + version: link:../pglite + '@solidjs/testing-library': + specifier: ^0.8.10 + version: 0.8.10(solid-js@1.9.7) + '@testing-library/dom': + specifier: ^10.4.0 + version: 10.4.0 + eslint-plugin-solid: + specifier: ^0.14.5 + version: 0.14.5(eslint@8.57.1)(typescript@5.6.3) + globals: + specifier: ^15.11.0 + version: 15.11.0 + jsdom: + specifier: ^24.1.3 + version: 24.1.3 + solid-js: + specifier: ^1.9.7 + version: 1.9.7 + vite-plugin-solid: + specifier: ^2.11.7 + version: 2.11.7(solid-js@1.9.7)(vite@5.4.8(@types/node@20.16.11)(terser@5.34.1)) + vitest: + specifier: ^2.1.2 + version: 2.1.2(@types/node@20.16.11)(jsdom@24.1.3)(terser@5.34.1) + packages/pglite-sync: dependencies: '@electric-sql/client': @@ -574,6 +607,10 @@ packages: resolution: {integrity: sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.18.6': + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.25.7': resolution: {integrity: sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==} engines: {node: '>=6.9.0'} @@ -592,6 +629,10 @@ packages: resolution: {integrity: sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==} engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + '@babel/helper-replace-supers@7.25.7': resolution: {integrity: sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==} engines: {node: '>=6.9.0'} @@ -638,6 +679,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.25.7': resolution: {integrity: sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==} engines: {node: '>=6.9.0'} @@ -1447,6 +1494,16 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} + '@solidjs/testing-library@0.8.10': + resolution: {integrity: sha512-qdeuIerwyq7oQTIrrKvV0aL9aFeuwTd86VYD3afdq5HYEwoox1OBTJy4y8A3TFZr8oAR0nujYgCzY/8wgHGfeQ==} + engines: {node: '>= 14'} + peerDependencies: + '@solidjs/router': '>=0.9.0' + solid-js: '>=1.0.0' + peerDependenciesMeta: + '@solidjs/router': + optional: true + '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} @@ -1598,10 +1655,6 @@ packages: resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.8.1': - resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@7.18.0': resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1619,15 +1672,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/type-utils@8.8.1': - resolution: {integrity: sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/types@7.18.0': resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1636,10 +1680,6 @@ packages: resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.8.1': - resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@7.18.0': resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1655,15 +1695,6 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/typescript-estree@8.8.1': - resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/utils@7.18.0': resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1677,12 +1708,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.8.1': - resolution: {integrity: sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - '@typescript-eslint/visitor-keys@7.18.0': resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1691,10 +1716,6 @@ packages: resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.8.1': - resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@uiw/codemirror-extensions-basic-setup@4.23.5': resolution: {integrity: sha512-eTMfT8TejVN/D5vvuz9Lab+MIoRYdtqa2ftZZmU3JpcDIXf9KaExPo+G2Rl9HqySzaasgGXOOG164MAnj3MSIw==} peerDependencies: @@ -2047,6 +2068,16 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + babel-plugin-jsx-dom-expressions@0.39.8: + resolution: {integrity: sha512-/MVOIIjonylDXnrWmG23ZX82m9mtKATsVHB7zYlPfDR9Vdd/NBE48if+wv27bSkBtyO7EPMUlcUc4J63QwuACQ==} + peerDependencies: + '@babel/core': ^7.20.12 + + babel-preset-solid@1.9.6: + resolution: {integrity: sha512-HXTK9f93QxoH8dYn1M2mJdOlWgMsR88Lg/ul6QCZGkNTktjTE5HAf93YxQumHoCudLEtZrU1cFCMFOVho6GqFg==} + peerDependencies: + '@babel/core': ^7.0.0 + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -2109,7 +2140,6 @@ packages: bun@1.1.30: resolution: {integrity: sha512-ysRL1pq10Xba0jqVLPrKU3YIv0ohfp3cTajCPtpjCyppbn3lfiAVNpGoHfyaxS17OlPmWmR67UZRPw/EueQuug==} - cpu: [arm64, x64] os: [darwin, linux, win32] hasBin: true @@ -2550,6 +2580,13 @@ packages: typescript: optional: true + eslint-plugin-solid@0.14.5: + resolution: {integrity: sha512-nfuYK09ah5aJG/oEN6P1qziy1zLgW4PDWe75VNPi4CEFYk1x2AEqwFeQfEPR7gNn0F2jOeqKhx2E+5oNCOBYWQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + typescript: '>=4.8.4' + eslint-plugin-vue@9.29.0: resolution: {integrity: sha512-hamyjrBhNH6Li6R1h1VF9KHfshJlKgKEg3ARbGTn72CMNDSMhWbgC7NdkRDEh25AFW+4SDATzyNM+3gWuZii8g==} engines: {node: ^14.17.0 || >=16.0.0} @@ -2875,6 +2912,13 @@ packages: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} + html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -2943,6 +2987,9 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + inline-style-parser@0.2.4: + resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -2990,6 +3037,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-html@2.0.0: + resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} + engines: {node: '>=8'} + is-immutable-type@5.0.0: resolution: {integrity: sha512-mcvHasqbRBWJznuPqqHRKiJgYAz60sZ0mvO3bN70JbkuK7ksfmgc489aKZYxMEjIbRvyOseaTjaRZLRF/xFeRA==} peerDependencies: @@ -3136,9 +3187,15 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + kebab-case@1.0.2: + resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + known-css-properties@0.30.0: + resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} + kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} @@ -3232,6 +3289,10 @@ packages: mdast-util-to-hast@13.2.0: resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3888,6 +3949,16 @@ packages: engines: {node: '>=10'} hasBin: true + seroval-plugins@1.3.2: + resolution: {integrity: sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.3.2: + resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} + engines: {node: '>=10'} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -3950,6 +4021,14 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + solid-js@1.9.7: + resolution: {integrity: sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==} + + solid-refresh@0.6.3: + resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} + peerDependencies: + solid-js: ^1.3 + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -4050,6 +4129,9 @@ packages: style-mod@4.1.2: resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} + style-to-object@1.0.9: + resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -4322,6 +4404,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + validate-html-nesting@1.2.3: + resolution: {integrity: sha512-kdkWdCl6eCeLlRShJKbjVOU2kFKxMF8Ghu50n+crEoyx+VKm3FxAxF9z4DCy6+bbTOqNW0+jcIYRnjoIRzigRw==} + validate-npm-package-name@5.0.1: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -4357,6 +4442,16 @@ packages: peerDependencies: vite: '*' + vite-plugin-solid@2.11.7: + resolution: {integrity: sha512-5TgK1RnE449g0Ryxb9BXqem89RSy7fE8XGVCo+Gw84IHgPuPVP7nYNP6WBVAaY/0xw+OqfdQee+kusL0y3XYNg==} + peerDependencies: + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^1.7.2 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + '@testing-library/jest-dom': + optional: true + vite@5.4.8: resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} engines: {node: ^18.0.0 || >=20.0.0} @@ -4388,6 +4483,14 @@ packages: terser: optional: true + vitefu@1.1.1: + resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 + peerDependenciesMeta: + vite: + optional: true + vitepress@1.4.0: resolution: {integrity: sha512-JXCv4EsKTDyAFb6C/UjZr7nsGAzZ6mafVk2rx7rG5o8N+B/4QstIk+iEOe/9dKoU6V624UIC6g1pZ+K63rxhlw==} hasBin: true @@ -4842,6 +4945,10 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-imports@7.18.6': + dependencies: + '@babel/types': 7.25.8 + '@babel/helper-module-imports@7.25.7': dependencies: '@babel/traverse': 7.25.7 @@ -4865,6 +4972,8 @@ snapshots: '@babel/helper-plugin-utils@7.25.7': {} + '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-replace-supers@7.25.7(@babel/core@7.25.8)': dependencies: '@babel/core': 7.25.8 @@ -4918,6 +5027,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-react-jsx-self@7.25.7(@babel/core@7.25.8)': dependencies: '@babel/core': 7.25.8 @@ -5377,9 +5491,9 @@ snapshots: dependencies: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.6.3) - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.6.3) + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) birecord: 0.1.1 string-ts: 2.2.0 ts-pattern: 5.4.0 @@ -5396,10 +5510,10 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) birecord: 0.1.1 short-unique-id: 5.2.0 ts-pattern: 5.4.0 @@ -5413,10 +5527,10 @@ snapshots: '@eslint-react/shared': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-plugin-react-debug: 1.14.3(eslint@8.57.1)(typescript@5.6.3) eslint-plugin-react-dom: 1.14.3(eslint@8.57.1)(typescript@5.6.3) @@ -5435,9 +5549,9 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) ts-pattern: 5.4.0 transitivePeerDependencies: - eslint @@ -5447,7 +5561,7 @@ snapshots: '@eslint-react/shared@1.14.3(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-react/tools': 1.14.3 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) picomatch: 4.0.2 transitivePeerDependencies: - eslint @@ -5459,8 +5573,8 @@ snapshots: '@eslint-react/types@1.14.3(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-react/tools': 1.14.3 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) transitivePeerDependencies: - eslint - supports-color @@ -5471,9 +5585,9 @@ snapshots: '@eslint-react/ast': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) ts-pattern: 5.4.0 transitivePeerDependencies: - eslint @@ -5790,6 +5904,11 @@ snapshots: '@sindresorhus/is@4.6.0': {} + '@solidjs/testing-library@0.8.10(solid-js@1.9.7)': + dependencies: + '@testing-library/dom': 10.4.0 + solid-js: 1.9.7 + '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.25.7 @@ -5989,11 +6108,6 @@ snapshots: '@typescript-eslint/types': 8.24.1 '@typescript-eslint/visitor-keys': 8.24.1 - '@typescript-eslint/scope-manager@8.8.1': - dependencies: - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/visitor-keys': 8.8.1 - '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.3) @@ -6017,24 +6131,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.8.1(eslint@8.57.1)(typescript@5.6.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.6.3) - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - debug: 4.3.7 - ts-api-utils: 1.3.0(typescript@5.6.3) - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - eslint - - supports-color - '@typescript-eslint/types@7.18.0': {} '@typescript-eslint/types@8.24.1': {} - '@typescript-eslint/types@8.8.1': {} - '@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 7.18.0 @@ -6064,21 +6164,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.8.1(typescript@5.6.3)': - dependencies: - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/visitor-keys': 8.8.1 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.6.3) - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/utils@7.18.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -6101,17 +6186,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.8.1(eslint@8.57.1)(typescript@5.6.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.6.3) - eslint: 8.57.1 - transitivePeerDependencies: - - supports-color - - typescript - '@typescript-eslint/visitor-keys@7.18.0': dependencies: '@typescript-eslint/types': 7.18.0 @@ -6122,11 +6196,6 @@ snapshots: '@typescript-eslint/types': 8.24.1 eslint-visitor-keys: 4.2.0 - '@typescript-eslint/visitor-keys@8.8.1': - dependencies: - '@typescript-eslint/types': 8.8.1 - eslint-visitor-keys: 3.4.3 - '@uiw/codemirror-extensions-basic-setup@4.23.5(@codemirror/autocomplete@6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.2))(@codemirror/commands@6.7.0)(@codemirror/language@6.10.3)(@codemirror/lint@6.8.2)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)': dependencies: '@codemirror/autocomplete': 6.18.1(@codemirror/language@6.10.3)(@codemirror/state@6.4.1)(@codemirror/view@6.34.1)(@lezer/common@1.2.2) @@ -6551,6 +6620,21 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + babel-plugin-jsx-dom-expressions@0.39.8(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.25.8) + '@babel/types': 7.25.8 + html-entities: 2.3.3 + parse5: 7.1.2 + validate-html-nesting: 1.2.3 + + babel-preset-solid@1.9.6(@babel/core@7.25.8): + dependencies: + '@babel/core': 7.25.8 + babel-plugin-jsx-dom-expressions: 0.39.8(@babel/core@7.25.8) + balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -7071,10 +7155,10 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 string-ts: 2.2.0 ts-pattern: 5.4.0 @@ -7092,9 +7176,9 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 ts-pattern: 5.4.0 optionalDependencies: @@ -7111,10 +7195,10 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 ts-pattern: 5.4.0 optionalDependencies: @@ -7134,10 +7218,10 @@ snapshots: '@eslint-react/shared': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 ts-pattern: 5.4.0 optionalDependencies: @@ -7158,9 +7242,9 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) birecord: 0.1.1 eslint: 8.57.1 ts-pattern: 5.4.0 @@ -7178,10 +7262,10 @@ snapshots: '@eslint-react/tools': 1.14.3 '@eslint-react/types': 1.14.3(eslint@8.57.1)(typescript@5.6.3) '@eslint-react/var': 1.14.3(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.24.1 + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 is-immutable-type: 5.0.0(eslint@8.57.1)(typescript@5.6.3) ts-pattern: 5.4.0 @@ -7190,6 +7274,19 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-solid@0.14.5(eslint@8.57.1)(typescript@5.6.3): + dependencies: + '@typescript-eslint/utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) + eslint: 8.57.1 + estraverse: 5.3.0 + is-html: 2.0.0 + kebab-case: 1.0.2 + known-css-properties: 0.30.0 + style-to-object: 1.0.9 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + eslint-plugin-vue@9.29.0(eslint@8.57.1): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -7562,6 +7659,10 @@ snapshots: dependencies: whatwg-encoding: 3.1.1 + html-entities@2.3.3: {} + + html-tags@3.3.1: {} + html-void-elements@3.0.0: {} http-proxy-agent@7.0.2: @@ -7641,6 +7742,8 @@ snapshots: ini@1.3.8: {} + inline-style-parser@0.2.4: {} + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 @@ -7688,9 +7791,13 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-html@2.0.0: + dependencies: + html-tags: 3.3.1 + is-immutable-type@5.0.0(eslint@8.57.1)(typescript@5.6.3): dependencies: - '@typescript-eslint/type-utils': 8.8.1(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.24.1(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 ts-api-utils: 1.3.0(typescript@5.6.3) ts-declaration-location: 1.0.4(typescript@5.6.3) @@ -7829,10 +7936,14 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + kebab-case@1.0.2: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + known-css-properties@0.30.0: {} + kolorist@1.8.0: {} levn@0.4.1: @@ -7928,6 +8039,10 @@ snapshots: unist-util-visit: 5.0.0 vfile: 6.0.3 + merge-anything@5.1.7: + dependencies: + is-what: 4.1.16 + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -8518,6 +8633,12 @@ snapshots: semver@7.6.3: {} + seroval-plugins@1.3.2(seroval@1.3.2): + dependencies: + seroval: 1.3.2 + + seroval@1.3.2: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -8586,6 +8707,21 @@ snapshots: slash@3.0.0: {} + solid-js@1.9.7: + dependencies: + csstype: 3.1.3 + seroval: 1.3.2 + seroval-plugins: 1.3.2(seroval@1.3.2) + + solid-refresh@0.6.3(solid-js@1.9.7): + dependencies: + '@babel/generator': 7.25.7 + '@babel/helper-module-imports': 7.25.7 + '@babel/types': 7.25.8 + solid-js: 1.9.7 + transitivePeerDependencies: + - supports-color + source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -8671,6 +8807,10 @@ snapshots: style-mod@4.1.2: {} + style-to-object@1.0.9: + dependencies: + inline-style-parser: 0.2.4 + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -8937,6 +9077,8 @@ snapshots: util-deprecate@1.0.2: {} + validate-html-nesting@1.2.3: {} + validate-npm-package-name@5.0.1: {} vfile-message@4.0.2: @@ -9008,6 +9150,19 @@ snapshots: minimatch: 9.0.5 vite: 5.4.8(@types/node@20.16.11)(terser@5.34.1) + vite-plugin-solid@2.11.7(solid-js@1.9.7)(vite@5.4.8(@types/node@20.16.11)(terser@5.34.1)): + dependencies: + '@babel/core': 7.25.8 + '@types/babel__core': 7.20.5 + babel-preset-solid: 1.9.6(@babel/core@7.25.8) + merge-anything: 5.1.7 + solid-js: 1.9.7 + solid-refresh: 0.6.3(solid-js@1.9.7) + vite: 5.4.8(@types/node@20.16.11)(terser@5.34.1) + vitefu: 1.1.1(vite@5.4.8(@types/node@20.16.11)(terser@5.34.1)) + transitivePeerDependencies: + - supports-color + vite@5.4.8(@types/node@20.16.11)(terser@5.34.1): dependencies: esbuild: 0.21.5 @@ -9018,6 +9173,10 @@ snapshots: fsevents: 2.3.3 terser: 5.34.1 + vitefu@1.1.1(vite@5.4.8(@types/node@20.16.11)(terser@5.34.1)): + optionalDependencies: + vite: 5.4.8(@types/node@20.16.11)(terser@5.34.1) + vitepress@1.4.0(@algolia/client-search@4.24.0)(@types/node@20.16.11)(@types/react@18.3.11)(@vue/composition-api@1.7.2(vue@3.5.11(typescript@5.6.3)))(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.2)(terser@5.34.1)(typescript@5.6.3): dependencies: '@docsearch/css': 3.6.2