diff --git a/.gitignore b/.gitignore
index dd37e8f..b85c72a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ coverage
out/
build
dist
+*.tsbuildinfo
# misc
.DS_Store
diff --git a/README.md b/README.md
index f66e77b..72be1d0 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,14 @@ Check the example apps to see common usages or use them as a boilerplate.
# Packages
- [ra-data-simple-prisma](./packages/ra-data-simple-prisma/)
+- [ra-data-duckdb](./packages/ra-data-duckdb/)
- [next-auth-prisma-adapter](./packages/next-auth-prisma-adapter/)
# Examples
[example admin app](./apps/admin/) Debug, test, and develop the packages, but also use it as the admin/CMS for the website!
[example website](./apps/website/) A nextjs/mui boilerplate to show the data (very much under construction yet)
+[DuckDB admin example](./apps/duckdb-admin/) Minimal in-memory DuckDB and React Admin app.
### Development
diff --git a/apps/duckdb-admin/README.md b/apps/duckdb-admin/README.md
new file mode 100644
index 0000000..e58d0d0
--- /dev/null
+++ b/apps/duckdb-admin/README.md
@@ -0,0 +1,16 @@
+# DuckDB Admin Example
+
+A minimal Next.js app using React Admin and the workspace's
+`ra-data-duckdb` package.
+
+The API creates an in-memory DuckDB database with three users when the server
+starts. Changes persist until the development server restarts.
+
+```sh
+pnpm --filter duckdb-admin-example dev
+```
+
+Open [http://localhost:3030](http://localhost:3030).
+
+Scripts pass `NODE_OPTIONS=--no-webstorage` because Node.js 25+ ships a partial
+`localStorage` that breaks Next.js 15.3 SSR.
diff --git a/apps/duckdb-admin/app/Admin.tsx b/apps/duckdb-admin/app/Admin.tsx
new file mode 100644
index 0000000..9cdcffd
--- /dev/null
+++ b/apps/duckdb-admin/app/Admin.tsx
@@ -0,0 +1,10 @@
+"use client";
+
+import dynamic from "next/dynamic";
+
+const AdminApp = dynamic(() => import("./AdminApp"), {
+ ssr: false,
+ loading: () =>
Loading admin…
,
+});
+
+export default AdminApp;
diff --git a/apps/duckdb-admin/app/AdminApp.tsx b/apps/duckdb-admin/app/AdminApp.tsx
new file mode 100644
index 0000000..8850d24
--- /dev/null
+++ b/apps/duckdb-admin/app/AdminApp.tsx
@@ -0,0 +1,73 @@
+"use client";
+
+import {
+ Admin,
+ BooleanField,
+ BooleanInput,
+ Create,
+ Datagrid,
+ Edit,
+ EditButton,
+ List,
+ NumberField,
+ NumberInput,
+ Resource,
+ SimpleForm,
+ TextField,
+ TextInput,
+ required,
+} from "react-admin";
+import { dataProvider } from "ra-data-duckdb";
+
+const usersProvider = dataProvider("/api");
+
+const userFilters = [
+ ,
+];
+
+const UserList = () => (
+
+
+
+
+
+
+
+
+
+
+);
+
+const UserForm = () => (
+
+
+
+
+
+
+);
+
+const UserCreate = () => (
+
+
+
+);
+
+const UserEdit = () => (
+
+
+
+);
+
+const AdminApp = () => (
+
+
+
+);
+
+export default AdminApp;
diff --git a/apps/duckdb-admin/app/api/[resource]/route.ts b/apps/duckdb-admin/app/api/[resource]/route.ts
new file mode 100644
index 0000000..86e1315
--- /dev/null
+++ b/apps/duckdb-admin/app/api/[resource]/route.ts
@@ -0,0 +1,63 @@
+import { DuckDBInstance } from "@duckdb/node-api";
+import {
+ defaultHandler,
+ DuckDBExecutor,
+ fromDuckDBConnection,
+ NotFoundError,
+} from "ra-data-duckdb/server";
+import { NextResponse } from "next/server";
+
+export const runtime = "nodejs";
+
+const globalForDuckDB = globalThis as typeof globalThis & {
+ duckDBDemo?: Promise;
+};
+
+const createDatabase = async (): Promise => {
+ const instance = await DuckDBInstance.create(":memory:");
+ const connection = await instance.connect();
+ const db = fromDuckDBConnection(connection);
+
+ await db.run("CREATE SEQUENCE users_id_seq START 4");
+ await db.run(`
+ CREATE TABLE users (
+ id INTEGER PRIMARY KEY DEFAULT nextval('users_id_seq'),
+ name VARCHAR NOT NULL,
+ email VARCHAR NOT NULL,
+ age INTEGER,
+ active BOOLEAN DEFAULT true
+ )
+ `);
+ await db.run(`
+ INSERT INTO users (id, name, email, age, active)
+ VALUES
+ (1, 'Ada Lovelace', 'ada@example.com', 36, true),
+ (2, 'Grace Hopper', 'grace@example.com', 85, true),
+ (3, 'Alan Turing', 'alan@example.com', 41, false)
+ `);
+
+ return db;
+};
+
+const getDatabase = () => {
+ globalForDuckDB.duckDBDemo ??= createDatabase();
+ return globalForDuckDB.duckDBDemo;
+};
+
+const handler = async (request: Request) => {
+ try {
+ const payload = await request.json();
+ const db = await getDatabase();
+ const result = await defaultHandler(payload, db, {
+ getList: { searchColumns: ["name", "email"] },
+ });
+
+ return NextResponse.json(result);
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Unknown error";
+ const status = error instanceof NotFoundError ? error.status : 400;
+ return NextResponse.json({ message }, { status });
+ }
+};
+
+export { handler as GET, handler as POST };
diff --git a/apps/duckdb-admin/app/layout.tsx b/apps/duckdb-admin/app/layout.tsx
new file mode 100644
index 0000000..390f1b4
--- /dev/null
+++ b/apps/duckdb-admin/app/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from "next";
+import type { ReactNode } from "react";
+
+export const metadata: Metadata = {
+ title: "React Admin + DuckDB",
+ description: "Minimal ra-data-duckdb example",
+};
+
+export default function RootLayout({ children }: { children: ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/apps/duckdb-admin/app/page.tsx b/apps/duckdb-admin/app/page.tsx
new file mode 100644
index 0000000..0f85aa2
--- /dev/null
+++ b/apps/duckdb-admin/app/page.tsx
@@ -0,0 +1,5 @@
+import Admin from "./Admin";
+
+export default function HomePage() {
+ return ;
+}
diff --git a/apps/duckdb-admin/next-env.d.ts b/apps/duckdb-admin/next-env.d.ts
new file mode 100644
index 0000000..1b3be08
--- /dev/null
+++ b/apps/duckdb-admin/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/apps/duckdb-admin/next.config.js b/apps/duckdb-admin/next.config.js
new file mode 100644
index 0000000..e100f86
--- /dev/null
+++ b/apps/duckdb-admin/next.config.js
@@ -0,0 +1,37 @@
+const path = require("path");
+
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ serverExternalPackages: ["@duckdb/node-api"],
+ transpilePackages: [
+ "ra-data-duckdb",
+ "react-admin",
+ "ra-core",
+ "ra-ui-materialui",
+ "ra-i18n-polyglot",
+ "ra-language-english",
+ "@mui/material",
+ "@mui/icons-material",
+ "@mui/system",
+ "@mui/utils",
+ ],
+ modularizeImports: {
+ "@mui/icons-material": {
+ transform: "@mui/icons-material/{{member}}",
+ },
+ },
+ webpack: (config) => {
+ config.resolve.alias = {
+ ...config.resolve.alias,
+ // ESM ra-ui-materialui default-imports CJS icon files; without this,
+ // webpack treats the CJS module namespace as the component (got: object).
+ "@mui/icons-material": path.resolve(
+ __dirname,
+ "../../node_modules/@mui/icons-material/esm"
+ ),
+ };
+ return config;
+ },
+};
+
+module.exports = nextConfig;
diff --git a/apps/duckdb-admin/package.json b/apps/duckdb-admin/package.json
new file mode 100644
index 0000000..7b2a6e8
--- /dev/null
+++ b/apps/duckdb-admin/package.json
@@ -0,0 +1,27 @@
+{
+ "name": "duckdb-admin-example",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "NODE_OPTIONS=--no-webstorage next dev -p 3030",
+ "build": "NODE_OPTIONS=--no-webstorage next build",
+ "start": "NODE_OPTIONS=--no-webstorage next start -p 3030"
+ },
+ "dependencies": {
+ "@duckdb/node-api": "1.5.5-r.4",
+ "@mui/icons-material": "5.17.1",
+ "@mui/material": "5.17.1",
+ "next": "15.3.0",
+ "ra-data-duckdb": "workspace:*",
+ "react": "19.1.0",
+ "react-admin": "^5.14.1",
+ "react-dom": "19.1.0",
+ "react-hook-form": "^7.65.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22",
+ "@types/react": "19.1.1",
+ "@types/react-dom": "19.1.2",
+ "typescript": "^5.9.3"
+ }
+}
diff --git a/apps/duckdb-admin/tsconfig.json b/apps/duckdb-admin/tsconfig.json
new file mode 100644
index 0000000..287a27e
--- /dev/null
+++ b/apps/duckdb-admin/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [{ "name": "next" }]
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/packages/ra-data-duckdb/README.md b/packages/ra-data-duckdb/README.md
new file mode 100644
index 0000000..491d618
--- /dev/null
+++ b/packages/ra-data-duckdb/README.md
@@ -0,0 +1,81 @@
+# React Admin + DuckDB
+
+Simple react-admin data provider backed by [DuckDB](https://duckdb.org/). Same request shape as `ra-data-simple-prisma`: the browser talks HTTP, the server runs SQL.
+
+### Installation
+
+```
+pnpm i ra-data-duckdb @duckdb/node-api
+```
+
+### Frontend
+
+```tsx
+import { Admin, Resource } from "react-admin";
+import { dataProvider } from "ra-data-duckdb";
+
+const ReactAdmin = () => (
+
+
+
+);
+```
+
+### Backend (Next.js App Router)
+
+```ts
+// app/api/[resource]/route.ts
+import { DuckDBInstance } from "@duckdb/node-api";
+import { defaultHandler, fromDuckDBConnection } from "ra-data-duckdb/server";
+import { NextResponse } from "next/server";
+
+const instance = await DuckDBInstance.create("data.duckdb");
+const connection = await instance.connect();
+const db = fromDuckDBConnection(connection);
+
+const handler = async (req: Request) => {
+ const body = await req.json();
+ const result = await defaultHandler(body, db, {
+ // optional: map react-admin resource names to table names
+ resourceToTableMap: { users: "app_users" },
+ });
+ return NextResponse.json(result);
+};
+
+export { handler as GET, handler as POST };
+```
+
+### Custom executor
+
+Handlers take a minimal `DuckDBExecutor` (`all` / `run`). Use `fromDuckDBConnection` for `@duckdb/node-api`, or supply your own:
+
+```ts
+import { defaultHandler, DuckDBExecutor } from "ra-data-duckdb/server";
+
+const db: DuckDBExecutor = {
+ all: async (sql, params) => { /* ... */ },
+ run: async (sql, params) => { /* ... */ },
+};
+
+await defaultHandler(body, db);
+```
+
+### Filters
+
+Common react-admin filters are mapped to SQL:
+
+| Filter | SQL |
+| --- | --- |
+| `age: 30` / `age_eq` | `"age" = $p` |
+| `age_gte` / `_gt` / `_lte` / `_lt` | comparison |
+| `name: "Al"` (string) | `LIKE '%Al%'` (case-insensitive by default) |
+| `id_in: [1,2]` / array value | `IN (...)` |
+| `q` + `searchColumns` | OR of LIKE across columns |
+| `OR` / `AND` / `NOT` | grouped boolean |
+
+Resource and column names are validated and quoted; only `[A-Za-z_][A-Za-z0-9_]*` identifiers are allowed.
+
+### Notes
+
+- DuckDB is not ideal for high-concurrency multi-writer admin apps; prefer a single writer or an analytics/read-heavy use case.
+- Audit logs and Prisma-style relation `include` / `connect` are not ported — keep v1 flat-table CRUD.
diff --git a/packages/ra-data-duckdb/jest.config.ts b/packages/ra-data-duckdb/jest.config.ts
new file mode 100644
index 0000000..5ef8077
--- /dev/null
+++ b/packages/ra-data-duckdb/jest.config.ts
@@ -0,0 +1,19 @@
+import type { Config } from "jest";
+
+const config: Config = {
+ testEnvironment: "node",
+ transform: {
+ "^.+\\.(t|j)sx?$": [
+ "babel-jest",
+ {
+ presets: [
+ ["@babel/preset-env", { targets: { node: "current" } }],
+ "@babel/preset-typescript",
+ ],
+ },
+ ],
+ },
+ testMatch: ["**/tests/**/*.test.ts"],
+};
+
+export default config;
diff --git a/packages/ra-data-duckdb/package.json b/packages/ra-data-duckdb/package.json
new file mode 100644
index 0000000..78ae076
--- /dev/null
+++ b/packages/ra-data-duckdb/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "ra-data-duckdb",
+ "version": "0.0.1",
+ "description": "Simple react-admin dataprovider for DuckDB",
+ "main": "./dist/index.js",
+ "module": "./dist/index.mjs",
+ "types": "./dist/index.d.ts",
+ "scripts": {
+ "build": "tsup src/index.ts src/server.ts --format esm,cjs --dts --treeshake --external react-admin --external ra-core --external ra-ui-materialui --external @duckdb/node-api",
+ "dev": "pnpm build --watch",
+ "lint": "eslint src --fix",
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
+ "prepublish": "pnpm build",
+ "test": "jest"
+ },
+ "files": [
+ "/dist"
+ ],
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.js"
+ },
+ "./server": {
+ "types": "./dist/server.d.ts",
+ "import": "./dist/server.mjs",
+ "require": "./dist/server.js"
+ }
+ },
+ "keywords": [
+ "duckdb",
+ "rest",
+ "marmelab",
+ "react-admin",
+ "dataprovider",
+ "admin",
+ "react"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/codeledge/ra-data-simple-prisma.git",
+ "directory": "packages/ra-data-duckdb"
+ },
+ "author": "Orlando Groppo ",
+ "license": "MIT",
+ "peerDependencies": {
+ "@duckdb/node-api": "*",
+ "react-admin": ">=5.7.2"
+ },
+ "peerDependenciesMeta": {
+ "@duckdb/node-api": {
+ "optional": true
+ }
+ },
+ "dependencies": {
+ "axios": "^1.13.5",
+ "deverything": "^5.5.1"
+ },
+ "devDependencies": {
+ "@babel/core": "7.29.0",
+ "@babel/preset-env": "^7.29.0",
+ "@babel/preset-typescript": "^7.28.5",
+ "@duckdb/node-api": "1.5.5-r.4",
+ "@types/jest": "^30.0.0",
+ "@types/node": "^25.2.3",
+ "eslint-config-custom": "workspace:*",
+ "jest": "^30.2.0",
+ "react-admin": "^5.14.1",
+ "ts-node": "^10.9.2",
+ "tsup": "^8.5.1",
+ "typescript": "^5.9.3"
+ }
+}
diff --git a/packages/ra-data-duckdb/src/Http.ts b/packages/ra-data-duckdb/src/Http.ts
new file mode 100644
index 0000000..b4a487f
--- /dev/null
+++ b/packages/ra-data-duckdb/src/Http.ts
@@ -0,0 +1,76 @@
+import type {
+ CreateParams,
+ DeleteManyParams,
+ DeleteParams,
+ GetListParams,
+ GetManyParams,
+ GetManyReferenceParams,
+ GetOneParams,
+ UpdateManyParams,
+ UpdateParams,
+} from "react-admin";
+
+export type RaPayload =
+ | GetListRequest
+ | GetOneRequest
+ | GetManyRequest
+ | GetManyReferenceRequest
+ | CreateRequest
+ | UpdateRequest
+ | UpdateManyRequest
+ | DeleteRequest
+ | DeleteManyRequest;
+
+export type GetListRequest = {
+ method: "getList";
+ params: GetListParams;
+ resource: T;
+};
+
+export type GetOneRequest = {
+ method: "getOne";
+ params: GetOneParams;
+ resource: T;
+};
+
+export type GetManyRequest = {
+ method: "getMany";
+ params: GetManyParams;
+ resource: T;
+};
+
+export type GetManyReferenceRequest = {
+ method: "getManyReference";
+ params: GetManyReferenceParams;
+ resource: T;
+};
+
+export type CreateRequest = {
+ method: "create";
+ params: CreateParams;
+ resource: T;
+};
+
+export type UpdateRequest = {
+ method: "update";
+ params: UpdateParams;
+ resource: T;
+};
+
+export type UpdateManyRequest = {
+ method: "updateMany";
+ params: UpdateManyParams;
+ resource: T;
+};
+
+export type DeleteRequest = {
+ method: "delete";
+ params: DeleteParams;
+ resource: T;
+};
+
+export type DeleteManyRequest = {
+ method: "deleteMany";
+ params: DeleteManyParams;
+ resource: T;
+};
diff --git a/packages/ra-data-duckdb/src/createHandler.ts b/packages/ra-data-duckdb/src/createHandler.ts
new file mode 100644
index 0000000..fbbaff3
--- /dev/null
+++ b/packages/ra-data-duckdb/src/createHandler.ts
@@ -0,0 +1,70 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import type { CreateRequest } from "./Http";
+import { isNotField } from "./lib/isNotField";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type CreateOptions = {
+ allowOnlyFields?: Record;
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+};
+
+const sanitizeWriteData = (
+ data: Record,
+ options?: CreateOptions,
+) => {
+ const primaryKey = options?.primaryKey ?? "id";
+ const cleaned: Record = {};
+
+ Object.entries(data).forEach(([key, value]) => {
+ // With a custom primary key, `id` is only React-admin's response alias.
+ if (primaryKey !== "id" && key === "id") return;
+ if (primaryKey !== "id" && key === primaryKey) {
+ throw new Error(
+ `createHandler: Field ${key} is reserved when primaryKey is configured; use id in responses and omit the original primary key from writes`,
+ );
+ }
+ if (value === "") return;
+ if (isNotField(key)) return;
+ if (options?.allowOnlyFields && !options.allowOnlyFields[key]) {
+ throw new Error(`createHandler: Field ${key} is not allowed in create`);
+ }
+ cleaned[key] = value;
+ });
+
+ return cleaned;
+};
+
+export const createHandler = async (
+ req: CreateRequest,
+ db: DuckDBExecutor,
+ options?: CreateOptions,
+) => {
+ const table = getTable(req, options?.resourceToTableMap);
+ const primaryKey = options?.primaryKey ?? "id";
+ const data = sanitizeWriteData(req.params.data as Record, options);
+
+ if (options?.debug) console.log("createHandler:data", data);
+
+ const columns = Object.keys(data);
+ if (!columns.length) {
+ throw new Error("createHandler: no fields to insert");
+ }
+
+ const params = new SqlParams();
+ const placeholders = columns.map((col) => params.add(data[col]));
+ const columnSql = columns.map(quoteIdent).join(", ");
+
+ const sql = `INSERT INTO ${table} (${columnSql}) VALUES (${placeholders.join(", ")}) RETURNING *`;
+
+ if (options?.debug) console.log("createHandler:sql", sql, params.get());
+
+ const rows = await db.all(sql, params.get());
+ const created = rows[0];
+
+ return { data: mapPrimaryKeyToId(created, primaryKey) };
+};
diff --git a/packages/ra-data-duckdb/src/dataProvider.ts b/packages/ra-data-duckdb/src/dataProvider.ts
new file mode 100644
index 0000000..b35c607
--- /dev/null
+++ b/packages/ra-data-duckdb/src/dataProvider.ts
@@ -0,0 +1,164 @@
+import { DataProvider, HttpError } from "react-admin";
+import axios from "axios";
+import type {
+ AxiosError,
+ AxiosInterceptorOptions,
+ CreateAxiosDefaults,
+} from "axios";
+import { isNumericId } from "deverything";
+
+type AxiosInterceptorFulfilled = ((value: V) => V | Promise) | null;
+type AxiosInterceptorError = ((error: any) => any) | null;
+
+export const dataProvider = (
+ endpoint: string,
+ options?: {
+ headers?: CreateAxiosDefaults["headers"];
+ withCredentials?: boolean;
+ axiosInterceptors?: {
+ response?: {
+ onFulfilled?: AxiosInterceptorFulfilled;
+ onRejected?: AxiosInterceptorError;
+ options?: AxiosInterceptorOptions;
+ }[];
+ request?: {
+ onFulfilled?: AxiosInterceptorFulfilled;
+ onRejected?: AxiosInterceptorError;
+ options?: AxiosInterceptorOptions;
+ }[];
+ };
+ },
+): DataProvider => {
+ const apiService = axios.create({
+ baseURL: endpoint,
+ headers: options?.headers,
+ withCredentials: options?.withCredentials,
+ });
+
+ apiService.interceptors.response.use((res) => res.data);
+
+ if (options?.axiosInterceptors) {
+ if (options.axiosInterceptors.request)
+ options.axiosInterceptors.request.forEach((value) =>
+ apiService.interceptors.request.use(
+ value.onFulfilled,
+ value.onRejected,
+ value.options,
+ ),
+ );
+
+ if (options.axiosInterceptors.response)
+ options.axiosInterceptors.response.forEach((value) =>
+ apiService.interceptors.response.use(
+ value.onFulfilled,
+ value.onRejected,
+ ),
+ );
+ }
+
+ return {
+ getList: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "getList",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ getOne: (resource, params) => {
+ castIdToOriginalType(params);
+
+ return apiService
+ .post(resource, {
+ method: "getOne",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ getMany: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "getMany",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ getManyReference: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "getManyReference",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ create: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "create",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ update: (resource, params) => {
+ castIdToOriginalType(params);
+
+ return apiService
+ .post(resource, {
+ method: "update",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ updateMany: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "updateMany",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ delete: (resource, params) => {
+ castIdToOriginalType(params);
+
+ return apiService
+ .post(resource, {
+ method: "delete",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ deleteMany: (resource, params) => {
+ return apiService
+ .post(resource, {
+ method: "deleteMany",
+ resource,
+ params,
+ })
+ .catch(reactAdminAxiosErrorHandler);
+ },
+ };
+};
+
+// https://github.com/marmelab/react-admin/issues/7728#issuecomment-1133959466
+// getOne will get the id from url so if the id is number it will be sent as string
+const castIdToOriginalType = (params: any) => {
+ if (isNumericId(params.id)) params.id = +params.id;
+};
+
+// react-admin expects the error to be thrown
+// https://marmelab.com/admin-on-rest/RestClients.html#writing-your-own-rest-client
+const reactAdminAxiosErrorHandler = (error: AxiosError) => {
+ throw new HttpError(
+ (error?.response?.data as any)?.message || error?.response?.statusText,
+ error?.response?.status,
+ error?.response?.data,
+ );
+};
diff --git a/packages/ra-data-duckdb/src/defaultHandler.ts b/packages/ra-data-duckdb/src/defaultHandler.ts
new file mode 100644
index 0000000..52a5fc0
--- /dev/null
+++ b/packages/ra-data-duckdb/src/defaultHandler.ts
@@ -0,0 +1,126 @@
+import { type CreateOptions, createHandler } from "./createHandler";
+import { type DeleteOptions, deleteHandler } from "./deleteHandler";
+import { type DeleteManyOptions, deleteManyHandler } from "./deleteManyHandler";
+import { DuckDBExecutor } from "./duckdb";
+import { type GetListOptions, getListHandler } from "./getListHandler";
+import { type GetManyOptions, getManyHandler } from "./getManyHandler";
+import {
+ type GetManyReferenceOptions,
+ getManyReferenceHandler,
+} from "./getManyReferenceHandler";
+import { type ResourceToTableMap } from "./getTable";
+import { type GetOneOptions, getOneHandler } from "./getOneHandler";
+import type {
+ CreateRequest,
+ DeleteManyRequest,
+ DeleteRequest,
+ GetListRequest,
+ GetManyReferenceRequest,
+ GetManyRequest,
+ GetOneRequest,
+ RaPayload,
+ UpdateManyRequest,
+ UpdateRequest,
+} from "./Http";
+import { type UpdateOptions, updateHandler } from "./updateHandler";
+import { updateManyHandler } from "./updateManyHandler";
+
+export type DefaultHandlerOptions = {
+ create?: CreateOptions;
+ delete?: DeleteOptions;
+ deleteMany?: DeleteManyOptions;
+ getList?: GetListOptions;
+ getMany?: GetManyOptions;
+ getManyReference?: GetManyReferenceOptions;
+ getOne?: GetOneOptions;
+ resourceToTableMap?: ResourceToTableMap;
+ update?: UpdateOptions;
+};
+
+const withResourceToTableMap = (
+ handlerOptions: T | undefined,
+ resourceToTableMap?: ResourceToTableMap,
+) => ({
+ ...(resourceToTableMap ? { resourceToTableMap } : {}),
+ ...handlerOptions,
+});
+
+export const defaultHandler = async (
+ req: RaPayload,
+ db: DuckDBExecutor,
+ options?: DefaultHandlerOptions,
+) => {
+ switch (req.method) {
+ case "create": {
+ return await createHandler(
+ req as CreateRequest,
+ db,
+ withResourceToTableMap(options?.create, options?.resourceToTableMap),
+ );
+ }
+ case "delete": {
+ return await deleteHandler(
+ req as DeleteRequest,
+ db,
+ withResourceToTableMap(options?.delete, options?.resourceToTableMap),
+ );
+ }
+ case "deleteMany": {
+ return deleteManyHandler(
+ req as DeleteManyRequest,
+ db,
+ withResourceToTableMap(
+ options?.deleteMany ?? options?.delete,
+ options?.resourceToTableMap,
+ ),
+ );
+ }
+ case "getList": {
+ return getListHandler(
+ req as GetListRequest,
+ db,
+ withResourceToTableMap(options?.getList, options?.resourceToTableMap),
+ );
+ }
+ case "getMany": {
+ return getManyHandler(
+ req as GetManyRequest,
+ db,
+ withResourceToTableMap(options?.getMany, options?.resourceToTableMap),
+ );
+ }
+ case "getManyReference": {
+ return getManyReferenceHandler(
+ req as GetManyReferenceRequest,
+ db,
+ withResourceToTableMap(
+ options?.getManyReference,
+ options?.resourceToTableMap,
+ ),
+ );
+ }
+ case "getOne": {
+ return getOneHandler(
+ req as GetOneRequest,
+ db,
+ withResourceToTableMap(options?.getOne, options?.resourceToTableMap),
+ );
+ }
+ case "update": {
+ return await updateHandler(
+ req as UpdateRequest,
+ db,
+ withResourceToTableMap(options?.update, options?.resourceToTableMap),
+ );
+ }
+ case "updateMany": {
+ return await updateManyHandler(
+ req as UpdateManyRequest,
+ db,
+ withResourceToTableMap(options?.update, options?.resourceToTableMap),
+ );
+ }
+ default:
+ throw new Error("Invalid method");
+ }
+};
diff --git a/packages/ra-data-duckdb/src/deleteHandler.ts b/packages/ra-data-duckdb/src/deleteHandler.ts
new file mode 100644
index 0000000..0534c09
--- /dev/null
+++ b/packages/ra-data-duckdb/src/deleteHandler.ts
@@ -0,0 +1,34 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { DeleteRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type DeleteOptions = {
+ softDeleteField?: string;
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+};
+
+export const deleteHandler = async (
+ req: DeleteRequest,
+ db: DuckDBExecutor,
+ options?: DeleteOptions,
+) => {
+ const { id } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+ const pk = quoteIdent(primaryKey);
+
+ const sql = options?.softDeleteField
+ ? `UPDATE ${table} SET ${quoteIdent(options.softDeleteField)} = CURRENT_TIMESTAMP WHERE ${pk} = $id RETURNING *`
+ : `DELETE FROM ${table} WHERE ${pk} = $id RETURNING *`;
+
+ if (options?.debug) console.log("deleteHandler", sql, { id });
+
+ const rows = await db.all(sql, { id });
+ const deleted = rows[0];
+
+ return { data: mapPrimaryKeyToId(deleted, primaryKey) };
+};
diff --git a/packages/ra-data-duckdb/src/deleteManyHandler.ts b/packages/ra-data-duckdb/src/deleteManyHandler.ts
new file mode 100644
index 0000000..edbe085
--- /dev/null
+++ b/packages/ra-data-duckdb/src/deleteManyHandler.ts
@@ -0,0 +1,40 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { DeleteManyRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+
+export type DeleteManyOptions = {
+ softDeleteField?: string;
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+};
+
+export const deleteManyHandler = async (
+ req: DeleteManyRequest,
+ db: DuckDBExecutor,
+ options?: DeleteManyOptions,
+) => {
+ const { ids } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+
+ if (!ids?.length) {
+ return { data: [] };
+ }
+
+ const params = new SqlParams();
+ const placeholders = ids.map((id) => params.add(id));
+ const pk = quoteIdent(primaryKey);
+
+ const sql = options?.softDeleteField
+ ? `UPDATE ${table} SET ${quoteIdent(options.softDeleteField)} = CURRENT_TIMESTAMP WHERE ${pk} IN (${placeholders.join(", ")})`
+ : `DELETE FROM ${table} WHERE ${pk} IN (${placeholders.join(", ")})`;
+
+ if (options?.debug) console.log("deleteManyHandler", sql, params.get());
+
+ await db.run(sql, params.get());
+
+ return { data: ids };
+};
diff --git a/packages/ra-data-duckdb/src/duckdb.ts b/packages/ra-data-duckdb/src/duckdb.ts
new file mode 100644
index 0000000..e93e85c
--- /dev/null
+++ b/packages/ra-data-duckdb/src/duckdb.ts
@@ -0,0 +1,39 @@
+/**
+ * Minimal DuckDB query surface used by handlers.
+ * Pass your own implementation, or wrap `@duckdb/node-api` via `fromDuckDBConnection`.
+ */
+export type DuckDBExecutor = {
+ all: >(
+ sql: string,
+ params?: Record,
+ ) => Promise;
+ run: (sql: string, params?: Record) => Promise;
+};
+
+type DuckDBConnectionLike = {
+ runAndReadAll: (
+ sql: string,
+ params?: any,
+ ) => Promise<{
+ getRowObjectsJson: () => Record[];
+ }>;
+ run: (sql: string, params?: any) => Promise;
+};
+
+/**
+ * Wrap a `@duckdb/node-api` DuckDBConnection (or compatible) as a DuckDBExecutor.
+ */
+export const fromDuckDBConnection = (
+ connection: DuckDBConnectionLike,
+): DuckDBExecutor => ({
+ all: async >(
+ sql: string,
+ params?: Record,
+ ) => {
+ const reader = await connection.runAndReadAll(sql, params);
+ return reader.getRowObjectsJson() as T[];
+ },
+ run: async (sql: string, params?: Record) => {
+ await connection.run(sql, params);
+ },
+});
diff --git a/packages/ra-data-duckdb/src/extractOrderBy.ts b/packages/ra-data-duckdb/src/extractOrderBy.ts
new file mode 100644
index 0000000..1991bc1
--- /dev/null
+++ b/packages/ra-data-duckdb/src/extractOrderBy.ts
@@ -0,0 +1,17 @@
+import { GetListRequest, GetManyReferenceRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+
+export const extractOrderBy = (
+ req: GetListRequest | GetManyReferenceRequest,
+ primaryKey = "id",
+): string => {
+ const { sort } = req.params;
+
+ if (sort?.field && sort?.order) {
+ const field = sort.field === "id" ? primaryKey : sort.field;
+ const direction = sort.order.toUpperCase() === "DESC" ? "DESC" : "ASC";
+ return `ORDER BY ${quoteIdent(field)} ${direction}`;
+ }
+
+ return "";
+};
diff --git a/packages/ra-data-duckdb/src/extractSkipTake.ts b/packages/ra-data-duckdb/src/extractSkipTake.ts
new file mode 100644
index 0000000..8a6fcf3
--- /dev/null
+++ b/packages/ra-data-duckdb/src/extractSkipTake.ts
@@ -0,0 +1,22 @@
+import { GetListRequest, GetManyReferenceRequest } from "./Http";
+
+export const extractSkipTake = (
+ req: GetListRequest | GetManyReferenceRequest,
+): { skip: number | undefined; take: number | undefined } => {
+ const { pagination } = req.params;
+
+ let skip: number | undefined;
+ let take: number | undefined;
+
+ if (pagination) {
+ const { page, perPage } = pagination;
+
+ const first = (page - 1) * perPage;
+ const last = page * perPage - 1;
+
+ skip = first;
+ take = last - first + 1;
+ }
+
+ return { skip, take };
+};
diff --git a/packages/ra-data-duckdb/src/extractWhere.ts b/packages/ra-data-duckdb/src/extractWhere.ts
new file mode 100644
index 0000000..2635bfc
--- /dev/null
+++ b/packages/ra-data-duckdb/src/extractWhere.ts
@@ -0,0 +1,214 @@
+import { isArray, isObject, isString, PlainObject } from "deverything";
+import { GetListRequest, GetManyReferenceRequest } from "./Http";
+import { isNotField } from "./lib/isNotField";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+
+export type FilterMode = "insensitive" | "default" | undefined;
+
+export type ExtractWhereOptions = {
+ filterMode?: FilterMode;
+ debug?: boolean;
+ /** Columns used when filter key `q` is present (OR of LIKE / ILIKE). */
+ searchColumns?: string[];
+ primaryKey?: string;
+};
+
+const SUFFIX_OPS: Record = {
+ _eq: "=",
+ _exact: "=",
+ _enum: "=",
+ _gt: ">",
+ _gte: ">=",
+ _lt: "<",
+ _lte: "<=",
+ _ne: "!=",
+ _not: "!=",
+};
+
+export type WhereClause = {
+ sql: string;
+ params: Record;
+};
+
+const buildClauses = (
+ filterObj: PlainObject,
+ params: SqlParams,
+ options: ExtractWhereOptions | undefined,
+ primaryKey: string,
+ caseInsensitive: boolean,
+): string[] => {
+ const clauses: string[] = [];
+
+ const pushCompare = (column: string, op: string, value: unknown) => {
+ const col = quoteIdent(column === "id" ? primaryKey : column);
+ if (value === null) {
+ clauses.push(op === "!=" ? `${col} IS NOT NULL` : `${col} IS NULL`);
+ return;
+ }
+ clauses.push(`${col} ${op} ${params.add(value)}`);
+ };
+
+ const pushLike = (column: string, pattern: string) => {
+ const col = quoteIdent(column === "id" ? primaryKey : column);
+ const placeholder = params.add(pattern);
+ clauses.push(
+ caseInsensitive
+ ? `LOWER(CAST(${col} AS VARCHAR)) LIKE LOWER(${placeholder})`
+ : `CAST(${col} AS VARCHAR) LIKE ${placeholder}`,
+ );
+ };
+
+ Object.entries(filterObj).forEach(([field, value]) => {
+ if (isNotField(field)) return;
+ if (value === "") return;
+
+ if (field === "q") {
+ if (isString(value) && options?.searchColumns?.length && value.length > 0) {
+ const ors = options.searchColumns.map((col) => {
+ const placeholder = params.add(`%${value}%`);
+ const quoted = quoteIdent(col);
+ return caseInsensitive
+ ? `LOWER(CAST(${quoted} AS VARCHAR)) LIKE LOWER(${placeholder})`
+ : `CAST(${quoted} AS VARCHAR) LIKE ${placeholder}`;
+ });
+ clauses.push(`(${ors.join(" OR ")})`);
+ }
+ return;
+ }
+
+ if (["OR", "AND", "NOT"].includes(field)) {
+ if (isArray(value) && value.every((item) => isObject(item))) {
+ const group: string[] = [];
+ for (const item of value as PlainObject[]) {
+ const nested = buildClauses(
+ item,
+ params,
+ options,
+ primaryKey,
+ caseInsensitive,
+ );
+ if (nested.length) {
+ group.push(`(${nested.join(" AND ")})`);
+ }
+ }
+ if (group.length) {
+ if (field === "NOT") {
+ clauses.push(`NOT (${group.join(" AND ")})`);
+ } else {
+ clauses.push(`(${group.join(` ${field} `)})`);
+ }
+ }
+ }
+ return;
+ }
+
+ const suffix = Object.keys(SUFFIX_OPS).find((s) => field.endsWith(s));
+ if (suffix) {
+ pushCompare(field.slice(0, -suffix.length), SUFFIX_OPS[suffix], value);
+ return;
+ }
+
+ if (field.endsWith("_contains")) {
+ pushLike(field.slice(0, -"_contains".length), `%${value}%`);
+ return;
+ }
+ if (field.endsWith("_startsWith")) {
+ pushLike(field.slice(0, -"_startsWith".length), `${value}%`);
+ return;
+ }
+ if (field.endsWith("_endsWith")) {
+ pushLike(field.slice(0, -"_endsWith".length), `%${value}`);
+ return;
+ }
+ if (field.endsWith("_trueOnly")) {
+ if (value === true) {
+ pushCompare(field.slice(0, -"_trueOnly".length), "=", true);
+ }
+ return;
+ }
+ if (field.endsWith("_in") && isArray(value)) {
+ const column = field.slice(0, -"_in".length);
+ const col = quoteIdent(column === "id" ? primaryKey : column);
+ if (value.length === 0) {
+ clauses.push("FALSE");
+ return;
+ }
+ const placeholders = value.map((v) => params.add(v));
+ clauses.push(`${col} IN (${placeholders.join(", ")})`);
+ return;
+ }
+
+ // Array values always become IN (...), including id-like fields such as
+ // `id`, `author_id`, or `userId` (ReferenceArrayInput / multi-select FKs).
+ if (isArray(value)) {
+ const col = quoteIdent(field === "id" ? primaryKey : field);
+ if (value.length === 0) {
+ clauses.push("FALSE");
+ return;
+ }
+ const placeholders = value.map((v) => params.add(v));
+ clauses.push(`${col} IN (${placeholders.join(", ")})`);
+ return;
+ }
+
+ if (
+ field === "id" ||
+ field === "uuid" ||
+ field === "uid" ||
+ field === "cuid" ||
+ field.endsWith("_id") ||
+ field.endsWith("_uuid") ||
+ field.endsWith("_uid") ||
+ field.endsWith("_cuid") ||
+ field.endsWith("Id") ||
+ typeof value === "number" ||
+ typeof value === "boolean" ||
+ value === null
+ ) {
+ pushCompare(field, "=", value);
+ } else if (isString(value)) {
+ pushLike(field, `%${value}%`);
+ } else if (isObject(value)) {
+ throw new Error(
+ `ra-data-duckdb: Nested filter "${field}" is not supported; use a flat column filter`,
+ );
+ } else {
+ console.info("ra-data-duckdb: Filter not handled", field, value);
+ }
+ });
+
+ return clauses;
+};
+
+export const extractWhere = (
+ req: GetListRequest | GetManyReferenceRequest,
+ options?: ExtractWhereOptions,
+): WhereClause => {
+ const { filter } = req.params;
+ const params = new SqlParams();
+ const primaryKey = options?.primaryKey ?? "id";
+ const caseInsensitive = options?.filterMode !== "default";
+
+ const clauses = filter
+ ? buildClauses(filter, params, options, primaryKey, caseInsensitive)
+ : [];
+
+ const sql = clauses.length ? `WHERE ${clauses.join(" AND ")}` : "";
+
+ if (options?.debug) console.debug("extractWhere", sql, params.get());
+
+ return { sql, params: params.get() };
+};
+
+/** Append an AND condition onto an existing WHERE clause. */
+export const andWhere = (
+ where: WhereClause,
+ extraSql: string,
+ extraParams?: Record,
+): WhereClause => {
+ const params = { ...where.params, ...extraParams };
+ if (!extraSql) return { sql: where.sql, params };
+ if (!where.sql) return { sql: `WHERE ${extraSql}`, params };
+ return { sql: `${where.sql} AND ${extraSql}`, params };
+};
diff --git a/packages/ra-data-duckdb/src/getListHandler.ts b/packages/ra-data-duckdb/src/getListHandler.ts
new file mode 100644
index 0000000..5ea5644
--- /dev/null
+++ b/packages/ra-data-duckdb/src/getListHandler.ts
@@ -0,0 +1,95 @@
+import { DuckDBExecutor } from "./duckdb";
+import { extractOrderBy } from "./extractOrderBy";
+import { extractSkipTake } from "./extractSkipTake";
+import { andWhere, extractWhere, FilterMode } from "./extractWhere";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { GetListRequest } from "./Http";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type GetListOptions = {
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+ filterMode?: FilterMode;
+ searchColumns?: string[];
+ /** Extra SQL AND condition (no leading WHERE/AND), e.g. `"active" = true` */
+ extraWhere?: string;
+ transformRow?: (
+ row: any,
+ rowIndex: number,
+ rows: any[],
+ ) => any | Promise;
+ transformRows?: (rows: any[]) => any[] | Promise;
+};
+
+export const getListHandler = async (
+ req: GetListRequest,
+ db: DuckDBExecutor,
+ options?: GetListOptions,
+) => {
+ const table = getTable(req, options?.resourceToTableMap);
+ const primaryKey = options?.primaryKey ?? "id";
+
+ let where = extractWhere(req, {
+ filterMode: options?.filterMode,
+ debug: options?.debug,
+ searchColumns: options?.searchColumns,
+ primaryKey,
+ });
+
+ if (options?.extraWhere) {
+ where = andWhere(where, options.extraWhere);
+ }
+
+ const { skip, take } = extractSkipTake(req);
+ const orderBy = extractOrderBy(req, primaryKey);
+
+ const limitSql =
+ take != null
+ ? `LIMIT ${Math.max(0, take)}${skip != null ? ` OFFSET ${Math.max(0, skip)}` : ""}`
+ : skip != null
+ ? `OFFSET ${Math.max(0, skip)}`
+ : "";
+
+ const listSql = [
+ `SELECT * FROM ${table}`,
+ where.sql,
+ orderBy,
+ limitSql,
+ ]
+ .filter(Boolean)
+ .join(" ");
+
+ const countSql = [`SELECT COUNT(*) AS total FROM ${table}`, where.sql]
+ .filter(Boolean)
+ .join(" ");
+
+ if (options?.debug) {
+ console.log("getListHandler:listSql", listSql, where.params);
+ console.log("getListHandler:countSql", countSql, where.params);
+ }
+
+ const [rows, countRows] = await Promise.all([
+ db.all(listSql, where.params),
+ db.all<{ total: number | bigint | string }>(countSql, where.params),
+ ]);
+
+ const total = Number(countRows[0]?.total ?? 0);
+
+ let data = rows;
+
+ if (options?.transformRow) {
+ data = await Promise.all(
+ data.map((row, i, arr) => options.transformRow!(row, i, arr)),
+ );
+ }
+
+ if (options?.transformRows) {
+ data = await options.transformRows(data);
+ }
+
+ return {
+ data: mapPrimaryKeyToId(data, primaryKey),
+ total,
+ };
+};
diff --git a/packages/ra-data-duckdb/src/getManyHandler.ts b/packages/ra-data-duckdb/src/getManyHandler.ts
new file mode 100644
index 0000000..b9a9f93
--- /dev/null
+++ b/packages/ra-data-duckdb/src/getManyHandler.ts
@@ -0,0 +1,46 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { GetManyRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type GetManyOptions = {
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+ transformRow?: (data: any) => any | Promise;
+ transformRows?: (rows: any[]) => any[] | Promise;
+};
+
+export const getManyHandler = async (
+ req: GetManyRequest,
+ db: DuckDBExecutor,
+ options?: GetManyOptions,
+) => {
+ const { ids } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+ const pk = quoteIdent(primaryKey);
+
+ if (!ids?.length) {
+ return { data: [] };
+ }
+
+ const params = new SqlParams();
+ const placeholders = ids.map((id) => params.add(id));
+ const sql = `SELECT * FROM ${table} WHERE ${pk} IN (${placeholders.join(", ")})`;
+
+ if (options?.debug) console.log("getManyHandler", sql, params.get());
+
+ let data = await db.all(sql, params.get());
+
+ if (options?.transformRow) {
+ data = await Promise.all(data.map(options.transformRow));
+ }
+ if (options?.transformRows) {
+ data = await options.transformRows(data);
+ }
+
+ return { data: mapPrimaryKeyToId(data, primaryKey) };
+};
diff --git a/packages/ra-data-duckdb/src/getManyReferenceHandler.ts b/packages/ra-data-duckdb/src/getManyReferenceHandler.ts
new file mode 100644
index 0000000..87061cb
--- /dev/null
+++ b/packages/ra-data-duckdb/src/getManyReferenceHandler.ts
@@ -0,0 +1,78 @@
+import { DuckDBExecutor } from "./duckdb";
+import { extractOrderBy } from "./extractOrderBy";
+import { extractSkipTake } from "./extractSkipTake";
+import { andWhere, extractWhere, FilterMode } from "./extractWhere";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { GetManyReferenceRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type GetManyReferenceOptions = {
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+ filterMode?: FilterMode;
+ searchColumns?: string[];
+ transformRow?: (data: any) => any | Promise;
+ transformRows?: (rows: any[]) => any[] | Promise;
+};
+
+export const getManyReferenceHandler = async (
+ req: GetManyReferenceRequest,
+ db: DuckDBExecutor,
+ options?: GetManyReferenceOptions,
+) => {
+ const { id, target } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+
+ let where = extractWhere(req, {
+ filterMode: options?.filterMode,
+ debug: options?.debug,
+ searchColumns: options?.searchColumns,
+ primaryKey,
+ });
+
+ where = andWhere(where, `${quoteIdent(target)} = $refId`, { refId: id });
+
+ const { skip, take } = extractSkipTake(req);
+ const orderBy = extractOrderBy(req, primaryKey);
+
+ const limitSql =
+ take != null
+ ? `LIMIT ${Math.max(0, take)}${skip != null ? ` OFFSET ${Math.max(0, skip)}` : ""}`
+ : skip != null
+ ? `OFFSET ${Math.max(0, skip)}`
+ : "";
+
+ const listSql = [`SELECT * FROM ${table}`, where.sql, orderBy, limitSql]
+ .filter(Boolean)
+ .join(" ");
+
+ const countSql = [`SELECT COUNT(*) AS total FROM ${table}`, where.sql]
+ .filter(Boolean)
+ .join(" ");
+
+ if (options?.debug) {
+ console.log("getManyReferenceHandler", listSql, where.params);
+ }
+
+ const [rows, countRows] = await Promise.all([
+ db.all(listSql, where.params),
+ db.all<{ total: number | bigint | string }>(countSql, where.params),
+ ]);
+
+ let data = rows;
+
+ if (options?.transformRow) {
+ data = await Promise.all(data.map(options.transformRow));
+ }
+ if (options?.transformRows) {
+ data = await options.transformRows(data);
+ }
+
+ return {
+ data: mapPrimaryKeyToId(data, primaryKey),
+ total: Number(countRows[0]?.total ?? 0),
+ };
+};
diff --git a/packages/ra-data-duckdb/src/getOneHandler.ts b/packages/ra-data-duckdb/src/getOneHandler.ts
new file mode 100644
index 0000000..d624f70
--- /dev/null
+++ b/packages/ra-data-duckdb/src/getOneHandler.ts
@@ -0,0 +1,42 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { GetOneRequest } from "./Http";
+import { NotFoundError } from "./lib/NotFoundError";
+import { quoteIdent } from "./lib/quoteIdent";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type GetOneOptions = {
+ debug?: boolean;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+ transform?: (row: any) => any | Promise;
+};
+
+export const getOneHandler = async (
+ req: GetOneRequest,
+ db: DuckDBExecutor,
+ options?: GetOneOptions,
+) => {
+ const { id } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+ const pk = quoteIdent(primaryKey);
+
+ const sql = `SELECT * FROM ${table} WHERE ${pk} = $id LIMIT 1`;
+
+ if (options?.debug) console.log("getOneHandler", sql, { id });
+
+ const rows = await db.all(sql, { id });
+ const row = rows[0];
+ if (!row) {
+ throw new NotFoundError(
+ `getOneHandler: no row found in ${table} for ${primaryKey}=${id}`,
+ );
+ }
+
+ const transformedRow = options?.transform
+ ? await options.transform(row)
+ : row;
+
+ return { data: mapPrimaryKeyToId(transformedRow, primaryKey) };
+};
diff --git a/packages/ra-data-duckdb/src/getTable.ts b/packages/ra-data-duckdb/src/getTable.ts
new file mode 100644
index 0000000..1f5a1d7
--- /dev/null
+++ b/packages/ra-data-duckdb/src/getTable.ts
@@ -0,0 +1,13 @@
+import { RaPayload } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+
+export type ResourceToTableMap = Record;
+
+export const getTable = (
+ req: RaPayload,
+ resourceToTableMap?: ResourceToTableMap,
+): string => {
+ const tableName = resourceToTableMap?.[req.resource] ?? req.resource;
+ if (!tableName) throw new Error(`table name is empty`);
+ return quoteIdent(tableName);
+};
diff --git a/packages/ra-data-duckdb/src/index.ts b/packages/ra-data-duckdb/src/index.ts
new file mode 100644
index 0000000..422c601
--- /dev/null
+++ b/packages/ra-data-duckdb/src/index.ts
@@ -0,0 +1,19 @@
+export * from "./createHandler";
+export * from "./dataProvider";
+export * from "./defaultHandler";
+export * from "./deleteHandler";
+export * from "./deleteManyHandler";
+export * from "./duckdb";
+export * from "./extractOrderBy";
+export * from "./extractSkipTake";
+export * from "./extractWhere";
+export * from "./getListHandler";
+export * from "./getManyHandler";
+export * from "./getManyReferenceHandler";
+export * from "./getOneHandler";
+export * from "./getTable";
+export * from "./Http";
+export * from "./lib/NotFoundError";
+export * from "./mapPrimaryKeyToId";
+export * from "./updateHandler";
+export * from "./updateManyHandler";
diff --git a/packages/ra-data-duckdb/src/lib/NotFoundError.ts b/packages/ra-data-duckdb/src/lib/NotFoundError.ts
new file mode 100644
index 0000000..bcc1ca5
--- /dev/null
+++ b/packages/ra-data-duckdb/src/lib/NotFoundError.ts
@@ -0,0 +1,9 @@
+/** Thrown by getOne/update when no row matches the requested id. */
+export class NotFoundError extends Error {
+ readonly status = 404;
+
+ constructor(message = "Record not found") {
+ super(message);
+ this.name = "NotFoundError";
+ }
+}
diff --git a/packages/ra-data-duckdb/src/lib/SqlParams.ts b/packages/ra-data-duckdb/src/lib/SqlParams.ts
new file mode 100644
index 0000000..e8be1e2
--- /dev/null
+++ b/packages/ra-data-duckdb/src/lib/SqlParams.ts
@@ -0,0 +1,18 @@
+export class SqlParams {
+ private values: Record = {};
+ private i = 0;
+
+ add(value: unknown): string {
+ const key = `p${++this.i}`;
+ this.values[key] = value;
+ return `$${key}`;
+ }
+
+ get(): Record {
+ return this.values;
+ }
+
+ merge(other: Record): void {
+ Object.assign(this.values, other);
+ }
+}
diff --git a/packages/ra-data-duckdb/src/lib/isNotField.ts b/packages/ra-data-duckdb/src/lib/isNotField.ts
new file mode 100644
index 0000000..5e6f70d
--- /dev/null
+++ b/packages/ra-data-duckdb/src/lib/isNotField.ts
@@ -0,0 +1,7 @@
+export const isNotField = (fieldName: string) => {
+ // ignore underscored fields (_count, _sum, _avg, _min, _max and _helpers)
+ // especially in updates they would throw an error
+ if (fieldName.startsWith("_")) return true;
+
+ return false;
+};
diff --git a/packages/ra-data-duckdb/src/lib/quoteIdent.ts b/packages/ra-data-duckdb/src/lib/quoteIdent.ts
new file mode 100644
index 0000000..4b1b035
--- /dev/null
+++ b/packages/ra-data-duckdb/src/lib/quoteIdent.ts
@@ -0,0 +1,9 @@
+const IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
+
+/** Validate and double-quote a SQL identifier (table/column). */
+export const quoteIdent = (name: string): string => {
+ if (!IDENT_RE.test(name)) {
+ throw new Error(`Invalid SQL identifier: "${name}"`);
+ }
+ return `"${name}"`;
+};
diff --git a/packages/ra-data-duckdb/src/mapPrimaryKeyToId.ts b/packages/ra-data-duckdb/src/mapPrimaryKeyToId.ts
new file mode 100644
index 0000000..2f2329f
--- /dev/null
+++ b/packages/ra-data-duckdb/src/mapPrimaryKeyToId.ts
@@ -0,0 +1,32 @@
+const mapRowPrimaryKeyToId = (row: T, primaryKey: string): T => {
+ if (primaryKey === "id" || row == null || typeof row !== "object") {
+ return row;
+ }
+
+ const hasIdField = Object.prototype.hasOwnProperty.call(row, "id");
+ const existingId = (row as any).id;
+ const keyValue = (row as any)[primaryKey];
+
+ if (typeof keyValue === "undefined") {
+ return row;
+ }
+
+ if (hasIdField && typeof existingId !== "undefined" && existingId !== keyValue) {
+ console.warn(`ra-data-duckdb: overwriting existing id with value from primaryKey "${primaryKey}"`);
+ }
+
+ const { [primaryKey]: _, ...rest } = row as any;
+
+ return {
+ ...rest,
+ id: keyValue,
+ };
+};
+
+export const mapPrimaryKeyToId = (data: T, primaryKey: string): T => {
+ if (Array.isArray(data)) {
+ return data.map((row) => mapRowPrimaryKeyToId(row, primaryKey)) as T;
+ }
+
+ return mapRowPrimaryKeyToId(data, primaryKey);
+};
diff --git a/packages/ra-data-duckdb/src/server.ts b/packages/ra-data-duckdb/src/server.ts
new file mode 100644
index 0000000..c047159
--- /dev/null
+++ b/packages/ra-data-duckdb/src/server.ts
@@ -0,0 +1,18 @@
+export * from "./createHandler";
+export * from "./defaultHandler";
+export * from "./deleteHandler";
+export * from "./deleteManyHandler";
+export * from "./duckdb";
+export * from "./extractOrderBy";
+export * from "./extractSkipTake";
+export * from "./extractWhere";
+export * from "./getListHandler";
+export * from "./getManyHandler";
+export * from "./getManyReferenceHandler";
+export * from "./getOneHandler";
+export * from "./getTable";
+export * from "./Http";
+export * from "./lib/NotFoundError";
+export * from "./mapPrimaryKeyToId";
+export * from "./updateHandler";
+export * from "./updateManyHandler";
diff --git a/packages/ra-data-duckdb/src/updateHandler.ts b/packages/ra-data-duckdb/src/updateHandler.ts
new file mode 100644
index 0000000..cd73cbc
--- /dev/null
+++ b/packages/ra-data-duckdb/src/updateHandler.ts
@@ -0,0 +1,82 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import type { UpdateRequest } from "./Http";
+import { isNotField } from "./lib/isNotField";
+import { NotFoundError } from "./lib/NotFoundError";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+import { mapPrimaryKeyToId } from "./mapPrimaryKeyToId";
+
+export type UpdateOptions = {
+ debug?: boolean;
+ skipFields?: Record;
+ allowOnlyFields?: Record;
+ primaryKey?: string;
+ resourceToTableMap?: ResourceToTableMap;
+};
+
+export const reduceData = (
+ data: Record,
+ options?: UpdateOptions,
+) => {
+ const primaryKey = options?.primaryKey ?? "id";
+ const fields: Record = {};
+
+ Object.entries(data).forEach(([key, value]) => {
+ // React-admin includes its record identifier in `data`. It is used in the
+ // WHERE clause and must not be written back, especially when `id` is only
+ // an alias for a custom primary key.
+ if (key === "id") return;
+ if (primaryKey !== "id" && key === primaryKey) {
+ throw new Error(
+ `updateHandler: Field ${key} is reserved when primaryKey is configured; use params.id and omit the original primary key from writes`,
+ );
+ }
+ if (isNotField(key)) return;
+ if (options?.skipFields?.[key]) return;
+ if (options?.allowOnlyFields && !options.allowOnlyFields[key]) {
+ throw new Error(`updateHandler: Field ${key} is not allowed in update`);
+ }
+ fields[key] = value;
+ });
+
+ return fields;
+};
+
+export const updateHandler = async (
+ req: UpdateRequest,
+ db: DuckDBExecutor,
+ options?: UpdateOptions,
+) => {
+ const { id } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+ const data = reduceData(req.params.data as Record, options);
+
+ if (options?.debug) console.log("updateHandler:data", data);
+
+ const columns = Object.keys(data);
+ if (!columns.length) {
+ throw new Error("updateHandler: no fields to update");
+ }
+
+ const params = new SqlParams();
+ const setSql = columns
+ .map((col) => `${quoteIdent(col)} = ${params.add(data[col])}`)
+ .join(", ");
+ const idPlaceholder = params.add(id);
+
+ const sql = `UPDATE ${table} SET ${setSql} WHERE ${quoteIdent(primaryKey)} = ${idPlaceholder} RETURNING *`;
+
+ if (options?.debug) console.log("updateHandler:sql", sql, params.get());
+
+ const rows = await db.all(sql, params.get());
+ const updated = rows[0];
+ if (!updated) {
+ throw new NotFoundError(
+ `updateHandler: no row found in ${table} for ${primaryKey}=${id}`,
+ );
+ }
+
+ return { data: mapPrimaryKeyToId(updated, primaryKey) };
+};
diff --git a/packages/ra-data-duckdb/src/updateManyHandler.ts b/packages/ra-data-duckdb/src/updateManyHandler.ts
new file mode 100644
index 0000000..1c89030
--- /dev/null
+++ b/packages/ra-data-duckdb/src/updateManyHandler.ts
@@ -0,0 +1,42 @@
+import { DuckDBExecutor } from "./duckdb";
+import { getTable, type ResourceToTableMap } from "./getTable";
+import { UpdateManyRequest } from "./Http";
+import { quoteIdent } from "./lib/quoteIdent";
+import { SqlParams } from "./lib/SqlParams";
+import { reduceData, UpdateOptions } from "./updateHandler";
+
+export const updateManyHandler = async (
+ req: UpdateManyRequest,
+ db: DuckDBExecutor,
+ options?: UpdateOptions,
+) => {
+ const { ids } = req.params;
+ const primaryKey = options?.primaryKey ?? "id";
+ const table = getTable(req, options?.resourceToTableMap);
+ const data = reduceData(req.params.data as Record, options);
+
+ if (options?.debug) console.log("updateManyHandler:data", data);
+
+ if (!ids?.length) {
+ return { data: [] };
+ }
+
+ const columns = Object.keys(data);
+ if (!columns.length) {
+ throw new Error("updateManyHandler: no fields to update");
+ }
+
+ const params = new SqlParams();
+ const setSql = columns
+ .map((col) => `${quoteIdent(col)} = ${params.add(data[col])}`)
+ .join(", ");
+ const placeholders = ids.map((id) => params.add(id));
+
+ const sql = `UPDATE ${table} SET ${setSql} WHERE ${quoteIdent(primaryKey)} IN (${placeholders.join(", ")})`;
+
+ if (options?.debug) console.log("updateManyHandler:sql", sql, params.get());
+
+ await db.run(sql, params.get());
+
+ return { data: ids };
+};
diff --git a/packages/ra-data-duckdb/tests/handlers.test.ts b/packages/ra-data-duckdb/tests/handlers.test.ts
new file mode 100644
index 0000000..42bb1df
--- /dev/null
+++ b/packages/ra-data-duckdb/tests/handlers.test.ts
@@ -0,0 +1,384 @@
+import {
+ DuckDBConnection,
+ DuckDBInstance,
+} from "@duckdb/node-api";
+import { createHandler } from "../src/createHandler";
+import { defaultHandler } from "../src/defaultHandler";
+import {
+ DuckDBExecutor,
+ fromDuckDBConnection,
+} from "../src/duckdb";
+import { extractWhere } from "../src/extractWhere";
+import { getListHandler } from "../src/getListHandler";
+import { getOneHandler } from "../src/getOneHandler";
+import { NotFoundError } from "../src/lib/NotFoundError";
+import { quoteIdent } from "../src/lib/quoteIdent";
+import { updateHandler } from "../src/updateHandler";
+import { deleteHandler } from "../src/deleteHandler";
+
+let connection: DuckDBConnection;
+let db: DuckDBExecutor;
+
+beforeEach(async () => {
+ const instance = await DuckDBInstance.create(":memory:");
+ connection = await instance.connect();
+ db = fromDuckDBConnection(connection);
+
+ await db.run("CREATE SEQUENCE users_id_seq START 4");
+ await db.run(`
+ CREATE TABLE users (
+ id INTEGER PRIMARY KEY DEFAULT nextval('users_id_seq'),
+ name VARCHAR NOT NULL,
+ age INTEGER,
+ active BOOLEAN DEFAULT false
+ )
+ `);
+ await db.run(`
+ INSERT INTO users (id, name, age, active)
+ VALUES
+ (1, 'Alice', 30, false),
+ (2, 'Bob', 25, false),
+ (3, 'Carol', 40, false)
+ `);
+
+ await db.run("CREATE SEQUENCE custom_users_id_seq START 4");
+ await db.run(`
+ CREATE TABLE custom_users (
+ user_key INTEGER PRIMARY KEY DEFAULT nextval('custom_users_id_seq'),
+ name VARCHAR NOT NULL
+ )
+ `);
+ await db.run(`
+ INSERT INTO custom_users (user_key, name)
+ VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Carol')
+ `);
+
+ await db.run(`
+ CREATE TABLE posts (
+ id INTEGER PRIMARY KEY,
+ user_id INTEGER NOT NULL,
+ title VARCHAR NOT NULL
+ )
+ `);
+ await db.run(`
+ INSERT INTO posts VALUES
+ (1, 1, 'First'),
+ (2, 1, 'Second'),
+ (3, 2, 'Third')
+ `);
+});
+
+afterEach(() => {
+ connection.disconnectSync();
+});
+
+describe("quoteIdent", () => {
+ it("quotes valid identifiers", () => {
+ expect(quoteIdent("users")).toBe('"users"');
+ });
+
+ it("rejects invalid identifiers", () => {
+ expect(() => quoteIdent('users; drop')).toThrow();
+ });
+});
+
+describe("extractWhere", () => {
+ it("builds equality and range filters", () => {
+ const where = extractWhere({
+ method: "getList",
+ resource: "users",
+ params: {
+ filter: { age_gte: 30, name: "Al" },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ } as any);
+
+ expect(where.sql).toContain('"age" >= $p1');
+ expect(where.sql).toContain("LIKE");
+ expect(where.params.p1).toBe(30);
+ });
+
+ it("supports OR groups without colliding params", () => {
+ const where = extractWhere({
+ method: "getList",
+ resource: "users",
+ params: {
+ filter: {
+ OR: [{ age_gte: 30 }, { name_eq: "Bob" }],
+ },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ } as any);
+
+ expect(where.sql).toContain(" OR ");
+ expect(where.params.p1).toBe(30);
+ expect(where.params.p2).toBe("Bob");
+ });
+
+ it("turns empty lists into an always-false condition", () => {
+ const where = extractWhere({
+ method: "getList",
+ resource: "users",
+ params: {
+ filter: { id_in: [] },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ } as any);
+
+ expect(where).toEqual({ sql: "WHERE FALSE", params: {} });
+ });
+
+ it("uses IN for plain array filters on id-like fields", () => {
+ const where = extractWhere({
+ method: "getList",
+ resource: "posts",
+ params: {
+ filter: { id: [1, 2], user_id: [1, 2], authorId: [3] },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ } as any);
+
+ expect(where.sql).toContain('"id" IN ($p1, $p2)');
+ expect(where.sql).toContain('"user_id" IN ($p3, $p4)');
+ expect(where.sql).toContain('"authorId" IN ($p5)');
+ expect(where.params).toEqual({
+ p1: 1,
+ p2: 2,
+ p3: 1,
+ p4: 2,
+ p5: 3,
+ });
+ });
+
+ it("rejects nested filters instead of querying the wrong column", () => {
+ expect(() =>
+ extractWhere({
+ method: "getList",
+ resource: "users",
+ params: {
+ filter: { profile: { city: "Rome" } },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ } as any),
+ ).toThrow('Nested filter "profile" is not supported');
+ });
+});
+
+describe("DuckDB integration", () => {
+ it("getList applies filters, sorting, pagination, and count", async () => {
+ const result = await getListHandler(
+ {
+ method: "getList",
+ resource: "users",
+ params: {
+ filter: { age_gte: 30 },
+ pagination: { page: 1, perPage: 1 },
+ sort: { field: "age", order: "DESC" },
+ },
+ },
+ db,
+ );
+
+ expect(result.data).toEqual([
+ expect.objectContaining({ id: 3, name: "Carol" }),
+ ]);
+ expect(result.total).toBe(2);
+ });
+
+ it("getOne / create / update / delete round-trip", async () => {
+ const one = await getOneHandler(
+ { method: "getOne", resource: "users", params: { id: 1 } },
+ db,
+ );
+ expect(one.data.name).toBe("Alice");
+
+ const created = await createHandler(
+ {
+ method: "create",
+ resource: "users",
+ params: { data: { name: "Dave", age: 22 } },
+ },
+ db,
+ );
+ expect(created.data.name).toBe("Dave");
+ expect(created.data.id).toBeDefined();
+
+ const updated = await updateHandler(
+ {
+ method: "update",
+ resource: "users",
+ params: {
+ id: created.data.id,
+ data: { id: created.data.id, name: "David", age: 23 },
+ previousData: created.data,
+ },
+ },
+ db,
+ );
+ expect(updated.data.name).toBe("David");
+
+ const deleted = await deleteHandler(
+ {
+ method: "delete",
+ resource: "users",
+ params: { id: created.data.id, previousData: updated.data },
+ },
+ db,
+ );
+ expect(deleted.data.id).toBe(created.data.id);
+ });
+
+ it("handles updateMany and deleteMany against DuckDB", async () => {
+ const updated = await defaultHandler(
+ {
+ method: "updateMany",
+ resource: "users",
+ params: { ids: [1, 2], data: { active: true } },
+ },
+ db,
+ );
+ expect(updated.data).toEqual([1, 2]);
+
+ const rows = await defaultHandler(
+ {
+ method: "getMany",
+ resource: "users",
+ params: { ids: [1, 2] },
+ },
+ db,
+ );
+ expect(rows.data).toEqual([
+ expect.objectContaining({ id: 1, active: true }),
+ expect.objectContaining({ id: 2, active: true }),
+ ]);
+
+ const deleted = await defaultHandler(
+ {
+ method: "deleteMany",
+ resource: "users",
+ params: { ids: [1, 2] },
+ },
+ db,
+ );
+ expect(deleted.data).toEqual([1, 2]);
+
+ const remaining = await db.all<{ id: number }>(
+ "SELECT id FROM users ORDER BY id",
+ );
+ expect(remaining).toEqual([{ id: 3 }]);
+ });
+
+ it("maps custom primary keys without writing the synthetic id", async () => {
+ const options = {
+ resourceToTableMap: { users: "custom_users" },
+ getOne: { primaryKey: "user_key" },
+ create: { primaryKey: "user_key" },
+ update: { primaryKey: "user_key" },
+ };
+
+ const one = await defaultHandler(
+ { method: "getOne", resource: "users", params: { id: 1 } },
+ db,
+ options,
+ );
+ expect(one.data).toEqual({ id: 1, name: "Alice" });
+
+ const updated = await defaultHandler(
+ {
+ method: "update",
+ resource: "users",
+ params: {
+ id: 1,
+ data: { ...one.data, name: "Alicia" },
+ previousData: one.data,
+ },
+ },
+ db,
+ options,
+ );
+ expect(updated.data).toEqual({ id: 1, name: "Alicia" });
+
+ const created = await defaultHandler(
+ {
+ method: "create",
+ resource: "users",
+ params: { data: { id: 999, name: "Dave" } },
+ },
+ db,
+ options,
+ );
+ expect(created.data).toEqual({ id: 4, name: "Dave" });
+ });
+
+ it("gets referenced records with the correct total", async () => {
+ const result = await defaultHandler(
+ {
+ method: "getManyReference",
+ resource: "posts",
+ params: {
+ id: 1,
+ target: "user_id",
+ filter: {},
+ pagination: { page: 1, perPage: 1 },
+ sort: { field: "id", order: "DESC" },
+ },
+ },
+ db,
+ );
+
+ expect(result.data).toEqual([
+ expect.objectContaining({ id: 2, title: "Second" }),
+ ]);
+ expect("total" in result && result.total).toBe(2);
+ });
+
+ it("filters id-like array fields with IN against DuckDB", async () => {
+ const result = await getListHandler(
+ {
+ method: "getList",
+ resource: "posts",
+ params: {
+ filter: { user_id: [1] },
+ pagination: { page: 1, perPage: 10 },
+ sort: { field: "id", order: "ASC" },
+ },
+ },
+ db,
+ );
+
+ expect(result.total).toBe(2);
+ expect(result.data).toEqual([
+ expect.objectContaining({ id: 1, user_id: 1 }),
+ expect.objectContaining({ id: 2, user_id: 1 }),
+ ]);
+ });
+
+ it("throws NotFoundError when getOne/update miss the row", async () => {
+ await expect(
+ getOneHandler(
+ { method: "getOne", resource: "users", params: { id: 999 } },
+ db,
+ ),
+ ).rejects.toBeInstanceOf(NotFoundError);
+
+ await expect(
+ updateHandler(
+ {
+ method: "update",
+ resource: "users",
+ params: {
+ id: 999,
+ data: { name: "Missing" },
+ previousData: { id: 999, name: "x" },
+ },
+ },
+ db,
+ ),
+ ).rejects.toBeInstanceOf(NotFoundError);
+ });
+});
diff --git a/packages/ra-data-duckdb/tsconfig.json b/packages/ra-data-duckdb/tsconfig.json
new file mode 100644
index 0000000..884d778
--- /dev/null
+++ b/packages/ra-data-duckdb/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "display": "Default",
+ "compilerOptions": {
+ "composite": false,
+ "declaration": true,
+ "declarationMap": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "inlineSources": false,
+ "isolatedModules": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "preserveWatchOutput": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "target": "es2017",
+ "lib": ["es2017"],
+ "types": ["node", "jest"]
+ },
+ "include": ["."],
+ "exclude": ["dist", "build", "node_modules"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d76c8d6..a817cf3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -55,7 +55,7 @@ importers:
version: 18.3.1
react-admin:
specifier: ^5.7.2
- version: 5.8.3(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/utils@7.3.8(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.4)(react@18.3.1)
+ version: 5.8.3(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/utils@7.3.8(@types/react@18.3.12)(react@18.3.1))(@tanstack/react-query@5.90.21(react@18.3.1))(@types/react@18.3.12)(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.4)(react@18.3.1)
react-dom:
specifier: 18.3.1
version: 18.3.1(react@18.3.1)
@@ -82,6 +82,49 @@ importers:
specifier: 5.8.3
version: 5.8.3
+ apps/duckdb-admin:
+ dependencies:
+ '@duckdb/node-api':
+ specifier: 1.5.5-r.4
+ version: 1.5.5-r.4
+ '@mui/icons-material':
+ specifier: 5.17.1
+ version: 5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
+ '@mui/material':
+ specifier: 5.17.1
+ version: 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ next:
+ specifier: 15.3.0
+ version: 15.3.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ ra-data-duckdb:
+ specifier: workspace:*
+ version: link:../../packages/ra-data-duckdb
+ react:
+ specifier: 19.1.0
+ version: 19.1.0
+ react-admin:
+ specifier: ^5.14.1
+ version: 5.14.1(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@mui/utils@7.3.8(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(csstype@3.2.3)(react-dom@19.1.0(react@19.1.0))(react-is@19.2.4)(react@19.1.0)
+ react-dom:
+ specifier: 19.1.0
+ version: 19.1.0(react@19.1.0)
+ react-hook-form:
+ specifier: ^7.65.0
+ version: 7.71.1(react@19.1.0)
+ devDependencies:
+ '@types/node':
+ specifier: ^22
+ version: 22.14.1
+ '@types/react':
+ specifier: 19.1.1
+ version: 19.1.1
+ '@types/react-dom':
+ specifier: 19.1.2
+ version: 19.1.2(@types/react@19.1.1)
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+
apps/website:
dependencies:
'@babel/core':
@@ -169,7 +212,7 @@ importers:
devDependencies:
jest:
specifier: ^29.7.0
- version: 29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))
+ version: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
prisma:
specifier: ^6.8.2
version: 6.8.2(typescript@5.8.3)
@@ -220,6 +263,52 @@ importers:
specifier: ^5.8.3
version: 5.8.3
+ packages/ra-data-duckdb:
+ dependencies:
+ axios:
+ specifier: ^1.13.5
+ version: 1.13.5
+ deverything:
+ specifier: ^5.5.1
+ version: 5.5.1
+ devDependencies:
+ '@babel/core':
+ specifier: 7.29.0
+ version: 7.29.0
+ '@babel/preset-env':
+ specifier: ^7.29.0
+ version: 7.29.0(@babel/core@7.29.0)
+ '@babel/preset-typescript':
+ specifier: ^7.28.5
+ version: 7.28.5(@babel/core@7.29.0)
+ '@duckdb/node-api':
+ specifier: 1.5.5-r.4
+ version: 1.5.5-r.4
+ '@types/jest':
+ specifier: ^30.0.0
+ version: 30.0.0
+ '@types/node':
+ specifier: ^25.2.3
+ version: 25.2.3
+ eslint-config-custom:
+ specifier: workspace:*
+ version: link:../eslint-config-custom
+ jest:
+ specifier: ^30.2.0
+ version: 30.2.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.9.3))
+ react-admin:
+ specifier: ^5.14.1
+ version: 5.14.1(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@mui/utils@7.3.8(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(csstype@3.2.3)(react-dom@19.1.0(react@19.1.0))(react-is@19.2.4)(react@19.1.0)
+ ts-node:
+ specifier: ^10.9.2
+ version: 10.9.2(@types/node@25.2.3)(typescript@5.9.3)
+ tsup:
+ specifier: ^8.5.1
+ version: 8.5.1(jiti@2.4.2)(postcss@8.4.31)(typescript@5.9.3)
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+
packages/ra-data-simple-prisma:
dependencies:
'@prisma/client':
@@ -984,21 +1073,58 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
- '@emnapi/core@1.4.3':
- resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
+ '@duckdb/node-api@1.5.5-r.4':
+ resolution: {integrity: sha512-8v0CZNo7aM6GQCNUHERGTrZWIfss8xKzZPF3ACNhPdMMrt7UjkNI5nRQ9FTFO7Yx8ghxYxVpdotmBBMQ5vXUOA==}
+
+ '@duckdb/node-bindings-darwin-arm64@1.5.5-r.4':
+ resolution: {integrity: sha512-4OdO3pkoJzAZDnZ2iyehi67XL4+WqHPCGYWbyAsYyhGJS+WscGrAnFhMhHudMM2XF8pIEM2tuOKMmwWnTNN2wQ==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@duckdb/node-bindings-darwin-x64@1.5.5-r.4':
+ resolution: {integrity: sha512-WHg3E+TupdujG31LGujMMcmtPIdW6rqRHeihlKgJR8EMetHycoYkwYxRud0niitJvS+uV0du/6pdemzs3HG9GQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@duckdb/node-bindings-linux-arm64-musl@1.5.5-r.4':
+ resolution: {integrity: sha512-Tswnf+/XWpOcFJNUUu1fkFIX/su4tMcnNz0ZV0Nru3/CkJKIMwBh+VL4SM9YV4zPK90GC4Lm8gzafjc1qDmfyQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@duckdb/node-bindings-linux-arm64@1.5.5-r.4':
+ resolution: {integrity: sha512-VIeHMpYAKpGiWZ4QYsOhODAHDEcXcn089aKty0MFsMEKaEfRJWixKwnwXy/ba2/wwFmnPiSFhKNqygj2BrQbqw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@duckdb/node-bindings-linux-x64-musl@1.5.5-r.4':
+ resolution: {integrity: sha512-h0ixrgGHtHh+C/Fu1eAL9hX4iCf8yuyJN6Y24Gh8axXXP8UuSh0rQRAQUQTYarQ8pm2qSG/67ZYjyYYydD+J/w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@duckdb/node-bindings-linux-x64@1.5.5-r.4':
+ resolution: {integrity: sha512-EY+CL/4h8MQZd9MxTBq+98m3U9osmvHBwhE9b5fMWQGt2I6p1j8fvX0SXiwy9KBfQIbjVUOf5XvGdXncI54KSg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@duckdb/node-bindings-win32-arm64@1.5.5-r.4':
+ resolution: {integrity: sha512-uorAnySIMwWkRDuUhM1yTDxWIislnX8mndhFIw6r4VKhVW61HEOOMX5oAgkSQFII4RNWpC5PCcUAEhSATgNvVQ==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@duckdb/node-bindings-win32-x64@1.5.5-r.4':
+ resolution: {integrity: sha512-X9XGcWQ10P3mvUIaMXXk2bi94Cow7b/ziTPMKxJ0U8U3wQPxsLzEUP7D7C/KrBWINl5am2k+5SkDVyA/THUgPg==}
+ cpu: [x64]
+ os: [win32]
+
+ '@duckdb/node-bindings@1.5.5-r.4':
+ resolution: {integrity: sha512-n+4hEfjp4vny3BuWn5p1Gh5CzHaPRxoI8TzTytxL1GMlIKKrXcg/o6sSAjrsROUXGAM4WQCiWPLKnPsjJJSggg==}
'@emnapi/core@1.8.1':
resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
- '@emnapi/runtime@1.4.3':
- resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
-
'@emnapi/runtime@1.8.1':
resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
- '@emnapi/wasi-threads@1.0.2':
- resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==}
-
'@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
@@ -1767,9 +1893,6 @@ packages:
'@mui/core-downloads-tracker@5.17.1':
resolution: {integrity: sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==}
- '@mui/core-downloads-tracker@7.3.8':
- resolution: {integrity: sha512-s9UHZo7QJVly7gNArEZkbbsimHqJZhElgBpXIJdehZ4OWXt+CCr0SBDgUCDJnQrqpd1dWK2dLq5rmO4mCBmI3w==}
-
'@mui/icons-material@5.17.1':
resolution: {integrity: sha512-CN86LocjkunFGG0yPlO4bgqHkNGgaEOEc3X/jG5Bzm401qYw79/SaLrofA7yAKCCXAGdIGnLoMHohc3+ubs95A==}
engines: {node: '>=12.0.0'}
@@ -1781,17 +1904,6 @@ packages:
'@types/react':
optional: true
- '@mui/icons-material@7.3.8':
- resolution: {integrity: sha512-88sWg/UJc1X82OMO+ISR4E3P58I3BjFVg0qkmDu7OWlN8VijneZD3ylFA+ImxuPjMHW3SHosfSJYy1fztoz0fw==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- '@mui/material': ^7.3.8
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@types/react':
- optional: true
-
'@mui/material@5.17.1':
resolution: {integrity: sha512-2B33kQf+GmPnrvXXweWAx+crbiUEsxCdCN979QDYnlH9ox4pd+0/IBriWLV+l6ORoBF60w39cWjFnJYGFdzXcw==}
engines: {node: '>=12.0.0'}
@@ -1809,26 +1921,6 @@ packages:
'@types/react':
optional: true
- '@mui/material@7.3.8':
- resolution: {integrity: sha512-QKd1RhDXE1hf2sQDNayA9ic9jGkEgvZOf0tTkJxlBPG8ns8aS4rS8WwYURw2x5y3739p0HauUXX9WbH7UufFLw==}
- engines: {node: '>=14.0.0'}
- peerDependencies:
- '@emotion/react': ^11.5.0
- '@emotion/styled': ^11.3.0
- '@mui/material-pigment-css': ^7.3.8
- '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0
- react: ^17.0.0 || ^18.0.0 || ^19.0.0
- react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
- peerDependenciesMeta:
- '@emotion/react':
- optional: true
- '@emotion/styled':
- optional: true
- '@mui/material-pigment-css':
- optional: true
- '@types/react':
- optional: true
-
'@mui/private-theming@5.17.1':
resolution: {integrity: sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==}
engines: {node: '>=12.0.0'}
@@ -1954,9 +2046,6 @@ packages:
'@types/react':
optional: true
- '@napi-rs/wasm-runtime@0.2.10':
- resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==}
-
'@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
@@ -2331,17 +2420,9 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
- '@tanstack/query-core@5.79.0':
- resolution: {integrity: sha512-s+epTqqLM0/TbJzMAK7OEhZIzh63P9sWz5HEFc5XHL4FvKQXQkcjI8F3nee+H/xVVn7mrP610nVXwOytTSYd0w==}
-
'@tanstack/query-core@5.90.20':
resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==}
- '@tanstack/react-query@5.79.0':
- resolution: {integrity: sha512-DjC4JIYZnYzxaTzbg3osOU63VNLP67dOrWet2cZvXgmgwAXNxfS52AMq86M5++ILuzW+BqTUEVMTjhrZ7/XBuA==}
- peerDependencies:
- react: ^18 || ^19
-
'@tanstack/react-query@5.90.21':
resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==}
peerDependencies:
@@ -2362,9 +2443,6 @@ packages:
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
- '@tybys/wasm-util@0.9.0':
- resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
-
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@@ -2374,9 +2452,6 @@ packages:
'@types/babel__template@7.4.4':
resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
- '@types/babel__traverse@7.20.7':
- resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
-
'@types/babel__traverse@7.28.0':
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
@@ -2422,9 +2497,6 @@ packages:
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
- '@types/prop-types@15.7.14':
- resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
-
'@types/prop-types@15.7.15':
resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
@@ -2521,6 +2593,7 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ deprecated: Potential CWE-502 - Update to 1.3.1 or higher
'@unrs/resolver-binding-android-arm-eabi@1.11.1':
resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
@@ -2537,171 +2610,86 @@ packages:
cpu: [arm64]
os: [darwin]
- '@unrs/resolver-binding-darwin-arm64@1.7.8':
- resolution: {integrity: sha512-rsRK8T7yxraNRDmpFLZCWqpea6OlXPNRRCjWMx24O1V86KFol7u2gj9zJCv6zB1oJjtnzWceuqdnCgOipFcJPA==}
- cpu: [arm64]
- os: [darwin]
-
'@unrs/resolver-binding-darwin-x64@1.11.1':
resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
cpu: [x64]
os: [darwin]
- '@unrs/resolver-binding-darwin-x64@1.7.8':
- resolution: {integrity: sha512-16yEMWa+Olqkk8Kl6Bu0ltT5OgEedkSAsxcz1B3yEctrDYp3EMBu/5PPAGhWVGnwhtf3hNe3y15gfYBAjOv5tQ==}
- cpu: [x64]
- os: [darwin]
-
'@unrs/resolver-binding-freebsd-x64@1.11.1':
resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
cpu: [x64]
os: [freebsd]
- '@unrs/resolver-binding-freebsd-x64@1.7.8':
- resolution: {integrity: sha512-ST4uqF6FmdZQgv+Q73FU1uHzppeT4mhX3IIEmHlLObrv5Ep50olWRz0iQ4PWovadjHMTAmpuJAGaAuCZYb7UAQ==}
- cpu: [x64]
- os: [freebsd]
-
'@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
cpu: [arm]
os: [linux]
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.8':
- resolution: {integrity: sha512-Z/A/4Rm2VWku2g25C3tVb986fY6unx5jaaCFpx1pbAj0OKkyuJ5wcQLHvNbIcJ9qhiYwXfrkB7JNlxrAbg7YFg==}
- cpu: [arm]
- os: [linux]
-
'@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
cpu: [arm]
os: [linux]
- '@unrs/resolver-binding-linux-arm-musleabihf@1.7.8':
- resolution: {integrity: sha512-HN0p7o38qKmDo3bZUiQa6gP7Qhf0sKgJZtRfSHi6JL2Gi4NaUVF0EO1sQ1RHbeQ4VvfjUGMh3QE5dxEh06BgQQ==}
- cpu: [arm]
- os: [linux]
-
'@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
cpu: [arm64]
os: [linux]
- '@unrs/resolver-binding-linux-arm64-gnu@1.7.8':
- resolution: {integrity: sha512-HsoVqDBt9G69AN0KWeDNJW+7i8KFlwxrbbnJffgTGpiZd6Jw+Q95sqkXp8y458KhKduKLmXfVZGnKBTNxAgPjw==}
- cpu: [arm64]
- os: [linux]
-
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
cpu: [arm64]
os: [linux]
- '@unrs/resolver-binding-linux-arm64-musl@1.7.8':
- resolution: {integrity: sha512-VfR2yTDUbUvn+e/Aw22CC9fQg9zdShHAfwWctNBdOk7w9CHWl2OtYlcMvjzMAns8QxoHQoqn3/CEnZ4Ts7hfrA==}
- cpu: [arm64]
- os: [linux]
-
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
cpu: [ppc64]
os: [linux]
- '@unrs/resolver-binding-linux-ppc64-gnu@1.7.8':
- resolution: {integrity: sha512-xUauVQNz4uDgs4UJJiUAwMe3N0PA0wvtImh7V0IFu++UKZJhssXbKHBRR4ecUJpUHCX2bc4Wc8sGsB6P+7BANg==}
- cpu: [ppc64]
- os: [linux]
-
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
cpu: [riscv64]
os: [linux]
- '@unrs/resolver-binding-linux-riscv64-gnu@1.7.8':
- resolution: {integrity: sha512-GqyIB+CuSHGhhc8ph5RrurtNetYJjb6SctSHafqmdGcRuGi6uyTMR8l18hMEhZFsXdFMc/MpInPLvmNV22xn+A==}
- cpu: [riscv64]
- os: [linux]
-
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
cpu: [riscv64]
os: [linux]
- '@unrs/resolver-binding-linux-riscv64-musl@1.7.8':
- resolution: {integrity: sha512-eEU3rWIFRv60xaAbtsgwHNWRZGD7cqkpCvNtio/f1TjEE3HfKLzPNB24fA9X/8ZXQrGldE65b7UKK3PmO4eWIQ==}
- cpu: [riscv64]
- os: [linux]
-
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
cpu: [s390x]
os: [linux]
- '@unrs/resolver-binding-linux-s390x-gnu@1.7.8':
- resolution: {integrity: sha512-GVLI0f4I4TlLqEUoOFvTWedLsJEdvsD0+sxhdvQ5s+N+m2DSynTs8h9jxR0qQbKlpHWpc2Ortz3z48NHRT4l+w==}
- cpu: [s390x]
- os: [linux]
-
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
cpu: [x64]
os: [linux]
- '@unrs/resolver-binding-linux-x64-gnu@1.7.8':
- resolution: {integrity: sha512-GX1pZ/4ncUreB0Rlp1l7bhKAZ8ZmvDIgXdeb5V2iK0eRRF332+6gRfR/r5LK88xfbtOpsmRHU6mQ4N8ZnwvGEA==}
- cpu: [x64]
- os: [linux]
-
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
cpu: [x64]
os: [linux]
- '@unrs/resolver-binding-linux-x64-musl@1.7.8':
- resolution: {integrity: sha512-n1N84MnsvDupzVuYqJGj+2pb9s8BI1A5RgXHvtVFHedGZVBCFjDpQVRlmsFMt6xZiKwDPaqsM16O/1isCUGt7w==}
- cpu: [x64]
- os: [linux]
-
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
- '@unrs/resolver-binding-wasm32-wasi@1.7.8':
- resolution: {integrity: sha512-x94WnaU5g+pCPDVedfnXzoG6lCOF2xFGebNwhtbJCWfceE94Zj8aysSxdxotlrZrxnz5D3ijtyFUYtpz04n39Q==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
-
'@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
cpu: [arm64]
os: [win32]
- '@unrs/resolver-binding-win32-arm64-msvc@1.7.8':
- resolution: {integrity: sha512-vst2u8EJZ5L6jhJ6iLis3w9rg16aYqRxQuBAMYQRVrPMI43693hLP7DuqyOBRKgsQXy9/jgh204k0ViHkqQgdg==}
- cpu: [arm64]
- os: [win32]
-
'@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
cpu: [ia32]
os: [win32]
- '@unrs/resolver-binding-win32-ia32-msvc@1.7.8':
- resolution: {integrity: sha512-yb3LZOLMFqnA+/ShlE1E5bpYPGDsA590VHHJPB+efnyowT776GJXBoh82em6O9WmYBUq57YblGTcMYAFBm72HA==}
- cpu: [ia32]
- os: [win32]
-
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
cpu: [x64]
os: [win32]
- '@unrs/resolver-binding-win32-x64-msvc@1.7.8':
- resolution: {integrity: sha512-hHKFx+opG5BA3/owMXon8ypwSotBGTdblG6oda/iOu9+OEYnk0cxD2uIcGyGT8jCK578kV+xMrNxqbn8Zjlpgw==}
- cpu: [x64]
- os: [win32]
-
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -2711,11 +2699,6 @@ packages:
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
engines: {node: '>=0.4.0'}
- acorn@8.14.1:
- resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
- engines: {node: '>=0.4.0'}
- hasBin: true
-
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
@@ -2994,12 +2977,6 @@ packages:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
- caniuse-lite@1.0.30001720:
- resolution: {integrity: sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==}
-
- caniuse-lite@1.0.30001735:
- resolution: {integrity: sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==}
-
caniuse-lite@1.0.30001769:
resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==}
@@ -3225,8 +3202,8 @@ packages:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
- detect-libc@2.0.4:
- resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
detect-newline@3.1.0:
@@ -3459,6 +3436,7 @@ packages:
eslint@9.24.0:
resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
peerDependencies:
jiti: '*'
@@ -4481,11 +4459,6 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- napi-postinstall@0.2.4:
- resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- hasBin: true
-
napi-postinstall@0.3.4:
resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -4910,12 +4883,6 @@ packages:
peerDependencies:
react: '>=16.13.1'
- react-hook-form@7.56.4:
- resolution: {integrity: sha512-Rob7Ftz2vyZ/ZGsQZPaRdIefkgOSrQSPXfqBdvOPwJfoGnjwRJUs7EM7Kc1mcoDv3NOtqBzPGbcMB8CGn9CKgw==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- react: ^16.8.0 || ^17 || ^18 || ^19
-
react-hook-form@7.71.1:
resolution: {integrity: sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==}
engines: {node: '>=18.0.0'}
@@ -5554,9 +5521,6 @@ packages:
unrs-resolver@1.11.1:
resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
- unrs-resolver@1.7.8:
- resolution: {integrity: sha512-2zsXwyOXmCX9nGz4vhtZRYhe30V78heAv+KDc21A/KMdovGHbZcixeD5JHEF0DrFXzdytwuzYclcPbvp8A3Jlw==}
-
update-browserslist-db@1.1.3:
resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
hasBin: true
@@ -5574,6 +5538,7 @@ packages:
uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+ deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
v8-compile-cache-lib@3.0.1:
@@ -5732,8 +5697,8 @@ snapshots:
'@babel/generator@7.27.3':
dependencies:
- '@babel/parser': 7.27.4
- '@babel/types': 7.27.3
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
jsesc: 3.1.0
@@ -5809,7 +5774,7 @@ snapshots:
'@babel/helper-module-imports@7.27.1':
dependencies:
'@babel/traverse': 7.29.0
- '@babel/types': 7.27.3
+ '@babel/types': 7.29.0
transitivePeerDependencies:
- supports-color
@@ -5825,7 +5790,7 @@ snapshots:
'@babel/core': 7.26.10
'@babel/helper-module-imports': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
- '@babel/traverse': 7.27.4
+ '@babel/traverse': 7.29.0
transitivePeerDependencies:
- supports-color
@@ -5887,8 +5852,8 @@ snapshots:
'@babel/helpers@7.27.4':
dependencies:
- '@babel/template': 7.27.2
- '@babel/types': 7.27.3
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
'@babel/helpers@7.28.6':
dependencies:
@@ -5897,7 +5862,7 @@ snapshots:
'@babel/parser@7.27.4':
dependencies:
- '@babel/types': 7.27.3
+ '@babel/types': 7.29.0
'@babel/parser@7.29.0':
dependencies:
@@ -6482,9 +6447,9 @@ snapshots:
'@babel/template@7.27.2':
dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/parser': 7.27.4
- '@babel/types': 7.27.3
+ '@babel/code-frame': 7.29.0
+ '@babel/parser': 7.29.0
+ '@babel/types': 7.29.0
'@babel/template@7.28.6':
dependencies:
@@ -6494,12 +6459,12 @@ snapshots:
'@babel/traverse@7.27.4':
dependencies:
- '@babel/code-frame': 7.27.1
- '@babel/generator': 7.27.3
- '@babel/parser': 7.27.4
- '@babel/template': 7.27.2
- '@babel/types': 7.27.3
- debug: 4.4.1
+ '@babel/code-frame': 7.29.0
+ '@babel/generator': 7.29.1
+ '@babel/parser': 7.29.0
+ '@babel/template': 7.28.6
+ '@babel/types': 7.29.0
+ debug: 4.4.3
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -6675,29 +6640,54 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
- '@emnapi/core@1.4.3':
+ '@duckdb/node-api@1.5.5-r.4':
dependencies:
- '@emnapi/wasi-threads': 1.0.2
- tslib: 2.8.1
+ '@duckdb/node-bindings': 1.5.5-r.4
+
+ '@duckdb/node-bindings-darwin-arm64@1.5.5-r.4':
optional: true
- '@emnapi/core@1.8.1':
- dependencies:
- '@emnapi/wasi-threads': 1.1.0
- tslib: 2.8.1
+ '@duckdb/node-bindings-darwin-x64@1.5.5-r.4':
optional: true
- '@emnapi/runtime@1.4.3':
- dependencies:
- tslib: 2.8.1
+ '@duckdb/node-bindings-linux-arm64-musl@1.5.5-r.4':
optional: true
- '@emnapi/runtime@1.8.1':
+ '@duckdb/node-bindings-linux-arm64@1.5.5-r.4':
+ optional: true
+
+ '@duckdb/node-bindings-linux-x64-musl@1.5.5-r.4':
+ optional: true
+
+ '@duckdb/node-bindings-linux-x64@1.5.5-r.4':
+ optional: true
+
+ '@duckdb/node-bindings-win32-arm64@1.5.5-r.4':
+ optional: true
+
+ '@duckdb/node-bindings-win32-x64@1.5.5-r.4':
+ optional: true
+
+ '@duckdb/node-bindings@1.5.5-r.4':
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ '@duckdb/node-bindings-darwin-arm64': 1.5.5-r.4
+ '@duckdb/node-bindings-darwin-x64': 1.5.5-r.4
+ '@duckdb/node-bindings-linux-arm64': 1.5.5-r.4
+ '@duckdb/node-bindings-linux-arm64-musl': 1.5.5-r.4
+ '@duckdb/node-bindings-linux-x64': 1.5.5-r.4
+ '@duckdb/node-bindings-linux-x64-musl': 1.5.5-r.4
+ '@duckdb/node-bindings-win32-arm64': 1.5.5-r.4
+ '@duckdb/node-bindings-win32-x64': 1.5.5-r.4
+
+ '@emnapi/core@1.8.1':
dependencies:
+ '@emnapi/wasi-threads': 1.1.0
tslib: 2.8.1
optional: true
- '@emnapi/wasi-threads@1.0.2':
+ '@emnapi/runtime@1.8.1':
dependencies:
tslib: 2.8.1
optional: true
@@ -6710,7 +6700,7 @@ snapshots:
'@emotion/babel-plugin@11.13.5':
dependencies:
'@babel/helper-module-imports': 7.28.6
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@emotion/hash': 0.9.2
'@emotion/memoize': 0.9.0
'@emotion/serialize': 1.3.3
@@ -6781,13 +6771,13 @@ snapshots:
'@emotion/memoize': 0.9.0
'@emotion/unitless': 0.10.0
'@emotion/utils': 1.4.2
- csstype: 3.1.3
+ csstype: 3.2.3
'@emotion/sheet@1.4.0': {}
'@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@emotion/babel-plugin': 11.13.5
'@emotion/is-prop-valid': 1.3.1
'@emotion/react': 11.14.0(@types/react@18.3.12)(react@18.3.1)
@@ -6992,7 +6982,7 @@ snapshots:
'@eslint/config-array@0.20.0':
dependencies:
'@eslint/object-schema': 2.1.6
- debug: 4.4.1
+ debug: 4.4.3
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
@@ -7010,7 +7000,7 @@ snapshots:
'@eslint/eslintrc@3.3.1':
dependencies:
ajv: 6.12.6
- debug: 4.4.1
+ debug: 4.4.3
espree: 10.3.0
globals: 14.0.0
ignore: 5.3.2
@@ -7112,7 +7102,7 @@ snapshots:
'@img/sharp-wasm32@0.34.2':
dependencies:
- '@emnapi/runtime': 1.4.3
+ '@emnapi/runtime': 1.8.1
optional: true
'@img/sharp-win32-arm64@0.34.2':
@@ -7153,7 +7143,7 @@ snapshots:
'@jest/console@29.7.0':
dependencies:
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
jest-message-util: 29.7.0
jest-util: 29.7.0
@@ -7162,12 +7152,47 @@ snapshots:
'@jest/console@30.2.0':
dependencies:
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
jest-message-util: 30.2.0
jest-util: 30.2.0
slash: 3.0.0
+ '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))':
+ dependencies:
+ '@jest/console': 29.7.0
+ '@jest/reporters': 29.7.0
+ '@jest/test-result': 29.7.0
+ '@jest/transform': 29.7.0
+ '@jest/types': 29.6.3
+ '@types/node': 22.14.1
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-changed-files: 29.7.0
+ jest-config: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ jest-haste-map: 29.7.0
+ jest-message-util: 29.7.0
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-resolve-dependencies: 29.7.0
+ jest-runner: 29.7.0
+ jest-runtime: 29.7.0
+ jest-snapshot: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ jest-watcher: 29.7.0
+ micromatch: 4.0.8
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-ansi: 6.0.1
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
'@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))':
dependencies:
'@jest/console': 29.7.0
@@ -7175,14 +7200,14 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.9.0
exit: 0.1.2
graceful-fs: 4.2.11
jest-changed-files: 29.7.0
- jest-config: 29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))
+ jest-config: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))
jest-haste-map: 29.7.0
jest-message-util: 29.7.0
jest-regex-util: 29.6.3
@@ -7211,14 +7236,14 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 4.4.0
exit-x: 0.2.2
graceful-fs: 4.2.11
jest-changed-files: 30.2.0
- jest-config: 30.2.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.9.3))
+ jest-config: 30.2.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.9.3))
jest-haste-map: 30.2.0
jest-message-util: 30.2.0
jest-regex-util: 30.0.1
@@ -7245,14 +7270,14 @@ snapshots:
dependencies:
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-mock: 29.7.0
'@jest/environment@30.2.0':
dependencies:
'@jest/fake-timers': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-mock: 30.2.0
'@jest/expect-utils@29.7.0':
@@ -7281,7 +7306,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@sinonjs/fake-timers': 10.3.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-message-util: 29.7.0
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -7290,7 +7315,7 @@ snapshots:
dependencies:
'@jest/types': 30.2.0
'@sinonjs/fake-timers': 13.0.5
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-message-util: 30.2.0
jest-mock: 30.2.0
jest-util: 30.2.0
@@ -7317,7 +7342,7 @@ snapshots:
'@jest/pattern@30.0.1':
dependencies:
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-regex-util: 30.0.1
'@jest/reporters@29.7.0':
@@ -7328,7 +7353,7 @@ snapshots:
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
'@jridgewell/trace-mapping': 0.3.31
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
collect-v8-coverage: 1.0.2
exit: 0.1.2
@@ -7357,7 +7382,7 @@ snapshots:
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
'@jridgewell/trace-mapping': 0.3.31
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
collect-v8-coverage: 1.0.3
exit-x: 0.2.2
@@ -7477,7 +7502,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -7487,7 +7512,7 @@ snapshots:
'@jest/schemas': 30.0.5
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
'@types/yargs': 17.0.35
chalk: 4.1.2
@@ -7553,35 +7578,25 @@ snapshots:
'@mui/core-downloads-tracker@5.17.1': {}
- '@mui/core-downloads-tracker@7.3.8': {}
-
'@mui/icons-material@5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react: 18.3.1
optionalDependencies:
'@types/react': 18.3.12
'@mui/icons-material@5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)':
- dependencies:
- '@babel/runtime': 7.27.4
- '@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- react: 19.1.0
- optionalDependencies:
- '@types/react': 19.1.1
-
- '@mui/icons-material@7.3.8(@mui/material@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)':
dependencies:
'@babel/runtime': 7.28.6
- '@mui/material': 7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
optionalDependencies:
'@types/react': 19.1.1
'@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/core-downloads-tracker': 5.17.1
'@mui/system': 5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.12)
@@ -7589,11 +7604,11 @@ snapshots:
'@popperjs/core': 2.11.8
'@types/react-transition-group': 4.4.12(@types/react@18.3.12)
clsx: 2.1.1
- csstype: 3.1.3
+ csstype: 3.2.3
prop-types: 15.8.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- react-is: 19.1.0
+ react-is: 19.2.4
react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@18.3.12)(react@18.3.1)
@@ -7602,7 +7617,7 @@ snapshots:
'@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/core-downloads-tracker': 5.17.1
'@mui/system': 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
'@mui/types': 7.2.24(@types/react@19.1.1)
@@ -7610,27 +7625,6 @@ snapshots:
'@popperjs/core': 2.11.8
'@types/react-transition-group': 4.4.12(@types/react@19.1.1)
clsx: 2.1.1
- csstype: 3.1.3
- prop-types: 15.8.1
- react: 19.1.0
- react-dom: 19.1.0(react@19.1.0)
- react-is: 19.1.0
- react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- optionalDependencies:
- '@emotion/react': 11.14.0(@types/react@19.1.1)(react@19.1.0)
- '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
- '@types/react': 19.1.1
-
- '@mui/material@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
- dependencies:
- '@babel/runtime': 7.28.6
- '@mui/core-downloads-tracker': 7.3.8
- '@mui/system': 7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
- '@mui/types': 7.4.11(@types/react@19.1.1)
- '@mui/utils': 7.3.8(@types/react@19.1.1)(react@19.1.0)
- '@popperjs/core': 2.11.8
- '@types/react-transition-group': 4.4.12(@types/react@19.1.1)
- clsx: 2.1.1
csstype: 3.2.3
prop-types: 15.8.1
react: 19.1.0
@@ -7680,9 +7674,9 @@ snapshots:
'@mui/styled-engine@5.16.14(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@emotion/cache': 11.14.0
- csstype: 3.1.3
+ csstype: 3.2.3
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
@@ -7691,9 +7685,9 @@ snapshots:
'@mui/styled-engine@5.16.14(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(react@19.1.0)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@emotion/cache': 11.14.0
- csstype: 3.1.3
+ csstype: 3.2.3
prop-types: 15.8.1
react: 19.1.0
optionalDependencies:
@@ -7774,13 +7768,13 @@ snapshots:
'@mui/system@5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/private-theming': 5.17.1(@types/react@18.3.12)(react@18.3.1)
'@mui/styled-engine': 5.16.14(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)
'@mui/types': 7.2.24(@types/react@18.3.12)
'@mui/utils': 5.17.1(@types/react@18.3.12)(react@18.3.1)
clsx: 2.1.1
- csstype: 3.1.3
+ csstype: 3.2.3
prop-types: 15.8.1
react: 18.3.1
optionalDependencies:
@@ -7790,13 +7784,13 @@ snapshots:
'@mui/system@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/private-theming': 5.17.1(@types/react@19.1.1)(react@19.1.0)
'@mui/styled-engine': 5.16.14(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(react@19.1.0)
'@mui/types': 7.2.24(@types/react@19.1.1)
'@mui/utils': 5.17.1(@types/react@19.1.1)(react@19.1.0)
clsx: 2.1.1
- csstype: 3.1.3
+ csstype: 3.2.3
prop-types: 15.8.1
react: 19.1.0
optionalDependencies:
@@ -7858,9 +7852,9 @@ snapshots:
'@mui/utils@5.17.1(@types/react@18.3.12)(react@18.3.1)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/types': 7.2.24(@types/react@18.3.12)
- '@types/prop-types': 15.7.14
+ '@types/prop-types': 15.7.15
clsx: 2.1.1
prop-types: 15.8.1
react: 18.3.1
@@ -7870,9 +7864,9 @@ snapshots:
'@mui/utils@5.17.1(@types/react@19.1.1)(react@19.1.0)':
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
'@mui/types': 7.2.24(@types/react@19.1.1)
- '@types/prop-types': 15.7.14
+ '@types/prop-types': 15.7.15
clsx: 2.1.1
prop-types: 15.8.1
react: 19.1.0
@@ -7904,13 +7898,6 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.1
- '@napi-rs/wasm-runtime@0.2.10':
- dependencies:
- '@emnapi/core': 1.4.3
- '@emnapi/runtime': 1.4.3
- '@tybys/wasm-util': 0.9.0
- optional: true
-
'@napi-rs/wasm-runtime@0.2.12':
dependencies:
'@emnapi/core': 1.8.1
@@ -8171,13 +8158,11 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@tanstack/query-core@5.79.0': {}
-
'@tanstack/query-core@5.90.20': {}
- '@tanstack/react-query@5.79.0(react@18.3.1)':
+ '@tanstack/react-query@5.90.21(react@18.3.1)':
dependencies:
- '@tanstack/query-core': 5.79.0
+ '@tanstack/query-core': 5.90.20
react: 18.3.1
'@tanstack/react-query@5.90.21(react@19.1.0)':
@@ -8198,11 +8183,6 @@ snapshots:
tslib: 2.8.1
optional: true
- '@tybys/wasm-util@0.9.0':
- dependencies:
- tslib: 2.8.1
- optional: true
-
'@types/babel__core@7.20.5':
dependencies:
'@babel/parser': 7.29.0
@@ -8220,10 +8200,6 @@ snapshots:
'@babel/parser': 7.29.0
'@babel/types': 7.29.0
- '@types/babel__traverse@7.20.7':
- dependencies:
- '@babel/types': 7.29.0
-
'@types/babel__traverse@7.28.0':
dependencies:
'@babel/types': 7.29.0
@@ -8234,7 +8210,7 @@ snapshots:
'@types/graceful-fs@4.1.9':
dependencies:
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
'@types/istanbul-lib-coverage@2.0.6': {}
@@ -8269,8 +8245,6 @@ snapshots:
'@types/parse-json@4.0.2': {}
- '@types/prop-types@15.7.14': {}
-
'@types/prop-types@15.7.15': {}
'@types/react-dom@18.3.1':
@@ -8291,12 +8265,12 @@ snapshots:
'@types/react@18.3.12':
dependencies:
- '@types/prop-types': 15.7.14
- csstype: 3.1.3
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
'@types/react@19.1.1':
dependencies:
- csstype: 3.1.3
+ csstype: 3.2.3
'@types/stack-utils@2.0.3': {}
@@ -8496,119 +8470,64 @@ snapshots:
'@unrs/resolver-binding-darwin-arm64@1.11.1':
optional: true
- '@unrs/resolver-binding-darwin-arm64@1.7.8':
- optional: true
-
'@unrs/resolver-binding-darwin-x64@1.11.1':
optional: true
- '@unrs/resolver-binding-darwin-x64@1.7.8':
- optional: true
-
'@unrs/resolver-binding-freebsd-x64@1.11.1':
optional: true
- '@unrs/resolver-binding-freebsd-x64@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-arm-musleabihf@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-arm64-gnu@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-arm64-musl@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-ppc64-gnu@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-riscv64-gnu@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-riscv64-musl@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-s390x-gnu@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-x64-gnu@1.7.8':
- optional: true
-
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
optional: true
- '@unrs/resolver-binding-linux-x64-musl@1.7.8':
- optional: true
-
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
dependencies:
'@napi-rs/wasm-runtime': 0.2.12
optional: true
- '@unrs/resolver-binding-wasm32-wasi@1.7.8':
- dependencies:
- '@napi-rs/wasm-runtime': 0.2.10
- optional: true
-
'@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
optional: true
- '@unrs/resolver-binding-win32-arm64-msvc@1.7.8':
- optional: true
-
'@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
optional: true
- '@unrs/resolver-binding-win32-ia32-msvc@1.7.8':
- optional: true
-
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@unrs/resolver-binding-win32-x64-msvc@1.7.8':
- optional: true
-
- acorn-jsx@5.3.2(acorn@8.14.1):
+ acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
- acorn: 8.14.1
+ acorn: 8.15.0
acorn-walk@8.3.4:
dependencies:
acorn: 8.15.0
- acorn@8.14.1: {}
-
acorn@8.15.0: {}
ajv@6.12.6:
@@ -8807,7 +8726,7 @@ snapshots:
'@babel/template': 7.28.6
'@babel/types': 7.29.0
'@types/babel__core': 7.20.5
- '@types/babel__traverse': 7.20.7
+ '@types/babel__traverse': 7.28.0
babel-plugin-jest-hoist@30.2.0:
dependencies:
@@ -8926,7 +8845,7 @@ snapshots:
browserslist@4.25.2:
dependencies:
- caniuse-lite: 1.0.30001735
+ caniuse-lite: 1.0.30001769
electron-to-chromium: 1.5.203
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.2)
@@ -8984,10 +8903,6 @@ snapshots:
camelcase@6.3.0: {}
- caniuse-lite@1.0.30001720: {}
-
- caniuse-lite@1.0.30001735: {}
-
caniuse-lite@1.0.30001769: {}
chalk@4.1.2:
@@ -9083,6 +8998,21 @@ snapshots:
path-type: 4.0.0
yaml: 1.10.2
+ create-jest@29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3)):
+ dependencies:
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ exit: 0.1.2
+ graceful-fs: 4.2.11
+ jest-config: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ jest-util: 29.7.0
+ prompts: 2.4.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
create-jest@29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3)):
dependencies:
'@jest/types': 29.6.3
@@ -9110,7 +9040,7 @@ snapshots:
css-vendor@2.0.8:
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
is-in-browser: 1.1.3
csstype@3.1.3: {}
@@ -9181,8 +9111,7 @@ snapshots:
detect-indent@6.1.0: {}
- detect-libc@2.0.4:
- optional: true
+ detect-libc@2.1.2: {}
detect-newline@3.1.0: {}
@@ -9204,8 +9133,8 @@ snapshots:
dom-helpers@5.2.1:
dependencies:
- '@babel/runtime': 7.27.4
- csstype: 3.1.3
+ '@babel/runtime': 7.28.6
+ csstype: 3.2.3
dompurify@3.2.6:
optionalDependencies:
@@ -9462,7 +9391,7 @@ snapshots:
dependencies:
debug: 3.2.7
is-core-module: 2.16.1
- resolve: 1.22.10
+ resolve: 1.22.11
transitivePeerDependencies:
- supports-color
@@ -9474,8 +9403,8 @@ snapshots:
get-tsconfig: 4.10.1
is-bun-module: 2.0.0
stable-hash: 0.0.5
- tinyglobby: 0.2.14
- unrs-resolver: 1.7.8
+ tinyglobby: 0.2.15
+ unrs-resolver: 1.11.1
optionalDependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.0(eslint@9.24.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.24.0(jiti@2.4.2))
transitivePeerDependencies:
@@ -9665,8 +9594,8 @@ snapshots:
espree@10.3.0:
dependencies:
- acorn: 8.14.1
- acorn-jsx: 5.3.2(acorn@8.14.1)
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
eslint-visitor-keys: 4.2.0
esprima@4.0.1: {}
@@ -10245,7 +10174,7 @@ snapshots:
'@jest/expect': 29.7.0
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
co: 4.6.0
dedent: 1.6.0(babel-plugin-macros@3.1.0)
@@ -10271,7 +10200,7 @@ snapshots:
'@jest/expect': 30.2.0
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
co: 4.6.0
dedent: 1.7.1(babel-plugin-macros@3.1.0)
@@ -10291,6 +10220,25 @@ snapshots:
- babel-plugin-macros
- supports-color
+ jest-cli@29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3)):
+ dependencies:
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ '@jest/test-result': 29.7.0
+ '@jest/types': 29.6.3
+ chalk: 4.1.2
+ create-jest: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ exit: 0.1.2
+ import-local: 3.2.0
+ jest-config: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
jest-cli@29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3)):
dependencies:
'@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))
@@ -10329,6 +10277,68 @@ snapshots:
- supports-color
- ts-node
+ jest-config@29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3)):
+ dependencies:
+ '@babel/core': 7.29.0
+ '@jest/test-sequencer': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.29.0)
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-circus: 29.7.0(babel-plugin-macros@3.1.0)
+ jest-environment-node: 29.7.0
+ jest-get-type: 29.6.3
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-runner: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.14.1
+ ts-node: 10.9.2(@types/node@22.14.1)(typescript@5.8.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-config@29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3)):
+ dependencies:
+ '@babel/core': 7.29.0
+ '@jest/test-sequencer': 29.7.0
+ '@jest/types': 29.6.3
+ babel-jest: 29.7.0(@babel/core@7.29.0)
+ chalk: 4.1.2
+ ci-info: 3.9.0
+ deepmerge: 4.3.1
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ jest-circus: 29.7.0(babel-plugin-macros@3.1.0)
+ jest-environment-node: 29.7.0
+ jest-get-type: 29.6.3
+ jest-regex-util: 29.6.3
+ jest-resolve: 29.7.0
+ jest-runner: 29.7.0
+ jest-util: 29.7.0
+ jest-validate: 29.7.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 29.7.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.14.1
+ ts-node: 10.9.2(@types/node@25.2.3)(typescript@5.8.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
jest-config@29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3)):
dependencies:
'@babel/core': 7.29.0
@@ -10360,6 +10370,39 @@ snapshots:
- babel-plugin-macros
- supports-color
+ jest-config@30.2.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.9.3)):
+ dependencies:
+ '@babel/core': 7.29.0
+ '@jest/get-type': 30.1.0
+ '@jest/pattern': 30.0.1
+ '@jest/test-sequencer': 30.2.0
+ '@jest/types': 30.2.0
+ babel-jest: 30.2.0(@babel/core@7.29.0)
+ chalk: 4.1.2
+ ci-info: 4.4.0
+ deepmerge: 4.3.1
+ glob: 10.5.0
+ graceful-fs: 4.2.11
+ jest-circus: 30.2.0(babel-plugin-macros@3.1.0)
+ jest-docblock: 30.2.0
+ jest-environment-node: 30.2.0
+ jest-regex-util: 30.0.1
+ jest-resolve: 30.2.0
+ jest-runner: 30.2.0
+ jest-util: 30.2.0
+ jest-validate: 30.2.0
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 30.2.0
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.14.1
+ ts-node: 10.9.2(@types/node@25.2.3)(typescript@5.9.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
jest-config@30.2.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.9.3)):
dependencies:
'@babel/core': 7.29.0
@@ -10436,7 +10479,7 @@ snapshots:
'@jest/environment': 29.7.0
'@jest/fake-timers': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-mock: 29.7.0
jest-util: 29.7.0
@@ -10445,7 +10488,7 @@ snapshots:
'@jest/environment': 30.2.0
'@jest/fake-timers': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-mock: 30.2.0
jest-util: 30.2.0
jest-validate: 30.2.0
@@ -10456,7 +10499,7 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
'@types/graceful-fs': 4.1.9
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -10471,7 +10514,7 @@ snapshots:
jest-haste-map@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.11
@@ -10534,13 +10577,13 @@ snapshots:
jest-mock@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-util: 29.7.0
jest-mock@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-util: 30.2.0
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
@@ -10599,7 +10642,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.11
@@ -10625,7 +10668,7 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
emittery: 0.13.1
exit-x: 0.2.2
@@ -10654,7 +10697,7 @@ snapshots:
'@jest/test-result': 29.7.0
'@jest/transform': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
cjs-module-lexer: 1.4.3
collect-v8-coverage: 1.0.2
@@ -10681,7 +10724,7 @@ snapshots:
'@jest/test-result': 30.2.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
cjs-module-lexer: 2.2.0
collect-v8-coverage: 1.0.3
@@ -10753,7 +10796,7 @@ snapshots:
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@@ -10762,7 +10805,7 @@ snapshots:
jest-util@30.2.0:
dependencies:
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
chalk: 4.1.2
ci-info: 4.4.0
graceful-fs: 4.2.11
@@ -10790,7 +10833,7 @@ snapshots:
dependencies:
'@jest/test-result': 29.7.0
'@jest/types': 29.6.3
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -10801,7 +10844,7 @@ snapshots:
dependencies:
'@jest/test-result': 30.2.0
'@jest/types': 30.2.0
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
@@ -10810,19 +10853,31 @@ snapshots:
jest-worker@29.7.0:
dependencies:
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
jest-util: 29.7.0
merge-stream: 2.0.0
supports-color: 8.1.1
jest-worker@30.2.0:
dependencies:
- '@types/node': 25.2.3
+ '@types/node': 22.14.1
'@ungap/structured-clone': 1.3.0
jest-util: 30.2.0
merge-stream: 2.0.0
supports-color: 8.1.1
+ jest@29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3)):
+ dependencies:
+ '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ '@jest/types': 29.6.3
+ import-local: 3.2.0
+ jest-cli: 29.7.0(@types/node@22.14.1)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3))
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - supports-color
+ - ts-node
+
jest@29.7.0(@types/node@25.2.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3)):
dependencies:
'@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3))
@@ -10933,7 +10988,7 @@ snapshots:
jss@10.10.0:
dependencies:
'@babel/runtime': 7.27.4
- csstype: 3.1.3
+ csstype: 3.2.3
is-in-browser: 1.1.3
tiny-warning: 1.0.3
@@ -11067,8 +11122,6 @@ snapshots:
nanoid@3.3.11: {}
- napi-postinstall@0.2.4: {}
-
napi-postinstall@0.3.4: {}
natural-compare@1.4.0: {}
@@ -11124,7 +11177,7 @@ snapshots:
'@swc/counter': 0.1.3
'@swc/helpers': 0.5.15
busboy: 1.6.0
- caniuse-lite: 1.0.30001720
+ caniuse-lite: 1.0.30001769
postcss: 8.4.31
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
@@ -11149,7 +11202,7 @@ snapshots:
'@swc/counter': 0.1.3
'@swc/helpers': 0.5.15
busboy: 1.6.0
- caniuse-lite: 1.0.30001720
+ caniuse-lite: 1.0.30001769
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
@@ -11174,7 +11227,7 @@ snapshots:
'@swc/counter': 0.1.3
'@swc/helpers': 0.5.15
busboy: 1.6.0
- caniuse-lite: 1.0.30001720
+ caniuse-lite: 1.0.30001769
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
@@ -11199,7 +11252,7 @@ snapshots:
'@swc/counter': 0.1.3
'@swc/helpers': 0.5.15
busboy: 1.6.0
- caniuse-lite: 1.0.30001720
+ caniuse-lite: 1.0.30001769
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
@@ -11481,6 +11534,23 @@ snapshots:
queue-microtask@1.2.3: {}
+ ra-core@5.14.1(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
+ dependencies:
+ '@tanstack/react-query': 5.90.21(react@18.3.1)
+ date-fns: 3.6.0
+ eventemitter3: 5.0.4
+ inflection: 3.0.2
+ jsonexport: 3.2.0
+ lodash: 4.17.23
+ query-string: 7.1.3
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-error-boundary: 4.1.2(react@18.3.1)
+ react-hook-form: 7.71.1(react@18.3.1)
+ react-is: 19.2.4
+ react-router: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react-router-dom: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+
ra-core@5.14.1(@tanstack/react-query@5.90.21(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react-hook-form@7.71.1(react@19.1.0))(react-router-dom@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-router@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0):
dependencies:
'@tanstack/react-query': 5.90.21(react@19.1.0)
@@ -11498,9 +11568,9 @@ snapshots:
react-router: 7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-router-dom: 7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- ra-core@5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
+ ra-core@5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
dependencies:
- '@tanstack/react-query': 5.79.0(react@18.3.1)
+ '@tanstack/react-query': 5.90.21(react@18.3.1)
clsx: 2.1.1
date-fns: 3.6.0
eventemitter3: 5.0.1
@@ -11511,7 +11581,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-error-boundary: 4.1.2(react@18.3.1)
- react-hook-form: 7.56.4(react@18.3.1)
+ react-hook-form: 7.71.1(react@18.3.1)
react-is: 19.1.0
react-router: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-router-dom: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11528,11 +11598,12 @@ snapshots:
- react-router
- react-router-dom
- ra-i18n-polyglot@5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
+ ra-i18n-polyglot@5.8.3(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
dependencies:
node-polyglot: 2.6.0
- ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-core: 5.14.1(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
transitivePeerDependencies:
+ - '@tanstack/react-query'
- react
- react-dom
- react-hook-form
@@ -11550,20 +11621,21 @@ snapshots:
- react-router
- react-router-dom
- ra-language-english@5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
+ ra-language-english@5.8.3(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1):
dependencies:
- ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-core: 5.14.1(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
transitivePeerDependencies:
+ - '@tanstack/react-query'
- react
- react-dom
- react-hook-form
- react-router
- react-router-dom
- ra-ui-materialui@5.14.1(e48715e1df3f51681540fa7fbce63ad8):
+ ra-ui-materialui@5.14.1(e044a4ef4fe72f4c3535eee066d44fff):
dependencies:
- '@mui/icons-material': 7.3.8(@mui/material@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
- '@mui/material': 7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@mui/icons-material': 5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
+ '@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/system': 7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
'@mui/utils': 7.3.8(@types/react@19.1.1)(react@19.1.0)
'@tanstack/react-query': 5.90.21(react@19.1.0)
@@ -11589,13 +11661,13 @@ snapshots:
react-router-dom: 7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
- ra-ui-materialui@5.8.3(520842cc75124fee71df308e74da342e):
+ ra-ui-materialui@5.8.3(b1e91f9a525aa665dc88318da06dae04):
dependencies:
'@mui/icons-material': 5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@mui/system': 7.3.8(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/utils': 7.3.8(@types/react@18.3.12)(react@18.3.1)
- '@tanstack/react-query': 5.79.0(react@18.3.1)
+ '@tanstack/react-query': 5.90.21(react@18.3.1)
autosuggest-highlight: 3.3.4
clsx: 2.1.1
css-mediaquery: 0.1.2
@@ -11605,12 +11677,12 @@ snapshots:
jsonexport: 3.2.0
lodash: 4.17.21
query-string: 7.1.3
- ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
react-dropzone: 14.3.8(react@18.3.1)
react-error-boundary: 4.1.2(react@18.3.1)
- react-hook-form: 7.56.4(react@18.3.1)
+ react-hook-form: 7.71.1(react@18.3.1)
react-is: 19.2.4
react-router: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-router-dom: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -11620,20 +11692,19 @@ snapshots:
dependencies:
'@emotion/react': 11.14.0(@types/react@19.1.1)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
- '@mui/icons-material': 7.3.8(@mui/material@7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
- '@mui/material': 7.3.8(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ '@mui/icons-material': 5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.1)(react@19.1.0)
+ '@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react@19.1.0))(@types/react@19.1.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tanstack/react-query': 5.90.21(react@19.1.0)
ra-core: 5.14.1(@tanstack/react-query@5.90.21(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react-hook-form@7.71.1(react@19.1.0))(react-router-dom@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-router@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
ra-i18n-polyglot: 5.14.1(@tanstack/react-query@5.90.21(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react-hook-form@7.71.1(react@19.1.0))(react-router-dom@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-router@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
ra-language-english: 5.14.1(@tanstack/react-query@5.90.21(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react-hook-form@7.71.1(react@19.1.0))(react-router-dom@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-router@7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
- ra-ui-materialui: 5.14.1(e48715e1df3f51681540fa7fbce63ad8)
+ ra-ui-materialui: 5.14.1(e044a4ef4fe72f4c3535eee066d44fff)
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-hook-form: 7.71.1(react@19.1.0)
react-router: 7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-router-dom: 7.13.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
transitivePeerDependencies:
- - '@mui/material-pigment-css'
- '@mui/system'
- '@mui/utils'
- '@types/react'
@@ -11641,24 +11712,25 @@ snapshots:
- react-is
- supports-color
- react-admin@5.8.3(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/utils@7.3.8(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.4)(react@18.3.1):
+ react-admin@5.8.3(@mui/system@7.3.8(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@mui/utils@7.3.8(@types/react@18.3.12)(react@18.3.1))(@tanstack/react-query@5.90.21(react@18.3.1))(@types/react@18.3.12)(csstype@3.2.3)(react-dom@18.3.1(react@18.3.1))(react-is@19.2.4)(react@18.3.1):
dependencies:
'@emotion/react': 11.14.0(@types/react@18.3.12)(react@18.3.1)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/icons-material': 5.17.1(@mui/material@5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
'@mui/material': 5.17.1(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
- ra-i18n-polyglot: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
- ra-language-english: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.56.4(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
- ra-ui-materialui: 5.8.3(520842cc75124fee71df308e74da342e)
+ ra-core: 5.8.3(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-i18n-polyglot: 5.8.3(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-language-english: 5.8.3(@tanstack/react-query@5.90.21(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-hook-form@7.71.1(react@18.3.1))(react-router-dom@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-router@7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+ ra-ui-materialui: 5.8.3(b1e91f9a525aa665dc88318da06dae04)
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- react-hook-form: 7.56.4(react@18.3.1)
+ react-hook-form: 7.71.1(react@18.3.1)
react-router: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-router-dom: 7.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
transitivePeerDependencies:
- '@mui/system'
- '@mui/utils'
+ - '@tanstack/react-query'
- '@types/react'
- csstype
- react-is
@@ -11699,7 +11771,7 @@ snapshots:
'@babel/runtime': 7.28.6
react: 19.1.0
- react-hook-form@7.56.4(react@18.3.1):
+ react-hook-form@7.71.1(react@18.3.1):
dependencies:
react: 18.3.1
@@ -11754,7 +11826,7 @@ snapshots:
react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
@@ -11763,7 +11835,7 @@ snapshots:
react-transition-group@4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
- '@babel/runtime': 7.27.4
+ '@babel/runtime': 7.28.6
dom-helpers: 5.2.1
loose-envify: 1.4.0
prop-types: 15.8.1
@@ -11983,7 +12055,7 @@ snapshots:
sharp@0.34.2:
dependencies:
color: 4.2.3
- detect-libc: 2.0.4
+ detect-libc: 2.1.2
semver: 7.7.4
optionalDependencies:
'@img/sharp-darwin-arm64': 0.34.2
@@ -12298,6 +12370,25 @@ snapshots:
ts-interface-checker@0.1.13: {}
+ ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3):
+ dependencies:
+ '@cspotcode/source-map-support': 0.8.1
+ '@tsconfig/node10': 1.0.12
+ '@tsconfig/node12': 1.0.11
+ '@tsconfig/node14': 1.0.3
+ '@tsconfig/node16': 1.0.4
+ '@types/node': 22.14.1
+ acorn: 8.15.0
+ acorn-walk: 8.3.4
+ arg: 4.1.3
+ create-require: 1.1.1
+ diff: 4.0.4
+ make-error: 1.3.6
+ typescript: 5.8.3
+ v8-compile-cache-lib: 3.0.1
+ yn: 3.1.1
+ optional: true
+
ts-node@10.9.2(@types/node@25.2.3)(typescript@5.8.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -12522,28 +12613,6 @@ snapshots:
'@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
'@unrs/resolver-binding-win32-x64-msvc': 1.11.1
- unrs-resolver@1.7.8:
- dependencies:
- napi-postinstall: 0.2.4
- optionalDependencies:
- '@unrs/resolver-binding-darwin-arm64': 1.7.8
- '@unrs/resolver-binding-darwin-x64': 1.7.8
- '@unrs/resolver-binding-freebsd-x64': 1.7.8
- '@unrs/resolver-binding-linux-arm-gnueabihf': 1.7.8
- '@unrs/resolver-binding-linux-arm-musleabihf': 1.7.8
- '@unrs/resolver-binding-linux-arm64-gnu': 1.7.8
- '@unrs/resolver-binding-linux-arm64-musl': 1.7.8
- '@unrs/resolver-binding-linux-ppc64-gnu': 1.7.8
- '@unrs/resolver-binding-linux-riscv64-gnu': 1.7.8
- '@unrs/resolver-binding-linux-riscv64-musl': 1.7.8
- '@unrs/resolver-binding-linux-s390x-gnu': 1.7.8
- '@unrs/resolver-binding-linux-x64-gnu': 1.7.8
- '@unrs/resolver-binding-linux-x64-musl': 1.7.8
- '@unrs/resolver-binding-wasm32-wasi': 1.7.8
- '@unrs/resolver-binding-win32-arm64-msvc': 1.7.8
- '@unrs/resolver-binding-win32-ia32-msvc': 1.7.8
- '@unrs/resolver-binding-win32-x64-msvc': 1.7.8
-
update-browserslist-db@1.1.3(browserslist@4.25.2):
dependencies:
browserslist: 4.25.2