diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..1380c2e7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +.next \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..404644f5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM node:20-alpine AS builder + +# Setting working directory. All the path will be relative to WORKDIR +WORKDIR /app +# Installing dependencies +COPY package*.json ./ +RUN npm install + +# Copying source files +COPY . . + +# Building app +RUN npm run build + +# Copy only standalone server to new image +FROM node:20-alpine +WORKDIR /app +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/static ./.next/static +CMD ["node", "server.js"] \ No newline at end of file diff --git a/README.md b/README.md index 4e4f4d0d..9f9042b9 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,4 @@ Outerbase Studio Desktop is a lightweight Electron wrapper for the Outerbase Stu - **Schema Editor**: It allows you to quickly create, modify, and remove table columns with just a few clicks without writing any SQL. - **Connection Manager**: It includes a flexible connection manager, allowing you to store your connections locally in your browser. You can also store them on a server and share your connections across multiple devices. -The features mentioned above are just a few of the many we offer. Give it a try to explore everything we have in store. +The features mentioned above are just a few of the many we offer. Give it a try to explore everything we have in store diff --git a/drizzle.config.ts b/drizzle.config.ts deleted file mode 100644 index 459cd212..00000000 --- a/drizzle.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { env } from "@/env"; -import type { Config } from "drizzle-kit"; - -export default { - schema: "./src/db/schema.ts", - out: "./drizzle", - driver: "turso", - dbCredentials: { - url: env.DATABASE_URL ?? "", - authToken: env.DATABASE_AUTH_TOKEN, - }, -} satisfies Config; diff --git a/next.config.js b/next.config.js index 6bc6fc24..8edd8f9a 100644 --- a/next.config.js +++ b/next.config.js @@ -4,6 +4,7 @@ const pkg = require("./package.json"); /** @type {import('next').NextConfig} */ const nextConfig = { + output: "standalone", reactStrictMode: false, pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], env: { @@ -19,4 +20,4 @@ const nextConfig = { }, }; -module.exports = withMDX(nextConfig); +module.exports = { ...withMDX(nextConfig), output: "standalone" }; diff --git a/package-lock.json b/package-lock.json index 83989cf0..91cc6e27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,32 +1,32 @@ { - "name": "@libsqlstudio/studio", - "version": "0.9.2", + "name": "@outerbase/studio", + "version": "0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@libsqlstudio/studio", - "version": "0.9.2", + "name": "@outerbase/studio", + "version": "0.10", "dependencies": { "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.5", + "@codemirror/merge": "^6.8.0", "@dagrejs/dagre": "^1.1.4", "@dnd-kit/core": "^6.1.0", "@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/sortable": "^8.0.0", - "@justmiracle/result": "^1.2.0", "@lezer/common": "^1.2.1", "@lezer/lr": "^1.4.0", "@libsql/client": "^0.5.3", - "@lucia-auth/adapter-sqlite": "^3.0.1", "@mdx-js/loader": "^3.0.1", "@mdx-js/react": "^3.0.1", "@next/mdx": "^14.2.4", - "@outerbase/sdk-transform": "^1.0.1", + "@outerbase/sdk-transform": "^1.0.5", "@phosphor-icons/react": "^2.1.7", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -46,8 +46,6 @@ "@radix-ui/react-tooltip": "^1.0.7", "@replit/codemirror-indentation-markers": "^6.5.3", "@t3-oss/env-nextjs": "^0.9.2", - "@tiptap/core": "^2.3.0", - "@tiptap/react": "^2.3.0", "@types/mdx": "^2.0.13", "@types/react-grid-layout": "^1.3.5", "@uiw/codemirror-extensions-langs": "^4.21.24", @@ -55,15 +53,12 @@ "@uiw/react-codemirror": "^4.21.21", "@vercel/analytics": "^1.3.1", "@xyflow/react": "^12.3.6", - "arctic": "^1.2.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.4", - "cookies-next": "^4.3.0", "deep-equal": "^2.2.3", "dexie": "^4.0.8", "dotenv": "^16.4.5", - "drizzle-orm": "^0.30.1", "echarts": "^5.6.0", "eslint-plugin-jest": "^27.6.3", "file-saver": "^2.0.5", @@ -71,12 +66,12 @@ "immer": "^10.1.1", "libsql-stateless-easy": "^1.6.11", "lodash": "^4.17.21", - "lucia": "^3.2.0", "lucide-react": "^0.474.0", + "motion": "^12.4.3", "next": "15.1.4", "next-themes": "^0.4.4", - "oslo": "^1.1.3", "react": "19.0.0", + "react-color": "^2.19.3", "react-dom": "19.0.0", "react-grid-layout": "^1.5.0", "react-resizable-panels": "^2.1.7", @@ -99,16 +94,15 @@ "@types/lodash": "^4.17.9", "@types/node": "^20", "@types/react": "^18", + "@types/react-color": "^3.0.13", "@types/react-dom": "^18", "@types/showdown": "^2.0.6", "@types/sql.js": "^1.4.9", "@types/wicg-file-system-access": "^2023.10.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "drizzle-kit": "^0.20.14", "eslint": "^8", "eslint-config-next": "14.0.4", - "gui": "^0.15.3", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "postcss": "^8.4.38", @@ -1048,6 +1042,19 @@ "crelt": "^1.0.5" } }, + "node_modules/@codemirror/merge": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@codemirror/merge/-/merge-6.8.0.tgz", + "integrity": "sha512-EcCD4OJlGz6lJaqZOFM/RE6fqM4XSQlWNWVxm2CJS1snbrbkgYLTvj8c++pFUWpJOUiNgcxvYMYkMisnC0aR6g==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/highlight": "^1.0.0", + "style-mod": "^4.1.0" + } + }, "node_modules/@codemirror/search": { "version": "6.5.8", "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz", @@ -1200,934 +1207,965 @@ "react": ">=16.8.0" } }, - "node_modules/@emnapi/core": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-0.45.0.tgz", - "integrity": "sha512-DPWjcUDQkCeEM4VnljEOEcXdAD7pp8zSZsgOujk/LGIwCXWbXJngin+MO4zbH429lzeC3WbYLGjE2MaUOwzpyw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "license": "MIT", "dependencies": { - "tslib": "^2.4.0" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@emnapi/runtime": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.45.0.tgz", - "integrity": "sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "license": "MIT", - "optional": true, "dependencies": { - "tslib": "^2.4.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild-kit/core-utils": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz", - "integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==", - "deprecated": "Merged into tsx: https://tsx.is", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "esbuild": "~0.18.20", - "source-map-support": "^0.5.21" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@floating-ui/core": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", + "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.13", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", + "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=12" + "node": ">=10.10.0" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "license": "BSD-3-Clause" + }, + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "peerDependencies": { + "react": "*" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "darwin" ], - "engines": { - "node": ">=12" - } + "funding": { + "url": "https://opencollective.com/libvips" + } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "darwin" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ "arm" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ "arm64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ - "ia32" + "s390x" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ - "loong64" + "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ - "mips64el" + "arm64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ - "ppc64" + "x64" ], - "dev": true, - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=12" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", "cpu": [ - "riscv64" + "arm" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", "cpu": [ - "s390x" + "arm64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", "cpu": [ - "x64" + "s390x" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", "cpu": [ - "x64" + "arm64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "sunos" + "linux" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", "cpu": [ - "arm64" + "wasm32" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-wasm32/node_modules/@emnapi/runtime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", "cpu": [ "ia32" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", "cpu": [ "x64" ], - "dev": true, - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/@esbuild-kit/esm-loader": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz", - "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", - "deprecated": "Merged into tsx: https://tsx.is", - "dev": true, - "license": "MIT", - "dependencies": { - "@esbuild-kit/core-utils": "^3.3.2", - "get-tsconfig": "^4.7.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "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": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "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.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "devOptional": true, + "license": "MIT" }, - "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "jest-get-type": "^29.6.3" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "devOptional": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "license": "MIT", + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "devOptional": true, + "license": "ISC", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "*" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "node_modules/@jest/reporters/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" @@ -2136,1898 +2174,489 @@ "node": "*" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "devOptional": true, "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", - "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "devOptional": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "devOptional": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.9" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "devOptional": true, "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", - "license": "MIT" - }, - "node_modules/@hono/node-server": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.13.7.tgz", - "integrity": "sha512-kTfUMsoloVKtRA2fLiGSd9qBddmru9KadNyhJCwgKBxTiNkaAJEwkVN9KV/rS4HtmmNRtUh6P+YpmjRMl0d9vQ==", - "dev": true, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=18.14.1" + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, - "peerDependencies": { - "hono": "^4" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@hono/zod-validator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.2.2.tgz", - "integrity": "sha512-dSDxaPV70Py8wuIU2QNpoVEIOSzSXZ/6/B/h4xA7eOMz7+AarKTSGV8E6QwrdcCbBLkpqfJ4Q2TmBO0eP1tCBQ==", - "dev": true, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "devOptional": true, "license": "MIT", - "peerDependencies": { - "hono": ">=3.9.0", - "zod": "^3.19.1" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=10.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "devOptional": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "devOptional": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=6.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "license": "Apache-2.0", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "devOptional": true, + "license": "MIT", "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=6.0.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "license": "BSD-3-Clause" - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-wasm32/node_modules/@emnapi/runtime": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", - "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "devOptional": true, - "license": "MIT", - "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": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "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.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "devOptional": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@justmiracle/result": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@justmiracle/result/-/result-1.2.0.tgz", - "integrity": "sha512-MyyfTSloRNvdB1EnzSDiOeyPtdXeK+gp1d2zxqcjq/XHoagsIzo7ImEJCKIUkOTlmuEInPfYZrcAU7sdeCWqkg==", - "license": "MIT" - }, - "node_modules/@lezer/common": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", - "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", - "license": "MIT" - }, - "node_modules/@lezer/cpp": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", - "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/css": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz", - "integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/go": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.0.tgz", - "integrity": "sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/highlight": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/html": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", - "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/java": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", - "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/javascript": { - "version": "1.4.21", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz", - "integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.1.3", - "@lezer/lr": "^1.3.0" - } - }, - "node_modules/@lezer/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", - "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lezer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@lezer/lezer/-/lezer-1.1.2.tgz", - "integrity": "sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==", - "license": "MIT", - "dependencies": { - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/markdown": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.0.tgz", - "integrity": "sha512-mk4MYeq6ZQdxgsgRAe0G7kqPRV6Desajfa14TcHoGGXIqqj1/2ARN31VFpmrXDgvXiGBWpA7RXtv0he+UdTkGw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0", - "@lezer/highlight": "^1.0.0" - } - }, - "node_modules/@lezer/php": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.2.tgz", - "integrity": "sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.1.0" - } - }, - "node_modules/@lezer/python": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.15.tgz", - "integrity": "sha512-aVQ43m2zk4FZYedCqL0KHPEUsqZOrmAvRhkhHlVPnDD1HODDyyQv5BRIuod4DadkgBEZd53vQOtXTonNbEgjrQ==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/rust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", - "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/sass": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.0.7.tgz", - "integrity": "sha512-8HLlOkuX/SMHOggI2DAsXUw38TuURe+3eQ5hiuk9QmYOUyC55B1dYEIMkav5A4IELVaW4e1T4P9WRiI5ka4mdw==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/xml": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", - "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0" - } - }, - "node_modules/@lezer/yaml": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", - "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.4.0" - } - }, - "node_modules/@libsql/client": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.5.6.tgz", - "integrity": "sha512-UBjmDoxz75Z2sHdP+ETCROpeLA/77VMesiff8R4UWK1rnaWbh6/YoCLDILMJL3Rh0udQeKxjL8MjXthqohax+g==", - "license": "MIT", - "dependencies": { - "@libsql/core": "^0.5.6", - "@libsql/hrana-client": "^0.5.6", - "js-base64": "^3.7.5", - "libsql": "^0.3.10" - } - }, - "node_modules/@libsql/core": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@libsql/core/-/core-0.5.6.tgz", - "integrity": "sha512-3vicUAydq6jPth410n4AsHHm1n2psTwvkSf94nfJlSXutGSZsl0updn2N/mJBgqUHkbuFoWZtlMifF0SwBj1xQ==", - "license": "MIT", - "dependencies": { - "js-base64": "^3.7.5" - } - }, - "node_modules/@libsql/darwin-arm64": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.3.19.tgz", - "integrity": "sha512-rmOqsLcDI65zzxlUOoEiPJLhqmbFsZF6p4UJQ2kMqB+Kc0Rt5/A1OAdOZ/Wo8fQfJWjR1IbkbpEINFioyKf+nQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@libsql/darwin-x64": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.3.19.tgz", - "integrity": "sha512-q9O55B646zU+644SMmOQL3FIfpmEvdWpRpzubwFc2trsa+zoBlSkHuzU9v/C+UNoPHQVRMP7KQctJ455I/h/xw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "devOptional": true, + "license": "MIT" }, - "node_modules/@libsql/hrana-client": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.5.6.tgz", - "integrity": "sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "devOptional": true, "license": "MIT", "dependencies": { - "@libsql/isomorphic-fetch": "^0.1.12", - "@libsql/isomorphic-ws": "^0.1.5", - "js-base64": "^3.7.5", - "node-fetch": "^3.3.2" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@libsql/isomorphic-fetch": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.1.12.tgz", - "integrity": "sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==", + "node_modules/@lezer/common": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", + "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", + "license": "MIT" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", + "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", "license": "MIT", "dependencies": { - "@types/node-fetch": "^2.6.11", - "node-fetch": "^2.7.0" + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@libsql/isomorphic-fetch/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/@lezer/css": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz", + "integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==", "license": "MIT", "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@libsql/isomorphic-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/@libsql/isomorphic-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/@libsql/isomorphic-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/@lezer/go": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.0.tgz", + "integrity": "sha512-co9JfT3QqX1YkrMmourYw2Z8meGC50Ko4d54QEcQbEYpvdUvN4yb0NBZdn/9ertgvjsySxHsKzH3lbm3vqJ4Jw==", "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@libsql/isomorphic-ws": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz", - "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", "license": "MIT", "dependencies": { - "@types/ws": "^8.5.4", - "ws": "^8.13.0" + "@lezer/common": "^1.0.0" } }, - "node_modules/@libsql/linux-arm64-gnu": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.3.19.tgz", - "integrity": "sha512-mgeAUU1oqqh57k7I3cQyU6Trpdsdt607eFyEmH5QO7dv303ti+LjUvh1pp21QWV6WX7wZyjeJV1/VzEImB+jRg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@libsql/linux-arm64-musl": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.3.19.tgz", - "integrity": "sha512-VEZtxghyK6zwGzU9PHohvNxthruSxBEnRrX7BSL5jQ62tN4n2JNepJ6SdzXp70pdzTfwroOj/eMwiPt94gkVRg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@libsql/linux-x64-gnu": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.3.19.tgz", - "integrity": "sha512-2t/J7LD5w2f63wGihEO+0GxfTyYIyLGEvTFEsMO16XI5o7IS9vcSHrxsvAJs4w2Pf907uDjmc7fUfMg6L82BrQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@libsql/linux-x64-musl": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.3.19.tgz", - "integrity": "sha512-BLsXyJaL8gZD8+3W2LU08lDEd9MIgGds0yPy5iNPp8tfhXx3pV/Fge2GErN0FC+nzt4DYQtjL+A9GUMglQefXQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@libsql/win32-x64-msvc": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.3.19.tgz", - "integrity": "sha512-ay1X9AobE4BpzG0XPw1gplyLZPGHIgJOovvW23gUrukRegiUP62uzhpRbKNogLlUOynyXeq//prHgPXiebUfWg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@lucia-auth/adapter-sqlite": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@lucia-auth/adapter-sqlite/-/adapter-sqlite-3.0.2.tgz", - "integrity": "sha512-UlXpF+2UoFEdm1AsriJii5BOARwqko6SX29rQ8T8Za7rnjj9KLXLaRVQUgBhGmggAyvzCtguJ2+XOZDsfWm6Sw==", + "node_modules/@lezer/html": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", + "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", "license": "MIT", - "peerDependencies": { - "@libsql/client": "^0.3.0", - "better-sqlite3": "8.x - 11.x", - "lucia": "3.x" - }, - "peerDependenciesMeta": { - "@libsql/client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - } + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@marijn/find-cluster-break": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", - "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", - "license": "MIT" - }, - "node_modules/@mdx-js/loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.0.tgz", - "integrity": "sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg==", + "node_modules/@lezer/java": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", + "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", "license": "MIT", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "webpack": ">=5" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", - "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/@lezer/javascript": { + "version": "1.4.21", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.21.tgz", + "integrity": "sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" } }, - "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", "license": "MIT", "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@neon-rs/load": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz", - "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==", - "license": "MIT" - }, - "node_modules/@next/env": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.4.tgz", - "integrity": "sha512-2fZ5YZjedi5AGaeoaC0B20zGntEHRhi2SdWcu61i48BllODcAmmtj8n7YarSPt4DaTsJaBFdxQAVEVzgmx2Zpw==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz", - "integrity": "sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==", - "dev": true, + "node_modules/@lezer/lezer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/lezer/-/lezer-1.1.2.tgz", + "integrity": "sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==", "license": "MIT", "dependencies": { - "glob": "7.1.7" + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@next/eslint-plugin-next/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@lezer/common": "^1.0.0" } }, - "node_modules/@next/eslint-plugin-next/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", + "node_modules/@lezer/markdown": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.0.tgz", + "integrity": "sha512-mk4MYeq6ZQdxgsgRAe0G7kqPRV6Desajfa14TcHoGGXIqqj1/2ARN31VFpmrXDgvXiGBWpA7RXtv0he+UdTkGw==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0" } }, - "node_modules/@next/eslint-plugin-next/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", + "node_modules/@lezer/php": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.2.tgz", + "integrity": "sha512-GN7BnqtGRpFyeoKSEqxvGvhJQiI4zkgmYnDk/JIyc7H7Ifc1tkPnUn/R2R8meH3h/aBf5rzjvU8ZQoyiNDtDrA==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" } }, - "node_modules/@next/mdx": { - "version": "14.2.23", - "resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-14.2.23.tgz", - "integrity": "sha512-4JVc67Gaj4Tr8w0WO+F5TAjS1JszagcqT06NLQ7CE6lNCyxfYRavo4LRYSdc3enp06aPiZLW6kklE3Xqf3p5rg==", + "node_modules/@lezer/python": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.15.tgz", + "integrity": "sha512-aVQ43m2zk4FZYedCqL0KHPEUsqZOrmAvRhkhHlVPnDD1HODDyyQv5BRIuod4DadkgBEZd53vQOtXTonNbEgjrQ==", "license": "MIT", "dependencies": { - "source-map": "^0.7.0" - }, - "peerDependencies": { - "@mdx-js/loader": ">=0.15.0", - "@mdx-js/react": ">=0.15.0" - }, - "peerDependenciesMeta": { - "@mdx-js/loader": { - "optional": true - }, - "@mdx-js/react": { - "optional": true - } + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.4.tgz", - "integrity": "sha512-wBEMBs+np+R5ozN1F8Y8d/Dycns2COhRnkxRc+rvnbXke5uZBHkUGFgWxfTXn5rx7OLijuUhyfB+gC/ap58dDw==", - "cpu": [ - "arm64" - ], + "node_modules/@lezer/rust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", + "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.4.tgz", - "integrity": "sha512-7sgf5rM7Z81V9w48F02Zz6DgEJulavC0jadab4ZsJ+K2sxMNK0/BtF8J8J3CxnsJN3DGcIdC260wEKssKTukUw==", - "cpu": [ - "x64" - ], + "node_modules/@lezer/sass": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.0.7.tgz", + "integrity": "sha512-8HLlOkuX/SMHOggI2DAsXUw38TuURe+3eQ5hiuk9QmYOUyC55B1dYEIMkav5A4IELVaW4e1T4P9WRiI5ka4mdw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.4.tgz", - "integrity": "sha512-JaZlIMNaJenfd55kjaLWMfok+vWBlcRxqnRoZrhFQrhM1uAehP3R0+Aoe+bZOogqlZvAz53nY/k3ZyuKDtT2zQ==", - "cpu": [ - "arm64" - ], + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.4.tgz", - "integrity": "sha512-7EBBjNoyTO2ipMDgCiORpwwOf5tIueFntKjcN3NK+GAQD7OzFJe84p7a2eQUeWdpzZvhVXuAtIen8QcH71ZCOQ==", - "cpu": [ - "arm64" - ], + "node_modules/@lezer/yaml": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", + "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.4.tgz", - "integrity": "sha512-9TGEgOycqZFuADyFqwmK/9g6S0FYZ3tphR4ebcmCwhL8Y12FW8pIBKJvSwV+UBjMkokstGNH+9F8F031JZKpHw==", - "cpu": [ - "x64" - ], + "node_modules/@libsql/client": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@libsql/client/-/client-0.5.6.tgz", + "integrity": "sha512-UBjmDoxz75Z2sHdP+ETCROpeLA/77VMesiff8R4UWK1rnaWbh6/YoCLDILMJL3Rh0udQeKxjL8MjXthqohax+g==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@libsql/core": "^0.5.6", + "@libsql/hrana-client": "^0.5.6", + "js-base64": "^3.7.5", + "libsql": "^0.3.10" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.4.tgz", - "integrity": "sha512-0578bLRVDJOh+LdIoKvgNDz77+Bd85c5JrFgnlbI1SM3WmEQvsjxTA8ATu9Z9FCiIS/AliVAW2DV/BDwpXbtiQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "node_modules/@libsql/core": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@libsql/core/-/core-0.5.6.tgz", + "integrity": "sha512-3vicUAydq6jPth410n4AsHHm1n2psTwvkSf94nfJlSXutGSZsl0updn2N/mJBgqUHkbuFoWZtlMifF0SwBj1xQ==", + "license": "MIT", + "dependencies": { + "js-base64": "^3.7.5" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.4.tgz", - "integrity": "sha512-JgFCiV4libQavwII+kncMCl30st0JVxpPOtzWcAI2jtum4HjYaclobKhj+JsRu5tFqMtA5CJIa0MvYyuu9xjjQ==", + "node_modules/@libsql/darwin-arm64": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.3.19.tgz", + "integrity": "sha512-rmOqsLcDI65zzxlUOoEiPJLhqmbFsZF6p4UJQ2kMqB+Kc0Rt5/A1OAdOZ/Wo8fQfJWjR1IbkbpEINFioyKf+nQ==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } + "darwin" + ] }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.4.tgz", - "integrity": "sha512-xxsJy9wzq7FR5SqPCUqdgSXiNXrMuidgckBa8nH9HtjjxsilgcN6VgXF6tZ3uEWuVEadotQJI8/9EQ6guTC4Yw==", + "node_modules/@libsql/darwin-x64": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.3.19.tgz", + "integrity": "sha512-q9O55B646zU+644SMmOQL3FIfpmEvdWpRpzubwFc2trsa+zoBlSkHuzU9v/C+UNoPHQVRMP7KQctJ455I/h/xw==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } + "darwin" + ] }, - "node_modules/@nextjournal/lang-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lang-clojure/-/lang-clojure-1.0.0.tgz", - "integrity": "sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==", - "license": "ISC", + "node_modules/@libsql/hrana-client": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.5.6.tgz", + "integrity": "sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==", + "license": "MIT", "dependencies": { - "@codemirror/language": "^6.0.0", - "@nextjournal/lezer-clojure": "1.0.0" + "@libsql/isomorphic-fetch": "^0.1.12", + "@libsql/isomorphic-ws": "^0.1.5", + "js-base64": "^3.7.5", + "node-fetch": "^3.3.2" } }, - "node_modules/@nextjournal/lezer-clojure": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@nextjournal/lezer-clojure/-/lezer-clojure-1.0.0.tgz", - "integrity": "sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==", - "license": "ISC", + "node_modules/@libsql/isomorphic-fetch": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.1.12.tgz", + "integrity": "sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==", + "license": "MIT", "dependencies": { - "@lezer/lr": "^1.0.0" + "@types/node-fetch": "^2.6.11", + "node-fetch": "^2.7.0" } }, - "node_modules/@node-rs/argon2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2/-/argon2-1.7.0.tgz", - "integrity": "sha512-zfULc+/tmcWcxn+nHkbyY8vP3+MpEqKORbszt4UkpqZgBgDAAIYvuDN/zukfTgdmo6tmJKKVfzigZOPk4LlIog==", + "node_modules/@libsql/isomorphic-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", - "engines": { - "node": ">= 10" + "dependencies": { + "whatwg-url": "^5.0.0" }, - "optionalDependencies": { - "@node-rs/argon2-android-arm-eabi": "1.7.0", - "@node-rs/argon2-android-arm64": "1.7.0", - "@node-rs/argon2-darwin-arm64": "1.7.0", - "@node-rs/argon2-darwin-x64": "1.7.0", - "@node-rs/argon2-freebsd-x64": "1.7.0", - "@node-rs/argon2-linux-arm-gnueabihf": "1.7.0", - "@node-rs/argon2-linux-arm64-gnu": "1.7.0", - "@node-rs/argon2-linux-arm64-musl": "1.7.0", - "@node-rs/argon2-linux-x64-gnu": "1.7.0", - "@node-rs/argon2-linux-x64-musl": "1.7.0", - "@node-rs/argon2-wasm32-wasi": "1.7.0", - "@node-rs/argon2-win32-arm64-msvc": "1.7.0", - "@node-rs/argon2-win32-ia32-msvc": "1.7.0", - "@node-rs/argon2-win32-x64-msvc": "1.7.0" - } - }, - "node_modules/@node-rs/argon2-android-arm-eabi": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm-eabi/-/argon2-android-arm-eabi-1.7.0.tgz", - "integrity": "sha512-udDqkr5P9E+wYX1SZwAVPdyfYvaF4ry9Tm+R9LkfSHbzWH0uhU6zjIwNRp7m+n4gx691rk+lqqDAIP8RLKwbhg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">= 10" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/@node-rs/argon2-android-arm64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-android-arm64/-/argon2-android-arm64-1.7.0.tgz", - "integrity": "sha512-s9j/G30xKUx8WU50WIhF0fIl1EdhBGq0RQ06lEhZ0Gi0ap8lhqbE2Bn5h3/G2D1k0Dx+yjeVVNmt/xOQIRG38A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } + "node_modules/@libsql/isomorphic-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, - "node_modules/@node-rs/argon2-darwin-arm64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-darwin-arm64/-/argon2-darwin-arm64-1.7.0.tgz", - "integrity": "sha512-ZIz4L6HGOB9U1kW23g+m7anGNuTZ0RuTw0vNp3o+2DWpb8u8rODq6A8tH4JRL79S+Co/Nq608m9uackN2pe0Rw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } + "node_modules/@libsql/isomorphic-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, - "node_modules/@node-rs/argon2-darwin-x64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-darwin-x64/-/argon2-darwin-x64-1.7.0.tgz", - "integrity": "sha512-5oi/pxqVhODW/pj1+3zElMTn/YukQeywPHHYDbcAW3KsojFjKySfhcJMd1DjKTc+CHQI+4lOxZzSUzK7mI14Hw==", - "cpu": [ - "x64" - ], + "node_modules/@libsql/isomorphic-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/@node-rs/argon2-freebsd-x64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-freebsd-x64/-/argon2-freebsd-x64-1.7.0.tgz", - "integrity": "sha512-Ify08683hA4QVXYoIm5SUWOY5DPIT/CMB0CQT+IdxQAg/F+qp342+lUkeAtD5bvStQuCx/dFO3bnnzoe2clMhA==", - "cpu": [ - "x64" - ], + "node_modules/@libsql/isomorphic-ws": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz", + "integrity": "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@types/ws": "^8.5.4", + "ws": "^8.13.0" } }, - "node_modules/@node-rs/argon2-linux-arm-gnueabihf": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm-gnueabihf/-/argon2-linux-arm-gnueabihf-1.7.0.tgz", - "integrity": "sha512-7DjDZ1h5AUHAtRNjD19RnQatbhL+uuxBASuuXIBu4/w6Dx8n7YPxwTP4MXfsvuRgKuMWiOb/Ub/HJ3kXVCXRkg==", + "node_modules/@libsql/linux-arm64-gnu": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.3.19.tgz", + "integrity": "sha512-mgeAUU1oqqh57k7I3cQyU6Trpdsdt607eFyEmH5QO7dv303ti+LjUvh1pp21QWV6WX7wZyjeJV1/VzEImB+jRg==", "cpu": [ - "arm" + "arm64" ], "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/argon2-linux-arm64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-gnu/-/argon2-linux-arm64-gnu-1.7.0.tgz", - "integrity": "sha512-nJDoMP4Y3YcqGswE4DvP080w6O24RmnFEDnL0emdI8Nou17kNYBzP2546Nasx9GCyLzRcYQwZOUjrtUuQ+od2g==", + "node_modules/@libsql/linux-arm64-musl": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-arm64-musl/-/linux-arm64-musl-0.3.19.tgz", + "integrity": "sha512-VEZtxghyK6zwGzU9PHohvNxthruSxBEnRrX7BSL5jQ62tN4n2JNepJ6SdzXp70pdzTfwroOj/eMwiPt94gkVRg==", "cpu": [ "arm64" ], @@ -4035,31 +2664,25 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/argon2-linux-arm64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-arm64-musl/-/argon2-linux-arm64-musl-1.7.0.tgz", - "integrity": "sha512-BKWS8iVconhE3jrb9mj6t1J9vwUqQPpzCbUKxfTGJfc+kNL58F1SXHBoe2cDYGnHrFEHTY0YochzXoAfm4Dm/A==", + "node_modules/@libsql/linux-x64-gnu": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.3.19.tgz", + "integrity": "sha512-2t/J7LD5w2f63wGihEO+0GxfTyYIyLGEvTFEsMO16XI5o7IS9vcSHrxsvAJs4w2Pf907uDjmc7fUfMg6L82BrQ==", "cpu": [ - "arm64" + "x64" ], "license": "MIT", "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/argon2-linux-x64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-gnu/-/argon2-linux-x64-gnu-1.7.0.tgz", - "integrity": "sha512-EmgqZOlf4Jurk/szW1iTsVISx25bKksVC5uttJDUloTgsAgIGReCpUUO1R24pBhu9ESJa47iv8NSf3yAfGv6jQ==", + "node_modules/@libsql/linux-x64-musl": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.3.19.tgz", + "integrity": "sha512-BLsXyJaL8gZD8+3W2LU08lDEd9MIgGds0yPy5iNPp8tfhXx3pV/Fge2GErN0FC+nzt4DYQtjL+A9GUMglQefXQ==", "cpu": [ "x64" ], @@ -4067,159 +2690,195 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@node-rs/argon2-linux-x64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-linux-x64-musl/-/argon2-linux-x64-musl-1.7.0.tgz", - "integrity": "sha512-/o1efYCYIxjfuoRYyBTi2Iy+1iFfhqHCvvVsnjNSgO1xWiWrX0Rrt/xXW5Zsl7vS2Y+yu8PL8KFWRzZhaVxfKA==", + "node_modules/@libsql/win32-x64-msvc": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.3.19.tgz", + "integrity": "sha512-ay1X9AobE4BpzG0XPw1gplyLZPGHIgJOovvW23gUrukRegiUP62uzhpRbKNogLlUOynyXeq//prHgPXiebUfWg==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "win32" + ] + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, + "node_modules/@mdx-js/loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.0.tgz", + "integrity": "sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "webpack": ">=5" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/@node-rs/argon2-wasm32-wasi": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-wasm32-wasi/-/argon2-wasm32-wasi-1.7.0.tgz", - "integrity": "sha512-Evmk9VcxqnuwQftfAfYEr6YZYSPLzmKUsbFIMep5nTt9PT4XYRFAERj7wNYp+rOcBenF3X4xoB+LhwcOMTNE5w==", - "cpu": [ - "wasm32" - ], + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "license": "MIT", - "optional": true, "dependencies": { - "@emnapi/core": "^0.45.0", - "@emnapi/runtime": "^0.45.0", - "@tybys/wasm-util": "^0.8.1", - "memfs-browser": "^3.4.13000" + "@types/mdx": "^2.0.0" }, - "engines": { - "node": ">=14.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@node-rs/argon2-win32-arm64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-arm64-msvc/-/argon2-win32-arm64-msvc-1.7.0.tgz", - "integrity": "sha512-qgsU7T004COWWpSA0tppDqDxbPLgg8FaU09krIJ7FBl71Sz8SFO40h7fDIjfbTT5w7u6mcaINMQ5bSHu75PCaA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } + "node_modules/@neon-rs/load": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz", + "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==", + "license": "MIT" }, - "node_modules/@node-rs/argon2-win32-ia32-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-ia32-msvc/-/argon2-win32-ia32-msvc-1.7.0.tgz", - "integrity": "sha512-JGafwWYQ/HpZ3XSwP4adQ6W41pRvhcdXvpzIWtKvX+17+xEXAe2nmGWM6s27pVkg1iV2ZtoYLRDkOUoGqZkCcg==", - "cpu": [ - "ia32" - ], + "node_modules/@next/env": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.4.tgz", + "integrity": "sha512-2fZ5YZjedi5AGaeoaC0B20zGntEHRhi2SdWcu61i48BllODcAmmtj8n7YarSPt4DaTsJaBFdxQAVEVzgmx2Zpw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.4.tgz", + "integrity": "sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "glob": "7.1.7" } }, - "node_modules/@node-rs/argon2-win32-x64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@node-rs/argon2-win32-x64-msvc/-/argon2-win32-x64-msvc-1.7.0.tgz", - "integrity": "sha512-9oq4ShyFakw8AG3mRls0AoCpxBFcimYx7+jvXeAf2OqKNO+mSA6eZ9z7KQeVCi0+SOEUYxMGf5UiGiDb9R6+9Q==", - "cpu": [ - "x64" - ], + "node_modules/@next/eslint-plugin-next/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@node-rs/bcrypt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.9.0.tgz", - "integrity": "sha512-u2OlIxW264bFUfvbFqDz9HZKFjwe8FHFtn7T/U8mYjPZ7DWYpbUB+/dkW/QgYfMSfR0ejkyuWaBBe0coW7/7ig==", - "license": "MIT", + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">= 10" + "node": "*" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, - "optionalDependencies": { - "@node-rs/bcrypt-android-arm-eabi": "1.9.0", - "@node-rs/bcrypt-android-arm64": "1.9.0", - "@node-rs/bcrypt-darwin-arm64": "1.9.0", - "@node-rs/bcrypt-darwin-x64": "1.9.0", - "@node-rs/bcrypt-freebsd-x64": "1.9.0", - "@node-rs/bcrypt-linux-arm-gnueabihf": "1.9.0", - "@node-rs/bcrypt-linux-arm64-gnu": "1.9.0", - "@node-rs/bcrypt-linux-arm64-musl": "1.9.0", - "@node-rs/bcrypt-linux-x64-gnu": "1.9.0", - "@node-rs/bcrypt-linux-x64-musl": "1.9.0", - "@node-rs/bcrypt-wasm32-wasi": "1.9.0", - "@node-rs/bcrypt-win32-arm64-msvc": "1.9.0", - "@node-rs/bcrypt-win32-ia32-msvc": "1.9.0", - "@node-rs/bcrypt-win32-x64-msvc": "1.9.0" - } - }, - "node_modules/@node-rs/bcrypt-android-arm-eabi": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm-eabi/-/bcrypt-android-arm-eabi-1.9.0.tgz", - "integrity": "sha512-nOCFISGtnodGHNiLrG0WYLWr81qQzZKYfmwHc7muUeq+KY0sQXyHOwZk9OuNQAWv/lnntmtbwkwT0QNEmOyLvA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">= 10" + "node": "*" } }, - "node_modules/@node-rs/bcrypt-android-arm64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-android-arm64/-/bcrypt-android-arm64-1.9.0.tgz", - "integrity": "sha512-+ZrIAtigVmjYkqZQTThHVlz0+TG6D+GDHWhVKvR2DifjtqJ0i+mb9gjo++hN+fWEQdWNGxKCiBBjwgT4EcXd6A==", - "cpu": [ - "arm64" - ], + "node_modules/@next/mdx": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-14.2.23.tgz", + "integrity": "sha512-4JVc67Gaj4Tr8w0WO+F5TAjS1JszagcqT06NLQ7CE6lNCyxfYRavo4LRYSdc3enp06aPiZLW6kklE3Xqf3p5rg==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "source-map": "^0.7.0" + }, + "peerDependencies": { + "@mdx-js/loader": ">=0.15.0", + "@mdx-js/react": ">=0.15.0" + }, + "peerDependenciesMeta": { + "@mdx-js/loader": { + "optional": true + }, + "@mdx-js/react": { + "optional": true + } } }, - "node_modules/@node-rs/bcrypt-darwin-arm64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-arm64/-/bcrypt-darwin-arm64-1.9.0.tgz", - "integrity": "sha512-CQiS+F9Pa0XozvkXR1g7uXE9QvBOPOplDg0iCCPRYTN9PqA5qYxhwe48G3o+v2UeQceNRrbnEtWuANm7JRqIhw==", + "node_modules/@next/swc-darwin-arm64": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.4.tgz", + "integrity": "sha512-wBEMBs+np+R5ozN1F8Y8d/Dycns2COhRnkxRc+rvnbXke5uZBHkUGFgWxfTXn5rx7OLijuUhyfB+gC/ap58dDw==", "cpu": [ "arm64" ], @@ -4232,10 +2891,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-darwin-x64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-darwin-x64/-/bcrypt-darwin-x64-1.9.0.tgz", - "integrity": "sha512-4pTKGawYd7sNEjdJ7R/R67uwQH1VvwPZ0SSUMmeNHbxD5QlwAPXdDH11q22uzVXsvNFZ6nGQBg8No5OUGpx6Ug==", + "node_modules/@next/swc-darwin-x64": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.4.tgz", + "integrity": "sha512-7sgf5rM7Z81V9w48F02Zz6DgEJulavC0jadab4ZsJ+K2sxMNK0/BtF8J8J3CxnsJN3DGcIdC260wEKssKTukUw==", "cpu": [ "x64" ], @@ -4248,42 +2907,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-freebsd-x64": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-freebsd-x64/-/bcrypt-freebsd-x64-1.9.0.tgz", - "integrity": "sha512-UmWzySX4BJhT/B8xmTru6iFif3h0Rpx3TqxRLCcbgmH43r7k5/9QuhpiyzpvKGpKHJCFNm4F3rC2wghvw5FCIg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-arm-gnueabihf": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm-gnueabihf/-/bcrypt-linux-arm-gnueabihf-1.9.0.tgz", - "integrity": "sha512-8qoX4PgBND2cVwsbajoAWo3NwdfJPEXgpCsZQZURz42oMjbGyhhSYbovBCskGU3EBLoC8RA2B1jFWooeYVn5BA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@node-rs/bcrypt-linux-arm64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-gnu/-/bcrypt-linux-arm64-gnu-1.9.0.tgz", - "integrity": "sha512-TuAC6kx0SbcIA4mSEWPi+OCcDjTQUMl213v5gMNlttF+D4ieIZx6pPDGTaMO6M2PDHTeCG0CBzZl0Lu+9b0c7Q==", + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.4.tgz", + "integrity": "sha512-JaZlIMNaJenfd55kjaLWMfok+vWBlcRxqnRoZrhFQrhM1uAehP3R0+Aoe+bZOogqlZvAz53nY/k3ZyuKDtT2zQ==", "cpu": [ "arm64" ], @@ -4296,10 +2923,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-linux-arm64-musl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-arm64-musl/-/bcrypt-linux-arm64-musl-1.9.0.tgz", - "integrity": "sha512-/sIvKDABOI8QOEnLD7hIj02BVaNOuCIWBKvxcJOt8+TuwJ6zmY1UI5kSv9d99WbiHjTp97wtAUbZQwauU4b9ew==", + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.4.tgz", + "integrity": "sha512-7EBBjNoyTO2ipMDgCiORpwwOf5tIueFntKjcN3NK+GAQD7OzFJe84p7a2eQUeWdpzZvhVXuAtIen8QcH71ZCOQ==", "cpu": [ "arm64" ], @@ -4312,10 +2939,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-linux-x64-gnu": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-gnu/-/bcrypt-linux-x64-gnu-1.9.0.tgz", - "integrity": "sha512-DyyhDHDsLBsCKz1tZ1hLvUZSc1DK0FU0v52jK6IBQxrj24WscSU9zZe7ie/V9kdmA4Ep57BfpWX8Dsa2JxGdgQ==", + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.4.tgz", + "integrity": "sha512-9TGEgOycqZFuADyFqwmK/9g6S0FYZ3tphR4ebcmCwhL8Y12FW8pIBKJvSwV+UBjMkokstGNH+9F8F031JZKpHw==", "cpu": [ "x64" ], @@ -4328,10 +2955,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-linux-x64-musl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-linux-x64-musl/-/bcrypt-linux-x64-musl-1.9.0.tgz", - "integrity": "sha512-duIiuqQ+Lew8ASSAYm6ZRqcmfBGWwsi81XLUwz86a2HR7Qv6V4yc3ZAUQovAikhjCsIqe8C11JlAZSK6+PlXYg==", + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.4.tgz", + "integrity": "sha512-0578bLRVDJOh+LdIoKvgNDz77+Bd85c5JrFgnlbI1SM3WmEQvsjxTA8ATu9Z9FCiIS/AliVAW2DV/BDwpXbtiQ==", "cpu": [ "x64" ], @@ -4344,29 +2971,10 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-wasm32-wasi": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-wasm32-wasi/-/bcrypt-wasm32-wasi-1.9.0.tgz", - "integrity": "sha512-ylaGmn9Wjwv/D5lxtawttx3H6Uu2WTTR7lWlRHGT6Ga/MB1Vj4OjSGUW8G8zIVnKuXpGbZ92pgHlt4HUpSLctw==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^0.45.0", - "@emnapi/runtime": "^0.45.0", - "@tybys/wasm-util": "^0.8.1", - "memfs-browser": "^3.4.13000" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@node-rs/bcrypt-win32-arm64-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-arm64-msvc/-/bcrypt-win32-arm64-msvc-1.9.0.tgz", - "integrity": "sha512-2h86gF7QFyEzODuDFml/Dp1MSJoZjxJ4yyT2Erf4NkwsiA5MqowUhUsorRwZhX6+2CtlGa7orbwi13AKMsYndw==", + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.4.tgz", + "integrity": "sha512-JgFCiV4libQavwII+kncMCl30st0JVxpPOtzWcAI2jtum4HjYaclobKhj+JsRu5tFqMtA5CJIa0MvYyuu9xjjQ==", "cpu": [ "arm64" ], @@ -4379,12 +2987,12 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-win32-ia32-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-ia32-msvc/-/bcrypt-win32-ia32-msvc-1.9.0.tgz", - "integrity": "sha512-kqxalCvhs4FkN0+gWWfa4Bdy2NQAkfiqq/CEf6mNXC13RSV673Ev9V8sRlQyNpCHCNkeXfOT9pgoBdJmMs9muA==", + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.1.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.4.tgz", + "integrity": "sha512-xxsJy9wzq7FR5SqPCUqdgSXiNXrMuidgckBa8nH9HtjjxsilgcN6VgXF6tZ3uEWuVEadotQJI8/9EQ6guTC4Yw==", "cpu": [ - "ia32" + "x64" ], "license": "MIT", "optional": true, @@ -4395,20 +3003,23 @@ "node": ">= 10" } }, - "node_modules/@node-rs/bcrypt-win32-x64-msvc": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@node-rs/bcrypt-win32-x64-msvc/-/bcrypt-win32-x64-msvc-1.9.0.tgz", - "integrity": "sha512-2y0Tuo6ZAT2Cz8V7DHulSlv1Bip3zbzeXyeur+uR25IRNYXKvI/P99Zl85Fbuu/zzYAZRLLlGTRe6/9IHofe/w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "node_modules/@nextjournal/lang-clojure": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@nextjournal/lang-clojure/-/lang-clojure-1.0.0.tgz", + "integrity": "sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==", + "license": "ISC", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@nextjournal/lezer-clojure": "1.0.0" + } + }, + "node_modules/@nextjournal/lezer-clojure": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@nextjournal/lezer-clojure/-/lezer-clojure-1.0.0.tgz", + "integrity": "sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==", + "license": "ISC", + "dependencies": { + "@lezer/lr": "^1.0.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -4456,42 +3067,10 @@ "node": ">=12.4.0" } }, - "node_modules/@oslojs/asn1": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oslojs/asn1/-/asn1-1.0.0.tgz", - "integrity": "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==", - "license": "MIT", - "dependencies": { - "@oslojs/binary": "1.0.0" - } - }, - "node_modules/@oslojs/binary": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oslojs/binary/-/binary-1.0.0.tgz", - "integrity": "sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==", - "license": "MIT" - }, - "node_modules/@oslojs/crypto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@oslojs/crypto/-/crypto-1.0.1.tgz", - "integrity": "sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==", - "license": "MIT", - "dependencies": { - "@oslojs/asn1": "1.0.0", - "@oslojs/binary": "1.0.0" - } - }, - "node_modules/@oslojs/encoding": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", - "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", - "license": "MIT" - }, "node_modules/@outerbase/sdk-transform": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@outerbase/sdk-transform/-/sdk-transform-1.0.1.tgz", - "integrity": "sha512-WxAf3oQS92JEQARrpEv66q2hdo8HMI5Gj/8FTJ1szEK0g0A4NlQSFPXOlLAZdJXz7AnQO8Q5UpRavCtzDJCDEg==", - "license": "MIT" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@outerbase/sdk-transform/-/sdk-transform-1.0.5.tgz", + "integrity": "sha512-JOBHD8svYDxK77Myr9peSWgr4eR/+Pu3Lv8i+A4o42Wz08Vb6b/bVOkvjkOjLY4ZD6sApeIdOKXLjOM3Gr4Pfg==" }, "node_modules/@phosphor-icons/react": { "version": "2.1.7", @@ -4506,16 +3085,6 @@ "react-dom": ">= 16.8" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", @@ -4635,6 +3204,36 @@ } } }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz", + "integrity": "sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", @@ -5607,13 +4206,6 @@ "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", "license": "MIT" }, - "node_modules/@remirror/core-constants": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", - "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", - "license": "MIT", - "peer": true - }, "node_modules/@replit/codemirror-indentation-markers": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/@replit/codemirror-indentation-markers/-/codemirror-indentation-markers-6.5.3.tgz", @@ -6179,107 +4771,6 @@ } } }, - "node_modules/@tiptap/core": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.11.3.tgz", - "integrity": "sha512-ibfi6U1gMRLo319Re6olv8uAuxtUpK343ygcVoZrJ8O4sqRnU9CEqPAM+n7YAKlOks1+Di0sTheIxZRak7Pj4g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/pm": "^2.7.0" - } - }, - "node_modules/@tiptap/extension-bubble-menu": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.11.3.tgz", - "integrity": "sha512-KOAy9zCzqssJO7cGIwZNgv2hFyxrZ2AHoWptICPA79nVZrHQQw2ZP1/FDTR8cDEZzLQMbpgGqQhUhjZcAs3/zQ==", - "license": "MIT", - "dependencies": { - "tippy.js": "^6.3.7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.7.0", - "@tiptap/pm": "^2.7.0" - } - }, - "node_modules/@tiptap/extension-floating-menu": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.11.3.tgz", - "integrity": "sha512-Za1x475cvv+URegCsoDr8rZI5GIoC4N6rHg/xqmozY4bA326Ko1cMrUbwpVF6p17nerDGAMCIstZM7SSUQdNSA==", - "license": "MIT", - "dependencies": { - "tippy.js": "^6.3.7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.7.0", - "@tiptap/pm": "^2.7.0" - } - }, - "node_modules/@tiptap/pm": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.3.tgz", - "integrity": "sha512-AEpiWvYmXdELpuGGhX6lS2aU155ANwS7WbQ/+/SFqH3YIYHjgUzP8UnY6KSiEBI7a7kX4TWhG84mWrzPA3dPaw==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-changeset": "^2.2.1", - "prosemirror-collab": "^1.3.1", - "prosemirror-commands": "^1.6.2", - "prosemirror-dropcursor": "^1.8.1", - "prosemirror-gapcursor": "^1.3.2", - "prosemirror-history": "^1.4.1", - "prosemirror-inputrules": "^1.4.0", - "prosemirror-keymap": "^1.2.2", - "prosemirror-markdown": "^1.13.1", - "prosemirror-menu": "^1.2.4", - "prosemirror-model": "^1.23.0", - "prosemirror-schema-basic": "^1.2.3", - "prosemirror-schema-list": "^1.4.1", - "prosemirror-state": "^1.4.3", - "prosemirror-tables": "^1.6.1", - "prosemirror-trailing-node": "^3.0.0", - "prosemirror-transform": "^1.10.2", - "prosemirror-view": "^1.37.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - } - }, - "node_modules/@tiptap/react": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.11.3.tgz", - "integrity": "sha512-tNY/xJ7swV1Ffc6W5CSEWJnBo3grDapkZnd2udSTJ7/zYMUe+vSN2bcdKga2Zo2rAC0WFuLUl27iUhrZ29FFuQ==", - "license": "MIT", - "dependencies": { - "@tiptap/extension-bubble-menu": "^2.11.3", - "@tiptap/extension-floating-menu": "^2.11.3", - "@types/use-sync-external-store": "^0.0.6", - "fast-deep-equal": "^3", - "use-sync-external-store": "^1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^2.7.0", - "@tiptap/pm": "^2.7.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -6318,16 +4809,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.8.3.tgz", - "integrity": "sha512-Z96T/L6dUFFxgFJ+pQtkPpne9q7i6kIPYCFnQBHSgSPV9idTsKfIhCss0h5iM9irweZCatkrdeP8yi5uM1eX6Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/acorn": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", @@ -6390,12 +4871,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", @@ -6465,7 +4940,7 @@ "version": "1.40.0", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.40.0.tgz", "integrity": "sha512-MD2JJ25S4tnjnhjWyalMS6K6p0h+zQV6+Ylm+aGbiS8tSn/aHLSGNzBgduj6FB4zH0ax2GRMGYi/8G1uOxhXWA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/estree": { @@ -6607,13 +5082,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "license": "MIT", - "peer": true - }, "node_modules/@types/lodash": { "version": "4.17.14", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", @@ -6621,17 +5089,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" - } - }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -6641,13 +5098,6 @@ "@types/unist": "*" } }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "license": "MIT", - "peer": true - }, "node_modules/@types/mdx": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", @@ -6695,6 +5145,18 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-color": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.13.tgz", + "integrity": "sha512-2c/9FZ4ixC5T3JzN0LP5Cke2Mf0MKOP2Eh0NPDPWmuVH3NjPyhEjqNMQpN1Phr5m74egAy+p2lYNAFrX1z9Yrg==", + "dev": true, + "dependencies": { + "@types/reactcss": "*" + }, + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.3.5", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", @@ -6713,6 +5175,15 @@ "@types/react": "*" } }, + "node_modules/@types/reactcss": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.13.tgz", + "integrity": "sha512-gi3S+aUi6kpkF5vdhUsnkwbiSEIU/BEJyD7kBy2SudWBUuKmJk8AQKE0OVcQQeEy40Azh0lV6uynxlikYIJuwg==", + "dev": true, + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -6730,7 +5201,7 @@ "version": "1.4.9", "resolved": "https://registry.npmjs.org/@types/sql.js/-/sql.js-1.4.9.tgz", "integrity": "sha512-ep8b36RKHlgWPqjNG9ToUrPiwkhwh0AEzy883mO5Xnd+cL6VBH1EvSjBAAuxLUFF2Vn/moE3Me6v9E1Lo+48GQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/emscripten": "*", @@ -6757,12 +5228,6 @@ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", - "license": "MIT" - }, "node_modules/@types/wicg-file-system-access": { "version": "2023.10.5", "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.5.tgz", @@ -7340,26 +5805,6 @@ "node": ">= 8" } }, - "node_modules/arctic": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/arctic/-/arctic-1.9.2.tgz", - "integrity": "sha512-VTnGpYx+ypboJdNrWnK17WeD7zN/xSCHnpecd5QYsBfVZde/5i+7DJ1wrf/ioSDMiEjagXmyNWAE3V2C9f1hNg==", - "license": "MIT", - "dependencies": { - "oslo": "1.2.0" - } - }, - "node_modules/arctic/node_modules/oslo": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/oslo/-/oslo-1.2.0.tgz", - "integrity": "sha512-OoFX6rDsNcOQVAD2gQD/z03u4vEjWZLzJtwkmgfRF+KpQUXwdgEXErD7zNhyowmHwHefP+PM9Pw13pgpHMRlzw==", - "deprecated": "Package is no longer supported. Please see https://oslojs.dev for the successor project.", - "license": "MIT", - "dependencies": { - "@node-rs/argon2": "1.7.0", - "@node-rs/bcrypt": "1.9.0" - } - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -7908,19 +6353,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", - "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001695", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", @@ -8071,23 +6503,6 @@ "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", "license": "MIT" }, - "node_modules/cli-color": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", - "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.64", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -8285,41 +6700,6 @@ "devOptional": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookies-next": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-4.3.0.tgz", - "integrity": "sha512-XxeCwLR30cWwRd94sa9X5lRCDLVujtx73tv+N0doQCFIDl83fuuYdxbu/WQUt9aSV7EJx7bkMvJldjvzuFqr4w==", - "license": "MIT", - "dependencies": { - "@types/cookie": "^0.6.0", - "cookie": "^0.7.0" - } - }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -8421,20 +6801,6 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, - "node_modules/d": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", - "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -8841,18 +7207,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/difflib": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", - "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", - "dev": true, - "dependencies": { - "heap": ">= 0.2.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -8886,225 +7240,35 @@ "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/domexception": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", - "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "license": "MIT", - "dependencies": { - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/download-yue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/download-yue/-/download-yue-2.1.0.tgz", - "integrity": "sha512-ECsv6WVYCBCFrCnBcpHTCgFsRM/h7C/AtrzXuTc8+xaW5lXj+Jw6c5S7Eq/ncix41h05JerSxan5p7p80H35qQ==", - "dev": true, - "license": "MIT", - "bin": { - "download-yue": "download-yue.js" - } - }, - "node_modules/dreamopt": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz", - "integrity": "sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==", - "dev": true, - "dependencies": { - "wordwrap": ">=0.0.2" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/drizzle-kit": { - "version": "0.20.18", - "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.20.18.tgz", - "integrity": "sha512-fLTwcnLqtBxGd+51H/dEm9TC0FW6+cIX/RVPyNcitBO77X9+nkogEfMAJebpd/8Yl4KucmePHRYRWWvUlW0rqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@esbuild-kit/esm-loader": "^2.5.5", - "@hono/node-server": "^1.9.0", - "@hono/zod-validator": "^0.2.0", - "camelcase": "^7.0.1", - "chalk": "^5.2.0", - "commander": "^9.4.1", - "env-paths": "^3.0.0", - "esbuild": "^0.19.7", - "esbuild-register": "^3.5.0", - "glob": "^8.1.0", - "hanji": "^0.0.5", - "hono": "^4.1.4", - "json-diff": "0.9.0", - "minimatch": "^7.4.3", - "semver": "^7.5.4", - "superjson": "^2.2.1", - "zod": "^3.20.2" - }, - "bin": { - "drizzle-kit": "bin.cjs" - } - }, - "node_modules/drizzle-kit/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } + "peer": true }, - "node_modules/drizzle-kit/node_modules/minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/drizzle-orm": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.30.10.tgz", - "integrity": "sha512-IRy/QmMWw9lAQHpwbUh1b8fcn27S/a9zMIzqea1WNOxK9/4EB8gIo+FZWLiPXzl2n9ixGSv8BhsLZiOppWEwBw==", - "license": "Apache-2.0", - "peerDependencies": { - "@aws-sdk/client-rds-data": ">=3", - "@cloudflare/workers-types": ">=3", - "@electric-sql/pglite": ">=0.1.1", - "@libsql/client": "*", - "@neondatabase/serverless": ">=0.1", - "@op-engineering/op-sqlite": ">=2", - "@opentelemetry/api": "^1.4.1", - "@planetscale/database": ">=1", - "@types/better-sqlite3": "*", - "@types/pg": "*", - "@types/react": ">=18", - "@types/sql.js": "*", - "@vercel/postgres": ">=0.8.0", - "@xata.io/client": "*", - "better-sqlite3": ">=7", - "bun-types": "*", - "expo-sqlite": ">=13.2.0", - "knex": "*", - "kysely": "*", - "mysql2": ">=2", - "pg": ">=8", - "postgres": ">=3", - "react": ">=18", - "sql.js": ">=1", - "sqlite3": ">=5" + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@aws-sdk/client-rds-data": { - "optional": true - }, - "@cloudflare/workers-types": { - "optional": true - }, - "@electric-sql/pglite": { - "optional": true - }, - "@libsql/client": { - "optional": true - }, - "@neondatabase/serverless": { - "optional": true - }, - "@op-engineering/op-sqlite": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@planetscale/database": { - "optional": true - }, - "@types/better-sqlite3": { - "optional": true - }, - "@types/pg": { - "optional": true - }, - "@types/react": { - "optional": true - }, - "@types/sql.js": { - "optional": true - }, - "@vercel/postgres": { - "optional": true - }, - "@xata.io/client": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "bun-types": { - "optional": true - }, - "expo-sqlite": { - "optional": true - }, - "knex": { - "optional": true - }, - "kysely": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "postgres": { - "optional": true - }, - "react": { - "optional": true - }, - "sql.js": { - "optional": true - }, - "sqlite3": { - "optional": true - } + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dunder-proto": { @@ -9187,6 +7351,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -9195,19 +7360,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -9406,62 +7558,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.64", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", - "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", - "dev": true, - "hasInstallScript": true, - "license": "ISC", - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "esniff": "^2.0.1", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", - "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "ext": "^1.7.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/esast-util-from-estree": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", @@ -9494,58 +7590,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, - "node_modules/esbuild-register": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", - "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "peerDependencies": { - "esbuild": ">=0.12 <1" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -10233,22 +8277,6 @@ "node": "*" } }, - "node_modules/esniff": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", - "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -10413,17 +8441,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -10474,16 +8491,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "license": "ISC", - "dependencies": { - "type": "^2.7.2" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -10699,12 +8706,32 @@ "node": ">=0.8" } }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "license": "Unlicense", - "optional": true + "node_modules/framer-motion": { + "version": "12.4.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.4.3.tgz", + "integrity": "sha512-rsMeO7w3dKyNG09o3cGwSH49iHU+VgDmfSSfsX+wfkO3zDA6WWkh4sUsMXd155YROjZP+7FTIhDrBYfgZeHjKQ==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.0.0", + "motion-utils": "^12.0.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -10898,27 +8925,6 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -10931,19 +8937,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -11021,28 +9014,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "license": "MIT" }, - "node_modules/gui": { - "version": "0.15.6", - "resolved": "https://registry.npmjs.org/gui/-/gui-0.15.6.tgz", - "integrity": "sha512-IYKRiCY1ys9cBVxn38yqwlDM6XOehoreTu8R8JcmQ4IDsTrYWlJxHeAa1RGZ75QP9tQG185vMTW1c5ulEBRmkg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "download-yue": "2.1.x" - } - }, - "node_modules/hanji": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/hanji/-/hanji-0.0.5.tgz", - "integrity": "sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==", - "dev": true, - "license": "ISC", - "dependencies": { - "lodash.throttle": "^4.1.1", - "sisteransi": "^1.0.5" - } - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -11223,23 +9194,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/heap": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true, - "license": "MIT" - }, - "node_modules/hono": { - "version": "4.6.18", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.6.18.tgz", - "integrity": "sha512-Fu7hEPvdwtPG8LqSAiPn8p8HjD+PDxrP/HVnwRBnwtVKOn5zDDKsw0ma2Xt58oq97Rlp3t/mRNADEV/Ym6cDng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.9.0" - } - }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -11788,13 +9742,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -11946,19 +9893,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -13208,24 +11142,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "license": "MIT" }, - "node_modules/json-diff": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.9.0.tgz", - "integrity": "sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-color": "^2.0.0", - "difflib": "~0.2.1", - "dreamopt": "~0.8.0" - }, - "bin": { - "json-diff": "bin/json-diff.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -13636,19 +11552,9 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "uc.micro": "^2.0.0" - } + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "devOptional": true, + "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", @@ -13671,19 +11577,17 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "license": "MIT" }, - "node_modules/lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -13716,26 +11620,6 @@ "yallist": "^3.0.2" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/lucia": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/lucia/-/lucia-3.2.2.tgz", - "integrity": "sha512-P1FlFBGCMPMXu+EGdVD9W4Mjm0DqsusmKgO7Xc33mI5X1bklmsQb0hfzPhXomQr9waWIBDsiOjvr1e6BTaUqpA==", - "license": "MIT", - "dependencies": { - "@oslojs/crypto": "^1.0.1", - "@oslojs/encoding": "^1.1.0" - } - }, "node_modules/lucide-react": { "version": "0.474.0", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.474.0.tgz", @@ -13801,23 +11685,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } + "node_modules/material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" }, "node_modules/math-intrinsics": { "version": "1.1.0", @@ -13998,56 +11869,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "license": "MIT", - "peer": true - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "license": "Unlicense", - "optional": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/memfs-browser": { - "version": "3.5.10302", - "resolved": "https://registry.npmjs.org/memfs-browser/-/memfs-browser-3.5.10302.tgz", - "integrity": "sha512-JJTc/nh3ig05O0gBBGZjTCPOyydaTxNF0uHYBrcc1gHNnO+KIHIvo0Y1FKCJsaei6FCl8C6xfQomXqu+cuzkIw==", - "license": "Unlicense", - "optional": true, - "dependencies": { - "memfs": "3.5.3" - } - }, - "node_modules/memoizee": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", - "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", - "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.2", - "es5-ext": "^0.10.64", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -14748,6 +12569,47 @@ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", "license": "BSD-3-Clause" }, + "node_modules/motion": { + "version": "12.4.3", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.4.3.tgz", + "integrity": "sha512-KeoMpKFEVdofN0v/z1g3tm4cMtk1WAHQ5Pg7M1ElxeRLA8cBSrkmSCJ9q6hLo7spp/n906h2kmeDNvBkysaxcQ==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.4.3", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.0.0.tgz", + "integrity": "sha512-CvYd15OeIR6kHgMdonCc1ihsaUG4MYh/wrkz8gZ3hBX/uamyZCXN9S9qJoYF03GqfTt7thTV/dxnHYX4+55vDg==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.0.0" + } + }, + "node_modules/motion-utils": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.0.0.tgz", + "integrity": "sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -14870,13 +12732,6 @@ "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true, - "license": "ISC" - }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -15174,24 +13029,6 @@ "node": ">= 0.8.0" } }, - "node_modules/orderedmap": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", - "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", - "license": "MIT", - "peer": true - }, - "node_modules/oslo": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/oslo/-/oslo-1.2.1.tgz", - "integrity": "sha512-HfIhB5ruTdQv0XX2XlncWQiJ5SIHZ7NHZhVyHth0CSZ/xzge00etRyYy/3wp/Dsu+PkxMC+6+B2lS/GcKoewkA==", - "deprecated": "Package is no longer supported. Please see https://oslojs.dev for the successor project.", - "license": "MIT", - "dependencies": { - "@node-rs/argon2": "1.7.0", - "@node-rs/bcrypt": "1.9.0" - } - }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", @@ -15672,219 +13509,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/prosemirror-changeset": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz", - "integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-collab": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", - "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-state": "^1.0.0" - } - }, - "node_modules/prosemirror-commands": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.6.2.tgz", - "integrity": "sha512-0nDHH++qcf/BuPLYvmqZTUUsPJUCPBUXt0J1ErTcDIS369CTp773itzLGIgIXG4LJXOlwYCr44+Mh4ii6MP1QA==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.10.2" - } - }, - "node_modules/prosemirror-dropcursor": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.1.tgz", - "integrity": "sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0", - "prosemirror-view": "^1.1.0" - } - }, - "node_modules/prosemirror-gapcursor": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", - "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-keymap": "^1.0.0", - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-view": "^1.0.0" - } - }, - "node_modules/prosemirror-history": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", - "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-state": "^1.2.2", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.31.0", - "rope-sequence": "^1.3.0" - } - }, - "node_modules/prosemirror-inputrules": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.4.0.tgz", - "integrity": "sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.0.0" - } - }, - "node_modules/prosemirror-keymap": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz", - "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-state": "^1.0.0", - "w3c-keyname": "^2.2.0" - } - }, - "node_modules/prosemirror-markdown": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.1.tgz", - "integrity": "sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/markdown-it": "^14.0.0", - "markdown-it": "^14.0.0", - "prosemirror-model": "^1.20.0" - } - }, - "node_modules/prosemirror-menu": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.4.tgz", - "integrity": "sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==", - "license": "MIT", - "peer": true, - "dependencies": { - "crelt": "^1.0.0", - "prosemirror-commands": "^1.0.0", - "prosemirror-history": "^1.0.0", - "prosemirror-state": "^1.0.0" - } - }, - "node_modules/prosemirror-model": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.24.1.tgz", - "integrity": "sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg==", - "license": "MIT", - "peer": true, - "dependencies": { - "orderedmap": "^2.0.0" - } - }, - "node_modules/prosemirror-schema-basic": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz", - "integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.19.0" - } - }, - "node_modules/prosemirror-schema-list": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.0.tgz", - "integrity": "sha512-gg1tAfH1sqpECdhIHOA/aLg2VH3ROKBWQ4m8Qp9mBKrOxQRW61zc+gMCI8nh22gnBzd1t2u1/NPLmO3nAa3ssg==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.7.3" - } - }, - "node_modules/prosemirror-state": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", - "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.0.0", - "prosemirror-transform": "^1.0.0", - "prosemirror-view": "^1.27.0" - } - }, - "node_modules/prosemirror-tables": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.6.2.tgz", - "integrity": "sha512-97dKocVLrEVTQjZ4GBLdrrMw7Gv3no8H8yMwf5IRM9OoHrzbWpcH5jJxYgNQIRCtdIqwDctT1HdMHrGTiwp1dQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-keymap": "^1.2.2", - "prosemirror-model": "^1.24.1", - "prosemirror-state": "^1.4.3", - "prosemirror-transform": "^1.10.2", - "prosemirror-view": "^1.37.1" - } - }, - "node_modules/prosemirror-trailing-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", - "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@remirror/core-constants": "3.0.0", - "escape-string-regexp": "^4.0.0" - }, - "peerDependencies": { - "prosemirror-model": "^1.22.1", - "prosemirror-state": "^1.4.2", - "prosemirror-view": "^1.33.8" - } - }, - "node_modules/prosemirror-transform": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.2.tgz", - "integrity": "sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.21.0" - } - }, - "node_modules/prosemirror-view": { - "version": "1.37.2", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.37.2.tgz", - "integrity": "sha512-ApcyrfV/cRcaL65on7TQcfWElwLyOgIjnIynfAuV+fIdlpbSvSWRwfuPaH7T5mo4AbO/FID29qOtjiDIKGWyog==", - "license": "MIT", - "peer": true, - "dependencies": { - "prosemirror-model": "^1.20.0", - "prosemirror-state": "^1.0.0", - "prosemirror-transform": "^1.1.0" - } - }, "node_modules/psl": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", @@ -15907,16 +13531,6 @@ "node": ">=6" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -15989,6 +13603,23 @@ "node": ">=0.10.0" } }, + "node_modules/react-color": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.19.3.tgz", + "integrity": "sha512-LEeGE/ZzNLIsFWa1TMe8y5VYqr7bibneWmvJwm1pCn/eNmrabWDh659JSPn9BuaMpEfU83WTOJfnCcjDZwNQTA==", + "dependencies": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.15", + "lodash-es": "^4.17.15", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-dom": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", @@ -16138,6 +13769,14 @@ } } }, + "node_modules/reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "dependencies": { + "lodash": "^4.0.1" + } + }, "node_modules/recma-build-jsx": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", @@ -16528,13 +14167,6 @@ "node": "*" } }, - "node_modules/rope-sequence": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", - "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", - "license": "MIT", - "peer": true - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -16942,27 +14574,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", @@ -17315,19 +14926,6 @@ } } }, - "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-anything": "^3.0.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -17475,28 +15073,10 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "license": "MIT" }, - "node_modules/timers-ext": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", - "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", - "dev": true, - "license": "ISC", - "dependencies": { - "es5-ext": "^0.10.64", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/tippy.js": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", - "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", - "license": "MIT", - "dependencies": { - "@popperjs/core": "^2.9.0" - } + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" }, "node_modules/tmpl": { "version": "1.0.5", @@ -18137,13 +15717,6 @@ "@esbuild/win32-x64": "0.23.1" } }, - "node_modules/type": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", - "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true, - "license": "ISC" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -18269,13 +15842,6 @@ "node": ">=14.17" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "license": "MIT", - "peer": true - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -18786,13 +16352,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index 3fb9fa50..bf0951ce 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,16 @@ { - "name": "@libsqlstudio/studio", - "version": "0.9.2", + "name": "@outerbase/studio", + "version": "0.10", "private": false, "scripts": { "dev": "next dev -p 3008", "dev-https": "next dev --experimental-https", "build": "next build", - "build-with-migrate": "npm run db:migrate && next build", "start": "next start", "tsc": "tsc --noEmit --skipLibCheck", "test": "jest", "test:coverage": "jest --coverage", "test:watch": "jest --watch", - "db:generate": "drizzle-kit generate:sqlite", - "db:migrate": "tsx src/db/migrate.ts", "generate-random-key": "tsx src/cli/generate-aes-key.ts", "staged": "npm run typecheck && npm run lint && jest", "typecheck": "tsc --noEmit --skipLibCheck", @@ -21,8 +18,7 @@ "format:fix": "prettier --write .", "lint": "next lint", "lint:fix": "next lint --fix .", - "dialect": "node build-dialect.js", - "remove-branch": "npx git-removed-branches --prune -f" + "dialect": "node build-dialect.js" }, "overrides": { "@libsql/client": "^0.5.3" @@ -30,23 +26,23 @@ "dependencies": { "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-sql": "^6.5.5", + "@codemirror/merge": "^6.8.0", "@dagrejs/dagre": "^1.1.4", "@dnd-kit/core": "^6.1.0", "@dnd-kit/modifiers": "^7.0.0", "@dnd-kit/sortable": "^8.0.0", - "@justmiracle/result": "^1.2.0", "@lezer/common": "^1.2.1", "@lezer/lr": "^1.4.0", "@libsql/client": "^0.5.3", - "@lucia-auth/adapter-sqlite": "^3.0.1", "@mdx-js/loader": "^3.0.1", "@mdx-js/react": "^3.0.1", "@next/mdx": "^14.2.4", - "@outerbase/sdk-transform": "^1.0.1", + "@outerbase/sdk-transform": "^1.0.5", "@phosphor-icons/react": "^2.1.7", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-collapsible": "^1.1.2", "@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", @@ -66,8 +62,6 @@ "@radix-ui/react-tooltip": "^1.0.7", "@replit/codemirror-indentation-markers": "^6.5.3", "@t3-oss/env-nextjs": "^0.9.2", - "@tiptap/core": "^2.3.0", - "@tiptap/react": "^2.3.0", "@types/mdx": "^2.0.13", "@types/react-grid-layout": "^1.3.5", "@uiw/codemirror-extensions-langs": "^4.21.24", @@ -75,15 +69,12 @@ "@uiw/react-codemirror": "^4.21.21", "@vercel/analytics": "^1.3.1", "@xyflow/react": "^12.3.6", - "arctic": "^1.2.1", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.4", - "cookies-next": "^4.3.0", "deep-equal": "^2.2.3", "dexie": "^4.0.8", "dotenv": "^16.4.5", - "drizzle-orm": "^0.30.1", "echarts": "^5.6.0", "eslint-plugin-jest": "^27.6.3", "file-saver": "^2.0.5", @@ -91,12 +82,12 @@ "immer": "^10.1.1", "libsql-stateless-easy": "^1.6.11", "lodash": "^4.17.21", - "lucia": "^3.2.0", "lucide-react": "^0.474.0", + "motion": "^12.4.3", "next": "15.1.4", "next-themes": "^0.4.4", - "oslo": "^1.1.3", "react": "19.0.0", + "react-color": "^2.19.3", "react-dom": "19.0.0", "react-grid-layout": "^1.5.0", "react-resizable-panels": "^2.1.7", @@ -119,16 +110,15 @@ "@types/lodash": "^4.17.9", "@types/node": "^20", "@types/react": "^18", + "@types/react-color": "^3.0.13", "@types/react-dom": "^18", "@types/showdown": "^2.0.6", "@types/sql.js": "^1.4.9", "@types/wicg-file-system-access": "^2023.10.5", "@typescript-eslint/eslint-plugin": "^6.21.0", "@typescript-eslint/parser": "^6.21.0", - "drizzle-kit": "^0.20.14", "eslint": "^8", "eslint-config-next": "14.0.4", - "gui": "^0.15.3", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "postcss": "^8.4.38", diff --git a/public/assets/clouds.jpg b/public/assets/clouds.jpg new file mode 100644 index 00000000..6559feb4 Binary files /dev/null and b/public/assets/clouds.jpg differ diff --git a/public/assets/onboarding_dark.svg b/public/assets/onboarding_dark.svg new file mode 100644 index 00000000..dbdee756 --- /dev/null +++ b/public/assets/onboarding_dark.svg @@ -0,0 +1,1553 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/assets/reset-password-orb.webp b/public/assets/reset-password-orb.webp new file mode 100644 index 00000000..87983bdf Binary files /dev/null and b/public/assets/reset-password-orb.webp differ diff --git a/public/assets/sat.png b/public/assets/sat.png new file mode 100644 index 00000000..3b249c01 Binary files /dev/null and b/public/assets/sat.png differ diff --git a/public/caret.svg b/public/caret.svg new file mode 100644 index 00000000..4b48370c --- /dev/null +++ b/public/caret.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/libsql-logo.png b/public/libsql-logo.png deleted file mode 100644 index eee4944c..00000000 Binary files a/public/libsql-logo.png and /dev/null differ diff --git a/script.sh b/script.sh deleted file mode 100644 index 62ac7a8d..00000000 --- a/script.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -echo "VERCEL_GIT_COMMIT_REF: $VERCEL_GIT_COMMIT_REF" - -if [[ "$VERCEL_GIT_COMMIT_REF" == "develop" || "$VERCEL_GIT_COMMIT_REF" == "master" ]] ; then - # Proceed with the build - echo "✅ - Build can proceed" - exit 1; - -else - # Don't build - echo "🛑 - Build cancelled" - exit 0; -fi \ No newline at end of file diff --git a/src/app/(dark-only)/layout.tsx b/src/app/(dark-only)/layout.tsx new file mode 100644 index 00000000..601b3a57 --- /dev/null +++ b/src/app/(dark-only)/layout.tsx @@ -0,0 +1,20 @@ +import { OuterbaseSessionProvider } from "@/app/(outerbase)/session-provider"; +import ClientOnly from "@/components/client-only"; +import { WorkspaceProvider } from "../(outerbase)/workspace-provider"; +import ThemeLayout from "../(theme)/theme_layout"; + +export default function OuterbaseLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + {children} + + + + ); +} diff --git a/src/app/(dark-only)/new-workspace/page.tsx b/src/app/(dark-only)/new-workspace/page.tsx new file mode 100644 index 00000000..cb104ac0 --- /dev/null +++ b/src/app/(dark-only)/new-workspace/page.tsx @@ -0,0 +1,97 @@ +"use client"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import OuterbaseLogo from "@/components/icons/outerbase"; +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { Label } from "@/components/orbit/label"; +import { strippedWorkspaceName } from "@/lib/utils"; +import { createOuterbaseWorkspace } from "@/outerbase-cloud/api-workspace"; +import useOuterbaseMutation from "@/outerbase-cloud/hook"; +import { useRouter } from "next/navigation"; +import { useCallback, useState } from "react"; + +const FRIENDLY_ERROR_NAME: Record = { + SHORT_NAME_TAKEN: "Workspace URL is unavailable.", +}; + +export default function NewWorkspacePage() { + const { + loading, + error, + trigger: createWorkspace, + } = useOuterbaseMutation(createOuterbaseWorkspace); + + const router = useRouter(); + const { refreshPartial } = useWorkspaces(); + const [name, setName] = useState(""); + const [shortName, setShortName] = useState(""); + + const finalShortName = shortName || strippedWorkspaceName(name); + + const onCreateClicked = useCallback(() => { + createWorkspace({ + name, + short_name: finalShortName, + }).then((workspace) => { + if (workspace) { + refreshPartial(workspace); + router.push(`/w/${workspace.short_name}`); + } + }); + }, [name, finalShortName, createWorkspace, refreshPartial, router]); + + return ( +
+
+
+
+ +
+ +

