diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a36d77227..4648eb31b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,6 @@ jobs: node-version: 22 cache: "pnpm" - run: pnpm install - - run: pnpm openapi:check + - run: pnpm openapi:check --explicit - run: pnpm test - run: pnpm build diff --git a/package.json b/package.json index a914b3ce6..b4452def6 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "download-language-names": "node scripts/download-language-names.js", "change-password": "node scripts/change-password.js", "openapi:generate": "tsx scripts/generate-openapi.ts", + "openapi:contracts": "tsx scripts/generate-openapi-contracts.ts", "openapi:check": "tsx scripts/check-openapi.ts", "postbuild": "node scripts/postbuild.js", "pretest": "pnpm build-db-client", diff --git a/public/openapi.json b/public/openapi.json index 2d043c653..0c606f3a8 100644 --- a/public/openapi.json +++ b/public/openapi.json @@ -705,8 +705,8 @@ "paths": { "/api/2fa/disable": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPost2faDisable", + "description": "Create or update 2fa disable. The request and response models are derived from the validated route contract.", + "operationId": "post2faDisable", "requestBody": { "content": { "application/json": { @@ -735,33 +735,172 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + }, + { + "properties": { + "ok": { + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "403": { - "$ref": "#/components/responses/ForbiddenResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "forbidden", + "message": "Forbidden.", + "status": 403 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Forbidden." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "429": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -774,28 +913,66 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/disable/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/disable/contract.generated.ts" } }, "/api/2fa/setup/cancel": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPost2faSetupCancel", + "description": "Create or update 2fa setup cancel. The request and response models are derived from the validated route contract.", + "operationId": "post2faSetupCancel", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -808,14 +985,14 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/setup/cancel/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/setup/cancel/contract.generated.ts" } }, "/api/2fa/setup/confirm": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPost2faSetupConfirm", + "description": "Create or update 2fa setup confirm. The request and response models are derived from the validated route contract.", + "operationId": "post2faSetupConfirm", "requestBody": { "content": { "application/json": { @@ -840,30 +1017,158 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + }, + { + "properties": { + "backupCodes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "backupCodes" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "429": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -876,34 +1181,104 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/setup/confirm/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/setup/confirm/contract.generated.ts" } }, "/api/2fa/setup/initiate": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPost2faSetupInitiate", + "description": "Create or update 2fa setup initiate. The request and response models are derived from the validated route contract.", + "operationId": "post2faSetupInitiate", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "manualKey": { + "type": "string" + }, + "qrCodeDataUrl": { + "type": "string" + } + }, + "required": [ + "qrCodeDataUrl", + "manualKey" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -916,25 +1291,96 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/setup/initiate/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/setup/initiate/contract.generated.ts" } }, "/api/2fa/status": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGet2faStatus", + "description": "Get 2fa status. The request and response models are derived from the validated route contract.", + "operationId": "get2faStatus", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "globalRequired": { + "type": "boolean" + }, + "isConfigured": { + "type": "boolean" + }, + "isEnabled": { + "type": "boolean" + }, + "isRequired": { + "type": "boolean" + }, + "requiredReason": { + "type": "null" + } + }, + "required": [ + "isEnabled", + "isRequired", + "requiredReason", + "isConfigured", + "globalRequired" + ], + "type": "object" + }, + { + "properties": { + "globalRequired": { + "type": "boolean" + }, + "isConfigured": { + "type": "boolean" + }, + "isEnabled": { + "type": "boolean" + }, + "isRequired": { + "type": "boolean" + }, + "requiredReason": { + "type": "string" + } + }, + "required": [ + "isEnabled", + "isRequired", + "requiredReason", + "isConfigured", + "globalRequired" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -947,14 +1393,14 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/status/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/status/contract.generated.ts" } }, "/api/2fa/verify": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPost2faVerify", + "description": "Create or update 2fa verify. The request and response models are derived from the validated route contract.", + "operationId": "post2faVerify", "requestBody": { "content": { "application/json": { @@ -995,30 +1441,207 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + }, + { + "properties": { + "token": { + "type": "string" + }, + "user": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "isAdmin": { + "type": "boolean" + }, + "role": { + "type": "string" + }, + "teams": { + "items": { + "properties": { + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "logoUrl", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "role", + "createdAt", + "isAdmin", + "teams" + ], + "type": "object" + } + }, + "required": [ + "token", + "user" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "429": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message", + "lockedUntil" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [], @@ -1027,14 +1650,14 @@ "Two-factor authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/2fa/verify/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/2fa/verify/contract.generated.ts" } }, "/api/admin/2fa/global": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAdmin2faGlobal", + "description": "Create or update admin 2fa global. The request and response models are derived from the validated route contract.", + "operationId": "postAdmin2faGlobal", "requestBody": { "content": { "application/json": { @@ -1057,22 +1680,90 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + }, + "required": {} + }, + "required": [ + "ok", + "required" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -1085,14 +1776,14 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/2fa/global/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/2fa/global/contract.generated.ts" } }, "/api/admin/teams": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetAdminTeams", + "description": "Get admin teams. The request and response models are derived from the validated route contract.", + "operationId": "getAdminTeams", "parameters": [ { "in": "query", @@ -1154,16 +1845,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1180,14 +1975,14 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/teams/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/teams/contract.generated.ts" } }, "/api/admin/teams/{teamId}/2fa": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAdminTeamsTeamId2fa", + "description": "Create or update admin teams team id 2fa. The request and response models are derived from the validated route contract.", + "operationId": "postAdminTeamsTeamId2fa", "parameters": [ { "in": "path", @@ -1220,22 +2015,94 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + }, + "teamId": { + "type": "string" + }, + "twoFactorRequired": {} + }, + "required": [ + "ok", + "teamId", + "twoFactorRequired" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -1248,14 +2115,14 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/teams/[teamId]/2fa/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/teams/[teamId]/2fa/contract.generated.ts" } }, "/api/admin/users": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetAdminUsers", + "description": "Get admin users. The request and response models are derived from the validated route contract.", + "operationId": "getAdminUsers", "parameters": [ { "in": "query", @@ -1317,16 +2184,117 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "_count": { + "properties": { + "websites": { + "type": "number" + } + }, + "required": [ + "websites" + ], + "type": "object" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "role", + "createdAt", + "twoFactorRequired" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1343,14 +2311,14 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/users/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/users/contract.generated.ts" } }, "/api/admin/users/{userId}/2fa": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteAdminUsersUserId2fa", + "description": "Delete admin users user id 2fa. The request and response models are derived from the validated route contract.", + "operationId": "deleteAdminUsersUserId2fa", "parameters": [ { "in": "path", @@ -1365,16 +2333,74 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + }, + "reset": { + "properties": { + "backupCodes": {}, + "otpUsed": {}, + "rateLimit": {}, + "twoFactorAuth": {} + }, + "required": [ + "twoFactorAuth", + "backupCodes", + "otpUsed", + "rateLimit" + ], + "type": "object" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "ok", + "userId", + "reset" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -1387,12 +2413,12 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/users/[userId]/2fa/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/users/[userId]/2fa/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetAdminUsersUserId2fa", + "description": "Get admin users user id 2fa. The request and response models are derived from the validated route contract.", + "operationId": "getAdminUsersUserId2fa", "parameters": [ { "in": "path", @@ -1407,16 +2433,54 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "isEnabled": { + "type": "boolean" + } + }, + "required": [ + "isEnabled" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -1429,12 +2493,12 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/users/[userId]/2fa/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/users/[userId]/2fa/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAdminUsersUserId2fa", + "description": "Create or update admin users user id 2fa. The request and response models are derived from the validated route contract.", + "operationId": "postAdminUsersUserId2fa", "parameters": [ { "in": "path", @@ -1467,22 +2531,94 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + }, + "twoFactorRequired": {}, + "userId": { + "type": "string" + } + }, + "required": [ + "ok", + "userId", + "twoFactorRequired" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [ @@ -1495,14 +2631,14 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/users/[userId]/2fa/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/users/[userId]/2fa/contract.generated.ts" } }, "/api/admin/websites": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetAdminWebsites", + "description": "Get admin websites. The request and response models are derived from the validated route contract.", + "operationId": "getAdminWebsites", "parameters": [ { "in": "query", @@ -1564,16 +2700,264 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + { + "properties": { + "createUser": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + }, + "shareId": { + "type": "string" + }, + "team": { + "properties": { + "members": { + "items": { + "properties": { + "role": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "userId", + "role" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "members" + ], + "type": "object" + }, + "user": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + } + }, + "required": [ + "shareId" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1590,8 +2974,8 @@ "Administration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/admin/websites/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/admin/websites/contract.generated.ts" } }, "/api/auth/login": { @@ -1620,13 +3004,55 @@ "description": "Authenticated successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "503": { - "$ref": "#/components/responses/ServiceUnavailableResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "service-unavailable", + "message": "Service unavailable.", + "status": 503 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Service unavailable." } }, "security": [], @@ -1641,21 +3067,43 @@ }, "/api/auth/logout": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAuthLogout", + "description": "Create or update auth logout. The request and response models are derived from the validated route contract.", + "operationId": "postAuthLogout", "responses": { "200": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1668,28 +3116,68 @@ "Authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/auth/logout/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/auth/logout/contract.generated.ts" } }, "/api/auth/sso": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAuthSso", + "description": "Create or update auth sso. The request and response models are derived from the validated route contract.", + "operationId": "postAuthSso", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "token": { + "type": "string" + }, + "user": {} + }, + "required": [ + "user", + "token" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [ @@ -1702,14 +3190,14 @@ "Authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/auth/sso/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/auth/sso/contract.generated.ts" } }, "/api/auth/subscription": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetAuthSubscription", + "description": "Get auth subscription. The request and response models are derived from the validated route contract.", + "operationId": "getAuthSubscription", "parameters": [ { "in": "query", @@ -1725,16 +3213,101 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "error": { + "properties": { + "code": { + "type": "string" + }, + "message": { + "type": "string" + }, + "status": { + "type": "number" + } + }, + "required": [ + "message", + "code", + "status" + ], + "type": "object" + } + }, + "required": [ + "error" + ], + "type": "object" + }, + { + "properties": { + "hasSubscription": { + "type": "boolean" + }, + "isBusiness": { + "type": "boolean" + }, + "isNoBilling": { + "type": "boolean" + }, + "isPro": { + "type": "boolean" + }, + "unlimitedWebsites": { + "type": "boolean" + } + }, + "required": [ + "isPro", + "isBusiness", + "isNoBilling", + "hasSubscription", + "unlimitedWebsites" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1751,25 +3324,47 @@ "Authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/auth/subscription/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/auth/subscription/contract.generated.ts" } }, "/api/auth/verify": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostAuthVerify", + "description": "Create or update auth verify. The request and response models are derived from the validated route contract.", + "operationId": "postAuthVerify", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "teams": {} + }, + "required": [ + "teams" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1782,14 +3377,14 @@ "Authentication" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/auth/verify/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/auth/verify/contract.generated.ts" } }, "/api/batch": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostBatch", + "description": "Create or update batch. The request and response models are derived from the validated route contract.", + "operationId": "postBatch", "requestBody": { "content": { "application/json": { @@ -1809,16 +3404,67 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "cache": {}, + "details": { + "items": {}, + "type": "array" + }, + "errors": { + "type": "number" + }, + "processed": { + "type": "number" + }, + "size": {} + }, + "required": [ + "size", + "processed", + "errors", + "details", + "cache" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [], @@ -1827,14 +3473,14 @@ "Collection" ], "x-umami-audience": "collect", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/batch/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/batch/contract.generated.ts" } }, "/api/boards": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetBoards", + "description": "Get boards. The request and response models are derived from the validated route contract.", + "operationId": "getBoards", "parameters": [ { "in": "query", @@ -1896,16 +3542,179 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -1918,12 +3727,12 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostBoards", + "description": "Create or update boards. The request and response models are derived from the validated route contract.", + "operationId": "postBoards", "requestBody": { "content": { "application/json": { @@ -2002,16 +3811,144 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2028,14 +3965,14 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/contract.generated.ts" } }, "/api/boards/{boardId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteBoardsBoardId", + "description": "Delete boards board id. The request and response models are derived from the validated route contract.", + "operationId": "deleteBoardsBoardId", "parameters": [ { "in": "path", @@ -2051,14 +3988,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2071,12 +4030,12 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetBoardsBoardId", + "description": "Get boards board id. The request and response models are derived from the validated route contract.", + "operationId": "getBoardsBoardId", "parameters": [ { "in": "path", @@ -2091,13 +4050,127 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2114,12 +4187,12 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostBoardsBoardId", + "description": "Create or update boards board id. The request and response models are derived from the validated route contract.", + "operationId": "postBoardsBoardId", "parameters": [ { "in": "path", @@ -2169,19 +4242,161 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [ @@ -2198,14 +4413,14 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/contract.generated.ts" } }, "/api/boards/{boardId}/clone": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostBoardsBoardIdClone", + "description": "Create or update boards board id clone. The request and response models are derived from the validated route contract.", + "operationId": "postBoardsBoardIdClone", "parameters": [ { "in": "path", @@ -2244,16 +4459,144 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2270,14 +4613,14 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/clone/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/clone/contract.generated.ts" } }, "/api/boards/{boardId}/shares": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetBoardsBoardIdShares", + "description": "Get boards board id shares. The request and response models are derived from the validated route contract.", + "operationId": "getBoardsBoardIdShares", "parameters": [ { "in": "path", @@ -2526,16 +4869,175 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2552,12 +5054,12 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/shares/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostBoardsBoardIdShares", + "description": "Create or update boards board id shares. The request and response models are derived from the validated route contract.", + "operationId": "postBoardsBoardIdShares", "parameters": [ { "in": "path", @@ -2595,16 +5097,140 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2617,22 +5243,64 @@ "Boards" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/boards/[boardId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/boards/[boardId]/shares/contract.generated.ts" } }, "/api/config": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetConfig", + "description": "Get config. The request and response models are derived from the validated route contract.", + "operationId": "getConfig", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "cloudMode": { + "type": "boolean" + }, + "faviconUrl": { + "type": "string" + }, + "linksUrl": { + "type": "string" + }, + "pixelsUrl": { + "type": "string" + }, + "privateMode": { + "type": "boolean" + }, + "sessionDeletionEnabled": { + "type": "boolean" + }, + "telemetryDisabled": { + "type": "boolean" + }, + "trackerScriptName": { + "type": "string" + }, + "updatesDisabled": { + "type": "boolean" + } + }, + "required": [ + "cloudMode", + "faviconUrl", + "linksUrl", + "pixelsUrl", + "privateMode", + "sessionDeletionEnabled", + "telemetryDisabled", + "trackerScriptName", + "updatesDisabled" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." } }, "security": [], @@ -2641,25 +5309,139 @@ "Configuration" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/config/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/config/contract.generated.ts" } }, "/api/dashboard": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetDashboard", + "description": "Get dashboard. The request and response models are derived from the validated route contract.", + "operationId": "getDashboard", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2672,12 +5454,12 @@ "Dashboard" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/dashboard/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/dashboard/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostDashboard", + "description": "Create or update dashboard. The request and response models are derived from the validated route contract.", + "operationId": "postDashboard", "requestBody": { "content": { "application/json": { @@ -2706,16 +5488,144 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2728,22 +5638,32 @@ "Dashboard" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/dashboard/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/dashboard/contract.generated.ts" } }, "/api/heartbeat": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetHeartbeat", + "description": "Get heartbeat. The request and response models are derived from the validated route contract.", + "operationId": "getHeartbeat", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." } }, "security": [], @@ -2752,14 +5672,14 @@ "System" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/heartbeat/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/heartbeat/contract.generated.ts" } }, "/api/links": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetLinks", + "description": "Get links. The request and response models are derived from the validated route contract.", + "operationId": "getLinks", "parameters": [ { "in": "query", @@ -2821,16 +5741,124 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2843,12 +5871,12 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostLinks", + "description": "Create or update links. The request and response models are derived from the validated route contract.", + "operationId": "postLinks", "requestBody": { "content": { "application/json": { @@ -2904,16 +5932,89 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2926,14 +6027,14 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/contract.generated.ts" } }, "/api/links/{linkId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteLinksLinkId", + "description": "Delete links link id. The request and response models are derived from the validated route contract.", + "operationId": "deleteLinksLinkId", "parameters": [ { "in": "path", @@ -2949,14 +6050,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -2969,12 +6092,12 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/[linkId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/[linkId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetLinksLinkId", + "description": "Get links link id. The request and response models are derived from the validated route contract.", + "operationId": "getLinksLinkId", "parameters": [ { "in": "path", @@ -2989,13 +6112,72 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3012,12 +6194,12 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/[linkId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/[linkId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostLinksLinkId", + "description": "Create or update links link id. The request and response models are derived from the validated route contract.", + "operationId": "postLinksLinkId", "parameters": [ { "in": "path", @@ -3057,19 +6239,106 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [ @@ -3082,14 +6351,14 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/[linkId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/[linkId]/contract.generated.ts" } }, "/api/links/{linkId}/shares": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetLinksLinkIdShares", + "description": "Get links link id shares. The request and response models are derived from the validated route contract.", + "operationId": "getLinksLinkIdShares", "parameters": [ { "in": "path", @@ -3338,16 +6607,175 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3364,12 +6792,12 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/[linkId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/[linkId]/shares/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostLinksLinkIdShares", + "description": "Create or update links link id shares. The request and response models are derived from the validated route contract.", + "operationId": "postLinksLinkIdShares", "parameters": [ { "in": "path", @@ -3407,16 +6835,140 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3429,14 +6981,14 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/[linkId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/[linkId]/shares/contract.generated.ts" } }, "/api/links/charts": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetLinksCharts", + "description": "Get links charts. The request and response models are derived from the validated route contract.", + "operationId": "getLinksCharts", "parameters": [ { "in": "query", @@ -3475,16 +7027,73 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "data": { + "additionalProperties": { + "properties": { + "total": { + "type": "number" + }, + "values": { + "items": { + "type": "number" + }, + "type": "array" + } + }, + "required": [ + "values", + "total" + ], + "type": "object" + }, + "properties": {}, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3501,25 +7110,138 @@ "Links" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/links/charts/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/links/charts/contract.generated.ts" } }, "/api/me": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetMe", + "description": "Get me. The request and response models are derived from the validated route contract.", + "operationId": "getMe", "responses": { "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "shareToken": { + "properties": { + "boardId": { + "type": "string" + }, + "linkId": { + "type": "string" + }, + "linkIds": { + "items": { + "type": "string" + }, + "type": "array" + }, + "parameters": { + "additionalProperties": { + "anyOf": [ + { + "const": false + }, + { + "const": true + }, + { + "const": "light" + }, + { + "const": "dark" + } + ] + }, + "properties": { + "allowFilter": { + "type": "boolean" + }, + "theme": { + "anyOf": [ + { + "const": "light" + }, + { + "const": "dark" + } + ] + } + }, + "type": "object" + }, + "pixelId": { + "type": "string" + }, + "pixelIds": { + "items": { + "type": "string" + }, + "type": "array" + }, + "shareType": { + "type": "number" + }, + "websiteId": { + "type": "string" + }, + "websiteIds": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "user": { + "properties": { + "id": { + "type": "string" + }, + "isAdmin": { + "type": "boolean" + }, + "role": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "role", + "isAdmin" + ], + "type": "object" + } + }, + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3532,14 +7254,14 @@ "Account" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/me/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/me/contract.generated.ts" } }, "/api/me/password": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostMePassword", + "description": "Create or update me password. The request and response models are derived from the validated route contract.", + "operationId": "postMePassword", "requestBody": { "content": { "application/json": { @@ -3567,16 +7289,67 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "username", + "role" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3589,14 +7362,14 @@ "Account" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/me/password/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/me/password/contract.generated.ts" } }, "/api/me/teams": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetMeTeams", + "description": "Get me teams. The request and response models are derived from the validated route contract.", + "operationId": "getMeTeams", "parameters": [ { "in": "query", @@ -3650,16 +7423,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3672,14 +7549,14 @@ "Account" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/me/teams/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/me/teams/contract.generated.ts" } }, "/api/me/websites": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetMeWebsites", + "description": "Get me websites. The request and response models are derived from the validated route contract.", + "operationId": "getMeWebsites", "parameters": [ { "in": "query", @@ -3741,16 +7618,264 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + { + "properties": { + "createUser": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + }, + "shareId": { + "type": "string" + }, + "team": { + "properties": { + "members": { + "items": { + "properties": { + "role": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "userId", + "role" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "members" + ], + "type": "object" + }, + "user": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + } + }, + "required": [ + "shareId" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3763,14 +7888,14 @@ "Account" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/me/websites/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/me/websites/contract.generated.ts" } }, "/api/pixels": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetPixels", + "description": "Get pixels. The request and response models are derived from the validated route contract.", + "operationId": "getPixels", "parameters": [ { "in": "query", @@ -3832,16 +7957,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3854,12 +8083,12 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostPixels", + "description": "Create or update pixels. The request and response models are derived from the validated route contract.", + "operationId": "postPixels", "requestBody": { "content": { "application/json": { @@ -3910,16 +8139,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3932,14 +8230,14 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/contract.generated.ts" } }, "/api/pixels/{pixelId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeletePixelsPixelId", + "description": "Delete pixels pixel id. The request and response models are derived from the validated route contract.", + "operationId": "deletePixelsPixelId", "parameters": [ { "in": "path", @@ -3955,14 +8253,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -3975,12 +8295,12 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/[pixelId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/[pixelId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetPixelsPixelId", + "description": "Get pixels pixel id. The request and response models are derived from the validated route contract.", + "operationId": "getPixelsPixelId", "parameters": [ { "in": "path", @@ -3995,13 +8315,68 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -4018,12 +8393,12 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/[pixelId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/[pixelId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostPixelsPixelId", + "description": "Create or update pixels pixel id. The request and response models are derived from the validated route contract.", + "operationId": "postPixelsPixelId", "parameters": [ { "in": "path", @@ -4059,19 +8434,102 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [ @@ -4084,14 +8542,14 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/[pixelId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/[pixelId]/contract.generated.ts" } }, "/api/pixels/{pixelId}/shares": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetPixelsPixelIdShares", + "description": "Get pixels pixel id shares. The request and response models are derived from the validated route contract.", + "operationId": "getPixelsPixelIdShares", "parameters": [ { "in": "path", @@ -4340,16 +8798,175 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -4366,12 +8983,12 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/[pixelId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/[pixelId]/shares/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostPixelsPixelIdShares", + "description": "Create or update pixels pixel id shares. The request and response models are derived from the validated route contract.", + "operationId": "postPixelsPixelIdShares", "parameters": [ { "in": "path", @@ -4409,16 +9026,140 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -4431,14 +9172,14 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/[pixelId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/[pixelId]/shares/contract.generated.ts" } }, "/api/pixels/charts": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetPixelsCharts", + "description": "Get pixels charts. The request and response models are derived from the validated route contract.", + "operationId": "getPixelsCharts", "parameters": [ { "in": "query", @@ -4477,16 +9218,73 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "data": { + "additionalProperties": { + "properties": { + "total": { + "type": "number" + }, + "values": { + "items": { + "type": "number" + }, + "type": "array" + } + }, + "required": [ + "values", + "total" + ], + "type": "object" + }, + "properties": {}, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -4503,14 +9301,14 @@ "Pixels" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/pixels/charts/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/pixels/charts/contract.generated.ts" } }, "/api/realtime/{websiteId}": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetRealtimeWebsiteId", + "description": "Get realtime website id. The request and response models are derived from the validated route contract.", + "operationId": "getRealtimeWebsiteId", "parameters": [ { "in": "path", @@ -4748,16 +9546,229 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "countries": { + "additionalProperties": { + "type": "number" + }, + "properties": {}, + "type": "object" + }, + "events": { + "items": { + "properties": { + "__type": { + "anyOf": [ + { + "const": "event" + }, + { + "const": "session" + }, + { + "const": "pageview" + } + ] + }, + "browser": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "eventName": { + "type": "string" + }, + "hostname": { + "type": "string" + }, + "os": { + "type": "string" + }, + "referrerDomain": { + "type": "string" + }, + "sessionId": { + "type": "string" + }, + "urlPath": { + "type": "string" + } + }, + "required": [ + "__type", + "sessionId", + "eventName", + "createdAt", + "browser", + "os", + "device", + "country", + "urlPath", + "referrerDomain", + "hostname" + ], + "type": "object" + }, + "type": "array" + }, + "referrers": { + "additionalProperties": { + "type": "number" + }, + "properties": {}, + "type": "object" + }, + "series": { + "properties": { + "views": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + }, + "visitors": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "views", + "visitors" + ], + "type": "object" + }, + "timestamp": { + "type": "number" + }, + "totals": { + "properties": { + "countries": { + "type": "number" + }, + "events": { + "type": "number" + }, + "views": { + "type": "number" + }, + "visitors": { + "type": "number" + } + }, + "required": [ + "views", + "visitors", + "events", + "countries" + ], + "type": "object" + }, + "urls": { + "additionalProperties": { + "type": "number" + }, + "properties": {}, + "type": "object" + } + }, + "required": [ + "countries", + "events", + "referrers", + "timestamp", + "series", + "totals", + "urls" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -4774,14 +9785,14 @@ "Realtime" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/realtime/[websiteId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/realtime/[websiteId]/contract.generated.ts" } }, "/api/record": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostRecord", + "description": "Create or update record. The request and response models are derived from the validated route contract.", + "operationId": "postRecord", "requestBody": { "content": { "application/json": { @@ -4941,22 +9952,118 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "ok": { + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "type": "object" + }, + { + "properties": { + "ok": { + "type": "boolean" + }, + "reason": { + "type": "string" + } + }, + "required": [ + "ok", + "reason" + ], + "type": "object" + }, + { + "properties": { + "beep": { + "type": "string" + } + }, + "required": [ + "beep" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "403": { - "$ref": "#/components/responses/ForbiddenResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "forbidden", + "message": "Forbidden.", + "status": 403 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Forbidden." }, "413": { - "$ref": "#/components/responses/PayloadTooLargeResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "payload-too-large", + "message": "Payload too large.", + "status": 413 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Payload too large." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [], @@ -4965,14 +10072,14 @@ "Collection" ], "x-umami-audience": "collect", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/record/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/record/contract.generated.ts" } }, "/api/reports": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetReports", + "description": "Get reports. The request and response models are derived from the validated route contract.", + "operationId": "getReports", "parameters": [ { "in": "query", @@ -5023,16 +10130,203 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + }, + { + "properties": { + "website": { + "properties": { + "domain": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "domain", + "userId" + ], + "type": "object" + } + }, + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5049,12 +10343,12 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReports", + "description": "Create or update reports. The request and response models are derived from the validated route contract.", + "operationId": "postReports", "requestBody": { "content": { "application/json": { @@ -5096,16 +10390,144 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5118,14 +10540,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/contract.generated.ts" } }, "/api/reports/{reportId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteReportsReportId", + "description": "Delete reports report id. The request and response models are derived from the validated route contract.", + "operationId": "deleteReportsReportId", "parameters": [ { "in": "path", @@ -5141,17 +10563,53 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -5164,12 +10622,12 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/[reportId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/[reportId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetReportsReportId", + "description": "Get reports report id. The request and response models are derived from the validated route contract.", + "operationId": "getReportsReportId", "parameters": [ { "in": "path", @@ -5184,16 +10642,144 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -5210,12 +10796,12 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/[reportId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/[reportId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsReportId", + "description": "Create or update reports report id. The request and response models are derived from the validated route contract.", + "operationId": "postReportsReportId", "parameters": [ { "in": "path", @@ -5267,19 +10853,161 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -5292,14 +11020,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/[reportId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/[reportId]/contract.generated.ts" } }, "/api/reports/attribution": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsAttribution", + "description": "Create or update reports attribution. The request and response models are derived from the validated route contract.", + "operationId": "postReportsAttribution", "requestBody": { "content": { "application/json": { @@ -5337,16 +11065,203 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "paidAds": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "referrer": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "total": { + "properties": { + "pageviews": { + "type": "number" + }, + "visitors": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "pageviews", + "visitors", + "visits" + ], + "type": "object" + }, + "utm_campaign": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "utm_content": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "utm_medium": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "utm_source": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "utm_term": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "referrer", + "paidAds", + "utm_source", + "utm_medium", + "utm_campaign", + "utm_content", + "utm_term", + "total" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5363,14 +11278,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/attribution/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/attribution/contract.generated.ts" } }, "/api/reports/breakdown": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsBreakdown", + "description": "Create or update reports breakdown. The request and response models are derived from the validated route contract.", + "operationId": "postReportsBreakdown", "requestBody": { "content": { "application/json": { @@ -5408,16 +11323,83 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, + "properties": { + "bounces": { + "type": "number" + }, + "totaltime": { + "type": "number" + }, + "views": { + "type": "number" + }, + "visitors": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "views", + "visitors", + "visits", + "bounces", + "totaltime" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5434,14 +11416,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/breakdown/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/breakdown/contract.generated.ts" } }, "/api/reports/funnel": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsFunnel", + "description": "Create or update reports funnel. The request and response models are derived from the validated route contract.", + "operationId": "postReportsFunnel", "requestBody": { "content": { "application/json": { @@ -5479,16 +11461,103 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "dropoff": { + "type": "number" + }, + "dropped": { + "type": "number" + }, + "filters": { + "items": { + "properties": { + "operator": { + "type": "string" + }, + "property": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "property", + "operator", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "previous": { + "type": "number" + }, + "remaining": { + "type": "number" + }, + "type": { + "type": "string" + }, + "value": { + "type": "string" + }, + "visitors": { + "type": "number" + } + }, + "required": [ + "visitors", + "previous", + "dropped", + "dropoff", + "remaining", + "type", + "value" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5505,14 +11574,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/funnel/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/funnel/contract.generated.ts" } }, "/api/reports/goal": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsGoal", + "description": "Create or update reports goal. The request and response models are derived from the validated route contract.", + "operationId": "postReportsGoal", "requestBody": { "content": { "application/json": { @@ -5550,16 +11619,58 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "num": { + "type": "number" + }, + "total": { + "type": "number" + } + }, + "required": [ + "num", + "total" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5576,14 +11687,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/goal/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/goal/contract.generated.ts" } }, "/api/reports/heatmap": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsHeatmap", + "description": "Create or update reports heatmap. The request and response models are derived from the validated route contract.", + "operationId": "postReportsHeatmap", "requestBody": { "content": { "application/json": { @@ -5621,16 +11732,230 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "mode": { + "anyOf": [ + { + "const": "click" + }, + { + "const": "scroll" + } + ] + }, + "pages": { + "items": { + "properties": { + "count": { + "type": "number" + }, + "sessions": { + "type": "number" + }, + "urlPath": { + "type": "string" + } + }, + "required": [ + "urlPath", + "count", + "sessions" + ], + "type": "object" + }, + "type": "array" + }, + "points": { + "items": { + "properties": { + "count": { + "type": "number" + }, + "pageH": { + "type": "number" + }, + "pageW": { + "type": "number" + }, + "pageX": { + "type": "number" + }, + "pageY": { + "type": "number" + }, + "viewportH": { + "type": "number" + }, + "viewportW": { + "type": "number" + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "y", + "pageX", + "pageY", + "pageW", + "pageH", + "viewportW", + "viewportH", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "scroll": { + "properties": { + "buckets": { + "items": { + "properties": { + "depth": { + "type": "number" + }, + "pageH": { + "type": "number" + }, + "pageW": { + "type": "number" + }, + "sessions": { + "type": "number" + }, + "viewportH": { + "type": "number" + }, + "viewportW": { + "type": "number" + } + }, + "required": [ + "depth", + "sessions", + "pageW", + "pageH", + "viewportW", + "viewportH" + ], + "type": "object" + }, + "type": "array" + }, + "pageH": { + "type": "number" + }, + "pageW": { + "type": "number" + }, + "totalSessions": { + "type": "number" + }, + "viewportH": { + "type": "number" + }, + "viewportW": { + "type": "number" + } + }, + "required": [ + "buckets", + "totalSessions", + "pageW", + "pageH", + "viewportW", + "viewportH" + ], + "type": "object" + }, + "snapshot": { + "properties": { + "id": { + "type": "string" + }, + "kind": { + "const": "iframe" + }, + "pageH": { + "type": "number" + }, + "pageW": { + "type": "number" + }, + "url": { + "type": "string" + }, + "viewportH": { + "type": "number" + }, + "viewportW": { + "type": "number" + } + }, + "required": [ + "kind", + "id", + "url", + "pageW", + "pageH", + "viewportW", + "viewportH" + ], + "type": "object" + } + }, + "required": [ + "mode", + "pages", + "points", + "snapshot", + "scroll" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5647,14 +11972,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/heatmap/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/heatmap/contract.generated.ts" } }, "/api/reports/journey": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsJourney", + "description": "Create or update reports journey. The request and response models are derived from the validated route contract.", + "operationId": "postReportsJourney", "requestBody": { "content": { "application/json": { @@ -5692,16 +12017,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "count": { + "type": "number" + }, + "e1": { + "type": "string" + }, + "e2": { + "type": "string" + }, + "e3": { + "type": "string" + }, + "e4": { + "type": "string" + }, + "e5": { + "type": "string" + }, + "e6": { + "type": "string" + }, + "e7": { + "type": "string" + } + }, + "required": [ + "e1", + "e2", + "e3", + "e4", + "e5", + "e6", + "e7", + "count" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5718,14 +12112,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/journey/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/journey/contract.generated.ts" } }, "/api/reports/performance": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsPerformance", + "description": "Create or update reports performance. The request and response models are derived from the validated route contract.", + "operationId": "postReportsPerformance", "requestBody": { "content": { "application/json": { @@ -5763,16 +12157,62 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "browsers": {}, + "chart": {}, + "devices": {}, + "pages": {}, + "pageTitles": {}, + "summary": {} + }, + "required": [ + "chart", + "summary", + "pages", + "pageTitles", + "devices", + "browsers" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5789,14 +12229,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/performance/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/performance/contract.generated.ts" } }, "/api/reports/retention": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsRetention", + "description": "Create or update reports retention. The request and response models are derived from the validated route contract.", + "operationId": "postReportsRetention", "requestBody": { "content": { "application/json": { @@ -5834,16 +12274,73 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "date": { + "type": "string" + }, + "day": { + "type": "number" + }, + "percentage": { + "type": "number" + }, + "returnVisitors": { + "type": "number" + }, + "visitors": { + "type": "number" + } + }, + "required": [ + "date", + "day", + "visitors", + "returnVisitors", + "percentage" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5860,14 +12357,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/retention/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/retention/contract.generated.ts" } }, "/api/reports/revenue": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsRevenue", + "description": "Create or update reports revenue. The request and response models are derived from the validated route contract.", + "operationId": "postReportsRevenue", "requestBody": { "content": { "application/json": { @@ -5905,16 +12402,159 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "channel": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "chart": { + "items": { + "properties": { + "count": { + "type": "number" + }, + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y", + "count" + ], + "type": "object" + }, + "type": "array" + }, + "country": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "referrer": { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + "region": { + "items": { + "properties": { + "country": { + "type": "string" + }, + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value", + "country" + ], + "type": "object" + }, + "type": "array" + }, + "total": {} + }, + "required": [ + "chart", + "total", + "country", + "region", + "referrer", + "channel" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -5931,14 +12571,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/revenue/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/revenue/contract.generated.ts" } }, "/api/reports/utm": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostReportsUtm", + "description": "Create or update reports utm. The request and response models are derived from the validated route contract.", + "operationId": "postReportsUtm", "requestBody": { "content": { "application/json": { @@ -5976,16 +12616,75 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "utm_campaign": { + "items": {}, + "type": "array" + }, + "utm_content": { + "items": {}, + "type": "array" + }, + "utm_medium": { + "items": {}, + "type": "array" + }, + "utm_source": { + "items": {}, + "type": "array" + }, + "utm_term": { + "items": {}, + "type": "array" + } + }, + "required": [ + "utm_source", + "utm_medium", + "utm_campaign", + "utm_term", + "utm_content" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6002,14 +12701,14 @@ "Reports" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/reports/utm/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/reports/utm/contract.generated.ts" } }, "/api/scripts/telemetry": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetScriptsTelemetry", + "description": "Get scripts telemetry. The request and response models are derived from the validated route contract.", + "operationId": "getScriptsTelemetry", "responses": { "200": { "content": { @@ -6028,14 +12727,14 @@ "Scripts" ], "x-umami-audience": "internal", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/scripts/telemetry/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/scripts/telemetry/contract.generated.ts" } }, "/api/send": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostSend", + "description": "Create or update send. The request and response models are derived from the validated route contract.", + "operationId": "postSend", "requestBody": { "content": { "application/json": { @@ -6151,19 +12850,88 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "beep": { + "type": "string" + } + }, + "required": [ + "beep" + ], + "type": "object" + }, + { + "properties": { + "cache": {}, + "sessionId": {}, + "visitId": {} + }, + "required": [ + "cache", + "sessionId", + "visitId" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "403": { - "$ref": "#/components/responses/ForbiddenResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "forbidden", + "message": "Forbidden.", + "status": 403 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Forbidden." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [], @@ -6172,14 +12940,14 @@ "Collection" ], "x-umami-audience": "collect", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/send/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/send/contract.generated.ts" } }, "/api/share": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostShare", + "description": "Create or update share. The request and response models are derived from the validated route contract.", + "operationId": "postShare", "requestBody": { "content": { "application/json": { @@ -6221,16 +12989,140 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6243,14 +13135,14 @@ "Shares" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/share/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/share/contract.generated.ts" } }, "/api/share/{slug}": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetShareSlug", + "description": "Get share slug. The request and response models are derived from the validated route contract.", + "operationId": "getShareSlug", "parameters": [ { "in": "path", @@ -6265,13 +13157,31 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "additionalProperties": {}, + "properties": {}, + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [], @@ -6280,14 +13190,14 @@ "Shares" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/share/[slug]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/share/[slug]/contract.generated.ts" } }, "/api/share/id/{shareId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteShareIdShareId", + "description": "Delete share id share id. The request and response models are derived from the validated route contract.", + "operationId": "deleteShareIdShareId", "parameters": [ { "in": "path", @@ -6303,14 +13213,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6323,12 +13255,12 @@ "Shares" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/share/id/[shareId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/share/id/[shareId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetShareIdShareId", + "description": "Get share id share id. The request and response models are derived from the validated route contract.", + "operationId": "getShareIdShareId", "parameters": [ { "in": "path", @@ -6343,13 +13275,123 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6366,12 +13408,12 @@ "Shares" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/share/id/[shareId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/share/id/[shareId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostShareIdShareId", + "description": "Create or update share id share id. The request and response models are derived from the validated route contract.", + "operationId": "postShareIdShareId", "parameters": [ { "in": "path", @@ -6415,19 +13457,157 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -6440,14 +13620,14 @@ "Shares" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/share/id/[shareId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/share/id/[shareId]/contract.generated.ts" } }, "/api/teams": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeams", + "description": "Get teams. The request and response models are derived from the validated route contract.", + "operationId": "getTeams", "parameters": [ { "in": "query", @@ -6501,16 +13681,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6523,12 +13807,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostTeams", + "description": "Create or update teams. The request and response models are derived from the validated route contract.", + "operationId": "postTeams", "requestBody": { "content": { "application/json": { @@ -6556,16 +13840,125 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + }, + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + } + ], + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6578,14 +13971,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/contract.generated.ts" } }, "/api/teams/{teamId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteTeamsTeamId", + "description": "Delete teams team id. The request and response models are derived from the validated route contract.", + "operationId": "deleteTeamsTeamId", "parameters": [ { "in": "path", @@ -6601,14 +13994,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6621,12 +14036,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamId", + "description": "Get teams team id. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamId", "parameters": [ { "in": "path", @@ -6641,16 +14056,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -6667,12 +14151,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostTeamsTeamId", + "description": "Create or update teams team id. The request and response models are derived from the validated route contract.", + "operationId": "postTeamsTeamId", "parameters": [ { "in": "path", @@ -6707,16 +14191,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6729,14 +14282,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/contract.generated.ts" } }, "/api/teams/{teamId}/boards": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdBoards", + "description": "Get teams team id boards. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdBoards", "parameters": [ { "in": "path", @@ -6806,16 +14359,179 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6832,14 +14548,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/boards/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/boards/contract.generated.ts" } }, "/api/teams/{teamId}/links": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdLinks", + "description": "Get teams team id links. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdLinks", "parameters": [ { "in": "path", @@ -6909,16 +14625,124 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -6935,14 +14759,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/links/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/links/contract.generated.ts" } }, "/api/teams/{teamId}/pixels": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdPixels", + "description": "Get teams team id pixels. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdPixels", "parameters": [ { "in": "path", @@ -7012,16 +14836,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7038,14 +14966,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/pixels/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/pixels/contract.generated.ts" } }, "/api/teams/{teamId}/users": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdUsers", + "description": "Get teams team id users. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdUsers", "parameters": [ { "in": "path", @@ -7095,16 +15023,135 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + }, + { + "properties": { + "user": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + } + }, + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7121,12 +15168,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/users/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/users/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostTeamsTeamIdUsers", + "description": "Create or update teams team id users. The request and response models are derived from the validated route contract.", + "operationId": "postTeamsTeamIdUsers", "parameters": [ { "in": "path", @@ -7169,16 +15216,76 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7191,14 +15298,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/users/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/users/contract.generated.ts" } }, "/api/teams/{teamId}/users/{userId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteTeamsTeamIdUsersUserId", + "description": "Delete teams team id users user id. The request and response models are derived from the validated route contract.", + "operationId": "deleteTeamsTeamIdUsersUserId", "parameters": [ { "in": "path", @@ -7222,17 +15329,53 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7245,12 +15388,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdUsersUserId", + "description": "Get teams team id users user id. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdUsersUserId", "parameters": [ { "in": "path", @@ -7273,13 +15416,59 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7292,12 +15481,12 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostTeamsTeamIdUsersUserId", + "description": "Create or update teams team id users user id. The request and response models are derived from the validated route contract.", + "operationId": "postTeamsTeamIdUsersUserId", "parameters": [ { "in": "path", @@ -7343,16 +15532,76 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7365,14 +15614,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts" } }, "/api/teams/{teamId}/websites": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetTeamsTeamIdWebsites", + "description": "Get teams team id websites. The request and response models are derived from the validated route contract.", + "operationId": "getTeamsTeamIdWebsites", "parameters": [ { "in": "path", @@ -7442,16 +15691,264 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + { + "properties": { + "createUser": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + }, + "shareId": { + "type": "string" + }, + "team": { + "properties": { + "members": { + "items": { + "properties": { + "role": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "userId", + "role" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "members" + ], + "type": "object" + }, + "user": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + } + }, + "required": [ + "shareId" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7468,14 +15965,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/[teamId]/websites/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/[teamId]/websites/contract.generated.ts" } }, "/api/teams/join": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostTeamsJoin", + "description": "Create or update teams join. The request and response models are derived from the validated route contract.", + "operationId": "postTeamsJoin", "requestBody": { "content": { "application/json": { @@ -7499,19 +15996,93 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -7524,14 +16095,14 @@ "Teams" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/teams/join/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/teams/join/contract.generated.ts" } }, "/api/users": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostUsers", + "description": "Create or update users. The request and response models are derived from the validated route contract.", + "operationId": "postUsers", "requestBody": { "content": { "application/json": { @@ -7574,16 +16145,62 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username", + "role" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7596,14 +16213,14 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/contract.generated.ts" } }, "/api/users/{userId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteUsersUserId", + "description": "Delete users user id. The request and response models are derived from the validated route contract.", + "operationId": "deleteUsersUserId", "parameters": [ { "in": "path", @@ -7619,17 +16236,53 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7642,12 +16295,12 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/[userId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetUsersUserId", + "description": "Get users user id. The request and response models are derived from the validated route contract.", + "operationId": "getUsersUserId", "parameters": [ { "in": "path", @@ -7662,13 +16315,815 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "_count": { + "properties": { + "boards": { + "type": "number" + }, + "createdBy": { + "type": "number" + }, + "links": { + "type": "number" + }, + "pixels": { + "type": "number" + }, + "reports": { + "type": "number" + }, + "teams": { + "type": "number" + }, + "twoFactorAuth": { + "type": "number" + }, + "twoFactorBackupCodes": { + "type": "number" + }, + "twoFactorOtpUseds": { + "type": "number" + }, + "twoFactorRateLimit": { + "type": "number" + }, + "websites": { + "type": "number" + } + }, + "required": [ + "websites", + "createdBy", + "links", + "pixels", + "teams", + "reports", + "boards", + "twoFactorAuth", + "twoFactorBackupCodes", + "twoFactorOtpUseds", + "twoFactorRateLimit" + ], + "type": "object" + }, + "boards": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "teamId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "teamId", + "type", + "description", + "parameters" + ], + "type": "object" + }, + "type": "array" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "links": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "url": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "url", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "password": { + "type": "string" + }, + "pixels": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "name", + "teamId", + "slug" + ], + "type": "object" + }, + "type": "array" + }, + "reports": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + }, + "type": "array" + }, + "role": { + "type": "string" + }, + "teams": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "role", + "teamId" + ], + "type": "object" + }, + "type": "array" + }, + "twoFactorAuth": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "isEnabled": { + "type": "boolean" + }, + "secret": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "isEnabled", + "id", + "userId", + "secret", + "createdAt", + "updatedAt" + ], + "type": "object" + }, + "twoFactorBackupCodes": { + "items": { + "properties": { + "codeHash": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "used": { + "type": "boolean" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "codeHash", + "used" + ], + "type": "object" + }, + "type": "array" + }, + "twoFactorOtpUseds": { + "items": { + "properties": { + "expiresAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "otp": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "otp", + "expiresAt" + ], + "type": "object" + }, + "type": "array" + }, + "twoFactorRateLimit": { + "properties": { + "attempts": { + "type": "number" + }, + "id": { + "type": "string" + }, + "lockedUntil": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "updatedAt", + "attempts", + "lockedUntil" + ], + "type": "object" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "websites": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "twoFactorAuth", + "twoFactorRateLimit", + "id", + "createdAt", + "username", + "password", + "role", + "twoFactorRequired", + "websites", + "createdBy", + "links", + "pixels", + "teams", + "reports", + "boards", + "twoFactorBackupCodes", + "twoFactorOtpUseds", + "_count" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7685,12 +17140,12 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/[userId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostUsersUserId", + "description": "Create or update users user id. The request and response models are derived from the validated route contract.", + "operationId": "postUsersUserId", "parameters": [ { "in": "path", @@ -7734,19 +17189,84 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "role": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "username", + "role" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -7759,14 +17279,14 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/[userId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/[userId]/contract.generated.ts" } }, "/api/users/{userId}/teams": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetUsersUserIdTeams", + "description": "Get users user id teams. The request and response models are derived from the validated route contract.", + "operationId": "getUsersUserIdTeams", "parameters": [ { "in": "path", @@ -7828,16 +17348,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "accessCode": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "logoUrl": { + "type": "string" + }, + "name": { + "type": "string" + }, + "twoFactorRequired": { + "type": "boolean" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "logoUrl", + "twoFactorRequired", + "deletedAt", + "name", + "accessCode" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7850,14 +17474,14 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/[userId]/teams/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/[userId]/teams/contract.generated.ts" } }, "/api/users/{userId}/websites": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetUsersUserIdWebsites", + "description": "Get users user id websites. The request and response models are derived from the validated route contract.", + "operationId": "getUsersUserIdWebsites", "parameters": [ { "in": "path", @@ -7935,16 +17559,264 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + }, + { + "properties": { + "createUser": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + }, + "shareId": { + "type": "string" + }, + "team": { + "properties": { + "members": { + "items": { + "properties": { + "role": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "userId", + "role" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "members" + ], + "type": "object" + }, + "user": { + "properties": { + "id": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "id", + "username" + ], + "type": "object" + } + }, + "required": [ + "shareId" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -7957,8 +17829,8 @@ "Users" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/users/[userId]/websites/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/users/[userId]/websites/contract.generated.ts" } }, "/api/websites": { @@ -8040,10 +17912,38 @@ "description": "A page of websites." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8083,10 +17983,38 @@ "description": "Website created." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8132,7 +18060,21 @@ "description": "Website deleted." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8183,7 +18125,21 @@ "description": "Website details, or null if it does not exist." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8241,13 +18197,55 @@ "description": "Website updated." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "500": { - "$ref": "#/components/responses/ServerErrorResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "server-error", + "message": "Server error.", + "status": 500 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Server error." } }, "security": [ @@ -8266,8 +18264,8 @@ }, "/api/websites/{websiteId}/active": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdActive", + "description": "Get websites website id active. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdActive", "parameters": [ { "in": "path", @@ -8282,13 +18280,37 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "visitors": { + "type": "number" + } + }, + "required": [ + "visitors" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8305,14 +18327,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/active/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/active/contract.generated.ts" } }, "/api/websites/{websiteId}/annotations": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdAnnotations", + "description": "Get websites website id annotations. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdAnnotations", "parameters": [ { "in": "path", @@ -8378,16 +18400,120 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "allDay": { + "type": "boolean" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "date": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "note": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "websiteId", + "date", + "allDay", + "note" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8404,12 +18530,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/annotations/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/annotations/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdAnnotations", + "description": "Create or update websites website id annotations. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdAnnotations", "parameters": [ { "in": "path", @@ -8452,16 +18578,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "allDay": { + "type": "boolean" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "date": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "note": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "websiteId", + "date", + "allDay", + "note" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8474,14 +18669,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/annotations/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/annotations/contract.generated.ts" } }, "/api/websites/{websiteId}/annotations/{annotationId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteWebsitesWebsiteIdAnnotationsAnnotationId", + "description": "Delete websites website id annotations annotation id. The request and response models are derived from the validated route contract.", + "operationId": "deleteWebsitesWebsiteIdAnnotationsAnnotationId", "parameters": [ { "in": "path", @@ -8505,17 +18700,53 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -8528,12 +18759,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdAnnotationsAnnotationId", + "description": "Get websites website id annotations annotation id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdAnnotationsAnnotationId", "parameters": [ { "in": "path", @@ -8556,16 +18787,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "allDay": { + "type": "boolean" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "date": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "note": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "websiteId", + "date", + "allDay", + "note" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -8582,12 +18882,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdAnnotationsAnnotationId", + "description": "Create or update websites website id annotations annotation id. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdAnnotationsAnnotationId", "parameters": [ { "in": "path", @@ -8638,19 +18938,102 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "allDay": { + "type": "boolean" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "date": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "note": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "websiteId", + "date", + "allDay", + "note" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -8663,14 +19046,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts" } }, "/api/websites/{websiteId}/daterange": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdDaterange", + "description": "Get websites website id daterange. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdDaterange", "parameters": [ { "in": "path", @@ -8685,13 +19068,43 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "endDate": { + "format": "date-time", + "type": "string" + }, + "startDate": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "startDate", + "endDate" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -8708,14 +19121,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/daterange/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/daterange/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventData", + "description": "Get websites website id event data. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventData", "parameters": [ { "in": "path", @@ -8980,16 +19393,136 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "eventId": { + "type": "string" + }, + "eventName": { + "type": "string" + }, + "eventProperties": { + "items": { + "properties": { + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "dataKey": { + "type": "string" + }, + "dataType": { + "type": "number" + }, + "dateValue": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "numberValue": { + "type": "number" + }, + "stringValue": { + "type": "string" + } + }, + "required": [ + "createdAt", + "dataKey", + "stringValue", + "numberValue", + "dateValue", + "dataType" + ], + "type": "object" + }, + "type": "array" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "websiteId", + "eventId", + "eventName", + "eventProperties" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -9006,14 +19539,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivot", + "description": "Get websites website id event data pivot. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivot", "parameters": [ { "in": "path", @@ -9302,16 +19835,127 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "eventId": { + "type": "string" + }, + "eventName": { + "type": "string" + }, + "propertyKeys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "propertyValues": { + "items": { + "type": "string" + }, + "type": "array" + }, + "sessionId": { + "type": "string" + }, + "urlPath": { + "type": "string" + } + }, + "required": [ + "eventId", + "sessionId", + "eventName", + "urlPath", + "createdAt", + "propertyKeys", + "propertyValues" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -9328,14 +19972,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot/array-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivotArraySeries", + "description": "Get websites website id event data pivot array series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivotArraySeries", "parameters": [ { "in": "path", @@ -9605,16 +20249,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -9631,14 +20324,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/array-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/array-series/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot/date-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivotDateSeries", + "description": "Get websites website id event data pivot date series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivotDateSeries", "parameters": [ { "in": "path", @@ -9900,16 +20593,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -9926,14 +20664,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/date-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/date-series/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot/numeric-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivotNumericSeries", + "description": "Get websites website id event data pivot numeric series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivotNumericSeries", "parameters": [ { "in": "path", @@ -10216,16 +20954,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -10242,14 +21025,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/numeric-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/numeric-series/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot/numeric-stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivotNumericStats", + "description": "Get websites website id event data pivot numeric stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivotNumericStats", "parameters": [ { "in": "path", @@ -10503,16 +21286,70 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "average": { + "type": "number" + }, + "max": { + "type": "number" + }, + "median": { + "type": "number" + }, + "min": { + "type": "number" + }, + "total": { + "type": "number" + } + }, + "required": [ + "total", + "average", + "median", + "max", + "min" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -10529,14 +21366,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/numeric-stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/numeric-stats/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data-pivot/property-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataPivotPropertySeries", + "description": "Get websites website id event data pivot property series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataPivotPropertySeries", "parameters": [ { "in": "path", @@ -10806,16 +21643,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -10832,14 +21718,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/property-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data-pivot/property-series/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/{eventId}": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataEventId", + "description": "Get websites website id event data event id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataEventId", "parameters": [ { "in": "path", @@ -10862,13 +21748,93 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "dataKey": { + "type": "string" + }, + "dataType": { + "type": "number" + }, + "dateValue": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "numberValue": { + "properties": { + "d": { + "items": { + "type": "number" + }, + "type": "array" + }, + "e": { + "type": "number" + }, + "s": { + "type": "number" + } + }, + "required": [ + "d", + "e", + "s" + ], + "type": "object" + }, + "stringValue": { + "type": "string" + }, + "websiteEventId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "websiteId", + "websiteEventId", + "dataKey", + "stringValue", + "numberValue", + "dateValue", + "dataType" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -10885,14 +21851,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/[eventId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/[eventId]/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/events": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataEvents", + "description": "Get websites website id event data events. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataEvents", "parameters": [ { "in": "path", @@ -11130,16 +22096,71 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "dataType": { + "type": "number" + }, + "eventName": { + "type": "string" + }, + "propertyName": { + "type": "string" + }, + "propertyValue": { + "type": "string" + }, + "total": { + "type": "number" + } + }, + "required": [ + "propertyName", + "dataType", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -11156,14 +22177,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/events/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/events/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/fields": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataFields", + "description": "Get websites website id event data fields. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataFields", "parameters": [ { "in": "path", @@ -11409,16 +22430,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "dataType": { + "type": "number" + }, + "propertyName": { + "type": "string" + }, + "total": { + "type": "number" + } + }, + "required": [ + "propertyName", + "dataType", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -11435,14 +22505,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/fields/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/fields/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/properties": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataProperties", + "description": "Get websites website id event data properties. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataProperties", "parameters": [ { "in": "path", @@ -11680,16 +22750,69 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "dataType": { + "type": "number" + }, + "eventName": { + "type": "string" + }, + "propertyName": { + "type": "string" + }, + "total": { + "type": "number" + } + }, + "required": [ + "eventName", + "propertyName", + "dataType", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -11706,14 +22829,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/properties/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/properties/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataStats", + "description": "Get websites website id event data stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataStats", "parameters": [ { "in": "path", @@ -11951,16 +23074,62 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "events": { + "type": "number" + }, + "properties": { + "type": "number" + }, + "records": { + "type": "number" + } + }, + "required": [ + "events", + "properties", + "records" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -11977,14 +23146,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/event-data/values": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventDataValues", + "description": "Get websites website id event data values. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventDataValues", "parameters": [ { "in": "path", @@ -12246,16 +23415,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "total": { + "type": "number" + }, + "value": { + "type": "string" + } + }, + "required": [ + "value", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -12272,14 +23486,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/event-data/values/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/event-data/values/contract.generated.ts" } }, "/api/websites/{websiteId}/events": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEvents", + "description": "Get websites website id events. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEvents", "parameters": [ { "in": "path", @@ -12598,16 +23812,169 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "browser": { + "type": "string" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "eventName": { + "type": "string" + }, + "eventType": { + "type": "number" + }, + "hasData": { + "type": "boolean" + }, + "hostname": { + "type": "string" + }, + "id": { + "type": "string" + }, + "os": { + "type": "string" + }, + "pageTitle": { + "type": "string" + }, + "referrerDomain": { + "type": "string" + }, + "referrerPath": { + "type": "string" + }, + "referrerQuery": { + "type": "string" + }, + "sessionId": { + "type": "string" + }, + "urlPath": { + "type": "string" + }, + "urlQuery": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "websiteId", + "sessionId", + "createdAt", + "hostname", + "urlPath", + "urlQuery", + "referrerPath", + "referrerQuery", + "referrerDomain", + "country", + "city", + "device", + "os", + "browser", + "pageTitle", + "eventType", + "eventName", + "hasData" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -12624,14 +23991,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/events/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/events/contract.generated.ts" } }, "/api/websites/{websiteId}/events/series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventsSeries", + "description": "Get websites website id events series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventsSeries", "parameters": [ { "in": "path", @@ -12893,16 +24260,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -12919,14 +24335,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/events/series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/events/series/contract.generated.ts" } }, "/api/websites/{websiteId}/events/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdEventsStats", + "description": "Get websites website id events stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdEventsStats", "parameters": [ { "in": "path", @@ -13210,16 +24626,89 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "data": { + "properties": { + "comparison": { + "items": { + "properties": { + "events": { + "type": "number" + }, + "uniqueEvents": { + "type": "number" + }, + "visitors": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "events", + "visitors", + "visits", + "uniqueEvents" + ], + "type": "object" + }, + "type": "array" + }, + "length": { + "type": "number" + } + }, + "required": [ + "comparison", + "length" + ], + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -13236,14 +24725,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/events/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/events/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/export": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdExport", + "description": "Get websites website id export. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdExport", "parameters": [ { "in": "path", @@ -13347,16 +24836,54 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "zip": { + "type": "string" + } + }, + "required": [ + "zip" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "function toString() { [native code] }": { "content": { @@ -13381,14 +24908,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/export/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/export/contract.generated.ts" } }, "/api/websites/{websiteId}/metrics": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdMetrics", + "description": "Get websites website id metrics. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdMetrics", "parameters": [ { "in": "path", @@ -13704,16 +25231,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -13730,14 +25306,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/metrics/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/metrics/contract.generated.ts" } }, "/api/websites/{websiteId}/metrics/expanded": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdMetricsExpanded", + "description": "Get websites website id metrics expanded. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdMetricsExpanded", "parameters": [ { "in": "path", @@ -14053,16 +25629,77 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "bounces": { + "type": "number" + }, + "name": { + "type": "string" + }, + "pageviews": { + "type": "number" + }, + "totaltime": { + "type": "number" + }, + "visitors": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "name", + "pageviews", + "visitors", + "visits", + "bounces", + "totaltime" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14079,14 +25716,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/metrics/expanded/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/metrics/expanded/contract.generated.ts" } }, "/api/websites/{websiteId}/pageviews": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdPageviews", + "description": "Get websites website id pageviews. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdPageviews", "parameters": [ { "in": "path", @@ -14370,16 +26007,101 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "compare": { + "properties": { + "endDate": { + "format": "date-time", + "type": "string" + }, + "pageviews": {}, + "sessions": {}, + "startDate": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "pageviews", + "sessions", + "startDate", + "endDate" + ], + "type": "object" + }, + "endDate": { + "format": "date-time", + "type": "string" + }, + "pageviews": {}, + "sessions": {}, + "startDate": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "pageviews", + "sessions", + "startDate", + "endDate", + "compare" + ], + "type": "object" + }, + { + "properties": { + "pageviews": {}, + "sessions": {} + }, + "required": [ + "pageviews", + "sessions" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14396,14 +26118,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/pageviews/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/pageviews/contract.generated.ts" } }, "/api/websites/{websiteId}/recorder": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdRecorder", + "description": "Get websites website id recorder. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdRecorder", "parameters": [ { "in": "path", @@ -14418,10 +26140,70 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, + { + "properties": { + "blockSelector": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "heatmapEnabled": { + "type": "boolean" + }, + "heatmapSampleRate": { + "type": "number" + }, + "maskLevel": { + "anyOf": [ + { + "const": "strict" + }, + { + "const": "moderate" + } + ] + }, + "maxDuration": { + "type": "number" + }, + "replayEnabled": { + "type": "boolean" + }, + "sampleRate": { + "type": "number" + } + }, + "required": [ + "enabled", + "replayEnabled", + "heatmapEnabled", + "sampleRate", + "heatmapSampleRate", + "maskLevel", + "maxDuration", + "blockSelector" + ], + "type": "object" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." } }, "security": [], @@ -14430,14 +26212,14 @@ "Websites" ], "x-umami-audience": "collect", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/recorder/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/recorder/contract.generated.ts" } }, "/api/websites/{websiteId}/replays": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdReplays", + "description": "Get websites website id replays. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdReplays", "parameters": [ { "in": "path", @@ -14765,16 +26547,165 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "browser": { + "type": "string" + }, + "chunkCount": { + "type": "number" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "duration": { + "type": "number" + }, + "endedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "eventCount": { + "type": "number" + }, + "id": { + "type": "string" + }, + "os": { + "type": "string" + }, + "sessionId": { + "type": "string" + }, + "startedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "sessionId", + "websiteId", + "browser", + "os", + "device", + "country", + "city", + "eventCount", + "chunkCount", + "startedAt", + "endedAt", + "duration", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14791,14 +26722,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/replays/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/replays/contract.generated.ts" } }, "/api/websites/{websiteId}/replays/{replayId}": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdReplaysReplayId", + "description": "Get websites website id replays replay id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdReplaysReplayId", "parameters": [ { "in": "path", @@ -14821,13 +26752,60 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "chunkCount": { + "type": "number" + }, + "endedAt": { + "format": "date-time", + "type": "string" + }, + "eventCount": { + "type": "number" + }, + "events": { + "items": {}, + "type": "array" + }, + "sessionId": { + "type": "string" + }, + "startedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "sessionId", + "events", + "startedAt", + "endedAt", + "eventCount", + "chunkCount" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14844,14 +26822,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/replays/[replayId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/replays/[replayId]/contract.generated.ts" } }, "/api/websites/{websiteId}/replays/saved": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdReplaysSaved", + "description": "Get websites website id replays saved. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdReplaysSaved", "parameters": [ { "in": "path", @@ -14901,16 +26879,111 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "visitId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "websiteId", + "visitId" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14927,14 +27000,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/contract.generated.ts" } }, "/api/websites/{websiteId}/replays/saved/{replayId}": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdReplaysSavedReplayId", + "description": "Get websites website id replays saved replay id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdReplaysSavedReplayId", "parameters": [ { "in": "path", @@ -14957,13 +27030,37 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "isSaved": { + "type": "boolean" + } + }, + "required": [ + "isSaved" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -14980,12 +27077,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/[replayId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/[replayId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdReplaysSavedReplayId", + "description": "Create or update websites website id replays saved replay id. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdReplaysSavedReplayId", "parameters": [ { "in": "path", @@ -15030,16 +27127,54 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "ok": { + "type": "boolean" + } + }, + "required": [ + "ok" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -15052,14 +27187,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/[replayId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/replays/saved/[replayId]/contract.generated.ts" } }, "/api/websites/{websiteId}/reports": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdReports", + "description": "Get websites website id reports. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdReports", "parameters": [ { "in": "path", @@ -15109,16 +27244,203 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "allOf": [ + { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "name", + "type", + "description", + "parameters", + "websiteId" + ], + "type": "object" + }, + { + "properties": { + "website": { + "properties": { + "domain": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "domain", + "userId" + ], + "type": "object" + } + }, + "type": "object" + } + ] + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -15135,14 +27457,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/reports/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/reports/contract.generated.ts" } }, "/api/websites/{websiteId}/reset": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdReset", + "description": "Create or update websites website id reset. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdReset", "parameters": [ { "in": "path", @@ -15158,14 +27480,36 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -15178,14 +27522,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/reset/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/reset/contract.generated.ts" } }, "/api/websites/{websiteId}/revenue/chart": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdRevenueChart", + "description": "Get websites website id revenue chart. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdRevenueChart", "parameters": [ { "in": "path", @@ -15477,16 +27821,77 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "chart": { + "items": { + "properties": { + "count": { + "type": "number" + }, + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y", + "count" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "chart" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -15503,14 +27908,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/revenue/chart/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/revenue/chart/contract.generated.ts" } }, "/api/websites/{websiteId}/revenue/metrics": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdRevenueMetrics", + "description": "Get websites website id revenue metrics. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdRevenueMetrics", "parameters": [ { "in": "path", @@ -15816,16 +28221,87 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "anyOf": [ + { + "items": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value" + ], + "type": "object" + }, + "type": "array" + }, + { + "items": { + "properties": { + "country": { + "type": "string" + }, + "name": { + "type": "string" + }, + "value": { + "type": "number" + } + }, + "required": [ + "name", + "value", + "country" + ], + "type": "object" + }, + "type": "array" + } + ] + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -15842,14 +28318,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/revenue/metrics/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/revenue/metrics/contract.generated.ts" } }, "/api/websites/{websiteId}/revenue/sessions": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdRevenueSessions", + "description": "Get websites website id revenue sessions. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdRevenueSessions", "parameters": [ { "in": "path", @@ -16176,16 +28652,177 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "browser": { + "type": "string" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "events": { + "type": "number" + }, + "firstAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "hostname": { + "type": "string" + }, + "id": { + "type": "string" + }, + "language": { + "type": "string" + }, + "lastAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "os": { + "type": "string" + }, + "region": { + "type": "string" + }, + "screen": { + "type": "string" + }, + "views": { + "type": "number" + }, + "visits": { + "type": "number" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "websiteId", + "hostname", + "browser", + "os", + "device", + "screen", + "language", + "country", + "region", + "city", + "firstAt", + "lastAt", + "visits", + "views", + "events", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -16202,14 +28839,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/revenue/sessions/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/revenue/sessions/contract.generated.ts" } }, "/api/websites/{websiteId}/revenue/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdRevenueStats", + "description": "Get websites website id revenue stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdRevenueStats", "parameters": [ { "in": "path", @@ -16501,16 +29138,52 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "comparison": {} + }, + "required": [ + "comparison" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -16527,14 +29200,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/revenue/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/revenue/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/segments": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSegments", + "description": "Get websites website id segments. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSegments", "parameters": [ { "in": "path", @@ -16569,16 +29242,171 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "type", + "parameters", + "websiteId" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -16595,12 +29423,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/segments/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/segments/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdSegments", + "description": "Create or update websites website id segments. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdSegments", "parameters": [ { "in": "path", @@ -16680,16 +29508,136 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "type", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -16702,14 +29650,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/segments/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/segments/contract.generated.ts" } }, "/api/websites/{websiteId}/segments/{segmentId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteWebsitesWebsiteIdSegmentsSegmentId", + "description": "Delete websites website id segments segment id. The request and response models are derived from the validated route contract.", + "operationId": "deleteWebsitesWebsiteIdSegmentsSegmentId", "parameters": [ { "in": "path", @@ -16733,17 +29681,53 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -16756,12 +29740,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSegmentsSegmentId", + "description": "Get websites website id segments segment id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSegmentsSegmentId", "parameters": [ { "in": "path", @@ -16784,16 +29768,136 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "type", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -16810,12 +29914,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdSegmentsSegmentId", + "description": "Create or update websites website id segments segment id. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdSegmentsSegmentId", "parameters": [ { "in": "path", @@ -16870,19 +29974,153 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "type": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "type", + "parameters", + "websiteId" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -16895,14 +30133,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data-pivot": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataPivot", + "description": "Get websites website id session data pivot. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataPivot", "parameters": [ { "in": "path", @@ -17191,16 +30429,119 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "distinctId": { + "type": "string" + }, + "propertyKeys": { + "items": { + "type": "string" + }, + "type": "array" + }, + "propertyValues": { + "items": { + "type": "string" + }, + "type": "array" + }, + "sessionId": { + "type": "string" + } + }, + "required": [ + "sessionId", + "distinctId", + "createdAt", + "propertyKeys", + "propertyValues" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -17217,14 +30558,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data-pivot/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data-pivot/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/array-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataArraySeries", + "description": "Get websites website id session data array series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataArraySeries", "parameters": [ { "in": "path", @@ -17486,16 +30827,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -17512,14 +30902,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/array-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/array-series/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/date-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataDateSeries", + "description": "Get websites website id session data date series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataDateSeries", "parameters": [ { "in": "path", @@ -17773,16 +31163,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -17799,14 +31234,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/date-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/date-series/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/numeric-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataNumericSeries", + "description": "Get websites website id session data numeric series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataNumericSeries", "parameters": [ { "in": "path", @@ -18081,16 +31516,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -18107,14 +31587,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/numeric-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/numeric-series/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/numeric-stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataNumericStats", + "description": "Get websites website id session data numeric stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataNumericStats", "parameters": [ { "in": "path", @@ -18368,16 +31848,70 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "average": { + "type": "number" + }, + "max": { + "type": "number" + }, + "median": { + "type": "number" + }, + "min": { + "type": "number" + }, + "total": { + "type": "number" + } + }, + "required": [ + "total", + "average", + "median", + "max", + "min" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -18394,14 +31928,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/numeric-stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/numeric-stats/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/properties": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataProperties", + "description": "Get websites website id session data properties. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataProperties", "parameters": [ { "in": "path", @@ -18647,16 +32181,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "dataType": { + "type": "number" + }, + "propertyName": { + "type": "string" + }, + "total": { + "type": "number" + } + }, + "required": [ + "propertyName", + "dataType", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -18673,14 +32256,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/properties/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/properties/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/property-series": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataPropertySeries", + "description": "Get websites website id session data property series. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataPropertySeries", "parameters": [ { "in": "path", @@ -18942,16 +32525,65 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "t": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "number" + } + }, + "required": [ + "x", + "t", + "y" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -18968,14 +32600,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/property-series/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/property-series/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataStats", + "description": "Get websites website id session data stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataStats", "parameters": [ { "in": "path", @@ -19237,16 +32869,77 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "activity": { + "type": "number" + }, + "events": { + "type": "number" + }, + "label": { + "type": "string" + }, + "sessions": { + "type": "number" + }, + "views": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "label", + "activity", + "sessions", + "visits", + "views", + "events" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -19263,14 +32956,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/session-data/values": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionDataValues", + "description": "Get websites website id session data values. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionDataValues", "parameters": [ { "in": "path", @@ -19524,16 +33217,61 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "total": { + "type": "number" + }, + "value": { + "type": "string" + } + }, + "required": [ + "value", + "total" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -19550,14 +33288,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/session-data/values/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/session-data/values/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessions", + "description": "Get websites website id sessions. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessions", "parameters": [ { "in": "path", @@ -19876,16 +33614,177 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "browser": { + "type": "string" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "events": { + "type": "number" + }, + "firstAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "hostname": { + "type": "string" + }, + "id": { + "type": "string" + }, + "language": { + "type": "string" + }, + "lastAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "os": { + "type": "string" + }, + "region": { + "type": "string" + }, + "screen": { + "type": "string" + }, + "views": { + "type": "number" + }, + "visits": { + "type": "number" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "websiteId", + "hostname", + "browser", + "os", + "device", + "screen", + "language", + "country", + "region", + "city", + "firstAt", + "lastAt", + "visits", + "views", + "events", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -19902,14 +33801,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/{sessionId}": { "delete": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredDeleteWebsitesWebsiteIdSessionsSessionId", + "description": "Delete websites website id sessions session id. The request and response models are derived from the validated route contract.", + "operationId": "deleteWebsitesWebsiteIdSessionsSessionId", "parameters": [ { "in": "path", @@ -19933,20 +33832,70 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Ok" + "properties": { + "ok": { + "const": true + } + }, + "required": [ + "ok" + ], + "type": "object" } } }, "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -19959,12 +33908,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/contract.generated.ts" }, "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsSessionId", + "description": "Get websites website id sessions session id. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsSessionId", "parameters": [ { "in": "path", @@ -19987,16 +33936,54 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "canDelete": {}, + "stitchedSessionCount": {} + }, + "required": [ + "canDelete", + "stitchedSessionCount" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." }, "404": { - "$ref": "#/components/responses/NotFoundResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "not-found", + "message": "Not found.", + "status": 404 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Not found." } }, "security": [ @@ -20013,14 +34000,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/{sessionId}/activity": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsSessionIdActivity", + "description": "Get websites website id sessions session id activity. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsSessionIdActivity", "parameters": [ { "in": "path", @@ -20067,16 +34054,101 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "eventId": { + "type": "string" + }, + "eventName": { + "type": "string" + }, + "eventType": { + "type": "number" + }, + "hasData": { + "type": "boolean" + }, + "hostname": { + "type": "string" + }, + "referrerDomain": { + "type": "string" + }, + "urlPath": { + "type": "string" + }, + "urlQuery": { + "type": "string" + }, + "visitId": { + "type": "string" + } + }, + "required": [ + "createdAt", + "urlPath", + "urlQuery", + "referrerDomain", + "eventId", + "eventType", + "eventName", + "visitId", + "hostname", + "hasData" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -20093,14 +34165,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/{sessionId}/properties": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsSessionIdProperties", + "description": "Get websites website id sessions session id properties. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsSessionIdProperties", "parameters": [ { "in": "path", @@ -20123,13 +34195,84 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "properties": { + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "dataKey": { + "type": "string" + }, + "dataType": { + "type": "number" + }, + "dateValue": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "numberValue": { + "type": "number" + }, + "sessionId": { + "type": "string" + }, + "stringValue": { + "type": "string" + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "websiteId", + "sessionId", + "dataKey", + "dataType", + "stringValue", + "numberValue", + "dateValue", + "createdAt" + ], + "type": "object" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -20146,14 +34289,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/properties/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/properties/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/{sessionId}/replays": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsSessionIdReplays", + "description": "Get websites website id sessions session id replays. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsSessionIdReplays", "parameters": [ { "in": "path", @@ -20273,16 +34416,165 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "browser": { + "type": "string" + }, + "chunkCount": { + "type": "number" + }, + "city": { + "type": "string" + }, + "country": { + "type": "string" + }, + "createdAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "device": { + "type": "string" + }, + "duration": { + "type": "number" + }, + "endedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "eventCount": { + "type": "number" + }, + "id": { + "type": "string" + }, + "os": { + "type": "string" + }, + "sessionId": { + "type": "string" + }, + "startedAt": { + "anyOf": [ + { + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + }, + "websiteId": { + "type": "string" + } + }, + "required": [ + "id", + "sessionId", + "websiteId", + "browser", + "os", + "device", + "country", + "city", + "eventCount", + "chunkCount", + "startedAt", + "endedAt", + "duration", + "createdAt" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -20299,14 +34591,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/replays/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/[sessionId]/replays/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsStats", + "description": "Get websites website id sessions stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsStats", "parameters": [ { "in": "path", @@ -20544,16 +34836,47 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": {}, + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -20570,14 +34893,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/sessions/weekly": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdSessionsWeekly", + "description": "Get websites website id sessions weekly. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdSessionsWeekly", "parameters": [ { "in": "path", @@ -20823,16 +35146,52 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": { + "items": { + "type": "number" + }, + "type": "array" + }, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -20849,14 +35208,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/sessions/weekly/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/sessions/weekly/contract.generated.ts" } }, "/api/websites/{websiteId}/shares": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdShares", + "description": "Get websites website id shares. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdShares", "parameters": [ { "in": "path", @@ -21105,16 +35464,175 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "count": { + "type": "number" + }, + "data": { + "items": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + }, + "type": "array" + }, + "isCapped": { + "type": "boolean" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "number" + }, + "pageSize": { + "type": "number" + }, + "search": { + "type": "string" + }, + "sortDescending": { + "type": "boolean" + } + }, + "required": [ + "data", + "count", + "page", + "pageSize" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21131,12 +35649,12 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/shares/contract.generated.ts" }, "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdShares", + "description": "Create or update websites website id shares. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdShares", "parameters": [ { "in": "path", @@ -21174,16 +35692,140 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "entityId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parameters": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "shareType": { + "type": "number" + }, + "slug": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "name", + "slug", + "parameters", + "entityId", + "shareType" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21196,14 +35838,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/shares/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/shares/contract.generated.ts" } }, "/api/websites/{websiteId}/stats": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdStats", + "description": "Get websites website id stats. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdStats", "parameters": [ { "in": "path", @@ -21487,16 +36129,85 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "comparison": { + "items": { + "properties": { + "bounces": { + "type": "number" + }, + "pageviews": { + "type": "number" + }, + "totaltime": { + "type": "number" + }, + "visitors": { + "type": "number" + }, + "visits": { + "type": "number" + } + }, + "required": [ + "pageviews", + "visitors", + "visits", + "bounces", + "totaltime" + ], + "type": "object" + }, + "type": "array" + }, + "length": { + "type": "number" + } + }, + "required": [ + "comparison", + "length" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21513,14 +36224,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/stats/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/stats/contract.generated.ts" } }, "/api/websites/{websiteId}/transfer": { "post": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredPostWebsitesWebsiteIdTransfer", + "description": "Create or update websites website id transfer. The request and response models are derived from the validated route contract.", + "operationId": "postWebsitesWebsiteIdTransfer", "parameters": [ { "in": "path", @@ -21555,16 +36266,158 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "createdAt": { + "format": "date-time", + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + }, + "domain": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "recorderEnabled": { + "type": "boolean" + }, + "replayConfig": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "const": false + }, + { + "const": true + }, + {}, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "properties": {}, + "type": "object" + }, + { + "properties": { + "length": { + "type": "number" + } + }, + "required": [ + "length" + ], + "type": "object" + } + ] + }, + "resetAt": { + "format": "date-time", + "type": "string" + }, + "teamId": { + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "id", + "userId", + "createdAt", + "updatedAt", + "deletedAt", + "createdBy", + "name", + "domain", + "resetAt", + "teamId", + "recorderEnabled", + "replayConfig" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21577,14 +36430,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/transfer/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/transfer/contract.generated.ts" } }, "/api/websites/{websiteId}/values": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesWebsiteIdValues", + "description": "Get websites website id values. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesWebsiteIdValues", "parameters": [ { "in": "path", @@ -21677,16 +36530,47 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "items": {}, + "type": "array" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21703,14 +36587,14 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/[websiteId]/values/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/[websiteId]/values/contract.generated.ts" } }, "/api/websites/charts": { "get": { - "description": "Generated from the App Router handler and its request-validation source. Add a colocated contract.ts to supply exact response models and curated documentation.", - "operationId": "inferredGetWebsitesCharts", + "description": "Get websites charts. The request and response models are derived from the validated route contract.", + "operationId": "getWebsitesCharts", "parameters": [ { "in": "query", @@ -21749,16 +36633,73 @@ "200": { "content": { "application/json": { - "schema": {} + "schema": { + "properties": { + "data": { + "additionalProperties": { + "properties": { + "total": { + "type": "number" + }, + "values": { + "items": { + "type": "number" + }, + "type": "array" + } + }, + "required": [ + "values", + "total" + ], + "type": "object" + }, + "properties": {}, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" + } } }, - "description": "Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema." + "description": "The operation completed successfully." }, "400": { - "$ref": "#/components/responses/BadRequestResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "bad-request", + "message": "Bad request.", + "status": 400 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Bad request." }, "401": { - "$ref": "#/components/responses/UnauthorizedResponse" + "content": { + "application/json": { + "example": { + "error": { + "code": "unauthorized", + "message": "Unauthorized.", + "status": 401 + } + }, + "schema": { + "$ref": "#/components/schemas/ApiError" + } + } + }, + "description": "Unauthorized." } }, "security": [ @@ -21775,8 +36716,8 @@ "Websites" ], "x-umami-audience": "public", - "x-umami-contract": "inferred", - "x-umami-source": "src/app/api/websites/charts/route.ts" + "x-umami-contract": "explicit", + "x-umami-source": "src/app/api/websites/charts/contract.generated.ts" } } }, diff --git a/scripts/generate-openapi-contracts.ts b/scripts/generate-openapi-contracts.ts new file mode 100644 index 000000000..c03fa6f75 --- /dev/null +++ b/scripts/generate-openapi-contracts.ts @@ -0,0 +1,88 @@ +import { execFile } from 'node:child_process'; +import { rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { promisify } from 'node:util'; +import { loadApiContracts } from '@/openapi/contracts'; +import { discoverApiOperations, discoverContractFiles } from '@/openapi/discover'; +import { buildOpenApiDocument } from '@/openapi/document'; +import { inferApiContracts } from '@/openapi/infer'; +import type { LoadedApiOperationContract } from '@/openapi/operation'; + +const projectRoot = process.cwd(); +const generatedFileName = 'contract.generated.ts'; +const generatedHeader = '// Generated by `pnpm openapi:contracts`. Do not edit directly.'; +const execFileAsync = promisify(execFile); + +const existingGeneratedFiles = (await discoverContractFiles(projectRoot)).filter( + file => path.basename(file) === generatedFileName, +); + +await Promise.all(existingGeneratedFiles.map(file => rm(file))); + +const [explicitContracts, discovered] = await Promise.all([ + loadApiContracts(projectRoot), + discoverApiOperations(projectRoot), +]); +const inferredContracts = inferApiContracts(discovered, explicitContracts); +const { document } = await buildOpenApiDocument('all', projectRoot); +const documentPaths = document.paths ?? {}; +const byRoute = new Map(); +const generatedFiles: string[] = []; + +inferredContracts.forEach(contract => { + byRoute.set(contract.source, [...(byRoute.get(contract.source) ?? []), contract]); +}); + +function serialize(value: unknown) { + return JSON.stringify(value, null, 2); +} + +for (const [routeSource, contracts] of byRoute) { + const routeFile = path.join(projectRoot, ...routeSource.split('/')); + const outputFile = path.join(path.dirname(routeFile), generatedFileName); + const operationDefinitions = contracts.map((contract, index) => { + const generatedOperation = documentPaths[contract.path]?.[contract.method]; + + if (!generatedOperation || typeof generatedOperation !== 'object') { + throw new Error( + `Generated document is missing ${contract.method.toUpperCase()} ${contract.path}.`, + ); + } + + const operation = structuredClone(generatedOperation) as Record; + delete operation.security; + delete operation['x-umami-audience']; + delete operation['x-umami-contract']; + delete operation['x-umami-source']; + + if ( + typeof operation.description === 'string' && + operation.description.startsWith('Generated from') + ) { + operation.description = `${operation.summary}. The request and response models are derived from the validated route contract.`; + } + + return `const operation${index + 1} = defineOperation({\n method: ${serialize(contract.method)},\n path: ${serialize(contract.path)},\n audience: ${serialize(contract.audience)},\n auth: ${serialize(contract.auth)},\n operation: ${serialize(operation)} as ZodOpenApiOperationObject,\n});`; + }); + const exports = contracts.map((_, index) => `operation${index + 1}`).join(', '); + const content = `${generatedHeader}\n\nimport type { ZodOpenApiOperationObject } from 'zod-openapi';\nimport { defineOperation } from '@/openapi/operation';\n\n${operationDefinitions.join('\n\n')}\n\nexport const operations = [${exports}] as const;\n`; + + await writeFile(outputFile, content, 'utf8'); + generatedFiles.push(outputFile); +} + +const formatter = path.join(projectRoot, 'node_modules', '@biomejs', 'biome', 'bin', 'biome'); +for (let index = 0; index < generatedFiles.length; index += 20) { + await execFileAsync(process.execPath, [ + formatter, + 'format', + '--write', + ...generatedFiles.slice(index, index + 20), + ]); +} + +const generatedCount = [...byRoute.values()].reduce( + (total, contracts) => total + contracts.length, + 0, +); +console.log(`Generated ${generatedCount} explicit contracts in ${byRoute.size} route modules.`); diff --git a/src/app/api/2fa/disable/contract.generated.ts b/src/app/api/2fa/disable/contract.generated.ts new file mode 100644 index 000000000..f6b18e74a --- /dev/null +++ b/src/app/api/2fa/disable/contract.generated.ts @@ -0,0 +1,199 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/2fa/disable', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'post2faDisable', + summary: 'Create or update 2fa disable', + description: + 'Create or update 2fa disable. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + password: { + type: 'string', + }, + token: { + type: 'string', + minLength: 6, + maxLength: 6, + }, + }, + required: ['password', 'token'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + required: ['ok'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '403': { + description: 'Forbidden.', + content: { + 'application/json': { + example: { + error: { + message: 'Forbidden.', + code: 'forbidden', + status: 403, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '429': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/2fa/setup/cancel/contract.generated.ts b/src/app/api/2fa/setup/cancel/contract.generated.ts new file mode 100644 index 000000000..983af2d67 --- /dev/null +++ b/src/app/api/2fa/setup/cancel/contract.generated.ts @@ -0,0 +1,72 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/2fa/setup/cancel', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'post2faSetupCancel', + summary: 'Create or update 2fa setup cancel', + description: + 'Create or update 2fa setup cancel. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/2fa/setup/confirm/contract.generated.ts b/src/app/api/2fa/setup/confirm/contract.generated.ts new file mode 100644 index 000000000..7f4eefab5 --- /dev/null +++ b/src/app/api/2fa/setup/confirm/contract.generated.ts @@ -0,0 +1,182 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/2fa/setup/confirm', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'post2faSetupConfirm', + summary: 'Create or update 2fa setup confirm', + description: + 'Create or update 2fa setup confirm. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + token: { + type: 'string', + minLength: 6, + maxLength: 6, + }, + }, + required: ['token'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + { + type: 'object', + properties: { + backupCodes: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + required: ['backupCodes'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '429': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/2fa/setup/initiate/contract.generated.ts b/src/app/api/2fa/setup/initiate/contract.generated.ts new file mode 100644 index 000000000..2024eb32d --- /dev/null +++ b/src/app/api/2fa/setup/initiate/contract.generated.ts @@ -0,0 +1,109 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/2fa/setup/initiate', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'post2faSetupInitiate', + summary: 'Create or update 2fa setup initiate', + description: + 'Create or update 2fa setup initiate. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + qrCodeDataUrl: { + type: 'string', + }, + manualKey: { + type: 'string', + }, + }, + required: ['qrCodeDataUrl', 'manualKey'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/2fa/status/contract.generated.ts b/src/app/api/2fa/status/contract.generated.ts new file mode 100644 index 000000000..2097e6243 --- /dev/null +++ b/src/app/api/2fa/status/contract.generated.ts @@ -0,0 +1,104 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/2fa/status', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'get2faStatus', + summary: 'Get 2fa status', + description: + 'Get 2fa status. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + isEnabled: { + type: 'boolean', + }, + isRequired: { + type: 'boolean', + }, + requiredReason: { + type: 'null', + }, + isConfigured: { + type: 'boolean', + }, + globalRequired: { + type: 'boolean', + }, + }, + required: [ + 'isEnabled', + 'isRequired', + 'requiredReason', + 'isConfigured', + 'globalRequired', + ], + }, + { + type: 'object', + properties: { + isEnabled: { + type: 'boolean', + }, + isRequired: { + type: 'boolean', + }, + requiredReason: { + type: 'string', + }, + isConfigured: { + type: 'boolean', + }, + globalRequired: { + type: 'boolean', + }, + }, + required: [ + 'isEnabled', + 'isRequired', + 'requiredReason', + 'isConfigured', + 'globalRequired', + ], + }, + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/2fa/verify/contract.generated.ts b/src/app/api/2fa/verify/contract.generated.ts new file mode 100644 index 000000000..593abc5c0 --- /dev/null +++ b/src/app/api/2fa/verify/contract.generated.ts @@ -0,0 +1,233 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/2fa/verify', + audience: 'public', + auth: 'none', + operation: { + operationId: 'post2faVerify', + summary: 'Create or update 2fa verify', + description: + 'Create or update 2fa verify. The request and response models are derived from the validated route contract.', + tags: ['Two-factor authentication'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + token: { + type: 'string', + minLength: 6, + maxLength: 6, + }, + }, + required: ['token'], + }, + { + type: 'object', + properties: { + backupCode: { + type: 'string', + minLength: 1, + }, + }, + required: ['backupCode'], + }, + ], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + { + type: 'object', + properties: { + token: { + type: 'string', + }, + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + isAdmin: { + type: 'boolean', + }, + teams: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + logoUrl: { + type: 'string', + }, + name: { + type: 'string', + }, + }, + required: ['id', 'logoUrl', 'name'], + }, + }, + }, + required: ['id', 'username', 'role', 'createdAt', 'isAdmin', 'teams'], + }, + }, + required: ['token', 'user'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '429': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + code: { + type: 'string', + }, + message: { + type: 'string', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['code', 'message', 'lockedUntil'], + }, + }, + required: ['error'], + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/admin/2fa/global/contract.generated.ts b/src/app/api/admin/2fa/global/contract.generated.ts new file mode 100644 index 000000000..4c7adcc96 --- /dev/null +++ b/src/app/api/admin/2fa/global/contract.generated.ts @@ -0,0 +1,123 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/admin/2fa/global', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'postAdmin2faGlobal', + summary: 'Create or update admin 2fa global', + description: + 'Create or update admin 2fa global. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + required: { + type: 'boolean', + }, + }, + required: ['required'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + required: {}, + }, + required: ['ok', 'required'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/admin/teams/[teamId]/2fa/contract.generated.ts b/src/app/api/admin/teams/[teamId]/2fa/contract.generated.ts new file mode 100644 index 000000000..50b00c59b --- /dev/null +++ b/src/app/api/admin/teams/[teamId]/2fa/contract.generated.ts @@ -0,0 +1,136 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/admin/teams/{teamId}/2fa', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'postAdminTeamsTeamId2fa', + summary: 'Create or update admin teams team id 2fa', + description: + 'Create or update admin teams team id 2fa. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + required: { + type: 'boolean', + }, + }, + required: ['required'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + teamId: { + type: 'string', + }, + twoFactorRequired: {}, + }, + required: ['ok', 'teamId', 'twoFactorRequired'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/admin/teams/contract.generated.ts b/src/app/api/admin/teams/contract.generated.ts new file mode 100644 index 000000000..285818771 --- /dev/null +++ b/src/app/api/admin/teams/contract.generated.ts @@ -0,0 +1,189 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/admin/teams', + audience: 'internal', + auth: 'bearer-or-share', + operation: { + operationId: 'getAdminTeams', + summary: 'Get admin teams', + description: + 'Get admin teams. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/admin/users/[userId]/2fa/contract.generated.ts b/src/app/api/admin/users/[userId]/2fa/contract.generated.ts new file mode 100644 index 000000000..17dad9f8f --- /dev/null +++ b/src/app/api/admin/users/[userId]/2fa/contract.generated.ts @@ -0,0 +1,301 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/admin/users/{userId}/2fa', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'deleteAdminUsersUserId2fa', + summary: 'Delete admin users user id 2fa', + description: + 'Delete admin users user id 2fa. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + userId: { + type: 'string', + }, + reset: { + type: 'object', + properties: { + twoFactorAuth: {}, + backupCodes: {}, + otpUsed: {}, + rateLimit: {}, + }, + required: ['twoFactorAuth', 'backupCodes', 'otpUsed', 'rateLimit'], + }, + }, + required: ['ok', 'userId', 'reset'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/admin/users/{userId}/2fa', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'getAdminUsersUserId2fa', + summary: 'Get admin users user id 2fa', + description: + 'Get admin users user id 2fa. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + isEnabled: { + type: 'boolean', + }, + }, + required: ['isEnabled'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/admin/users/{userId}/2fa', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'postAdminUsersUserId2fa', + summary: 'Create or update admin users user id 2fa', + description: + 'Create or update admin users user id 2fa. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + required: { + type: 'boolean', + }, + }, + required: ['required'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + userId: { + type: 'string', + }, + twoFactorRequired: {}, + }, + required: ['ok', 'userId', 'twoFactorRequired'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '503': { + description: 'Service unavailable.', + content: { + 'application/json': { + example: { + error: { + message: 'Service unavailable.', + code: 'service-unavailable', + status: 503, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/admin/users/contract.generated.ts b/src/app/api/admin/users/contract.generated.ts new file mode 100644 index 000000000..92ecba7db --- /dev/null +++ b/src/app/api/admin/users/contract.generated.ts @@ -0,0 +1,178 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/admin/users', + audience: 'internal', + auth: 'bearer-or-share', + operation: { + operationId: 'getAdminUsers', + summary: 'Get admin users', + description: + 'Get admin users. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + twoFactorRequired: { + type: 'boolean', + }, + _count: { + type: 'object', + properties: { + websites: { + type: 'number', + }, + }, + required: ['websites'], + }, + }, + required: ['id', 'username', 'role', 'createdAt', 'twoFactorRequired'], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/admin/websites/contract.generated.ts b/src/app/api/admin/websites/contract.generated.ts new file mode 100644 index 000000000..e0668893b --- /dev/null +++ b/src/app/api/admin/websites/contract.generated.ts @@ -0,0 +1,316 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/admin/websites', + audience: 'internal', + auth: 'bearer-or-share', + operation: { + operationId: 'getAdminWebsites', + summary: 'Get admin websites', + description: + 'Get admin websites. The request and response models are derived from the validated route contract.', + tags: ['Administration'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + { + type: 'object', + properties: { + shareId: { + type: 'string', + }, + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + createUser: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + team: { + type: 'object', + properties: { + members: { + type: 'array', + items: { + type: 'object', + properties: { + userId: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['userId', 'role'], + }, + }, + }, + required: ['members'], + }, + }, + required: ['shareId'], + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/auth/logout/contract.generated.ts b/src/app/api/auth/logout/contract.generated.ts new file mode 100644 index 000000000..628e4844b --- /dev/null +++ b/src/app/api/auth/logout/contract.generated.ts @@ -0,0 +1,55 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/auth/logout', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postAuthLogout', + summary: 'Create or update auth logout', + description: + 'Create or update auth logout. The request and response models are derived from the validated route contract.', + tags: ['Authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/auth/sso/contract.generated.ts b/src/app/api/auth/sso/contract.generated.ts new file mode 100644 index 000000000..4cf457128 --- /dev/null +++ b/src/app/api/auth/sso/contract.generated.ts @@ -0,0 +1,73 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/auth/sso', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postAuthSso', + summary: 'Create or update auth sso', + description: + 'Create or update auth sso. The request and response models are derived from the validated route contract.', + tags: ['Authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + user: {}, + token: { + type: 'string', + }, + }, + required: ['user', 'token'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/auth/subscription/contract.generated.ts b/src/app/api/auth/subscription/contract.generated.ts new file mode 100644 index 000000000..a2e5837e7 --- /dev/null +++ b/src/app/api/auth/subscription/contract.generated.ts @@ -0,0 +1,126 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/auth/subscription', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getAuthSubscription', + summary: 'Get auth subscription', + description: + 'Get auth subscription. The request and response models are derived from the validated route contract.', + tags: ['Authentication'], + parameters: [ + { + name: 'teamId', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + error: { + type: 'object', + properties: { + message: { + type: 'string', + }, + code: { + type: 'string', + }, + status: { + type: 'number', + }, + }, + required: ['message', 'code', 'status'], + }, + }, + required: ['error'], + }, + { + type: 'object', + properties: { + isPro: { + type: 'boolean', + }, + isBusiness: { + type: 'boolean', + }, + isNoBilling: { + type: 'boolean', + }, + hasSubscription: { + type: 'boolean', + }, + unlimitedWebsites: { + type: 'boolean', + }, + }, + required: [ + 'isPro', + 'isBusiness', + 'isNoBilling', + 'hasSubscription', + 'unlimitedWebsites', + ], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/auth/verify/contract.generated.ts b/src/app/api/auth/verify/contract.generated.ts new file mode 100644 index 000000000..f6f5c6a62 --- /dev/null +++ b/src/app/api/auth/verify/contract.generated.ts @@ -0,0 +1,53 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/auth/verify', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postAuthVerify', + summary: 'Create or update auth verify', + description: + 'Create or update auth verify. The request and response models are derived from the validated route contract.', + tags: ['Authentication'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + teams: {}, + }, + required: ['teams'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/batch/contract.generated.ts b/src/app/api/batch/contract.generated.ts new file mode 100644 index 000000000..9b7339bb4 --- /dev/null +++ b/src/app/api/batch/contract.generated.ts @@ -0,0 +1,96 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/batch', + audience: 'collect', + auth: 'none', + operation: { + operationId: 'postBatch', + summary: 'Create or update batch', + description: + 'Create or update batch. The request and response models are derived from the validated route contract.', + tags: ['Collection'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + additionalProperties: true, + }, + maxItems: 500, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + size: {}, + processed: { + type: 'number', + }, + errors: { + type: 'number', + }, + details: { + type: 'array', + items: {}, + }, + cache: {}, + }, + required: ['size', 'processed', 'errors', 'details', 'cache'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/boards/[boardId]/clone/contract.generated.ts b/src/app/api/boards/[boardId]/clone/contract.generated.ts new file mode 100644 index 000000000..db7d31749 --- /dev/null +++ b/src/app/api/boards/[boardId]/clone/contract.generated.ts @@ -0,0 +1,194 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/boards/{boardId}/clone', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postBoardsBoardIdClone', + summary: 'Create or update boards board id clone', + description: + 'Create or update boards board id clone. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + description: { + type: 'string', + maxLength: 500, + }, + parameters: { + type: 'object', + properties: {}, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/boards/[boardId]/contract.generated.ts b/src/app/api/boards/[boardId]/contract.generated.ts new file mode 100644 index 000000000..1c12ae170 --- /dev/null +++ b/src/app/api/boards/[boardId]/contract.generated.ts @@ -0,0 +1,428 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/boards/{boardId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteBoardsBoardId', + summary: 'Delete boards board id', + description: + 'Delete boards board id. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/boards/{boardId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getBoardsBoardId', + summary: 'Get boards board id', + description: + 'Get boards board id. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/boards/{boardId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postBoardsBoardId', + summary: 'Create or update boards board id', + description: + 'Create or update boards board id. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + type: { + anyOf: [ + { + type: 'string', + enum: [], + }, + { + const: 'open', + }, + ], + }, + name: { + type: 'string', + maxLength: 200, + }, + description: { + type: 'string', + maxLength: 500, + }, + parameters: { + type: 'object', + properties: {}, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/boards/[boardId]/shares/contract.generated.ts b/src/app/api/boards/[boardId]/shares/contract.generated.ts new file mode 100644 index 000000000..47410b980 --- /dev/null +++ b/src/app/api/boards/[boardId]/shares/contract.generated.ts @@ -0,0 +1,608 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/boards/{boardId}/shares', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getBoardsBoardIdShares', + summary: 'Get boards board id shares', + description: + 'Get boards board id shares. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/boards/{boardId}/shares', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postBoardsBoardIdShares', + summary: 'Create or update boards board id shares', + description: + 'Create or update boards board id shares. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'boardId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/boards/contract.generated.ts b/src/app/api/boards/contract.generated.ts new file mode 100644 index 000000000..63ec127e1 --- /dev/null +++ b/src/app/api/boards/contract.generated.ts @@ -0,0 +1,469 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/boards', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getBoards', + summary: 'Get boards', + description: + 'Get boards. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/boards', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postBoards', + summary: 'Create or update boards', + description: + 'Create or update boards. The request and response models are derived from the validated route contract.', + tags: ['Boards'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + type: { + anyOf: [ + { + type: 'string', + enum: [], + }, + { + const: 'open', + }, + ], + }, + name: { + type: 'string', + maxLength: 100, + }, + description: { + type: 'string', + maxLength: 500, + }, + userId: { + anyOf: [ + { + type: 'string', + format: 'uuid', + }, + { + type: 'null', + }, + ], + }, + teamId: { + anyOf: [ + { + type: 'string', + format: 'uuid', + }, + { + type: 'null', + }, + ], + }, + parameters: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + pixelId: { + type: 'string', + format: 'uuid', + }, + linkId: { + type: 'string', + format: 'uuid', + }, + }, + }, + }, + required: ['type', 'name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/config/contract.generated.ts b/src/app/api/config/contract.generated.ts new file mode 100644 index 000000000..c984c3e75 --- /dev/null +++ b/src/app/api/config/contract.generated.ts @@ -0,0 +1,72 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/config', + audience: 'internal', + auth: 'none', + operation: { + operationId: 'getConfig', + summary: 'Get config', + description: + 'Get config. The request and response models are derived from the validated route contract.', + tags: ['Configuration'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + cloudMode: { + type: 'boolean', + }, + faviconUrl: { + type: 'string', + }, + linksUrl: { + type: 'string', + }, + pixelsUrl: { + type: 'string', + }, + privateMode: { + type: 'boolean', + }, + sessionDeletionEnabled: { + type: 'boolean', + }, + telemetryDisabled: { + type: 'boolean', + }, + trackerScriptName: { + type: 'string', + }, + updatesDisabled: { + type: 'boolean', + }, + }, + required: [ + 'cloudMode', + 'faviconUrl', + 'linksUrl', + 'pixelsUrl', + 'privateMode', + 'sessionDeletionEnabled', + 'telemetryDisabled', + 'trackerScriptName', + 'updatesDisabled', + ], + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/dashboard/contract.generated.ts b/src/app/api/dashboard/contract.generated.ts new file mode 100644 index 000000000..b41b6da58 --- /dev/null +++ b/src/app/api/dashboard/contract.generated.ts @@ -0,0 +1,321 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/dashboard', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'getDashboard', + summary: 'Get dashboard', + description: + 'Get dashboard. The request and response models are derived from the validated route contract.', + tags: ['Dashboard'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/dashboard', + audience: 'internal', + auth: 'bearer', + operation: { + operationId: 'postDashboard', + summary: 'Create or update dashboard', + description: + 'Create or update dashboard. The request and response models are derived from the validated route contract.', + tags: ['Dashboard'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + description: { + type: 'string', + maxLength: 500, + }, + parameters: { + type: 'object', + properties: {}, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/heartbeat/contract.generated.ts b/src/app/api/heartbeat/contract.generated.ts new file mode 100644 index 000000000..527df82b9 --- /dev/null +++ b/src/app/api/heartbeat/contract.generated.ts @@ -0,0 +1,38 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/heartbeat', + audience: 'internal', + auth: 'none', + operation: { + operationId: 'getHeartbeat', + summary: 'Get heartbeat', + description: + 'Get heartbeat. The request and response models are derived from the validated route contract.', + tags: ['System'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + required: ['ok'], + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/links/[linkId]/contract.generated.ts b/src/app/api/links/[linkId]/contract.generated.ts new file mode 100644 index 000000000..216ede2a9 --- /dev/null +++ b/src/app/api/links/[linkId]/contract.generated.ts @@ -0,0 +1,316 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/links/{linkId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteLinksLinkId', + summary: 'Delete links link id', + description: + 'Delete links link id. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'linkId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/links/{linkId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getLinksLinkId', + summary: 'Get links link id', + description: + 'Get links link id. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'linkId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/links/{linkId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postLinksLinkId', + summary: 'Create or update links link id', + description: + 'Create or update links link id. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'linkId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 100, + }, + url: { + type: 'string', + maxLength: 500, + }, + slug: { + type: 'string', + minLength: 8, + maxLength: 100, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/links/[linkId]/shares/contract.generated.ts b/src/app/api/links/[linkId]/shares/contract.generated.ts new file mode 100644 index 000000000..64a573594 --- /dev/null +++ b/src/app/api/links/[linkId]/shares/contract.generated.ts @@ -0,0 +1,608 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/links/{linkId}/shares', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getLinksLinkIdShares', + summary: 'Get links link id shares', + description: + 'Get links link id shares. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'linkId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/links/{linkId}/shares', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postLinksLinkIdShares', + summary: 'Create or update links link id shares', + description: + 'Create or update links link id shares. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'linkId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/links/charts/contract.generated.ts b/src/app/api/links/charts/contract.generated.ts new file mode 100644 index 000000000..1d2f669f0 --- /dev/null +++ b/src/app/api/links/charts/contract.generated.ts @@ -0,0 +1,122 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/links/charts', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getLinksCharts', + summary: 'Get links charts', + description: + 'Get links charts. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'ids', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'object', + properties: { + values: { + type: 'array', + items: { + type: 'number', + }, + }, + total: { + type: 'number', + }, + }, + required: ['values', 'total'], + }, + }, + }, + required: ['data'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/links/contract.generated.ts b/src/app/api/links/contract.generated.ts new file mode 100644 index 000000000..d0f72ff9b --- /dev/null +++ b/src/app/api/links/contract.generated.ts @@ -0,0 +1,343 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/links', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getLinks', + summary: 'Get links', + description: + 'Get links. The request and response models are derived from the validated route contract.', + tags: ['Links'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/links', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postLinks', + summary: 'Create or update links', + description: + 'Create or update links. The request and response models are derived from the validated route contract.', + tags: ['Links'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 100, + }, + url: { + type: 'string', + maxLength: 500, + }, + slug: { + type: 'string', + minLength: 8, + maxLength: 100, + }, + teamId: { + anyOf: [ + { + type: 'string', + }, + { + type: 'null', + }, + ], + }, + id: { + anyOf: [ + { + type: 'string', + format: 'uuid', + }, + { + type: 'null', + }, + ], + }, + }, + required: ['name', 'url', 'slug'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/me/contract.generated.ts b/src/app/api/me/contract.generated.ts new file mode 100644 index 000000000..8161f3038 --- /dev/null +++ b/src/app/api/me/contract.generated.ts @@ -0,0 +1,141 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/me', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getMe', + summary: 'Get me', + description: + 'Get me. The request and response models are derived from the validated route contract.', + tags: ['Account'], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + isAdmin: { + type: 'boolean', + }, + }, + required: ['id', 'username', 'role', 'isAdmin'], + }, + shareToken: { + type: 'object', + properties: { + shareType: { + type: 'number', + }, + websiteId: { + type: 'string', + }, + websiteIds: { + type: 'array', + items: { + type: 'string', + }, + }, + boardId: { + type: 'string', + }, + pixelId: { + type: 'string', + }, + pixelIds: { + type: 'array', + items: { + type: 'string', + }, + }, + linkId: { + type: 'string', + }, + linkIds: { + type: 'array', + items: { + type: 'string', + }, + }, + parameters: { + type: 'object', + properties: { + allowFilter: { + type: 'boolean', + }, + theme: { + anyOf: [ + { + const: 'light', + }, + { + const: 'dark', + }, + ], + }, + }, + additionalProperties: { + anyOf: [ + { + const: false, + }, + { + const: true, + }, + { + const: 'light', + }, + { + const: 'dark', + }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/me/password/contract.generated.ts b/src/app/api/me/password/contract.generated.ts new file mode 100644 index 000000000..224ba9d5d --- /dev/null +++ b/src/app/api/me/password/contract.generated.ts @@ -0,0 +1,102 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/me/password', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postMePassword', + summary: 'Create or update me password', + description: + 'Create or update me password. The request and response models are derived from the validated route contract.', + tags: ['Account'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + currentPassword: { + type: 'string', + }, + newPassword: { + type: 'string', + minLength: 8, + }, + }, + required: ['currentPassword', 'newPassword'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'username', 'role'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/me/route.ts b/src/app/api/me/route.ts index 59a325525..cb1a23a6e 100644 --- a/src/app/api/me/route.ts +++ b/src/app/api/me/route.ts @@ -1,5 +1,6 @@ import { parseRequest } from '@/lib/request'; import { json } from '@/lib/response'; +import type { Auth } from '@/lib/types'; export async function GET(request: Request) { const { auth, error } = await parseRequest(request); @@ -8,5 +9,5 @@ export async function GET(request: Request) { return error(); } - return json(auth); + return json(auth as Auth); } diff --git a/src/app/api/me/teams/contract.generated.ts b/src/app/api/me/teams/contract.generated.ts new file mode 100644 index 000000000..f672e6d22 --- /dev/null +++ b/src/app/api/me/teams/contract.generated.ts @@ -0,0 +1,181 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/me/teams', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getMeTeams', + summary: 'Get me teams', + description: + 'Get me teams. The request and response models are derived from the validated route contract.', + tags: ['Account'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/me/websites/contract.generated.ts b/src/app/api/me/websites/contract.generated.ts new file mode 100644 index 000000000..cd48dcced --- /dev/null +++ b/src/app/api/me/websites/contract.generated.ts @@ -0,0 +1,316 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/me/websites', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getMeWebsites', + summary: 'Get me websites', + description: + 'Get me websites. The request and response models are derived from the validated route contract.', + tags: ['Account'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + { + name: 'includeTeams', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + { + type: 'object', + properties: { + shareId: { + type: 'string', + }, + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + createUser: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + team: { + type: 'object', + properties: { + members: { + type: 'array', + items: { + type: 'object', + properties: { + userId: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['userId', 'role'], + }, + }, + }, + required: ['members'], + }, + }, + required: ['shareId'], + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/pixels/[pixelId]/contract.generated.ts b/src/app/api/pixels/[pixelId]/contract.generated.ts new file mode 100644 index 000000000..7ac4c777a --- /dev/null +++ b/src/app/api/pixels/[pixelId]/contract.generated.ts @@ -0,0 +1,304 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/pixels/{pixelId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deletePixelsPixelId', + summary: 'Delete pixels pixel id', + description: + 'Delete pixels pixel id. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'pixelId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/pixels/{pixelId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getPixelsPixelId', + summary: 'Get pixels pixel id', + description: + 'Get pixels pixel id. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'pixelId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/pixels/{pixelId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postPixelsPixelId', + summary: 'Create or update pixels pixel id', + description: + 'Create or update pixels pixel id. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'pixelId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 100, + }, + slug: { + type: 'string', + minLength: 8, + maxLength: 100, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/pixels/[pixelId]/shares/contract.generated.ts b/src/app/api/pixels/[pixelId]/shares/contract.generated.ts new file mode 100644 index 000000000..e22389cc3 --- /dev/null +++ b/src/app/api/pixels/[pixelId]/shares/contract.generated.ts @@ -0,0 +1,608 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/pixels/{pixelId}/shares', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getPixelsPixelIdShares', + summary: 'Get pixels pixel id shares', + description: + 'Get pixels pixel id shares. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'pixelId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/pixels/{pixelId}/shares', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postPixelsPixelIdShares', + summary: 'Create or update pixels pixel id shares', + description: + 'Create or update pixels pixel id shares. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'pixelId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/pixels/charts/contract.generated.ts b/src/app/api/pixels/charts/contract.generated.ts new file mode 100644 index 000000000..1752835a3 --- /dev/null +++ b/src/app/api/pixels/charts/contract.generated.ts @@ -0,0 +1,122 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/pixels/charts', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getPixelsCharts', + summary: 'Get pixels charts', + description: + 'Get pixels charts. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'ids', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'object', + properties: { + values: { + type: 'array', + items: { + type: 'number', + }, + }, + total: { + type: 'number', + }, + }, + required: ['values', 'total'], + }, + }, + }, + required: ['data'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/pixels/contract.generated.ts b/src/app/api/pixels/contract.generated.ts new file mode 100644 index 000000000..9f91416e4 --- /dev/null +++ b/src/app/api/pixels/contract.generated.ts @@ -0,0 +1,331 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/pixels', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getPixels', + summary: 'Get pixels', + description: + 'Get pixels. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/pixels', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postPixels', + summary: 'Create or update pixels', + description: + 'Create or update pixels. The request and response models are derived from the validated route contract.', + tags: ['Pixels'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 100, + }, + slug: { + type: 'string', + minLength: 8, + maxLength: 100, + }, + teamId: { + anyOf: [ + { + type: 'string', + }, + { + type: 'null', + }, + ], + }, + id: { + anyOf: [ + { + type: 'string', + format: 'uuid', + }, + { + type: 'null', + }, + ], + }, + }, + required: ['name', 'slug'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/realtime/[websiteId]/contract.generated.ts b/src/app/api/realtime/[websiteId]/contract.generated.ts new file mode 100644 index 000000000..159481128 --- /dev/null +++ b/src/app/api/realtime/[websiteId]/contract.generated.ts @@ -0,0 +1,463 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/realtime/{websiteId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getRealtimeWebsiteId', + summary: 'Get realtime website id', + description: + 'Get realtime website id. The request and response models are derived from the validated route contract.', + tags: ['Realtime'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + countries: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'number', + }, + }, + events: { + type: 'array', + items: { + type: 'object', + properties: { + __type: { + anyOf: [ + { + const: 'event', + }, + { + const: 'session', + }, + { + const: 'pageview', + }, + ], + }, + sessionId: { + type: 'string', + }, + eventName: { + type: 'string', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + country: { + type: 'string', + }, + urlPath: { + type: 'string', + }, + referrerDomain: { + type: 'string', + }, + hostname: { + type: 'string', + }, + }, + required: [ + '__type', + 'sessionId', + 'eventName', + 'createdAt', + 'browser', + 'os', + 'device', + 'country', + 'urlPath', + 'referrerDomain', + 'hostname', + ], + }, + }, + referrers: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'number', + }, + }, + timestamp: { + type: 'number', + }, + series: { + type: 'object', + properties: { + views: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + visitors: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + required: ['views', 'visitors'], + }, + totals: { + type: 'object', + properties: { + views: { + type: 'number', + }, + visitors: { + type: 'number', + }, + events: { + type: 'number', + }, + countries: { + type: 'number', + }, + }, + required: ['views', 'visitors', 'events', 'countries'], + }, + urls: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'number', + }, + }, + }, + required: [ + 'countries', + 'events', + 'referrers', + 'timestamp', + 'series', + 'totals', + 'urls', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/record/contract.generated.ts b/src/app/api/record/contract.generated.ts new file mode 100644 index 000000000..ed3055f48 --- /dev/null +++ b/src/app/api/record/contract.generated.ts @@ -0,0 +1,268 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/record', + audience: 'collect', + auth: 'none', + operation: { + operationId: 'postRecord', + summary: 'Create or update record', + description: + 'Create or update record. The request and response models are derived from the validated route contract.', + tags: ['Collection'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + type: { + const: 'record', + }, + payload: { + type: 'object', + properties: { + website: { + type: 'string', + format: 'uuid', + }, + events: { + type: 'array', + items: {}, + maxItems: 200, + }, + timestamp: { + type: 'integer', + }, + }, + required: ['website', 'events'], + }, + }, + required: ['type', 'payload'], + }, + { + type: 'object', + properties: { + type: { + const: 'heatmap', + }, + payload: { + type: 'object', + properties: { + website: { + type: 'string', + format: 'uuid', + }, + events: { + type: 'array', + items: { + anyOf: [ + { + type: 'object', + properties: { + type: { + const: 'click', + }, + url: { + type: 'string', + }, + x: { + type: 'number', + }, + y: { + type: 'number', + }, + pageX: { + type: 'number', + }, + pageY: { + type: 'number', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + timestamp: { + type: 'integer', + }, + }, + required: ['type', 'url'], + }, + { + type: 'object', + properties: { + type: { + const: 'scroll', + }, + url: { + type: 'string', + }, + scrollPct: { + type: 'number', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + timestamp: { + type: 'integer', + }, + }, + required: ['type', 'url'], + }, + ], + }, + maxItems: 200, + }, + timestamp: { + type: 'integer', + }, + }, + required: ['website', 'events'], + }, + }, + required: ['type', 'payload'], + }, + ], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + required: ['ok'], + }, + { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + reason: { + type: 'string', + }, + }, + required: ['ok', 'reason'], + }, + { + type: 'object', + properties: { + beep: { + type: 'string', + }, + }, + required: ['beep'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '403': { + description: 'Forbidden.', + content: { + 'application/json': { + example: { + error: { + message: 'Forbidden.', + code: 'forbidden', + status: 403, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '413': { + description: 'Payload too large.', + content: { + 'application/json': { + example: { + error: { + message: 'Payload too large.', + code: 'payload-too-large', + status: 413, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/[reportId]/contract.generated.ts b/src/app/api/reports/[reportId]/contract.generated.ts new file mode 100644 index 000000000..2339cb252 --- /dev/null +++ b/src/app/api/reports/[reportId]/contract.generated.ts @@ -0,0 +1,459 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/reports/{reportId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteReportsReportId', + summary: 'Delete reports report id', + description: + 'Delete reports report id. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + parameters: [ + { + name: 'reportId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/reports/{reportId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getReportsReportId', + summary: 'Get reports report id', + description: + 'Get reports report id. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + parameters: [ + { + name: 'reportId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/reports/{reportId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postReportsReportId', + summary: 'Create or update reports report id', + description: + 'Create or update reports report id. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + parameters: [ + { + name: 'reportId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + type: { + type: 'string', + }, + name: { + type: 'string', + maxLength: 200, + }, + description: { + type: 'string', + maxLength: 500, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'type', 'name', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/reports/attribution/contract.generated.ts b/src/app/api/reports/attribution/contract.generated.ts new file mode 100644 index 000000000..92afbf1b6 --- /dev/null +++ b/src/app/api/reports/attribution/contract.generated.ts @@ -0,0 +1,226 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/attribution', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsAttribution', + summary: 'Create or update reports attribution', + description: + 'Create or update reports attribution. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + referrer: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + paidAds: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + utm_source: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + utm_medium: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + utm_campaign: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + utm_content: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + utm_term: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + total: { + type: 'object', + properties: { + pageviews: { + type: 'number', + }, + visitors: { + type: 'number', + }, + visits: { + type: 'number', + }, + }, + required: ['pageviews', 'visitors', 'visits'], + }, + }, + required: [ + 'referrer', + 'paidAds', + 'utm_source', + 'utm_medium', + 'utm_campaign', + 'utm_content', + 'utm_term', + 'total', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/breakdown/contract.generated.ts b/src/app/api/reports/breakdown/contract.generated.ts new file mode 100644 index 000000000..9433fce61 --- /dev/null +++ b/src/app/api/reports/breakdown/contract.generated.ts @@ -0,0 +1,125 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/breakdown', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsBreakdown', + summary: 'Create or update reports breakdown', + description: + 'Create or update reports breakdown. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + views: { + type: 'number', + }, + visitors: { + type: 'number', + }, + visits: { + type: 'number', + }, + bounces: { + type: 'number', + }, + totaltime: { + type: 'number', + }, + }, + required: ['views', 'visitors', 'visits', 'bounces', 'totaltime'], + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + ], + }, + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/contract.generated.ts b/src/app/api/reports/contract.generated.ts new file mode 100644 index 000000000..d7aca97fc --- /dev/null +++ b/src/app/api/reports/contract.generated.ts @@ -0,0 +1,443 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/reports', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getReports', + summary: 'Get reports', + description: + 'Get reports. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + parameters: [ + { + name: 'websiteId', + in: 'query', + required: true, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'type', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + { + type: 'object', + properties: { + website: { + type: 'object', + properties: { + domain: { + type: 'string', + }, + userId: { + type: 'string', + }, + }, + required: ['domain', 'userId'], + }, + }, + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/reports', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postReports', + summary: 'Create or update reports', + description: + 'Create or update reports. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + type: { + type: 'string', + }, + name: { + type: 'string', + maxLength: 200, + }, + description: { + type: 'string', + maxLength: 500, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'type', 'name', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/reports/funnel/contract.generated.ts b/src/app/api/reports/funnel/contract.generated.ts new file mode 100644 index 000000000..c0b6267a3 --- /dev/null +++ b/src/app/api/reports/funnel/contract.generated.ts @@ -0,0 +1,147 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/funnel', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsFunnel', + summary: 'Create or update reports funnel', + description: + 'Create or update reports funnel. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + visitors: { + type: 'number', + }, + previous: { + type: 'number', + }, + dropped: { + type: 'number', + }, + dropoff: { + type: 'number', + }, + remaining: { + type: 'number', + }, + type: { + type: 'string', + }, + value: { + type: 'string', + }, + filters: { + type: 'array', + items: { + type: 'object', + properties: { + property: { + type: 'string', + }, + operator: { + type: 'string', + }, + value: { + type: 'string', + }, + }, + required: ['property', 'operator', 'value'], + }, + }, + }, + required: [ + 'visitors', + 'previous', + 'dropped', + 'dropoff', + 'remaining', + 'type', + 'value', + ], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/goal/contract.generated.ts b/src/app/api/reports/goal/contract.generated.ts new file mode 100644 index 000000000..870698ae6 --- /dev/null +++ b/src/app/api/reports/goal/contract.generated.ts @@ -0,0 +1,103 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/goal', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsGoal', + summary: 'Create or update reports goal', + description: + 'Create or update reports goal. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + num: { + type: 'number', + }, + total: { + type: 'number', + }, + }, + required: ['num', 'total'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/heatmap/contract.generated.ts b/src/app/api/reports/heatmap/contract.generated.ts new file mode 100644 index 000000000..01ed553f1 --- /dev/null +++ b/src/app/api/reports/heatmap/contract.generated.ts @@ -0,0 +1,253 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/heatmap', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsHeatmap', + summary: 'Create or update reports heatmap', + description: + 'Create or update reports heatmap. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + mode: { + anyOf: [ + { + const: 'click', + }, + { + const: 'scroll', + }, + ], + }, + pages: { + type: 'array', + items: { + type: 'object', + properties: { + urlPath: { + type: 'string', + }, + count: { + type: 'number', + }, + sessions: { + type: 'number', + }, + }, + required: ['urlPath', 'count', 'sessions'], + }, + }, + points: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'number', + }, + y: { + type: 'number', + }, + pageX: { + type: 'number', + }, + pageY: { + type: 'number', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + count: { + type: 'number', + }, + }, + required: [ + 'x', + 'y', + 'pageX', + 'pageY', + 'pageW', + 'pageH', + 'viewportW', + 'viewportH', + 'count', + ], + }, + }, + snapshot: { + type: 'object', + properties: { + kind: { + const: 'iframe', + }, + id: { + type: 'string', + }, + url: { + type: 'string', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + }, + required: ['kind', 'id', 'url', 'pageW', 'pageH', 'viewportW', 'viewportH'], + }, + scroll: { + type: 'object', + properties: { + buckets: { + type: 'array', + items: { + type: 'object', + properties: { + depth: { + type: 'number', + }, + sessions: { + type: 'number', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + }, + required: ['depth', 'sessions', 'pageW', 'pageH', 'viewportW', 'viewportH'], + }, + }, + totalSessions: { + type: 'number', + }, + pageW: { + type: 'number', + }, + pageH: { + type: 'number', + }, + viewportW: { + type: 'number', + }, + viewportH: { + type: 'number', + }, + }, + required: [ + 'buckets', + 'totalSessions', + 'pageW', + 'pageH', + 'viewportW', + 'viewportH', + ], + }, + }, + required: ['mode', 'pages', 'points', 'snapshot', 'scroll'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/journey/contract.generated.ts b/src/app/api/reports/journey/contract.generated.ts new file mode 100644 index 000000000..af89a7a6c --- /dev/null +++ b/src/app/api/reports/journey/contract.generated.ts @@ -0,0 +1,124 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/journey', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsJourney', + summary: 'Create or update reports journey', + description: + 'Create or update reports journey. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + e1: { + type: 'string', + }, + e2: { + type: 'string', + }, + e3: { + type: 'string', + }, + e4: { + type: 'string', + }, + e5: { + type: 'string', + }, + e6: { + type: 'string', + }, + e7: { + type: 'string', + }, + count: { + type: 'number', + }, + }, + required: ['e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'count'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/performance/contract.generated.ts b/src/app/api/reports/performance/contract.generated.ts new file mode 100644 index 000000000..95addcbe4 --- /dev/null +++ b/src/app/api/reports/performance/contract.generated.ts @@ -0,0 +1,103 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/performance', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsPerformance', + summary: 'Create or update reports performance', + description: + 'Create or update reports performance. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + chart: {}, + summary: {}, + pages: {}, + pageTitles: {}, + devices: {}, + browsers: {}, + }, + required: ['chart', 'summary', 'pages', 'pageTitles', 'devices', 'browsers'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/retention/contract.generated.ts b/src/app/api/reports/retention/contract.generated.ts new file mode 100644 index 000000000..b848b58a6 --- /dev/null +++ b/src/app/api/reports/retention/contract.generated.ts @@ -0,0 +1,115 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/retention', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsRetention', + summary: 'Create or update reports retention', + description: + 'Create or update reports retention. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + date: { + type: 'string', + }, + day: { + type: 'number', + }, + visitors: { + type: 'number', + }, + returnVisitors: { + type: 'number', + }, + percentage: { + type: 'number', + }, + }, + required: ['date', 'day', 'visitors', 'returnVisitors', 'percentage'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/revenue/contract.generated.ts b/src/app/api/reports/revenue/contract.generated.ts new file mode 100644 index 000000000..6be50608e --- /dev/null +++ b/src/app/api/reports/revenue/contract.generated.ts @@ -0,0 +1,182 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/revenue', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsRevenue', + summary: 'Create or update reports revenue', + description: + 'Create or update reports revenue. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + chart: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + count: { + type: 'number', + }, + }, + required: ['x', 't', 'y', 'count'], + }, + }, + total: {}, + country: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + region: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + country: { + type: 'string', + }, + }, + required: ['name', 'value', 'country'], + }, + }, + referrer: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + channel: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + }, + required: ['chart', 'total', 'country', 'region', 'referrer', 'channel'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/reports/utm/contract.generated.ts b/src/app/api/reports/utm/contract.generated.ts new file mode 100644 index 000000000..32a5b87a7 --- /dev/null +++ b/src/app/api/reports/utm/contract.generated.ts @@ -0,0 +1,117 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/reports/utm', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'postReportsUtm', + summary: 'Create or update reports utm', + description: + 'Create or update reports utm. The request and response models are derived from the validated route contract.', + tags: ['Reports'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + websiteId: { + type: 'string', + format: 'uuid', + }, + filters: { + type: 'object', + additionalProperties: true, + }, + type: { + type: 'string', + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['websiteId', 'filters', 'type', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + utm_source: { + type: 'array', + items: {}, + }, + utm_medium: { + type: 'array', + items: {}, + }, + utm_campaign: { + type: 'array', + items: {}, + }, + utm_term: { + type: 'array', + items: {}, + }, + utm_content: { + type: 'array', + items: {}, + }, + }, + required: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/scripts/telemetry/contract.generated.ts b/src/app/api/scripts/telemetry/contract.generated.ts new file mode 100644 index 000000000..8dbb1e8f9 --- /dev/null +++ b/src/app/api/scripts/telemetry/contract.generated.ts @@ -0,0 +1,33 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/scripts/telemetry', + audience: 'internal', + auth: 'none', + operation: { + operationId: 'getScriptsTelemetry', + summary: 'Get scripts telemetry', + description: + 'Get scripts telemetry. The request and response models are derived from the validated route contract.', + tags: ['Scripts'], + responses: { + '200': { + description: + 'Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema.', + content: { + 'text/javascript': { + schema: { + type: 'string', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/send/contract.generated.ts b/src/app/api/send/contract.generated.ts new file mode 100644 index 000000000..7546744d6 --- /dev/null +++ b/src/app/api/send/contract.generated.ts @@ -0,0 +1,206 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/send', + audience: 'collect', + auth: 'none', + operation: { + operationId: 'postSend', + summary: 'Create or update send', + description: + 'Create or update send. The request and response models are derived from the validated route contract.', + tags: ['Collection'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + type: { + type: 'string', + enum: ['event', 'identify', 'performance'], + }, + payload: { + type: 'object', + properties: { + website: { + type: 'string', + format: 'uuid', + }, + link: { + type: 'string', + format: 'uuid', + }, + pixel: { + type: 'string', + format: 'uuid', + }, + data: { + type: 'object', + additionalProperties: true, + }, + hostname: { + type: 'string', + }, + language: { + type: 'string', + }, + referrer: { + type: 'string', + }, + screen: { + type: 'string', + }, + title: { + type: 'string', + }, + url: { + type: 'string', + }, + name: {}, + tag: {}, + ip: { + type: 'string', + }, + userAgent: { + type: 'string', + }, + timestamp: { + type: 'integer', + }, + id: { + type: 'string', + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + lcp: { + type: 'number', + minimum: 0, + maximum: 60000, + }, + inp: { + type: 'number', + minimum: 0, + maximum: 60000, + }, + cls: { + type: 'number', + minimum: 0, + maximum: 100, + }, + fcp: { + type: 'number', + minimum: 0, + maximum: 60000, + }, + ttfb: { + type: 'number', + minimum: 0, + maximum: 60000, + }, + }, + }, + }, + required: ['type', 'payload'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + beep: { + type: 'string', + }, + }, + required: ['beep'], + }, + { + type: 'object', + properties: { + cache: {}, + sessionId: {}, + visitId: {}, + }, + required: ['cache', 'sessionId', 'visitId'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '403': { + description: 'Forbidden.', + content: { + 'application/json': { + example: { + error: { + message: 'Forbidden.', + code: 'forbidden', + status: 403, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '500': { + description: 'Server error.', + content: { + 'application/json': { + example: { + error: { + message: 'Server error.', + code: 'server-error', + status: 500, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/share/[slug]/contract.generated.ts b/src/app/api/share/[slug]/contract.generated.ts new file mode 100644 index 000000000..15dda7e8f --- /dev/null +++ b/src/app/api/share/[slug]/contract.generated.ts @@ -0,0 +1,61 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/share/{slug}', + audience: 'public', + auth: 'none', + operation: { + operationId: 'getShareSlug', + summary: 'Get share slug', + description: + 'Get share slug. The request and response models are derived from the validated route contract.', + tags: ['Shares'], + parameters: [ + { + name: 'slug', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: {}, + additionalProperties: {}, + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/share/contract.generated.ts b/src/app/api/share/contract.generated.ts new file mode 100644 index 000000000..409962472 --- /dev/null +++ b/src/app/api/share/contract.generated.ts @@ -0,0 +1,188 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/share', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postShare', + summary: 'Create or update share', + description: + 'Create or update share. The request and response models are derived from the validated route contract.', + tags: ['Shares'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + entityId: { + type: 'string', + format: 'uuid', + }, + shareType: { + type: 'integer', + }, + name: { + type: 'string', + maxLength: 200, + }, + slug: { + type: 'string', + maxLength: 100, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['entityId', 'shareType', 'name', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/share/id/[shareId]/contract.generated.ts b/src/app/api/share/id/[shareId]/contract.generated.ts new file mode 100644 index 000000000..d6436c9cb --- /dev/null +++ b/src/app/api/share/id/[shareId]/contract.generated.ts @@ -0,0 +1,410 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/share/id/{shareId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteShareIdShareId', + summary: 'Delete share id share id', + description: + 'Delete share id share id. The request and response models are derived from the validated route contract.', + tags: ['Shares'], + parameters: [ + { + name: 'shareId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/share/id/{shareId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getShareIdShareId', + summary: 'Get share id share id', + description: + 'Get share id share id. The request and response models are derived from the validated route contract.', + tags: ['Shares'], + parameters: [ + { + name: 'shareId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/share/id/{shareId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postShareIdShareId', + summary: 'Create or update share id share id', + description: + 'Create or update share id share id. The request and response models are derived from the validated route contract.', + tags: ['Shares'], + parameters: [ + { + name: 'shareId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + slug: { + type: 'string', + maxLength: 100, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['name', 'slug', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/teams/[teamId]/boards/contract.generated.ts b/src/app/api/teams/[teamId]/boards/contract.generated.ts new file mode 100644 index 000000000..1620ab25d --- /dev/null +++ b/src/app/api/teams/[teamId]/boards/contract.generated.ts @@ -0,0 +1,252 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/boards', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamIdBoards', + summary: 'Get teams team id boards', + description: + 'Get teams team id boards. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/teams/[teamId]/contract.generated.ts b/src/app/api/teams/[teamId]/contract.generated.ts new file mode 100644 index 000000000..6e2f7826e --- /dev/null +++ b/src/app/api/teams/[teamId]/contract.generated.ts @@ -0,0 +1,303 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/teams/{teamId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteTeamsTeamId', + summary: 'Delete teams team id', + description: + 'Delete teams team id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamId', + summary: 'Get teams team id', + description: + 'Get teams team id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/teams/{teamId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postTeamsTeamId', + summary: 'Create or update teams team id', + description: + 'Create or update teams team id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 50, + }, + accessCode: { + type: 'string', + maxLength: 50, + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/teams/[teamId]/links/contract.generated.ts b/src/app/api/teams/[teamId]/links/contract.generated.ts new file mode 100644 index 000000000..22620ade9 --- /dev/null +++ b/src/app/api/teams/[teamId]/links/contract.generated.ts @@ -0,0 +1,201 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/links', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamIdLinks', + summary: 'Get teams team id links', + description: + 'Get teams team id links. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/teams/[teamId]/pixels/contract.generated.ts b/src/app/api/teams/[teamId]/pixels/contract.generated.ts new file mode 100644 index 000000000..3fc019da1 --- /dev/null +++ b/src/app/api/teams/[teamId]/pixels/contract.generated.ts @@ -0,0 +1,197 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/pixels', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamIdPixels', + summary: 'Get teams team id pixels', + description: + 'Get teams team id pixels. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts b/src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts new file mode 100644 index 000000000..0152e5b8f --- /dev/null +++ b/src/app/api/teams/[teamId]/users/[userId]/contract.generated.ts @@ -0,0 +1,292 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/teams/{teamId}/users/{userId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteTeamsTeamIdUsersUserId', + summary: 'Delete teams team id users user id', + description: + 'Delete teams team id users user id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/users/{userId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getTeamsTeamIdUsersUserId', + summary: 'Get teams team id users user id', + description: + 'Get teams team id users user id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/teams/{teamId}/users/{userId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postTeamsTeamIdUsersUserId', + summary: 'Create or update teams team id users user id', + description: + 'Create or update teams team id users user id. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + role: { + type: 'string', + enum: ['team-member', 'team-view-only', 'team-manager'], + }, + }, + required: ['role'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/teams/[teamId]/users/contract.generated.ts b/src/app/api/teams/[teamId]/users/contract.generated.ts new file mode 100644 index 000000000..8078d6491 --- /dev/null +++ b/src/app/api/teams/[teamId]/users/contract.generated.ts @@ -0,0 +1,299 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/users', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamIdUsers', + summary: 'Get teams team id users', + description: + 'Get teams team id users. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + { + type: 'object', + properties: { + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + }, + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/teams/{teamId}/users', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postTeamsTeamIdUsers', + summary: 'Create or update teams team id users', + description: + 'Create or update teams team id users. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid', + }, + role: { + type: 'string', + enum: ['team-member', 'team-view-only', 'team-manager'], + }, + }, + required: ['userId', 'role'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/teams/[teamId]/websites/contract.generated.ts b/src/app/api/teams/[teamId]/websites/contract.generated.ts new file mode 100644 index 000000000..c154bed73 --- /dev/null +++ b/src/app/api/teams/[teamId]/websites/contract.generated.ts @@ -0,0 +1,324 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams/{teamId}/websites', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getTeamsTeamIdWebsites', + summary: 'Get teams team id websites', + description: + 'Get teams team id websites. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'teamId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + { + type: 'object', + properties: { + shareId: { + type: 'string', + }, + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + createUser: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + team: { + type: 'object', + properties: { + members: { + type: 'array', + items: { + type: 'object', + properties: { + userId: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['userId', 'role'], + }, + }, + }, + required: ['members'], + }, + }, + required: ['shareId'], + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/teams/contract.generated.ts b/src/app/api/teams/contract.generated.ts new file mode 100644 index 000000000..7b3da6063 --- /dev/null +++ b/src/app/api/teams/contract.generated.ts @@ -0,0 +1,334 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/teams', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getTeams', + summary: 'Get teams', + description: + 'Get teams. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + parameters: [ + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/teams', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postTeams', + summary: 'Create or update teams', + description: + 'Create or update teams. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 50, + }, + ownerId: { + type: 'string', + format: 'uuid', + }, + }, + required: ['name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + prefixItems: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + ], + minItems: 2, + maxItems: 2, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/teams/join/contract.generated.ts b/src/app/api/teams/join/contract.generated.ts new file mode 100644 index 000000000..21654f42b --- /dev/null +++ b/src/app/api/teams/join/contract.generated.ts @@ -0,0 +1,123 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/teams/join', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postTeamsJoin', + summary: 'Create or update teams join', + description: + 'Create or update teams join. The request and response models are derived from the validated route contract.', + tags: ['Teams'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + accessCode: { + type: 'string', + maxLength: 50, + }, + }, + required: ['accessCode'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/users/[userId]/contract.generated.ts b/src/app/api/users/[userId]/contract.generated.ts new file mode 100644 index 000000000..107841d5a --- /dev/null +++ b/src/app/api/users/[userId]/contract.generated.ts @@ -0,0 +1,1002 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/users/{userId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteUsersUserId', + summary: 'Delete users user id', + description: + 'Delete users user id. The request and response models are derived from the validated route contract.', + tags: ['Users'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/users/{userId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getUsersUserId', + summary: 'Get users user id', + description: + 'Get users user id. The request and response models are derived from the validated route contract.', + tags: ['Users'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + twoFactorAuth: { + type: 'object', + properties: { + isEnabled: { + type: 'boolean', + }, + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + secret: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + }, + required: ['isEnabled', 'id', 'userId', 'secret', 'createdAt', 'updatedAt'], + }, + twoFactorRateLimit: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + attempts: { + type: 'number', + }, + lockedUntil: { + type: 'string', + format: 'date-time', + }, + }, + required: ['id', 'userId', 'updatedAt', 'attempts', 'lockedUntil'], + }, + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + username: { + type: 'string', + }, + password: { + type: 'string', + }, + role: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + websites: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + }, + createdBy: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + }, + links: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + url: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'url', + 'slug', + ], + }, + }, + pixels: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + slug: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'name', + 'teamId', + 'slug', + ], + }, + }, + teams: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + role: { + type: 'string', + }, + teamId: { + type: 'string', + }, + }, + required: ['id', 'userId', 'createdAt', 'updatedAt', 'role', 'teamId'], + }, + }, + reports: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + }, + boards: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + teamId: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'teamId', + 'type', + 'description', + 'parameters', + ], + }, + }, + twoFactorBackupCodes: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + codeHash: { + type: 'string', + }, + used: { + type: 'boolean', + }, + }, + required: ['id', 'userId', 'createdAt', 'codeHash', 'used'], + }, + }, + twoFactorOtpUseds: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + otp: { + type: 'string', + }, + expiresAt: { + type: 'string', + format: 'date-time', + }, + }, + required: ['id', 'userId', 'otp', 'expiresAt'], + }, + }, + _count: { + type: 'object', + properties: { + websites: { + type: 'number', + }, + createdBy: { + type: 'number', + }, + links: { + type: 'number', + }, + pixels: { + type: 'number', + }, + teams: { + type: 'number', + }, + reports: { + type: 'number', + }, + boards: { + type: 'number', + }, + twoFactorAuth: { + type: 'number', + }, + twoFactorBackupCodes: { + type: 'number', + }, + twoFactorOtpUseds: { + type: 'number', + }, + twoFactorRateLimit: { + type: 'number', + }, + }, + required: [ + 'websites', + 'createdBy', + 'links', + 'pixels', + 'teams', + 'reports', + 'boards', + 'twoFactorAuth', + 'twoFactorBackupCodes', + 'twoFactorOtpUseds', + 'twoFactorRateLimit', + ], + }, + }, + required: [ + 'twoFactorAuth', + 'twoFactorRateLimit', + 'id', + 'createdAt', + 'username', + 'password', + 'role', + 'twoFactorRequired', + 'websites', + 'createdBy', + 'links', + 'pixels', + 'teams', + 'reports', + 'boards', + 'twoFactorBackupCodes', + 'twoFactorOtpUseds', + '_count', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/users/{userId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postUsersUserId', + summary: 'Create or update users user id', + description: + 'Create or update users user id. The request and response models are derived from the validated route contract.', + tags: ['Users'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + username: { + type: 'string', + maxLength: 255, + }, + password: { + type: 'string', + minLength: 8, + maxLength: 255, + }, + role: { + type: 'string', + enum: ['admin', 'user', 'view-only'], + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'username', 'role'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/users/[userId]/teams/contract.generated.ts b/src/app/api/users/[userId]/teams/contract.generated.ts new file mode 100644 index 000000000..5e910934b --- /dev/null +++ b/src/app/api/users/[userId]/teams/contract.generated.ts @@ -0,0 +1,189 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/users/{userId}/teams', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getUsersUserIdTeams', + summary: 'Get users user id teams', + description: + 'Get users user id teams. The request and response models are derived from the validated route contract.', + tags: ['Users'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + logoUrl: { + type: 'string', + }, + twoFactorRequired: { + type: 'boolean', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + accessCode: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'logoUrl', + 'twoFactorRequired', + 'deletedAt', + 'name', + 'accessCode', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/users/[userId]/websites/contract.generated.ts b/src/app/api/users/[userId]/websites/contract.generated.ts new file mode 100644 index 000000000..fff246679 --- /dev/null +++ b/src/app/api/users/[userId]/websites/contract.generated.ts @@ -0,0 +1,332 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/users/{userId}/websites', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'getUsersUserIdWebsites', + summary: 'Get users user id websites', + description: + 'Get users user id websites. The request and response models are derived from the validated route contract.', + tags: ['Users'], + parameters: [ + { + name: 'userId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'orderBy', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'sortDescending', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['true', 'false'], + }, + }, + { + name: 'includeTeams', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + { + type: 'object', + properties: { + shareId: { + type: 'string', + }, + user: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + createUser: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + }, + required: ['id', 'username'], + }, + team: { + type: 'object', + properties: { + members: { + type: 'array', + items: { + type: 'object', + properties: { + userId: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['userId', 'role'], + }, + }, + }, + required: ['members'], + }, + }, + required: ['shareId'], + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/users/contract.generated.ts b/src/app/api/users/contract.generated.ts new file mode 100644 index 000000000..10b3472da --- /dev/null +++ b/src/app/api/users/contract.generated.ts @@ -0,0 +1,108 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/users', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postUsers', + summary: 'Create or update users', + description: + 'Create or update users. The request and response models are derived from the validated route contract.', + tags: ['Users'], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + format: 'uuid', + }, + username: { + type: 'string', + maxLength: 255, + }, + password: { + type: 'string', + minLength: 8, + maxLength: 255, + }, + role: { + type: 'string', + enum: ['admin', 'user', 'view-only'], + }, + }, + required: ['username', 'password', 'role'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + username: { + type: 'string', + }, + role: { + type: 'string', + }, + }, + required: ['id', 'username', 'role'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/active/contract.generated.ts b/src/app/api/websites/[websiteId]/active/contract.generated.ts new file mode 100644 index 000000000..75f5e57f8 --- /dev/null +++ b/src/app/api/websites/[websiteId]/active/contract.generated.ts @@ -0,0 +1,65 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/active', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdActive', + summary: 'Get websites website id active', + description: + 'Get websites website id active. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + visitors: { + type: 'number', + }, + }, + required: ['visitors'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts b/src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts new file mode 100644 index 000000000..40d2d559a --- /dev/null +++ b/src/app/api/websites/[websiteId]/annotations/[annotationId]/contract.generated.ts @@ -0,0 +1,366 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/websites/{websiteId}/annotations/{annotationId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteWebsitesWebsiteIdAnnotationsAnnotationId', + summary: 'Delete websites website id annotations annotation id', + description: + 'Delete websites website id annotations annotation id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'annotationId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/annotations/{annotationId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdAnnotationsAnnotationId', + summary: 'Get websites website id annotations annotation id', + description: + 'Get websites website id annotations annotation id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'annotationId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + websiteId: { + type: 'string', + }, + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'websiteId', + 'date', + 'allDay', + 'note', + ], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/annotations/{annotationId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdAnnotationsAnnotationId', + summary: 'Create or update websites website id annotations annotation id', + description: + 'Create or update websites website id annotations annotation id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'annotationId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + minLength: 1, + maxLength: 500, + }, + }, + required: ['date', 'note'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + websiteId: { + type: 'string', + }, + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'websiteId', + 'date', + 'allDay', + 'note', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/websites/[websiteId]/annotations/contract.generated.ts b/src/app/api/websites/[websiteId]/annotations/contract.generated.ts new file mode 100644 index 000000000..6fc09be69 --- /dev/null +++ b/src/app/api/websites/[websiteId]/annotations/contract.generated.ts @@ -0,0 +1,330 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/annotations', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdAnnotations', + summary: 'Get websites website id annotations', + description: + 'Get websites website id annotations. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + websiteId: { + type: 'string', + }, + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'websiteId', + 'date', + 'allDay', + 'note', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/annotations', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdAnnotations', + summary: 'Create or update websites website id annotations', + description: + 'Create or update websites website id annotations. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + minLength: 1, + maxLength: 500, + }, + }, + required: ['date', 'note'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + websiteId: { + type: 'string', + }, + date: { + type: 'string', + format: 'date-time', + }, + allDay: { + type: 'boolean', + }, + note: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'websiteId', + 'date', + 'allDay', + 'note', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/websites/[websiteId]/daterange/contract.generated.ts b/src/app/api/websites/[websiteId]/daterange/contract.generated.ts new file mode 100644 index 000000000..eec492674 --- /dev/null +++ b/src/app/api/websites/[websiteId]/daterange/contract.generated.ts @@ -0,0 +1,70 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/daterange', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdDaterange', + summary: 'Get websites website id daterange', + description: + 'Get websites website id daterange. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + startDate: { + type: 'string', + format: 'date-time', + }, + endDate: { + type: 'string', + format: 'date-time', + }, + }, + required: ['startDate', 'endDate'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/array-series/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/array-series/contract.generated.ts new file mode 100644 index 000000000..ae135b871 --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/array-series/contract.generated.ts @@ -0,0 +1,343 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot/array-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivotArraySeries', + summary: 'Get websites website id event data pivot array series', + description: + 'Get websites website id event data pivot array series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/contract.generated.ts new file mode 100644 index 000000000..7811a9d3e --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/contract.generated.ts @@ -0,0 +1,423 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivot', + summary: 'Get websites website id event data pivot', + description: + 'Get websites website id event data pivot. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + eventId: { + type: 'string', + }, + sessionId: { + type: 'string', + }, + eventName: { + type: 'string', + }, + urlPath: { + type: 'string', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + propertyKeys: { + type: 'array', + items: { + type: 'string', + }, + }, + propertyValues: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + required: [ + 'eventId', + 'sessionId', + 'eventName', + 'urlPath', + 'createdAt', + 'propertyKeys', + 'propertyValues', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/date-series/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/date-series/contract.generated.ts new file mode 100644 index 000000000..f8bbfd40e --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/date-series/contract.generated.ts @@ -0,0 +1,332 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot/date-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivotDateSeries', + summary: 'Get websites website id event data pivot date series', + description: + 'Get websites website id event data pivot date series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['t', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/numeric-series/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/numeric-series/contract.generated.ts new file mode 100644 index 000000000..41c02ec3c --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/numeric-series/contract.generated.ts @@ -0,0 +1,349 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot/numeric-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivotNumericSeries', + summary: 'Get websites website id event data pivot numeric series', + description: + 'Get websites website id event data pivot numeric series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'metric', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['sum', 'avg', 'count'], + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['t', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/numeric-stats/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/numeric-stats/contract.generated.ts new file mode 100644 index 000000000..99cafcaaf --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/numeric-stats/contract.generated.ts @@ -0,0 +1,330 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot/numeric-stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivotNumericStats', + summary: 'Get websites website id event data pivot numeric stats', + description: + 'Get websites website id event data pivot numeric stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + total: { + type: 'number', + }, + average: { + type: 'number', + }, + median: { + type: 'number', + }, + max: { + type: 'number', + }, + min: { + type: 'number', + }, + }, + required: ['total', 'average', 'median', 'max', 'min'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data-pivot/property-series/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data-pivot/property-series/contract.generated.ts new file mode 100644 index 000000000..317e23138 --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data-pivot/property-series/contract.generated.ts @@ -0,0 +1,343 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data-pivot/property-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataPivotPropertySeries', + summary: 'Get websites website id event data pivot property series', + description: + 'Get websites website id event data pivot property series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/[eventId]/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/[eventId]/contract.generated.ts new file mode 100644 index 000000000..8f464be68 --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/[eventId]/contract.generated.ts @@ -0,0 +1,127 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/{eventId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataEventId', + summary: 'Get websites website id event data event id', + description: + 'Get websites website id event data event id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'eventId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + websiteId: { + type: 'string', + }, + websiteEventId: { + type: 'string', + }, + dataKey: { + type: 'string', + }, + stringValue: { + type: 'string', + }, + numberValue: { + type: 'object', + properties: { + d: { + type: 'array', + items: { + type: 'number', + }, + }, + e: { + type: 'number', + }, + s: { + type: 'number', + }, + }, + required: ['d', 'e', 's'], + }, + dateValue: { + type: 'string', + format: 'date-time', + }, + dataType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'websiteId', + 'websiteEventId', + 'dataKey', + 'stringValue', + 'numberValue', + 'dateValue', + 'dataType', + ], + }, + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/contract.generated.ts new file mode 100644 index 000000000..5b55c901e --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/contract.generated.ts @@ -0,0 +1,403 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventData', + summary: 'Get websites website id event data', + description: + 'Get websites website id event data. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + websiteId: { + type: 'string', + }, + eventId: { + type: 'string', + }, + eventName: { + type: 'string', + }, + eventProperties: { + type: 'array', + items: { + type: 'object', + properties: { + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + dataKey: { + type: 'string', + }, + stringValue: { + type: 'string', + }, + numberValue: { + type: 'number', + }, + dateValue: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + dataType: { + type: 'number', + }, + }, + required: [ + 'createdAt', + 'dataKey', + 'stringValue', + 'numberValue', + 'dateValue', + 'dataType', + ], + }, + }, + }, + required: ['websiteId', 'eventId', 'eventName', 'eventProperties'], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/events/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/events/contract.generated.ts new file mode 100644 index 000000000..9a0bc5a6c --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/events/contract.generated.ts @@ -0,0 +1,317 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/events', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataEvents', + summary: 'Get websites website id event data events', + description: + 'Get websites website id event data events. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + eventName: { + type: 'string', + }, + propertyName: { + type: 'string', + }, + dataType: { + type: 'number', + }, + propertyValue: { + type: 'string', + }, + total: { + type: 'number', + }, + }, + required: ['propertyName', 'dataType', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/fields/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/fields/contract.generated.ts new file mode 100644 index 000000000..e619920eb --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/fields/contract.generated.ts @@ -0,0 +1,319 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/fields', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataFields', + summary: 'Get websites website id event data fields', + description: + 'Get websites website id event data fields. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + propertyName: { + type: 'string', + }, + dataType: { + type: 'number', + }, + total: { + type: 'number', + }, + }, + required: ['propertyName', 'dataType', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/properties/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/properties/contract.generated.ts new file mode 100644 index 000000000..bc395a6ab --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/properties/contract.generated.ts @@ -0,0 +1,314 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/properties', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataProperties', + summary: 'Get websites website id event data properties', + description: + 'Get websites website id event data properties. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + eventName: { + type: 'string', + }, + propertyName: { + type: 'string', + }, + dataType: { + type: 'number', + }, + total: { + type: 'number', + }, + }, + required: ['eventName', 'propertyName', 'dataType', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/route.ts b/src/app/api/websites/[websiteId]/event-data/route.ts index 5b4f31226..2a6ccad7f 100644 --- a/src/app/api/websites/[websiteId]/event-data/route.ts +++ b/src/app/api/websites/[websiteId]/event-data/route.ts @@ -2,9 +2,24 @@ import { z } from 'zod'; import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; import { filterParams, pagingParams } from '@/lib/schema'; +import type { PageResult } from '@/lib/types'; import { canViewWebsiteSection } from '@/permissions'; import { getEventData } from '@/queries/sql/events/getEventData'; +interface EventDataRow { + websiteId: string; + eventId: string; + eventName: string; + dataKey: string; + stringValue: string | null; + numberValue: number | null; + dateValue: Date | string | null; + dataType: number; + createdAt: Date | string; +} + +type EventProperty = Omit; + export async function GET( request: Request, { params }: { params: Promise<{ websiteId: string }> }, @@ -30,11 +45,16 @@ export async function GET( const filters = await getQueryFilters(query, websiteId); - const { data: rows, count, page, pageSize } = await getEventData(websiteId, filters); + const { + data: rows, + count, + page, + pageSize, + } = (await getEventData(websiteId, filters)) as PageResult; const eventMap = new Map< string, - { websiteId: string; eventId: string; eventName: string; eventProperties: object[] } + { websiteId: string; eventId: string; eventName: string; eventProperties: EventProperty[] } >(); for (const { websiteId, eventId, eventName, ...props } of rows) { diff --git a/src/app/api/websites/[websiteId]/event-data/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/stats/contract.generated.ts new file mode 100644 index 000000000..092544338 --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/stats/contract.generated.ts @@ -0,0 +1,308 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataStats', + summary: 'Get websites website id event data stats', + description: + 'Get websites website id event data stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + events: { + type: 'number', + }, + properties: { + type: 'number', + }, + records: { + type: 'number', + }, + }, + required: ['events', 'properties', 'records'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/event-data/values/contract.generated.ts b/src/app/api/websites/[websiteId]/event-data/values/contract.generated.ts new file mode 100644 index 000000000..cb3932acd --- /dev/null +++ b/src/app/api/websites/[websiteId]/event-data/values/contract.generated.ts @@ -0,0 +1,332 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/event-data/values', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventDataValues', + summary: 'Get websites website id event data values', + description: + 'Get websites website id event data values. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'eventName', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'dataType', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + value: { + type: 'string', + }, + total: { + type: 'number', + }, + }, + required: ['value', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/events/contract.generated.ts b/src/app/api/websites/[websiteId]/events/contract.generated.ts new file mode 100644 index 000000000..ae76f769f --- /dev/null +++ b/src/app/api/websites/[websiteId]/events/contract.generated.ts @@ -0,0 +1,492 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/events', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEvents', + summary: 'Get websites website id events', + description: + 'Get websites website id events. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + sessionId: { + type: 'string', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + hostname: { + type: 'string', + }, + urlPath: { + type: 'string', + }, + urlQuery: { + type: 'string', + }, + referrerPath: { + type: 'string', + }, + referrerQuery: { + type: 'string', + }, + referrerDomain: { + type: 'string', + }, + country: { + type: 'string', + }, + city: { + type: 'string', + }, + device: { + type: 'string', + }, + os: { + type: 'string', + }, + browser: { + type: 'string', + }, + pageTitle: { + type: 'string', + }, + eventType: { + type: 'number', + }, + eventName: { + type: 'string', + }, + hasData: { + type: 'boolean', + }, + }, + required: [ + 'id', + 'websiteId', + 'sessionId', + 'createdAt', + 'hostname', + 'urlPath', + 'urlQuery', + 'referrerPath', + 'referrerQuery', + 'referrerDomain', + 'country', + 'city', + 'device', + 'os', + 'browser', + 'pageTitle', + 'eventType', + 'eventName', + 'hasData', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/events/series/contract.generated.ts b/src/app/api/websites/[websiteId]/events/series/contract.generated.ts new file mode 100644 index 000000000..2f1d61d48 --- /dev/null +++ b/src/app/api/websites/[websiteId]/events/series/contract.generated.ts @@ -0,0 +1,335 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/events/series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventsSeries', + summary: 'Get websites website id events series', + description: + 'Get websites website id events series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'limit', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/events/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/events/stats/contract.generated.ts new file mode 100644 index 000000000..c97ee68c5 --- /dev/null +++ b/src/app/api/websites/[websiteId]/events/stats/contract.generated.ts @@ -0,0 +1,372 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/events/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdEventsStats', + summary: 'Get websites website id events stats', + description: + 'Get websites website id events stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'object', + properties: { + comparison: { + type: 'array', + items: { + type: 'object', + properties: { + events: { + type: 'number', + }, + visitors: { + type: 'number', + }, + visits: { + type: 'number', + }, + uniqueEvents: { + type: 'number', + }, + }, + required: ['events', 'visitors', 'visits', 'uniqueEvents'], + }, + }, + length: { + type: 'number', + }, + }, + required: ['comparison', 'length'], + }, + }, + required: ['data'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/export/contract.generated.ts b/src/app/api/websites/[websiteId]/export/contract.generated.ts new file mode 100644 index 000000000..2784da6d5 --- /dev/null +++ b/src/app/api/websites/[websiteId]/export/contract.generated.ts @@ -0,0 +1,177 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/export', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdExport', + summary: 'Get websites website id export', + description: + 'Get websites website id export. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + zip: { + type: 'string', + }, + }, + required: ['zip'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + 'function toString() { [native code] }': { + description: + 'Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema.', + content: { + 'application/json': { + schema: {}, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/metrics/contract.generated.ts b/src/app/api/websites/[websiteId]/metrics/contract.generated.ts new file mode 100644 index 000000000..9e98c4a9d --- /dev/null +++ b/src/app/api/websites/[websiteId]/metrics/contract.generated.ts @@ -0,0 +1,386 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/metrics', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdMetrics', + summary: 'Get websites website id metrics', + description: + 'Get websites website id metrics. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'type', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'limit', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'offset', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/metrics/expanded/contract.generated.ts b/src/app/api/websites/[websiteId]/metrics/expanded/contract.generated.ts new file mode 100644 index 000000000..9787f688e --- /dev/null +++ b/src/app/api/websites/[websiteId]/metrics/expanded/contract.generated.ts @@ -0,0 +1,395 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/metrics/expanded', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdMetricsExpanded', + summary: 'Get websites website id metrics expanded', + description: + 'Get websites website id metrics expanded. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'type', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'limit', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'offset', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + pageviews: { + type: 'number', + }, + visitors: { + type: 'number', + }, + visits: { + type: 'number', + }, + bounces: { + type: 'number', + }, + totaltime: { + type: 'number', + }, + }, + required: ['name', 'pageviews', 'visitors', 'visits', 'bounces', 'totaltime'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/pageviews/contract.generated.ts b/src/app/api/websites/[websiteId]/pageviews/contract.generated.ts new file mode 100644 index 000000000..a8d4ac042 --- /dev/null +++ b/src/app/api/websites/[websiteId]/pageviews/contract.generated.ts @@ -0,0 +1,380 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/pageviews', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdPageviews', + summary: 'Get websites website id pageviews', + description: + 'Get websites website id pageviews. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + pageviews: {}, + sessions: {}, + startDate: { + type: 'string', + format: 'date-time', + }, + endDate: { + type: 'string', + format: 'date-time', + }, + compare: { + type: 'object', + properties: { + pageviews: {}, + sessions: {}, + startDate: { + type: 'string', + format: 'date-time', + }, + endDate: { + type: 'string', + format: 'date-time', + }, + }, + required: ['pageviews', 'sessions', 'startDate', 'endDate'], + }, + }, + required: ['pageviews', 'sessions', 'startDate', 'endDate', 'compare'], + }, + { + type: 'object', + properties: { + pageviews: {}, + sessions: {}, + }, + required: ['pageviews', 'sessions'], + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/recorder/contract.generated.ts b/src/app/api/websites/[websiteId]/recorder/contract.generated.ts new file mode 100644 index 000000000..b24234ffa --- /dev/null +++ b/src/app/api/websites/[websiteId]/recorder/contract.generated.ts @@ -0,0 +1,98 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/recorder', + audience: 'collect', + auth: 'none', + operation: { + operationId: 'getWebsitesWebsiteIdRecorder', + summary: 'Get websites website id recorder', + description: + 'Get websites website id recorder. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'object', + properties: { + enabled: { + type: 'boolean', + }, + }, + required: ['enabled'], + }, + { + type: 'object', + properties: { + enabled: { + type: 'boolean', + }, + replayEnabled: { + type: 'boolean', + }, + heatmapEnabled: { + type: 'boolean', + }, + sampleRate: { + type: 'number', + }, + heatmapSampleRate: { + type: 'number', + }, + maskLevel: { + anyOf: [ + { + const: 'strict', + }, + { + const: 'moderate', + }, + ], + }, + maxDuration: { + type: 'number', + }, + blockSelector: { + type: 'string', + }, + }, + required: [ + 'enabled', + 'replayEnabled', + 'heatmapEnabled', + 'sampleRate', + 'heatmapSampleRate', + 'maskLevel', + 'maxDuration', + 'blockSelector', + ], + }, + ], + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/replays/[replayId]/contract.generated.ts b/src/app/api/websites/[websiteId]/replays/[replayId]/contract.generated.ts new file mode 100644 index 000000000..16b8a45d7 --- /dev/null +++ b/src/app/api/websites/[websiteId]/replays/[replayId]/contract.generated.ts @@ -0,0 +1,91 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/replays/{replayId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdReplaysReplayId', + summary: 'Get websites website id replays replay id', + description: + 'Get websites website id replays replay id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'replayId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + sessionId: { + type: 'string', + }, + events: { + type: 'array', + items: {}, + }, + startedAt: { + type: 'string', + format: 'date-time', + }, + endedAt: { + type: 'string', + format: 'date-time', + }, + eventCount: { + type: 'number', + }, + chunkCount: { + type: 'number', + }, + }, + required: ['sessionId', 'events', 'startedAt', 'endedAt', 'eventCount', 'chunkCount'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/replays/contract.generated.ts b/src/app/api/websites/[websiteId]/replays/contract.generated.ts new file mode 100644 index 000000000..9440951f4 --- /dev/null +++ b/src/app/api/websites/[websiteId]/replays/contract.generated.ts @@ -0,0 +1,497 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/replays', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdReplays', + summary: 'Get websites website id replays', + description: + 'Get websites website id replays. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'minDuration', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 0, + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + sessionId: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + country: { + type: 'string', + }, + city: { + type: 'string', + }, + eventCount: { + type: 'number', + }, + chunkCount: { + type: 'number', + }, + startedAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + endedAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + duration: { + type: 'number', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + }, + required: [ + 'id', + 'sessionId', + 'websiteId', + 'browser', + 'os', + 'device', + 'country', + 'city', + 'eventCount', + 'chunkCount', + 'startedAt', + 'endedAt', + 'duration', + 'createdAt', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/replays/saved/[replayId]/contract.generated.ts b/src/app/api/websites/[websiteId]/replays/saved/[replayId]/contract.generated.ts new file mode 100644 index 000000000..f52b50bf4 --- /dev/null +++ b/src/app/api/websites/[websiteId]/replays/saved/[replayId]/contract.generated.ts @@ -0,0 +1,177 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/replays/saved/{replayId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdReplaysSavedReplayId', + summary: 'Get websites website id replays saved replay id', + description: + 'Get websites website id replays saved replay id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'replayId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + isSaved: { + type: 'boolean', + }, + }, + required: ['isSaved'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/replays/saved/{replayId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdReplaysSavedReplayId', + summary: 'Create or update websites website id replays saved replay id', + description: + 'Create or update websites website id replays saved replay id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'replayId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + isSaved: { + type: 'boolean', + }, + name: { + type: 'string', + maxLength: 100, + }, + }, + required: ['isSaved'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + required: ['ok'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/websites/[websiteId]/replays/saved/contract.generated.ts b/src/app/api/websites/[websiteId]/replays/saved/contract.generated.ts new file mode 100644 index 000000000..60327abc4 --- /dev/null +++ b/src/app/api/websites/[websiteId]/replays/saved/contract.generated.ts @@ -0,0 +1,164 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/replays/saved', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdReplaysSaved', + summary: 'Get websites website id replays saved', + description: + 'Get websites website id replays saved. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + visitId: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'updatedAt', 'name', 'websiteId', 'visitId'], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/reports/contract.generated.ts b/src/app/api/websites/[websiteId]/reports/contract.generated.ts new file mode 100644 index 000000000..ef8e33cb2 --- /dev/null +++ b/src/app/api/websites/[websiteId]/reports/contract.generated.ts @@ -0,0 +1,256 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/reports', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdReports', + summary: 'Get websites website id reports', + description: + 'Get websites website id reports. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'type', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + allOf: [ + { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + description: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'description', + 'parameters', + 'websiteId', + ], + }, + { + type: 'object', + properties: { + website: { + type: 'object', + properties: { + domain: { + type: 'string', + }, + userId: { + type: 'string', + }, + }, + required: ['domain', 'userId'], + }, + }, + }, + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/reset/contract.generated.ts b/src/app/api/websites/[websiteId]/reset/contract.generated.ts new file mode 100644 index 000000000..d110bef77 --- /dev/null +++ b/src/app/api/websites/[websiteId]/reset/contract.generated.ts @@ -0,0 +1,65 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/reset', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdReset', + summary: 'Create or update websites website id reset', + description: + 'Create or update websites website id reset. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/revenue/chart/contract.generated.ts b/src/app/api/websites/[websiteId]/revenue/chart/contract.generated.ts new file mode 100644 index 000000000..9527ed140 --- /dev/null +++ b/src/app/api/websites/[websiteId]/revenue/chart/contract.generated.ts @@ -0,0 +1,371 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/revenue/chart', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdRevenueChart', + summary: 'Get websites website id revenue chart', + description: + 'Get websites website id revenue chart. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'currency', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + chart: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + count: { + type: 'number', + }, + }, + required: ['x', 't', 'y', 'count'], + }, + }, + }, + required: ['chart'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/revenue/metrics/contract.generated.ts b/src/app/api/websites/[websiteId]/revenue/metrics/contract.generated.ts new file mode 100644 index 000000000..c73e55f1c --- /dev/null +++ b/src/app/api/websites/[websiteId]/revenue/metrics/contract.generated.ts @@ -0,0 +1,390 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/revenue/metrics', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdRevenueMetrics', + summary: 'Get websites website id revenue metrics', + description: + 'Get websites website id revenue metrics. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'type', + in: 'query', + required: true, + schema: { + type: 'string', + enum: ['country', 'region', 'referrer', 'channel'], + }, + }, + { + name: 'currency', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + anyOf: [ + { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + }, + required: ['name', 'value'], + }, + }, + { + type: 'array', + items: { + type: 'object', + properties: { + name: { + type: 'string', + }, + value: { + type: 'number', + }, + country: { + type: 'string', + }, + }, + required: ['name', 'value', 'country'], + }, + }, + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/revenue/sessions/contract.generated.ts b/src/app/api/websites/[websiteId]/revenue/sessions/contract.generated.ts new file mode 100644 index 000000000..ca514bbb6 --- /dev/null +++ b/src/app/api/websites/[websiteId]/revenue/sessions/contract.generated.ts @@ -0,0 +1,508 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/revenue/sessions', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdRevenueSessions', + summary: 'Get websites website id revenue sessions', + description: + 'Get websites website id revenue sessions. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'currency', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + hostname: { + type: 'string', + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + screen: { + type: 'string', + }, + language: { + type: 'string', + }, + country: { + type: 'string', + }, + region: { + type: 'string', + }, + city: { + type: 'string', + }, + firstAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + lastAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + visits: { + type: 'number', + }, + views: { + type: 'number', + }, + events: { + type: 'number', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + }, + required: [ + 'id', + 'websiteId', + 'hostname', + 'browser', + 'os', + 'device', + 'screen', + 'language', + 'country', + 'region', + 'city', + 'firstAt', + 'lastAt', + 'visits', + 'views', + 'events', + 'createdAt', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/revenue/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/revenue/stats/contract.generated.ts new file mode 100644 index 000000000..f79754021 --- /dev/null +++ b/src/app/api/websites/[websiteId]/revenue/stats/contract.generated.ts @@ -0,0 +1,351 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/revenue/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdRevenueStats', + summary: 'Get websites website id revenue stats', + description: + 'Get websites website id revenue stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'currency', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + comparison: {}, + }, + required: ['comparison'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts b/src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts new file mode 100644 index 000000000..77a84277a --- /dev/null +++ b/src/app/api/websites/[websiteId]/segments/[segmentId]/contract.generated.ts @@ -0,0 +1,444 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/websites/{websiteId}/segments/{segmentId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteWebsitesWebsiteIdSegmentsSegmentId', + summary: 'Delete websites website id segments segment id', + description: + 'Delete websites website id segments segment id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'segmentId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/segments/{segmentId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSegmentsSegmentId', + summary: 'Get websites website id segments segment id', + description: + 'Get websites website id segments segment id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'segmentId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'updatedAt', 'name', 'type', 'parameters', 'websiteId'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation3 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/segments/{segmentId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdSegmentsSegmentId', + summary: 'Create or update websites website id segments segment id', + description: + 'Create or update websites website id segments segment id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'segmentId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + type: { + type: 'string', + enum: ['segment', 'cohort'], + }, + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['type', 'name', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'updatedAt', 'name', 'type', 'parameters', 'websiteId'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2, operation3] as const; diff --git a/src/app/api/websites/[websiteId]/segments/contract.generated.ts b/src/app/api/websites/[websiteId]/segments/contract.generated.ts new file mode 100644 index 000000000..c3277797d --- /dev/null +++ b/src/app/api/websites/[websiteId]/segments/contract.generated.ts @@ -0,0 +1,409 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/segments', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSegments', + summary: 'Get websites website id segments', + description: + 'Get websites website id segments. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'type', + in: 'query', + required: true, + schema: { + type: 'string', + enum: ['segment', 'cohort'], + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'type', + 'parameters', + 'websiteId', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/segments', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdSegments', + summary: 'Create or update websites website id segments', + description: + 'Create or update websites website id segments. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + type: { + type: 'string', + enum: ['segment', 'cohort'], + }, + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + properties: { + filters: { + type: 'array', + items: { + type: 'object', + additionalProperties: true, + }, + }, + match: { + type: 'string', + enum: ['all', 'any'], + }, + dateRange: { + type: 'string', + }, + action: { + type: 'object', + properties: { + type: { + type: 'string', + }, + value: { + type: 'string', + }, + }, + required: ['type', 'value'], + }, + }, + }, + }, + required: ['type', 'name', 'parameters'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + type: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + websiteId: { + type: 'string', + }, + }, + required: ['id', 'createdAt', 'updatedAt', 'name', 'type', 'parameters', 'websiteId'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/websites/[websiteId]/session-data-pivot/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data-pivot/contract.generated.ts new file mode 100644 index 000000000..913813d40 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data-pivot/contract.generated.ts @@ -0,0 +1,415 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data-pivot', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataPivot', + summary: 'Get websites website id session data pivot', + description: + 'Get websites website id session data pivot. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + sessionId: { + type: 'string', + }, + distinctId: { + type: 'string', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + propertyKeys: { + type: 'array', + items: { + type: 'string', + }, + }, + propertyValues: { + type: 'array', + items: { + type: 'string', + }, + }, + }, + required: [ + 'sessionId', + 'distinctId', + 'createdAt', + 'propertyKeys', + 'propertyValues', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/array-series/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/array-series/contract.generated.ts new file mode 100644 index 000000000..012f800d7 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/array-series/contract.generated.ts @@ -0,0 +1,335 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/array-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataArraySeries', + summary: 'Get websites website id session data array series', + description: + 'Get websites website id session data array series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/date-series/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/date-series/contract.generated.ts new file mode 100644 index 000000000..ce22cbf90 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/date-series/contract.generated.ts @@ -0,0 +1,324 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/date-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataDateSeries', + summary: 'Get websites website id session data date series', + description: + 'Get websites website id session data date series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['t', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/numeric-series/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/numeric-series/contract.generated.ts new file mode 100644 index 000000000..74470ca47 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/numeric-series/contract.generated.ts @@ -0,0 +1,341 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/numeric-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataNumericSeries', + summary: 'Get websites website id session data numeric series', + description: + 'Get websites website id session data numeric series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'metric', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['sum', 'avg', 'count'], + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['t', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/numeric-stats/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/numeric-stats/contract.generated.ts new file mode 100644 index 000000000..3423b1fa8 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/numeric-stats/contract.generated.ts @@ -0,0 +1,330 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/numeric-stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataNumericStats', + summary: 'Get websites website id session data numeric stats', + description: + 'Get websites website id session data numeric stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + total: { + type: 'number', + }, + average: { + type: 'number', + }, + median: { + type: 'number', + }, + max: { + type: 'number', + }, + min: { + type: 'number', + }, + }, + required: ['total', 'average', 'median', 'max', 'min'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/properties/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/properties/contract.generated.ts new file mode 100644 index 000000000..130954ecb --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/properties/contract.generated.ts @@ -0,0 +1,319 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/properties', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataProperties', + summary: 'Get websites website id session data properties', + description: + 'Get websites website id session data properties. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + propertyName: { + type: 'string', + }, + dataType: { + type: 'number', + }, + total: { + type: 'number', + }, + }, + required: ['propertyName', 'dataType', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/property-series/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/property-series/contract.generated.ts new file mode 100644 index 000000000..640a983b6 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/property-series/contract.generated.ts @@ -0,0 +1,335 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/property-series', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataPropertySeries', + summary: 'Get websites website id session data property series', + description: + 'Get websites website id session data property series. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + x: { + type: 'string', + }, + t: { + type: 'string', + }, + y: { + type: 'number', + }, + }, + required: ['x', 't', 'y'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/stats/contract.generated.ts new file mode 100644 index 000000000..f8c72fb18 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/stats/contract.generated.ts @@ -0,0 +1,344 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataStats', + summary: 'Get websites website id session data stats', + description: + 'Get websites website id session data stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + label: { + type: 'string', + }, + activity: { + type: 'number', + }, + sessions: { + type: 'number', + }, + visits: { + type: 'number', + }, + views: { + type: 'number', + }, + events: { + type: 'number', + }, + }, + required: ['label', 'activity', 'sessions', 'visits', 'views', 'events'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/session-data/values/contract.generated.ts b/src/app/api/websites/[websiteId]/session-data/values/contract.generated.ts new file mode 100644 index 000000000..87af3d580 --- /dev/null +++ b/src/app/api/websites/[websiteId]/session-data/values/contract.generated.ts @@ -0,0 +1,324 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/session-data/values', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionDataValues', + summary: 'Get websites website id session data values', + description: + 'Get websites website id session data values. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'propertyName', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'dataType', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + value: { + type: 'string', + }, + total: { + type: 'number', + }, + }, + required: ['value', 'total'], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/contract.generated.ts new file mode 100644 index 000000000..48e029db8 --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/contract.generated.ts @@ -0,0 +1,163 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/{sessionId}/activity', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsSessionIdActivity', + summary: 'Get websites website id sessions session id activity', + description: + 'Get websites website id sessions session id activity. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'sessionId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + urlPath: { + type: 'string', + }, + urlQuery: { + type: 'string', + }, + referrerDomain: { + type: 'string', + }, + eventId: { + type: 'string', + }, + eventType: { + type: 'number', + }, + eventName: { + type: 'string', + }, + visitId: { + type: 'string', + }, + hostname: { + type: 'string', + }, + hasData: { + type: 'boolean', + }, + }, + required: [ + 'createdAt', + 'urlPath', + 'urlQuery', + 'referrerDomain', + 'eventId', + 'eventType', + 'eventName', + 'visitId', + 'hostname', + 'hasData', + ], + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts index 29efcad62..cad956b24 100644 --- a/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/activity/route.ts @@ -3,12 +3,9 @@ import { z } from 'zod'; import { FIELD_LENGTH } from '@/lib/constants'; import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; +import type { SessionActivity } from '@/lib/types'; import { canViewWebsiteSection } from '@/permissions'; -import { - getLinkedDistinctIds, - getLinkedSessionIds, - getSessionActivity, -} from '@/queries/sql'; +import { getLinkedDistinctIds, getLinkedSessionIds, getSessionActivity } from '@/queries/sql'; export async function GET( request: Request, @@ -60,7 +57,7 @@ export async function GET( const filters = await getQueryFilters({ ...query, startAt, endAt }, websiteId); - const data = await getSessionActivity(websiteId, sessionIds, filters); + const data = (await getSessionActivity(websiteId, sessionIds, filters)) as SessionActivity[]; return json(data); } diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/contract.generated.ts new file mode 100644 index 000000000..ae43b9f3c --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/contract.generated.ts @@ -0,0 +1,190 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'delete', + path: '/api/websites/{websiteId}/sessions/{sessionId}', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'deleteWebsitesWebsiteIdSessionsSessionId', + summary: 'Delete websites website id sessions session id', + description: + 'Delete websites website id sessions session id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'sessionId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + ok: { + const: true, + }, + }, + required: ['ok'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/{sessionId}', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsSessionId', + summary: 'Get websites website id sessions session id', + description: + 'Get websites website id sessions session id. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'sessionId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + canDelete: {}, + stitchedSessionCount: {}, + }, + required: ['canDelete', 'stitchedSessionCount'], + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '404': { + description: 'Not found.', + content: { + 'application/json': { + example: { + error: { + message: 'Not found.', + code: 'not-found', + status: 404, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/properties/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/properties/contract.generated.ts new file mode 100644 index 000000000..7e6dcd723 --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/properties/contract.generated.ts @@ -0,0 +1,122 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/{sessionId}/properties', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsSessionIdProperties', + summary: 'Get websites website id sessions session id properties', + description: + 'Get websites website id sessions session id properties. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'sessionId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'object', + properties: { + websiteId: { + type: 'string', + }, + sessionId: { + type: 'string', + }, + dataKey: { + type: 'string', + }, + dataType: { + type: 'number', + }, + stringValue: { + type: 'string', + }, + numberValue: { + type: 'number', + }, + dateValue: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + }, + required: [ + 'websiteId', + 'sessionId', + 'dataKey', + 'dataType', + 'stringValue', + 'numberValue', + 'dateValue', + 'createdAt', + ], + }, + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/[sessionId]/replays/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/[sessionId]/replays/contract.generated.ts new file mode 100644 index 000000000..b86b4e1c4 --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/[sessionId]/replays/contract.generated.ts @@ -0,0 +1,292 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/{sessionId}/replays', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsSessionIdReplays', + summary: 'Get websites website id sessions session id replays', + description: + 'Get websites website id sessions session id replays. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'sessionId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + sessionId: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + country: { + type: 'string', + }, + city: { + type: 'string', + }, + eventCount: { + type: 'number', + }, + chunkCount: { + type: 'number', + }, + startedAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + endedAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + duration: { + type: 'number', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + }, + required: [ + 'id', + 'sessionId', + 'websiteId', + 'browser', + 'os', + 'device', + 'country', + 'city', + 'eventCount', + 'chunkCount', + 'startedAt', + 'endedAt', + 'duration', + 'createdAt', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/contract.generated.ts new file mode 100644 index 000000000..0dafdec2e --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/contract.generated.ts @@ -0,0 +1,500 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessions', + summary: 'Get websites website id sessions', + description: + 'Get websites website id sessions. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + websiteId: { + type: 'string', + }, + hostname: { + type: 'string', + }, + browser: { + type: 'string', + }, + os: { + type: 'string', + }, + device: { + type: 'string', + }, + screen: { + type: 'string', + }, + language: { + type: 'string', + }, + country: { + type: 'string', + }, + region: { + type: 'string', + }, + city: { + type: 'string', + }, + firstAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + lastAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + visits: { + type: 'number', + }, + views: { + type: 'number', + }, + events: { + type: 'number', + }, + createdAt: { + anyOf: [ + { + type: 'string', + }, + { + type: 'string', + format: 'date-time', + }, + ], + }, + }, + required: [ + 'id', + 'websiteId', + 'hostname', + 'browser', + 'os', + 'device', + 'screen', + 'language', + 'country', + 'region', + 'city', + 'firstAt', + 'lastAt', + 'visits', + 'views', + 'events', + 'createdAt', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/stats/contract.generated.ts new file mode 100644 index 000000000..2e89a2638 --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/stats/contract.generated.ts @@ -0,0 +1,297 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsStats', + summary: 'Get websites website id sessions stats', + description: + 'Get websites website id sessions stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: {}, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/sessions/weekly/contract.generated.ts b/src/app/api/websites/[websiteId]/sessions/weekly/contract.generated.ts new file mode 100644 index 000000000..28ca575f3 --- /dev/null +++ b/src/app/api/websites/[websiteId]/sessions/weekly/contract.generated.ts @@ -0,0 +1,310 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/sessions/weekly', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdSessionsWeekly', + summary: 'Get websites website id sessions weekly', + description: + 'Get websites website id sessions weekly. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: true, + schema: { + type: 'integer', + }, + }, + { + name: 'timezone', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: { + type: 'array', + items: { + type: 'number', + }, + }, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/shares/contract.generated.ts b/src/app/api/websites/[websiteId]/shares/contract.generated.ts new file mode 100644 index 000000000..e022f831b --- /dev/null +++ b/src/app/api/websites/[websiteId]/shares/contract.generated.ts @@ -0,0 +1,608 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/shares', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdShares', + summary: 'Get websites website id shares', + description: + 'Get websites website id shares. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + { + name: 'page', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'pageSize', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'maxResults', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + count: { + type: 'number', + }, + page: { + type: 'number', + }, + pageSize: { + type: 'number', + }, + orderBy: { + type: 'string', + }, + sortDescending: { + type: 'boolean', + }, + search: { + type: 'string', + }, + isCapped: { + type: 'boolean', + }, + }, + required: ['data', 'count', 'page', 'pageSize'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +const operation2 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/shares', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdShares', + summary: 'Create or update websites website id shares', + description: + 'Create or update websites website id shares. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + name: { + type: 'string', + maxLength: 200, + }, + parameters: { + type: 'object', + additionalProperties: true, + }, + }, + required: ['name'], + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + name: { + type: 'string', + }, + slug: { + type: 'string', + }, + parameters: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + entityId: { + type: 'string', + }, + shareType: { + type: 'number', + }, + }, + required: [ + 'id', + 'createdAt', + 'updatedAt', + 'name', + 'slug', + 'parameters', + 'entityId', + 'shareType', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1, operation2] as const; diff --git a/src/app/api/websites/[websiteId]/stats/contract.generated.ts b/src/app/api/websites/[websiteId]/stats/contract.generated.ts new file mode 100644 index 000000000..0bdaa834b --- /dev/null +++ b/src/app/api/websites/[websiteId]/stats/contract.generated.ts @@ -0,0 +1,369 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/stats', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdStats', + summary: 'Get websites website id stats', + description: + 'Get websites website id stats. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'path', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'referrer', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'title', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'query', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'os', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'browser', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'device', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'country', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'region', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'city', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'tag', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'hostname', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'distinctId', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'language', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'event', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmSource', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmMedium', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmCampaign', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmContent', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'utmTerm', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'excludeBounce', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'segment', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'cohort', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'uuid', + }, + }, + { + name: 'eventType', + in: 'query', + required: false, + schema: { + type: 'integer', + minimum: 1, + }, + }, + { + name: 'match', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['all', 'any'], + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + comparison: { + type: 'array', + items: { + type: 'object', + properties: { + pageviews: { + type: 'number', + }, + visitors: { + type: 'number', + }, + visits: { + type: 'number', + }, + bounces: { + type: 'number', + }, + totaltime: { + type: 'number', + }, + }, + required: ['pageviews', 'visitors', 'visits', 'bounces', 'totaltime'], + }, + }, + length: { + type: 'number', + }, + }, + required: ['comparison', 'length'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/transfer/contract.generated.ts b/src/app/api/websites/[websiteId]/transfer/contract.generated.ts new file mode 100644 index 000000000..94565b03d --- /dev/null +++ b/src/app/api/websites/[websiteId]/transfer/contract.generated.ts @@ -0,0 +1,204 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'post', + path: '/api/websites/{websiteId}/transfer', + audience: 'public', + auth: 'bearer', + operation: { + operationId: 'postWebsitesWebsiteIdTransfer', + summary: 'Create or update websites website id transfer', + description: + 'Create or update websites website id transfer. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + userId: { + type: 'string', + format: 'uuid', + }, + teamId: { + type: 'string', + format: 'uuid', + }, + }, + }, + }, + }, + }, + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + id: { + type: 'string', + }, + userId: { + type: 'string', + }, + createdAt: { + type: 'string', + format: 'date-time', + }, + updatedAt: { + type: 'string', + format: 'date-time', + }, + deletedAt: { + type: 'string', + format: 'date-time', + }, + createdBy: { + type: 'string', + }, + name: { + type: 'string', + }, + domain: { + type: 'string', + }, + resetAt: { + type: 'string', + format: 'date-time', + }, + teamId: { + type: 'string', + }, + recorderEnabled: { + type: 'boolean', + }, + replayConfig: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + { + type: 'object', + properties: {}, + additionalProperties: { + anyOf: [ + { + type: 'string', + }, + { + type: 'number', + }, + { + const: false, + }, + { + const: true, + }, + {}, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + { + type: 'object', + properties: { + length: { + type: 'number', + }, + }, + required: ['length'], + }, + ], + }, + }, + required: [ + 'id', + 'userId', + 'createdAt', + 'updatedAt', + 'deletedAt', + 'createdBy', + 'name', + 'domain', + 'resetAt', + 'teamId', + 'recorderEnabled', + 'replayConfig', + ], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/[websiteId]/values/contract.generated.ts b/src/app/api/websites/[websiteId]/values/contract.generated.ts new file mode 100644 index 000000000..d76fac0d6 --- /dev/null +++ b/src/app/api/websites/[websiteId]/values/contract.generated.ts @@ -0,0 +1,152 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/{websiteId}/values', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesWebsiteIdValues', + summary: 'Get websites website id values', + description: + 'Get websites website id values. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'websiteId', + in: 'path', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'number', + }, + }, + { + name: 'startDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'endDate', + in: 'query', + required: false, + schema: { + type: 'string', + format: 'date-time', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'unit', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + { + name: 'compare', + in: 'query', + required: false, + schema: { + type: 'string', + enum: ['prev', 'yoy'], + }, + }, + { + name: 'type', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'search', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'array', + items: {}, + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/app/api/websites/charts/contract.generated.ts b/src/app/api/websites/charts/contract.generated.ts new file mode 100644 index 000000000..e3324bca6 --- /dev/null +++ b/src/app/api/websites/charts/contract.generated.ts @@ -0,0 +1,122 @@ +// Generated by `pnpm openapi:contracts`. Do not edit directly. + +import type { ZodOpenApiOperationObject } from 'zod-openapi'; +import { defineOperation } from '@/openapi/operation'; + +const operation1 = defineOperation({ + method: 'get', + path: '/api/websites/charts', + audience: 'public', + auth: 'bearer-or-share', + operation: { + operationId: 'getWebsitesCharts', + summary: 'Get websites charts', + description: + 'Get websites charts. The request and response models are derived from the validated route contract.', + tags: ['Websites'], + parameters: [ + { + name: 'ids', + in: 'query', + required: true, + schema: { + type: 'string', + }, + }, + { + name: 'startAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'endAt', + in: 'query', + required: false, + schema: { + type: 'integer', + }, + }, + { + name: 'timezone', + in: 'query', + required: false, + schema: { + type: 'string', + }, + }, + ], + responses: { + '200': { + description: 'The operation completed successfully.', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'object', + properties: {}, + additionalProperties: { + type: 'object', + properties: { + values: { + type: 'array', + items: { + type: 'number', + }, + }, + total: { + type: 'number', + }, + }, + required: ['values', 'total'], + }, + }, + }, + required: ['data'], + }, + }, + }, + }, + '400': { + description: 'Bad request.', + content: { + 'application/json': { + example: { + error: { + message: 'Bad request.', + code: 'bad-request', + status: 400, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + '401': { + description: 'Unauthorized.', + content: { + 'application/json': { + example: { + error: { + message: 'Unauthorized.', + code: 'unauthorized', + status: 401, + }, + }, + schema: { + $ref: '#/components/schemas/ApiError', + }, + }, + }, + }, + }, + } as ZodOpenApiOperationObject, +}); + +export const operations = [operation1] as const; diff --git a/src/lib/types.ts b/src/lib/types.ts index d069538da..98f47af6e 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -190,15 +190,132 @@ export interface PageResult { isCapped?: boolean; } +export interface ActiveVisitors { + visitors: number; +} + +export interface WebsiteDateRange { + startDate: Date | null; + endDate: Date | null; +} + +export interface PropertyMetric { + propertyName: string; + dataType: number; + total: number; +} + +export interface PropertyValue { + value: string; + total: number; +} + +export interface TimeSeriesValue { + t: string; + y: number; +} + +export interface WebsiteSession { + id: string; + websiteId: string; + hostname: string; + browser: string; + os: string; + device: string; + screen: string; + language: string; + country: string; + region: string; + city: string; + firstAt: Date | string; + lastAt: Date | string; + visits: number; + views: number; + events: number; + createdAt: Date | string; +} + +export interface WebsiteEvent { + id: string; + websiteId: string; + sessionId: string; + createdAt: Date | string; + hostname: string; + urlPath: string; + urlQuery: string; + referrerPath: string; + referrerQuery: string; + referrerDomain: string; + country: string; + city: string; + device: string; + os: string; + browser: string; + pageTitle: string; + eventType: number; + eventName: string; + hasData: boolean; +} + +export interface EventDataPivotRow { + eventId: string; + sessionId: string; + eventName: string; + urlPath: string; + createdAt: Date | string; + propertyKeys: string[]; + propertyValues: string[]; +} + +export interface SessionReplaySummary { + id: string; + sessionId: string; + websiteId: string; + browser: string; + os: string; + device: string; + country: string; + city: string; + eventCount: number; + chunkCount: number; + startedAt: Date | string; + endedAt: Date | string; + duration: number; + createdAt: Date | string; +} + +export interface SessionActivity { + createdAt: Date | string; + urlPath: string; + urlQuery: string; + referrerDomain: string; + eventId: string; + eventType: number; + eventName: string; + visitId: string; + hostname: string; + hasData: boolean; +} + +export interface SessionDataValue { + websiteId: string; + sessionId: string; + dataKey: string; + dataType: number; + stringValue: string | null; + numberValue: number | null; + dateValue: Date | string | null; + createdAt: Date | string; +} + export interface RealtimeData { countries: Record; - events: any[]; - pageviews: any[]; + events: RealtimeEvent[]; referrers: Record; timestamp: number; series: { - views: any[]; - visitors: any[]; + views: EventDataSeriesPoint[]; + visitors: EventDataSeriesPoint[]; }; totals: { views: number; @@ -207,7 +324,23 @@ export interface RealtimeData { countries: number; }; urls: Record; - visitors: any[]; +} + +export interface RealtimeActivity { + sessionId: string; + eventName: string; + createdAt: Date | string; + browser: string; + os: string; + device: string; + country: string; + urlPath: string; + referrerDomain: string; + hostname: string; +} + +export interface RealtimeEvent extends RealtimeActivity { + __type: 'session' | 'event' | 'pageview'; } export interface ApiError extends Error { diff --git a/src/openapi/README.md b/src/openapi/README.md index 760e1736c..d69bf7e25 100644 --- a/src/openapi/README.md +++ b/src/openapi/README.md @@ -7,6 +7,8 @@ contract wherever one exists. ## Commands - `pnpm openapi:generate` regenerates the public OpenAPI document. +- `pnpm openapi:contracts` refreshes source-controlled contracts for routes without a curated + `contract.ts` module. - `pnpm openapi:check` validates contract alignment and checks that the generated file is current. - `pnpm openapi:check --explicit` also fails while any non-OPTIONS API route lacks a hand-authored contract. @@ -17,9 +19,13 @@ tests and build steps. ## Adding an operation -Create a `contract.ts` next to the matching `route.ts` and export an `operations` array. Define -request and response shapes with Zod, and import the same request schema into the route handler for -`parseRequest` validation. +Run `pnpm openapi:contracts` to create a `contract.generated.ts` next to every route that does not +have a curated contract. Generated contracts use the route's Zod request validation and TypeScript +response types. They are checked in so operation IDs and client-facing schemas remain stable. + +For curated descriptions, examples, or runtime-shared Zod response models, replace the generated +module with a `contract.ts` that exports an `operations` array. Define request and response shapes +with Zod, and import the same request schema into the route handler for `parseRequest` validation. Contract modules must remain safe to import from a build script. They must not import route handlers, database clients, Redis clients, or modules with environment-dependent side effects. @@ -34,8 +40,8 @@ Route paths and HTTP methods are discovered independently from `src/app/api/**/r requires all discovered non-OPTIONS operations in the artifact and rejects duplicate contracts, duplicate operation IDs, orphaned contracts, and mismatched dynamic path parameters. -Inferred operations are marked with `x-umami-contract: inferred` and their source file. The inference -layer extracts path parameters, Zod request fields, authentication, response status helpers, and -response media types without importing route modules. Unknown response bodies remain free-form JSON -instead of being assigned an unverified shape. Explicit contracts are marked `explicit` and remain -the way to add exact response schemas, examples, and curated prose. +New operations are initially marked with `x-umami-contract: inferred` and their source file. The +inference layer extracts path parameters, Zod request fields, authentication, typed response bodies, +response status helpers, and response media types without importing route modules. Running +`pnpm openapi:contracts` snapshots that behavior into an explicit contract. Curated `contract.ts` +modules remain the way to add examples, custom operation IDs, and hand-written prose. diff --git a/src/openapi/discover.ts b/src/openapi/discover.ts index bf720bde3..4c090d64d 100644 --- a/src/openapi/discover.ts +++ b/src/openapi/discover.ts @@ -103,16 +103,21 @@ export async function discoverApiOperations( const apiRoot = path.join(projectRoot, 'src', 'app', 'api'); const routeFiles = await walk(apiRoot, name => ROUTE_FILE_PATTERN.test(name)); const operations: DiscoveredApiOperation[] = []; + const configFile = ts.readConfigFile(path.join(projectRoot, 'tsconfig.json'), ts.sys.readFile); + const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, projectRoot); + const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options); + const checker = program.getTypeChecker(); for (const routeFile of routeFiles.sort()) { - const content = await readFile(routeFile, 'utf8'); - const source = ts.createSourceFile( - routeFile, - content, - ts.ScriptTarget.Latest, - true, - routeFile.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS, - ); + const source = + program.getSourceFile(routeFile) ?? + ts.createSourceFile( + routeFile, + await readFile(routeFile, 'utf8'), + ts.ScriptTarget.Latest, + true, + routeFile.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS, + ); const routePath = getRoutePath(apiRoot, routeFile); const relativeSource = path.relative(projectRoot, routeFile).replaceAll(path.sep, '/'); @@ -121,7 +126,7 @@ export async function discoverApiOperations( method, path: routePath, source: relativeSource, - analysis: analyzeSourceOperation(source, method), + analysis: analyzeSourceOperation(source, method, checker), }); }); } @@ -134,5 +139,7 @@ export async function discoverApiOperations( export async function discoverContractFiles(projectRoot = process.cwd()) { const apiRoot = path.join(projectRoot, 'src', 'app', 'api'); - return (await walk(apiRoot, name => name === 'contract.ts')).sort(); + return ( + await walk(apiRoot, name => name === 'contract.ts' || name === 'contract.generated.ts') + ).sort(); } diff --git a/src/openapi/document.ts b/src/openapi/document.ts index 843a69ca4..783172a00 100644 --- a/src/openapi/document.ts +++ b/src/openapi/document.ts @@ -10,6 +10,7 @@ import { import { discoverApiOperations } from '@/openapi/discover'; import { inferApiContracts } from '@/openapi/infer'; import type { ApiAudience } from '@/openapi/operation'; +import { errorResponseComponents } from '@/openapi/schemas'; import { getSecurityRequirements, securitySchemes } from '@/openapi/security'; export type DocumentAudience = ApiAudience | 'all'; @@ -108,6 +109,7 @@ export async function buildOpenApiDocument( paths, components: { securitySchemes, + responses: errorResponseComponents, }, }, { diff --git a/src/openapi/infer.ts b/src/openapi/infer.ts index 9efd7fd43..13fcf9cf0 100644 --- a/src/openapi/infer.ts +++ b/src/openapi/infer.ts @@ -74,7 +74,7 @@ function pascalCase(value: string) { } function getOperationId(method: ApiHttpMethod, path: string) { - return `inferred${pascalCase(method)}${getPathSegments(path).map(pascalCase).join('')}`; + return `${method}${getPathSegments(path).map(pascalCase).join('')}`; } function getSummary(method: ApiHttpMethod, path: string) { @@ -144,18 +144,25 @@ function getQueryParameters(schema: InferredOpenApiSchema | undefined) { })); } -function successResponse(mediaType: string, returnsOk: boolean): ZodOpenApiResponseObject { +function successResponse( + mediaType: string, + returnsOk: boolean, + schema?: InferredOpenApiSchema, +): ZodOpenApiResponseObject { return { - description: returnsOk - ? 'The operation completed successfully.' - : 'Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema.', + description: + schema || returnsOk + ? 'The operation completed successfully.' + : 'Successful response. The response shape is inferred as free-form because the handler does not expose a reusable response schema.', content: { [mediaType]: { - schema: returnsOk - ? okSchema - : mediaType === 'application/json' - ? ({} as ZodOpenApiSchemaObject) - : ({ type: 'string' } as ZodOpenApiSchemaObject), + schema: schema + ? (schema as ZodOpenApiSchemaObject) + : returnsOk + ? okSchema + : mediaType === 'application/json' + ? ({} as ZodOpenApiSchemaObject) + : ({ type: 'string' } as ZodOpenApiSchemaObject), }, }, }; @@ -168,7 +175,11 @@ function getResponses(operation: DiscoveredApiOperation): ZodOpenApiResponsesObj const response = errorResponses[status]; responses[`${status}` as `${1 | 2 | 3 | 4 | 5}${string}`] = response ?? - successResponse(operation.analysis.responseMediaType, operation.analysis.returnsOk); + successResponse( + operation.analysis.responseMediaType, + operation.analysis.returnsOk, + operation.analysis.responseSchemas[status], + ); }); return responses; diff --git a/src/openapi/schemas.ts b/src/openapi/schemas.ts index 958026b40..0600ee202 100644 --- a/src/openapi/schemas.ts +++ b/src/openapi/schemas.ts @@ -87,3 +87,13 @@ export const serviceUnavailableResponse = errorResponse( 'service-unavailable', 'Service unavailable.', ); + +export const errorResponseComponents = { + BadRequestResponse: badRequestResponse, + UnauthorizedResponse: unauthorizedResponse, + ForbiddenResponse: forbiddenResponse, + NotFoundResponse: notFoundResponse, + PayloadTooLargeResponse: payloadTooLargeResponse, + ServerErrorResponse: serverErrorResponse, + ServiceUnavailableResponse: serviceUnavailableResponse, +}; diff --git a/src/openapi/source-analysis.ts b/src/openapi/source-analysis.ts index db14c23c2..f2bb420bd 100644 --- a/src/openapi/source-analysis.ts +++ b/src/openapi/source-analysis.ts @@ -30,6 +30,7 @@ export interface SourceOperationAnalysis { hasRequestSchema: boolean; requestSchema?: Schema; responseStatuses: number[]; + responseSchemas: Record; responseMediaType: string; returnsOk: boolean; } @@ -56,6 +57,161 @@ const numberSchema = (): Schema => ({ type: 'number' }); const booleanSchema = (): Schema => ({ type: 'boolean' }); const unknownSchema = (): Schema => ({}); +function isUnknownSchema(schema: Schema) { + return Object.keys(schema).length === 0; +} + +function typeToSchema( + type: ts.Type, + checker: ts.TypeChecker, + location: ts.Node, + seen = new Set(), + depth = 0, +): Schema { + if (depth > 12 || seen.has(type)) { + return unknownSchema(); + } + + if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.TypeParameter)) { + return unknownSchema(); + } + + if (type.flags & ts.TypeFlags.Never) { + return unknownSchema(); + } + + if (type.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void | ts.TypeFlags.Null)) { + return { type: 'null' }; + } + + if (type.isStringLiteral()) { + return { const: type.value }; + } + + if (type.flags & (ts.TypeFlags.String | ts.TypeFlags.TemplateLiteral)) { + return stringSchema(); + } + + if (type.isNumberLiteral()) { + return { const: type.value }; + } + + if (type.flags & (ts.TypeFlags.Number | ts.TypeFlags.BigInt)) { + return numberSchema(); + } + + if (type.flags & ts.TypeFlags.BooleanLiteral) { + return { const: checker.typeToString(type) === 'true' }; + } + + if (type.flags & ts.TypeFlags.Boolean) { + return booleanSchema(); + } + + if (type.isUnion()) { + const variants = type.types + .filter(variant => !(variant.flags & ts.TypeFlags.Undefined)) + .map(variant => typeToSchema(variant, checker, location, new Set(seen), depth + 1)); + const unique = [...new Map(variants.map(schema => [JSON.stringify(schema), schema])).values()]; + + if (unique.length === 0) return unknownSchema(); + if (unique.length === 1) return unique[0]; + return { anyOf: unique }; + } + + if (type.isIntersection()) { + return { + allOf: type.types.map(variant => + typeToSchema(variant, checker, location, new Set(seen), depth + 1), + ), + }; + } + + const symbolName = type.aliasSymbol?.getName() ?? type.getSymbol()?.getName(); + const promised = symbolName === 'Promise' ? checker.getAwaitedType(type) : undefined; + if (promised && promised !== type) { + return typeToSchema(promised, checker, location, seen, depth + 1); + } + + if (symbolName === 'Date') { + return { type: 'string', format: 'date-time' }; + } + + if (checker.isTupleType(type)) { + const typeArguments = checker.getTypeArguments(type as ts.TypeReference); + const prefixItems = typeArguments.map(item => + typeToSchema(item, checker, location, new Set(seen), depth + 1), + ); + return { + type: 'array', + prefixItems, + minItems: prefixItems.length, + maxItems: prefixItems.length, + }; + } + + if (checker.isArrayType(type)) { + const item = checker.getTypeArguments(type as ts.TypeReference)[0]; + return { + type: 'array', + items: item + ? typeToSchema(item, checker, location, new Set(seen), depth + 1) + : unknownSchema(), + }; + } + + if (type.flags & ts.TypeFlags.Object) { + const nextSeen = new Set(seen); + nextSeen.add(type); + const properties: Record = {}; + const requiredProperties: string[] = []; + + checker.getPropertiesOfType(type).forEach(property => { + if (property.getName().startsWith('__@')) { + return; + } + + const declaration = property.valueDeclaration ?? property.declarations?.[0] ?? location; + const propertyType = checker.getTypeOfSymbolAtLocation(property, declaration); + + // Functions are not JSON values. This also prevents array prototype methods from + // leaking into schemas when an array is spread into an object literal. + if (propertyType.getCallSignatures().length) { + return; + } + + properties[property.getName()] = typeToSchema( + propertyType, + checker, + declaration, + new Set(nextSeen), + depth + 1, + ); + + if (!(property.flags & ts.SymbolFlags.Optional)) { + requiredProperties.push(property.getName()); + } + }); + + const stringIndex = checker.getIndexTypeOfType(type, ts.IndexKind.String); + const schema = objectSchema(properties, requiredProperties); + + if (stringIndex) { + schema.additionalProperties = typeToSchema( + stringIndex, + checker, + location, + new Set(nextSeen), + depth + 1, + ); + } + + return schema; + } + + return unknownSchema(); +} + function required(schema: Schema): InferredSchema { return { schema, optional: false }; } @@ -638,6 +794,7 @@ function getNumericStatus(options: ts.Expression | undefined, source: ts.SourceF export function analyzeSourceOperation( source: ts.SourceFile, method: ApiHttpMethod, + checker?: ts.TypeChecker, ): SourceOperationAnalysis { const handler = findHandler(source, method); @@ -646,6 +803,7 @@ export function analyzeSourceOperation( auth: 'bearer', hasRequestSchema: false, responseStatuses: [200], + responseSchemas: {}, responseMediaType: 'application/json', returnsOk: false, }; @@ -668,6 +826,23 @@ export function analyzeSourceOperation( let returnsOk = false; let responseMediaType = 'application/json'; const responseStatuses = new Set(); + const responseSchemaVariants = new Map(); + + const addResponseSchema = (status: number, expression: ts.Expression | undefined) => { + if (!expression) { + return; + } + + const syntactic = inferExpression(expression, source, declarations).schema; + const typed = checker + ? typeToSchema(checker.getTypeAtLocation(expression), checker, expression) + : unknownSchema(); + const schema = isUnknownSchema(typed) ? syntactic : typed; + + if (!isUnknownSchema(schema)) { + responseSchemaVariants.set(status, [...(responseSchemaVariants.get(status) ?? []), schema]); + } + }; const visit = (node: ts.Node) => { if (ts.isCallExpression(node)) { @@ -691,10 +866,21 @@ export function analyzeSourceOperation( if (mappedStatus) { responseStatuses.add(mappedStatus); returnsOk ||= name === 'ok'; + + if (name === 'ok') { + responseSchemaVariants.set(mappedStatus, [ + ...(responseSchemaVariants.get(mappedStatus) ?? []), + objectSchema({ ok: { const: true } }), + ]); + } else if (name === 'json') { + addResponseSchema(mappedStatus, node.arguments[0]); + } } if (calleeText === 'Response.json') { - responseStatuses.add(getNumericStatus(node.arguments[1], source) ?? 200); + const status = getNumericStatus(node.arguments[1], source) ?? 200; + responseStatuses.add(status); + addResponseSchema(status, node.arguments[0]); } } @@ -731,6 +917,15 @@ export function analyzeSourceOperation( responseStatuses.add(200); } + const responseSchemas = Object.fromEntries( + [...responseSchemaVariants.entries()].map(([status, variants]) => { + const unique = [ + ...new Map(variants.map(schema => [JSON.stringify(schema), schema])).values(), + ]; + return [status, unique.length === 1 ? unique[0] : { anyOf: unique }]; + }), + ); + return { auth, hasRequestSchema, @@ -738,6 +933,7 @@ export function analyzeSourceOperation( ? inferExpression(schemaArgument, source, declarations).schema : undefined, responseStatuses: [...responseStatuses].sort((left, right) => left - right), + responseSchemas, responseMediaType, returnsOk, }; diff --git a/src/queries/prisma/annotation.ts b/src/queries/prisma/annotation.ts index 6d23f4cbb..940b1270c 100644 --- a/src/queries/prisma/annotation.ts +++ b/src/queries/prisma/annotation.ts @@ -1,6 +1,6 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Annotation, Prisma } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; export async function getAnnotation(annotationId: string) { return prisma.client.annotation.findUnique({ @@ -19,7 +19,7 @@ export async function getWebsiteAnnotation(websiteId: string, annotationId: stri export async function getWebsiteAnnotations( websiteId: string, filters: QueryFilters & { startDate?: Date; endDate?: Date } = {}, -) { +): Promise> { const { search, startDate, endDate } = filters; const { getSearchParameters, pagedQuery } = prisma; diff --git a/src/queries/prisma/board.ts b/src/queries/prisma/board.ts index d433850d7..48f806ac5 100644 --- a/src/queries/prisma/board.ts +++ b/src/queries/prisma/board.ts @@ -1,8 +1,8 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Board, Prisma } from '@/generated/prisma/client'; import { BOARD_TYPES } from '@/lib/boards'; import prisma from '@/lib/prisma'; import { sanitizeSortFilters } from '@/lib/sort'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; const BOARD_SORT_FIELDS = ['name', 'description', 'type', 'createdAt'] as const; @@ -18,7 +18,10 @@ export async function getBoard(boardId: string) { }); } -export async function getBoards(criteria: Prisma.BoardFindManyArgs, filters: QueryFilters = {}) { +export async function getBoards( + criteria: Prisma.BoardFindManyArgs, + filters: QueryFilters = {}, +): Promise> { const sortFilters = sanitizeSortFilters(filters, BOARD_SORT_FIELDS); const { search } = sortFilters; const { getSearchParameters, pagedQuery } = prisma; diff --git a/src/queries/prisma/link.ts b/src/queries/prisma/link.ts index c59adc025..ee8a8d631 100644 --- a/src/queries/prisma/link.ts +++ b/src/queries/prisma/link.ts @@ -1,7 +1,7 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Link, Prisma } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; import { sanitizeSortFilters } from '@/lib/sort'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; const LINK_SORT_FIELDS = ['name', 'slug', 'url', 'createdAt'] as const; @@ -17,7 +17,10 @@ export async function getLink(linkId: string) { }); } -export async function getLinks(criteria: Prisma.LinkFindManyArgs, filters: QueryFilters = {}) { +export async function getLinks( + criteria: Prisma.LinkFindManyArgs, + filters: QueryFilters = {}, +): Promise> { const sortFilters = sanitizeSortFilters(filters, LINK_SORT_FIELDS); const { search } = sortFilters; const { getSearchParameters, pagedQuery } = prisma; diff --git a/src/queries/prisma/pixel.ts b/src/queries/prisma/pixel.ts index 2ea9c6f28..bb81dca8f 100644 --- a/src/queries/prisma/pixel.ts +++ b/src/queries/prisma/pixel.ts @@ -1,7 +1,7 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Pixel, Prisma } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; import { sanitizeSortFilters } from '@/lib/sort'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; const PIXEL_SORT_FIELDS = ['name', 'slug', 'createdAt'] as const; @@ -17,7 +17,10 @@ export async function getPixel(pixelId: string) { }); } -export async function getPixels(criteria: Prisma.PixelFindManyArgs, filters: QueryFilters = {}) { +export async function getPixels( + criteria: Prisma.PixelFindManyArgs, + filters: QueryFilters = {}, +): Promise> { const sortFilters = sanitizeSortFilters(filters, PIXEL_SORT_FIELDS); const { search } = sortFilters; diff --git a/src/queries/prisma/report.ts b/src/queries/prisma/report.ts index f8a59d4a9..fb1d46d43 100644 --- a/src/queries/prisma/report.ts +++ b/src/queries/prisma/report.ts @@ -1,9 +1,16 @@ -import { Prisma } from '@/generated/prisma/client'; +import { Prisma, type Report } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; import ReportFindManyArgs = Prisma.ReportFindManyArgs; +export type ReportListItem = Report & { + website?: { + domain: string; + userId: string; + } | null; +}; + async function findReport(criteria: Prisma.ReportFindUniqueArgs) { return prisma.client.report.findUnique(criteria); } @@ -16,7 +23,10 @@ export async function getReport(reportId: string) { }); } -export async function getReports(criteria: ReportFindManyArgs, filters: QueryFilters = {}) { +export async function getReports( + criteria: ReportFindManyArgs, + filters: QueryFilters = {}, +): Promise> { const { search } = filters; const orderBy = criteria.orderBy ?? [{ name: 'asc' }, { id: 'asc' }]; diff --git a/src/queries/prisma/segment.ts b/src/queries/prisma/segment.ts index 3a17d2735..6f00d476c 100644 --- a/src/queries/prisma/segment.ts +++ b/src/queries/prisma/segment.ts @@ -1,6 +1,6 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Prisma, Segment } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; async function findSegment(criteria: Prisma.SegmentFindUniqueArgs) { return prisma.client.segment.findUnique(criteria); @@ -14,7 +14,10 @@ export async function getSegment(segmentId: string) { }); } -export async function getSegments(criteria: Prisma.SegmentFindManyArgs, filters: QueryFilters) { +export async function getSegments( + criteria: Prisma.SegmentFindManyArgs, + filters: QueryFilters, +): Promise> { const { search } = filters; const { getSearchParameters, pagedQuery } = prisma; diff --git a/src/queries/prisma/sessionReplay.ts b/src/queries/prisma/sessionReplay.ts index 2eb7ab922..c97be31b3 100644 --- a/src/queries/prisma/sessionReplay.ts +++ b/src/queries/prisma/sessionReplay.ts @@ -1,6 +1,7 @@ +import type { SessionReplaySaved } from '@/generated/prisma/client'; import { uuid } from '@/lib/crypto'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; export interface CreateReplayChunkArgs { websiteId: string; @@ -91,7 +92,10 @@ export async function deleteReplaySaved(websiteId: string, visitId: string) { }); } -export async function getSavedReplays(websiteId: string, filters: QueryFilters) { +export async function getSavedReplays( + websiteId: string, + filters: QueryFilters, +): Promise> { const { search } = filters; const { getSearchParameters, pagedQuery } = prisma; diff --git a/src/queries/prisma/share.ts b/src/queries/prisma/share.ts index 146f11ee9..85fa0bfa0 100644 --- a/src/queries/prisma/share.ts +++ b/src/queries/prisma/share.ts @@ -1,6 +1,6 @@ -import type { Prisma } from '@/generated/prisma/client'; +import type { Prisma, Share } from '@/generated/prisma/client'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; export async function findShare(criteria: Prisma.ShareFindUniqueArgs) { return prisma.client.share.findUnique(criteria); @@ -33,7 +33,10 @@ export async function getShareByEntityId(entityId: string) { }); } -export async function getSharesByEntityId(entityId: string, filters?: QueryFilters) { +export async function getSharesByEntityId( + entityId: string, + filters?: QueryFilters, +): Promise> { const { pagedQuery } = prisma; return pagedQuery( diff --git a/src/queries/prisma/team.ts b/src/queries/prisma/team.ts index 3428d9ee0..00c16718a 100644 --- a/src/queries/prisma/team.ts +++ b/src/queries/prisma/team.ts @@ -1,4 +1,4 @@ -import { Prisma, type Team } from '@/generated/prisma/client'; +import { Prisma, type Team, type TeamUser } from '@/generated/prisma/client'; import { ROLES } from '@/lib/constants'; import { uuid } from '@/lib/crypto'; import prisma from '@/lib/prisma'; @@ -123,7 +123,10 @@ export async function getTeamOwner(teamId: string) { }); } -export async function createTeam(data: Prisma.TeamCreateInput, userId: string): Promise { +export async function createTeam( + data: Prisma.TeamCreateInput, + userId: string, +): Promise<[Team, TeamUser]> { const { id } = data; const { client, transaction } = prisma; @@ -139,7 +142,7 @@ export async function createTeam(data: Prisma.TeamCreateInput, userId: string): role: ROLES.teamOwner, }, }), - ]); + ]) as Promise<[Team, TeamUser]>; } export async function updateTeam(teamId: string, data: Prisma.TeamUpdateInput): Promise { diff --git a/src/queries/prisma/teamUser.ts b/src/queries/prisma/teamUser.ts index 2210deeb5..4f4027d67 100644 --- a/src/queries/prisma/teamUser.ts +++ b/src/queries/prisma/teamUser.ts @@ -1,10 +1,17 @@ -import { Prisma } from '@/generated/prisma/client'; +import { Prisma, type TeamUser } from '@/generated/prisma/client'; import { uuid } from '@/lib/crypto'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters } from '@/lib/types'; import TeamUserFindManyArgs = Prisma.TeamUserFindManyArgs; +export type TeamUserListItem = TeamUser & { + user?: { + id: string; + username: string; + }; +}; + export async function findTeamUser(criteria: Prisma.TeamUserFindUniqueArgs) { return prisma.client.teamUser.findUnique(criteria); } @@ -18,7 +25,10 @@ export async function getTeamUser(teamId: string, userId: string) { }); } -export async function getTeamUsers(criteria: TeamUserFindManyArgs, filters?: QueryFilters) { +export async function getTeamUsers( + criteria: TeamUserFindManyArgs, + filters?: QueryFilters, +): Promise> { const { search } = filters; const where: Prisma.TeamUserWhereInput = { diff --git a/src/queries/prisma/user.ts b/src/queries/prisma/user.ts index 17a254ca5..9fe508328 100644 --- a/src/queries/prisma/user.ts +++ b/src/queries/prisma/user.ts @@ -4,7 +4,7 @@ import { getRandomChars } from '@/lib/generate'; import prisma from '@/lib/prisma'; import redis from '@/lib/redis'; import { sanitizeSortFilters } from '@/lib/sort'; -import type { QueryFilters, Role } from '@/lib/types'; +import type { PageResult, QueryFilters, Role } from '@/lib/types'; import UserFindManyArgs = Prisma.UserFindManyArgs; @@ -15,6 +15,17 @@ export interface GetUserOptions { showDeleted?: boolean; } +export interface UserSummary { + id: string; + username: string; + role: string; + createdAt: Date; + twoFactorRequired: boolean; + _count?: { + websites: number; + }; +} + async function findUser(criteria: Prisma.UserFindUniqueArgs, options: GetUserOptions = {}) { const { includePassword = false, showDeleted = false } = options; @@ -50,7 +61,10 @@ export async function getUserByUsername(username: string, options: GetUserOption return findUser({ where: { username: username.toLowerCase() } }, options); } -export async function getUsers(criteria: UserFindManyArgs, filters: QueryFilters = {}) { +export async function getUsers( + criteria: UserFindManyArgs, + filters: QueryFilters = {}, +): Promise> { const sortFilters = sanitizeSortFilters(filters, USER_SORT_FIELDS, { orderBy: 'createdAt', sortDescending: true, diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts index 60a342138..707ff1683 100644 --- a/src/queries/prisma/website.ts +++ b/src/queries/prisma/website.ts @@ -1,13 +1,22 @@ +import { z } from 'zod'; import type { Prisma, Website } from '@/generated/prisma/client'; import { ROLES } from '@/lib/constants'; import prisma, { getSchema } from '@/lib/prisma'; import redis from '@/lib/redis'; import { sanitizeSortFilters } from '@/lib/sort'; -import type { QueryFilters } from '@/lib/types'; -import { z } from 'zod'; +import type { PageResult, QueryFilters } from '@/lib/types'; const WEBSITE_SORT_FIELDS = ['name', 'domain', 'createdAt'] as const; +export type WebsiteListItem = Website & { + shareId: string | null; + user?: { id: string; username: string } | null; + createUser?: { id: string; username: string } | null; + team?: { + members: { userId: string; role: string }[]; + } | null; +}; + async function deleteWebsiteDependentData(tx: any, websiteId: string) { await tx.sessionReplaySaved.deleteMany({ where: { websiteId }, @@ -86,7 +95,10 @@ export async function getWebsite(websiteId: string) { return attachShareIdToWebsite(website); } -export async function getWebsites(criteria: Prisma.WebsiteFindManyArgs, filters: QueryFilters) { +export async function getWebsites( + criteria: Prisma.WebsiteFindManyArgs, + filters: QueryFilters, +): Promise> { const sortFilters = sanitizeSortFilters(filters, WEBSITE_SORT_FIELDS); const { search } = sortFilters; const { getSearchParameters, pagedQuery } = prisma; @@ -307,14 +319,9 @@ export async function attachShareIdToWebsite(website: Website) { }; } -export async function attachShareIdToWebsites(websites: { - data: any; - count: any; - page: number; - pageSize: number; - orderBy: string; - search: string; -}) { +export async function attachShareIdToWebsites( + websites: PageResult<(Website & Partial)[]>, +): Promise> { const websiteIds = websites.data.map(website => website.id); if (websiteIds.length === 0) { diff --git a/src/queries/sql/events/getEventDataFields.ts b/src/queries/sql/events/getEventDataFields.ts index 3d3643f38..39a5d0c54 100644 --- a/src/queries/sql/events/getEventDataFields.ts +++ b/src/queries/sql/events/getEventDataFields.ts @@ -1,13 +1,13 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PropertyMetric, QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getEventDataFields'; export async function getEventDataFields( ...args: [websiteId: string, eventName: string | undefined, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/events/getEventDataNumericSeries.ts b/src/queries/sql/events/getEventDataNumericSeries.ts index d9df94f54..5cd9fd546 100644 --- a/src/queries/sql/events/getEventDataNumericSeries.ts +++ b/src/queries/sql/events/getEventDataNumericSeries.ts @@ -1,7 +1,7 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { EventPropertyFilter, QueryFilters } from '@/lib/types'; +import type { EventPropertyFilter, QueryFilters, TimeSeriesValue } from '@/lib/types'; const FUNCTION_NAME = 'getEventDataNumericSeries'; @@ -14,7 +14,7 @@ export async function getEventDataNumericSeries( filters: QueryFilters, eventFilters?: EventPropertyFilter[], ] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/events/getEventDataPivot.ts b/src/queries/sql/events/getEventDataPivot.ts index 210a7cdc6..a0d2cb019 100644 --- a/src/queries/sql/events/getEventDataPivot.ts +++ b/src/queries/sql/events/getEventDataPivot.ts @@ -1,7 +1,7 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { EventPropertyFilter, QueryFilters } from '@/lib/types'; +import type { EventDataPivotRow, EventPropertyFilter, PageResult, QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getEventDataPivot'; @@ -12,7 +12,7 @@ export async function getEventDataPivot( filters: QueryFilters, eventFilters?: EventPropertyFilter[], ] -) { +): Promise> { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/events/getEventDataProperties.ts b/src/queries/sql/events/getEventDataProperties.ts index 943dca84d..f1fe55a7c 100644 --- a/src/queries/sql/events/getEventDataProperties.ts +++ b/src/queries/sql/events/getEventDataProperties.ts @@ -3,11 +3,18 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; +export interface EventDataProperty { + eventName: string; + propertyName: string; + dataType: number; + total: number; +} + const FUNCTION_NAME = 'getEventDataProperties'; export async function getEventDataProperties( ...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/events/getWebsiteEvents.ts b/src/queries/sql/events/getWebsiteEvents.ts index ca779c5ed..614133ad2 100644 --- a/src/queries/sql/events/getWebsiteEvents.ts +++ b/src/queries/sql/events/getWebsiteEvents.ts @@ -1,13 +1,14 @@ import clickhouse from '@/lib/clickhouse'; -import { DEFAULT_PAGE_SIZE } from '@/lib/constants'; -import { EVENT_TYPE } from '@/lib/constants'; +import { DEFAULT_PAGE_SIZE, EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters, WebsiteEvent } from '@/lib/types'; const FUNCTION_NAME = 'getWebsiteEvents'; -export function getWebsiteEvents(...args: [websiteId: string, filters: QueryFilters]) { +export function getWebsiteEvents( + ...args: [websiteId: string, filters: QueryFilters] +): Promise> { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/getActiveVisitors.ts b/src/queries/sql/getActiveVisitors.ts index d763c12ec..a332a1ae4 100644 --- a/src/queries/sql/getActiveVisitors.ts +++ b/src/queries/sql/getActiveVisitors.ts @@ -2,10 +2,13 @@ import { subMinutes } from 'date-fns'; import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; +import type { ActiveVisitors } from '@/lib/types'; const FUNCTION_NAME = 'getActiveVisitors'; -export async function getActiveVisitors(...args: [websiteId: string]) { +export async function getActiveVisitors( + ...args: [websiteId: string] +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -30,7 +33,7 @@ async function relationalQuery(websiteId: string) { return result?.[0] ?? null; } -async function clickhouseQuery(websiteId: string): Promise<{ x: number }> { +async function clickhouseQuery(websiteId: string): Promise { const { rawQuery } = clickhouse; const startDate = subMinutes(new Date(), 5); diff --git a/src/queries/sql/getRealtimeActivity.ts b/src/queries/sql/getRealtimeActivity.ts index f328d6488..b34a9ff27 100644 --- a/src/queries/sql/getRealtimeActivity.ts +++ b/src/queries/sql/getRealtimeActivity.ts @@ -2,11 +2,13 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { QueryFilters, RealtimeActivity } from '@/lib/types'; const FUNCTION_NAME = 'getRealtimeActivity'; -export async function getRealtimeActivity(...args: [websiteId: string, filters: QueryFilters]) { +export async function getRealtimeActivity( + ...args: [websiteId: string, filters: QueryFilters] +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -50,7 +52,10 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ); } -async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promise<{ x: number }> { +async function clickhouseQuery( + websiteId: string, + filters: QueryFilters, +): Promise { const { rawQuery, parseFilters } = clickhouse; const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({ ...filters, diff --git a/src/queries/sql/getRealtimeData.ts b/src/queries/sql/getRealtimeData.ts index 4b97cb055..8afc620a0 100644 --- a/src/queries/sql/getRealtimeData.ts +++ b/src/queries/sql/getRealtimeData.ts @@ -1,4 +1,4 @@ -import type { QueryFilters } from '@/lib/types'; +import type { QueryFilters, RealtimeActivity, RealtimeData, RealtimeEvent } from '@/lib/types'; import { getRealtimeActivity } from '@/queries/sql/getRealtimeActivity'; import { getPageviewStats } from '@/queries/sql/pageviews/getPageviewStats'; import { getSessionStats } from '@/queries/sql/sessions/getSessionStats'; @@ -13,7 +13,10 @@ function increment(data: object, key: string) { } } -export async function getRealtimeData(websiteId: string, filters: QueryFilters) { +export async function getRealtimeData( + websiteId: string, + filters: QueryFilters, +): Promise { const [activity, pageviews, sessions] = await Promise.all([ getRealtimeActivity(websiteId, filters), getPageviewStats(websiteId, filters), @@ -24,14 +27,13 @@ export async function getRealtimeData(websiteId: string, filters: QueryFilters) const { countries, urls, referrers, events } = activity.reverse().reduce( ( - obj: { countries: any; urls: any; referrers: any; events: any }, - event: { - sessionId: string; - urlPath: string; - referrerDomain: string; - country: string; - eventName: string; + obj: { + countries: Record; + urls: Record; + referrers: Record; + events: RealtimeEvent[]; }, + event: RealtimeActivity, ) => { const { countries, urls, referrers, events } = obj; const { sessionId, urlPath, referrerDomain, country, eventName } = event; diff --git a/src/queries/sql/getWebsiteDateRange.ts b/src/queries/sql/getWebsiteDateRange.ts index d6333ad52..d5318e863 100644 --- a/src/queries/sql/getWebsiteDateRange.ts +++ b/src/queries/sql/getWebsiteDateRange.ts @@ -2,8 +2,11 @@ import clickhouse from '@/lib/clickhouse'; import { DEFAULT_RESET_DATE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; +import type { WebsiteDateRange } from '@/lib/types'; -export async function getWebsiteDateRange(...args: [websiteId: string]) { +export async function getWebsiteDateRange( + ...args: [websiteId: string] +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/getWeeklyTraffic.ts b/src/queries/sql/getWeeklyTraffic.ts index bd439841f..82ca6e123 100644 --- a/src/queries/sql/getWeeklyTraffic.ts +++ b/src/queries/sql/getWeeklyTraffic.ts @@ -6,7 +6,9 @@ import type { QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getWeeklyTraffic'; -export async function getWeeklyTraffic(...args: [websiteId: string, filters: QueryFilters]) { +export async function getWeeklyTraffic( + ...args: [websiteId: string, filters: QueryFilters] +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -88,8 +90,8 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) { return rawQuery(sql, queryParams, FUNCTION_NAME).then(formatResults); } -function formatResults(data: any) { - const days = []; +function formatResults(data: any): number[][] { + const days: number[][] = []; for (let i = 0; i < 7; i++) { days.push([]); diff --git a/src/queries/sql/replays/getSessionReplays.ts b/src/queries/sql/replays/getSessionReplays.ts index 4cff4103c..8bd8b076c 100644 --- a/src/queries/sql/replays/getSessionReplays.ts +++ b/src/queries/sql/replays/getSessionReplays.ts @@ -1,13 +1,13 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters, SessionReplaySummary } from '@/lib/types'; const FUNCTION_NAME = 'getSessionReplays'; export function getSessionReplays( ...args: [websiteId: string, filters: QueryFilters, sessionId?: string] -) { +): Promise> { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getAttribution.ts b/src/queries/sql/reports/getAttribution.ts index a25c92896..9e16ffa8f 100644 --- a/src/queries/sql/reports/getAttribution.ts +++ b/src/queries/sql/reports/getAttribution.ts @@ -25,7 +25,7 @@ export interface AttributionResult { export async function getAttribution( ...args: [websiteId: string, parameters: AttributionParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getBreakdown.ts b/src/queries/sql/reports/getBreakdown.ts index 57258013b..4995c9c1a 100644 --- a/src/queries/sql/reports/getBreakdown.ts +++ b/src/queries/sql/reports/getBreakdown.ts @@ -1,9 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { - EVENT_TYPE, - FILTER_COLUMNS, - SESSION_COLUMNS, -} from '@/lib/constants'; +import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -15,13 +11,17 @@ export interface BreakdownParameters { } export interface BreakdownData { - x: string; - y: number; + views: number; + visitors: number; + visits: number; + bounces: number; + totaltime: number; + [field: string]: string | number; } export async function getBreakdown( ...args: [websiteId: string, parameters: BreakdownParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -35,18 +35,19 @@ async function relationalQuery( ): Promise { const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma; const { startDate, endDate, fields } = parameters; - const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters( - { - ...filters, - websiteId, - startDate, - endDate, - eventType: EVENT_TYPE.pageView, - }, - { - joinSession: !!fields.find((name: string) => SESSION_COLUMNS.includes(name)), - }, - ); + const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } = + parseFilters( + { + ...filters, + websiteId, + startDate, + endDate, + eventType: EVENT_TYPE.pageView, + }, + { + joinSession: !!fields.find((name: string) => SESSION_COLUMNS.includes(name)), + }, + ); const needsBounceEvents = filters.excludeBounce !== true; const bounceQuery = needsBounceEvents ? `sum(case when t.c = 1 and coalesce(e.has_custom_event, 0) = 0 then 1 else 0 end) as "bounces",` diff --git a/src/queries/sql/reports/getFunnel.ts b/src/queries/sql/reports/getFunnel.ts index 72148ae43..eeccf9c69 100644 --- a/src/queries/sql/reports/getFunnel.ts +++ b/src/queries/sql/reports/getFunnel.ts @@ -32,7 +32,7 @@ export interface FunnelResult extends FunnelStep { export async function getFunnel( ...args: [websiteId: string, parameters: FunnelParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getGoal.ts b/src/queries/sql/reports/getGoal.ts index e6f425519..b29f2c078 100644 --- a/src/queries/sql/reports/getGoal.ts +++ b/src/queries/sql/reports/getGoal.ts @@ -11,9 +11,14 @@ export interface GoalParameters { value: string; } +export interface GoalResult { + num: number; + total: number; +} + export async function getGoal( ...args: [websiteId: string, params: GoalParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getJourney.ts b/src/queries/sql/reports/getJourney.ts index d12d371b6..66e8c2714 100644 --- a/src/queries/sql/reports/getJourney.ts +++ b/src/queries/sql/reports/getJourney.ts @@ -24,7 +24,7 @@ export interface JourneyResult { export async function getJourney( ...args: [websiteId: string, parameters: JourneyParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getRetention.ts b/src/queries/sql/reports/getRetention.ts index 6e1c60db9..a48710381 100644 --- a/src/queries/sql/reports/getRetention.ts +++ b/src/queries/sql/reports/getRetention.ts @@ -19,7 +19,7 @@ export interface RetentionResult { export async function getRetention( ...args: [websiteId: string, parameters: RetentionParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getRevenueChart.ts b/src/queries/sql/reports/getRevenueChart.ts index d95b42bf2..a2d8e7c27 100644 --- a/src/queries/sql/reports/getRevenueChart.ts +++ b/src/queries/sql/reports/getRevenueChart.ts @@ -13,9 +13,18 @@ export interface RevenuParameters { compare?: string; } +export interface RevenueChartResult { + chart: { + x: string; + t: string; + y: number; + count: number; + }[]; +} + export async function getRevenueChart( ...args: [websiteId: string, parameters: RevenuParameters, filters: QueryFilters] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getRevenueMetrics.ts b/src/queries/sql/reports/getRevenueMetrics.ts index fd9bf9863..ebb51a047 100644 --- a/src/queries/sql/reports/getRevenueMetrics.ts +++ b/src/queries/sql/reports/getRevenueMetrics.ts @@ -30,7 +30,7 @@ export async function getRevenueMetrics( filters: QueryFilters, type: RevenueMetricType, ] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/reports/getRevenueSessions.ts b/src/queries/sql/reports/getRevenueSessions.ts index f7aa70dd0..969d3befc 100644 --- a/src/queries/sql/reports/getRevenueSessions.ts +++ b/src/queries/sql/reports/getRevenueSessions.ts @@ -2,13 +2,13 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters, WebsiteSession } from '@/lib/types'; const FUNCTION_NAME = 'getRevenueSessions'; export async function getRevenueSessions( ...args: [websiteId: string, currency: string, filters: QueryFilters] -) { +): Promise> { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/sessions/getSessionData.ts b/src/queries/sql/sessions/getSessionData.ts index 8f1e49332..cac326610 100644 --- a/src/queries/sql/sessions/getSessionData.ts +++ b/src/queries/sql/sessions/getSessionData.ts @@ -1,10 +1,13 @@ import clickhouse from '@/lib/clickhouse'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; +import type { SessionDataValue } from '@/lib/types'; const FUNCTION_NAME = 'getSessionData'; -export async function getSessionData(...args: [websiteId: string, sessionId: string]) { +export async function getSessionData( + ...args: [websiteId: string, sessionId: string] +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/sessions/getSessionDataNumericSeries.ts b/src/queries/sql/sessions/getSessionDataNumericSeries.ts index 64f74fc25..1d22c6ff8 100644 --- a/src/queries/sql/sessions/getSessionDataNumericSeries.ts +++ b/src/queries/sql/sessions/getSessionDataNumericSeries.ts @@ -2,7 +2,7 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { PropertyFilter, QueryFilters } from '@/lib/types'; +import type { PropertyFilter, QueryFilters, TimeSeriesValue } from '@/lib/types'; const FUNCTION_NAME = 'getSessionDataNumericSeries'; @@ -14,7 +14,7 @@ export async function getSessionDataNumericSeries( filters: QueryFilters, propertyFilters?: PropertyFilter[], ] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/sessions/getSessionDataProperties.ts b/src/queries/sql/sessions/getSessionDataProperties.ts index 1d81c7bd0..53e8e89cf 100644 --- a/src/queries/sql/sessions/getSessionDataProperties.ts +++ b/src/queries/sql/sessions/getSessionDataProperties.ts @@ -2,7 +2,7 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { PropertyFilter, QueryFilters } from '@/lib/types'; +import type { PropertyFilter, PropertyMetric, QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getSessionDataProperties'; @@ -13,7 +13,7 @@ export async function getSessionDataProperties( propertyFilters?: PropertyFilter[], propertyName?: string, ] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), diff --git a/src/queries/sql/sessions/getSessionDataValues.ts b/src/queries/sql/sessions/getSessionDataValues.ts index d862fa66a..f3d9bf486 100644 --- a/src/queries/sql/sessions/getSessionDataValues.ts +++ b/src/queries/sql/sessions/getSessionDataValues.ts @@ -2,13 +2,13 @@ import clickhouse from '@/lib/clickhouse'; import { DATA_TYPE, EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PropertyValue, QueryFilters } from '@/lib/types'; const FUNCTION_NAME = 'getSessionDataValues'; export async function getSessionDataValues( ...args: [websiteId: string, filters: QueryFilters & { propertyName?: string; dataType?: number }] -) { +): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args), @@ -87,7 +87,7 @@ async function relationalQuery( async function clickhouseQuery( websiteId: string, filters: QueryFilters & { propertyName?: string; dataType?: number }, -): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { +): Promise { const { rawQuery, parseFilters } = clickhouse; const { dataType } = filters; const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId }); diff --git a/src/queries/sql/sessions/getWebsiteSessions.ts b/src/queries/sql/sessions/getWebsiteSessions.ts index 641099469..9bf0a232f 100644 --- a/src/queries/sql/sessions/getWebsiteSessions.ts +++ b/src/queries/sql/sessions/getWebsiteSessions.ts @@ -2,14 +2,16 @@ import clickhouse from '@/lib/clickhouse'; import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; -import type { QueryFilters } from '@/lib/types'; +import type { PageResult, QueryFilters, WebsiteSession } from '@/lib/types'; const FUNCTION_NAME = 'getWebsiteSessions'; const QUALIFIED_FILTER_COLUMNS = Object.fromEntries( Object.entries(FILTER_COLUMNS).map(([key, value]) => [key, `website_event.${value}`]), ); -export async function getWebsiteSessions(...args: [websiteId: string, filters: QueryFilters]) { +export async function getWebsiteSessions( + ...args: [websiteId: string, filters: QueryFilters] +): Promise> { return runQuery({ [PRISMA]: () => relationalQuery(...args), [CLICKHOUSE]: () => clickhouseQuery(...args),