diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000..e5b6d8d6 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000..d88011f6 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..5ee60542 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,85 @@ +name: Release Packages + +on: + workflow_dispatch: + inputs: + release_type: + description: 'Type of release' + required: true + default: 'patch' + type: choice + options: + - patch + - minor + - major + dry_run: + description: 'Dry run (no actual release)' + required: true + default: false + type: boolean + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + registry-url: 'https://registry.npmjs.org' + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + + - name: Install dependencies + run: pnpm install + + - name: Run format checks + run: pnpm format + + - name: Start emulator and run tests + run: | + pnpm emulator & + EMULATOR_PID=$! + sleep 10 # Give emulator time to start + pnpm turbo test + kill $EMULATOR_PID + + - name: Build packages + run: pnpm turbo build + + # New step to create changesets if they don't exist + - name: Create changeset if needed + run: | + if [ -z "$(ls .changeset/*.md 2>/dev/null)" ]; then + echo "No changesets found. Creating changeset with ${{ inputs.release_type }} bump..." + pnpm changeset add --${{ inputs.release_type }} + else + echo "Existing changesets found. Using those for versioning." + fi + + - name: Create Release Pull Request or Publish + if: ${{ !inputs.dry_run }} + id: changesets + uses: changesets/action@v1 + with: + publish: pnpm release + commit: "chore: version packages" + title: "chore: version packages" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Dry Run - Show Changes + if: ${{ inputs.dry_run }} + run: | + echo "This is a dry run. The following changes would be made:" + pnpm changeset version --dry-run \ No newline at end of file diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8e4d1e42..81bf3e07 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -19,7 +19,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@v4 with: - version: 9 + version: 10.10.0 run_install: false # We'll do this later # Setup Node.js with pnpm @@ -33,7 +33,7 @@ jobs: - name: Install dependencies (pnpm) run: pnpm install - name: Check formatting - run: pnpm format:ci + run: pnpm format - name: Start Firebase Emulator Suite uses: invertase/firebase-emulator-action@v1.0.1 with: diff --git a/.gitignore b/.gitignore index 8133c67a..aa24d3da 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,7 @@ functions/lib/**/*.js functions/lib/**/*.js.map # Firebase cache -.firebase/ \ No newline at end of file +.firebase/ +.turbo/ +.next/ +.dataconnect/ diff --git a/.vscode/launch.json b/.vscode/launch.json index d4b60469..7e2b7f00 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,27 +1,26 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "name": "vscode-jest-tests.v2", - "request": "launch", - "runtimeExecutable": "yarn", - "args": [ - "test", - "--watch-all=false", - "--test-name-pattern", - "${jest.testNamePattern}", - "--test-path-pattern", - "${jest.testFilePattern}" - ], - "cwd": "${workspaceFolder}/packages/angular", - "console": "integratedTerminal", - "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true - } - - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "name": "vscode-jest-tests.v2", + "request": "launch", + "runtimeExecutable": "yarn", + "args": [ + "test", + "--watch-all=false", + "--test-name-pattern", + "${jest.testNamePattern}", + "--test-path-pattern", + "${jest.testFilePattern}" + ], + "cwd": "${workspaceFolder}/packages/angular", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 966f0703..7dc3f23b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { "angular.enable-strict-mode-prompt": false -} \ No newline at end of file +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..f1bff9ba --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,120 @@ +# Contributing to TanStack Query Firebase + +Thank you for your interest in contributing to TanStack Query Firebase! This document provides guidelines and instructions for setting up the development environment and contributing to the project. + +## Development Setup + +### Prerequisites + +- Node.js 20 or later +- pnpm 8.15.4 or later +- Firebase CLI (for local development) + +### Initial Setup + +1. Clone the repository: +```bash +git clone https://github.com/invertase/tanstack-query-firebase.git +cd tanstack-query-firebase +``` + +2. Install dependencies: +```bash +pnpm install +``` + +3. Start the Firebase emulators (required for testing): +```bash +pnpm emulator +``` + +## Development Tools + +### Turborepo + +This project uses Turborepo for managing the monorepo. Key commands: + +- `pnpm turbo build` - Build all packages +- `pnpm turbo test` - Run tests across all packages +- `pnpm turbo dev` - Start development servers + +The Turborepo configuration ensures proper dependency management and caching for all tasks. + +### Biome + +We use Biome for code formatting and linting. Available commands: + +- `pnpm format` - Format all files +- `pnpm format:ci` - Check formatting without making changes +- `pnpm format:fix` - Fix formatting issues + +### Changesets + +We use Changesets for versioning and publishing packages. To create a new changeset: + +1. Make your changes +2. Run `pnpm changeset` +3. Follow the prompts to describe your changes +4. Commit the generated changeset file + +## Testing + +The project uses Vitest for testing. Each package has its own test suite and configuration: + +- React package: `cd packages/react && pnpm test` +- Angular package: `cd packages/angular && pnpm test` + +Tests are configured to run sequentially (no parallel execution) to prevent race conditions. The test configuration is managed in each package's `vitest.config.ts` file. + +To run all tests through Turborepo: +```bash +pnpm test +``` + +Note: Make sure the Firebase emulator is running before executing tests. + +## GitHub Workflows + +The project has two main workflows: + +1. **Tests** (`tests.yaml`): + - Runs on push to main and pull requests + - Checks formatting + - Runs tests for changed packages + - Uses Firebase emulators for testing + - Respects package-specific test configurations + +2. **Release** (`release.yml`): + - Manual trigger with release type selection + - Creates or updates changesets + - Publishes packages to npm + - Supports dry runs + +## Making Changes + +1. Create a new branch for your changes +2. Make your changes +3. Add tests if applicable +4. Run formatting: `pnpm format` +5. Run tests: `pnpm test` +6. Create a changeset if needed: `pnpm changeset` +7. Submit a pull request + +## Code Style + +- Use Biome for formatting and linting +- Follow the existing code style +- Write tests for new features +- Update documentation as needed + +## Documentation + +Documentation is managed in the `docs` directory and uses docs.page for hosting. When making changes: + +1. Update relevant documentation +2. Test documentation changes locally +3. Ensure all links are working + +## Questions? + +If you have any questions about contributing, please open an issue or reach out to the maintainers. \ No newline at end of file diff --git a/biome.json b/biome.json index 64c9952c..0b17d631 100644 --- a/biome.json +++ b/biome.json @@ -1,40 +1,65 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "vcs": { - "enabled": false, - "clientKind": "git", - "useIgnoreFile": false - }, - "files": { - "ignoreUnknown": false, - "ignore": ["dist/**"] - }, - "formatter": { - "enabled": true, - "indentStyle": "space" - }, - "organizeImports": { - "enabled": true - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true, - "style": { - "noNonNullAssertion": "off" - }, - "suspicious": { - "noExplicitAny": "off", - "noConfusingVoidType": "off" - }, - "complexity": { - "noForEach": "off" - } - } - }, - "javascript": { - "formatter": { - "quoteStyle": "double" - } - } + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "ignore": [ + "dist/**", + ".next/**", + ".turbo/**", + "dataconnect-sdk/**", + "**/node_modules/**", + "**/coverage/**", + "**/.dataconnect/**", + "**/*.gql" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "noNonNullAssertion": "off", + "useNodejsImportProtocol": "off" + }, + "suspicious": { + "noExplicitAny": "off", + "noConfusingVoidType": "off" + }, + "complexity": { + "noForEach": "off" + }, + "a11y": { + "useButtonType": "off" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double", + "semicolons": "always" + } + }, + "json": { + "parser": { + "allowComments": true + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + } + } } diff --git a/examples/react-example/src/app/layout.tsx b/examples/react-example/src/app/layout.tsx index 2cc5bc4f..6358a512 100644 --- a/examples/react-example/src/app/layout.tsx +++ b/examples/react-example/src/app/layout.tsx @@ -1,16 +1,16 @@ import Providers from "./providers"; export default function RootLayout({ - children, + children, }: { - children: React.ReactNode; + children: React.ReactNode; }) { - return ( - - - - {children} - - - ); + return ( + + + + {children} + + + ); } diff --git a/examples/react-example/src/app/providers.tsx b/examples/react-example/src/app/providers.tsx index 9e53c7b0..76857882 100644 --- a/examples/react-example/src/app/providers.tsx +++ b/examples/react-example/src/app/providers.tsx @@ -2,47 +2,46 @@ // Since QueryClientProvider relies on useContext under the hood, we have to put 'use client' on top import { - QueryClient, - QueryClientProvider, - isServer, + QueryClient, + QueryClientProvider, + isServer, } from "@tanstack/react-query"; function makeQueryClient() { - return new QueryClient({ - defaultOptions: { - queries: { - // With SSR, we usually want to set some default staleTime - // above 0 to avoid refetching immediately on the client - staleTime: 60 * 1000, - }, - }, - }); + return new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 60 * 1000, + }, + }, + }); } let browserQueryClient: QueryClient | undefined = undefined; function getQueryClient() { - if (isServer) { - // Server: always make a new query client - return makeQueryClient(); - } else { - // Browser: make a new query client if we don't already have one - // This is very important, so we don't re-make a new client if React - // suspends during the initial render. This may not be needed if we - // have a suspense boundary BELOW the creation of the query client - if (!browserQueryClient) browserQueryClient = makeQueryClient(); - return browserQueryClient; - } + if (isServer) { + // Server: always make a new query client + return makeQueryClient(); + } + // Browser: make a new query client if we don't already have one + // This is very important, so we don't re-make a new client if React + // suspends during the initial render. This may not be needed if we + // have a suspense boundary BELOW the creation of the query client + if (!browserQueryClient) browserQueryClient = makeQueryClient(); + return browserQueryClient; } export default function Providers({ children }: { children: React.ReactNode }) { - // NOTE: Avoid useState when initializing the query client if you don't - // have a suspense boundary between this and the code that may - // suspend because React will throw away the client on the initial - // render if it suspends and there is no boundary - const queryClient = getQueryClient(); + // NOTE: Avoid useState when initializing the query client if you don't + // have a suspense boundary between this and the code that may + // suspend because React will throw away the client on the initial + // render if it suspends and there is no boundary + const queryClient = getQueryClient(); - return ( - {children} - ); + return ( + {children} + ); } diff --git a/examples/react-example/src/app/rsc/data-connect/page.tsx b/examples/react-example/src/app/rsc/data-connect/page.tsx index 2c7c2462..7630e4ef 100644 --- a/examples/react-example/src/app/rsc/data-connect/page.tsx +++ b/examples/react-example/src/app/rsc/data-connect/page.tsx @@ -1,18 +1,23 @@ import { Movies } from "@/examples/data-connect"; import { listMoviesRef } from "@dataconnect/default-connector"; -import { DataConnectQueryClient } from "@tanstack-query-firebase/react/data-connect"; import { HydrationBoundary, dehydrate } from "@tanstack/react-query"; +import { QueryClient } from "@tanstack/react-query"; +import { executeQuery } from "firebase/data-connect"; import "@/firebase"; export default async function PostsPage() { - const queryClient = new DataConnectQueryClient(); + const queryClient = new QueryClient(); + const result = await executeQuery(listMoviesRef()); - await queryClient.prefetchDataConnectQuery(listMoviesRef()); + queryClient.setQueryData( + [result.ref.name, result.ref.variables], + result.data, + ); - return ( - - - - ); + return ( + + + + ); } diff --git a/examples/react-example/src/examples/data-connect.tsx b/examples/react-example/src/examples/data-connect.tsx index 41b0a3b6..3fd0cb9c 100644 --- a/examples/react-example/src/examples/data-connect.tsx +++ b/examples/react-example/src/examples/data-connect.tsx @@ -2,52 +2,53 @@ import { createMovieRef, listMoviesRef } from "@dataconnect/default-connector"; import { - useDataConnectMutation, - useDataConnectQuery, + useDataConnectMutation, + useDataConnectQuery, } from "@tanstack-query-firebase/react/data-connect"; import "@/firebase"; export function Movies() { - const movies = useDataConnectQuery(listMoviesRef()); + const movies = useDataConnectQuery(listMoviesRef()); - const addMovie = useDataConnectMutation(createMovieRef, { - invalidate: [listMoviesRef()], - }); + const addMovie = useDataConnectMutation(createMovieRef, { + invalidate: [listMoviesRef()], + }); - if (movies.isLoading) { - return
Loading...
; - } + if (movies.isLoading) { + return
Loading...
; + } - if (movies.isError) { - return
Error: {movies.error.message}
; - } + if (movies.isError) { + return
Error: {movies.error.message}
; + } - return ( -
-

Movies

- - -
- ); + return ( +
+

Movies

+ + +
+ ); } diff --git a/examples/react-example/src/firebase.ts b/examples/react-example/src/firebase.ts index df6b6c16..bb37a844 100644 --- a/examples/react-example/src/firebase.ts +++ b/examples/react-example/src/firebase.ts @@ -1,14 +1,14 @@ import { connectorConfig } from "@dataconnect/default-connector"; import { getApps, initializeApp } from "firebase/app"; import { - connectDataConnectEmulator, - getDataConnect, + connectDataConnectEmulator, + getDataConnect, } from "firebase/data-connect"; if (getApps().length === 0) { - initializeApp({ - projectId: "example", - }); - const dataConnect = getDataConnect(connectorConfig); - connectDataConnectEmulator(dataConnect, "localhost", 9399); + initializeApp({ + projectId: "example", + }); + const dataConnect = getDataConnect(connectorConfig); + connectDataConnectEmulator(dataConnect, "localhost", 9399); } diff --git a/examples/react-example/src/pages/_app.tsx b/examples/react-example/src/pages/_app.tsx index e40634eb..e0b252f0 100644 --- a/examples/react-example/src/pages/_app.tsx +++ b/examples/react-example/src/pages/_app.tsx @@ -1,24 +1,26 @@ +"use client"; + import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import type { AppProps } from "next/app"; import React from "react"; export default function MyApp({ Component, pageProps }: AppProps) { - const [queryClient] = React.useState( - () => - new QueryClient({ - defaultOptions: { - queries: { - // With SSR, we usually want to set some default staleTime - // above 0 to avoid refetching immediately on the client - staleTime: 60 * 1000, - }, - }, - }), - ); + const [queryClient] = React.useState( + () => + new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 60 * 1000, + }, + }, + }), + ); - return ( - - - - ); + return ( + + + + ); } diff --git a/examples/react-example/src/pages/client/data-connect.tsx b/examples/react-example/src/pages/client/data-connect.tsx index 2109cecb..67fe64d0 100644 --- a/examples/react-example/src/pages/client/data-connect.tsx +++ b/examples/react-example/src/pages/client/data-connect.tsx @@ -1,5 +1,7 @@ +"use client"; + import { Movies } from "@/examples/data-connect"; export default function MoviesRoute() { - return ; + return ; } diff --git a/examples/react-example/src/pages/ssr/data-connect.tsx b/examples/react-example/src/pages/ssr/data-connect.tsx index f94ed385..a7e4a3fb 100644 --- a/examples/react-example/src/pages/ssr/data-connect.tsx +++ b/examples/react-example/src/pages/ssr/data-connect.tsx @@ -6,23 +6,23 @@ import { DataConnectQueryClient } from "@tanstack-query-firebase/react/data-conn import type { InferGetStaticPropsType } from "next"; export async function getStaticProps() { - const queryClient = new DataConnectQueryClient(); + const queryClient = new DataConnectQueryClient(); - await queryClient.prefetchDataConnectQuery(listMoviesRef()); + await queryClient.prefetchDataConnectQuery(listMoviesRef()); - return { - props: { - dehydratedState: dehydrate(queryClient), - }, - }; + return { + props: { + dehydratedState: dehydrate(queryClient), + }, + }; } export default function MoviesRoute({ - dehydratedState, + dehydratedState, }: InferGetStaticPropsType) { - return ( - - - - ); + return ( + + + + ); } diff --git a/functions/src/index.js b/functions/src/index.js index 16719ef8..0755da01 100644 --- a/functions/src/index.js +++ b/functions/src/index.js @@ -9,6 +9,6 @@ module.exports.test = functions.https.onCall((data) => { module.exports.getJoke = functions.https.onCall(async (data) => { return axios("https://api.icndb.com/jokes/random").then( - (res) => res.data.value.joke + (res) => res.data.value.joke, ); }); diff --git a/package.json b/package.json index 64150ec2..65d42bf1 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,23 @@ { "name": "@tanstack-query-firebase/root", "private": true, + "packageManager": "pnpm@10.10.0", "scripts": { - "test": "vitest --dom --coverage", + "test": "turbo test:ci", "serve:coverage": "npx serve coverage", "emulator": "firebase emulators:start --project test-project", "emulator:kill": "lsof -t -i:4001 -i:8080 -i:9000 -i:9099 -i:9199 -i:8085 | xargs kill -9", - "format:ci": "pnpm biome ci ./packages/react/src ./packages/angular/src", - "format": "pnpm biome check --write ./packages/react/src ./packages/angular/src" + "format": "biome check .", + "format:fix": "biome check . --write", + "changeset": "changeset", + "version": "changeset version", + "release": "pnpm build && changeset publish", + "build": "turbo build" }, "devDependencies": { "@angular/core": "^19.1.8", "@biomejs/biome": "1.9.4", + "@changesets/cli": "^2.29.4", "@tanstack/angular-query-experimental": "5.66.4", "@tanstack/react-query": "^5.55.4", "@types/jsonwebtoken": "^9.0.7", @@ -21,6 +27,7 @@ "jsonwebtoken": "^9.0.2", "react": "^19.0.0", "tsup": "^8.2.4", + "turbo": "^2.5.3", "typescript": "^5.6.2", "vitest": "^2.0.5" }, diff --git a/packages/angular/test-setup.ts b/packages/angular/test-setup.ts index bc6df85d..79775c82 100644 --- a/packages/angular/test-setup.ts +++ b/packages/angular/test-setup.ts @@ -1,10 +1,10 @@ +import { getTestBed } from "@angular/core/testing"; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting, -} from '@angular/platform-browser-dynamic/testing' -import { getTestBed } from '@angular/core/testing' +} from "@angular/platform-browser-dynamic/testing"; getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), -) \ No newline at end of file +); diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json index 62120275..27ff6951 100644 --- a/packages/angular/tsconfig.json +++ b/packages/angular/tsconfig.json @@ -1,20 +1,20 @@ { - "compilerOptions": { - "target": "es2015", - "module": "esnext", - "moduleResolution": "node", - "declaration": true, - "jsx": "react", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "resolveJsonModule": true, - "forceConsistentCasingInFileNames": true, - "types": ["vitest/globals"], - "paths": { - "~/testing-utils": ["../react/vitest/utils.ts"], - "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] - } - }, - "include": ["src", "utils.tsx", "./package.json"] + "compilerOptions": { + "target": "es2015", + "module": "esnext", + "moduleResolution": "node", + "declaration": true, + "jsx": "react", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "forceConsistentCasingInFileNames": true, + "types": ["vitest/globals"], + "paths": { + "~/testing-utils": ["../react/vitest/utils.ts"], + "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] + } + }, + "include": ["src", "utils.tsx", "./package.json"] } diff --git a/packages/angular/tsup.config.ts b/packages/angular/tsup.config.ts index 3676c0f5..90d55d50 100644 --- a/packages/angular/tsup.config.ts +++ b/packages/angular/tsup.config.ts @@ -1,23 +1,22 @@ +import * as fs from "node:fs/promises"; import { defineConfig } from "tsup"; -import * as fs from 'node:fs/promises'; export default defineConfig({ - entry: ['src/data-connect/index.ts', 'src/index.ts'], - format: ["esm"], - dts: true, // generates .d.ts files - outDir: "./dist", - clean: true, - esbuildOptions(options) { - options.outbase = './src'; - }, - async onSuccess() { - try { - await fs.copyFile('./package.json', './dist/package.json'); - await fs.copyFile('./README.md', './dist/README.md'); - await fs.copyFile('./LICENSE', './dist/LICENSE'); - } catch (e) { - console.error(`Error copying files: ${e}`); - } - - } + entry: ["src/data-connect/index.ts", "src/index.ts"], + format: ["esm"], + dts: true, // generates .d.ts files + outDir: "./dist", + clean: true, + esbuildOptions(options) { + options.outbase = "./src"; + }, + async onSuccess() { + try { + await fs.copyFile("./package.json", "./dist/package.json"); + await fs.copyFile("./README.md", "./dist/README.md"); + await fs.copyFile("./LICENSE", "./dist/LICENSE"); + } catch (e) { + console.error(`Error copying files: ${e}`); + } + }, }); diff --git a/packages/angular/vitest.config.ts b/packages/angular/vitest.config.ts index 0a604fd0..a9631f72 100644 --- a/packages/angular/vitest.config.ts +++ b/packages/angular/vitest.config.ts @@ -1,31 +1,30 @@ -import { defineConfig } from 'vitest/config' -import * as path from 'path'; +import * as path from "path"; +import { defineConfig } from "vitest/config"; -import packageJson from './package.json' +import packageJson from "./package.json"; export default defineConfig({ resolve: { alias: { "~/testing-utils": path.resolve(__dirname, "../../vitest/utils"), -"@/dataconnect/default-connector": path.resolve( + "@/dataconnect/default-connector": path.resolve( __dirname, - "../../dataconnect-sdk/js/default-connector" + "../../dataconnect-sdk/js/default-connector", ), - } -, + }, }, test: { fakeTimers: { - toFake: ['setTimeout', 'clearTimeout', 'Date'] + toFake: ["setTimeout", "clearTimeout", "Date"], }, name: packageJson.name, - dir: './src', + dir: "./src", watch: false, - environment: 'happy-dom', - setupFiles: ['test-setup.ts'], - coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] }, + environment: "happy-dom", + setupFiles: ["test-setup.ts"], + coverage: { enabled: true, provider: "istanbul", include: ["src/**/*"] }, typecheck: { enabled: true }, globals: true, restoreMocks: true, }, -}) \ No newline at end of file +}); diff --git a/packages/react/package.json b/packages/react/package.json index cdbc12f8..2107f8ac 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,50 +1,51 @@ { - "name": "@tanstack-query-firebase/react", - "version": "1.0.7", - "description": "TanStack Query bindings for Firebase and React", - "type": "module", - "scripts": { - "test": "vitest --dom --coverage", - "build": "tsup", - "prepublishOnly": "pnpm build", - "serve:coverage": "npx serve coverage", - "emulator": "firebase emulators:start --project test-project", - "emulator:kill": "lsof -t -i:4001 -i:8080 -i:9000 -i:9099 -i:9199 -i:8085 | xargs kill -9", - "check": "tsc --noEmit", - "publish-package": "pnpm run build && cd dist && npm publish" - }, - "exports": { - ".": { - "import": "./index.js", - "types": "./index.d.ts" - }, - "./auth": { - "import": "./auth/index.js", - "types": "./auth/index.d.ts" - }, - "./firestore": { - "import": "./firestore/index.js", - "types": "./firestore/index.d.ts" - }, - "./data-connect": { - "import": "./data-connect/index.js", - "types": "./data-connect/index.d.ts" - } - }, - "author": { - "name": "Invertase", - "email": "oss@invertase.io", - "url": "https://github.com/invertase/tanstack-query-firebase" - }, - "license": "Apache-2.0", - "devDependencies": { - "@dataconnect/default-connector": "workspace:*", - "@testing-library/react": "^16.0.1", - "@types/react": "^19.0.1", - "react": "^19.0.0" - }, - "peerDependencies": { - "@tanstack/react-query": "^5", - "firebase": "^11.3.0" - } + "name": "@tanstack-query-firebase/react", + "version": "1.0.7", + "description": "TanStack Query bindings for Firebase and React", + "type": "module", + "scripts": { + "test": "vitest --dom --coverage", + "test:ci": "vitest --dom --coverage --run", + "build": "tsup", + "prepublishOnly": "pnpm build", + "serve:coverage": "npx serve coverage", + "emulator": "firebase emulators:start --project test-project", + "emulator:kill": "lsof -t -i:4001 -i:8080 -i:9000 -i:9099 -i:9199 -i:8085 | xargs kill -9", + "check": "tsc --noEmit", + "publish-package": "pnpm run build && cd dist && npm publish" + }, + "exports": { + ".": { + "import": "./index.js", + "types": "./index.d.ts" + }, + "./auth": { + "import": "./auth/index.js", + "types": "./auth/index.d.ts" + }, + "./firestore": { + "import": "./firestore/index.js", + "types": "./firestore/index.d.ts" + }, + "./data-connect": { + "import": "./data-connect/index.js", + "types": "./data-connect/index.d.ts" + } + }, + "author": { + "name": "Invertase", + "email": "oss@invertase.io", + "url": "https://github.com/invertase/tanstack-query-firebase" + }, + "license": "Apache-2.0", + "devDependencies": { + "@dataconnect/default-connector": "workspace:*", + "@testing-library/react": "^16.0.1", + "@types/react": "^19.0.1", + "react": "^19.0.0" + }, + "peerDependencies": { + "@tanstack/react-query": "^5", + "firebase": "^11.3.0" + } } diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index a4617843..2217fc6f 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -1,19 +1,19 @@ { - "compilerOptions": { - "target": "es2015", - "module": "esnext", - "moduleResolution": "node", - "declaration": true, - "jsx": "react-jsx", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "types": ["vitest/globals"], - "paths": { - "~/testing-utils": ["./vitest/utils.ts"], - "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] - } - }, - "include": ["src", "utils.tsx"] + "compilerOptions": { + "target": "es2015", + "module": "esnext", + "moduleResolution": "node", + "declaration": true, + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "types": ["vitest/globals"], + "paths": { + "~/testing-utils": ["./vitest/utils.ts"], + "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] + } + }, + "include": ["src", "utils.tsx"] } diff --git a/packages/react/tsup.config.ts b/packages/react/tsup.config.ts index bf07cf62..c0b58b9c 100644 --- a/packages/react/tsup.config.ts +++ b/packages/react/tsup.config.ts @@ -1,24 +1,24 @@ +import * as fs from "node:fs/promises"; import { defineConfig } from "tsup"; -import * as fs from 'node:fs/promises'; -const supportedPackages = ['data-connect', 'firestore', 'auth']; +const supportedPackages = ["data-connect", "firestore", "auth"]; export default defineConfig({ - entry: [`src/(${supportedPackages.join('|')})/index.ts`, 'src/index.ts'], - format: ["esm"], - dts: true, // generates .d.ts files - outDir: "dist", - external: ['react'], - esbuildOptions(options, context) { - options.outbase = './src'; - }, - // splitting: false, // Disable code splitting to generate distinct files - clean: true, - async onSuccess() { - try { - await fs.copyFile('./package.json', './dist/package.json'); - await fs.copyFile('./README.md', './dist/README.md'); - await fs.copyFile('./LICENSE', './dist/LICENSE'); - } catch (e) { - console.error(`Error copying files: ${e}`); - } - } + entry: [`src/(${supportedPackages.join("|")})/index.ts`, "src/index.ts"], + format: ["esm"], + dts: true, // generates .d.ts files + outDir: "dist", + external: ["react"], + esbuildOptions(options, context) { + options.outbase = "./src"; + }, + // splitting: false, // Disable code splitting to generate distinct files + clean: true, + async onSuccess() { + try { + await fs.copyFile("./package.json", "./dist/package.json"); + await fs.copyFile("./README.md", "./dist/README.md"); + await fs.copyFile("./LICENSE", "./dist/LICENSE"); + } catch (e) { + console.error(`Error copying files: ${e}`); + } + }, }); diff --git a/packages/react/utils.tsx b/packages/react/utils.tsx index 3ad78cf6..0be3e061 100644 --- a/packages/react/utils.tsx +++ b/packages/react/utils.tsx @@ -1,7 +1,7 @@ import { QueryClient, QueryClientProvider, - UseMutationResult, + type UseMutationResult, } from "@tanstack/react-query"; import React, { type ReactNode } from "react"; import { expect } from "vitest"; diff --git a/packages/react/vitest.config.ts b/packages/react/vitest.config.ts index 232713ca..b73b049c 100644 --- a/packages/react/vitest.config.ts +++ b/packages/react/vitest.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from "vitest/config"; import path from "path"; +import { defineConfig } from "vitest/config"; export default defineConfig({ test: { @@ -11,7 +11,7 @@ export default defineConfig({ "~/testing-utils": path.resolve(__dirname, "./vitest/utils"), "@/dataconnect/default-connector": path.resolve( __dirname, - "../../dataconnect-sdk/js/default-connector" + "../../dataconnect-sdk/js/default-connector", ), }, }, diff --git a/packages/react/vitest/utils.ts b/packages/react/vitest/utils.ts index 30c4c58f..6ad5cce5 100644 --- a/packages/react/vitest/utils.ts +++ b/packages/react/vitest/utils.ts @@ -1,16 +1,16 @@ +import { connectorConfig } from "@/dataconnect/default-connector"; import { type FirebaseApp, FirebaseError, initializeApp } from "firebase/app"; -import { getAuth, connectAuthEmulator, type Auth } from "firebase/auth"; -import { - getFirestore, - connectFirestoreEmulator, - type Firestore, -} from "firebase/firestore"; -import { expect } from "vitest"; +import { type Auth, connectAuthEmulator, getAuth } from "firebase/auth"; import { connectDataConnectEmulator, getDataConnect, } from "firebase/data-connect"; -import { connectorConfig } from "@/dataconnect/default-connector"; +import { + type Firestore, + connectFirestoreEmulator, + getFirestore, +} from "firebase/firestore"; +import { expect } from "vitest"; const firebaseTestingOptions = { projectId: "test-project", @@ -32,7 +32,7 @@ if (!firebaseApp) { connectDataConnectEmulator( getDataConnect(connectorConfig), "localhost", - 9399 + 9399, ); } @@ -41,7 +41,7 @@ async function wipeFirestore() { "http://localhost:8080/emulator/v1/projects/test-project/databases/(default)/documents", { method: "DELETE", - } + }, ); if (!response.ok) { @@ -54,7 +54,7 @@ async function wipeAuth() { "http://localhost:9099/emulator/v1/projects/test-project/accounts", { method: "DELETE", - } + }, ); if (!response.ok) { @@ -69,7 +69,7 @@ function expectFirestoreError(error: unknown, expectedCode: string) { expect(error.code).toBe(expectedCode); } else { throw new Error( - "Expected a Firestore error, but received a different type." + "Expected a Firestore error, but received a different type.", ); } } @@ -88,7 +88,7 @@ function expectFirebaseError(error: unknown, expectedCode: string) { : error, }); throw new Error( - "Expected a Firebase error, but received a different type." + "Expected a Firebase error, but received a different type.", ); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f74bb3a8..da68e80c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: '@biomejs/biome': specifier: 1.9.4 version: 1.9.4 + '@changesets/cli': + specifier: ^2.29.4 + version: 2.29.4 '@tanstack/angular-query-experimental': specifier: 5.66.4 version: 5.66.4(@angular/common@19.1.8(@angular/core@19.1.8(rxjs@7.8.1)(zone.js@0.15.0))(rxjs@7.8.1))(@angular/core@19.1.8(rxjs@7.8.1)(zone.js@0.15.0)) @@ -45,6 +48,9 @@ importers: tsup: specifier: ^8.2.4 version: 8.4.0(jiti@1.21.7)(postcss@8.5.3)(typescript@5.7.3)(yaml@2.7.0) + turbo: + specifier: ^2.5.3 + version: 2.5.3 typescript: specifier: ^5.6.2 version: 5.7.3 @@ -397,6 +403,61 @@ packages: cpu: [x64] os: [win32] + '@changesets/apply-release-plan@7.0.12': + resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} + + '@changesets/assemble-release-plan@6.0.8': + resolution: {integrity: sha512-y8+8LvZCkKJdbUlpXFuqcavpzJR80PN0OIfn8HZdwK7Sh6MgLXm4hKY5vu6/NDoKp8lAlM4ERZCqRMLxP4m+MQ==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/cli@2.29.4': + resolution: {integrity: sha512-VW30x9oiFp/un/80+5jLeWgEU6Btj8IqOgI+X/zAYu4usVOWXjPIK5jSSlt5jsCU7/6Z7AxEkarxBxGUqkAmNg==} + hasBin: true + + '@changesets/config@3.1.1': + resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.3': + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} + + '@changesets/get-release-plan@4.0.12': + resolution: {integrity: sha512-KukdEgaafnyGryUwpHG2kZ7xJquOmWWWk5mmoeQaSvZTWH1DC5D/Sw6ClgGFYtQnOMSQhgoEbDxAbpIIayKH1g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.1': + resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.5': + resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} @@ -1092,6 +1153,12 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@next/env@15.1.0': resolution: {integrity: sha512-UcCO481cROsqJuszPPXJnb7GGuLq617ve4xuAyyNG4VSSocJNtMU5Fsx+Lp6mlN8c7W58aZLc5y6D/2xNmaK+w==} @@ -1373,6 +1440,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@20.17.19': resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} @@ -1492,6 +1562,10 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1522,6 +1596,9 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1540,6 +1617,10 @@ packages: resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + array.prototype.findlast@1.2.5: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} @@ -1593,6 +1674,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -1666,6 +1751,9 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -1678,6 +1766,10 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -1794,6 +1886,10 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -1801,6 +1897,10 @@ packages: didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -1834,6 +1934,10 @@ packages: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1991,6 +2095,11 @@ packages: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -2014,6 +2123,13 @@ packages: resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} engines: {node: '>=12.0.0'} + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2057,6 +2173,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -2079,6 +2199,14 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2141,6 +2269,10 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -2188,6 +2320,14 @@ packages: http-parser-js@0.5.9: resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} + human-id@4.1.1: + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} + hasBin: true + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + idb@7.1.1: resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} @@ -2307,6 +2447,10 @@ packages: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + is-symbol@1.1.1: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} @@ -2331,6 +2475,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2375,6 +2523,10 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2408,6 +2560,9 @@ packages: jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -2447,6 +2602,10 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -2481,6 +2640,9 @@ packages: lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} @@ -2550,6 +2712,10 @@ packages: engines: {node: '>=10'} hasBin: true + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -2640,21 +2806,51 @@ packages: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2677,6 +2873,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -2699,6 +2899,10 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -2774,6 +2978,11 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -2789,6 +2998,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2810,6 +3022,10 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2901,6 +3117,9 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + scheduler@0.25.0: resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} @@ -2966,6 +3185,10 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2978,6 +3201,12 @@ packages: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} @@ -3076,6 +3305,10 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + test-exclude@7.0.1: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} @@ -3109,6 +3342,10 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3157,6 +3394,40 @@ packages: typescript: optional: true + turbo-darwin-64@2.5.3: + resolution: {integrity: sha512-YSItEVBUIvAGPUDpAB9etEmSqZI3T6BHrkBkeSErvICXn3dfqXUfeLx35LfptLDEbrzFUdwYFNmt8QXOwe9yaw==} + cpu: [x64] + os: [darwin] + + turbo-darwin-arm64@2.5.3: + resolution: {integrity: sha512-5PefrwHd42UiZX7YA9m1LPW6x9YJBDErXmsegCkVp+GjmWrADfEOxpFrGQNonH3ZMj77WZB2PVE5Aw3gA+IOhg==} + cpu: [arm64] + os: [darwin] + + turbo-linux-64@2.5.3: + resolution: {integrity: sha512-M9xigFgawn5ofTmRzvjjLj3Lqc05O8VHKuOlWNUlnHPUltFquyEeSkpQNkE/vpPdOR14AzxqHbhhxtfS4qvb1w==} + cpu: [x64] + os: [linux] + + turbo-linux-arm64@2.5.3: + resolution: {integrity: sha512-auJRbYZ8SGJVqvzTikpg1bsRAsiI9Tk0/SDkA5Xgg0GdiHDH/BOzv1ZjDE2mjmlrO/obr19Dw+39OlMhwLffrw==} + cpu: [arm64] + os: [linux] + + turbo-windows-64@2.5.3: + resolution: {integrity: sha512-arLQYohuHtIEKkmQSCU9vtrKUg+/1TTstWB9VYRSsz+khvg81eX6LYHtXJfH/dK7Ho6ck+JaEh5G+QrE1jEmCQ==} + cpu: [x64] + os: [win32] + + turbo-windows-arm64@2.5.3: + resolution: {integrity: sha512-3JPn66HAynJ0gtr6H+hjY4VHpu1RPKcEwGATvGUTmLmYSYBQieVlnGDRMMoYN066YfyPqnNGCfhYbXfH92Cm0g==} + cpu: [arm64] + os: [win32] + + turbo@2.5.3: + resolution: {integrity: sha512-iHuaNcq5GZZnr3XDZNuu2LSyCzAOPwDuo5Qt+q64DfsTP1i3T2bKfxJhni2ZQxsvAoxRbuUK5QetJki4qc5aYA==} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -3192,6 +3463,10 @@ packages: unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + update-browserslist-db@1.1.3: resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -3599,6 +3874,148 @@ snapshots: '@biomejs/cli-win32-x64@1.9.4': optional: true + '@changesets/apply-release-plan@7.0.12': + dependencies: + '@changesets/config': 3.1.1 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.1 + + '@changesets/assemble-release-plan@6.0.8': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.1 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.29.4': + dependencies: + '@changesets/apply-release-plan': 7.0.12 + '@changesets/assemble-release-plan': 6.0.8 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.1 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/get-release-plan': 4.0.12 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.5 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + ci-info: 3.9.0 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + mri: 1.2.0 + p-limit: 2.3.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.1 + spawndamnit: 3.0.1 + term-size: 2.2.1 + + '@changesets/config@3.1.1': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.3 + '@changesets/logger': 0.1.1 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.3': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.1 + + '@changesets/get-release-plan@4.0.12': + dependencies: + '@changesets/assemble-release-plan': 6.0.8 + '@changesets/config': 3.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.5 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.1': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 3.14.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.5': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.1 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.1 + prettier: 2.8.8 + '@emnapi/runtime@1.3.1': dependencies: tslib: 2.8.1 @@ -4236,6 +4653,22 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.26.9 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.26.9 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + '@next/env@15.1.0': {} '@next/eslint-plugin-next@15.1.0': @@ -4449,6 +4882,8 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@12.20.55': {} + '@types/node@20.17.19': dependencies: undici-types: 6.19.8 @@ -4620,6 +5055,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + ansi-colors@4.1.3: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -4641,6 +5078,10 @@ snapshots: arg@5.0.2: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} aria-query@5.3.0: @@ -4663,6 +5104,8 @@ snapshots: get-intrinsic: 1.3.0 is-string: 1.1.1 + array-union@2.1.0: {} + array.prototype.findlast@1.2.5: dependencies: call-bind: 1.0.8 @@ -4731,6 +5174,10 @@ snapshots: base64-js@1.5.1: {} + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + binary-extensions@2.3.0: {} bl@4.1.0: @@ -4813,6 +5260,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chardet@0.7.0: {} + check-error@2.1.1: {} chokidar@3.6.0: @@ -4831,6 +5280,8 @@ snapshots: dependencies: readdirp: 4.1.2 + ci-info@3.9.0: {} + cli-cursor@3.1.0: dependencies: restore-cursor: 3.1.0 @@ -4935,11 +5386,17 @@ snapshots: dequal@2.0.3: {} + detect-indent@6.1.0: {} + detect-libc@2.0.3: optional: true didyoumean@1.2.2: {} + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + dlv@1.1.3: {} doctrine@2.1.0: @@ -4971,6 +5428,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.1 + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + entities@4.5.0: {} es-abstract@1.23.9: @@ -5315,6 +5777,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 4.2.0 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -5333,6 +5797,14 @@ snapshots: expect-type@1.1.0: {} + extendable-error@0.1.7: {} + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + fast-deep-equal@3.1.3: {} fast-glob@3.3.1: @@ -5377,6 +5849,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -5431,6 +5908,18 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fsevents@2.3.3: optional: true @@ -5505,6 +5994,15 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -5543,6 +6041,12 @@ snapshots: http-parser-js@0.5.9: {} + human-id@4.1.1: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + idb@7.1.1: {} ieee754@1.2.1: {} @@ -5663,6 +6167,10 @@ snapshots: call-bound: 1.0.3 has-tostringtag: 1.0.2 + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + is-symbol@1.1.1: dependencies: call-bound: 1.0.3 @@ -5686,6 +6194,8 @@ snapshots: call-bound: 1.0.3 get-intrinsic: 1.3.0 + is-windows@1.0.2: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -5742,6 +6252,11 @@ snapshots: js-tokens@4.0.0: {} + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -5764,6 +6279,10 @@ snapshots: jsonc-parser@3.3.1: {} + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + jsonwebtoken@9.0.2: dependencies: jws: 3.2.2 @@ -5816,6 +6335,10 @@ snapshots: load-tsconfig@0.2.5: {} + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -5840,6 +6363,8 @@ snapshots: lodash.sortby@4.7.0: {} + lodash.startcase@4.4.0: {} + log-symbols@4.1.0: dependencies: chalk: 4.1.2 @@ -5900,6 +6425,8 @@ snapshots: mkdirp@3.0.1: {} + mri@1.2.0: {} + ms@2.1.3: {} mz@2.7.0: @@ -6009,22 +6536,46 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + os-tmpdir@1.0.2: {} + + outdent@0.5.0: {} + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 object-keys: 1.1.1 safe-push-apply: 1.0.0 + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-map@2.1.0: {} + + p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.10 + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -6042,6 +6593,8 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-type@4.0.0: {} + pathe@1.1.2: {} pathval@2.0.0: {} @@ -6054,6 +6607,8 @@ snapshots: pify@2.3.0: {} + pify@4.0.1: {} + pirates@4.0.6: {} possible-typed-array-names@1.1.0: {} @@ -6111,6 +6666,8 @@ snapshots: prelude-ls@1.2.1: {} + prettier@2.8.8: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 @@ -6140,6 +6697,8 @@ snapshots: punycode@2.3.1: {} + quansync@0.2.10: {} + queue-microtask@1.2.3: {} react-dom@19.0.0(react@19.0.0): @@ -6157,6 +6716,13 @@ snapshots: dependencies: pify: 2.3.0 + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -6279,6 +6845,8 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safer-buffer@2.1.2: {} + scheduler@0.25.0: {} semver@6.3.1: {} @@ -6379,6 +6947,8 @@ snapshots: is-arrayish: 0.3.2 optional: true + slash@3.0.0: {} + source-map-js@1.2.1: {} source-map@0.7.4: {} @@ -6387,6 +6957,13 @@ snapshots: dependencies: whatwg-url: 7.1.0 + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + sprintf-js@1.0.3: {} + stable-hash@0.0.4: {} stackback@0.0.2: {} @@ -6525,6 +7102,8 @@ snapshots: tapable@2.2.1: {} + term-size@2.2.1: {} + test-exclude@7.0.1: dependencies: '@istanbuljs/schema': 0.1.3 @@ -6554,6 +7133,10 @@ snapshots: tinyspy@3.0.2: {} + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -6611,6 +7194,33 @@ snapshots: - tsx - yaml + turbo-darwin-64@2.5.3: + optional: true + + turbo-darwin-arm64@2.5.3: + optional: true + + turbo-linux-64@2.5.3: + optional: true + + turbo-linux-arm64@2.5.3: + optional: true + + turbo-windows-64@2.5.3: + optional: true + + turbo-windows-arm64@2.5.3: + optional: true + + turbo@2.5.3: + optionalDependencies: + turbo-darwin-64: 2.5.3 + turbo-darwin-arm64: 2.5.3 + turbo-linux-64: 2.5.3 + turbo-linux-arm64: 2.5.3 + turbo-windows-64: 2.5.3 + turbo-windows-arm64: 2.5.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -6663,6 +7273,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + universalify@0.1.2: {} + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: browserslist: 4.24.4 diff --git a/turbo.json b/turbo.json new file mode 100644 index 00000000..ccaaf791 --- /dev/null +++ b/turbo.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://turbo.build/schema.json", + "globalDependencies": ["**/.env.*local"], + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**"] + }, + "test": { + "dependsOn": ["^build"], + "outputs": ["coverage/**"], + "inputs": [ + "src/**/*.tsx", + "src/**/*.ts", + "test/**/*.ts", + "test/**/*.tsx", + "vitest.config.ts" + ], + "cache": false, + "persistent": true + }, + "test:ci": { + "dependsOn": ["^build"], + "outputs": ["coverage/**"], + "inputs": [ + "src/**/*.tsx", + "src/**/*.ts", + "test/**/*.ts", + "test/**/*.tsx", + "vitest.config.ts" + ], + "cache": false + }, + "//#format": { + "cache": false + }, + "//#format:fix": { + "cache": false + }, + "dev": { + "cache": false, + "persistent": true + } + } +}