+ New Workspace +

+ + + + + + {error && ( +

+ {FRIENDLY_ERROR_NAME[error.message] ?? error.message} +

+ )} + +
+ +
+
+
+
+
+ ); +} diff --git a/src/app/(dark-only)/password_reset/page.tsx b/src/app/(dark-only)/password_reset/page.tsx new file mode 100644 index 00000000..f794c80f --- /dev/null +++ b/src/app/(dark-only)/password_reset/page.tsx @@ -0,0 +1,147 @@ +"use client"; +import OuterbaseLogo from "@/components/icons/outerbase"; +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { Label } from "@/components/orbit/label"; +import { isValidEmail } from "@/lib/validation"; +import { + requestResetPassword, + resetPassword, +} from "@/outerbase-cloud/api-account"; +import { SendHorizonal } from "lucide-react"; +import Link from "next/link"; +import { useRouter, useSearchParams } from "next/navigation"; +import { useCallback, useMemo, useState } from "react"; +import { toast } from "sonner"; + +export default function PasswordResetPage() { + const param = useSearchParams(); + const router = useRouter(); + const reset_token = param.get("reset_token"); + const [loading, setLoading] = useState(false); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [isSent, setIsSent] = useState(false); + + const onResetPassword = useCallback(() => { + if (!reset_token) return; + setLoading(true); + resetPassword({ + password, + reset_token, + }) + .then(() => { + toast.success("Your password has been reseted"); + router.replace("/signin"); + }) + .catch((error) => { + setLoading(false); + toast.error(`Error: ${error.message}`); + }); + }, [password, reset_token, router]); + + const onRequestResetPassword = useCallback(() => { + setLoading(true); + requestResetPassword({ email }) + .then(() => setIsSent(true)) + .catch((error) => { + setLoading(false); + toast.error(`Error: ${error.message}`); + }) + .finally(() => { + setLoading(false); + }); + }, [email]); + + const { title, description } = useMemo(() => { + let title, description; + + if (isSent) { + title = "Check your email"; + description = "We've sent a reset link to"; + } else if (reset_token) { + title = "Choose a new password"; + description = "Enter a new password for your account."; + } else { + title = "Reset your password"; + description = `Enter the email address you log in to Outerbase with, and we’ll email you a link to reset your password.`; + } + + return { title, description }; + }, [isSent, reset_token]); + + return ( +
+
+
+
+
+
+
+ + + +
+
+
{title}
+
+ {isSent && } + +

+ {description} + {isSent && ( + +
+ {email} +
+ )} +

+
+ {(!isSent || reset_token) && ( + <> + +
+
+
+
+
+
+
+ ); +} diff --git a/src/app/signin/page.tsx b/src/app/(dark-only)/signin/page.tsx similarity index 53% rename from src/app/signin/page.tsx rename to src/app/(dark-only)/signin/page.tsx index d64871e1..5661f39a 100644 --- a/src/app/signin/page.tsx +++ b/src/app/(dark-only)/signin/page.tsx @@ -1,19 +1,14 @@ "use client"; import LabelInput from "@/components/label-input"; -import { Button } from "@/components/ui/button"; +import { Button } from "@/components/orbit/button"; import { - getOuterbaseWorkspace, + getOuterbaseSession, loginOuterbaseByPassword, } from "@/outerbase-cloud/api"; -import { - OuterbaseAPIError, - OuterbaseAPISession, -} from "@/outerbase-cloud/api-type"; -import { LucideLoader } from "lucide-react"; +import { OuterbaseAPIError } from "@/outerbase-cloud/api-type"; import Link from "next/link"; import { useRouter } from "next/navigation"; -import { useCallback, useEffect, useState } from "react"; -import ThemeLayout from "../(theme)/theme_layout"; +import { useCallback, useState } from "react"; import { LoginBaseSpaceship } from "./starbase-portal"; export default function SigninPage() { @@ -22,17 +17,24 @@ export default function SigninPage() { const [error, setError] = useState(""); const router = useRouter(); const [loading, setLoading] = useState(false); - const [session, setSession] = useState(); const onLoginClicked = useCallback(() => { setLoading(true); loginOuterbaseByPassword(email, password) - .then((session) => { - localStorage.setItem("session", JSON.stringify(session)); + .then(async (session) => { localStorage.setItem("ob-token", session.token); + localStorage.setItem("session", JSON.stringify(session)); + + const { user } = await getOuterbaseSession(); - setSession(session); + if (user.has_otp) { + router.push("/verify"); + return; + } + + const redirect = localStorage.getItem("continue-redirect"); + router.push(redirect ?? "/"); }) .catch((e) => { setLoading(false); @@ -40,30 +42,10 @@ export default function SigninPage() { setError(e.description); } }); - }, [email, password]); - - useEffect(() => { - if (!session) return; - - const redirect = localStorage.getItem("continue-redirect"); - if (redirect) { - localStorage.removeItem("continue-redirect"); - router.push(redirect); - return; - } - - getOuterbaseWorkspace() - .then((w) => { - router.push(`/w/${w.items[0].short_name}`); - }) - .catch(console.error) - .finally(() => { - setLoading(false); - }); - }, [session, router]); + }, [email, password, router]); return ( - + <>
Sign in to your existing account

- setEmail(e.currentTarget.value)} - /> +
{ + onLoginClicked(); + e.preventDefault(); + }} + className="flex flex-col gap-4" + > + setEmail(e.currentTarget.value)} + /> - setPassword(e.currentTarget.value)} - /> + setPassword(e.currentTarget.value)} + /> - {error &&
{error}
} + {error &&
{error}
} - + + - + Forget password +
+ {`Don't have an account?`}{" "} + + Sign Up + +
- + ); } diff --git a/src/app/signin/starbase-portal.tsx b/src/app/(dark-only)/signin/starbase-portal.tsx similarity index 100% rename from src/app/signin/starbase-portal.tsx rename to src/app/(dark-only)/signin/starbase-portal.tsx diff --git a/src/app/signin/styles.css b/src/app/(dark-only)/signin/styles.css similarity index 100% rename from src/app/signin/styles.css rename to src/app/(dark-only)/signin/styles.css diff --git a/src/app/(dark-only)/signup-workspace/page.tsx b/src/app/(dark-only)/signup-workspace/page.tsx new file mode 100644 index 00000000..fb12b9bf --- /dev/null +++ b/src/app/(dark-only)/signup-workspace/page.tsx @@ -0,0 +1,164 @@ +"use client"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import { OuterbaseIcon } from "@/components/icons/outerbase"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { Label } from "@/components/orbit/label"; +import { Select } from "@/components/orbit/select"; +import { strippedWorkspaceName } from "@/lib/utils"; +import { updateOuterbaseUserProfile } from "@/outerbase-cloud/api-account"; +import { createOuterbaseWorkspace } from "@/outerbase-cloud/api-workspace"; +import { useRouter } from "next/navigation"; +import { useCallback, useState } from "react"; +import { LoginBaseSpaceship } from "../signin/starbase-portal"; +import { SpaceshipContentContainer } from "../spaceship-container"; + +function generateRandomString(length: number) { + const characters = "0123456789abcdefghijklmnopqrstuvwxyz"; + let result = ""; + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + result += characters[randomIndex]; + } + return result; +} + +export default function SignupPage() { + const router = useRouter(); + const [role, setRole] = useState(""); + const [companySize, setCompanySize] = useState(""); + const [firstName, setFirstName] = useState(""); + const [lastName, setLastName] = useState(""); + const [workspaceName, setWorkspaceName] = useState(""); + const [loading, setLoading] = useState(false); + const { refreshPartial } = useWorkspaces(); + + const createWorkspaceWithProfile = useCallback(async () => { + const random = generateRandomString(4); + const workspaceShortName = `${strippedWorkspaceName(workspaceName)}-${random}`; + + await updateOuterbaseUserProfile({ + first_name: firstName, + last_name: lastName, + }).then(() => {}); + + const createdWorkspace = await createOuterbaseWorkspace({ + name: workspaceName, + short_name: workspaceShortName, + }); + + refreshPartial(createdWorkspace); + router.push(`/w/${createdWorkspace.short_name}`); + }, [workspaceName, firstName, lastName, router, refreshPartial]); + + return ( + <> + +
+ + +

Create Workspace

+

Workspaces are a home for your databases.

+
+ +
{ + e.preventDefault(); + + setLoading(true); + createWorkspaceWithProfile() + .then() + .catch() + .finally(() => { + setLoading(false); + }); + }} + className="flex flex-col gap-4" + > + setFirstName(e.currentTarget.value)} + required + /> + + setLastName(e.currentTarget.value)} + required + /> + + setWorkspaceName(e.currentTarget.value)} + /> + + + + + +
+ + + ); +} diff --git a/src/app/(dark-only)/signup/page.tsx b/src/app/(dark-only)/signup/page.tsx new file mode 100644 index 00000000..c1a9b88d --- /dev/null +++ b/src/app/(dark-only)/signup/page.tsx @@ -0,0 +1,19 @@ +"use client"; +import { useSearchParams } from "next/navigation"; +import { LoginBaseSpaceship } from "../signin/starbase-portal"; +import { SignupForm } from "./signup-form"; +import { SignupOtp } from "./signup-otp"; + +//https://app.outerbase.com/api/v1/auth/register +export default function SignupPage() { + const searchParams = useSearchParams(); + + const verify = searchParams.get("verify") === "true"; + + return ( + <> + {verify ? : } + + + ); +} diff --git a/src/app/(dark-only)/signup/signup-form.tsx b/src/app/(dark-only)/signup/signup-form.tsx new file mode 100644 index 00000000..9b6ef272 --- /dev/null +++ b/src/app/(dark-only)/signup/signup-form.tsx @@ -0,0 +1,147 @@ +"use client"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + registerOuterbaseByPassword, + verifyOuterbaseRequestEmail, +} from "@/outerbase-cloud/api"; +import { + OuterbaseAPIError, + OuterbaseAPISession, +} from "@/outerbase-cloud/api-type"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useCallback, useEffect, useState } from "react"; + +export function SignupForm() { + const router = useRouter(); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const [loading, setLoading] = useState(false); + const [session, setSession] = useState(); + + const onRegisterClicked = useCallback(() => { + setLoading(true); + + registerOuterbaseByPassword(email, password) + .then((session) => { + localStorage.setItem("ob-token", session.token); + localStorage.setItem("session", JSON.stringify({ ...session, email })); + //Alway error 403 + verifyOuterbaseRequestEmail().then(() => { + setLoading(false); + localStorage.setItem("continue-redirect", "/signup?verify=true"); + setSession(session); + }); + }) + .catch((e) => { + setLoading(false); + if (e instanceof OuterbaseAPIError) { + setError(e.description); + } + }); + }, [email, password]); + + useEffect(() => { + if (!session) return; + + const redirect = localStorage.getItem("continue-redirect"); + if (redirect) { + router.push(redirect); + return; + } + + router.push("/"); + }, [session, router]); + + return ( +
+
+
+ + + + +

