diff --git a/.github/workflows/generate-client.yml b/.github/workflows/generate-client.yml index 1cf417ab89..304363ce96 100644 --- a/.github/workflows/generate-client.yml +++ b/.github/workflows/generate-client.yml @@ -27,7 +27,7 @@ jobs: with: python-version: "3.10" - name: Install uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v5 with: version: "0.4.15" enable-cache: true @@ -39,6 +39,10 @@ jobs: - run: uv run bash scripts/generate-client.sh env: VIRTUAL_ENV: backend/.venv + ENVIRONMENT: production + SECRET_KEY: just-for-generating-client + POSTGRES_PASSWORD: just-for-generating-client + FIRST_SUPERUSER_PASSWORD: just-for-generating-client - name: Add changes to git run: | git config --local user.email "github-actions@github.com" diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 2762cc22a3..607c5243b0 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -30,7 +30,7 @@ jobs: with: # To allow latest-changes to commit to the main branch token: ${{ secrets.LATEST_CHANGES }} - - uses: tiangolo/latest-changes@0.3.1 + - uses: tiangolo/latest-changes@0.3.2 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: ./release-notes.md diff --git a/.github/workflows/lint-backend.yml b/.github/workflows/lint-backend.yml index c7d7f2f8e4..a6e536bffe 100644 --- a/.github/workflows/lint-backend.yml +++ b/.github/workflows/lint-backend.yml @@ -20,7 +20,7 @@ jobs: with: python-version: "3.10" - name: Install uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v5 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 8c741221f7..5b13c58689 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -59,6 +59,18 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + version: "0.4.15" + enable-cache: true + - run: uv sync + working-directory: backend + - run: npm ci + working-directory: frontend + - run: uv run bash scripts/generate-client.sh + env: + VIRTUAL_ENV: backend/.venv - run: docker compose build - run: docker compose down -v --remove-orphans - name: Run Playwright tests diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index 2244836a01..cbbb78de46 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -20,7 +20,7 @@ jobs: with: python-version: "3.10" - name: Install uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v5 with: version: "0.4.15" enable-cache: true diff --git a/backend/app/api/main.py b/backend/app/api/main.py index 09e0663fc3..eac18c8e8f 100644 --- a/backend/app/api/main.py +++ b/backend/app/api/main.py @@ -1,9 +1,14 @@ from fastapi import APIRouter -from app.api.routes import items, login, users, utils +from app.api.routes import items, login, private, users, utils +from app.core.config import settings api_router = APIRouter() -api_router.include_router(login.router, tags=["login"]) -api_router.include_router(users.router, prefix="/users", tags=["users"]) -api_router.include_router(utils.router, prefix="/utils", tags=["utils"]) -api_router.include_router(items.router, prefix="/items", tags=["items"]) +api_router.include_router(login.router) +api_router.include_router(users.router) +api_router.include_router(utils.router) +api_router.include_router(items.router) + + +if settings.ENVIRONMENT == "local": + api_router.include_router(private.router) diff --git a/backend/app/api/routes/items.py b/backend/app/api/routes/items.py index 67196c2366..177dc1e476 100644 --- a/backend/app/api/routes/items.py +++ b/backend/app/api/routes/items.py @@ -7,7 +7,7 @@ from app.api.deps import CurrentUser, SessionDep from app.models import Item, ItemCreate, ItemPublic, ItemsPublic, ItemUpdate, Message -router = APIRouter() +router = APIRouter(prefix="/items", tags=["items"]) @router.get("/", response_model=ItemsPublic) diff --git a/backend/app/api/routes/login.py b/backend/app/api/routes/login.py index fe7e94d5c1..980c66f86f 100644 --- a/backend/app/api/routes/login.py +++ b/backend/app/api/routes/login.py @@ -18,7 +18,7 @@ verify_password_reset_token, ) -router = APIRouter() +router = APIRouter(tags=["login"]) @router.post("/login/access-token") diff --git a/backend/app/api/routes/private.py b/backend/app/api/routes/private.py new file mode 100644 index 0000000000..9f33ef1900 --- /dev/null +++ b/backend/app/api/routes/private.py @@ -0,0 +1,38 @@ +from typing import Any + +from fastapi import APIRouter +from pydantic import BaseModel + +from app.api.deps import SessionDep +from app.core.security import get_password_hash +from app.models import ( + User, + UserPublic, +) + +router = APIRouter(tags=["private"], prefix="/private") + + +class PrivateUserCreate(BaseModel): + email: str + password: str + full_name: str + is_verified: bool = False + + +@router.post("/users/", response_model=UserPublic) +def create_user(user_in: PrivateUserCreate, session: SessionDep) -> Any: + """ + Create a new user. + """ + + user = User( + email=user_in.email, + full_name=user_in.full_name, + hashed_password=get_password_hash(user_in.password), + ) + + session.add(user) + session.commit() + + return user diff --git a/backend/app/api/routes/users.py b/backend/app/api/routes/users.py index c636b094ee..0e8b5a87f8 100644 --- a/backend/app/api/routes/users.py +++ b/backend/app/api/routes/users.py @@ -26,7 +26,7 @@ ) from app.utils import generate_new_account_email, send_email -router = APIRouter() +router = APIRouter(prefix="/users", tags=["users"]) @router.get( diff --git a/backend/app/api/routes/utils.py b/backend/app/api/routes/utils.py index a73b80d761..fc093419b3 100644 --- a/backend/app/api/routes/utils.py +++ b/backend/app/api/routes/utils.py @@ -5,7 +5,7 @@ from app.models import Message from app.utils import generate_test_email, send_email -router = APIRouter() +router = APIRouter(prefix="/utils", tags=["utils"]) @router.post( diff --git a/backend/app/tests/api/routes/test_private.py b/backend/app/tests/api/routes/test_private.py new file mode 100644 index 0000000000..1e1f985021 --- /dev/null +++ b/backend/app/tests/api/routes/test_private.py @@ -0,0 +1,26 @@ +from fastapi.testclient import TestClient +from sqlmodel import Session, select + +from app.core.config import settings +from app.models import User + + +def test_create_user(client: TestClient, db: Session) -> None: + r = client.post( + f"{settings.API_V1_STR}/private/users/", + json={ + "email": "pollo@listo.com", + "password": "password123", + "full_name": "Pollo Listo", + }, + ) + + assert r.status_code == 200 + + data = r.json() + + user = db.exec(select(User).where(User.id == data["id"])).first() + + assert user + assert user.email == "pollo@listo.com" + assert user.full_name == "Pollo Listo" diff --git a/frontend/README.md b/frontend/README.md index fde8267842..569af503b4 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -59,7 +59,7 @@ If you are developing an API-only app and want to remove the frontend, you can d * In the `docker-compose.yml` file, remove the whole service / section `frontend`. -* In the `docker-compose.override.yml` file, remove the whole service / section `frontend`. +* In the `docker-compose.override.yml` file, remove the whole service / section `frontend` and `playwright`. Done, you have a frontend-less (api-only) app. 🤓 diff --git a/frontend/modify-openapi-operationids.js b/frontend/modify-openapi-operationids.js deleted file mode 100644 index b22fd17f9e..0000000000 --- a/frontend/modify-openapi-operationids.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as fs from "node:fs" - -async function modifyOpenAPIFile(filePath) { - try { - const data = await fs.promises.readFile(filePath) - const openapiContent = JSON.parse(data) - - const paths = openapiContent.paths - for (const pathKey of Object.keys(paths)) { - const pathData = paths[pathKey] - for (const method of Object.keys(pathData)) { - const operation = pathData[method] - if (operation.tags && operation.tags.length > 0) { - const tag = operation.tags[0] - const operationId = operation.operationId - const toRemove = `${tag}-` - if (operationId.startsWith(toRemove)) { - const newOperationId = operationId.substring(toRemove.length) - operation.operationId = newOperationId - } - } - } - } - - await fs.promises.writeFile( - filePath, - JSON.stringify(openapiContent, null, 2), - ) - console.log("File successfully modified") - } catch (err) { - console.error("Error:", err) - } -} - -const filePath = "./openapi.json" -modifyOpenAPIFile(filePath) diff --git a/frontend/openapi-ts.config.ts b/frontend/openapi-ts.config.ts new file mode 100644 index 0000000000..3cd5ff3c46 --- /dev/null +++ b/frontend/openapi-ts.config.ts @@ -0,0 +1,28 @@ +import { defineConfig } from "@hey-api/openapi-ts" + +export default defineConfig({ + client: "legacy/axios", + input: "./openapi.json", + output: "./src/client", + // exportSchemas: true, + plugins: [ + { + name: "@hey-api/sdk", + // NOTE: this doesn't allow tree-shaking + asClass: true, + operationId: true, + methodNameBuilder: (operation) => { + // @ts-ignore + let name: string = operation.name + // @ts-ignore + let service: string = operation.service + + if (service && name.toLowerCase().startsWith(service.toLowerCase())) { + name = name.slice(service.length) + } + + return name.charAt(0).toLowerCase() + name.slice(1) + }, + }, + ], +}) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5155a31c0a..661ce88605 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -26,7 +26,7 @@ }, "devDependencies": { "@biomejs/biome": "1.6.1", - "@hey-api/openapi-ts": "^0.34.1", + "@hey-api/openapi-ts": "^0.57.0", "@playwright/test": "^1.45.2", "@tanstack/router-devtools": "1.19.1", "@tanstack/router-vite-plugin": "1.19.0", @@ -39,6 +39,24 @@ "vite": "^5.0.13" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", + "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -2064,66 +2082,36 @@ } }, "node_modules/@hey-api/openapi-ts": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.34.1.tgz", - "integrity": "sha512-7Ak+0nvf4Nhzk04tXGg6h4eM7lnWRgfjCPmMl2MyXrhS5urxd3Bg/PhtpB84u18wnwcM4rIeCUlTwDDQ/OB3NQ==", + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.57.0.tgz", + "integrity": "sha512-TFcr7CYAFYLJVjJzCNk8bbGpLhn5K7PR3SHvBizVCZM4PdrcbTx6++W7FyKq84TGXuptN70+LvM+8bOSf3PgCw==", "dev": true, + "license": "FSL-1.1-MIT", "dependencies": { - "@apidevtools/json-schema-ref-parser": "11.5.4", - "camelcase": "8.0.0", - "commander": "12.0.0", + "@apidevtools/json-schema-ref-parser": "11.7.2", + "c12": "2.0.1", + "commander": "12.1.0", "handlebars": "4.7.8" }, "bin": { - "openapi-ts": "bin/index.js" + "openapi-ts": "bin/index.cjs" }, "engines": { "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/@hey-api/openapi-ts/node_modules/@apidevtools/json-schema-ref-parser": { - "version": "11.5.4", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.5.4.tgz", - "integrity": "sha512-o2fsypTGU0WxRxbax8zQoHiIB4dyrkwYfcm8TxZ+bx9pCzcWZbQtiMqpgBvWA/nJ2TrGjK5adCLfTH8wUeU/Wg==", - "dev": true, - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.15", - "js-yaml": "^4.1.0" - }, - "engines": { - "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, - "node_modules/@hey-api/openapi-ts/node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dev": true, - "engines": { - "node": ">=16" + "url": "https://github.com/sponsors/hey-api" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@hey-api/openapi-ts/node_modules/commander": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", - "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", - "dev": true, - "engines": { - "node": ">=18" + "peerDependencies": { + "typescript": "^5.x" } }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@playwright/test": { "version": "1.45.2", @@ -2725,7 +2713,8 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.14.202", @@ -2816,11 +2805,25 @@ "@zag-js/dom-query": "0.16.0" } }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/aria-hidden": { "version": "1.2.3", @@ -2862,6 +2865,35 @@ "npm": ">=6" } }, + "node_modules/c12": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/c12/-/c12-2.0.1.tgz", + "integrity": "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.1", + "confbox": "^0.1.7", + "defu": "^6.1.4", + "dotenv": "^16.4.5", + "giget": "^1.2.3", + "jiti": "^2.3.0", + "mlly": "^1.7.1", + "ohash": "^1.1.4", + "pathe": "^1.1.2", + "perfect-debounce": "^1.0.0", + "pkg-types": "^1.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2870,6 +2902,42 @@ "node": ">=6" } }, + "node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, "node_modules/clsx": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", @@ -2895,11 +2963,38 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/compute-scroll-into-view": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -2928,6 +3023,21 @@ "node": ">=10" } }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -2957,6 +3067,13 @@ "url": "https://opencollective.com/date-fns" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2965,6 +3082,13 @@ "node": ">=0.4.0" } }, + "node_modules/destr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz", + "integrity": "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -3038,6 +3162,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -3137,6 +3285,32 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3167,6 +3341,39 @@ "node": ">=6" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, "node_modules/goober": { "version": "2.1.14", "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", @@ -3216,6 +3423,16 @@ "react-is": "^16.7.0" } }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3255,6 +3472,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.0.tgz", + "integrity": "sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3265,6 +3512,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3298,6 +3546,13 @@ "loose-envify": "cli.js" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -3317,6 +3572,19 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -3326,6 +3594,69 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "pathe": "^1.1.2", + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -3350,6 +3681,63 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.12.tgz", + "integrity": "sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3358,6 +3746,29 @@ "node": ">=0.10.0" } }, + "node_modules/ohash": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz", + "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3386,6 +3797,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -3399,12 +3820,38 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, + "node_modules/pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, "node_modules/playwright": { "version": "1.45.2", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", @@ -3507,6 +3954,17 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -3675,6 +4133,20 @@ } } }, + "node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -3747,6 +4219,42 @@ "loose-envify": "^1.1.0" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3765,6 +4273,19 @@ "node": ">=0.10.0" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -3781,6 +4302,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -3822,6 +4361,13 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true, + "license": "MIT" + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -3945,12 +4491,35 @@ } } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "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 }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", @@ -3970,6 +4539,17 @@ } }, "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz", + "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==", + "dev": true, + "requires": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + } + }, "@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -5369,40 +5949,15 @@ "optional": true }, "@hey-api/openapi-ts": { - "version": "0.34.1", - "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.34.1.tgz", - "integrity": "sha512-7Ak+0nvf4Nhzk04tXGg6h4eM7lnWRgfjCPmMl2MyXrhS5urxd3Bg/PhtpB84u18wnwcM4rIeCUlTwDDQ/OB3NQ==", + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.57.0.tgz", + "integrity": "sha512-TFcr7CYAFYLJVjJzCNk8bbGpLhn5K7PR3SHvBizVCZM4PdrcbTx6++W7FyKq84TGXuptN70+LvM+8bOSf3PgCw==", "dev": true, "requires": { - "@apidevtools/json-schema-ref-parser": "11.5.4", - "camelcase": "8.0.0", - "commander": "12.0.0", + "@apidevtools/json-schema-ref-parser": "11.7.2", + "c12": "2.0.1", + "commander": "12.1.0", "handlebars": "4.7.8" - }, - "dependencies": { - "@apidevtools/json-schema-ref-parser": { - "version": "11.5.4", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.5.4.tgz", - "integrity": "sha512-o2fsypTGU0WxRxbax8zQoHiIB4dyrkwYfcm8TxZ+bx9pCzcWZbQtiMqpgBvWA/nJ2TrGjK5adCLfTH8wUeU/Wg==", - "dev": true, - "requires": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.15", - "js-yaml": "^4.1.0" - } - }, - "camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dev": true - }, - "commander": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz", - "integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==", - "dev": true - } } }, "@jsdevtools/ono": { @@ -5816,6 +6371,12 @@ "@zag-js/dom-query": "0.16.0" } }, + "acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5855,11 +6416,55 @@ "resolve": "^1.19.0" } }, + "c12": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/c12/-/c12-2.0.1.tgz", + "integrity": "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==", + "dev": true, + "requires": { + "chokidar": "^4.0.1", + "confbox": "^0.1.7", + "defu": "^6.1.4", + "dotenv": "^16.4.5", + "giget": "^1.2.3", + "jiti": "^2.3.0", + "mlly": "^1.7.1", + "ohash": "^1.1.4", + "pathe": "^1.1.2", + "perfect-debounce": "^1.0.0", + "pkg-types": "^1.2.0", + "rc9": "^2.1.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, + "chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "requires": { + "readdirp": "^4.0.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "requires": { + "consola": "^3.2.3" + } + }, "clsx": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", @@ -5879,11 +6484,29 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true + }, "compute-scroll-into-view": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.0.3.tgz", "integrity": "sha512-nadqwNxghAGTamwIqQSG433W6OADZx2vCo3UXHNrzTRHK/htu+7+L0zhjEoaeaQVNAi3YgqWDv8+tzf0hRfR+A==" }, + "confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true + }, + "consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true + }, "convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -5909,6 +6532,17 @@ "yaml": "^1.10.0" } }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -5931,11 +6565,23 @@ "@babel/runtime": "^7.21.0" } }, + "defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "destr": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.3.tgz", + "integrity": "sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==", + "dev": true + }, "detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -5990,6 +6636,23 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -6059,6 +6722,26 @@ } } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -6076,6 +6759,28 @@ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==" }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "requires": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + } + }, "goober": { "version": "2.1.14", "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz", @@ -6112,6 +6817,12 @@ "react-is": "^16.7.0" } }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -6142,6 +6853,24 @@ "hasown": "^2.0.0" } }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jiti": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.0.tgz", + "integrity": "sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6179,6 +6908,12 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -6192,12 +6927,63 @@ "mime-db": "1.52.0" } }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mlly": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", + "dev": true, + "requires": { + "acorn": "^8.14.0", + "pathe": "^1.1.2", + "pkg-types": "^1.2.1", + "ufo": "^1.5.4" + } + }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -6210,11 +6996,63 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, + "npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + } + } + }, + "nypm": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.12.tgz", + "integrity": "sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==", + "dev": true, + "requires": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, + "ohash": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz", + "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==", + "dev": true + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6234,6 +7072,12 @@ "lines-and-columns": "^1.1.6" } }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -6244,12 +7088,35 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, + "pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, + "pkg-types": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", + "integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==", + "dev": true, + "requires": { + "confbox": "^0.1.8", + "mlly": "^1.7.2", + "pathe": "^1.1.2" + } + }, "playwright": { "version": "1.45.2", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", @@ -6307,6 +7174,16 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dev": true, + "requires": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -6406,6 +7283,12 @@ "tslib": "^2.0.0" } }, + "readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true + }, "regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -6460,6 +7343,27 @@ "loose-envify": "^1.1.0" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -6472,6 +7376,12 @@ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, "stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -6482,6 +7392,20 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -6513,6 +7437,12 @@ "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true }, + "ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, "uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -6561,12 +7491,27 @@ "rollup": "^4.2.0" } }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1a7a547f68..546028c9a9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,10 +5,10 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc && vite build", + "build": "tsc -p tsconfig.build.json && vite build", "lint": "biome check --apply-unsafe --no-errors-on-unmatched --files-ignore-unknown=true ./", "preview": "vite preview", - "generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios --exportSchemas true" + "generate-client": "openapi-ts" }, "dependencies": { "@chakra-ui/icons": "2.1.1", @@ -29,7 +29,7 @@ }, "devDependencies": { "@biomejs/biome": "1.6.1", - "@hey-api/openapi-ts": "^0.34.1", + "@hey-api/openapi-ts": "^0.57.0", "@playwright/test": "^1.45.2", "@tanstack/router-devtools": "1.19.1", "@tanstack/router-vite-plugin": "1.19.0", diff --git a/frontend/src/client/core/ApiRequestOptions.ts b/frontend/src/client/core/ApiRequestOptions.ts index 4cc259284f..d1136f428b 100644 --- a/frontend/src/client/core/ApiRequestOptions.ts +++ b/frontend/src/client/core/ApiRequestOptions.ts @@ -1,20 +1,21 @@ -export type ApiRequestOptions = { +export type ApiRequestOptions = { + readonly body?: any + readonly cookies?: Record + readonly errors?: Record + readonly formData?: Record | any[] | Blob | File + readonly headers?: Record + readonly mediaType?: string readonly method: - | "GET" - | "PUT" - | "POST" | "DELETE" - | "OPTIONS" + | "GET" | "HEAD" + | "OPTIONS" | "PATCH" - readonly url: string + | "POST" + | "PUT" readonly path?: Record - readonly cookies?: Record - readonly headers?: Record readonly query?: Record - readonly formData?: Record - readonly body?: any - readonly mediaType?: string readonly responseHeader?: string - readonly errors?: Record + readonly responseTransformer?: (data: unknown) => Promise + readonly url: string } diff --git a/frontend/src/client/core/OpenAPI.ts b/frontend/src/client/core/OpenAPI.ts index 746df5e61d..e99068ea2e 100644 --- a/frontend/src/client/core/OpenAPI.ts +++ b/frontend/src/client/core/OpenAPI.ts @@ -1,10 +1,9 @@ import type { AxiosRequestConfig, AxiosResponse } from "axios" import type { ApiRequestOptions } from "./ApiRequestOptions" -import type { TResult } from "./types" type Headers = Record type Middleware = (value: T) => T | Promise -type Resolver = (options: ApiRequestOptions) => Promise +type Resolver = (options: ApiRequestOptions) => Promise export class Interceptors { _fns: Middleware[] @@ -13,14 +12,14 @@ export class Interceptors { this._fns = [] } - eject(fn: Middleware) { + eject(fn: Middleware): void { const index = this._fns.indexOf(fn) if (index !== -1) { this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)] } } - use(fn: Middleware) { + use(fn: Middleware): void { this._fns = [...this._fns, fn] } } @@ -31,7 +30,6 @@ export type OpenAPIConfig = { ENCODE_PATH?: ((path: string) => string) | undefined HEADERS?: Headers | Resolver | undefined PASSWORD?: string | Resolver | undefined - RESULT?: TResult TOKEN?: string | Resolver | undefined USERNAME?: string | Resolver | undefined VERSION: string @@ -48,10 +46,12 @@ export const OpenAPI: OpenAPIConfig = { ENCODE_PATH: undefined, HEADERS: undefined, PASSWORD: undefined, - RESULT: "body", TOKEN: undefined, USERNAME: undefined, VERSION: "0.1.0", WITH_CREDENTIALS: false, - interceptors: { request: new Interceptors(), response: new Interceptors() }, + interceptors: { + request: new Interceptors(), + response: new Interceptors(), + }, } diff --git a/frontend/src/client/core/request.ts b/frontend/src/client/core/request.ts index 99d38b46f1..8b42272b93 100644 --- a/frontend/src/client/core/request.ts +++ b/frontend/src/client/core/request.ts @@ -54,7 +54,9 @@ export const getQueryString = (params: Record): string => { return } - if (Array.isArray(value)) { + if (value instanceof Date) { + append(key, value.toISOString()) + } else if (Array.isArray(value)) { value.forEach((v) => encodePair(key, v)) } else if (typeof value === "object") { Object.entries(value).forEach(([k, v]) => encodePair(`${key}[${k}]`, v)) @@ -113,10 +115,10 @@ export const getFormData = ( return undefined } -type Resolver = (options: ApiRequestOptions) => Promise +type Resolver = (options: ApiRequestOptions) => Promise export const resolve = async ( - options: ApiRequestOptions, + options: ApiRequestOptions, resolver?: T | Resolver, ): Promise => { if (typeof resolver === "function") { @@ -125,14 +127,18 @@ export const resolve = async ( return resolver } -export const getHeaders = async ( +export const getHeaders = async ( config: OpenAPIConfig, - options: ApiRequestOptions, + options: ApiRequestOptions, ): Promise> => { const [token, username, password, additionalHeaders] = await Promise.all([ + // @ts-ignore resolve(options, config.TOKEN), + // @ts-ignore resolve(options, config.USERNAME), + // @ts-ignore resolve(options, config.PASSWORD), + // @ts-ignore resolve(options, config.HEADERS), ]) @@ -187,7 +193,7 @@ export const getRequestBody = (options: ApiRequestOptions): unknown => { export const sendRequest = async ( config: OpenAPIConfig, - options: ApiRequestOptions, + options: ApiRequestOptions, url: string, body: unknown, formData: FormData | undefined, @@ -325,7 +331,7 @@ export const catchErrorCodes = ( */ export const request = ( config: OpenAPIConfig, - options: ApiRequestOptions, + options: ApiRequestOptions, axiosClient: AxiosInstance = axios, ): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { @@ -357,12 +363,17 @@ export const request = ( options.responseHeader, ) + let transformedBody = responseBody + if (options.responseTransformer && isSuccess(response.status)) { + transformedBody = await options.responseTransformer(responseBody) + } + const result: ApiResult = { url, ok: isSuccess(response.status), status: response.status, statusText: response.statusText, - body: responseHeader ?? responseBody, + body: responseHeader ?? transformedBody, } catchErrorCodes(options, result) diff --git a/frontend/src/client/core/types.ts b/frontend/src/client/core/types.ts deleted file mode 100644 index 199c08d3df..0000000000 --- a/frontend/src/client/core/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { ApiResult } from "./ApiResult" - -export type TResult = "body" | "raw" - -export type TApiResponse = Exclude< - T, - "raw" -> extends never - ? ApiResult - : ApiResult["body"] - -export type TConfig = { - _result?: T -} diff --git a/frontend/src/client/index.ts b/frontend/src/client/index.ts index adf1d0cabf..2228dde8b4 100644 --- a/frontend/src/client/index.ts +++ b/frontend/src/client/index.ts @@ -1,8 +1,6 @@ +// This file is auto-generated by @hey-api/openapi-ts export { ApiError } from "./core/ApiError" export { CancelablePromise, CancelError } from "./core/CancelablePromise" -export { OpenAPI } from "./core/OpenAPI" -export type { OpenAPIConfig } from "./core/OpenAPI" - -export * from "./models" -export * from "./schemas" -export * from "./services" +export { OpenAPI, type OpenAPIConfig } from "./core/OpenAPI" +export * from "./sdk.gen" +export * from "./types.gen" diff --git a/frontend/src/client/models.ts b/frontend/src/client/models.ts deleted file mode 100644 index 2c8074ddd6..0000000000 --- a/frontend/src/client/models.ts +++ /dev/null @@ -1,99 +0,0 @@ -export type Body_login_login_access_token = { - grant_type?: string | null - username: string - password: string - scope?: string - client_id?: string | null - client_secret?: string | null -} - -export type HTTPValidationError = { - detail?: Array -} - -export type ItemCreate = { - title: string - description?: string | null -} - -export type ItemPublic = { - title: string - description?: string | null - id: string - owner_id: string -} - -export type ItemUpdate = { - title?: string | null - description?: string | null -} - -export type ItemsPublic = { - data: Array - count: number -} - -export type Message = { - message: string -} - -export type NewPassword = { - token: string - new_password: string -} - -export type Token = { - access_token: string - token_type?: string -} - -export type UpdatePassword = { - current_password: string - new_password: string -} - -export type UserCreate = { - email: string - is_active?: boolean - is_superuser?: boolean - full_name?: string | null - password: string -} - -export type UserPublic = { - email: string - is_active?: boolean - is_superuser?: boolean - full_name?: string | null - id: string -} - -export type UserRegister = { - email: string - password: string - full_name?: string | null -} - -export type UserUpdate = { - email?: string | null - is_active?: boolean - is_superuser?: boolean - full_name?: string | null - password?: string | null -} - -export type UserUpdateMe = { - full_name?: string | null - email?: string | null -} - -export type UsersPublic = { - data: Array - count: number -} - -export type ValidationError = { - loc: Array - msg: string - type: string -} diff --git a/frontend/src/client/schemas.ts b/frontend/src/client/schemas.gen.ts similarity index 58% rename from frontend/src/client/schemas.ts rename to frontend/src/client/schemas.gen.ts index 9e92efd106..ca22051056 100644 --- a/frontend/src/client/schemas.ts +++ b/frontend/src/client/schemas.gen.ts @@ -1,8 +1,9 @@ -export const $Body_login_login_access_token = { +// This file is auto-generated by @hey-api/openapi-ts + +export const Body_login_login_access_tokenSchema = { properties: { grant_type: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", pattern: "password", @@ -11,22 +12,23 @@ export const $Body_login_login_access_token = { type: "null", }, ], + title: "Grant Type", }, username: { type: "string", - isRequired: true, + title: "Username", }, password: { type: "string", - isRequired: true, + title: "Password", }, scope: { type: "string", + title: "Scope", default: "", }, client_id: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", }, @@ -34,10 +36,10 @@ export const $Body_login_login_access_token = { type: "null", }, ], + title: "Client Id", }, client_secret: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", }, @@ -45,32 +47,38 @@ export const $Body_login_login_access_token = { type: "null", }, ], + title: "Client Secret", }, }, + type: "object", + required: ["username", "password"], + title: "Body_login-login_access_token", } as const -export const $HTTPValidationError = { +export const HTTPValidationErrorSchema = { properties: { detail: { - type: "array", - contains: { - type: "ValidationError", + items: { + $ref: "#/components/schemas/ValidationError", }, + type: "array", + title: "Detail", }, }, + type: "object", + title: "HTTPValidationError", } as const -export const $ItemCreate = { +export const ItemCreateSchema = { properties: { title: { type: "string", - isRequired: true, maxLength: 255, minLength: 1, + title: "Title", }, description: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -79,21 +87,24 @@ export const $ItemCreate = { type: "null", }, ], + title: "Description", }, }, + type: "object", + required: ["title"], + title: "ItemCreate", } as const -export const $ItemPublic = { +export const ItemPublicSchema = { properties: { title: { type: "string", - isRequired: true, maxLength: 255, minLength: 1, + title: "Title", }, description: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -102,25 +113,28 @@ export const $ItemPublic = { type: "null", }, ], + title: "Description", }, id: { type: "string", - isRequired: true, format: "uuid", + title: "Id", }, owner_id: { type: "string", - isRequired: true, format: "uuid", + title: "Owner Id", }, }, + type: "object", + required: ["title", "id", "owner_id"], + title: "ItemPublic", } as const -export const $ItemUpdate = { +export const ItemUpdateSchema = { properties: { title: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -130,10 +144,10 @@ export const $ItemUpdate = { type: "null", }, ], + title: "Title", }, description: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -142,99 +156,119 @@ export const $ItemUpdate = { type: "null", }, ], + title: "Description", }, }, + type: "object", + title: "ItemUpdate", } as const -export const $ItemsPublic = { +export const ItemsPublicSchema = { properties: { data: { - type: "array", - contains: { - type: "ItemPublic", + items: { + $ref: "#/components/schemas/ItemPublic", }, - isRequired: true, + type: "array", + title: "Data", }, count: { - type: "number", - isRequired: true, + type: "integer", + title: "Count", }, }, + type: "object", + required: ["data", "count"], + title: "ItemsPublic", } as const -export const $Message = { +export const MessageSchema = { properties: { message: { type: "string", - isRequired: true, + title: "Message", }, }, + type: "object", + required: ["message"], + title: "Message", } as const -export const $NewPassword = { +export const NewPasswordSchema = { properties: { token: { type: "string", - isRequired: true, + title: "Token", }, new_password: { type: "string", - isRequired: true, maxLength: 40, minLength: 8, + title: "New Password", }, }, + type: "object", + required: ["token", "new_password"], + title: "NewPassword", } as const -export const $Token = { +export const TokenSchema = { properties: { access_token: { type: "string", - isRequired: true, + title: "Access Token", }, token_type: { type: "string", + title: "Token Type", default: "bearer", }, }, + type: "object", + required: ["access_token"], + title: "Token", } as const -export const $UpdatePassword = { +export const UpdatePasswordSchema = { properties: { current_password: { type: "string", - isRequired: true, maxLength: 40, minLength: 8, + title: "Current Password", }, new_password: { type: "string", - isRequired: true, maxLength: 40, minLength: 8, + title: "New Password", }, }, + type: "object", + required: ["current_password", "new_password"], + title: "UpdatePassword", } as const -export const $UserCreate = { +export const UserCreateSchema = { properties: { email: { type: "string", - isRequired: true, - format: "email", maxLength: 255, + format: "email", + title: "Email", }, is_active: { type: "boolean", + title: "Is Active", default: true, }, is_superuser: { type: "boolean", + title: "Is Superuser", default: false, }, full_name: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -243,35 +277,40 @@ export const $UserCreate = { type: "null", }, ], + title: "Full Name", }, password: { type: "string", - isRequired: true, maxLength: 40, minLength: 8, + title: "Password", }, }, + type: "object", + required: ["email", "password"], + title: "UserCreate", } as const -export const $UserPublic = { +export const UserPublicSchema = { properties: { email: { type: "string", - isRequired: true, - format: "email", maxLength: 255, + format: "email", + title: "Email", }, is_active: { type: "boolean", + title: "Is Active", default: true, }, is_superuser: { type: "boolean", + title: "Is Superuser", default: false, }, full_name: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -280,32 +319,35 @@ export const $UserPublic = { type: "null", }, ], + title: "Full Name", }, id: { type: "string", - isRequired: true, format: "uuid", + title: "Id", }, }, + type: "object", + required: ["email", "id"], + title: "UserPublic", } as const -export const $UserRegister = { +export const UserRegisterSchema = { properties: { email: { type: "string", - isRequired: true, - format: "email", maxLength: 255, + format: "email", + title: "Email", }, password: { type: "string", - isRequired: true, maxLength: 40, minLength: 8, + title: "Password", }, full_name: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -314,36 +356,41 @@ export const $UserRegister = { type: "null", }, ], + title: "Full Name", }, }, + type: "object", + required: ["email", "password"], + title: "UserRegister", } as const -export const $UserUpdate = { +export const UserUpdateSchema = { properties: { email: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", - format: "email", maxLength: 255, + format: "email", }, { type: "null", }, ], + title: "Email", }, is_active: { type: "boolean", + title: "Is Active", default: true, }, is_superuser: { type: "boolean", + title: "Is Superuser", default: false, }, full_name: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -352,10 +399,10 @@ export const $UserUpdate = { type: "null", }, ], + title: "Full Name", }, password: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 40, @@ -365,15 +412,17 @@ export const $UserUpdate = { type: "null", }, ], + title: "Password", }, }, + type: "object", + title: "UserUpdate", } as const -export const $UserUpdateMe = { +export const UserUpdateMeSchema = { properties: { full_name: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", maxLength: 255, @@ -382,63 +431,71 @@ export const $UserUpdateMe = { type: "null", }, ], + title: "Full Name", }, email: { - type: "any-of", - contains: [ + anyOf: [ { type: "string", - format: "email", maxLength: 255, + format: "email", }, { type: "null", }, ], + title: "Email", }, }, + type: "object", + title: "UserUpdateMe", } as const -export const $UsersPublic = { +export const UsersPublicSchema = { properties: { data: { - type: "array", - contains: { - type: "UserPublic", + items: { + $ref: "#/components/schemas/UserPublic", }, - isRequired: true, + type: "array", + title: "Data", }, count: { - type: "number", - isRequired: true, + type: "integer", + title: "Count", }, }, + type: "object", + required: ["data", "count"], + title: "UsersPublic", } as const -export const $ValidationError = { +export const ValidationErrorSchema = { properties: { loc: { - type: "array", - contains: { - type: "any-of", - contains: [ + items: { + anyOf: [ { type: "string", }, { - type: "number", + type: "integer", }, ], }, - isRequired: true, + type: "array", + title: "Location", }, msg: { type: "string", - isRequired: true, + title: "Message", }, type: { type: "string", - isRequired: true, + title: "Error Type", }, }, + type: "object", + required: ["loc", "msg", "type"], + title: "ValidationError", } as const diff --git a/frontend/src/client/services.ts b/frontend/src/client/sdk.gen.ts similarity index 54% rename from frontend/src/client/services.ts rename to frontend/src/client/sdk.gen.ts index a7d58e9c02..92ded2bde8 100644 --- a/frontend/src/client/services.ts +++ b/frontend/src/client/sdk.gen.ts @@ -1,56 +1,191 @@ +// This file is auto-generated by @hey-api/openapi-ts + import type { CancelablePromise } from "./core/CancelablePromise" import { OpenAPI } from "./core/OpenAPI" import { request as __request } from "./core/request" - import type { - Body_login_login_access_token, - Message, - NewPassword, - Token, - UserPublic, - UpdatePassword, - UserCreate, - UserRegister, - UsersPublic, - UserUpdate, - UserUpdateMe, - ItemCreate, - ItemPublic, - ItemsPublic, - ItemUpdate, -} from "./models" + ItemsReadItemsData, + ItemsReadItemsResponse, + ItemsCreateItemData, + ItemsCreateItemResponse, + ItemsReadItemData, + ItemsReadItemResponse, + ItemsUpdateItemData, + ItemsUpdateItemResponse, + ItemsDeleteItemData, + ItemsDeleteItemResponse, + LoginLoginAccessTokenData, + LoginLoginAccessTokenResponse, + LoginTestTokenResponse, + LoginRecoverPasswordData, + LoginRecoverPasswordResponse, + LoginResetPasswordData, + LoginResetPasswordResponse, + LoginRecoverPasswordHtmlContentData, + LoginRecoverPasswordHtmlContentResponse, + UsersReadUsersData, + UsersReadUsersResponse, + UsersCreateUserData, + UsersCreateUserResponse, + UsersReadUserMeResponse, + UsersDeleteUserMeResponse, + UsersUpdateUserMeData, + UsersUpdateUserMeResponse, + UsersUpdatePasswordMeData, + UsersUpdatePasswordMeResponse, + UsersRegisterUserData, + UsersRegisterUserResponse, + UsersReadUserByIdData, + UsersReadUserByIdResponse, + UsersUpdateUserData, + UsersUpdateUserResponse, + UsersDeleteUserData, + UsersDeleteUserResponse, + UtilsTestEmailData, + UtilsTestEmailResponse, + UtilsHealthCheckResponse, +} from "./types.gen" -export type TDataLoginAccessToken = { - formData: Body_login_login_access_token -} -export type TDataRecoverPassword = { - email: string -} -export type TDataResetPassword = { - requestBody: NewPassword -} -export type TDataRecoverPasswordHtmlContent = { - email: string +export class ItemsService { + /** + * Read Items + * Retrieve items. + * @param data The data for the request. + * @param data.skip + * @param data.limit + * @returns ItemsPublic Successful Response + * @throws ApiError + */ + public static readItems( + data: ItemsReadItemsData = {}, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/api/v1/items/", + query: { + skip: data.skip, + limit: data.limit, + }, + errors: { + 422: "Validation Error", + }, + }) + } + + /** + * Create Item + * Create new item. + * @param data The data for the request. + * @param data.requestBody + * @returns ItemPublic Successful Response + * @throws ApiError + */ + public static createItem( + data: ItemsCreateItemData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "POST", + url: "/api/v1/items/", + body: data.requestBody, + mediaType: "application/json", + errors: { + 422: "Validation Error", + }, + }) + } + + /** + * Read Item + * Get item by ID. + * @param data The data for the request. + * @param data.id + * @returns ItemPublic Successful Response + * @throws ApiError + */ + public static readItem( + data: ItemsReadItemData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/api/v1/items/{id}", + path: { + id: data.id, + }, + errors: { + 422: "Validation Error", + }, + }) + } + + /** + * Update Item + * Update an item. + * @param data The data for the request. + * @param data.id + * @param data.requestBody + * @returns ItemPublic Successful Response + * @throws ApiError + */ + public static updateItem( + data: ItemsUpdateItemData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "PUT", + url: "/api/v1/items/{id}", + path: { + id: data.id, + }, + body: data.requestBody, + mediaType: "application/json", + errors: { + 422: "Validation Error", + }, + }) + } + + /** + * Delete Item + * Delete an item. + * @param data The data for the request. + * @param data.id + * @returns Message Successful Response + * @throws ApiError + */ + public static deleteItem( + data: ItemsDeleteItemData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "DELETE", + url: "/api/v1/items/{id}", + path: { + id: data.id, + }, + errors: { + 422: "Validation Error", + }, + }) + } } export class LoginService { /** * Login Access Token * OAuth2 compatible token login, get an access token for future requests + * @param data The data for the request. + * @param data.formData * @returns Token Successful Response * @throws ApiError */ public static loginAccessToken( - data: TDataLoginAccessToken, - ): CancelablePromise { - const { formData } = data + data: LoginLoginAccessTokenData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/login/access-token", - formData: formData, + formData: data.formData, mediaType: "application/x-www-form-urlencoded", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -61,7 +196,7 @@ export class LoginService { * @returns UserPublic Successful Response * @throws ApiError */ - public static testToken(): CancelablePromise { + public static testToken(): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/login/test-token", @@ -71,21 +206,22 @@ export class LoginService { /** * Recover Password * Password Recovery + * @param data The data for the request. + * @param data.email * @returns Message Successful Response * @throws ApiError */ public static recoverPassword( - data: TDataRecoverPassword, - ): CancelablePromise { - const { email } = data + data: LoginRecoverPasswordData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/password-recovery/{email}", path: { - email, + email: data.email, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -93,20 +229,21 @@ export class LoginService { /** * Reset Password * Reset password + * @param data The data for the request. + * @param data.requestBody * @returns Message Successful Response * @throws ApiError */ public static resetPassword( - data: TDataResetPassword, - ): CancelablePromise { - const { requestBody } = data + data: LoginResetPasswordData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/reset-password/", - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -114,73 +251,49 @@ export class LoginService { /** * Recover Password Html Content * HTML Content for Password Recovery + * @param data The data for the request. + * @param data.email * @returns string Successful Response * @throws ApiError */ public static recoverPasswordHtmlContent( - data: TDataRecoverPasswordHtmlContent, - ): CancelablePromise { - const { email } = data + data: LoginRecoverPasswordHtmlContentData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/password-recovery-html-content/{email}", path: { - email, + email: data.email, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } } -export type TDataReadUsers = { - limit?: number - skip?: number -} -export type TDataCreateUser = { - requestBody: UserCreate -} -export type TDataUpdateUserMe = { - requestBody: UserUpdateMe -} -export type TDataUpdatePasswordMe = { - requestBody: UpdatePassword -} -export type TDataRegisterUser = { - requestBody: UserRegister -} -export type TDataReadUserById = { - userId: string -} -export type TDataUpdateUser = { - requestBody: UserUpdate - userId: string -} -export type TDataDeleteUser = { - userId: string -} - export class UsersService { /** * Read Users * Retrieve users. + * @param data The data for the request. + * @param data.skip + * @param data.limit * @returns UsersPublic Successful Response * @throws ApiError */ public static readUsers( - data: TDataReadUsers = {}, - ): CancelablePromise { - const { limit = 100, skip = 0 } = data + data: UsersReadUsersData = {}, + ): CancelablePromise { return __request(OpenAPI, { method: "GET", url: "/api/v1/users/", query: { - skip, - limit, + skip: data.skip, + limit: data.limit, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -188,20 +301,21 @@ export class UsersService { /** * Create User * Create new user. + * @param data The data for the request. + * @param data.requestBody * @returns UserPublic Successful Response * @throws ApiError */ public static createUser( - data: TDataCreateUser, - ): CancelablePromise { - const { requestBody } = data + data: UsersCreateUserData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/users/", - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -212,7 +326,7 @@ export class UsersService { * @returns UserPublic Successful Response * @throws ApiError */ - public static readUserMe(): CancelablePromise { + public static readUserMe(): CancelablePromise { return __request(OpenAPI, { method: "GET", url: "/api/v1/users/me", @@ -225,7 +339,7 @@ export class UsersService { * @returns Message Successful Response * @throws ApiError */ - public static deleteUserMe(): CancelablePromise { + public static deleteUserMe(): CancelablePromise { return __request(OpenAPI, { method: "DELETE", url: "/api/v1/users/me", @@ -235,20 +349,21 @@ export class UsersService { /** * Update User Me * Update own user. + * @param data The data for the request. + * @param data.requestBody * @returns UserPublic Successful Response * @throws ApiError */ public static updateUserMe( - data: TDataUpdateUserMe, - ): CancelablePromise { - const { requestBody } = data + data: UsersUpdateUserMeData, + ): CancelablePromise { return __request(OpenAPI, { method: "PATCH", url: "/api/v1/users/me", - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -256,20 +371,21 @@ export class UsersService { /** * Update Password Me * Update own password. + * @param data The data for the request. + * @param data.requestBody * @returns Message Successful Response * @throws ApiError */ public static updatePasswordMe( - data: TDataUpdatePasswordMe, - ): CancelablePromise { - const { requestBody } = data + data: UsersUpdatePasswordMeData, + ): CancelablePromise { return __request(OpenAPI, { method: "PATCH", url: "/api/v1/users/me/password", - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -277,20 +393,21 @@ export class UsersService { /** * Register User * Create new user without the need to be logged in. + * @param data The data for the request. + * @param data.requestBody * @returns UserPublic Successful Response * @throws ApiError */ public static registerUser( - data: TDataRegisterUser, - ): CancelablePromise { - const { requestBody } = data + data: UsersRegisterUserData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/users/signup", - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -298,21 +415,22 @@ export class UsersService { /** * Read User By Id * Get a specific user by id. + * @param data The data for the request. + * @param data.userId * @returns UserPublic Successful Response * @throws ApiError */ public static readUserById( - data: TDataReadUserById, - ): CancelablePromise { - const { userId } = data + data: UsersReadUserByIdData, + ): CancelablePromise { return __request(OpenAPI, { method: "GET", url: "/api/v1/users/{user_id}", path: { - user_id: userId, + user_id: data.userId, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -320,23 +438,25 @@ export class UsersService { /** * Update User * Update a user. + * @param data The data for the request. + * @param data.userId + * @param data.requestBody * @returns UserPublic Successful Response * @throws ApiError */ public static updateUser( - data: TDataUpdateUser, - ): CancelablePromise { - const { requestBody, userId } = data + data: UsersUpdateUserData, + ): CancelablePromise { return __request(OpenAPI, { method: "PATCH", url: "/api/v1/users/{user_id}", path: { - user_id: userId, + user_id: data.userId, }, - body: requestBody, + body: data.requestBody, mediaType: "application/json", errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -344,45 +464,47 @@ export class UsersService { /** * Delete User * Delete a user. + * @param data The data for the request. + * @param data.userId * @returns Message Successful Response * @throws ApiError */ - public static deleteUser(data: TDataDeleteUser): CancelablePromise { - const { userId } = data + public static deleteUser( + data: UsersDeleteUserData, + ): CancelablePromise { return __request(OpenAPI, { method: "DELETE", url: "/api/v1/users/{user_id}", path: { - user_id: userId, + user_id: data.userId, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } } -export type TDataTestEmail = { - emailTo: string -} - export class UtilsService { /** * Test Email * Test emails. + * @param data The data for the request. + * @param data.emailTo * @returns Message Successful Response * @throws ApiError */ - public static testEmail(data: TDataTestEmail): CancelablePromise { - const { emailTo } = data + public static testEmail( + data: UtilsTestEmailData, + ): CancelablePromise { return __request(OpenAPI, { method: "POST", url: "/api/v1/utils/test-email/", query: { - email_to: emailTo, + email_to: data.emailTo, }, errors: { - 422: `Validation Error`, + 422: "Validation Error", }, }) } @@ -392,138 +514,10 @@ export class UtilsService { * @returns boolean Successful Response * @throws ApiError */ - public static healthCheck(): CancelablePromise { + public static healthCheck(): CancelablePromise { return __request(OpenAPI, { method: "GET", url: "/api/v1/utils/health-check/", }) } } - -export type TDataReadItems = { - limit?: number - skip?: number -} -export type TDataCreateItem = { - requestBody: ItemCreate -} -export type TDataReadItem = { - id: string -} -export type TDataUpdateItem = { - id: string - requestBody: ItemUpdate -} -export type TDataDeleteItem = { - id: string -} - -export class ItemsService { - /** - * Read Items - * Retrieve items. - * @returns ItemsPublic Successful Response - * @throws ApiError - */ - public static readItems( - data: TDataReadItems = {}, - ): CancelablePromise { - const { limit = 100, skip = 0 } = data - return __request(OpenAPI, { - method: "GET", - url: "/api/v1/items/", - query: { - skip, - limit, - }, - errors: { - 422: `Validation Error`, - }, - }) - } - - /** - * Create Item - * Create new item. - * @returns ItemPublic Successful Response - * @throws ApiError - */ - public static createItem( - data: TDataCreateItem, - ): CancelablePromise { - const { requestBody } = data - return __request(OpenAPI, { - method: "POST", - url: "/api/v1/items/", - body: requestBody, - mediaType: "application/json", - errors: { - 422: `Validation Error`, - }, - }) - } - - /** - * Read Item - * Get item by ID. - * @returns ItemPublic Successful Response - * @throws ApiError - */ - public static readItem(data: TDataReadItem): CancelablePromise { - const { id } = data - return __request(OpenAPI, { - method: "GET", - url: "/api/v1/items/{id}", - path: { - id, - }, - errors: { - 422: `Validation Error`, - }, - }) - } - - /** - * Update Item - * Update an item. - * @returns ItemPublic Successful Response - * @throws ApiError - */ - public static updateItem( - data: TDataUpdateItem, - ): CancelablePromise { - const { id, requestBody } = data - return __request(OpenAPI, { - method: "PUT", - url: "/api/v1/items/{id}", - path: { - id, - }, - body: requestBody, - mediaType: "application/json", - errors: { - 422: `Validation Error`, - }, - }) - } - - /** - * Delete Item - * Delete an item. - * @returns Message Successful Response - * @throws ApiError - */ - public static deleteItem(data: TDataDeleteItem): CancelablePromise { - const { id } = data - return __request(OpenAPI, { - method: "DELETE", - url: "/api/v1/items/{id}", - path: { - id, - }, - errors: { - 422: `Validation Error`, - }, - }) - } -} diff --git a/frontend/src/client/types.gen.ts b/frontend/src/client/types.gen.ts new file mode 100644 index 0000000000..c2a58d06cb --- /dev/null +++ b/frontend/src/client/types.gen.ts @@ -0,0 +1,221 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type Body_login_login_access_token = { + grant_type?: string | null + username: string + password: string + scope?: string + client_id?: string | null + client_secret?: string | null +} + +export type HTTPValidationError = { + detail?: Array +} + +export type ItemCreate = { + title: string + description?: string | null +} + +export type ItemPublic = { + title: string + description?: string | null + id: string + owner_id: string +} + +export type ItemsPublic = { + data: Array + count: number +} + +export type ItemUpdate = { + title?: string | null + description?: string | null +} + +export type Message = { + message: string +} + +export type NewPassword = { + token: string + new_password: string +} + +export type Token = { + access_token: string + token_type?: string +} + +export type UpdatePassword = { + current_password: string + new_password: string +} + +export type UserCreate = { + email: string + is_active?: boolean + is_superuser?: boolean + full_name?: string | null + password: string +} + +export type UserPublic = { + email: string + is_active?: boolean + is_superuser?: boolean + full_name?: string | null + id: string +} + +export type UserRegister = { + email: string + password: string + full_name?: string | null +} + +export type UsersPublic = { + data: Array + count: number +} + +export type UserUpdate = { + email?: string | null + is_active?: boolean + is_superuser?: boolean + full_name?: string | null + password?: string | null +} + +export type UserUpdateMe = { + full_name?: string | null + email?: string | null +} + +export type ValidationError = { + loc: Array + msg: string + type: string +} + +export type ItemsReadItemsData = { + limit?: number + skip?: number +} + +export type ItemsReadItemsResponse = ItemsPublic + +export type ItemsCreateItemData = { + requestBody: ItemCreate +} + +export type ItemsCreateItemResponse = ItemPublic + +export type ItemsReadItemData = { + id: string +} + +export type ItemsReadItemResponse = ItemPublic + +export type ItemsUpdateItemData = { + id: string + requestBody: ItemUpdate +} + +export type ItemsUpdateItemResponse = ItemPublic + +export type ItemsDeleteItemData = { + id: string +} + +export type ItemsDeleteItemResponse = Message + +export type LoginLoginAccessTokenData = { + formData: Body_login_login_access_token +} + +export type LoginLoginAccessTokenResponse = Token + +export type LoginTestTokenResponse = UserPublic + +export type LoginRecoverPasswordData = { + email: string +} + +export type LoginRecoverPasswordResponse = Message + +export type LoginResetPasswordData = { + requestBody: NewPassword +} + +export type LoginResetPasswordResponse = Message + +export type LoginRecoverPasswordHtmlContentData = { + email: string +} + +export type LoginRecoverPasswordHtmlContentResponse = string + +export type UsersReadUsersData = { + limit?: number + skip?: number +} + +export type UsersReadUsersResponse = UsersPublic + +export type UsersCreateUserData = { + requestBody: UserCreate +} + +export type UsersCreateUserResponse = UserPublic + +export type UsersReadUserMeResponse = UserPublic + +export type UsersDeleteUserMeResponse = Message + +export type UsersUpdateUserMeData = { + requestBody: UserUpdateMe +} + +export type UsersUpdateUserMeResponse = UserPublic + +export type UsersUpdatePasswordMeData = { + requestBody: UpdatePassword +} + +export type UsersUpdatePasswordMeResponse = Message + +export type UsersRegisterUserData = { + requestBody: UserRegister +} + +export type UsersRegisterUserResponse = UserPublic + +export type UsersReadUserByIdData = { + userId: string +} + +export type UsersReadUserByIdResponse = UserPublic + +export type UsersUpdateUserData = { + requestBody: UserUpdate + userId: string +} + +export type UsersUpdateUserResponse = UserPublic + +export type UsersDeleteUserData = { + userId: string +} + +export type UsersDeleteUserResponse = Message + +export type UtilsTestEmailData = { + emailTo: string +} + +export type UtilsTestEmailResponse = Message + +export type UtilsHealthCheckResponse = boolean diff --git a/frontend/tests/user-settings.spec.ts b/frontend/tests/user-settings.spec.ts index a3a8a27490..8175d155c4 100644 --- a/frontend/tests/user-settings.spec.ts +++ b/frontend/tests/user-settings.spec.ts @@ -1,7 +1,8 @@ import { expect, test } from "@playwright/test" import { firstSuperuser, firstSuperuserPassword } from "./config.ts" import { randomEmail, randomPassword } from "./utils/random" -import { logInUser, logOutUser, signUpNewUser } from "./utils/user" +import { logInUser, logOutUser } from "./utils/user" +import { createUser } from "./utils/privateApi.ts" const tabs = ["My profile", "Password", "Appearance"] @@ -26,13 +27,11 @@ test.describe("Edit user full name and email successfully", () => { test.use({ storageState: { cookies: [], origins: [] } }) test("Edit user name with a valid name", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const updatedName = "Test User 2" const password = randomPassword() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -50,13 +49,11 @@ test.describe("Edit user full name and email successfully", () => { }) test("Edit user email with a valid email", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const updatedEmail = randomEmail() const password = randomPassword() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -77,13 +74,11 @@ test.describe("Edit user with invalid data", () => { test.use({ storageState: { cookies: [], origins: [] } }) test("Edit user email with an invalid email", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const invalidEmail = "" - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -97,13 +92,11 @@ test.describe("Edit user with invalid data", () => { }) test("Cancel edit action restores original name", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const updatedName = "Test User" - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + const user = await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -114,18 +107,18 @@ test.describe("Edit user with invalid data", () => { await page.getByLabel("Full name").fill(updatedName) await page.getByRole("button", { name: "Cancel" }).first().click() await expect( - page.getByLabel("My profile").getByText(fullName, { exact: true }), + page + .getByLabel("My profile") + .getByText(user.full_name as string, { exact: true }), ).toBeVisible() }) test("Cancel edit action restores original email", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const updatedEmail = randomEmail() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -147,13 +140,11 @@ test.describe("Change password successfully", () => { test.use({ storageState: { cookies: [], origins: [] } }) test("Update password successfully", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const NewPassword = randomPassword() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -177,13 +168,11 @@ test.describe("Change password with invalid data", () => { test.use({ storageState: { cookies: [], origins: [] } }) test("Update password with weak passwords", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const weakPassword = "weak" - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -201,14 +190,12 @@ test.describe("Change password with invalid data", () => { test("New password and confirmation password do not match", async ({ page, }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() const newPassword = randomPassword() const confirmPassword = randomPassword() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) @@ -223,12 +210,10 @@ test.describe("Change password with invalid data", () => { }) test("Current password and new password are the same", async ({ page }) => { - const fullName = "Test User" const email = randomEmail() const password = randomPassword() - // Sign up a new user - await signUpNewUser(page, fullName, email, password) + await createUser({ email, password }) // Log in the user await logInUser(page, email, password) diff --git a/frontend/tests/utils/privateApi.ts b/frontend/tests/utils/privateApi.ts new file mode 100644 index 0000000000..b6fa0afe67 --- /dev/null +++ b/frontend/tests/utils/privateApi.ts @@ -0,0 +1,22 @@ +// Note: the `PrivateService` is only available when generating the client +// for local environments +import { OpenAPI, PrivateService } from "../../src/client" + +OpenAPI.BASE = `${process.env.VITE_API_URL}` + +export const createUser = async ({ + email, + password, +}: { + email: string + password: string +}) => { + return await PrivateService.createUser({ + requestBody: { + email, + password, + is_verified: true, + full_name: "Test User", + }, + }) +} diff --git a/frontend/tsconfig.build.json b/frontend/tsconfig.build.json new file mode 100644 index 0000000000..13bd2efc21 --- /dev/null +++ b/frontend/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["tests/**/*.ts"] +} diff --git a/release-notes.md b/release-notes.md index d712192ebf..6d5edfb673 100644 --- a/release-notes.md +++ b/release-notes.md @@ -2,8 +2,15 @@ ## Latest Changes +### Features + +* ✨ Add private, local only, API for usage in E2E tests. PR [#1429](https://github.com/fastapi/full-stack-fastapi-template/pull/1429) by [@patrick91](https://github.com/patrick91). +* ✨ Migrate to latest openapi-ts. PR [#1430](https://github.com/fastapi/full-stack-fastapi-template/pull/1430) by [@patrick91](https://github.com/patrick91). + ### Refactors +* 🎨 Move `prefix` and `tags` to routers. PR [#1439](https://github.com/fastapi/full-stack-fastapi-template/pull/1439) by [@patrick91](https://github.com/patrick91). +* ♻️ Remove modify id script in favor of openapi-ts config. PR [#1434](https://github.com/fastapi/full-stack-fastapi-template/pull/1434) by [@patrick91](https://github.com/patrick91). * 👷 Improve Playwright CI speed: sharding (paralel runs), run in Docker to use cache, use env vars. PR [#1405](https://github.com/fastapi/full-stack-fastapi-template/pull/1405) by [@tiangolo](https://github.com/tiangolo). * ♻️ Add PaginationFooter component. PR [#1381](https://github.com/fastapi/full-stack-fastapi-template/pull/1381) by [@saltie2193](https://github.com/saltie2193). * ♻️ Refactored code to use encryption algorithm name from settings for consistency. PR [#1160](https://github.com/fastapi/full-stack-fastapi-template/pull/1160) by [@sameeramin](https://github.com/sameeramin). @@ -13,11 +20,15 @@ ### Docs +* 📝 Update `frontend/README.md` to also remove Playwright when removing Frontend. PR [#1452](https://github.com/fastapi/full-stack-fastapi-template/pull/1452) by [@youben11](https://github.com/youben11). * 📝 Update `deployment.md`, instructions to install GitHub Runner in non-root VMs. PR [#1412](https://github.com/fastapi/full-stack-fastapi-template/pull/1412) by [@tiangolo](https://github.com/tiangolo). * 📝 Add MailCatcher to `development.md`. PR [#1387](https://github.com/fastapi/full-stack-fastapi-template/pull/1387) by [@tobiase](https://github.com/tobiase). ### Internal +* ⬆ Bump astral-sh/setup-uv from 4 to 5. PR [#1453](https://github.com/fastapi/full-stack-fastapi-template/pull/1453) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump astral-sh/setup-uv from 3 to 4. PR [#1433](https://github.com/fastapi/full-stack-fastapi-template/pull/1433) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump tiangolo/latest-changes from 0.3.1 to 0.3.2. PR [#1418](https://github.com/fastapi/full-stack-fastapi-template/pull/1418) by [@dependabot[bot]](https://github.com/apps/dependabot). * 👷 Update issue manager workflow. PR [#1398](https://github.com/fastapi/full-stack-fastapi-template/pull/1398) by [@alejsdev](https://github.com/alejsdev). * 👷 Fix smokeshow, checkout files on CI. PR [#1395](https://github.com/fastapi/full-stack-fastapi-template/pull/1395) by [@tiangolo](https://github.com/tiangolo). * 👷 Update `labeler.yml`. PR [#1388](https://github.com/fastapi/full-stack-fastapi-template/pull/1388) by [@tiangolo](https://github.com/tiangolo). diff --git a/scripts/generate-client.sh b/scripts/generate-client.sh index f7a564fdf0..1e76864d42 100644 --- a/scripts/generate-client.sh +++ b/scripts/generate-client.sh @@ -6,7 +6,6 @@ set -x cd backend python -c "import app.main; import json; print(json.dumps(app.main.app.openapi()))" > ../openapi.json cd .. -node frontend/modify-openapi-operationids.js mv openapi.json frontend/ cd frontend npm run generate-client