Create your Account

+

Sign up to get started with Outerbase

+
+ +
{ + e.preventDefault(); + }} + className="flex flex-col gap-4" + > + setEmail(e.currentTarget.value)} + /> + + setPassword(e.currentTarget.value)} + /> + + {error &&
{error}
} + + + +
+ Already have an account?{" "} + + Sign In + +
+
+
+ By signing up, you agree to our +
+ + Terms of Service + {" "} + and{" "} + + Privacy Policy + +
+
+ ); +} diff --git a/src/app/(dark-only)/signup/signup-otp.tsx b/src/app/(dark-only)/signup/signup-otp.tsx new file mode 100644 index 00000000..3eee92d1 --- /dev/null +++ b/src/app/(dark-only)/signup/signup-otp.tsx @@ -0,0 +1,101 @@ +"use client"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { verifyOuterbaseSubmitEmail } from "@/outerbase-cloud/api"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useCallback, useEffect, useState } from "react"; + +export function SignupOtp() { + const [code, setCode] = useState(""); + const [error, setError] = useState(""); + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [email, setEmail] = useState(""); + + const onVerifyOTP = useCallback(() => { + if (code.length < 6) return; + setLoading(true); + verifyOuterbaseSubmitEmail(code) + .then(() => { + localStorage.removeItem("continue-redirect"); + router.push("/"); + }) + .catch((err) => setError(err.message)) + .finally(() => { + setLoading(false); + }); + }, [code, router]); + + useEffect(() => { + const session = localStorage.getItem("session"); + if (!session) return; + const user = JSON.parse(session); + setEmail(user.email); + }, []); + + return ( +
+
+ + + + +

Check your email

+

+ We've sent a link to {email ?? ""} +

+
+ +
{ + onVerifyOTP(); + e.preventDefault(); + }} + className="flex flex-col gap-4" + > + setCode(e.currentTarget.value)} + /> + + {error &&
{error}
} + + + + +
+ Still having trouble?{" "} + + Contact support + +
+
+ ); +} diff --git a/src/app/(dark-only)/spaceship-container.tsx b/src/app/(dark-only)/spaceship-container.tsx new file mode 100644 index 00000000..d177e24c --- /dev/null +++ b/src/app/(dark-only)/spaceship-container.tsx @@ -0,0 +1,15 @@ +import { PropsWithChildren } from "react"; + +export function SpaceshipContentContainer({ children }: PropsWithChildren) { + return ( +
+ {children} +
+ ); +} diff --git a/src/app/(dark-only)/verify/page.tsx b/src/app/(dark-only)/verify/page.tsx new file mode 100644 index 00000000..97aa1270 --- /dev/null +++ b/src/app/(dark-only)/verify/page.tsx @@ -0,0 +1,103 @@ +"use client"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { verifyOuterbaseOTP } from "@/outerbase-cloud/api-account"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useCallback, useState } from "react"; +import { LoginBaseSpaceship } from "../signin/starbase-portal"; + +export default function VerifyPage() { + const [code, setCode] = useState(""); + const [error, setError] = useState(""); + const router = useRouter(); + const [loading, setLoading] = useState(false); + + const onVerifyOTP = useCallback(() => { + if (code.length < 6) return; + setLoading(true); + verifyOuterbaseOTP(code) + .then(() => { + if (localStorage.getItem("continue-redirect")) { + router.push(localStorage.getItem("continue-redirect") ?? "/"); + localStorage.removeItem("continue-redirect"); + } else { + router.push("/"); + } + }) + .catch((err) => setError(err.message)) + .finally(() => { + setLoading(false); + }); + }, [code, router]); + + return ( + <> +
+
+ + + + +

Verify that it's you

+

+ Enter the verification code for Outerbase from your two-factor + authentication app. +

+
+ +
{ + onVerifyOTP(); + e.preventDefault(); + }} + className="flex flex-col gap-4" + > + setCode(e.currentTarget.value)} + /> + + {error &&
{error}
} + + + + +
+ Still having trouble?{" "} + + Contact support + +
+
+ + + + ); +} diff --git a/src/app/(outerbase)/account/account-footer.tsx b/src/app/(outerbase)/account/account-footer.tsx new file mode 100644 index 00000000..3fb1c359 --- /dev/null +++ b/src/app/(outerbase)/account/account-footer.tsx @@ -0,0 +1,136 @@ +import { useSession } from "@/app/(outerbase)/session-provider"; +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { Label } from "@/components/orbit/label"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { isValidEmail } from "@/lib/validation"; +import { deleteOuterbaseUser } from "@/outerbase-cloud/api-account"; +import { Check, Copy } from "lucide-react"; +import { useRouter } from "next/router"; +import { useCallback, useMemo, useState } from "react"; +import { toast } from "sonner"; + +export default function AccountFooter() { + const { session } = useSession(); + const router = useRouter(); + const [open, setOpen] = useState(false); + const [copied, setCopied] = useState(false); + const [email, setEmail] = useState(""); + const [loading, setLoading] = useState(false); + + const copyToClipboard = async () => { + if (!session) return; + try { + await navigator.clipboard.writeText(session?.user.email); + setCopied(true); + } catch (error) { + console.error("Failed to copy:", error); + } + }; + + const onClose = () => { + setCopied(false); + setOpen(false); + setEmail(""); + setLoading(false); + }; + + const onDeleteOuerbaseUser = useCallback(() => { + setLoading(true); + deleteOuterbaseUser() + .then(() => { + onClose(); + router.push("/signout"); + }) + .catch((err) => { + setLoading(false); + toast.error(err.message); + }); + }, [router]); + + const fullName = useMemo(() => { + if (!session) return; + return session?.user.first_name + " " + session?.user.last_name; + }, [session]); + + const disabled = useMemo(() => { + return !isValidEmail(email) || email !== session?.user.email; + }, [email, session]); + + return ( + <> + { + if (!open) { + onClose(); + } + }} + > + + + + Confirm deletion of {fullName}' account + + + + + Deleting this account will delete all Bases and Workspaces and + revoke all connections made to your databases. All members will lose + access. This action is permanent and{" "} + cannot be + undone. + + + +
+
+
+
+
+

+ Delete Account +

+
+ This will delete your account and all the workspaces you own. +
+
+ + ); +} diff --git a/src/app/(outerbase)/account/editor-theme.tsx b/src/app/(outerbase)/account/editor-theme.tsx new file mode 100644 index 00000000..2d4f93e6 --- /dev/null +++ b/src/app/(outerbase)/account/editor-theme.tsx @@ -0,0 +1,106 @@ +import SqlEditor from "@/components/gui/sql-editor"; +import { Button } from "@/components/orbit/button"; +import { Label } from "@/components/ui/label"; +import { cn } from "@/lib/utils"; +import { useTheme } from "next-themes"; +import { useState } from "react"; + +function EditorTheme() { + const [selectedTheme, setSelectedTheme] = useState(""); + + const statement = `CREATE TABLE video_game ( + game_id SERIAL PRIMARY KEY, + title VARCHAR(222) NOT NULL, + genre VARCHAR(222), + plaform VARCHAR(100), + release_dat DATE, + developer VARCHAR(255) + );`; + + const EditorThemes = [ + { + title: "Moondust", + value: "moondust", + }, + { + title: "Invasion", + value: "invasion", + }, + { + title: "Freedom", + value: "freedom", + }, + ]; + return ( +
+

Editor theme

+ {EditorThemes.map((theme, index) => { + const isSelected = theme.value === selectedTheme; + return ( +
setSelectedTheme(theme.value)} + className="mb-2 w-full cursor-pointer" + > + +
+
+ +
+
+
+ ); + })} +
+ ); +} + +export default function UserEditorTheme() { + const { theme, setTheme } = useTheme(); + + // Not implement yet + return ( +
+

+ Theming +

+

Theme

+
+
+ +
+ ); +} diff --git a/src/app/(outerbase)/account/page.tsx b/src/app/(outerbase)/account/page.tsx new file mode 100644 index 00000000..ac60d7d0 --- /dev/null +++ b/src/app/(outerbase)/account/page.tsx @@ -0,0 +1,30 @@ +"use client"; +import { useSession } from "@/app/(outerbase)/session-provider"; +import NavigationLayout from "../nav-layout"; +import AccountFooter from "./account-footer"; +import TwoFactorAuth from "./two-factor-auth"; +import UserAvatar from "./user-avatar"; +import UserFormInput from "./user-form-input"; + +export default function AccountPage() { + const { session } = useSession(); + + if (!session?.user) return
You are not login!
; + + return ( + +
+
+

Account Setting

+

+ Details +

+ + + + +
+
+
+ ); +} diff --git a/src/app/(outerbase)/account/two-factor-auth.tsx b/src/app/(outerbase)/account/two-factor-auth.tsx new file mode 100644 index 00000000..34f756f0 --- /dev/null +++ b/src/app/(outerbase)/account/two-factor-auth.tsx @@ -0,0 +1,326 @@ +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { CountryCodePicker } from "@/components/picker/country-code-picker"; +import { Label } from "@/components/ui/label"; +import { + deleteOuterbaseTwoFactorAuth, + requestOuterbase2FAPhone, + requestOuterbaseTwoFactorAuth, + submitVerifyPhone2FA, + verifyOuterbase2FAOTP, +} from "@/outerbase-cloud/api-account"; +import { CheckCircle2 } from "lucide-react"; +import Image from "next/image"; +import { useCallback, useState } from "react"; +import { toast } from "sonner"; +import { useSession } from "../session-provider"; + +interface HasOTPProps { + loading?: boolean; + onDelete: () => void; +} +function HasOTP({ onDelete, loading }: HasOTPProps) { + return ( +
+
Authentication App
+

+ Verification codes will be generated by the authentication app you + configured. +

+
+ ); +} + +interface VerifyCodeInputProps { + loading: boolean; + code: string; + disabled?: boolean; + onCancel?: () => void; + onSave: () => void; + onChange: (v: string) => void; +} +function VerifyCodeInput({ + code, + onChange, + onSave, + disabled, + loading, + onCancel, +}: VerifyCodeInputProps) { + return ( + <> +
+ + +
+
+
+ + ); +} + +type TwoFactorAuthType = "otp" | "phone"; +interface QRCode { + base32: string; + id: string; + image: string; +} + +interface ISMS { + id: string; + number_masked: string; + user_id: string; +} +export default function TwoFactorAuth() { + const { session, refreshSession } = useSession(); + const [twoFactorType, setTwoFactorType] = + useState("phone"); + const [add, setAdd] = useState(false); + const [loading, setLoading] = useState(false); + const [prefix, setPrefix] = useState("+1"); + const [phone, setPhone] = useState(""); + const [verifyCode, setVerifyCode] = useState(""); + const [sms, setSMS] = useState(); + const [qrcode, setQrcode] = useState(); + const [deleting, setDeleting] = useState(false); + const [sending, setSending] = useState(false); + + const onClear = () => { + setDeleting(false); + setQrcode(undefined); + setDeleting(false); + setVerifyCode(""); + setAdd(false); + setTwoFactorType("phone"); + }; + + const onRefreshSession = useCallback( + (msg: string) => { + refreshSession().then(() => { + onClear(); + toast.success(msg); + }); + }, + [refreshSession] + ); + + const onSendRequestPhone2FA = useCallback(() => { + setSending(true); + requestOuterbaseTwoFactorAuth("phone", { + number: prefix + phone, + }) + .then((r) => { + requestOuterbase2FAPhone((r as ISMS).id).then(() => { + setSMS(r as ISMS); + setSending(false); + }); + }) + .catch(() => setSending(false)); + }, [prefix, phone]); + + const onRequestOuterbaseTwoFactorAuth = useCallback( + (type: TwoFactorAuthType) => { + setTwoFactorType(type); + if (type === "otp" && !qrcode) { + requestOuterbaseTwoFactorAuth(type, {}) + .then((r) => { + if (type === "otp") { + setQrcode(r as QRCode); + } + }) + .catch() + .finally(); + } + }, + [qrcode] + ); + + const onVerifyOuterbaseOTP = useCallback(() => { + if (!qrcode?.id) return; + setLoading(true); + verifyOuterbase2FAOTP({ + otp_id: qrcode.id, + token: verifyCode, + }) + .then(() => { + onRefreshSession("2FA enabled"); + }) + .catch((error) => { + setLoading(false); + toast.error(error.message); + }); + }, [qrcode, verifyCode, onRefreshSession]); + + const onSubmitPhone2FA = useCallback(() => { + if (!sms) return; + setLoading(true); + submitVerifyPhone2FA(sms?.id, { code: verifyCode }) + .then(() => { + onRefreshSession("2FA enabled"); + }) + .catch((error) => { + setLoading(false); + toast.error(error.message); + }); + }, [sms, verifyCode, onRefreshSession]); + + function handleSave() { + if (twoFactorType === "otp") { + onVerifyOuterbaseOTP(); + } else { + onSubmitPhone2FA(); + } + } + + const onDeleteTwoFactor = useCallback(() => { + setDeleting(true); + deleteOuterbaseTwoFactorAuth() + .then(() => { + onRefreshSession("2FA disabled"); + }) + .catch((error) => { + setDeleting(false); + toast.error(error.message); + }); + }, [onRefreshSession]); + + const disabled = twoFactorType === "otp" && verifyCode.length < 6; + + if (session?.user.has_otp) { + return ; + } + + let footer = ( +
+
+ {twoFactorType === "otp" ? ( + <> + +
+ Use an authentication app like Google Authenticator, 1Password + or Authy. +
{" "} +
+ {qrcode && ( + qr-code + )} +
+ + ) : ( + <> + +
+ { + setPrefix(c.code); + }} + className="w-[250px]" + /> +
+ + )} +
+ {twoFactorType === "phone" && ( +
+ + +
+
+
+ )} + + + + ); + } + return ( +
+

+ Two-factor authentication +

+ + Requiring more than just a password to sign in to your account, giving + your Outerbase account an additional layer of security. + + {footer} +
+ ); +} diff --git a/src/app/(outerbase)/account/user-avatar.tsx b/src/app/(outerbase)/account/user-avatar.tsx new file mode 100644 index 00000000..34727a32 --- /dev/null +++ b/src/app/(outerbase)/account/user-avatar.tsx @@ -0,0 +1,25 @@ +import { Button } from "@/components/orbit/button"; +import { OuterbaseAPIUser } from "@/outerbase-cloud/api-type"; +import Image from "next/image"; + +export default function UserAvatar({ user }: { user: OuterbaseAPIUser }) { + // not implement upload user avatar + + return ( +
+
+ {user.avatar ? ( + User Avatar + ) : ( + {user.initials} + )} +
+
+ ); +} diff --git a/src/app/(outerbase)/account/user-form-input.tsx b/src/app/(outerbase)/account/user-form-input.tsx new file mode 100644 index 00000000..7bfb1a90 --- /dev/null +++ b/src/app/(outerbase)/account/user-form-input.tsx @@ -0,0 +1,140 @@ +import { useSession } from "@/app/(outerbase)/session-provider"; +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { Label } from "@/components/orbit/label"; +import { + updateOuterbaseUserPassword, + updateOuterbaseUserProfile, +} from "@/outerbase-cloud/api-account"; +import { OuterbaseAPIUser } from "@/outerbase-cloud/api-type"; +import { produce } from "immer"; +import { useCallback, useState } from "react"; +import { toast } from "sonner"; + +interface Props { + user: OuterbaseAPIUser; +} + +export default function UserFormInput({ user }: Props) { + const { refreshSession } = useSession(); + const [loading, setLoading] = useState< + "user_profile" | "login_method" | undefined + >(); + const [userData, setUserData] = useState(user); + const [currentPassword, setCurrentPassword] = useState(""); + const [newPassword, setNewPassword] = useState(""); + const updateUserProfile = useCallback(() => { + setLoading("user_profile"); + updateOuterbaseUserProfile({ + first_name: userData.first_name, + last_name: userData.last_name, + }) + .then(() => { + toast.success("Profile updated"); + refreshSession(); + }) + .catch((error) => { + toast.error(error?.message); + }) + .finally(() => { + setLoading(undefined); + }); + }, [userData, refreshSession]); + + const updateUserPassword = useCallback(() => { + setLoading("login_method"); + updateOuterbaseUserPassword({ + new_password: newPassword, + old_password: currentPassword, + }) + .then(() => { + toast.success("Password updated"); + refreshSession(); + }) + .catch((error) => toast.error(error?.message)) + .finally(() => { + setLoading(undefined); + }); + }, [newPassword, currentPassword, refreshSession]); + + return ( +
+ + +
+ ); +} diff --git a/src/app/(outerbase)/auth-provider.tsx b/src/app/(outerbase)/auth-provider.tsx new file mode 100644 index 00000000..5f0a72c1 --- /dev/null +++ b/src/app/(outerbase)/auth-provider.tsx @@ -0,0 +1,26 @@ +"use client"; +import { usePathname, useRouter } from "next/navigation"; +import { PropsWithChildren, useEffect } from "react"; +import { useSession } from "./session-provider"; + +export default function AuthProvider({ children }: PropsWithChildren) { + const router = useRouter(); + const pathname = usePathname(); + const { isLoading, session } = useSession(); + + useEffect(() => { + if (isLoading) return; + const redirect = localStorage.getItem("continue-redirect"); + if (!session?.session || !session?.user) { + localStorage.setItem("continue-redirect", pathname); + router.replace("/signin"); + // IF user enabled 2FA keep redirect to verify page + } else if (session.user.has_otp && redirect === "/verify") { + router.replace(redirect); + } else { + localStorage.removeItem("continue-redirect"); + } + }, [isLoading, session, pathname, router]); + + return <>{children}; +} diff --git a/src/app/(outerbase)/base-template.tsx b/src/app/(outerbase)/base-template.tsx new file mode 100644 index 00000000..921e4e89 --- /dev/null +++ b/src/app/(outerbase)/base-template.tsx @@ -0,0 +1,34 @@ +import { + CommonConnectionConfig, + CommonConnectionConfigTemplate, +} from "@/components/connection-config-editor"; +import { OuterbaseAPISourceInput } from "@/outerbase-cloud/api-type"; +import { ReactElement } from "react"; +import { SavedConnectionRawLocalStorage } from "../(theme)/connect/saved-connection-storage"; + +export interface ConnectionTemplateList { + template: CommonConnectionConfigTemplate; + localFrom?: (value: SavedConnectionRawLocalStorage) => CommonConnectionConfig; + localTo?: (value: CommonConnectionConfig) => SavedConnectionRawLocalStorage; + + /** + * Convert the remote source config to common connecting config + * @param value + * @returns + */ + remoteFrom?: (value: { + source: OuterbaseAPISourceInput; + name: string; + }) => CommonConnectionConfig; + + /** + * Convert the common connecting config to remote source config + * @param value + * @returns + */ + remoteTo?: (value: CommonConnectionConfig) => { + source: OuterbaseAPISourceInput; + name: string; + }; + instruction?: ReactElement; +} diff --git a/src/app/(outerbase)/layout.tsx b/src/app/(outerbase)/layout.tsx new file mode 100644 index 00000000..853ce284 --- /dev/null +++ b/src/app/(outerbase)/layout.tsx @@ -0,0 +1,20 @@ +import { OuterbaseSessionProvider } from "@/app/(outerbase)/session-provider"; +import ClientOnly from "@/components/client-only"; +import ThemeLayout from "../(theme)/theme_layout"; +import { WorkspaceProvider } from "./workspace-provider"; + +export default function OuterbaseLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + {children} + + + + ); +} diff --git a/src/app/(outerbase)/local/board/[boardId]/page.tsx b/src/app/(outerbase)/local/board/[boardId]/page.tsx new file mode 100644 index 00000000..827459b3 --- /dev/null +++ b/src/app/(outerbase)/local/board/[boardId]/page.tsx @@ -0,0 +1,79 @@ +"use client"; +import NavigationDashboardLayout from "@/app/(outerbase)/nav-board-layout"; +import Board, { DashboardProps } from "@/components/board"; +import { BoardSourceDriver } from "@/drivers/board-source/base-source"; +import LocalBoardSource from "@/drivers/board-source/local"; +import LocalBoardStorage from "@/drivers/board-storage/local"; +import { LocalDashboardData } from "@/indexdb"; +import { useParams } from "next/navigation"; +import { useEffect, useMemo, useState } from "react"; +import { getLocalConnectionList, useLocalDashboardList } from "../../hooks"; + +function LocalBoardWithDataPage({ + initialValue, +}: { + initialValue: LocalDashboardData; +}) { + const [interval, setIntervals] = useState(0); + const [filter, setFilter] = useState({}); + const [value, setValue] = useState(initialValue); + + const [boardSources, setBoardSources] = useState(); + const boardStorage = useMemo(() => { + return new LocalBoardStorage(initialValue); + }, [initialValue]); + + // Loading the local board source + useEffect(() => { + getLocalConnectionList().then((sources) => { + setBoardSources(new LocalBoardSource(sources.map((s) => s.content))); + }); + }, []); + + if (!boardSources) return
Loading
; + + return ( + + ); +} + +export default function LocalBoardPage() { + const { boardId } = useParams<{ + boardId: string; + }>(); + + const { data, isLoading } = useLocalDashboardList(); + const board = data?.find((b) => b.id === boardId); + + const dashboardList = useMemo(() => { + return (data ?? []).map((board) => { + return { + href: `/local/board/${board.id}`, + name: board.content.name, + id: board.id, + }; + }); + }, [data]); + + if (!board) return
Loading...
; + + return ( + + + + ); +} diff --git a/src/app/(outerbase)/local/dialog-base-delete.tsx b/src/app/(outerbase)/local/dialog-base-delete.tsx new file mode 100644 index 00000000..848aa6ac --- /dev/null +++ b/src/app/(outerbase)/local/dialog-base-delete.tsx @@ -0,0 +1,73 @@ +import CopyableText from "@/components/copyable-text"; +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; +import { removeLocalConnection } from "./hooks"; + +export const deleteLocalBaseDialog = createDialog<{ + baseId: string; + baseName: string; +}>(({ close, baseName, baseId }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const deleteClicked = useCallback(async () => { + if (name !== baseName) return; + + setLoading(true); + await removeLocalConnection(baseId); + setLoading(false); + + close(undefined); + }, [name, baseId, close, baseName]); + + return ( + <> + + Confirm deletion of {baseName} + + All saved queries, dashboards, definitions and any other contributions + made to your Base will be deleted. This action is permanent and{" "} + cannot + be undone. + + + +
+
+ +
+ + setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/local/dialog-board-create.tsx b/src/app/(outerbase)/local/dialog-board-create.tsx new file mode 100644 index 00000000..8c3d968c --- /dev/null +++ b/src/app/(outerbase)/local/dialog-board-create.tsx @@ -0,0 +1,67 @@ +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { LocalDashboardData } from "@/indexdb"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; +import { createLocalDashboard } from "./hooks"; + +export const createLocalBoardDialog = createDialog< + object, + LocalDashboardData | undefined +>(({ close }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const createBoardClicked = useCallback(() => { + if (name.length === 0) return; + + setLoading(true); + + createLocalDashboard(name) + .then((createdBoard) => { + close(createdBoard); + }) + .finally(() => { + setLoading(false); + }); + }, [close, name]); + + return ( + <> + + New Board + + + +
+ setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/local/dialog-board-delete.tsx b/src/app/(outerbase)/local/dialog-board-delete.tsx new file mode 100644 index 00000000..a0fa0077 --- /dev/null +++ b/src/app/(outerbase)/local/dialog-board-delete.tsx @@ -0,0 +1,76 @@ +import CopyableText from "@/components/copyable-text"; +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; +import { deleteLocalDashboard } from "./hooks"; + +export const deleteLocalBoardDialog = createDialog<{ + boardId: string; + boardName: string; +}>(({ close, boardName, boardId }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const deleteClicked = useCallback(() => { + if (name !== boardName) return; + + setLoading(true); + + deleteLocalDashboard(boardId) + .then(() => { + close(undefined); + }) + .finally(() => { + setLoading(false); + }); + }, [name, boardId, close, boardName]); + + return ( + <> + + Confirm deletion of board {boardName} + + All saved charts and any other contributions made to your Dashboard + will be deleted. This action is permanent and cannot{" "} + be undone. + + + +
+
+ +
+ + setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/local/edit-base/[baseId]/page.tsx b/src/app/(outerbase)/local/edit-base/[baseId]/page.tsx new file mode 100644 index 00000000..faaa144e --- /dev/null +++ b/src/app/(outerbase)/local/edit-base/[baseId]/page.tsx @@ -0,0 +1,112 @@ +"use client"; +import { ConnectionTemplateList } from "@/app/(outerbase)/base-template"; +import { + CommonConnectionConfig, + ConnectionConfigEditor, + validateTemplate, +} from "@/components/connection-config-editor"; +import { ConnectionTemplateDictionary } from "@/components/connection-config-editor/template"; +import { Button } from "@/components/orbit/button"; +import { ArrowLeft, ArrowRight, FloppyDisk } from "@phosphor-icons/react"; +import { useParams, useRouter } from "next/navigation"; +import { useCallback, useEffect, useState } from "react"; +import { getLocalConnection, updateLocalConnection } from "../../hooks"; + +export default function LocalEditBasePage() { + const router = useRouter(); + const { baseId } = useParams<{ baseId: string }>(); + const [value, setValue] = useState({ name: "" }); + const [loading, setLoading] = useState(true); + const [databaseName, setDatabaseName] = useState(""); + const [template, setTemplate] = useState(); + const [validateErrors, setValidateErrors] = useState>( + {} + ); + + const onSave = useCallback(async () => { + if (!template?.localTo) return; + + const errors = validateTemplate(value, template); + setValidateErrors(errors); + if (Object.keys(errors).length > 0) return; + + await updateLocalConnection(baseId, template.localTo(value)); + router.push("/local"); + }, [template, value, router, baseId]); + + const onConnect = useCallback(async () => { + if (!template?.localTo) return; + + const errors = validateTemplate(value, template); + setValidateErrors(errors); + if (Object.keys(errors).length > 0) return; + + setLoading(true); + const tmp = await updateLocalConnection(baseId, template.localTo(value)); + router.push( + tmp?.content.driver === "sqlite-filehandler" + ? `/playground/client?s=${tmp?.content.id}` + : `/client/s/${tmp?.content.driver ?? "turso"}?p=${tmp?.content.id}` + ); + }, [template, value, router, baseId]); + + // Loading the base + useEffect(() => { + getLocalConnection(baseId).then((config) => { + if (!config) return; + + // Check for the template + const template = + ConnectionTemplateDictionary[config.content.driver ?? ""]; + if (!template?.localFrom) return; + + setDatabaseName(config.content.name ?? ""); + setTemplate(template); + setValue(template.localFrom(config.content)); + setLoading(false); + }); + }, [baseId]); + + if (loading || !template) return
Loading....
; + + return ( + <> +
+
+ + +
+
+ +
+
+ Edit {databaseName} +
+
+ + +
+ +
+
+ + +
+
+ + ); +} diff --git a/src/app/(outerbase)/local/hooks.tsx b/src/app/(outerbase)/local/hooks.tsx new file mode 100644 index 00000000..dd84a604 --- /dev/null +++ b/src/app/(outerbase)/local/hooks.tsx @@ -0,0 +1,162 @@ +import { SavedConnectionRawLocalStorage } from "@/app/(theme)/connect/saved-connection-storage"; +import { LocalConnectionData, LocalDashboardData, localDb } from "@/indexdb"; +import parseSafeJson from "@/lib/json-safe"; +import useSWR, { mutate } from "swr"; + +export function useLocalDashboardList() { + return useSWR( + "/dashboards/local", + () => { + return localDb.board.toCollection().toArray(); + }, + { + revalidateOnFocus: false, + revalidateOnReconnect: false, + revalidateIfStale: false, + } + ); +} + +export async function createLocalDashboard(boardName: string) { + const id = crypto.randomUUID(); + const now = Date.now(); + + const data: LocalDashboardData = { + id, + created_at: now, + updated_at: now, + name: boardName, + layout: [], + charts: [], + data: { + filters: [], + }, + }; + + await localDb.table("board").add({ id, content: data }); + return data; +} + +export async function deleteLocalDashboard(boardId: string) { + await localDb.table("board").delete(boardId); + mutate("/dashboards/local"); +} + +export function useLocalConnectionList() { + return useSWR( + "/connections/local", + async (): Promise => { + // Migrate the connection from local storage to indexdb + if (localStorage.getItem("connections")) { + const legacyList = parseSafeJson( + localStorage.getItem("connections") ?? "[]", + [] + ); + + if (legacyList.length) { + const list = legacyList.map((conn) => { + return { + id: conn.id!, + content: conn, + created_at: Date.now(), + updated_at: conn.last_used ?? Date.now(), + }; + }); + + try { + await localDb.connection.bulkAdd(list); + } catch (e) { + console.log(e); + } + + localStorage.removeItem("connections"); + return list; + } + + localStorage.removeItem("connections"); + } + + return await localDb.connection.toCollection().toArray(); + } + ); +} + +export function useLocalConnection(id: string) { + return useSWR( + `/connections/local/${id}`, + async (): Promise => { + return await localDb.connection.get(id); + }, + { + revalidateOnFocus: false, + revalidateOnReconnect: false, + revalidateIfStale: false, + } + ); +} + +export async function removeLocalConnection(id: string) { + await localDb.connection.delete(id); + mutate("/connections/local"); +} + +export async function createLocalConnection( + config: SavedConnectionRawLocalStorage +): Promise { + const id = crypto.randomUUID(); + + const data = { + id, + content: config, + created_at: Date.now(), + updated_at: Date.now(), + }; + + await localDb.connection.put(data); + mutate("/connections/local"); + + return data; +} + +export async function updateLocalConnection( + id: string, + config: SavedConnectionRawLocalStorage +) { + const oldData = await localDb.connection.get(id); + if (!oldData) return; + + const data = { + id, + content: config, + updated_at: Date.now(), + created_at: oldData.created_at, + }; + + await localDb.connection.put(data); + mutate("/connections/local"); + + return data; +} + +export async function updateLocalConnectionUsed(id: string) { + const oldData = await localDb.connection.get(id); + if (!oldData) return; + + const data = { + ...oldData, + updated_at: Date.now(), + }; + + await localDb.connection.put(data); + mutate("/connections/local"); + + return data; +} + +export async function getLocalConnectionList() { + return await localDb.connection.toCollection().toArray(); +} + +export async function getLocalConnection(id: string) { + return await localDb.connection.get(id); +} diff --git a/src/app/(outerbase)/local/new-base/[driver]/page.tsx b/src/app/(outerbase)/local/new-base/[driver]/page.tsx new file mode 100644 index 00000000..13803018 --- /dev/null +++ b/src/app/(outerbase)/local/new-base/[driver]/page.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { + CommonConnectionConfig, + ConnectionConfigEditor, + validateTemplate, +} from "@/components/connection-config-editor"; +import { ConnectionTemplateDictionary } from "@/components/connection-config-editor/template"; +import { Button } from "@/components/orbit/button"; +import { getDatabaseFriendlyName } from "@/components/resource-card/utils"; +import { ArrowLeft, ArrowRight, FloppyDisk } from "@phosphor-icons/react"; +import { useParams, useRouter } from "next/navigation"; +import { useCallback, useMemo, useState } from "react"; +import { mutate } from "swr"; +import { createLocalConnection } from "../../hooks"; + +export default function LocalNewBasePage() { + const { driver } = useParams<{ driver: string }>(); + const router = useRouter(); + const [value, setValue] = useState({ name: "" }); + const [loading, setLoading] = useState(false); + const [validateErrors, setValidateErrors] = useState>( + {} + ); + + const template = useMemo(() => { + return ConnectionTemplateDictionary[driver]; + }, [driver]); + + const onSave = useCallback(async () => { + if (!template?.localTo) return; + + const errors = validateTemplate(value, template); + setValidateErrors(errors); + if (Object.keys(errors).length > 0) return; + + setLoading(true); + await createLocalConnection(template.localTo(value)); + router.push("/local"); + }, [template, value, router]); + + const onConnect = useCallback(async () => { + if (!template?.localTo) return; + + const errors = validateTemplate(value, template); + setValidateErrors(errors); + if (Object.keys(errors).length > 0) return; + + setLoading(true); + const newConnection = await createLocalConnection(template.localTo(value)); + + // Redirect to the connection page + mutate("/local/bases"); + router.replace( + newConnection.content.driver === "sqlite-filehandler" + ? `/playground/client?s=${newConnection.id}` + : `/client/s/${newConnection.content.driver ?? "turso"}?p=${newConnection.id}` + ); + }, [template, value, router]); + + if (!template?.localTo || !template?.localFrom) { + return
Invalid driver
; + } + + return ( + <> +
+
+ + +
+
+ +
+
Connect to {getDatabaseFriendlyName(driver)} database
+
+ + +
+ +
+
+ + +
+
+ + ); +} diff --git a/src/app/(outerbase)/local/new-base/cloud-support-only.tsx b/src/app/(outerbase)/local/new-base/cloud-support-only.tsx new file mode 100644 index 00000000..97a9c0ac --- /dev/null +++ b/src/app/(outerbase)/local/new-base/cloud-support-only.tsx @@ -0,0 +1,163 @@ +"use client"; +import { useSession } from "@/app/(outerbase)/session-provider"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import { Button } from "@/components/orbit/button"; +import { Loader } from "@/components/orbit/loader"; +import { getDatabaseFriendlyName } from "@/components/resource-card/utils"; +import { + ArrowLeft, + ChartBar, + Folder, + Icon, + MagicWand, + ShieldCheck, + UsersThree, +} from "@phosphor-icons/react"; +import Link from "next/link"; + +function OuterbaseHighlightCard({ + title, + description, + icon: Icon, +}: { + title: string; + description: string; + icon: Icon; +}) { + return ( +
+
+
+ +
+
+

{title}

+

{description}

+
+ ); +} + +function SignupPromotion({ type }: { type: string }) { + const { isLoading, session } = useSession(); + const { workspaces, loading } = useWorkspaces(); + + if (isLoading || loading) { + return ( +
+ +
+ ); + } + + if (!session?.user) { + return ( +
+

Outerbase Cloud

+ + + Sign In To Our Cloud + + +
+ + + + + + + +
+
+ ); + } + + return ( +
+
+

Outerbase Cloud

+

Please select the workspace

+
+ + {(workspaces ?? []).map((workspace) => { + return ( + + + {workspace.name} + + ); + })} +
+ ); +} + +export function CloudDriverSupportOnly({ type }: { type: string }) { + return ( +
+
+ +
+ +
+ Running {getDatabaseFriendlyName(type)} from a browser is not possible. +
Please use the desktop app or our cloud services instead. +
+ +
+ + +
+
+

Desktop App

+
+ + + + +
+
Download the desktop app
+

+ Outerbase Studio Desktop is a lightweight Electron wrapper for + the Outerbase Studio web version. It enables support for drivers + that aren't feasible in a browser environment, such as + MySQL and PostgreSQL. +

+
+ +
+
+
+ ); +} diff --git a/src/app/(outerbase)/local/new-base/mysql/page.tsx b/src/app/(outerbase)/local/new-base/mysql/page.tsx new file mode 100644 index 00000000..1d6eb05d --- /dev/null +++ b/src/app/(outerbase)/local/new-base/mysql/page.tsx @@ -0,0 +1,6 @@ +"use client"; +import { CloudDriverSupportOnly } from "../cloud-support-only"; + +export default function LocalMySQLNewBasePage() { + return ; +} diff --git a/src/app/(outerbase)/local/new-base/postgres/page.tsx b/src/app/(outerbase)/local/new-base/postgres/page.tsx new file mode 100644 index 00000000..fa4b7333 --- /dev/null +++ b/src/app/(outerbase)/local/new-base/postgres/page.tsx @@ -0,0 +1,6 @@ +"use client"; +import { CloudDriverSupportOnly } from "../cloud-support-only"; + +export default function LocalMySQLNewBasePage() { + return ; +} diff --git a/src/app/(outerbase)/local/page.tsx b/src/app/(outerbase)/local/page.tsx new file mode 100644 index 00000000..44ca3efa --- /dev/null +++ b/src/app/(outerbase)/local/page.tsx @@ -0,0 +1,179 @@ +"use client"; + +import { MySQLIcon, SQLiteIcon } from "@/components/icons/outerbase-icon"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { CaretDown } from "@phosphor-icons/react"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useCallback, useMemo } from "react"; +import NavigationLayout from "../nav-layout"; +import { ResourceItemList, ResourceItemProps } from "../resource-item-helper"; +import { deleteLocalBaseDialog } from "./dialog-base-delete"; +import { createLocalBoardDialog } from "./dialog-board-create"; +import { deleteLocalBoardDialog } from "./dialog-board-delete"; +import { useLocalConnectionList, useLocalDashboardList } from "./hooks"; + +export default function LocalConnectionPage() { + const router = useRouter(); + + const { + data: localBases, + isLoading, + mutate: refreshBase, + } = useLocalConnectionList(); + + const baseResources = useMemo(() => { + return (localBases ?? []).map((conn) => { + return { + href: + conn.content.driver === "sqlite-filehandler" + ? `/playground/client?s=${conn.id}` + : `/client/s/${conn.content.driver ?? "turso"}?p=${conn.id}`, + name: conn.content.name, + lastUsed: conn.updated_at, + id: conn.id, + type: conn.content.driver, + status: "", + color: conn.content.label || "default", + } as ResourceItemProps; + }); + }, [localBases]); + + // Getting the board from indexdb + const { data: dashboardList, mutate: refreshDashboard } = + useLocalDashboardList(); + const dashboardResources = useMemo(() => { + return ( + (dashboardList ?? []).map((board) => { + return { + href: `/local/board/${board.id}`, + name: board.content.name, + lastUsed: board.content.updated_at, + id: board.id, + type: "board", + } as ResourceItemProps; + }) ?? [] + ); + }, [dashboardList]); + + const onBoardCreate = useCallback(() => { + createLocalBoardDialog.show({}).then(() => { + refreshDashboard(); + }); + }, [refreshDashboard]); + + const onBaseRemove = useCallback( + (deletedResource: ResourceItemProps) => { + deleteLocalBaseDialog + .show({ baseId: deletedResource.id, baseName: deletedResource.name }) + .then(refreshBase) + .catch(); + }, + [refreshBase] + ); + + const onBoardRemove = useCallback((deletedResource: ResourceItemProps) => { + deleteLocalBoardDialog + .show({ boardId: deletedResource.id, boardName: deletedResource.name }) + .then() + .catch(); + }, []); + + return ( + +
+
+ + + + + + + Open Empty SQLite Database + + +
+ + Northwind + + The Northwind Database is a sample business database for + learning SQL queries and database design. + + + + + Chinook + + The Chinook Database is a sample digital media store + database for learning and practicing SQL queries. + + +
+
+
+ + +
+ + { + router.push(`/local/edit-base/${resource.id}`); + }} + onBoardCreate={onBoardCreate} + /> +
+
+ ); +} diff --git a/src/app/(outerbase)/nav-board-layout.tsx b/src/app/(outerbase)/nav-board-layout.tsx new file mode 100644 index 00000000..5bedef3e --- /dev/null +++ b/src/app/(outerbase)/nav-board-layout.tsx @@ -0,0 +1,76 @@ +"use client"; +import { + SidebarMenuHeader, + SidebarMenuItem, + SidebarMenuLoadingItem, +} from "@/components/sidebar-menu"; +import { CaretLeft, ChartBar } from "@phosphor-icons/react"; +import { useParams, useRouter } from "next/navigation"; +import { PropsWithChildren } from "react"; + +interface NavigationDashboardLayoutProps { + boards?: { + name: string; + id: string; + href: string; + }[]; + workspaceName?: string; + backHref?: string; + loading?: boolean; +} + +export default function NavigationDashboardLayout({ + children, + backHref, + boards, + workspaceName, + loading, +}: PropsWithChildren) { + const router = useRouter(); + const { boardId } = useParams<{ boardId?: string }>(); + + return ( +
+
+
{ + if (backHref) router.push(backHref); + }} + > + + {workspaceName} +
+ +
+ + + {(boards ?? []).map((board) => { + return ( + { + router.push(board.href); + }} + /> + ); + })} + + {loading && ( + <> + + + + + )} +
+
+
+ {children} +
+
+ ); +} diff --git a/src/app/(outerbase)/nav-header-local.tsx b/src/app/(outerbase)/nav-header-local.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/app/(outerbase)/nav-header.tsx b/src/app/(outerbase)/nav-header.tsx new file mode 100644 index 00000000..b7538a66 --- /dev/null +++ b/src/app/(outerbase)/nav-header.tsx @@ -0,0 +1,57 @@ +import { cn } from "@/lib/utils"; +import { Database, Gear } from "@phosphor-icons/react"; +import Link from "next/link"; +import { useParams, usePathname } from "next/navigation"; +import { useWorkspaces } from "./workspace-provider"; + +export default function NavigationHeader() { + const tabClassName = + "p-2 border-b-2 border-background flex gap-2 items-center h-full"; + const selectedTabClassName = cn(tabClassName, "border-orange-500"); + + const { workspaceId } = useParams<{ workspaceId: string }>(); + const { currentWorkspace } = useWorkspaces(); + const pathname = usePathname(); + + return ( +
+ +
+ ); +} diff --git a/src/app/(outerbase)/nav-layout.tsx b/src/app/(outerbase)/nav-layout.tsx new file mode 100644 index 00000000..f581536e --- /dev/null +++ b/src/app/(outerbase)/nav-layout.tsx @@ -0,0 +1,102 @@ +"use client"; +import { + SidebarMenuHeader, + SidebarMenuItem, + SidebarMenuLoadingItem, +} from "@/components/sidebar-menu"; +import { Database, Plus } from "@phosphor-icons/react"; +import { useParams, usePathname, useRouter } from "next/navigation"; +import { PropsWithChildren } from "react"; +import NavigationProfile from "./nav-profile"; +import NavigationSigninBanner from "./nav-signin-banner"; +import { useSession } from "./session-provider"; +import { useWorkspaces } from "./workspace-provider"; + +export default function NavigationLayout({ children }: PropsWithChildren) { + const router = useRouter(); + const { session } = useSession(); + const { workspaces, loading: workspaceLoading } = useWorkspaces(); + const pathname = usePathname(); + const { workspaceId } = useParams<{ workspaceId?: string }>(); + + return ( +
+
+
+ +
+ + {/*
+ } + /> +
*/} + +
+ + + + {workspaces.map((workspace) => { + return ( + { + router.push(`/w/${workspace.short_name}`); + } + } + selected={workspace.short_name === workspaceId} + badge={ + !workspace.is_enterprise && + workspace.subscription.plan === "starter" ? ( + + Free + + ) : undefined + } + /> + ); + })} + + {workspaceLoading && ( + <> + + + + + )} + + { + if (session?.user) { + router.push("/new-workspace"); + } else { + localStorage.setItem("continue-redirect", "/new-workspace"); + router.push("/signin"); + } + }} + /> +
+ + +
+
+ {children} +
+
+ ); +} diff --git a/src/app/(outerbase)/nav-profile.tsx b/src/app/(outerbase)/nav-profile.tsx new file mode 100644 index 00000000..aaa57b21 --- /dev/null +++ b/src/app/(outerbase)/nav-profile.tsx @@ -0,0 +1,132 @@ +import { Avatar } from "@/components/orbit/avatar"; +import { buttonVariants } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { cn } from "@/lib/utils"; +import { + CaretDown, + Gear, + SignOut, + ToggleLeft, + ToggleRight, +} from "@phosphor-icons/react"; +import { useTheme } from "next-themes"; +import { useRouter } from "next/navigation"; +import { useCallback } from "react"; +import { useSession } from "./session-provider"; + +export default function NavigationProfile() { + const { resolvedTheme, forcedTheme, setTheme } = useTheme(); + const { session, isLoading } = useSession(); + const router = useRouter(); + + const theme = forcedTheme ?? resolvedTheme; + + const onLogoutClicked = useCallback(() => { + router.push("/signout"); + }, [router]); + + const onThemeToggleClicked = useCallback( + (e: React.MouseEvent) => { + setTheme(theme === "dark" ? "light" : "dark"); + + // We don't want the dropdown to close + e.stopPropagation(); + e.preventDefault(); + }, + [theme, setTheme] + ); + + return ( + + +
+ + {!isLoading && ( +
+ {session + ? session.user.first_name + " " + session?.user.last_name + : "Guest"} +
+ )} + + {isLoading && ( +
+ )} +
+ +
+
+ + +
+ + +
+
+ {session + ? session.user.first_name + " " + session?.user.last_name + : "Guest"} +
+ {session &&
{session.user.email}
} +
+
+ +
+ {session && ( + { + router.push(`/account`); + }} + > + Account Setting + + + )} + + Theme + {theme === "dark" ? ( + + ) : ( + + )} + + {session && ( + + Log out + + )} + {!session && ( + { + router.push("/signin"); + }} + className="justify-between" + > + Log in + + )} +
+
+ + ); +} diff --git a/src/app/(outerbase)/nav-signin-banner.tsx b/src/app/(outerbase)/nav-signin-banner.tsx new file mode 100644 index 00000000..02dd7195 --- /dev/null +++ b/src/app/(outerbase)/nav-signin-banner.tsx @@ -0,0 +1,53 @@ +import Banner from "@/components/orbit/banner"; +import RippleFilter from "@/components/orbit/banner/ripple-filter"; +import { Button } from "@/components/orbit/button"; +import { useRouter } from "next/navigation"; +import { useSession } from "./session-provider"; + +export default function NavigationSigninBanner() { + const { isLoading, session } = useSession(); + const router = useRouter(); + + if (isLoading) { + return null; + } + + if (session) { + return null; + } + + return ( +
+ } + className="ripple w-full" + onClick={() => { + router.push("/signin"); + }} + > +
+ +
+

Unlock Full Potential

+

+ Outerbase Cloud gives you AI-driver insights, managed database, and + team collaboation. +

+ + +
+ +
+ img +
+
+
+ ); +} diff --git a/src/app/(outerbase)/navigation.tsx b/src/app/(outerbase)/navigation.tsx deleted file mode 100644 index bc69f167..00000000 --- a/src/app/(outerbase)/navigation.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { OuterbaseIcon } from "@/components/icons/outerbase"; -import { getDatabaseIcon } from "@/components/resource-card/utils"; -import { Button, buttonVariants } from "@/components/ui/button"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; -import { cn } from "@/lib/utils"; -import { CaretUpDown } from "@phosphor-icons/react"; -import { useParams, useRouter } from "next/navigation"; -import { useMemo, useState } from "react"; -import { useWorkspaces } from "./workspace-provider"; - -function WorkspaceSelector() { - const router = useRouter(); - const { workspaces, currentWorkspace } = useWorkspaces(); - const { workspaceId } = useParams<{ workspaceId: string }>(); - const [selectedWorkspaceId, setSelectedWorkspaceId] = useState(workspaceId); - - const selectedWorkspace = workspaces.find( - (w) => w.id === selectedWorkspaceId || w.short_name === selectedWorkspaceId - ); - - const bases = useMemo(() => { - const currentBases = [...(selectedWorkspace?.bases ?? [])]; - currentBases.sort((a, b) => a.name.localeCompare(b.name)); - return currentBases; - }, [selectedWorkspace]); - - return ( -
-
- - {workspaces.map((workspace) => ( -
router.push(`/w/${workspace.short_name}`)} - key={workspace.id} - onMouseEnter={() => setSelectedWorkspaceId(workspace.short_name)} - className={cn( - buttonVariants({ - variant: - currentWorkspace?.id === workspace.id ? "secondary" : "ghost", - size: "sm", - }), - "cursor-pointer justify-start py-0.5" - )} - > - {workspace.name} -
- ))} -
-
- - {bases.map((base) => { - const IconComponent = getDatabaseIcon(base.sources[0]?.type); - - return ( -
- router.push(`/w/${selectedWorkspaceId}/${base.short_name}`, {}) - } - key={base.id} - className={cn( - buttonVariants({ - variant: "ghost", - size: "sm", - }), - "cursor-pointer justify-start p-2" - )} - > - - {base.name} -
- ); - })} -
-
- ); -} - -export function NavigationBar() { - const { currentWorkspace } = useWorkspaces(); - - if (!currentWorkspace) { - return null; - } - - return ( -
- - - - - - - - - -
- ); -} diff --git a/src/app/(outerbase)/new-resource-button.tsx b/src/app/(outerbase)/new-resource-button.tsx new file mode 100644 index 00000000..9fa55887 --- /dev/null +++ b/src/app/(outerbase)/new-resource-button.tsx @@ -0,0 +1,232 @@ +import { Button } from "@/components/orbit/button"; +import { Input } from "@/components/orbit/input"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { cn } from "@/lib/utils"; +import { CaretDown, ChartBar, MagnifyingGlass } from "@phosphor-icons/react"; +import Link from "next/link"; +import { PropsWithChildren, useMemo, useState } from "react"; +import { getCreateResourceTypeList } from "./new-resource-list"; + +function CreateResourceItem({ + selected, + data, +}: PropsWithChildren<{ data: NewResourceType; selected?: boolean }>) { + if (data.comingSoon) { + return ( +
+ + {data.name} + {data.comingSoon && ( + + Coming Soon + + )} +
+ ); + } + + return ( + + + {data.name} + + ); +} + +export interface NewResourceType { + name: string; + icon: React.FC>; + href: string; + comingSoon?: boolean; + colorClassName?: string; + thirdParty?: boolean; +} +interface NewResourceProps { + onCreateBoard?: () => void; + workspaceId?: string; +} + +export default function NewResourceType({ + onCreateBoard, + workspaceId, +}: NewResourceProps) { + const resourceTypeList = useMemo(() => { + const tmp = getCreateResourceTypeList(workspaceId); + tmp.sort((a, b) => a.name.localeCompare(b.name)); + return tmp; + }, [workspaceId]); + + const [search, setSearch] = useState(""); + const [open, setOpen] = useState(false); + + const allResourceType = ( + <> +
+ + + {/* */} +
+ +

+ Bring your existing databases +

+ +
+
+ {resourceTypeList + .filter((resource) => !resource.thirdParty) + .filter((_, idx) => idx % 2 === 0) + .map((resource) => ( + + ))} +
+ +
+ {resourceTypeList + .filter((resource) => !resource.thirdParty) + .filter((_, idx) => idx % 2 === 1) + .map((resource) => ( + + ))} +
+
+ +

+ Third party integrations +

+ +
+
+ {resourceTypeList + .filter((resource) => !!resource.thirdParty) + .filter((_, idx) => idx % 2 === 0) + .map((resource) => ( + + ))} +
+ +
+ {resourceTypeList + .filter((resource) => !!resource.thirdParty) + .filter((_, idx) => idx % 2 === 1) + .map((resource) => ( + + ))} +
+
+ + {/*

Or use connection string

+
+ } + placeholder="postgres://testing" + /> +
*/} + + ); + + const resourceSearch = useMemo(() => { + const filteredResource = resourceTypeList + .filter((resource) => + resource.name.toLowerCase().includes(search.toLowerCase()) + ) + .sort((a, b) => { + return a.name.localeCompare(b.name); + }); + + if (filteredResource.length === 0) { + return ( +
+ + There is no resource type of {search} + +
+ ); + } + + return ( +
+ {filteredResource + .sort((a, b) => { + return a.name.localeCompare(b.name); + }) + .map((resource, resourceIdx) => ( + + ))} +
+ ); + }, [search, resourceTypeList]); + + return ( + <> + { + setSearch(""); + setOpen(openState); + }} + modal={false} + > + + + + +
+ } + /> +
+ + {search ? resourceSearch : allResourceType} +
+
+ {open && ( +
+ )} + + ); +} diff --git a/src/app/(outerbase)/new-resource-list.tsx b/src/app/(outerbase)/new-resource-list.tsx new file mode 100644 index 00000000..4857cb7d --- /dev/null +++ b/src/app/(outerbase)/new-resource-list.tsx @@ -0,0 +1,106 @@ +import { + MySQLIcon, + PostgreIcon, + SQLiteIcon, +} from "@/components/icons/outerbase-icon"; +import { + CloudflareIcon, + DigitalOceanIcon, + NeonIcon, + RQLiteIcon, + StarbaseIcon, + SupabaseIcon, + TursoIcon, + ValTownIcon, +} from "@/components/resource-card/icon"; +import { NewResourceType } from "./new-resource-button"; + +export function getCreateResourceTypeList( + workspaceId?: string +): NewResourceType[] { + return [ + { + name: "Supabase", + icon: SupabaseIcon, + href: workspaceId ? "" : "", + comingSoon: true, + thirdParty: true, + }, + { + name: "Cloudflare", + icon: CloudflareIcon, + href: workspaceId ? "" : "", + thirdParty: true, + comingSoon: true, + }, + { + name: "Cloudflare (Manual)", + icon: CloudflareIcon, + href: workspaceId ? "" : "/local/new-base/cloudflare-d1", + }, + { + name: "Neon", + icon: NeonIcon, + href: workspaceId ? "" : "", + comingSoon: true, + thirdParty: true, + }, + { + name: "StarbaseDB", + icon: StarbaseIcon, + href: workspaceId + ? `/w/${workspaceId}/new-base/starbasedb` + : "/local/new-base/starbase", + }, + { + name: "Turso/LibSQL (Manual)", + icon: TursoIcon, + href: workspaceId ? "" : "/local/new-base/turso", + }, + { + name: "Turso", + icon: TursoIcon, + thirdParty: true, + comingSoon: true, + href: workspaceId + ? `/w/${workspaceId}/new-base/turso` + : "/local/new-base/turso", + }, + { + name: "DigitalOcean", + icon: DigitalOceanIcon, + comingSoon: true, + href: workspaceId ? "" : "", + thirdParty: true, + }, + { + name: "Postgres", + icon: PostgreIcon, + href: workspaceId + ? `/w/${workspaceId}/new-base/postgres` + : "/local/new-base/postgres", + }, + { + name: "MySQL", + icon: MySQLIcon, + href: workspaceId + ? `/w/${workspaceId}/new-base/mysql` + : "/local/new-base/mysql", + }, + { + name: "SQLite", + icon: SQLiteIcon, + href: workspaceId ? "" : "/local/new-base/sqlite-filehandler", + }, + { + name: "val.town", + icon: ValTownIcon, + href: workspaceId ? "" : "/local/new-base/valtown", + }, + { + name: "rqlite", + icon: RQLiteIcon, + href: workspaceId ? "" : "/local/new-base/rqlite", + }, + ].filter((resource) => resource.href || resource.comingSoon); +} diff --git a/src/app/(outerbase)/page.tsx b/src/app/(outerbase)/page.tsx new file mode 100644 index 00000000..fcb67f60 --- /dev/null +++ b/src/app/(outerbase)/page.tsx @@ -0,0 +1,41 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import NavigationLayout from "./nav-layout"; +import { ResourceItemList } from "./resource-item-helper"; +import { useSession } from "./session-provider"; +import { useWorkspaces } from "./workspace-provider"; + +export default function OuterbaseMainPage() { + const router = useRouter(); + const { isLoading: sessionLoading, session } = useSession(); + const { workspaces, loading: workspaceLoading } = useWorkspaces(); + + useEffect(() => { + if (sessionLoading) return; + + // Invalid session, go to local connection + if (!session) { + router.push("/local"); + } + + if (workspaceLoading) return; + if (!workspaces) return; + + // Redirect to the first workspace + if (workspaces.length > 0) { + router.push(`/w/${workspaces[0].short_name}`); + } else { + router.push("/local"); + } + }, [session, sessionLoading, workspaceLoading, workspaces, router]); + + return ( + +
+ +
+
+ ); +} diff --git a/src/app/(outerbase)/resource-card-loading.tsx b/src/app/(outerbase)/resource-card-loading.tsx new file mode 100644 index 00000000..e28e5af4 --- /dev/null +++ b/src/app/(outerbase)/resource-card-loading.tsx @@ -0,0 +1,13 @@ +export default function ResourceCardLoading() { + return ( +
+
+
+
+
+
+
+
+
+ ); +} diff --git a/src/app/(outerbase)/resource-item-helper.tsx b/src/app/(outerbase)/resource-item-helper.tsx new file mode 100644 index 00000000..071564d4 --- /dev/null +++ b/src/app/(outerbase)/resource-item-helper.tsx @@ -0,0 +1,284 @@ +import { Input } from "@/components/orbit/input"; +import { MenuBar } from "@/components/orbit/menu-bar"; +import ResourceCard from "@/components/resource-card"; +import { + getDatabaseColor, + getDatabaseFriendlyName, + getDatabaseIcon, + getDatabaseVisual, +} from "@/components/resource-card/utils"; +import { + DropdownMenuItem, + DropdownMenuSeparator, +} from "@/components/ui/dropdown-menu"; +import { timeSince } from "@/lib/utils-datetime"; +import { + OuterbaseAPIBase, + OuterbaseAPIDashboard, + OuterbaseAPIWorkspace, +} from "@/outerbase-cloud/api-type"; +import { + CalendarDots, + MagnifyingGlass, + Pencil, + SortAscending, + SortDescending, + Trash, +} from "@phosphor-icons/react"; +import { AnimatePresence, motion } from "framer-motion"; +import { useMemo, useState } from "react"; +import NewResourceButton from "./new-resource-button"; +import ResourceCardLoading from "./resource-card-loading"; + +export interface ResourceItemProps { + id: string; + type: string; + name: string; + href: string; + status?: string; + lastUsed: number; + color?: string; +} + +export function getResourceItemPropsFromBase( + workspace: OuterbaseAPIWorkspace, + base: OuterbaseAPIBase +): ResourceItemProps { + return { + id: base.id, + type: base.sources[0]?.type ?? "database", + name: base.name, + color: getDatabaseColor(base.sources[0]?.type ?? "database"), + href: `/w/${workspace.short_name}/${base.short_name}`, + lastUsed: base.last_analytics_event?.created_at + ? new Date(base.last_analytics_event?.created_at).getTime() + : 0, + }; +} + +export function getResourceItemPropsFromBoard( + workspace: OuterbaseAPIWorkspace, + board: OuterbaseAPIDashboard +): ResourceItemProps { + return { + id: board.id, + type: "board", + name: board.name, + href: `/w/${workspace?.short_name}/board/${board.id}`, + lastUsed: new Date(board.updated_at).getTime(), + }; +} + +type SortedType = "name_asc" | "name_desc" | "recent"; + +function sortResources(resources: ResourceItemProps[], sorted: SortedType) { + return resources.sort((a, b) => { + if (sorted === "name_asc") { + return (a.name ?? "").localeCompare(b.name ?? ""); + } else if (sorted === "name_desc") { + return (b.name ?? "").localeCompare(a.name ?? ""); + } else if (sorted === "recent") { + return b.lastUsed - a.lastUsed; + } + return 0; + }); +} + +export function ResourceItemList({ + bases, + boards, + loading, + onBoardRemove, + onBaseRemove, + onBaseEdit, + onBoardCreate, + workspaceId, +}: { + bases: ResourceItemProps[]; + boards: ResourceItemProps[]; + loading?: boolean; + onBoardRemove?: (item: ResourceItemProps) => void; + onBaseRemove?: (item: ResourceItemProps) => void; + onBaseEdit?: (item: ResourceItemProps) => void; + onBoardCreate?: () => void; + workspaceId?: string; +}) { + const [search, setSearch] = useState(""); + const [sorted, setSorted] = useState("name_asc"); + + const sortedBases = useMemo(() => { + return sortResources(bases, sorted); + }, [sorted, bases]); + + const sortedBoards = useMemo(() => { + return sortResources(boards, sorted); + }, [sorted, boards]); + + const baseMatchedCount = useMemo(() => { + return bases.filter((base) => + (base.name ?? "").toLowerCase().includes(search.toLowerCase()) + ).length; + }, [bases, search]); + + const boardMatchedCount = useMemo(() => { + return boards.filter((board) => + (board.name ?? "").toLowerCase().includes(search.toLowerCase()) + ).length; + }, [boards, search]); + + return ( + <> +
+ + + + setSorted(newSortOrder as SortedType) + } + items={[ + { value: "name_asc", content: }, + { value: "name_desc", content: }, + { value: "recent", content: }, + ]} + /> + +
+ + } + placeholder="Search" + /> +
+ + {boardMatchedCount > 0 && ( + <> +

Boards

+
+ + {sortedBoards.map((resource: ResourceItemProps) => { + const status = `Last updated ${timeSince(resource.lastUsed)} ago`; + + return ( + + + { + if (onBoardRemove) onBoardRemove(resource); + }} + > + + Remove board + + + + ); + })} + +
+ + )} + + {boardMatchedCount > 0 && baseMatchedCount > 0 && ( +

Bases

+ )} + +
+ {loading && ( + <> + + + + + + )} + + {bases.length > 0 && ( + + {sortedBases.map((resource: ResourceItemProps) => { + const status = `Last updated ${timeSince(resource.lastUsed)} ago`; + + return ( + + + { + if (onBaseEdit) onBaseEdit(resource); + }} + > + + Edit base + + + { + if (onBaseRemove) onBaseRemove(resource); + }} + > + + Remove base + + + + ); + })} + + )} +
+ + ); +} diff --git a/src/app/(outerbase)/session-provider.tsx b/src/app/(outerbase)/session-provider.tsx index 4e4309c4..21e2fae6 100644 --- a/src/app/(outerbase)/session-provider.tsx +++ b/src/app/(outerbase)/session-provider.tsx @@ -1,7 +1,11 @@ "use client"; -import { usePathname, useRouter } from "next/navigation"; -import { createContext, PropsWithChildren, useContext, useEffect } from "react"; -import useSWR from "swr"; +import { + createContext, + PropsWithChildren, + useCallback, + useContext, +} from "react"; +import useSWR, { mutate } from "swr"; import { getOuterbaseSession } from "../../outerbase-cloud/api"; import { OuterbaseAPISession, @@ -9,26 +13,35 @@ import { } from "../../outerbase-cloud/api-type"; interface OuterebaseSessionContextProps { - session: OuterbaseAPISession; - user: OuterbaseAPIUser; + isLoading: boolean; + token?: string; + session?: { + session: OuterbaseAPISession; + user: OuterbaseAPIUser; + }; + logout: () => void; + refreshSession: () => Promise; } -const OuterbaseSessionContext = createContext<{ - session: OuterbaseAPISession; - user: OuterbaseAPIUser; -}>({} as OuterebaseSessionContextProps); +const OuterbaseSessionContext = createContext({ + isLoading: true, + logout: () => {}, + refreshSession: async () => {}, +}); export function useSession() { return useContext(OuterbaseSessionContext); } export function OuterbaseSessionProvider({ children }: PropsWithChildren) { - const router = useRouter(); - const pathname = usePathname(); const token = - typeof window !== "undefined" ? localStorage.getItem("ob-token") : ""; + typeof window !== "undefined" ? localStorage.getItem("ob-token") || "" : ""; - const { data, isLoading } = useSWR( + const { + data, + isLoading, + mutate: mutateSession, + } = useSWR( token ? "session-" + token : undefined, () => { return getOuterbaseSession(); @@ -37,24 +50,24 @@ export function OuterbaseSessionProvider({ children }: PropsWithChildren) { revalidateIfStale: false, revalidateOnFocus: false, revalidateOnReconnect: false, + errorRetryCount: 0, } ); - useEffect(() => { - if (isLoading) return; - if (!data?.session || !data?.user) { - localStorage.setItem("continue-redirect", pathname); - router.push("/signin"); - } - }, [isLoading, data, pathname, router]); + const refreshSession = useCallback(async () => { + if (!token) return; + await mutate("session-" + token); + }, [token]); - if (isLoading || !data) { - return
Session Loading...
; - } + const logout = useCallback(() => { + localStorage.removeItem("session"); + localStorage.removeItem("ob-token"); + mutateSession(undefined, false); + }, [mutateSession]); return ( {children} diff --git a/src/app/(outerbase)/signout/page.tsx b/src/app/(outerbase)/signout/page.tsx new file mode 100644 index 00000000..1c15335a --- /dev/null +++ b/src/app/(outerbase)/signout/page.tsx @@ -0,0 +1,25 @@ +"use client"; + +import { Loader } from "@/components/orbit/loader"; +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import { useSession } from "../session-provider"; + +export default function SignoutPage() { + const { logout } = useSession(); + const router = useRouter(); + + useEffect(() => { + if (typeof window === "undefined") return; + + logout(); + router.push("/"); + }, [router, logout]); + + return ( +
+ +

Signing out....

+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/[baseId]/page-client.tsx b/src/app/(outerbase)/w/[workspaceId]/[baseId]/page-client.tsx deleted file mode 100644 index f1d4d8b8..00000000 --- a/src/app/(outerbase)/w/[workspaceId]/[baseId]/page-client.tsx +++ /dev/null @@ -1,85 +0,0 @@ -"use client"; - -import OpacityLoading from "@/components/gui/loading-opacity"; -import { Studio } from "@/components/gui/studio"; -import { StudioExtensionManager } from "@/core/extension-manager"; -import { - createMySQLExtensions, - createPostgreSQLExtensions, - createSQLiteExtensions, -} from "@/core/standard-extension"; -import { getOuterbaseBase } from "@/outerbase-cloud/api"; -import { OuterbaseAPISource } from "@/outerbase-cloud/api-type"; -import { OuterbaseMySQLDriver } from "@/outerbase-cloud/database/mysql"; -import { OuterbasePostgresDriver } from "@/outerbase-cloud/database/postgresql"; -import { OuterbaseSqliteDriver } from "@/outerbase-cloud/database/sqlite"; -import OuterbaseQueryDriver from "@/outerbase-cloud/query-driver"; -import { useEffect, useMemo, useState } from "react"; - -export default function OuterbaseSourcePageClient({ - workspaceId, - baseId, -}: { - workspaceId: string; - baseId: string; -}) { - const [source, setSource] = useState(); - - useEffect(() => { - if (!workspaceId) return; - if (!baseId) return; - - getOuterbaseBase(workspaceId, baseId).then((base) => { - if (!base) return; - setSource(base.sources[0]); - }); - }, [workspaceId, baseId]); - - const savedDocDriver = useMemo(() => { - if (!workspaceId || !source?.id || !baseId) return null; - return new OuterbaseQueryDriver(workspaceId, baseId, source.id); - }, [workspaceId, baseId, source?.id]); - - const [outerbaseDriver, extensions] = useMemo(() => { - if (!workspaceId || !source) return [null, null]; - - const dialect = source.type; - const outerbaseConfig = { - workspaceId, - sourceId: source.id, - baseId: "", - token: localStorage.getItem("ob-token") ?? "", - }; - - if (dialect === "postgres") { - return [ - new OuterbasePostgresDriver(outerbaseConfig), - new StudioExtensionManager(createPostgreSQLExtensions()), - ]; - } else if (dialect === "mysql") { - return [ - new OuterbaseMySQLDriver(outerbaseConfig), - new StudioExtensionManager(createMySQLExtensions()), - ]; - } - - return [ - new OuterbaseSqliteDriver(outerbaseConfig), - new StudioExtensionManager(createSQLiteExtensions()), - ]; - }, [workspaceId, source]); - - if (!outerbaseDriver || !savedDocDriver) { - return ; - } - - return ( - - ); -} diff --git a/src/app/(outerbase)/w/[workspaceId]/[baseId]/page.tsx b/src/app/(outerbase)/w/[workspaceId]/[baseId]/page.tsx index b2908d20..727c9ad7 100644 --- a/src/app/(outerbase)/w/[workspaceId]/[baseId]/page.tsx +++ b/src/app/(outerbase)/w/[workspaceId]/[baseId]/page.tsx @@ -1,24 +1,101 @@ -import ClientOnly from "@/components/client-only"; -import OuterbaseSourcePageClient from "./page-client"; +"use client"; -interface OuterbaseSourcePageProps { - params: Promise<{ +import { Studio } from "@/components/gui/studio"; +import PageLoading from "@/components/page-loading"; +import { StudioExtensionManager } from "@/core/extension-manager"; +import { + createMySQLExtensions, + createPostgreSQLExtensions, + createSQLiteExtensions, +} from "@/core/standard-extension"; +import DataCatalogExtension from "@/extensions/data-catalog"; +import { getOuterbaseBase } from "@/outerbase-cloud/api"; +import { OuterbaseAPISource } from "@/outerbase-cloud/api-type"; +import DataCatalogOuterbaseDriver from "@/outerbase-cloud/data-catalog-driver"; +import { OuterbaseMySQLDriver } from "@/outerbase-cloud/database/mysql"; +import { OuterbasePostgresDriver } from "@/outerbase-cloud/database/postgresql"; +import { OuterbaseSqliteDriver } from "@/outerbase-cloud/database/sqlite"; +import OuterbaseQueryDriver from "@/outerbase-cloud/query-driver"; +import { useParams } from "next/navigation"; +import { useEffect, useMemo, useState } from "react"; + +export default function OuterbaseSourcePage() { + const { workspaceId, baseId } = useParams<{ workspaceId: string; baseId: string; - }>; -} + }>(); + const [name, setName] = useState(""); + const [source, setSource] = useState(); + + useEffect(() => { + if (!workspaceId) return; + if (!baseId) return; + + getOuterbaseBase(workspaceId, baseId).then((base) => { + if (!base) return; + setSource(base.sources[0]); + setName(base.name); + }); + }, [workspaceId, baseId]); + + const savedDocDriver = useMemo(() => { + if (!workspaceId || !source?.id || !baseId) return null; + return new OuterbaseQueryDriver(workspaceId, baseId, source.id); + }, [workspaceId, baseId, source?.id]); + + const [outerbaseDriver, extensions] = useMemo(() => { + if (!workspaceId || !source) return [null, null]; + + const dialect = source.type; + const outerbaseConfig = { + workspaceId, + sourceId: source.id, + baseId, + token: localStorage.getItem("ob-token") ?? "", + }; + + const outerbaseSpecifiedDrivers = [ + new DataCatalogExtension(new DataCatalogOuterbaseDriver(outerbaseConfig)), + ]; + + if (dialect === "postgres") { + return [ + new OuterbasePostgresDriver(outerbaseConfig), + new StudioExtensionManager([ + ...createPostgreSQLExtensions(), + ...outerbaseSpecifiedDrivers, + ]), + ]; + } else if (dialect === "mysql") { + return [ + new OuterbaseMySQLDriver(outerbaseConfig), + new StudioExtensionManager([ + ...createMySQLExtensions(), + ...outerbaseSpecifiedDrivers, + ]), + ]; + } + + return [ + new OuterbaseSqliteDriver(outerbaseConfig), + new StudioExtensionManager([ + ...createSQLiteExtensions(), + ...outerbaseSpecifiedDrivers, + ]), + ]; + }, [workspaceId, source, baseId]); -export default async function OuterbaseSourcePage( - props: OuterbaseSourcePageProps -) { - const params = await props.params; + if (!outerbaseDriver || !savedDocDriver) { + return Loading Base ...; + } return ( - - - + ); } diff --git a/src/app/(outerbase)/w/[workspaceId]/billing/page.tsx b/src/app/(outerbase)/w/[workspaceId]/billing/page.tsx new file mode 100644 index 00000000..85114a4b --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/billing/page.tsx @@ -0,0 +1,14 @@ +"use client"; +import NavigationHeader from "@/app/(outerbase)/nav-header"; +import NavigationLayout from "@/app/(outerbase)/nav-layout"; + +export default function WorkspaceBillingPage() { + return ( + + +
+

Billing

+
+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page-client.tsx b/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page-client.tsx deleted file mode 100644 index 78b65fde..00000000 --- a/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page-client.tsx +++ /dev/null @@ -1,15 +0,0 @@ -"use client"; - -export default function BoardPageClient({ - workspaceId, - boardId, -}: { - workspaceId: string; - boardId: string; -}) { - return ( -
- {workspaceId} {boardId} -
- ); -} diff --git a/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page.tsx b/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page.tsx index 253e83f1..779ae602 100644 --- a/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page.tsx +++ b/src/app/(outerbase)/w/[workspaceId]/board/[boardId]/page.tsx @@ -1,19 +1,114 @@ -import ClientOnly from "@/components/client-only"; -import BoardPageClient from "./page-client"; +"use client"; -interface BoardPageProps { - params: Promise<{ workspaceId: string; boardId: string }>; +import NavigationDashboardLayout from "@/app/(outerbase)/nav-board-layout"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import Board, { DashboardProps } from "@/components/board"; +import { Loader } from "@/components/orbit/loader"; +import { WEBSITE_NAME } from "@/const"; +import OuterbaseBoardStorageDriver from "@/drivers/board-storage/outerbase"; + +import { getOuterbaseDashboard } from "@/outerbase-cloud/api"; +import { OuterbaseAPIDashboardDetail } from "@/outerbase-cloud/api-type"; +import OuterbaseBoardSourceDriver from "@/outerbase-cloud/database-source"; +import { useOuterbaseDashboardList } from "@/outerbase-cloud/hook"; +import { useParams } from "next/navigation"; +import { useMemo, useState } from "react"; +import useSWR, { KeyedMutator } from "swr"; + +function BoardPageEditor({ + initialValue, +}: { + initialValue: OuterbaseAPIDashboardDetail; + mutate: KeyedMutator; +}) { + const { boardId } = useParams<{ + workspaceId: string; + boardId: string; + }>(); + const { currentWorkspace } = useWorkspaces(); + const [interval, setIntervals] = useState(0); + + const boardSources = useMemo(() => { + if (!currentWorkspace) return; + return new OuterbaseBoardSourceDriver(currentWorkspace); + }, [currentWorkspace]); + + const storageDriver = useMemo(() => { + if (!currentWorkspace) return; + return new OuterbaseBoardStorageDriver( + currentWorkspace.short_name, + boardId + ); + }, [boardId, currentWorkspace]); + + const [value, setValue] = useState(initialValue); + const [filter, setFilter] = useState({}); + + if (!boardSources) { + return
Loading Workspace....
; + } + + return ( + + ); } -export default async function BoardPage(props: BoardPageProps) { - const params = await props.params; +export default function BoardPage() { + const { workspaceId, boardId } = useParams<{ + boardId: string; + workspaceId: string; + }>(); + const { data, mutate } = useSWR(`board-${boardId}`, () => { + return getOuterbaseDashboard(workspaceId, boardId); + }); + + const { currentWorkspace, loading: workspaceLoading } = useWorkspaces(); + const { data: dashboardList, isLoading: dashboardLoading } = + useOuterbaseDashboardList(); + + const dashboards = useMemo(() => { + if (!currentWorkspace) return []; + if (!dashboardList) return []; + + const tmp = (dashboardList ?? []).filter( + (board) => + board.workspace_id === currentWorkspace.id && board.base_id === null + ); + + tmp.sort((a, b) => a.name.localeCompare(b.name)); + return tmp.map((board) => { + return { + id: board.id, + name: board.name, + href: `/w/${currentWorkspace.short_name}/board/${board.id}`, + }; + }); + }, [dashboardList, currentWorkspace]); return ( - - - + + {data?.name ?? WEBSITE_NAME} +
+ {data ? ( + + ) : ( + + )} +
+
); } diff --git a/src/app/(outerbase)/w/[workspaceId]/dialog-base-delete.tsx b/src/app/(outerbase)/w/[workspaceId]/dialog-base-delete.tsx new file mode 100644 index 00000000..86a30c61 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/dialog-base-delete.tsx @@ -0,0 +1,78 @@ +import CopyableText from "@/components/copyable-text"; +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/ui/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { deleteOuterbaseBase } from "@/outerbase-cloud/api"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; + +export const deleteBaseDialog = createDialog<{ + workspaceId: string; + baseId: string; + baseName: string; +}>(({ close, baseName, workspaceId, baseId }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const deleteClicked = useCallback(() => { + if (name !== baseName) return; + + setLoading(true); + + deleteOuterbaseBase(workspaceId, baseId) + .then(() => { + close(undefined); + }) + .finally(() => { + setLoading(false); + }); + }, [name, workspaceId, baseId, close, baseName]); + + return ( + <> + + Confirm deletion of {baseName} + + All saved queries, dashboards, definitions and any other contributions + made to your Base will be deleted. This action is permanent and{" "} + cannot + be undone. + + + +
+
+ +
+ + setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/w/[workspaceId]/dialog-board-create.tsx b/src/app/(outerbase)/w/[workspaceId]/dialog-board-create.tsx new file mode 100644 index 00000000..eb194bc9 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/dialog-board-create.tsx @@ -0,0 +1,67 @@ +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { createOuterbaseDashboard } from "@/outerbase-cloud/api"; +import { OuterbaseAPIDashboardDetail } from "@/outerbase-cloud/api-type"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; + +export const createBoardDialog = createDialog< + { workspaceId: string }, + OuterbaseAPIDashboardDetail | undefined +>(({ close, workspaceId }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const createBoardClicked = useCallback(() => { + if (name.length === 0) return; + + setLoading(true); + + createOuterbaseDashboard(workspaceId, undefined, name) + .then((createdBoard) => { + close(createdBoard); + }) + .finally(() => { + setLoading(false); + }); + }, [close, name, workspaceId]); + + return ( + <> + + New Board + + + +
+ setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/w/[workspaceId]/dialog-board-delete.tsx b/src/app/(outerbase)/w/[workspaceId]/dialog-board-delete.tsx new file mode 100644 index 00000000..8caea7e8 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/dialog-board-delete.tsx @@ -0,0 +1,77 @@ +import CopyableText from "@/components/copyable-text"; +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/ui/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { deleteOuterbaseDashboard } from "@/outerbase-cloud/api"; +import { LucideLoader } from "lucide-react"; +import { useCallback, useState } from "react"; + +export const deleteBoardDialog = createDialog<{ + workspaceId: string; + boardId: string; + boardName: string; +}>(({ close, boardName, workspaceId, boardId }) => { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const deleteClicked = useCallback(() => { + if (name !== boardName) return; + + setLoading(true); + + deleteOuterbaseDashboard(workspaceId, boardId) + .then(() => { + close(undefined); + }) + .finally(() => { + setLoading(false); + }); + }, [name, workspaceId, boardId, close, boardName]); + + return ( + <> + + Confirm deletion of board {boardName} + + All saved charts and any other contributions made to your Dashboard + will be deleted. This action is permanent and cannot{" "} + be undone. + + + +
+
+ +
+ + setName(e.currentTarget.value)} + /> +
+ + + + + + + ); +}); diff --git a/src/app/(outerbase)/w/[workspaceId]/layout.tsx b/src/app/(outerbase)/w/[workspaceId]/layout.tsx index 02b2a905..0c544d48 100644 --- a/src/app/(outerbase)/w/[workspaceId]/layout.tsx +++ b/src/app/(outerbase)/w/[workspaceId]/layout.tsx @@ -1,20 +1,15 @@ -import { OuterbaseSessionProvider } from "@/app/(outerbase)/session-provider"; -import ClientOnly from "@/components/client-only"; -import ThemeLayout from "../../../(theme)/theme_layout"; -import { WorkspaceProvider } from "../../workspace-provider"; +import { DialogProvider } from "@/components/create-dialog"; +import AuthProvider from "../../auth-provider"; -export default function RootLayout({ +export default function OuterbaseLayout({ children, }: { children: React.ReactNode; }) { return ( - - - - {children} - - - + + {children} + + ); } diff --git a/src/app/(outerbase)/w/[workspaceId]/new-base/[driver]/page.tsx b/src/app/(outerbase)/w/[workspaceId]/new-base/[driver]/page.tsx new file mode 100644 index 00000000..67f28f61 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/new-base/[driver]/page.tsx @@ -0,0 +1,145 @@ +"use client"; +import { + CommonConnectionConfig, + ConnectionConfigEditor, + validateTemplate, +} from "@/components/connection-config-editor"; +import { ConnectionTemplateDictionary } from "@/components/connection-config-editor/template"; +import { Button } from "@/components/orbit/button"; +import { getDatabaseFriendlyName } from "@/components/resource-card/utils"; +import { + createOuterbaseBase, + createOuterbaseConnection, + createOuterbaseSource, + testOuterbaseSource, +} from "@/outerbase-cloud/api-workspace"; +import { ArrowLeft, ArrowRight, FloppyDisk } from "@phosphor-icons/react"; +import { useParams, useRouter } from "next/navigation"; +import { useCallback, useMemo, useState } from "react"; + +export default function WorkspaceNewBasePage() { + const { driver, workspaceId } = useParams<{ + driver: string; + workspaceId: string; + }>(); + const router = useRouter(); + const [value, setValue] = useState({ name: "" }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(""); + const [validateErrors, setValidateErrors] = useState>( + {} + ); + + const template = useMemo(() => { + return ConnectionTemplateDictionary[driver]; + }, [driver]); + + const onSave = useCallback( + (overrideRedirect?: string) => { + if (!template.remoteFrom || !template.remoteTo) return; + + const errors = validateTemplate(value, template); + setValidateErrors(errors); + if (Object.keys(errors).length > 0) return; + + setLoading(true); + setError(""); + + const { name: baseName, source } = template.remoteTo(value); + + const runSave = async () => { + await testOuterbaseSource(workspaceId, source); + const baseResponse = await createOuterbaseBase(workspaceId, baseName); + const connResponse = await createOuterbaseConnection( + workspaceId, + baseResponse.id, + baseName + ); + + await createOuterbaseSource(workspaceId, { + ...source, + base_id: baseResponse.id, + connection_id: connResponse.id, + }); + + router.replace( + overrideRedirect ?? `/w/${workspaceId}/${baseResponse.short_name}` + ); + }; + + runSave() + .then() + .catch((e) => { + if (e instanceof Error) { + setError(e.message); + } else { + setError(e.toString()); + } + }) + .finally(() => setLoading(false)); + }, + [workspaceId, template, value, router] + ); + + if (!template.remoteFrom || !template.remoteTo) { + return
Invalid driver
; + } + + return ( + <> +
+
+ + +
+
+ +
+
Connect to {getDatabaseFriendlyName(driver)} database
+
+ + {error && ( +
+ {error} +
+ )} + + +
+ +
+
+ + + +
+
+ + ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/new-base/page.tsx b/src/app/(outerbase)/w/[workspaceId]/new-base/page.tsx new file mode 100644 index 00000000..d7c56182 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/new-base/page.tsx @@ -0,0 +1,3 @@ +export default function NewBasePage() { + return
Unknown page
; +} diff --git a/src/app/(outerbase)/w/[workspaceId]/page-client.tsx b/src/app/(outerbase)/w/[workspaceId]/page-client.tsx deleted file mode 100644 index 2d822a2d..00000000 --- a/src/app/(outerbase)/w/[workspaceId]/page-client.tsx +++ /dev/null @@ -1,118 +0,0 @@ -"use client"; - -import { ButtonGroup, ButtonGroupItem } from "@/components/button-group"; -import { Toolbar } from "@/components/gui/toolbar"; -import ResourceCard from "@/components/resource-card"; -import { - getDatabaseFriendlyName, - getDatabaseIcon, - getDatabaseVisual, -} from "@/components/resource-card/utils"; -import { BoardVisual } from "@/components/resource-card/visual"; -import { DropdownMenuItem } from "@/components/ui/dropdown-menu"; -import { getOuterbaseDashboardList } from "@/outerbase-cloud/api"; -import { - CalendarDots, - ChartBar, - SortAscending, - SortDescending, -} from "@phosphor-icons/react"; -import { useParams } from "next/navigation"; -import useSWR from "swr"; -import { NavigationBar } from "../../navigation"; -import { useWorkspaces } from "../../workspace-provider"; - -export default function WorkspaceListPageClient() { - const { workspaces } = useWorkspaces(); - const { workspaceId } = useParams<{ workspaceId: string }>(); - - const { data: boards } = useSWR( - `/workspace/${workspaceId}/boards`, - () => { - return getOuterbaseDashboardList(workspaceId); - }, - { - revalidateIfStale: false, - revalidateOnFocus: false, - revalidateOnReconnect: false, - } - ); - - const bases = - workspaces.find( - (workspace) => - workspace.short_name === workspaceId || workspace.id === workspaceId - )?.bases ?? []; - - return ( -
- - -
-
- - - All - Bases - Boards - - - - - - - - - - - - - - - - - - - -
- -

Board

-
- {(boards?.items ?? []) - .filter((board) => board.base_id === null) - .map((board) => ( - - ))} -
- -

Base

- -
- {bases.map((base) => ( - - Remove - - ))} -
-
-
- ); -} diff --git a/src/app/(outerbase)/w/[workspaceId]/page.tsx b/src/app/(outerbase)/w/[workspaceId]/page.tsx index 006063e3..455c90ea 100644 --- a/src/app/(outerbase)/w/[workspaceId]/page.tsx +++ b/src/app/(outerbase)/w/[workspaceId]/page.tsx @@ -1,11 +1,128 @@ "use client"; -import ClientOnly from "@/components/client-only"; -import WorkspaceListPageClient from "./page-client"; + +import { useOuterbaseDashboardList } from "@/outerbase-cloud/hook"; +import { useRouter } from "next/navigation"; +import { useCallback, useMemo } from "react"; +import NavigationHeader from "../../nav-header"; +import NavigationLayout from "../../nav-layout"; +import { + getResourceItemPropsFromBase, + getResourceItemPropsFromBoard, + ResourceItemList, + ResourceItemProps, +} from "../../resource-item-helper"; +import { useWorkspaces } from "../../workspace-provider"; +import { deleteBaseDialog } from "./dialog-base-delete"; +import { createBoardDialog } from "./dialog-board-create"; +import { deleteBoardDialog } from "./dialog-board-delete"; export default function WorkspaceListPage() { + const router = useRouter(); + const { + currentWorkspace, + loading: workspaceLoading, + refreshWorkspace, + } = useWorkspaces(); + const { data: dashboardList, mutate: refreshDashboardList } = + useOuterbaseDashboardList(); + + const bases = useMemo(() => { + if (!currentWorkspace) return []; + + const bases = + (currentWorkspace.bases ?? []).map((base) => { + return getResourceItemPropsFromBase(currentWorkspace, base); + }) ?? []; + + return bases; + }, [currentWorkspace]); + + const dashboards = useMemo(() => { + if (!currentWorkspace) return []; + + return ( + (dashboardList ?? []) + .filter( + (board) => + board.workspace_id === currentWorkspace.id && board.base_id === null + ) + .map((board) => { + return getResourceItemPropsFromBoard(currentWorkspace, board); + }) ?? [] + ); + }, [currentWorkspace, dashboardList]); + + const onDeleteBoardClicked = useCallback( + (deletedResource: ResourceItemProps) => { + if (!currentWorkspace) return; + + deleteBoardDialog + .show({ + workspaceId: currentWorkspace.id, + boardId: deletedResource.id, + boardName: deletedResource.name, + }) + .then(() => { + refreshDashboardList(); + }) + .catch(); + }, + [currentWorkspace, refreshDashboardList] + ); + + const onDeleteBaseClicked = useCallback( + (deletedResource: ResourceItemProps) => { + if (!currentWorkspace) return; + + deleteBaseDialog + .show({ + workspaceId: currentWorkspace.id, + baseId: deletedResource.id, + baseName: deletedResource.name, + }) + .then(() => { + refreshWorkspace(); + }) + .catch(); + }, + [currentWorkspace, refreshWorkspace] + ); + + const onCreateBoardClicked = useCallback(() => { + if (!currentWorkspace) return; + + createBoardDialog + .show({ + workspaceId: currentWorkspace.id, + }) + .then((createdBoard) => { + if (!createdBoard) return; + + refreshDashboardList(); + router.push( + `/w/${currentWorkspace.short_name}/board/${createdBoard.id}` + ); + }); + }, [currentWorkspace, router, refreshDashboardList]); + return ( - - - + <> + {currentWorkspace?.name ?? "Untitled"} + + + +
+ +
+
+ ); } diff --git a/src/app/(outerbase)/w/[workspaceId]/redirect-valid-workspace.ts b/src/app/(outerbase)/w/[workspaceId]/redirect-valid-workspace.ts new file mode 100644 index 00000000..b20afd13 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/redirect-valid-workspace.ts @@ -0,0 +1,24 @@ +"use client"; +import { useParams, useRouter } from "next/navigation"; +import { useEffect } from "react"; +import { useWorkspaces } from "../../workspace-provider"; + +export default function useRedirectValidWorkspace() { + const { workspaceId } = useParams(); + const { currentWorkspace, workspaces, loading } = useWorkspaces(); + const router = useRouter(); + + useEffect(() => { + // If the current workspace is not found, redirect to the first workspace + if (loading) return; + if (!workspaceId) return; + if (workspaceId === "local-workspace") return; + if (typeof window === "undefined") return; + + if (!currentWorkspace) { + if (workspaces?.length) { + router.replace(`/w/${workspaces[0].short_name}`); + } + } + }, [loading, workspaces, currentWorkspace, workspaceId, router]); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/settings/delete.tsx b/src/app/(outerbase)/w/[workspaceId]/settings/delete.tsx new file mode 100644 index 00000000..b5075281 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/settings/delete.tsx @@ -0,0 +1,121 @@ +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import CopyableText from "@/components/copyable-text"; +import { createDialog } from "@/components/create-dialog"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { OuterbaseAPIWorkspace } from "@/outerbase-cloud/api-type"; +import { deleteOuterbaseWorkspace } from "@/outerbase-cloud/api-workspace"; +import { useRouter } from "next/navigation"; +import { useCallback, useState } from "react"; + +function DeleteWorkspaceDialog({ + workspace, + close, +}: { + workspace: OuterbaseAPIWorkspace; + close: (value: boolean) => void; +}) { + const [loading, setLoading] = useState(false); + const [name, setName] = useState(""); + + const onDeletedClicked = useCallback(() => { + setLoading(true); + deleteOuterbaseWorkspace(workspace.id) + .then(() => { + close(true); + }) + .finally(() => { + setLoading(false); + }); + }, [close, workspace]); + + return ( + <> + + Confirm deletion of {workspace.name} + + + + Deleting this workspace will delete all Bases and revoke all connections + made to your databases. All members will lose access. This action is + permanent and cannot be undone. + + +
+
+ +
+ + +
+ + + + + + + ); +} + +const deleteWorkspaceDialog = createDialog< + { + workspace: OuterbaseAPIWorkspace; + }, + boolean +>( + ({ workspace, close }) => { + return ; + }, + { defaultValue: false, slot: "workspace" } +); + +export default function WorkspaceDeleteSection({ + workspace, +}: { + workspace: OuterbaseAPIWorkspace; +}) { + const router = useRouter(); + const { refreshWorkspace } = useWorkspaces(); + + const onDeleteClicked = useCallback(async () => { + const success = await deleteWorkspaceDialog.show({ workspace }); + if (success) { + refreshWorkspace().then(() => router.push("/")); + } + }, [workspace, router, refreshWorkspace]); + + return ( +
+

Delete workspace

+

+ This will delete all Bases within this workspace. All members will lose + access. +

+ +
+ +
+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/settings/detail.tsx b/src/app/(outerbase)/w/[workspaceId]/settings/detail.tsx new file mode 100644 index 00000000..5e33f9b4 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/settings/detail.tsx @@ -0,0 +1,69 @@ +"use client"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import LabelInput from "@/components/label-input"; +import { Button } from "@/components/orbit/button"; +import { OuterbaseAPIWorkspace } from "@/outerbase-cloud/api-type"; +import { updateOuterbaseWorkspace } from "@/outerbase-cloud/api-workspace"; +import { useRouter } from "next/navigation"; +import { useCallback, useState } from "react"; + +export default function WorkspaceDetailSection({ + workspace, +}: { + workspace: OuterbaseAPIWorkspace; +}) { + const router = useRouter(); + const { refreshWorkspace } = useWorkspaces(); + const [loading, setLoading] = useState(false); + const [shortName, setShortName] = useState(workspace.short_name); + const [name, setName] = useState(workspace.name); + + const onUpdateClicked = useCallback(() => { + setLoading(true); + updateOuterbaseWorkspace(workspace.id, { short_name: shortName, name }) + .then(() => { + refreshWorkspace().then(() => { + if (workspace.short_name !== shortName) { + router.push(`/w/${shortName}/settings`); + } + setLoading(false); + }); + }) + .catch(() => setLoading(false)); + }, [shortName, name, workspace, router, refreshWorkspace]); + + return ( +
+

Details

+ +
+ + +
+ +
+
+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/settings/gateway.tsx b/src/app/(outerbase)/w/[workspaceId]/settings/gateway.tsx new file mode 100644 index 00000000..b5b55b5f --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/settings/gateway.tsx @@ -0,0 +1,20 @@ +import { Button } from "@/components/orbit/button"; + +export default function WorkspaceGatewaySection() { + return ( +
+

Gateway

+ +

+ Securely access private network databases without modifying your + firewall or VPN +

+ +
+ +
+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/settings/members.tsx b/src/app/(outerbase)/w/[workspaceId]/settings/members.tsx new file mode 100644 index 00000000..780c1f82 --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/settings/members.tsx @@ -0,0 +1,17 @@ +"use client"; +import { Button } from "@/components/orbit/button"; +import { Plus } from "@phosphor-icons/react"; + +export default function WorkspaceMemberSection() { + return ( +
+
+

Members

+ +
+
+ ); +} diff --git a/src/app/(outerbase)/w/[workspaceId]/settings/page.tsx b/src/app/(outerbase)/w/[workspaceId]/settings/page.tsx new file mode 100644 index 00000000..d03497ef --- /dev/null +++ b/src/app/(outerbase)/w/[workspaceId]/settings/page.tsx @@ -0,0 +1,35 @@ +"use client"; +import NavigationHeader from "@/app/(outerbase)/nav-header"; +import NavigationLayout from "@/app/(outerbase)/nav-layout"; +import { useWorkspaces } from "@/app/(outerbase)/workspace-provider"; +import { Loader } from "@/components/orbit/loader"; +import WorkspaceDeleteSection from "./delete"; +import WorkspaceDetailSection from "./detail"; + +export default function WorkspaceBillingPage() { + const { currentWorkspace } = useWorkspaces(); + + return ( + + + +
+

Workspace settings

+ + {currentWorkspace ? ( + <> + + {/* + */} + + + ) : ( +
+ + Loading workspace... +
+ )} +
+
+ ); +} diff --git a/src/app/(outerbase)/workspace-provider.tsx b/src/app/(outerbase)/workspace-provider.tsx index 35608622..6b568daa 100644 --- a/src/app/(outerbase)/workspace-provider.tsx +++ b/src/app/(outerbase)/workspace-provider.tsx @@ -1,23 +1,55 @@ "use client"; import { getOuterbaseWorkspace } from "@/outerbase-cloud/api"; import { OuterbaseAPIWorkspace } from "@/outerbase-cloud/api-type"; +import { produce } from "immer"; +import { noop } from "lodash"; import { useParams } from "next/navigation"; -import { createContext, PropsWithChildren, useContext, useMemo } from "react"; +import { + createContext, + PropsWithChildren, + useCallback, + useContext, + useMemo, +} from "react"; import useSWR from "swr"; +import { useSession } from "./session-provider"; const WorkspaceContext = createContext<{ workspaces: OuterbaseAPIWorkspace[]; currentWorkspace?: OuterbaseAPIWorkspace; + refreshWorkspace: () => Promise; + + /** + * Updates the specified workspace in the cache directly, + * instead of refreshing all workspaces from the server. + * This is useful when the modify API returns the updated workspace object, + * allowing us to save time by updating the cache directly. + * + * @param workspace - The workspace object to update in the cache. + */ + refreshPartial: (workspace: OuterbaseAPIWorkspace) => void; loading: boolean; -}>({ workspaces: [], loading: true }); +}>({ + workspaces: [], + loading: true, + refreshWorkspace: async () => {}, + refreshPartial: noop, +}); export function useWorkspaces() { return useContext(WorkspaceContext); } export function WorkspaceProvider({ children }: PropsWithChildren) { - const { data, isLoading } = useSWR( - "workspaces", + const { token } = useSession(); + + const { data, isLoading, mutate } = useSWR( + // The workspace cache depends on the token. + // Including the token in the key ensures the cache is user-specific. + // Without this, the cache might be shared between different users, + // causing a brief period where the workspace data is incorrect + // when a user logs out and another logs in. + token ? `/workspaces?=${token}` : undefined, () => { return getOuterbaseWorkspace(); }, @@ -25,6 +57,7 @@ export function WorkspaceProvider({ children }: PropsWithChildren) { revalidateIfStale: false, revalidateOnFocus: false, revalidateOnReconnect: false, + errorRetryCount: 0, } ); @@ -40,7 +73,36 @@ export function WorkspaceProvider({ children }: PropsWithChildren) { ); }, [workspaceId, data]); - console.log(data, workspaceId, currentWorkspace); + const refreshPartial = useCallback( + (modifiedWorkspace: OuterbaseAPIWorkspace) => { + if (!data) return; + + const newData = produce(data, (draft) => { + for (let i = 0; i < draft.items.length; i++) { + if (draft.items[i].id === modifiedWorkspace.id) { + draft.items[i] = modifiedWorkspace; + return; + } + } + + draft.items.push(modifiedWorkspace); + }); + + mutate(newData, { + revalidate: false, + optimisticData: newData, + }); + }, + [mutate, data] + ); + + const refreshWorkspace = useCallback(async () => { + const newWorkspceList = await getOuterbaseWorkspace(); + mutate(newWorkspceList, { + revalidate: true, + optimisticData: newWorkspceList, + }); + }, [mutate]); return ( {children} diff --git a/src/app/(public)/learn/sqlite/indexing/page.mdx b/src/app/(public)/learn/sqlite/indexing/page.mdx deleted file mode 100644 index ce7ce9bf..00000000 --- a/src/app/(public)/learn/sqlite/indexing/page.mdx +++ /dev/null @@ -1,5 +0,0 @@ -import { DocContent } from "@/components/mdx/docs"; - - -Blank Content - diff --git a/src/app/(public)/learn/sqlite/introduction/page.mdx b/src/app/(public)/learn/sqlite/introduction/page.mdx deleted file mode 100644 index 70685157..00000000 --- a/src/app/(public)/learn/sqlite/introduction/page.mdx +++ /dev/null @@ -1,5 +0,0 @@ -import { DocContent } from "@/components/mdx/docs"; - - -Blank Content - diff --git a/src/app/(public)/learn/sqlite/layout.tsx b/src/app/(public)/learn/sqlite/layout.tsx deleted file mode 100644 index 2bf507af..00000000 --- a/src/app/(public)/learn/sqlite/layout.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { DocLayout } from "@/components/mdx/docs"; - -const TableContent = [ - { - title: "Introduction", - sub: [ - { - title: "Introduction to this course", - href: "/learn/sqlite/introduction", - }, - ], - }, - { - title: "Indexing", - sub: [ - { - title: "Indexing", - href: "/learn/sqlite/indexing", - }, - { - title: "Index Hinting", - href: "/learn/sqlite/indexing", - }, - { - title: "Composite Index", - href: "/learn/sqlite/indexing", - }, - ], - }, -]; - -export default function MdxLayout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/src/app/(public)/login/github/callback/route.ts b/src/app/(public)/login/github/callback/route.ts deleted file mode 100644 index a27e4210..00000000 --- a/src/app/(public)/login/github/callback/route.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { PROVIDER, github } from "@/lib/auth"; -import { cookies } from "next/headers"; -import { OAuth2RequestError } from "arctic"; -import * as AuthController from "@/controllers/auth"; -import { NextRequest } from "next/server"; - -export const GET = async (request: NextRequest) => { - const url = new URL(request.url!); - const code = url.searchParams.get("code"); - const state = url.searchParams.get("state"); - const GITHUB_API_URL = "https://api.github.com"; - - const storedState = - (await cookies()).get("github_oauth_state")?.value ?? null; - if (!code || !state || !storedState || state !== storedState) { - return new Response(null, { - status: 400, - }); - } - - try { - const token = await github(request).validateAuthorizationCode(code); - const githubUserResponse = await fetch(`${GITHUB_API_URL}/user`, { - headers: { - Authorization: `Bearer ${token.accessToken}`, - }, - }); - const githubUser: GitHubUser = await githubUserResponse.json(); - - if (githubUser.email === null) { - const resp = await fetch(`${GITHUB_API_URL}/user/emails`, { - headers: { - Authorization: `Bearer ${token.accessToken}`, - }, - }); - const githubEmails: GitHubEmail[] = await resp.json(); - githubUser.email = - githubEmails.find((email) => email.primary)?.email || null; - } - - await AuthController.save( - { - id: githubUser.id, - name: githubUser.login, - email: githubUser.email || "", - }, - PROVIDER.GITHUB - ); - - return new Response(null, { - status: 302, - headers: { - Location: "/", - }, - }); - } catch (e) { - // the specific error message depends on the provider - if (e instanceof OAuth2RequestError) { - // invalid code - return new Response(null, { - status: 400, - }); - } - return new Response(null, { - status: 500, - }); - } -}; - -interface GitHubUser { - id: string; - login: string; - email: string | null; -} - -interface GitHubEmail { - email: string; - primary: boolean; - verified: boolean; - visibility: "public" | "private"; -} diff --git a/src/app/(public)/login/github/route.ts b/src/app/(public)/login/github/route.ts deleted file mode 100644 index 302a3f35..00000000 --- a/src/app/(public)/login/github/route.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { github } from "@/lib/auth"; -import { generateState } from "arctic"; -import { cookies } from "next/headers"; -import { NextRequest } from "next/server"; - -export const GET = async (req: NextRequest) => { - const state = generateState(); - const url = await github(req).createAuthorizationURL(state, { - scopes: ["user:email"], - }); - - (await cookies()).set("github_oauth_state", state, { - path: "/", - secure: process.env.NODE_ENV === "production", - httpOnly: true, - maxAge: 60 * 10, - sameSite: "lax", - }); - - return Response.redirect(url); -}; diff --git a/src/app/(public)/login/google/callback/route.ts b/src/app/(public)/login/google/callback/route.ts deleted file mode 100644 index a4b5ada9..00000000 --- a/src/app/(public)/login/google/callback/route.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { PROVIDER, google } from "@/lib/auth"; -import { cookies } from "next/headers"; -import { OAuth2RequestError } from "arctic"; -import * as AuthController from "@/controllers/auth"; -import { NextRequest } from "next/server"; - -export const GET = async (request: NextRequest) => { - const url = new URL(request.url!); - const code = url.searchParams.get("code"); - const state = url.searchParams.get("state"); - - const cookieStore = await cookies(); - - const storedState = cookieStore.get("google_oauth_state")?.value ?? null; - const storedCodeVerifier = - cookieStore.get("google_oauth_code_verifier")?.value ?? null; - if ( - !code || - !state || - !storedState || - !storedCodeVerifier || - state !== storedState - ) { - return new Response(null, { - status: 400, - }); - } - - try { - const token = await google(request).validateAuthorizationCode( - code, - storedCodeVerifier - ); - - const resp = await fetch( - "https://openidconnect.googleapis.com/v1/userinfo", - { - headers: { - Authorization: `Bearer ${token.accessToken}`, - }, - } - ); - const googleUser: GoogleUser = await resp.json(); - - await AuthController.save( - { - id: googleUser.sub, - name: googleUser.name, - email: googleUser.email, - }, - PROVIDER.GOOGLE - ); - - return new Response(null, { - status: 302, - headers: { - Location: "/", - }, - }); - } catch (e) { - console.error(e); - // the specific error message depends on the provider - if (e instanceof OAuth2RequestError) { - // invalid code - return new Response(null, { - status: 400, - }); - } - return new Response(null, { - status: 500, - }); - } -}; - -interface GoogleUser { - sub: string; - name: string; - given_name: string; - picture: string; - email: string; - email_verified: boolean; - locale: string; -} diff --git a/src/app/(public)/login/google/route.ts b/src/app/(public)/login/google/route.ts deleted file mode 100644 index dc4465a7..00000000 --- a/src/app/(public)/login/google/route.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { google } from "@/lib/auth"; -import { generateCodeVerifier, generateState } from "arctic"; -import { cookies } from "next/headers"; -import { NextRequest } from "next/server"; - -export const GET = async (req: NextRequest) => { - const state = generateState(); - const codeVerifier = generateCodeVerifier(); - const url = await google(req).createAuthorizationURL(state, codeVerifier, { - scopes: ["profile", "email"], - }); - - const cookieStore = await cookies(); - - cookieStore.set("google_oauth_state", state, { - path: "/", - secure: process.env.NODE_ENV === "production", - httpOnly: true, - maxAge: 60 * 10, - sameSite: "lax", - }); - - cookieStore.set("google_oauth_code_verifier", codeVerifier, { - path: "/", - secure: process.env.NODE_ENV === "production", - httpOnly: true, - maxAge: 60 * 10, - sameSite: "lax", - }); - - return Response.redirect(url); -}; diff --git a/src/app/(public)/login/page.tsx b/src/app/(public)/login/page.tsx deleted file mode 100644 index e2bd2da2..00000000 --- a/src/app/(public)/login/page.tsx +++ /dev/null @@ -1,87 +0,0 @@ -"use server"; -import LogoLoading from "@/components/gui/logo-loading"; -import { WEBSITE_NAME } from "@/const"; -import { env } from "@/env"; -import Link from "next/link"; - -export default async function LoginPage() { - const GOOGLE_LOGIN_SUPPORT = env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET; - const GITHUB_LOGIN_SUPPORT = env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET; - - return ( -
-
-
- - -

- Unlock the full potential -

- -

- {WEBSITE_NAME} is free and doesn't require login. However, - logged-in users get extra features: -

- -
    -
  • - Remote storage and{" "} - - syncing of connections - {" "} - and saved queries across devices -
  • -
  • - Database connection{" "} - - sharing and collaboration - -
  • -
  • Attachment uploads
  • -
  • More features coming soon
  • -
-
-
-
-
-

Login to your account

- - {GITHUB_LOGIN_SUPPORT && ( - - - - - Continue with Github - - )} - - {GOOGLE_LOGIN_SUPPORT && ( - - Google - Continue with Google - - )} -
-
-
- ); -} diff --git a/src/app/(public)/logout/route.tsx b/src/app/(public)/logout/route.tsx deleted file mode 100644 index 4a36350e..00000000 --- a/src/app/(public)/logout/route.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { cookies } from "next/headers"; -import { getSessionFromCookie, LuciaAuth } from "@/lib/auth"; - -export async function GET() { - const { session } = await getSessionFromCookie(); - - if (!session) { - return Response.json({}); - } - - const lucia = LuciaAuth.get(); - if (!lucia) { - return Response.json({}); - } - - await lucia.invalidateSession(session.id); - - const sessionCookie = lucia.createBlankSessionCookie(); - (await cookies()).set( - sessionCookie.name, - sessionCookie.value, - sessionCookie.attributes - ); - - return new Response(null, { - status: 302, - headers: { - Location: "/login", - }, - }); -} diff --git a/src/app/(public)/page.tsx b/src/app/(public)/page.tsx deleted file mode 100644 index 97e27d71..00000000 --- a/src/app/(public)/page.tsx +++ /dev/null @@ -1,332 +0,0 @@ -import { - MySQLIcon, - PostgreIcon, - SQLiteIcon, -} from "@/components/icons/outerbase-icon"; -import { buttonVariants } from "@/components/ui/button"; -import WebsiteLayout from "@/components/website-layout"; -import { WEBSITE_GENERAL_DESCRIPTION, WEBSITE_NAME } from "@/const"; -import { cn } from "@/lib/utils"; -import type { Metadata } from "next"; -import Link from "next/link"; -import { PropsWithChildren } from "react"; - -export const metadata: Metadata = { - title: WEBSITE_NAME, - keywords: [ - "libsql", - "rqlite", - "sqlite", - "cloudflare d1", - "studio", - "browser", - "editor", - "gui", - "online", - "client", - ], - description: WEBSITE_GENERAL_DESCRIPTION, - openGraph: { - siteName: WEBSITE_NAME, - description: WEBSITE_GENERAL_DESCRIPTION, - }, -}; - -function LinkButton({ title, url }: Readonly<{ title: string; url: string }>) { - return ( - - {title} - - ); -} - -function DatabaseBlock({ - children, - center, - link, -}: PropsWithChildren<{ center?: boolean; link: string }>) { - return ( - - {children} - - ); -} - -function HeroSection() { - return ( -
-
- -
-
-

- Powerful Database Client -

-

- {WEBSITE_NAME} is a fully-featured, lightweight GUI client for - managing Turso, LibSQL, Cloudflare D1, rqlite, MySQL, and - PostgreSQL. It runs entirely in your browser, so there's no - need to download anything. -

- -
- -
-
-
-
- ); -} - -function SupportDriver() { - return ( -
-
-
- Supporting Drivers -
- -

- We support a variety of databases, with more to come in the future. -

- -
- - -
SQLite
-
- - - - PostgreSQL - Beta - - - - - MySQL - Beta - - - - -
LibSQL
-
-
-
-
- ); -} - -function FeatureList() { - return ( -
-
- Modern Design and
- Intuitive Interface -
- -

- Sleek modern design meets a thoughtfully crafted, intuitive user - interface for a seamless experience. -

- -
-
- - -

- Powerful Data Editor -

- -

- The handy data editor allows you to add, delete, and edit - information. Any changes you make in the data editor are saved on - your device and can be submitted all at once. -

-
- -
- - -

- Saved Your Query -

- -

- {WEBSITE_NAME} allows you to save your queries and organize them - into folders, with the ability to sync across multiple devices. -

-
- -
- - -

- Writing and Running SQL -

- -

- {WEBSITE_NAME} features a user-friendly query editor equipped with - auto-completion and function hint tooltips. It allows you to execute - multiple queries simultaneously and view their results efficiently. -

-
- -
- - -

- Create and Edit Table -

- -

- {WEBSITE_NAME} allows you to quickly create, modify, and remove - table columns with just a few clicks without writing any SQL. -

-
-
-
- ); -} - -function CommunitySection() { - return ( -
-

Community

- -

- Join our community for the latest updates, roadmap insights, and - discussions on the future of {WEBSITE_NAME}. -

- -
- - - - -
Github
-
- - - - - - -
Discord
-
- - - - -
Twitter
-
-
-
- ); -} - -export default async function MainPage() { - return ( - - - - - -
-
-
- and much much more... -
- -

- {WEBSITE_NAME} has many features and is regularly updated. Since it - is an{" "} - - open-source - {" "} - project, you can{" "} - - request new features - {" "} - or even extend them yourself. -

-
-
-
-
- ); -} diff --git a/src/app/(public)/playground/mysql-playground-button.tsx b/src/app/(public)/playground/mysql-playground-button.tsx deleted file mode 100644 index 08b39e41..00000000 --- a/src/app/(public)/playground/mysql-playground-button.tsx +++ /dev/null @@ -1,36 +0,0 @@ -"use client"; -import { MySQLIcon } from "@/components/icons/outerbase-icon"; -import { useRouter } from "next/navigation"; - -export default function MySQLPlaygroundButton() { - const router = useRouter(); - - return ( - - ); -} diff --git a/src/app/(public)/playground/page.tsx b/src/app/(public)/playground/page.tsx deleted file mode 100644 index ebf40259..00000000 --- a/src/app/(public)/playground/page.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { SQLiteIcon } from "@/components/icons/outerbase-icon"; -import { buttonVariants } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import WebsiteLayout from "@/components/website-layout"; -import { get_database } from "@/db"; -import { dbDataset } from "@/db/schema-dataset"; -import { Metadata } from "next"; -import Link from "next/link"; -import MySQLPlaygroundButton from "./mysql-playground-button"; - -export const metadata: Metadata = { - title: "SQLite Online Editor", - description: - "A robust SQLite editor available directly in your browser. Explore and practice SQLite with ease. Begin with a blank database or choose from a selection of sample datasets.", -}; - -export default async function PlaygroundPage() { - let templateList: (typeof dbDataset.$inferSelect)[] = []; - - try { - const db = get_database(); - templateList = await db.select().from(dbDataset); - } catch { - templateList = []; - } - - return ( - -
-

Playground

-

- A robust SQLite editor available directly in your browser. Explore and - practice SQLite with ease. Begin with a blank database or choose from - a selection of sample datasets. -

- -
- -
- -
-
SQLite
-
Playground
-
-
- -

- Launch in-memory SQLite -
- inside the browser -

- - - -
-
- - - -
-

Existing Dataset

-

Preload the database with existing dataset.

-
- {templateList.map((t) => { - return ( -
-

{t.name}

-

{t.summary}

-
- - Explore - -
-
- ); - })} -
-
-
- ); -} diff --git a/src/app/(theme)/client/[[...driver]]/page-client.tsx b/src/app/(theme)/client/[[...driver]]/page-client.tsx deleted file mode 100644 index cafaf051..00000000 --- a/src/app/(theme)/client/[[...driver]]/page-client.tsx +++ /dev/null @@ -1,42 +0,0 @@ -"use client"; -import TursoDriver from "@/drivers/turso-driver"; -import { useMemo } from "react"; -import { - SavedConnectionItemConfigConfig, - SupportedDriver, -} from "../../connect/saved-connection-storage"; -import RqliteDriver from "@/drivers/rqlite-driver"; -import ValtownDriver from "@/drivers/valtown-driver"; - -import MyStudio from "@/components/my-studio"; -import CloudflareD1Driver from "@/drivers/cloudflare-d1-driver"; -import StarbaseDriver from "@/drivers/starbase-driver"; - -export default function ClientPageBody() { - const driver = useMemo(() => { - const config: SavedConnectionItemConfigConfig & { - driver: SupportedDriver; - } = JSON.parse(sessionStorage.getItem("connection") ?? "{}"); - - if (config.driver === "rqlite") { - return new RqliteDriver(config.url, config.username, config.password); - } else if (config.driver === "valtown") { - return new ValtownDriver(config.token); - } else if (config.driver === "cloudflare-d1") { - return new CloudflareD1Driver("/proxy/d1", { - Authorization: "Bearer " + (config.token ?? ""), - "x-account-id": config.username ?? "", - "x-database-id": config.database ?? "", - }); - } else if (config.driver === "starbase") { - return new StarbaseDriver("/proxy/starbase", { - Authorization: "Bearer " + (config.token ?? ""), - "x-starbase-url": config.url ?? "", - }); - } - - return new TursoDriver(config.url, config.token as string, true); - }, []); - - return ; -} diff --git a/src/app/(theme)/client/[[...driver]]/page.tsx b/src/app/(theme)/client/[[...driver]]/page.tsx deleted file mode 100644 index 935bee1c..00000000 --- a/src/app/(theme)/client/[[...driver]]/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import ClientOnly from "@/components/client-only"; -import ClientPageBody from "./page-client"; - -export default function SessionPage() { - return ( - - - - ); -} diff --git a/src/app/(theme)/client/r/page-client.tsx b/src/app/(theme)/client/r/page-client.tsx deleted file mode 100644 index 7507278a..00000000 --- a/src/app/(theme)/client/r/page-client.tsx +++ /dev/null @@ -1,43 +0,0 @@ -"use client"; -import { SavedConnectionItem } from "@/app/(theme)/connect/saved-connection-storage"; -import CollaborationDriver from "@/drivers/collaboration-driver"; -import RemoteDriver from "@/drivers/remote-driver"; -import { useSearchParams } from "next/navigation"; -import { useMemo } from "react"; -import MyStudio from "@/components/my-studio"; -import RemoteSavedDocDriver from "@/drivers/saved-doc/remote-saved-doc"; - -export default function ClientPageBody({ - token, - config, -}: Readonly<{ - token: string; - config: SavedConnectionItem; -}>) { - const params = useSearchParams(); - - const { driver, collaborator, docDriver } = useMemo(() => { - const databaseId = params.get("p"); - if (!databaseId) return { driver: null }; - - return { - driver: new RemoteDriver("remote", databaseId, token), - collaborator: new CollaborationDriver(databaseId, token), - docDriver: new RemoteSavedDocDriver(databaseId), - }; - }, [params, token]); - - if (!driver) { - return
Something wrong
; - } - - return ( - - ); -} diff --git a/src/app/(theme)/client/r/page.tsx b/src/app/(theme)/client/r/page.tsx deleted file mode 100644 index 920a13f6..00000000 --- a/src/app/(theme)/client/r/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import type { SavedConnectionLabel } from "@/app/(theme)/connect/saved-connection-storage"; -import { get_database } from "@/db"; -import { database } from "@/db/schema"; -import { getSessionFromCookie } from "@/lib/auth"; -import { and, eq, isNotNull } from "drizzle-orm"; -import ClientPageBody from "./page-client"; -import ClientOnly from "@/components/client-only"; - -interface RemoteSessionPageProps { - searchParams: Promise<{ p: string }>; -} - -export default async function RemoteSessionPage(props: RemoteSessionPageProps) { - const searchParams = await props.searchParams; - const { session } = await getSessionFromCookie(); - - if (!session) { - return
Something wrong
; - } - - const db = get_database(); - const databaseId = searchParams?.p; - const databaseInfo = await db.query.database.findFirst({ - where: and(eq(database.id, databaseId), isNotNull(database.id)), - }); - - if (!databaseInfo) { - return
Not found
; - } - - return ( - - - - ); -} diff --git a/src/app/(theme)/client/s/[[...driver]]/page-client.tsx b/src/app/(theme)/client/s/[[...driver]]/page-client.tsx index 233a6e60..2fcb2a9e 100644 --- a/src/app/(theme)/client/s/[[...driver]]/page-client.tsx +++ b/src/app/(theme)/client/s/[[...driver]]/page-client.tsx @@ -1,49 +1,31 @@ "use client"; -import { SavedConnectionLocalStorage } from "@/app/(theme)/connect/saved-connection-storage"; -import RqliteDriver from "@/drivers/rqlite-driver"; -import TursoDriver from "@/drivers/turso-driver"; -import ValtownDriver from "@/drivers/valtown-driver"; -import { useSearchParams } from "next/navigation"; -import { useMemo } from "react"; +import { + updateLocalConnectionUsed, + useLocalConnection, +} from "@/app/(outerbase)/local/hooks"; import MyStudio from "@/components/my-studio"; +import { createLocalDriver } from "@/drivers/helpers"; import IndexdbSavedDoc from "@/drivers/saved-doc/indexdb-saved-doc"; -import CloudflareD1Driver from "@/drivers/cloudflare-d1-driver"; -import StarbaseDriver from "@/drivers/starbase-driver"; +import { useSearchParams } from "next/navigation"; +import { useEffect, useMemo } from "react"; export default function ClientPageBody() { const params = useSearchParams(); - const conn = useMemo(() => { - const connectionParams = params.get("p"); - if (!connectionParams) return null; + const baseId = params.get("p") ?? ""; + const { data: conn } = useLocalConnection(baseId); - const conn = SavedConnectionLocalStorage.get(connectionParams); - return conn; - }, [params]); + useEffect(() => { + if (!baseId) return; + updateLocalConnectionUsed(baseId).then().catch(); + }, [baseId]); const driver = useMemo(() => { if (!conn) return null; - if (conn.driver === "rqlite") { - return new RqliteDriver( - conn.config.url, - conn.config.username, - conn.config.password - ); - } else if (conn.driver === "valtown") { - return new ValtownDriver(conn.config.token); - } else if (conn.driver === "cloudflare-d1") { - return new CloudflareD1Driver("/proxy/d1", { - Authorization: "Bearer " + conn.config.token, - "x-account-id": conn.config.username ?? "", - "x-database-id": conn.config.database ?? "", - }); - } else if (conn.driver === "starbase") { - return new StarbaseDriver("/proxy/starbase", { - Authorization: "Bearer " + (conn.config.token ?? ""), - "x-starbase-url": conn.config.url ?? "", - }); - } - return new TursoDriver(conn.config.url, conn.config.token, true); + const config = conn.content; + if (!config) return null; + + return createLocalDriver(config); }, [conn]); const docDriver = useMemo(() => { @@ -60,8 +42,8 @@ export default function ClientPageBody() { ); } diff --git a/src/app/(theme)/connect/connection-list.tsx b/src/app/(theme)/connect/connection-list.tsx deleted file mode 100644 index 1563c4ad..00000000 --- a/src/app/(theme)/connect/connection-list.tsx +++ /dev/null @@ -1,268 +0,0 @@ -"use client"; -import { Button } from "@/components/ui/button"; -import { - Dispatch, - SetStateAction, - useCallback, - useEffect, - useMemo, - useState, -} from "react"; -import SaveConnection from "./saved-connection"; -import { - SavedConnectionItem, - SavedConnectionLocalStorage, - SupportedDriver, -} from "@/app/(theme)/connect/saved-connection-storage"; -import EditSavedConnection from "./saved-edit-connection"; -import RemoveSavedConnection from "./saved-remove-connection"; -import ConnectionItemCard from "./saved-connection-card"; -import { getDatabases } from "@/lib/api/fetch-databases"; -import { User } from "lucia"; -import QuickConnect from "./quick-connect"; -import { LucideChevronDown, LucideSearch } from "lucide-react"; -import DriverDropdown from "./driver-dropdown"; -import { cn } from "@/lib/utils"; - -function ConnectionListSection({ - data, - name, - search, - onRemove, - onEdit, -}: Readonly<{ - search: string; - data: SavedConnectionItem[]; - name?: string; - onRemove: Dispatch>; - onEdit: Dispatch>; -}>) { - const body = useMemo(() => { - const filteredData = data.filter((d) => - d.name.toLowerCase().includes(search.toLowerCase()) - ); - - if (filteredData.length === 0) - return ( -
- {search - ? `There is no record with '${search}'` - : "There is no base. Please add new base"} -
- ); - - return ( -
- {filteredData.map((conn) => { - return ( - { - onRemove(conn); - }} - onEdit={() => { - onEdit(conn); - }} - /> - ); - })} -
- ); - }, [name, data, search, onRemove, onEdit]); - - return ( - <> - {name && ( -

{name}

- )} - {body} - - ); -} - -export default function ConnectionList({ - user, -}: Readonly<{ user: User | null }>) { - const [search, setSearch] = useState(""); - const [quickConnect, setQuickConnect] = useState( - null - ); - const [showAddConnection, setShowAddConnection] = - useState(null); - const [removeConnection, setRemoveConnection] = - useState(); - const [editConnection, setEditConnection] = useState(); - const [localSavedConns, setLocalSavedConns] = useState( - [] - ); - - const [remoteSavedConns, setRemoteSavedConns] = useState< - SavedConnectionItem[] - >([]); - - useEffect(() => { - setLocalSavedConns(SavedConnectionLocalStorage.getList()); - if (user) getDatabases().then((r) => setRemoteSavedConns(r.databases)); - }, [setLocalSavedConns, setRemoteSavedConns, user]); - - // --------------------------------------------- - // Remove the connection handlers - // --------------------------------------------- - const onRemoveConnectionClose = useCallback(() => { - setRemoveConnection(undefined); - }, [setRemoveConnection]); - - const onRemoveConnectionComplete = useCallback( - (conn: SavedConnectionItem) => { - if (conn.storage === "local") { - setLocalSavedConns(SavedConnectionLocalStorage.getList()); - } else { - setRemoteSavedConns((prev) => prev.filter((r) => r.id !== conn.id)); - } - - onRemoveConnectionClose(); - }, - [setLocalSavedConns, onRemoveConnectionClose, setRemoteSavedConns] - ); - - // --------------------------------------------- - // Add new connection handlers - // --------------------------------------------- - const onSaveComplete = useCallback( - (savedConn: SavedConnectionItem) => { - if (savedConn.storage === "remote") { - setRemoteSavedConns((prev) => [savedConn, ...prev]); - } else { - setLocalSavedConns(SavedConnectionLocalStorage.getList()); - } - setShowAddConnection(null); - }, - [setLocalSavedConns, setRemoteSavedConns, setShowAddConnection] - ); - - // --------------------------------------------- - // Edit connection handlers - // --------------------------------------------- - const onEditComplete = useCallback( - (savedConn: SavedConnectionItem) => { - if (savedConn.storage === "remote") { - setRemoteSavedConns((prev) => - prev.map((r) => { - if (r.id === savedConn.id) return savedConn; - return r; - }) - ); - } else { - setLocalSavedConns(SavedConnectionLocalStorage.getList()); - } - - setEditConnection(undefined); - }, - [setLocalSavedConns, setEditConnection, setRemoteSavedConns] - ); - - let dialogComponent: JSX.Element | null = null; - - // --------------------------------------------- - // Display Part - // --------------------------------------------- - if (editConnection) { - dialogComponent = ( - { - setEditConnection(undefined); - }} - conn={editConnection} - storage={editConnection.storage} - onSaveComplete={onEditComplete} - /> - ); - } - - if (showAddConnection) { - dialogComponent = ( - setShowAddConnection(null)} - onSaveComplete={onSaveComplete} - /> - ); - } - - if (quickConnect) { - dialogComponent = ( - setQuickConnect(null)} - /> - ); - } - - if (removeConnection) { - dialogComponent = ( - - ); - } - - return ( -
-
-

- Bases -

- -
-
-
- -
- setSearch(e.currentTarget.value)} - type="text" - className="bg-inherit p-2 pl-2 pr-2 outline-hidden text-sm h-full grow" - placeholder="Search base name" - /> -
-
- - - - - - - - -
- - {dialogComponent} - - - - {user && ( - - )} -
- ); -} diff --git a/src/app/(theme)/connect/connection-string-input.tsx b/src/app/(theme)/connect/connection-string-input.tsx deleted file mode 100644 index 13afda5b..00000000 --- a/src/app/(theme)/connect/connection-string-input.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Textarea } from "@/components/ui/textarea"; -import { - DRIVER_DETAIL, - SavedConnectionItemConfigConfig, - SupportedDriver, -} from "./saved-connection-storage"; -import { Input } from "@/components/ui/input"; -import FileHandlerPicker from "@/components/filehandler-picker"; -import { CommonDialogProvider } from "@/components/common-dialog"; - -export default function ConnectionStringInput({ - value, - onChange, - driver, - showLockedCredential, - autoFocus, -}: Readonly<{ - value: SavedConnectionItemConfigConfig; - onChange: (value: SavedConnectionItemConfigConfig) => void; - driver: SupportedDriver; - showLockedCredential?: boolean; - autoFocus?: boolean; -}>) { - const driverDetail = DRIVER_DETAIL[driver]; - - return ( - <> - {driverDetail.fields.map((field, idx) => { - let inputDom =
; - const error = field.invalidate - ? field.invalidate(value[field.name] ?? "") - : null; - - if (field.type === "text" || field.type === "password") { - inputDom = ( - { - onChange({ ...value, [field.name]: e.currentTarget.value }); - }} - /> - ); - } else if (field.type === "textarea") { - inputDom = ( -