diff --git a/frameworks-elysia/.gitignore b/frameworks-elysia/.gitignore new file mode 100644 index 00000000..87e56100 --- /dev/null +++ b/frameworks-elysia/.gitignore @@ -0,0 +1,42 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +**/*.trace +**/*.zip +**/*.tar.gz +**/*.tgz +**/*.log +package-lock.json +**/*.bun \ No newline at end of file diff --git a/frameworks-elysia/README.md b/frameworks-elysia/README.md new file mode 100644 index 00000000..1d130121 --- /dev/null +++ b/frameworks-elysia/README.md @@ -0,0 +1,54 @@ +# Elysia Train Travel OpenAPI example + +This Elysia app demonstrates Speakeasy-focused OpenAPI practices using the Train Travel domain from the Bump example API. + +The sample includes resource-style endpoints for: + +- `GET /stations` +- `GET /trips` +- `GET /bookings` +- `POST /bookings` +- `GET /bookings/{bookingId}` +- `DELETE /bookings/{bookingId}` +- `POST /bookings/{bookingId}/payment` + +The OpenAPI output is generated from route metadata using `@elysia/openapi` and exported to YAML for SDK generation. + +## Prerequisites + +- Bun +- Speakeasy CLI (optional, for SDK generation) + +## Install + +```bash +bun install +``` + +## Run the server + +```bash +bun run dev +``` + +Scalar UI is available at `http://localhost:3000/openapi`. + +## Generate OpenAPI YAML + +Run: + +```bash +bun run generate:openapi +``` + +This writes `openapi.yaml` in the project root. + +## Generate SDKs with Speakeasy + +```bash +speakeasy quickstart +``` + +## License + +Apache 2.0 diff --git a/frameworks-elysia/bun.lockb b/frameworks-elysia/bun.lockb new file mode 100755 index 00000000..5f12ad91 Binary files /dev/null and b/frameworks-elysia/bun.lockb differ diff --git a/frameworks-elysia/openapi.yaml b/frameworks-elysia/openapi.yaml new file mode 100644 index 00000000..4a92e369 --- /dev/null +++ b/frameworks-elysia/openapi.yaml @@ -0,0 +1,1267 @@ +info: + title: Train Travel API + description: API for finding and booking train trips across Europe. + version: 2.0.0 + contact: + name: Train Support + url: https://example.com/support + email: support@example.com +servers: + - url: https://api.example.com + description: Production + - url: http://localhost:3000 + description: Development server +security: + - OAuth2: + - read +components: + securitySchemes: + OAuth2: + type: oauth2 + description: OAuth 2.0 authorization code flow. + flows: + authorizationCode: + authorizationUrl: https://example.com/oauth/authorize + tokenUrl: https://example.com/oauth/token + scopes: + read: Read access + write: Write access + schemas: {} +x-speakeasy-retries: + strategy: backoff + backoff: + initialInterval: 500 + maxInterval: 60000 + maxElapsedTime: 3600000 + exponent: 1.5 + statusCodes: + - 5XX + retryConnectionErrors: true +tags: + - name: Stations + description: >- + Find and filter train stations across Europe, including their location and + local timezone. + - name: Trips + description: >- + Timetables and routes for train trips between stations, including pricing + and availability. + - name: Bookings + description: >- + Create and manage bookings for train trips, including passenger details + and optional extras. + - name: Payments + description: >- + Pay for bookings using a card or bank account, and view payment status and + history. +openapi: 3.1.2 +paths: + /stations/: + get: + operationId: get-stations + summary: Get a list of train stations + description: Returns a paginated and searchable list of all train stations. + tags: + - Stations + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + required: + - data + - links + properties: + data: + type: array + items: + description: A train station. + type: object + required: + - id + - name + - address + - country_code + - timezone + properties: + id: + format: uuid + example: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + type: string + name: + example: Berlin Hauptbahnhof + type: string + address: + example: Invalidenstrasse 10557 Berlin, Germany + type: string + country_code: + example: DE + type: string + timezone: + example: Europe/Berlin + type: string + links: + type: object + allOf: + - type: object + required: + - self + properties: + self: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + - type: object + properties: + next: + format: uri + example: https://api.example.com/bookings?page=2 + type: string + prev: + format: uri + example: https://api.example.com/bookings?page=1 + type: string + '400': + description: Bad Request + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: page + in: query + required: false + schema: + minimum: 1 + default: 1 + type: number + - name: limit + in: query + required: false + schema: + minimum: 1 + maximum: 100 + default: 10 + type: number + - name: coordinates + in: query + required: false + schema: + example: 52.5200,13.4050 + type: string + - name: search + in: query + required: false + schema: + example: Milano Centrale + type: string + - name: country + in: query + required: false + schema: + minLength: 2 + maxLength: 2 + example: DE + type: string + /trips/: + get: + operationId: get-trips + summary: Get available train trips + description: >- + Returns a list of available train trips between the specified origin and + destination stations on the given date. + tags: + - Trips + responses: + '200': + description: A list of available train trips + content: + application/json: + schema: + type: object + required: + - data + - links + properties: + data: + type: array + items: + description: A train trip. + type: object + required: + - id + - origin + - destination + - departure_time + - arrival_time + - operator + - price + - bicycles_allowed + - dogs_allowed + properties: + id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + origin: + format: uuid + example: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + type: string + destination: + format: uuid + example: b2e783e1-c824-4d63-b37a-d8d698862f1d + type: string + departure_time: + format: date-time + example: '2024-02-01T10:00:00Z' + type: string + arrival_time: + format: date-time + example: '2024-02-01T16:00:00Z' + type: string + operator: + example: Deutsche Bahn + type: string + price: + example: 50 + type: number + bicycles_allowed: + example: true + type: boolean + dogs_allowed: + example: true + type: boolean + links: + type: object + allOf: + - type: object + required: + - self + properties: + self: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + - type: object + properties: + next: + format: uri + example: https://api.example.com/bookings?page=2 + type: string + prev: + format: uri + example: https://api.example.com/bookings?page=1 + type: string + '400': + description: Bad Request + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: page + in: query + required: false + schema: + minimum: 1 + default: 1 + type: number + - name: limit + in: query + required: false + schema: + minimum: 1 + maximum: 100 + default: 10 + type: number + - name: origin + in: query + required: true + schema: + format: uuid + example: efdbb9d1-02c2-4bc3-afb7-6788d8782b1e + type: string + - name: destination + in: query + required: true + schema: + format: uuid + example: b2e783e1-c824-4d63-b37a-d8d698862f1d + type: string + - name: date + in: query + required: true + schema: + format: date-time + example: '2024-02-01T09:00:00Z' + type: string + - name: bicycles + in: query + required: false + schema: + default: false + type: boolean + - name: dogs + in: query + required: false + schema: + default: false + type: boolean + /bookings/: + get: + operationId: get-bookings + summary: List existing bookings + description: Returns a list of all trip bookings by the authenticated user. + tags: + - Bookings + responses: + '200': + description: A list of bookings + content: + application/json: + schema: + type: object + required: + - data + - links + properties: + data: + type: array + items: + description: A booking for a train trip. + type: object + required: + - id + - trip_id + - passenger_name + - has_bicycle + - has_dog + properties: + id: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + links: + type: object + allOf: + - type: object + required: + - self + properties: + self: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + - type: object + properties: + next: + format: uri + example: https://api.example.com/bookings?page=2 + type: string + prev: + format: uri + example: https://api.example.com/bookings?page=1 + type: string + '401': + description: Unauthorized + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + '500': + description: Internal Server Error + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: page + in: query + required: false + schema: + minimum: 1 + default: 1 + type: number + - name: limit + in: query + required: false + schema: + minimum: 1 + maximum: 100 + default: 10 + type: number + post: + operationId: create-booking + summary: Create a booking + description: >- + A booking is a temporary hold on a trip. It is not confirmed until + payment is processed. + tags: + - Bookings + security: + - OAuth2: + - write + x-speakeasy-retries: + strategy: backoff + backoff: + initialInterval: 300 + maxInterval: 40000 + maxElapsedTime: 3000000 + exponent: 1.2 + statusCodes: + - 5XX + retryConnectionErrors: true + responses: + '201': + description: Booking successful + content: + application/json: + schema: + type: object + allOf: + - description: A booking for a train trip. + type: object + required: + - id + - trip_id + - passenger_name + - has_bicycle + - has_dog + properties: + id: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + - type: object + required: + - links + properties: + links: + type: object + required: + - self + properties: + self: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + '404': + description: Not Found + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + '409': + description: Conflict + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + requestBody: + description: Booking details. + required: true + content: + application/json: + schema: + description: Booking details. + example: + trip_id: ea399ba1-6d95-433f-92d1-83f67b775594 + passenger_name: John Doe + has_bicycle: true + has_dog: false + type: object + required: + - trip_id + - passenger_name + properties: + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + application/x-www-form-urlencoded: + schema: + description: Booking details. + example: + trip_id: ea399ba1-6d95-433f-92d1-83f67b775594 + passenger_name: John Doe + has_bicycle: true + has_dog: false + type: object + required: + - trip_id + - passenger_name + properties: + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + multipart/form-data: + schema: + description: Booking details. + example: + trip_id: ea399ba1-6d95-433f-92d1-83f67b775594 + passenger_name: John Doe + has_bicycle: true + has_dog: false + type: object + required: + - trip_id + - passenger_name + properties: + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + /bookings/{bookingId}: + get: + operationId: get-booking + summary: Get a booking + description: Returns the details of a specific booking. + tags: + - Bookings + responses: + '200': + description: The booking details + content: + application/json: + schema: + type: object + allOf: + - description: A booking for a train trip. + type: object + required: + - id + - trip_id + - passenger_name + - has_bicycle + - has_dog + properties: + id: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + trip_id: + format: uuid + example: ea399ba1-6d95-433f-92d1-83f67b775594 + type: string + passenger_name: + example: John Doe + type: string + has_bicycle: + example: true + type: boolean + has_dog: + example: false + type: boolean + - type: object + required: + - links + properties: + links: + type: object + required: + - self + properties: + self: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + '404': + description: Not Found + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: bookingId + in: path + required: true + schema: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + delete: + operationId: delete-booking + summary: Delete a booking + description: Deletes a booking, cancelling the hold on the trip. + tags: + - Bookings + security: + - OAuth2: + - write + responses: + '204': + description: Booking deleted + '404': + description: Not Found + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: bookingId + in: path + required: true + schema: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + /bookings/{bookingId}/payment: + post: + operationId: create-booking-payment + summary: Pay for a booking + description: A payment attempt confirms the booking and enables ticket retrieval. + tags: + - Payments + responses: + '200': + description: Payment successful + content: + application/json: + schema: + type: object + allOf: + - type: object + required: + - id + - amount + - currency + - source + - status + properties: + id: + format: uuid + example: 2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a + type: string + amount: + example: 49.99 + type: number + currency: + example: gbp + type: string + source: + anyOf: + - type: object + required: + - object + - name + - number + - cvc + - exp_month + - exp_year + - address_country + properties: + object: + const: card + type: string + name: + example: J. Doe + type: string + number: + example: '4242424242424242' + type: string + cvc: + minLength: 3 + maxLength: 4 + example: '123' + type: string + exp_month: + example: 12 + type: number + exp_year: + example: 2025 + type: number + address_country: + example: gb + type: string + address_post_code: + example: N12 9XX + type: string + - type: object + required: + - object + - name + - number + - account_type + - bank_name + - country + properties: + object: + const: bank_account + type: string + name: + example: J. Doe + type: string + number: + example: '00012345' + type: string + sort_code: + example: '000123' + type: string + account_type: + anyOf: + - const: individual + type: string + - const: company + type: string + bank_name: + example: Starling Bank + type: string + country: + example: gb + type: string + status: + anyOf: + - const: pending + type: string + - const: succeeded + type: string + - const: failed + type: string + - type: object + required: + - links + properties: + links: + type: object + required: + - booking + properties: + booking: + format: uri + example: >- + https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + '404': + description: Not Found + content: + application/problem+json: + schema: + type: object + required: + - type + - title + - status + - detail + properties: + type: + example: https://example.com/errors/not-found + type: string + title: + example: Not Found + type: string + status: + example: 404 + type: number + detail: + example: The requested resource was not found. + type: string + parameters: + - name: bookingId + in: path + required: true + schema: + format: uuid + example: 1725ff48-ab45-4bb5-9d02-88745177dedb + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - amount + - currency + - source + properties: + amount: + exclusiveMinimum: 0 + example: 49.99 + type: number + currency: + type: string + enum: + - bam + - bgn + - chf + - eur + - gbp + - nok + - sek + promo_code: + anyOf: + - example: SUMMER20 + type: string + - type: 'null' + source: + anyOf: + - type: object + required: + - object + - name + - number + - cvc + - exp_month + - exp_year + - address_country + properties: + object: + const: card + type: string + name: + example: J. Doe + type: string + number: + example: '4242424242424242' + type: string + cvc: + minLength: 3 + maxLength: 4 + example: '123' + type: string + exp_month: + example: 12 + type: number + exp_year: + example: 2025 + type: number + address_country: + example: gb + type: string + address_post_code: + example: N12 9XX + type: string + - type: object + required: + - object + - name + - number + - account_type + - bank_name + - country + properties: + object: + const: bank_account + type: string + name: + example: J. Doe + type: string + number: + example: '00012345' + type: string + sort_code: + example: '000123' + type: string + account_type: + anyOf: + - const: individual + type: string + - const: company + type: string + bank_name: + example: Starling Bank + type: string + country: + example: gb + type: string + application/x-www-form-urlencoded: + schema: + type: object + required: + - amount + - currency + - source + properties: + amount: + exclusiveMinimum: 0 + example: 49.99 + type: number + currency: + type: string + enum: + - bam + - bgn + - chf + - eur + - gbp + - nok + - sek + promo_code: + anyOf: + - example: SUMMER20 + type: string + - type: 'null' + source: + anyOf: + - type: object + required: + - object + - name + - number + - cvc + - exp_month + - exp_year + - address_country + properties: + object: + const: card + type: string + name: + example: J. Doe + type: string + number: + example: '4242424242424242' + type: string + cvc: + minLength: 3 + maxLength: 4 + example: '123' + type: string + exp_month: + example: 12 + type: number + exp_year: + example: 2025 + type: number + address_country: + example: gb + type: string + address_post_code: + example: N12 9XX + type: string + - type: object + required: + - object + - name + - number + - account_type + - bank_name + - country + properties: + object: + const: bank_account + type: string + name: + example: J. Doe + type: string + number: + example: '00012345' + type: string + sort_code: + example: '000123' + type: string + account_type: + anyOf: + - const: individual + type: string + - const: company + type: string + bank_name: + example: Starling Bank + type: string + country: + example: gb + type: string + multipart/form-data: + schema: + type: object + required: + - amount + - currency + - source + properties: + amount: + exclusiveMinimum: 0 + example: 49.99 + type: number + currency: + type: string + enum: + - bam + - bgn + - chf + - eur + - gbp + - nok + - sek + promo_code: + anyOf: + - example: SUMMER20 + type: string + - type: 'null' + source: + anyOf: + - type: object + required: + - object + - name + - number + - cvc + - exp_month + - exp_year + - address_country + properties: + object: + const: card + type: string + name: + example: J. Doe + type: string + number: + example: '4242424242424242' + type: string + cvc: + minLength: 3 + maxLength: 4 + example: '123' + type: string + exp_month: + example: 12 + type: number + exp_year: + example: 2025 + type: number + address_country: + example: gb + type: string + address_post_code: + example: N12 9XX + type: string + - type: object + required: + - object + - name + - number + - account_type + - bank_name + - country + properties: + object: + const: bank_account + type: string + name: + example: J. Doe + type: string + number: + example: '00012345' + type: string + sort_code: + example: '000123' + type: string + account_type: + anyOf: + - const: individual + type: string + - const: company + type: string + bank_name: + example: Starling Bank + type: string + country: + example: gb + type: string diff --git a/frameworks-elysia/package.json b/frameworks-elysia/package.json new file mode 100644 index 00000000..98c55d96 --- /dev/null +++ b/frameworks-elysia/package.json @@ -0,0 +1,22 @@ +{ + "name": "speakeasy-elysia-openapi-example", + "version": "2.0.0", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "bun run --watch src/index.ts", + "generate:openapi": "bun run src/generateOpenAPIDocument.ts", + "postinstall": "cd node_modules/@elysia/openapi && bun install && bun run build" + }, + "dependencies": { + "@elysiajs/cors": "^1.4.2", + "@elysia/openapi": "^1.4.15", + "@sinclair/typebox": "^0.34.0", + "@types/js-yaml": "^4.0.9", + "elysia": "^1.4.19", + "js-yaml": "^4.2.0" + }, + "devDependencies": { + "bun-types": "latest" + }, + "module": "src/index.js" +} diff --git a/frameworks-elysia/sdk-typescript/.devcontainer/README.md b/frameworks-elysia/sdk-typescript/.devcontainer/README.md new file mode 100644 index 00000000..ce22244d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.devcontainer/README.md @@ -0,0 +1,30 @@ + +> **Remember to shutdown a GitHub Codespace when it is not in use!** + +# Dev Containers Quick Start + +The default location for usage snippets is the `samples` directory. + +## Running a Usage Sample + +A sample usage example has been provided in a `root.ts` file. As you work with the SDK, it's expected that you will modify these samples to fit your needs. To execute this particular snippet, use the command below. + +``` +ts-node root.ts +``` + +## Generating Additional Usage Samples + +The speakeasy CLI allows you to generate more usage snippets. Here's how: + +- To generate a sample for a specific operation by providing an operation ID, use: + +``` +speakeasy generate usage -s ./openapi.yaml -l typescript -i {INPUT_OPERATION_ID} -o ./samples +``` + +- To generate samples for an entire namespace (like a tag or group name), use: + +``` +speakeasy generate usage -s ./openapi.yaml -l typescript -n {INPUT_TAG_NAME} -o ./samples +``` diff --git a/frameworks-elysia/sdk-typescript/.devcontainer/devcontainer.json b/frameworks-elysia/sdk-typescript/.devcontainer/devcontainer.json new file mode 100644 index 00000000..4d560dd5 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.devcontainer/devcontainer.json @@ -0,0 +1,45 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/images/tree/main/src/typescript-node +{ + "name": "TypeScript", + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "sudo chmod +x ./.devcontainer/setup.sh && ./.devcontainer/setup.sh", + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.vscode-typescript-tslint-plugin", + "esbenp.prettier-vscode", + "github.vscode-pull-request-github" + ], + "settings": { + "files.eol": "\n", + "editor.formatOnSave": true, + "typescript.tsc.autoDetect": "on", + "typescript.updateImportsOnFileMove.enabled": "always", + "typescript.preferences.importModuleSpecifier": "relative", + "[typescript]": { + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + }, + "[typescriptreact]": { + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + } + } + }, + "codespaces": { + "openFiles": [ + ".devcontainer/README.md" + ] + } + } + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/frameworks-elysia/sdk-typescript/.devcontainer/setup.sh b/frameworks-elysia/sdk-typescript/.devcontainer/setup.sh new file mode 100644 index 00000000..90285db9 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.devcontainer/setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Install the speakeasy CLI +curl -fsSL https://raw.githubusercontent.com/speakeasy-api/speakeasy/main/install.sh | sh + +# Setup samples directory +rmdir samples || true +mkdir samples + +npm install --ignore-scripts +npm install -g ts-node --ignore-scripts +npm link +npm link sdk +TS_CONFIG_CONTENT=$(cat < samples/tsconfig.json + +# Generate starter usage sample with speakeasy +speakeasy generate usage -s ./openapi.yaml -l typescript -o samples/root.ts \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/.gitattributes b/frameworks-elysia/sdk-typescript/.gitattributes new file mode 100644 index 00000000..113eead5 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.gitattributes @@ -0,0 +1,2 @@ +# This allows generated code to be indexed correctly +*.ts linguist-generated=false \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/.gitignore b/frameworks-elysia/sdk-typescript/.gitignore new file mode 100644 index 00000000..d50f10f7 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.gitignore @@ -0,0 +1,30 @@ +/examples/node_modules +/mcp-server +/bin +/.eslintcache +.DS_Store +**/.speakeasy/temp/ +**/.speakeasy/logs/ +.DS_Store +/.speakeasy/reports +.env +.env.local +.env.*.local +/models +/models/errors +/types +/node_modules +/lib +/sdk +/funcs +/react-query +/hooks +/index.* +/core.* +/cjs +/esm +/dist +/.tsbuildinfo +/.tshy +/.tshy-* +/__tests__ diff --git a/frameworks-elysia/sdk-typescript/.npmignore b/frameworks-elysia/sdk-typescript/.npmignore new file mode 100644 index 00000000..670ac0a6 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.npmignore @@ -0,0 +1,19 @@ +**/* +!/FUNCTIONS.md +!/RUNTIMES.md +!/REACT_QUERY.md +!/**/*.ts +!/**/*.js +!/**/*.mjs +!/package.json +!/jsr.json +!/dist/**/*.json +!/esm/**/*.json +!/**/*.map + +/eslint.config.mjs +/.oxlintrc.json +/cjs +/.tshy +/.tshy-* +/__tests__ diff --git a/frameworks-elysia/sdk-typescript/.speakeasy/gen.lock b/frameworks-elysia/sdk-typescript/.speakeasy/gen.lock new file mode 100644 index 00000000..f2918ad1 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.speakeasy/gen.lock @@ -0,0 +1,728 @@ +lockVersion: 2.0.0 +id: 710ea1be-a838-453b-adf7-b1cdc6925887 +management: + docChecksum: 5910f06dd5fa21b6490463a83c40c701 + docVersion: 2.0.0 + speakeasyVersion: 1.771.1 + generationVersion: 2.893.0 + releaseVersion: 0.1.0 + configChecksum: bad88536565ede2b6345498b5526581f +persistentEdits: + generation_id: c2baad01-c1d9-45a3-8e9a-df17dcfcf723 + pristine_commit_hash: b2e2b8d18aca5252edb1a2f52fe220e45d20ebff + pristine_tree_hash: 40c72ba79c55f3ffb0b358bf65d96867f25b68f2 +features: + typescript: + additionalDependencies: 0.1.0 + constsAndDefaults: 0.1.14 + core: 3.27.0 + defaultEnabledRetries: 0.1.0 + devContainers: 2.90.1 + enumUnions: 0.1.0 + envVarSecurityUsage: 0.1.2 + globalSecurity: 2.82.16 + globalSecurityCallbacks: 0.1.0 + globalSecurityFlattening: 0.1.1 + globalServerURLs: 2.83.1 + nullables: 0.1.1 + responseFormat: 0.3.0 + retries: 2.83.0 + sdkHooks: 0.4.0 + unions: 2.86.4 +trackedFiles: + .devcontainer/README.md: + id: b170c0f184ac + last_write_checksum: sha1:60415939db8ad10c3f64675b9a6d8d803e547565 + pristine_git_object: ce22244d7ba72000c407581df0dfc3dfb78ff172 + .devcontainer/devcontainer.json: + id: b34062a34eb1 + last_write_checksum: sha1:d0b15193202c961e7d1875864ddb15f9d17c84dd + pristine_git_object: 4d560dd5f40afaf10d96eb75b1f02cd48bbd640c + .devcontainer/setup.sh: + id: 5f1dfbfeb8eb + last_write_checksum: sha1:309d4102c603bc13339e5891a20b2be3c7e9c475 + pristine_git_object: 90285db95678c84b9af183ca3a5db70acc748535 + .gitattributes: + id: 24139dae6567 + last_write_checksum: sha1:26d16d8297b104945139da8c25bd38feeaad3e25 + pristine_git_object: 113eead5093c17d43a46159132885318f281a68a + .npmignore: + id: aa70c1f807c3 + last_write_checksum: sha1:6572da81f2e7a978ec29c22c2210bf461c5897b2 + pristine_git_object: 670ac0a62d7e568c9d44a14f5deafb8442a255d8 + FUNCTIONS.md: + id: 21b9df02aaeb + last_write_checksum: sha1:0220a48e27d6d87bb0057dc31141d41ba8bf51a1 + pristine_git_object: 0972362c5eb9f1ecc4d4be6d92d0f418d12b70ea + RUNTIMES.md: + id: 620c490847b6 + last_write_checksum: sha1:e45b854f02c357cbcfdb8c3663000e8339e16505 + pristine_git_object: 27731c3b5ace66bedc454ed5acbe15075aacd3dc + USAGE.md: + id: 3aed33ce6e6f + last_write_checksum: sha1:a192a5823e6adc7f965a8c1f40b05047b073bde0 + pristine_git_object: 3c0a5ee39b6944c259709a1c94e3dec1641856f6 + docs/lib/utils/retryconfig.md: + id: 0ce9707cb848 + last_write_checksum: sha1:bc4454e196fcd219f5a78da690375a884f5ed07b + pristine_git_object: 08f95f4552349360b2c0b01802aa71ec3a55d2c2 + docs/models/components/security.md: + id: 54906b49ea28 + last_write_checksum: sha1:1eaa3707e3dbadeb578364f2fe36d010f30acf79 + pristine_git_object: 5ef3a75ff72c6f00cf5fc4c09185118d79b1bd75 + docs/models/errors/createbookingbookingsresponsebody.md: + id: 61054c982bf9 + last_write_checksum: sha1:fc7372da61e541916b4b70da4bea9cbf7c6258f2 + pristine_git_object: 1ee2b75a7407be947ff60c0d6f3be9281a5d3a41 + docs/models/errors/createbookingpaymentresponsebody.md: + id: 7486d70c3cf4 + last_write_checksum: sha1:31436bed3085bf2cc60b24740180a6fe3ab64196 + pristine_git_object: 1047acc74def41a3805d9c95cec9e48f7cc1fbe9 + docs/models/errors/createbookingresponsebody.md: + id: 4f24b12e54cf + last_write_checksum: sha1:aa23818aeed13c5c587c12517d57850191a26f6a + pristine_git_object: 920a109cc5b665a7eae4f65b870f6906c86b866a + docs/models/errors/deletebookingresponsebody.md: + id: d08a922f5bd8 + last_write_checksum: sha1:271960545594dd9b5bff45891b807b65413f2cf9 + pristine_git_object: 789eede46ad16dea79ab416ab3303ad387c765cb + docs/models/errors/getbookingresponsebody.md: + id: 9acd451caa52 + last_write_checksum: sha1:5801628f672685ff68e49ad4e5675ea4ba14f5f8 + pristine_git_object: 04a980e15e63fe6a2a71eaa3b177f122e8818a08 + docs/models/errors/getbookingsbookingsresponsebody.md: + id: 19b889bebbd2 + last_write_checksum: sha1:0d878ba1409a4a20a29b288f3100fb98a629e4c2 + pristine_git_object: 7743a6e0b5c04b7b9fc168a5f3358c3f1d52fe1e + docs/models/errors/getbookingsresponsebody.md: + id: ef993c09441a + last_write_checksum: sha1:c1b741ba2ec9c32cdba7c09fef8bd066127fc52f + pristine_git_object: 8e57e781909f1cdbed668a371007b6a1474309aa + docs/models/errors/getstationsresponsebody.md: + id: 00f9fd3a5b67 + last_write_checksum: sha1:1b19f70a0fa3f44e2660ba4d125ca15f7415b036 + pristine_git_object: 5d539051061352ffe9a541d8dad5df1fe0455f7f + docs/models/errors/gettripsresponsebody.md: + id: efdea5c650d9 + last_write_checksum: sha1:29224f07314da88ed7f98211ec45db9065863eea + pristine_git_object: aaefe46762854b9cb86f5e5e5f9164a2f0d1c784 + docs/models/operations/createbookingbookingsrequestrequestbody.md: + id: b8ac8b219130 + last_write_checksum: sha1:aabb3901da14da86a31750d47ef324752524014d + pristine_git_object: 032c39224e6ece752962ea937e332e3cef9f6db6 + docs/models/operations/createbookinglinks.md: + id: 60a23f831eed + last_write_checksum: sha1:3ff6e71425b1362c0136be80aec195b24b17ed17 + pristine_git_object: 8e505848c5ccae6582d490ff0582fa6fbfe06b72 + docs/models/operations/createbookingpaymentlinks.md: + id: 8a2afbe9ba91 + last_write_checksum: sha1:c20f8bd0ab961cba8bb211c72af0fda1992bd82c + pristine_git_object: f20641aec2cfb41e09959487e3a270f5dd7d0c70 + docs/models/operations/createbookingpaymentpaymentscurrency.md: + id: 8d25cbb29eca + last_write_checksum: sha1:442fe7a48fde8a5e211082cb3d92f2f5907b7050 + pristine_git_object: fc1bb9bbbda010e461d93ef82840ec7c129335c3 + docs/models/operations/createbookingpaymentpaymentsrequestrequestbody.md: + id: f25866c577b6 + last_write_checksum: sha1:6127c40244c10680b417d09621d026cfccf4be2d + pristine_git_object: ccbda0e55634802f305975c96f9a7da3c9f1c64d + docs/models/operations/createbookingpaymentpaymentsresponsesource.md: + id: 96ba3b26035a + last_write_checksum: sha1:a69c1295bb97e260a1e7396c9a3a07672ea7395a + pristine_git_object: daee501b114abdfc6c2e829611abff0516615be4 + docs/models/operations/createbookingpaymentpaymentssource.md: + id: d8229e606006 + last_write_checksum: sha1:0fc873e8b464686bdbd0fe1fe450079e5597f074 + pristine_git_object: 42b2b71dc8e9f0d90a1c795b4a2f4966573ba741 + docs/models/operations/createbookingpaymentrequest.md: + id: f484d7f1d410 + last_write_checksum: sha1:01eb73b1db58a215bd03c844e3dd2767694904ee + pristine_git_object: f19843e64c1271ef0d9f19dee16cb67ab3231f84 + docs/models/operations/createbookingpaymentresponsebody.md: + id: d1fed73da0e8 + last_write_checksum: sha1:19e2188193a5dd5d20388ac3c393a98098f4375d + pristine_git_object: a44bec2d32d94e991ba4766fe14ad49ceb329a88 + docs/models/operations/createbookingpaymentsource1.md: + id: 200939e669dc + last_write_checksum: sha1:42e77a9371fdf81a4cc46c94e9d4028685922a74 + pristine_git_object: 7c1925c4dd6d8386dd8b10c0affd3c0e51d6efa4 + docs/models/operations/createbookingpaymentsource2.md: + id: cbd54ecf3938 + last_write_checksum: sha1:926f4447befc4154e27f0815374a65b57d05e5c8 + pristine_git_object: 10860e66a04234763621f4f64099183af54dcdc5 + docs/models/operations/createbookingpaymentsourceaccounttype.md: + id: 60dd63b65f46 + last_write_checksum: sha1:0b157d098d476303dedd4edde3566b9dd1d3eee4 + pristine_git_object: 13045acb959b3950384c27eb0073435f89a4a4f2 + docs/models/operations/createbookingpaymentsourcepayments1.md: + id: 007bad3d7b10 + last_write_checksum: sha1:cee27ac015f7a59c31208cb7cd81a5bd840a27e6 + pristine_git_object: 3695fceb7dbbc4b8cc17ebc27dedfcd1a3893e60 + docs/models/operations/createbookingpaymentsourcepayments2.md: + id: 654d6dda71fb + last_write_checksum: sha1:a15971c5da402bf871be2666d57cb74235be679e + pristine_git_object: 5ec7a56d80d5b05beaf6e99103fdea81911f73cb + docs/models/operations/createbookingpaymentsourcepaymentsaccounttype.md: + id: b837681b118f + last_write_checksum: sha1:c37de76b1ed188a4482df2132ebfa3a11d06ff39 + pristine_git_object: 23d3013cf758c5e5c5e5f8f79a5de4e7905e7eb1 + docs/models/operations/createbookingresponsebody.md: + id: f1cc5bd58251 + last_write_checksum: sha1:ceda7dc77c23f3b777d15bd4a2bed37311ca9623 + pristine_git_object: 58b025159c19b87fc577ed51b05449bbabeebce3 + docs/models/operations/data.md: + id: acd9ffac9680 + last_write_checksum: sha1:22d80504ea9edbe44ffa92da4dba488d2057f755 + pristine_git_object: 3547186d616ac8c74b711ad8780f0e797181dfb1 + docs/models/operations/deletebookingrequest.md: + id: cd93b2f5e3b2 + last_write_checksum: sha1:684553f351464eb377bcd479b50536852b936c52 + pristine_git_object: 5082d2e87724b2fc3be47600f0b60519462f9bab + docs/models/operations/getbookinglinks.md: + id: bc28aea276d3 + last_write_checksum: sha1:7e75a896647ae4a77d34d29848e0db987887fc44 + pristine_git_object: 630a166d66baa4a72a38670f3a53ef195f3af844 + docs/models/operations/getbookingrequest.md: + id: 084d7aa8fede + last_write_checksum: sha1:0c20abf582fe78cef496645514c713772c959c31 + pristine_git_object: 6248731adabe7d2255d58be05c998fa67f17f79a + docs/models/operations/getbookingresponsebody.md: + id: eb600600d62f + last_write_checksum: sha1:827ce81060046c8baea8d8f1c8a2e14a8ab4bf61 + pristine_git_object: 3e2d973f1434658f457bbae683cbedcb61494bf4 + docs/models/operations/getbookingsdata.md: + id: d3cdcd9aa650 + last_write_checksum: sha1:0ee76ceb735ae641b888e0797da76cca4c1dc669 + pristine_git_object: 4c278c4442a6663602ae82778fdca81ae55aebdb + docs/models/operations/getbookingslinks.md: + id: a492e1adc24c + last_write_checksum: sha1:270d3c76a2a6e8f5730a927de4d0f6a5f9e04dde + pristine_git_object: 14deec96664e66d68f04c07b436943988f3bdec7 + docs/models/operations/getbookingsrequest.md: + id: 7f574480f924 + last_write_checksum: sha1:cddad59551c7a58b30b85b5af86450134e4b6a05 + pristine_git_object: 4faff3d9cbf0a86813c562e47666ef5fbdefadd6 + docs/models/operations/getbookingsresponsebody.md: + id: 965d8cf292eb + last_write_checksum: sha1:4eedc8f98b248303727b3c5ba663158f79934acb + pristine_git_object: 469a39390a03f438e144b68664c95b8a632675f7 + docs/models/operations/getstationsrequest.md: + id: a39674bb1bbe + last_write_checksum: sha1:246d807b73979cfc98a1094db04da370922f01f1 + pristine_git_object: 1623a93901d79ac06920ccbf468120edc8dfbb12 + docs/models/operations/getstationsresponsebody.md: + id: 3c61002612dc + last_write_checksum: sha1:168f915c25e85d62d16cfa7d50f40dfefb295e57 + pristine_git_object: 59321a7a9460b2fa264b1088905cf5a93c942d28 + docs/models/operations/gettripsdata.md: + id: 1fc1d928e22d + last_write_checksum: sha1:7aa864894ae7f4e94e6a1ae94ce3710000b48c27 + pristine_git_object: 411803de350b4482f01990051d0c5f4bb9200d9f + docs/models/operations/gettripslinks.md: + id: 839737b4d820 + last_write_checksum: sha1:e53a404d0d6d40951f09b9ba95ffd65cc66ccce6 + pristine_git_object: edcc216550ff63d93885d706625e9c9c36b180b6 + docs/models/operations/gettripsrequest.md: + id: 7fbeabd09147 + last_write_checksum: sha1:7eabf9e45fa0a7cab3cd89b35ffb9204a0e73e40 + pristine_git_object: 9c429925ec3868d13f9ad258b095bd074ae0c5bd + docs/models/operations/gettripsresponsebody.md: + id: 52f3596af8a9 + last_write_checksum: sha1:30b533a5b105ef650ce9f640bdc3d06667f637f9 + pristine_git_object: 169ac890ff7dbc6ad6da8b0200eb47159f9981ea + docs/models/operations/links.md: + id: 161455a12c65 + last_write_checksum: sha1:2c8cce242262d34cf7f8169c445414b1ddd2029e + pristine_git_object: 161fdb60dcf6ef1af944e0add93de63601a01731 + docs/models/operations/status.md: + id: a42267b6f2cb + last_write_checksum: sha1:82bbd906a89b8c22fb58a7439eaabc70bb30aa8a + pristine_git_object: d98c8c306d3670760e4aa0ce3b48caf8c045f587 + docs/sdks/bookings/README.md: + id: e45a5ceed45e + last_write_checksum: sha1:bff69fd410eb7f580687c63c9333032ca1400ed0 + pristine_git_object: 2851f53d8a57e00916600eb1a90bf1e824a024d1 + docs/sdks/payments/README.md: + id: 0ddb15ec8c20 + last_write_checksum: sha1:01174070226b6e9c3c6e06ea61c65fadecab92ed + pristine_git_object: 1769d92bf7dc594ad98d0513eaaef00833127cec + docs/sdks/stations/README.md: + id: 1299da0ccf94 + last_write_checksum: sha1:c38e266a9e6f37699e1614d0cd3cc962fc328d5c + pristine_git_object: 16d4c5f233f152239c0e58d3a1798c30d6dbfac1 + docs/sdks/trips/README.md: + id: 2e6550a2a974 + last_write_checksum: sha1:4f75fcecd7a396ae2bdc262b4b57a657ff7c0a15 + pristine_git_object: e2ba3580c2672cb0f50bce528e3a7198b2a56d68 + eslint.config.mjs: + id: 461c8d07f6da + last_write_checksum: sha1:9398f326377fe47f67af2df6eb6370750c0790b4 + pristine_git_object: 67bccfec985be20a00970d90155752832dd47135 + examples/.env.template: + id: 52cbe5afed92 + last_write_checksum: sha1:d8f04ffd594acd4ddd4d8119ac66b477e7287217 + pristine_git_object: 63defb75676fb7b8bb2717c2489f19a3acf0bb10 + examples/README.md: + id: 9d0f69d6e677 + last_write_checksum: sha1:dfbdc7f6f862e9ce747e83ada3d31d1458a78373 + pristine_git_object: fe153610f2f311eb9c643ca710f4e2c1c0565840 + examples/package.json: + id: c1d7b0ec8e7e + last_write_checksum: sha1:497704f9350994b7c54e5f1436ed86ca3cde6de9 + pristine_git_object: 30f913dadae69b1ec0623749ce4857a97137fecb + examples/stationsGetStations.example.ts: + id: aff6e4db9ba3 + last_write_checksum: sha1:0cb8eb5c9e520c8e32647c4ab74418433185cd5a + pristine_git_object: 8510dd2a0e633e40bed5b7858e95dbd046e6becf + jsr.json: + id: 7f6ab7767282 + last_write_checksum: sha1:87c3cd54c732ea96111d5316912bc2abdcf1ddc4 + pristine_git_object: 288e3f4b2c8e727af42a5fd46509513c22d0b9c7 + package.json: + id: 7030d0b2f71b + last_write_checksum: sha1:7172d899718dc48bb9de38103f4241e1700fe0ff + pristine_git_object: a0811ff69a2fadd6b997f4795bb7050f79875d13 + src/core.ts: + id: f431fdbcd144 + last_write_checksum: sha1:ce840032c45608f5f4022b32bcce32cb69c5ed26 + pristine_git_object: c4486e4ac5f122d666243b52072232a064716999 + src/funcs/bookingsCreateBooking.ts: + id: 3a7d5b7e1a4b + last_write_checksum: sha1:7c958057fd747772c9ea135facc0d86356b5273f + pristine_git_object: 36e23947da774cd74f030abc970d35adc349b3e2 + src/funcs/bookingsDeleteBooking.ts: + id: 7d9fc275ee3d + last_write_checksum: sha1:f95b90f4b1cd78dbb1bc1315a1128d7a1406929f + pristine_git_object: 838199147d57650058884b67af6013d54faf65e3 + src/funcs/bookingsGetBooking.ts: + id: bb51c1809f74 + last_write_checksum: sha1:e208c79d361a5c8173e6954a935e0e3d838b3bc1 + pristine_git_object: ba7e017f352bea37a46fa3a1d45dcf7359e8347c + src/funcs/bookingsGetBookings.ts: + id: fd34dbcf44ec + last_write_checksum: sha1:e684435b65da5d7e6f4dac70c392ec4b651a8a9e + pristine_git_object: 35af58c3a3246923c8b345cccd91bc30891108be + src/funcs/paymentsCreateBookingPayment.ts: + id: c7e1337cf14e + last_write_checksum: sha1:ff6c5443ac3dd23863a371aed5cbcc1cc7115cf3 + pristine_git_object: 56b62fc68e95dd7bb8b5282f642b76d7d63c6465 + src/funcs/stationsGetStations.ts: + id: 6e0a50fffe7c + last_write_checksum: sha1:a808f6325acd6c09bb38e51e13917d8f7dc5dcdf + pristine_git_object: 21ac45d89ad33a1764ba7a7b9a4fa61b8458dcf6 + src/funcs/tripsGetTrips.ts: + id: d466063b45fe + last_write_checksum: sha1:dd7d85ba0d5495ad58e63964eb989958e3836e72 + pristine_git_object: e31946ea2da4be555f5ec54ffe78a1e3e18aa47a + src/hooks/hooks.ts: + id: a2463fc6f69b + last_write_checksum: sha1:646c1538dbffb2552af9d7516de64c339b5e96c2 + pristine_git_object: fc9b13b25900a363b2123d2bad90f541e1d5d176 + src/hooks/index.ts: + id: 5f2dab62b520 + last_write_checksum: sha1:1a11c073a6cd792932218e1d4ed36b8567bad8ef + pristine_git_object: f60ec7acd76141a71d78008c5a362eb0236d8335 + src/hooks/oauth2scopes.ts: + id: a709b8ce2ddb + last_write_checksum: sha1:0957a4e095788424ae41f85ff498d42ed37d3502 + pristine_git_object: f9184cb4e30f04dc8a593ac739c66f58e279b958 + src/hooks/types.ts: + id: 2a02d86ec24f + last_write_checksum: sha1:29372122898cc523fa47576f3f6608a28ec6080e + pristine_git_object: 8bfe4fe8137138decea7af0a5ed791bf01201789 + src/index.ts: + id: c5fb850250c7 + last_write_checksum: sha1:35c9cde3ae14b18b3f893a1afe8b6c44f8760f24 + pristine_git_object: dbcba164a0082e3bb8c43cf21fa7f8ffb9d35dfc + src/lib/base64.ts: + id: "598522066688" + last_write_checksum: sha1:b0b12ddbd8625efb47c0e955a18641aeb10c6532 + pristine_git_object: 0aebd8b0a4867e35cb3348fc52921c3c0b4725b7 + src/lib/config.ts: + id: 320761608fb3 + last_write_checksum: sha1:6e716db91e7dddf3c6fdc27ef0bb0c5b34b51a3f + pristine_git_object: 1a45685bed90d9a96a2ae301b2c39b0959240397 + src/lib/dlv.ts: + id: b1988214835a + last_write_checksum: sha1:1dd3e3fbb4550c4bf31f5ef997faff355d6f3250 + pristine_git_object: e81091f5e536f82739f71379b1fddc2d147c49e2 + src/lib/encodings.ts: + id: 3bd8ead98afd + last_write_checksum: sha1:d47614c415b37e092965c34cb668562195701004 + pristine_git_object: 2791d25bc4f7cf6eec17a65f899851e225fa3deb + src/lib/env.ts: + id: c52972a3b198 + last_write_checksum: sha1:7d24e01b787b1a4d113739fe57fdc29125c597f6 + pristine_git_object: 83cc953a85ff9be462365b0d4dd23e307be8d134 + src/lib/files.ts: + id: e5efa54fcb95 + last_write_checksum: sha1:795c14026405d547bfc47012f7ad9666e530fa7f + pristine_git_object: 6ca6b37d35a12448da176ee2517cc036db12c81c + src/lib/http.ts: + id: 63a80782d37e + last_write_checksum: sha1:797cbf16d3c7c4d62d3ba0eedb08617524938457 + pristine_git_object: 13cf1fd7894a89f727b8d2db2ad24313a94f68c7 + src/lib/is-plain-object.ts: + id: b9862591096a + last_write_checksum: sha1:df687f25a9590b6fd95d39df41a652ae3fd4e517 + pristine_git_object: 61070d3d7c7e5e95b1ed7e7ea21869eb0767db77 + src/lib/logger.ts: + id: 7ee7741a02bf + last_write_checksum: sha1:0ec9d3a2a34c362746b767e4f9a746c055d57a7b + pristine_git_object: d181f2937d4128afbe9b0327e0f81d1fa9c877b7 + src/lib/matchers.ts: + id: d54b2253b719 + last_write_checksum: sha1:32bda3887292d2b0430bb6688982e34038342919 + pristine_git_object: b7ef1986eaa94795a3b1a7409e8aeed6591a11e6 + src/lib/primitives.ts: + id: 74859f750b28 + last_write_checksum: sha1:987869fc54790b9c22e9182099103d6aa7c67016 + pristine_git_object: d21f1dc49affa4e6d324bdd60811b470fdfa7eb6 + src/lib/retries.ts: + id: b24a69d15639 + last_write_checksum: sha1:f3da74dffcbe2756c69393f8600205aa1dc06e68 + pristine_git_object: e3ce9aba72150fc3c18f3105d39b21aba809377b + src/lib/schemas.ts: + id: deb4b531fae1 + last_write_checksum: sha1:209cfaabfa7fc1c1310f97453215cb0755619c6e + pristine_git_object: 47edb9725c2482c667e2ddc8a56b1fec4285c492 + src/lib/sdks.ts: + id: 8a6d91f1218d + last_write_checksum: sha1:be457a188aa0589a3ce65db83c0c29238eaa9e90 + pristine_git_object: 212ccb74a8fd45e659dd63f30dd25ac4a07ab8f8 + src/lib/security.ts: + id: 0502afa7922e + last_write_checksum: sha1:e3ca920b3dfb8607bf7cbda5e4a1edbe9330982c + pristine_git_object: 36d6d87d9523de0edb3eff401f33482afff77c31 + src/lib/url.ts: + id: b0057e24ed76 + last_write_checksum: sha1:3bceadd74bf0b31adf13eb06b7531077c3e07d65 + pristine_git_object: 79e7ce660b3732053e3adcbb5a4cdeb51496e8aa + src/models/components/index.ts: + id: 0aa842dce54d + last_write_checksum: sha1:a445498c6a67166ab0fd15bc7a3f890780f560eb + pristine_git_object: 2edb51c4860cdd2d34f0e40b67aa4d2aed7af6af + src/models/components/security.ts: + id: 472dde81bb1c + last_write_checksum: sha1:f72e8f65f247167421cf5c19bc887f35b13ef2ea + pristine_git_object: c0becc2f64023022742ece55ad0a31da320c41a8 + src/models/errors/apierror.ts: + id: e2280e075454 + last_write_checksum: sha1:e0a90fcc324191d487a1054b3f1d62943e3377e4 + pristine_git_object: d514b64bafb1b7d36d66b425e4b80a9795ce73bb + src/models/errors/createbooking.ts: + id: f5dd85da17bb + last_write_checksum: sha1:2e2501ef908ea5bfe7c78797450693c70d92ba1a + pristine_git_object: 6db97db6026557ef4de402b18047e3159f92b54b + src/models/errors/createbookingpayment.ts: + id: e3ee30db534d + last_write_checksum: sha1:d12c2958acf18b0f600e1e1c8fe7ef69d3d1458d + pristine_git_object: 40810b7e173e9c745c356edbe9f3913987531763 + src/models/errors/deletebooking.ts: + id: d3569460f590 + last_write_checksum: sha1:b486f6aa8f8e159039935df5ae851892ce017b29 + pristine_git_object: 5cac079a39aaf709598f0e80e0732facdea687a2 + src/models/errors/getbooking.ts: + id: ed4a14a61ee7 + last_write_checksum: sha1:b68450e15225944a3e198172757668e7ac572d85 + pristine_git_object: 96611bb7073eccdae0443f0f75d2592a5b67e2ce + src/models/errors/getbookings.ts: + id: a109043886c8 + last_write_checksum: sha1:46d0c8bb4586335128ce6ae60c4546550da0ba7e + pristine_git_object: 714010fd217291080d86cbf0a48ceba070a5c298 + src/models/errors/getstations.ts: + id: cd9338571cd2 + last_write_checksum: sha1:fdb7b45a3e40ccd87d43239be4987bcf64b03d6f + pristine_git_object: 3fff16e2d9b02b524ee8e1c918054913a13a9866 + src/models/errors/gettrips.ts: + id: a7250602fa4b + last_write_checksum: sha1:aeb290d609bf3ae00b899778e42c7b15dcaa7c30 + pristine_git_object: aaa233a4fa2bc6fcd2487a521c1f35d3792656b2 + src/models/errors/httpclienterrors.ts: + id: 6948de76af99 + last_write_checksum: sha1:994ced121c54fecd0af038ccfb7855fbfd3868ec + pristine_git_object: b34f612124c797c2a1106b9735708f679a90b74f + src/models/errors/index.ts: + id: c4e22507cb83 + last_write_checksum: sha1:f2349e40736875566ec586ce42633e043d3f4976 + pristine_git_object: 5147c3c22b3e10fcbe2daec96f2545ccf15d36fb + src/models/errors/responsevalidationerror.ts: + id: 88ff98a41be9 + last_write_checksum: sha1:03a754d4012c73ff1e53b727fc14cc08e2756e66 + pristine_git_object: d6620ee0d6c771e6ecce4beab2df8a0119a0334b + src/models/errors/sdkerror.ts: + id: 3d4212e33e26 + last_write_checksum: sha1:8699ba62e2be76f2bc78c2822a547a6456e38b74 + pristine_git_object: efcdf908437379b4143b6b2233bfba53800e2450 + src/models/errors/sdkvalidationerror.ts: + id: fb6b2b49c445 + last_write_checksum: sha1:a69da17627bcc32b820544608f3400423ea53f26 + pristine_git_object: 6826e1208a5d7b7d310535d18909646522bf0fbd + src/models/operations/createbooking.ts: + id: 010dbc271f3b + last_write_checksum: sha1:cdbd25dc6e08d38bb0dfe11844ac9810ec9c402f + pristine_git_object: c07601c36c2092129660b28fcffce9a65d6b2f0f + src/models/operations/createbookingpayment.ts: + id: 36810ce5ef5c + last_write_checksum: sha1:537492bad43b7fbf22ccef549216856f95bcd899 + pristine_git_object: d17d7f95d29794e2e3b0080bae2f8129199f4a12 + src/models/operations/deletebooking.ts: + id: 15b997dcea76 + last_write_checksum: sha1:230c63acf1ab8294f47c5eec6adff7bf6334e968 + pristine_git_object: a6b04310c607a551df44de2d3ab323d841f4556b + src/models/operations/getbooking.ts: + id: 12e02cb0fa3a + last_write_checksum: sha1:cf9019762aa870e7b0929e04b72bb14e0f916a7a + pristine_git_object: 0e87d118e62e18a48d9ae46121cd15cda623cb0c + src/models/operations/getbookings.ts: + id: 9c538fbacb7b + last_write_checksum: sha1:da1c18a89a9d501cccfc5f1e7f8aa4da63f5d648 + pristine_git_object: d6173b7b47e824649ab0eb4328f7281cd1089dad + src/models/operations/getstations.ts: + id: 28af28d1df58 + last_write_checksum: sha1:331edf497e371290ba268c1aef05f02b04497814 + pristine_git_object: fab7696cbf5cdb8ce81666dc937190eaf76258a9 + src/models/operations/gettrips.ts: + id: c39e8e371278 + last_write_checksum: sha1:18fc0ee24e85fa8930221ff57b8f3ad459ee60d0 + pristine_git_object: d0b4c2c315fcf66bbec4534a8d1d2c13980c66e6 + src/models/operations/index.ts: + id: 0d9ffaf774d2 + last_write_checksum: sha1:297c00f91cf47c8bb2c81154f9a4a158ca167594 + pristine_git_object: 638d1f90f46124bdfb0063f01872d6f251ddf1a0 + src/sdk/bookings.ts: + id: 49019c0d99de + last_write_checksum: sha1:55a4b4dfc34bb09c29c9937eea02be16b1123e0d + pristine_git_object: b48f88bd5d4c0680e6116928a9f2b928eb8e6be1 + src/sdk/index.ts: + id: a857902a703f + last_write_checksum: sha1:ed6d64f2a6135349aa8498b8d8cff9ba85c7fb8f + pristine_git_object: ecac2264817bb369ff2dbf0f0e9029807e67ff77 + src/sdk/payments.ts: + id: f059d3c1d898 + last_write_checksum: sha1:dfb12850debb058b4b0bbc76c31eec660ae606e2 + pristine_git_object: 07655a176f25c89dc5dce0baa4d9739127166208 + src/sdk/sdk.ts: + id: 784571af2f69 + last_write_checksum: sha1:d96356766df9642fe398d4089afceb1c4b50121b + pristine_git_object: 5844664215684e69f36f4c4b761c6a6e9eeb1b27 + src/sdk/stations.ts: + id: e0d10fffccfb + last_write_checksum: sha1:3bd501282ad5c0cfcf0947335b4b2c46a61c0031 + pristine_git_object: 5333111e4733c4702fb70ef82a2e171ffe93b016 + src/sdk/trips.ts: + id: 2e466ceaf03e + last_write_checksum: sha1:5424af8d8fb5b0407cb24d6f88e9065dd075b31a + pristine_git_object: 819559252b7783d7ff9d2eb2088ec4653377dbba + src/types/async.ts: + id: fac8da972f86 + last_write_checksum: sha1:675d04bb4b4081dc3482f18de98674f9b446e7b4 + pristine_git_object: 1543b95cf7be9b5a871d7395f259dbd65331dc21 + src/types/blobs.ts: + id: f8ab9b326c86 + last_write_checksum: sha1:cf45d78916671cb6345a11c97c633c64402bc27c + pristine_git_object: cce2892d4f573a120ef3907db90ab15f5979cfda + src/types/constdatetime.ts: + id: 0f7b6f513917 + last_write_checksum: sha1:dfaaf9adfaf49808bd4c9dea0039f21b7088d9c0 + pristine_git_object: fe62144eaf6a2054fc8ca9a98466e70f41b5434d + src/types/enums.ts: + id: 4d03ddfe5100 + last_write_checksum: sha1:ee590453d2c87e33e89c633d37ee46907eca0e58 + pristine_git_object: aba0ffd2a3308a31e516d83b52823d80aa65a8f9 + src/types/fp.ts: + id: ae9f0fb8aab6 + last_write_checksum: sha1:d24994d58f37a1ca106847fcc6d2e976c6f1c093 + pristine_git_object: ccbe51eac69dfb0da5131f14fd753c4b47c1d527 + src/types/index.ts: + id: cd7a0a5ed005 + last_write_checksum: sha1:bf43b3dccb960ca9ae9c5ab940da4786255881cd + pristine_git_object: abf0b7ab8f196829df8946da40d627a46da68e3c + src/types/operations.ts: + id: 314da01dca47 + last_write_checksum: sha1:c49e724cfb1259296381cb57bc0fcdd2eae45865 + pristine_git_object: beb81e10f0b9eee2ed398a853fe6f737b743f818 + src/types/rfcdate.ts: + id: 9eb64906dcd6 + last_write_checksum: sha1:8e5f382e02fe21c2f2e24deb1b7bbf8cddd3dd16 + pristine_git_object: c79b3f53a3dd922aa2ace5a4191c8652cf9a8e89 + src/types/streams.ts: + id: f99be9c4bf14 + last_write_checksum: sha1:cc9ced2dd34a76c3a1bd7784ccda1cc3b37ab9a9 + pristine_git_object: a0163e7a99cea88f21d0ad4ce3af1c720180ee20 + src/types/unrecognized.ts: + id: 476605c40716 + last_write_checksum: sha1:d33ac686528492f4cdc0dbf81ed343b4afe020fe + pristine_git_object: b7a2a13f3dff50663429df24ae2f55b647ff1084 + tsconfig.json: + id: 61ebb9fd6e8c + last_write_checksum: sha1:79dc1550d921fefec69f8632ed3b24dad41ca2f6 + pristine_git_object: 76110f883cac40bb04fb2f376cd69ea8c8d6d215 +examples: + get-stations: + speakeasy-default-get-stations: + parameters: + query: + page: 1 + limit: 10 + coordinates: "52.5200,13.4050" + search: "Milano Centrale" + country: "DE" + responses: + "200": + application/json: {"data": [], "links": {"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", "next": "https://api.example.com/bookings?page=2", "prev": "https://api.example.com/bookings?page=1"}} + "400": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + get-trips: + speakeasy-default-get-trips: + parameters: + query: + page: 1 + limit: 10 + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e" + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d" + date: "2024-02-01T09:00:00Z" + bicycles: false + dogs: false + responses: + "200": + application/json: {"data": [], "links": {"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", "next": "https://api.example.com/bookings?page=2", "prev": "https://api.example.com/bookings?page=1"}} + "400": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + get-bookings: + speakeasy-default-get-bookings: + parameters: + query: + page: 1 + limit: 10 + responses: + "200": + application/json: {"data": [], "links": {"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", "next": "https://api.example.com/bookings?page=2", "prev": "https://api.example.com/bookings?page=1"}} + "401": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + "500": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + create-booking: + speakeasy-default-create-booking: + requestBody: + application/json: {"trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594", "passenger_name": "John Doe", "has_bicycle": true, "has_dog": false} + application/x-www-form-urlencoded: {"trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594", "passenger_name": "John Doe", "has_bicycle": true, "has_dog": false} + multipart/form-data: {"trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594", "passenger_name": "John Doe", "has_bicycle": true, "has_dog": false} + responses: + "201": + application/json: {"id": "1725ff48-ab45-4bb5-9d02-88745177dedb", "trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594", "passenger_name": "John Doe", "has_bicycle": true, "has_dog": false, "links": {"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"}} + "404": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + "409": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + get-booking: + speakeasy-default-get-booking: + parameters: + path: + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb" + responses: + "200": + application/json: {"id": "1725ff48-ab45-4bb5-9d02-88745177dedb", "trip_id": "ea399ba1-6d95-433f-92d1-83f67b775594", "passenger_name": "John Doe", "has_bicycle": true, "has_dog": false, "links": {"self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"}} + "404": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + delete-booking: + speakeasy-default-delete-booking: + parameters: + path: + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb" + responses: + "404": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} + create-booking-payment: + speakeasy-default-create-booking-payment: + parameters: + path: + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb" + requestBody: + application/json: {"amount": 49.99, "currency": "bgn", "promo_code": "SUMMER20", "source": {"object": "card", "name": "J. Doe", "number": "4242424242424242", "cvc": "123", "exp_month": 12, "exp_year": 2025, "address_country": "gb"}} + application/x-www-form-urlencoded: {"amount": 49.99, "currency": "bgn", "promo_code": "SUMMER20", "source": {"object": "card", "name": "J. Doe", "number": "4242424242424242", "cvc": "123", "exp_month": 12, "exp_year": 2025, "address_country": "gb"}} + multipart/form-data: {"amount": 49.99, "currency": "bgn", "promo_code": "SUMMER20", "source": {"object": "card", "name": "J. Doe", "number": "4242424242424242", "cvc": "123", "exp_month": 12, "exp_year": 2025, "address_country": "gb"}} + responses: + "200": + application/json: {"id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", "amount": 49.99, "currency": "gbp", "source": {"object": "card", "name": "J. Doe", "number": "4242424242424242", "cvc": "123", "exp_month": 12, "exp_year": 2025, "address_country": "gb"}, "status": "failed", "links": {"booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"}} + "404": + application/problem+json: {"type": "https://example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "The requested resource was not found."} +examplesVersion: 1.0.2 +generatedTests: {} +generatedFiles: + - .devcontainer/README.md + - .devcontainer/devcontainer.json + - .devcontainer/setup.sh + - .eslintrc.cjs + - .gitattributes + - .npmignore + - CONTRIBUTING.md + - FUNCTIONS.md + - RUNTIMES.md + - USAGE.md + - docs/lib/utils/retryconfig.md + - docs/models/components/id.md + - docs/models/components/successresponse.md + - docs/models/components/user.md + - docs/models/errors/errorresponse.md + - docs/models/operations/deleteusersbyidrequest.md + - docs/models/operations/getusersbyidrequest.md + - docs/models/operations/patchusersbyidrequest.md + - docs/models/operations/patchusersbyidrequestbody.md + - docs/models/operations/postusersrequestbody.md + - docs/sdks/sdk/README.md + - docs/sdks/users/README.md + - jsr.json + - package.json + - src/core.ts + - src/funcs/usersDeleteUsersById.ts + - src/funcs/usersGetUsers.ts + - src/funcs/usersGetUsersById.ts + - src/funcs/usersPatchUsersById.ts + - src/funcs/usersPostUsers.ts + - src/hooks/hooks.ts + - src/hooks/index.ts + - src/hooks/types.ts + - src/index.ts + - src/lib/base64.ts + - src/lib/config.ts + - src/lib/dlv.ts + - src/lib/encodings.ts + - src/lib/env.ts + - src/lib/files.ts + - src/lib/http.ts + - src/lib/is-plain-object.ts + - src/lib/logger.ts + - src/lib/matchers.ts + - src/lib/primitives.ts + - src/lib/retries.ts + - src/lib/schemas.ts + - src/lib/sdks.ts + - src/lib/security.ts + - src/lib/url.ts + - src/models/components/id.ts + - src/models/components/index.ts + - src/models/components/successresponse.ts + - src/models/components/user.ts + - src/models/errors/apierror.ts + - src/models/errors/errorresponse.ts + - src/models/errors/httpclienterrors.ts + - src/models/errors/index.ts + - src/models/errors/sdkvalidationerror.ts + - src/models/operations/deleteusersbyid.ts + - src/models/operations/getusersbyid.ts + - src/models/operations/index.ts + - src/models/operations/patchusersbyid.ts + - src/models/operations/postusers.ts + - src/sdk/index.ts + - src/sdk/sdk.ts + - src/sdk/users.ts + - src/types/blobs.ts + - src/types/constdatetime.ts + - src/types/enums.ts + - src/types/fp.ts + - src/types/index.ts + - src/types/operations.ts + - src/types/rfcdate.ts + - src/types/streams.ts + - tsconfig.json diff --git a/frameworks-elysia/sdk-typescript/.speakeasy/gen.yaml b/frameworks-elysia/sdk-typescript/.speakeasy/gen.yaml new file mode 100644 index 00000000..a67b0277 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.speakeasy/gen.yaml @@ -0,0 +1,94 @@ +configVersion: 2.0.0 +generation: + devContainers: + enabled: true + schemaPath: ./openapi.yaml + sdkClassName: Sdk + maintainOpenAPIOrder: true + usageSnippets: + optionalPropertyRendering: withExample + sdkInitStyle: constructor + useClassNamesForArrayFields: true + fixes: + nameResolutionDec2023: true + nameResolutionFeb2025: false + parameterOrderingFeb2024: true + requestResponseComponentNamesFeb2024: true + securityFeb2025: false + sharedErrorComponentsApr2025: false + sharedNestedComponentsJan2026: false + nameOverrideFeb2026: false + auth: + oAuth2ClientCredentialsEnabled: false + oAuth2PasswordEnabled: false + hoistGlobalSecurity: true + schemas: + allOfMergeStrategy: shallowMerge + requestBodyFieldName: "" + versioningStrategy: automatic + persistentEdits: {} + tests: + generateTests: true + generateNewTests: false + skipResponseBodyAssertions: false +typescript: + version: 0.1.0 + acceptHeaderEnum: true + additionalDependencies: + dependencies: {} + devDependencies: {} + peerDependencies: {} + additionalPackageJSON: {} + additionalScripts: {} + alwaysIncludeInboundAndOutbound: false + author: Speakeasy + baseErrorName: SDKError + clientServerStatusCodesAsErrors: true + constFieldsAlwaysOptional: false + defaultErrorName: APIError + enableCustomCodeRegions: false + enableMCPServer: false + enableReactQuery: false + enumFormat: union + envVarPrefix: SDK + exportZodModelNamespace: false + fixEnumNameSanitization: false + flatAdditionalProperties: false + flattenGlobalSecurity: true + flatteningOrder: parameters-first + formStringArrayEncodeMode: encoded-string + forwardCompatibleEnumsByDefault: false + forwardCompatibleUnionsByDefault: "false" + generateExamples: true + imports: + option: openapi + paths: + callbacks: models/callbacks + errors: models/errors + operations: models/operations + shared: models/components + webhooks: models/webhooks + inferUnionDiscriminators: true + inputModelSuffix: input + jsonpath: legacy + laxMode: strict + legacyFileNaming: true + maxMethodParams: 0 + methodArguments: require-security-and-request + modelPropertyCasing: camel + moduleFormat: commonjs + multipartArrayFormat: legacy + outputModelSuffix: output + packageName: sdk + preApplyUnionDiscriminators: true + preserveModelFieldNames: false + privateIdentifierPrefix: '#' + responseFormat: flat + sseFlatResponse: false + templateVersion: v2 + unionStrategy: left-to-right + usageSDKInitImports: [] + useIndexModules: true + useOxlint: false + useTsgo: false + zodVersion: v3 diff --git a/frameworks-elysia/sdk-typescript/.speakeasy/workflow.yaml b/frameworks-elysia/sdk-typescript/.speakeasy/workflow.yaml new file mode 100644 index 00000000..a6fbed38 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/.speakeasy/workflow.yaml @@ -0,0 +1,16 @@ +workflowVersion: 1.0.0 +speakeasyVersion: latest +sources: + Users app documentation: + inputs: + - location: ../openapi.yaml + registry: + location: registry.speakeasyapi.dev/ritza-rzx/ritza/users-app-documentation +targets: + sdk: + target: typescript + source: Users app documentation + codeSamples: + registry: + location: registry.speakeasyapi.dev/ritza-rzx/ritza/users-app-documentation-typescript-code-samples + blocking: false diff --git a/frameworks-elysia/sdk-typescript/CONTRIBUTING.md b/frameworks-elysia/sdk-typescript/CONTRIBUTING.md new file mode 100644 index 00000000..d585717f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to This Repository + +Thank you for your interest in contributing to this repository. Please note that this repository contains generated code. As such, we do not accept direct changes or pull requests. Instead, we encourage you to follow the guidelines below to report issues and suggest improvements. + +## How to Report Issues + +If you encounter any bugs or have suggestions for improvements, please open an issue on GitHub. When reporting an issue, please provide as much detail as possible to help us reproduce the problem. This includes: + +- A clear and descriptive title +- Steps to reproduce the issue +- Expected and actual behavior +- Any relevant logs, screenshots, or error messages +- Information about your environment (e.g., operating system, software versions) + - For example can be collected using the `npx envinfo` command from your terminal if you have Node.js installed + +## Issue Triage and Upstream Fixes + +We will review and triage issues as quickly as possible. Our goal is to address bugs and incorporate improvements in the upstream source code. Fixes will be included in the next generation of the generated code. + +## Contact + +If you have any questions or need further assistance, please feel free to reach out by opening an issue. + +Thank you for your understanding and cooperation! + +The Maintainers diff --git a/frameworks-elysia/sdk-typescript/FUNCTIONS.md b/frameworks-elysia/sdk-typescript/FUNCTIONS.md new file mode 100644 index 00000000..0972362c --- /dev/null +++ b/frameworks-elysia/sdk-typescript/FUNCTIONS.md @@ -0,0 +1,91 @@ +# Standalone Functions + +> [!NOTE] +> This section is useful if you are using a bundler and targeting browsers and +> runtimes where the size of an application affects performance and load times. + +Every method in this SDK is also available as a standalone function. This +alternative API is suitable when targeting the browser or serverless runtimes +and using a bundler to build your application since all unused functionality +will be tree-shaken away. This includes code for unused methods, Zod schemas, +encoding helpers and response handlers. The result is dramatically smaller +impact on the application's final bundle size which grows very slowly as you use +more and more functionality from this SDK. + +Calling methods through the main SDK class remains a valid and generally more +more ergonomic option. Standalone functions represent an optimisation for a +specific category of applications. + +## Example + +```typescript +import { SDKCore } from "sdk/core.js"; +import { stationsGetStations } from "sdk/funcs/stationsGetStations.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await stationsGetStations(sdk, { + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("stationsGetStations failed:", res.error); + } +} + +run(); +``` + +## Result types + +Standalone functions differ from SDK methods in that they return a +`Result` type to capture _known errors_ and document them using +the type system. By avoiding throwing errors, application code maintains clear +control flow and error-handling become part of the regular flow of application +code. + +> We use the term "known errors" because standalone functions, and JavaScript +> code in general, can still throw unexpected errors such as `TypeError`s, +> `RangeError`s and `DOMException`s. Exhaustively catching all errors may be +> something this SDK addresses in the future. Nevertheless, there is still a lot +> of benefit from capturing most errors and turning them into values. + +The second reason for this style of programming is because these functions will +typically be used in front-end applications where exception throwing is +sometimes discouraged or considered unidiomatic. React and similar ecosystems +and libraries tend to promote this style of programming so that components +render useful content under all states (loading, success, error and so on). + +The general pattern when calling standalone functions looks like this: + +```typescript +import { Core } from ""; +import { fetchSomething } from "/funcs/fetchSomething.js"; + +const client = new Core(); + +async function run() { + const result = await fetchSomething(client, { id: "123" }); + if (!result.ok) { + // You can throw the error or handle it. It's your choice now. + throw result.error; + } + + console.log(result.value); +} + +run(); +``` + +Notably, `result.error` above will have an explicit type compared to a try-catch +variation where the error in the catch block can only be of type `unknown` (or +`any` depending on your TypeScript settings). \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/README.md b/frameworks-elysia/sdk-typescript/README.md new file mode 100644 index 00000000..3fe06501 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/README.md @@ -0,0 +1,507 @@ +# sdk + +Developer-friendly & type-safe Typescript SDK specifically catered to leverage *sdk* API. + +
+ + + + +
+ + +

+> [!IMPORTANT] +> This SDK is not yet ready for production use. To complete setup please follow the steps outlined in your [workspace](https://app.speakeasy.com/org/ritza-rzx/ritza). Delete this section before > publishing to a package manager. + + +## Summary + +Train Travel API: API for finding and booking train trips across Europe. + + + +## Table of Contents + +* [sdk](#sdk) + * [SDK Installation](#sdk-installation) + * [Requirements](#requirements) + * [SDK Example Usage](#sdk-example-usage) + * [Authentication](#authentication) + * [Available Resources and Operations](#available-resources-and-operations) + * [Standalone functions](#standalone-functions) + * [Retries](#retries) + * [Error Handling](#error-handling) + * [Server Selection](#server-selection) + * [Custom HTTP Client](#custom-http-client) + * [Debugging](#debugging) +* [Development](#development) + * [Maturity](#maturity) + * [Contributions](#contributions) + + + + +## SDK Installation + +> [!TIP] +> To finish publishing your SDK to npm and others you must [run your first generation action](https://www.speakeasy.com/docs/github-setup#step-by-step-guide). + + +The SDK can be installed with either [npm](https://www.npmjs.com/), [pnpm](https://pnpm.io/), [bun](https://bun.sh/) or [yarn](https://classic.yarnpkg.com/en/) package managers. + +### NPM + +```bash +npm add +``` + +### PNPM + +```bash +pnpm add +``` + +### Bun + +```bash +bun add +``` + +### Yarn + +```bash +yarn add +``` + + + +## Requirements + +For supported JavaScript runtimes, please consult [RUNTIMES.md](RUNTIMES.md). + + + +## SDK Example Usage + +### Example + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + + + +## Authentication + +### Per-Client Security Schemes + +This SDK supports the following security scheme globally: + +| Name | Type | Scheme | Environment Variable | +| -------- | ------ | ------------ | -------------------- | +| `oAuth2` | oauth2 | OAuth2 token | `SDK_O_AUTH2` | + +To authenticate with the API the `oAuth2` parameter must be set when initializing the SDK client instance. For example: +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + + + +## Available Resources and Operations + +
+Available methods + +### [Bookings](docs/sdks/bookings/README.md) + +* [getBookings](docs/sdks/bookings/README.md#getbookings) - List existing bookings +* [createBooking](docs/sdks/bookings/README.md#createbooking) - Create a booking +* [getBooking](docs/sdks/bookings/README.md#getbooking) - Get a booking +* [deleteBooking](docs/sdks/bookings/README.md#deletebooking) - Delete a booking + +### [Payments](docs/sdks/payments/README.md) + +* [createBookingPayment](docs/sdks/payments/README.md#createbookingpayment) - Pay for a booking + +### [Stations](docs/sdks/stations/README.md) + +* [getStations](docs/sdks/stations/README.md#getstations) - Get a list of train stations + +### [Trips](docs/sdks/trips/README.md) + +* [getTrips](docs/sdks/trips/README.md#gettrips) - Get available train trips + +
+ + + +## Standalone functions + +All the methods listed above are available as standalone functions. These +functions are ideal for use in applications running in the browser, serverless +runtimes or other environments where application bundle size is a primary +concern. When using a bundler to build your application, all unused +functionality will be either excluded from the final bundle or tree-shaken away. + +To read more about standalone functions, check [FUNCTIONS.md](./FUNCTIONS.md). + +
+ +Available standalone functions + +- [`bookingsCreateBooking`](docs/sdks/bookings/README.md#createbooking) - Create a booking +- [`bookingsDeleteBooking`](docs/sdks/bookings/README.md#deletebooking) - Delete a booking +- [`bookingsGetBooking`](docs/sdks/bookings/README.md#getbooking) - Get a booking +- [`bookingsGetBookings`](docs/sdks/bookings/README.md#getbookings) - List existing bookings +- [`paymentsCreateBookingPayment`](docs/sdks/payments/README.md#createbookingpayment) - Pay for a booking +- [`stationsGetStations`](docs/sdks/stations/README.md#getstations) - Get a list of train stations +- [`tripsGetTrips`](docs/sdks/trips/README.md#gettrips) - Get available train trips + +
+ + + +## Retries + +Some of the endpoints in this SDK support retries. If you use the SDK without any configuration, it will fall back to the default retry strategy provided by the API. However, the default retry strategy can be overridden on a per-operation basis, or across the entire SDK. + +To change the default retry strategy for a single API call, simply provide a retryConfig object to the call: +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }, { + retries: { + strategy: "backoff", + backoff: { + initialInterval: 1, + maxInterval: 50, + exponent: 1.1, + maxElapsedTime: 100, + }, + retryConnectionErrors: false, + }, + }); + + console.log(result); +} + +run(); + +``` + +If you'd like to override the default retry strategy for all operations that support retries, you can provide a retryConfig at SDK initialization: +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + retryConfig: { + strategy: "backoff", + backoff: { + initialInterval: 1, + maxInterval: 50, + exponent: 1.1, + maxElapsedTime: 100, + }, + retryConnectionErrors: false, + }, + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + + + +## Error Handling + +[`SDKError`](./src/models/errors/sdkerror.ts) is the base class for all HTTP error responses. It has the following properties: + +| Property | Type | Description | +| ------------------- | ---------- | --------------------------------------------------------------------------------------- | +| `error.message` | `string` | Error message | +| `error.statusCode` | `number` | HTTP response status code eg `404` | +| `error.headers` | `Headers` | HTTP response headers | +| `error.body` | `string` | HTTP body. Can be empty string if no body is returned. | +| `error.rawResponse` | `Response` | Raw HTTP response | +| `error.data$` | | Optional. Some errors may contain structured data. [See Error Classes](#error-classes). | + +### Example +```typescript +import { SDK } from "sdk"; +import * as errors from "sdk/models/errors"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + try { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); + } catch (error) { + // The base class for HTTP error responses + if (error instanceof errors.SDKError) { + console.log(error.message); + console.log(error.statusCode); + console.log(error.body); + console.log(error.headers); + + // Depending on the method different errors may be thrown + if (error instanceof errors.GetStationsResponseBody) { + console.log(error.data$.type); // string + console.log(error.data$.title); // string + console.log(error.data$.status); // number + console.log(error.data$.detail); // string + } + } + } +} + +run(); + +``` + +### Error Classes +**Primary error:** +* [`SDKError`](./src/models/errors/sdkerror.ts): The base class for HTTP error responses. + +
Less common errors (15) + +
+ +**Network errors:** +* [`ConnectionError`](./src/models/errors/httpclienterrors.ts): HTTP client was unable to make a request to a server. +* [`RequestTimeoutError`](./src/models/errors/httpclienterrors.ts): HTTP request timed out due to an AbortSignal signal. +* [`RequestAbortedError`](./src/models/errors/httpclienterrors.ts): HTTP request was aborted by the client. +* [`InvalidRequestError`](./src/models/errors/httpclienterrors.ts): Any input used to create a request is invalid. +* [`UnexpectedClientError`](./src/models/errors/httpclienterrors.ts): Unrecognised or unexpected error. + + +**Inherit from [`SDKError`](./src/models/errors/sdkerror.ts)**: +* [`GetStationsResponseBody`](./src/models/errors/getstationsresponsebody.ts): Bad Request. Status code `400`. Applicable to 1 of 7 methods.* +* [`GetTripsResponseBody`](./src/models/errors/gettripsresponsebody.ts): Bad Request. Status code `400`. Applicable to 1 of 7 methods.* +* [`GetBookingsResponseBody`](./src/models/errors/getbookingsresponsebody.ts): Unauthorized. Status code `401`. Applicable to 1 of 7 methods.* +* [`CreateBookingResponseBody`](./src/models/errors/createbookingresponsebody.ts): Not Found. Status code `404`. Applicable to 1 of 7 methods.* +* [`GetBookingResponseBody`](./src/models/errors/getbookingresponsebody.ts): Not Found. Status code `404`. Applicable to 1 of 7 methods.* +* [`DeleteBookingResponseBody`](./src/models/errors/deletebookingresponsebody.ts): Not Found. Status code `404`. Applicable to 1 of 7 methods.* +* [`CreateBookingPaymentResponseBody`](./src/models/errors/createbookingpaymentresponsebody.ts): Not Found. Status code `404`. Applicable to 1 of 7 methods.* +* [`CreateBookingBookingsResponseBody`](./src/models/errors/createbookingbookingsresponsebody.ts): Conflict. Status code `409`. Applicable to 1 of 7 methods.* +* [`GetBookingsBookingsResponseBody`](./src/models/errors/getbookingsbookingsresponsebody.ts): Internal Server Error. Status code `500`. Applicable to 1 of 7 methods.* +* [`ResponseValidationError`](./src/models/errors/responsevalidationerror.ts): Type mismatch between the data returned from the server and the structure expected by the SDK. See `error.rawValue` for the raw value and `error.pretty()` for a nicely formatted multi-line string. + +
+ +\* Check [the method documentation](#available-resources-and-operations) to see if the error is applicable. + + + +## Server Selection + +### Select Server by Index + +You can override the default server globally by passing a server index to the `serverIdx: number` optional parameter when initializing the SDK client instance. The selected server will then be used as the default on the operations that use it. This table lists the indexes associated with the available servers: + +| # | Server | Description | +| --- | ------------------------- | ------------------ | +| 0 | `https://api.example.com` | Production | +| 1 | `http://localhost:3000` | Development server | + +#### Example + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + serverIdx: 0, + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + +### Override Server URL Per-Client + +The default server can also be overridden globally by passing a URL to the `serverURL: string` optional parameter when initializing the SDK client instance. For example: +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + serverURL: "http://localhost:3000", + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + + + +## Custom HTTP Client + +The TypeScript SDK makes API calls using an `HTTPClient` that wraps the native +[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). This +client is a thin wrapper around `fetch` and provides the ability to attach hooks +around the request lifecycle that can be used to modify the request or handle +errors and response. + +The `HTTPClient` constructor takes an optional `fetcher` argument that can be +used to integrate a third-party HTTP client or when writing tests to mock out +the HTTP client and feed in fixtures. + +The following example shows how to: +- route requests through a proxy server using [undici](https://www.npmjs.com/package/undici)'s ProxyAgent +- use the `"beforeRequest"` hook to add a custom header and a timeout to requests +- use the `"requestError"` hook to log errors + +```typescript +import { SDK } from "sdk"; +import { ProxyAgent } from "undici"; +import { HTTPClient } from "sdk/lib/http"; + +const dispatcher = new ProxyAgent("http://proxy.example.com:8080"); + +const httpClient = new HTTPClient({ + // 'fetcher' takes a function that has the same signature as native 'fetch'. + fetcher: (input, init) => + // 'dispatcher' is specific to undici and not part of the standard Fetch API. + fetch(input, { ...init, dispatcher } as RequestInit), +}); + +httpClient.addHook("beforeRequest", (request) => { + const nextRequest = new Request(request, { + signal: request.signal || AbortSignal.timeout(5000) + }); + + nextRequest.headers.set("x-custom-header", "custom value"); + + return nextRequest; +}); + +httpClient.addHook("requestError", (error, request) => { + console.group("Request Error"); + console.log("Reason:", `${error}`); + console.log("Endpoint:", `${request.method} ${request.url}`); + console.groupEnd(); +}); + +const sdk = new SDK({ httpClient: httpClient }); +``` + + + +## Debugging + +You can setup your SDK to emit debug logs for SDK requests and responses. + +You can pass a logger that matches `console`'s interface as an SDK option. + +> [!WARNING] +> Beware that debug logging will reveal secrets, like API tokens in headers, in log messages printed to a console or files. It's recommended to use this feature only during local development and not in production. + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ debugLogger: console }); +``` + +You can also enable a default debug logger by setting an environment variable `SDK_DEBUG` to true. + + + + +# Development + +## Maturity + +This SDK is in beta, and there may be breaking changes between versions without a major version update. Therefore, we recommend pinning usage +to a specific package version. This way, you can install the same version each time without breaking changes unless you are intentionally +looking for the latest version. + +## Contributions + +While we value open-source contributions to this SDK, this library is generated programmatically. Any manual changes added to internal files will be overwritten on the next generation. +We look forward to hearing your feedback. Feel free to open a PR or an issue with a proof of concept and we'll do our best to include it in a future release. + +### SDK Created by [Speakeasy](https://www.speakeasy.com/?utm_source=sdk&utm_campaign=typescript) diff --git a/frameworks-elysia/sdk-typescript/RUNTIMES.md b/frameworks-elysia/sdk-typescript/RUNTIMES.md new file mode 100644 index 00000000..27731c3b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/RUNTIMES.md @@ -0,0 +1,48 @@ +# Supported JavaScript runtimes + +This SDK is intended to be used in JavaScript runtimes that support ECMAScript 2020 or newer. The SDK uses the following features: + +- [Web Fetch API][web-fetch] +- [Web Streams API][web-streams] and in particular `ReadableStream` +- [Async iterables][async-iter] using `Symbol.asyncIterator` + +[web-fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API +[web-streams]: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API +[async-iter]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols + +Runtime environments that are explicitly supported are: + +- Evergreen browsers which include: Chrome, Safari, Edge, Firefox +- Node.js active and maintenance LTS releases + - Currently, this is v18 and v20 +- Bun v1 and above +- Deno v1.39 + - Note that Deno does not currently have native support for streaming file uploads backed by the filesystem ([issue link][deno-file-streaming]) + +[deno-file-streaming]: https://github.com/denoland/deno/issues/11018 + +## Recommended TypeScript compiler options + +The following `tsconfig.json` options are recommended for projects using this +SDK in order to get static type support for features like async iterables, +streams and `fetch`-related APIs ([`for await...of`][for-await-of], +[`AbortSignal`][abort-signal], [`Request`][request], [`Response`][response] and +so on): + +[for-await-of]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of +[abort-signal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal +[request]: https://developer.mozilla.org/en-US/docs/Web/API/Request +[response]: https://developer.mozilla.org/en-US/docs/Web/API/Response + +```jsonc +{ + "compilerOptions": { + "target": "es2020", // or higher + "lib": ["es2020", "dom", "dom.iterable"] + } +} +``` + +While `target` can be set to older ECMAScript versions, it may result in extra, +unnecessary compatibility code being generated if you are not targeting old +runtimes. diff --git a/frameworks-elysia/sdk-typescript/USAGE.md b/frameworks-elysia/sdk-typescript/USAGE.md new file mode 100644 index 00000000..3c0a5ee3 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/USAGE.md @@ -0,0 +1,22 @@ + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); + +``` + \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/lib/utils/retryconfig.md b/frameworks-elysia/sdk-typescript/docs/lib/utils/retryconfig.md new file mode 100644 index 00000000..08f95f45 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/lib/utils/retryconfig.md @@ -0,0 +1,24 @@ +# RetryConfig + +Allows customizing the default retry configuration. It is only permitted in methods that accept retry policies. + +## Fields + +| Name | Type | Description | Example | +| ------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------ | ----------- | +| `strategy` | `"backoff" | "none"` | The retry strategy to use. | `"backoff"` | +| `backoff` | [BackoffStrategy](#backoffstrategy) | When strategy is "backoff", this configurates for the backoff parameters. | | +| `retryConnectionErrors` | `*boolean*` | When strategy is "backoff", this determines whether or not to retry on connection errors. | `true` | + +## BackoffStrategy + +The backoff strategy allows retrying a request with an exponential backoff between each retry. + +### Fields + +| Name | Type | Description | Example | +| ------------------ | ------------ | ----------------------------------------- | -------- | +| `initialInterval` | `*number*` | The initial interval in milliseconds. | `500` | +| `maxInterval` | `*number*` | The maximum interval in milliseconds. | `60000` | +| `exponent` | `*number*` | The exponent to use for the backoff. | `1.5` | +| `maxElapsedTime` | `*number*` | The maximum elapsed time in milliseconds. | `300000` | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/components/security.md b/frameworks-elysia/sdk-typescript/docs/models/components/security.md new file mode 100644 index 00000000..5ef3a75f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/components/security.md @@ -0,0 +1,15 @@ +# Security + +## Example Usage + +```typescript +import { Security } from "sdk/models/components"; + +let value: Security = {}; +``` + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `oAuth2` | *string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingbookingsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingbookingsresponsebody.md new file mode 100644 index 00000000..1ee2b75a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingbookingsresponsebody.md @@ -0,0 +1,20 @@ +# CreateBookingBookingsResponseBody + +Conflict + +## Example Usage + +```typescript +import { CreateBookingBookingsResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingpaymentresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingpaymentresponsebody.md new file mode 100644 index 00000000..1047acc7 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingpaymentresponsebody.md @@ -0,0 +1,20 @@ +# CreateBookingPaymentResponseBody + +Not Found + +## Example Usage + +```typescript +import { CreateBookingPaymentResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingresponsebody.md new file mode 100644 index 00000000..920a109c --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/createbookingresponsebody.md @@ -0,0 +1,20 @@ +# CreateBookingResponseBody + +Not Found + +## Example Usage + +```typescript +import { CreateBookingResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/deletebookingresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/deletebookingresponsebody.md new file mode 100644 index 00000000..789eede4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/deletebookingresponsebody.md @@ -0,0 +1,20 @@ +# DeleteBookingResponseBody + +Not Found + +## Example Usage + +```typescript +import { DeleteBookingResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingresponsebody.md new file mode 100644 index 00000000..04a980e1 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingresponsebody.md @@ -0,0 +1,20 @@ +# GetBookingResponseBody + +Not Found + +## Example Usage + +```typescript +import { GetBookingResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsbookingsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsbookingsresponsebody.md new file mode 100644 index 00000000..7743a6e0 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsbookingsresponsebody.md @@ -0,0 +1,20 @@ +# GetBookingsBookingsResponseBody + +Internal Server Error + +## Example Usage + +```typescript +import { GetBookingsBookingsResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsresponsebody.md new file mode 100644 index 00000000..8e57e781 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/getbookingsresponsebody.md @@ -0,0 +1,20 @@ +# GetBookingsResponseBody + +Unauthorized + +## Example Usage + +```typescript +import { GetBookingsResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/getstationsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/getstationsresponsebody.md new file mode 100644 index 00000000..5d539051 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/getstationsresponsebody.md @@ -0,0 +1,20 @@ +# GetStationsResponseBody + +Bad Request + +## Example Usage + +```typescript +import { GetStationsResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/errors/gettripsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/errors/gettripsresponsebody.md new file mode 100644 index 00000000..aaefe467 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/errors/gettripsresponsebody.md @@ -0,0 +1,20 @@ +# GetTripsResponseBody + +Bad Request + +## Example Usage + +```typescript +import { GetTripsResponseBody } from "sdk/models/errors"; + +// No examples available for this model +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `type` | *string* | :heavy_check_mark: | N/A | https://example.com/errors/not-found | +| `title` | *string* | :heavy_check_mark: | N/A | Not Found | +| `status` | *number* | :heavy_check_mark: | N/A | 404 | +| `detail` | *string* | :heavy_check_mark: | N/A | The requested resource was not found. | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingbookingsrequestrequestbody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingbookingsrequestrequestbody.md new file mode 100644 index 00000000..032c3922 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingbookingsrequestrequestbody.md @@ -0,0 +1,25 @@ +# CreateBookingBookingsRequestRequestBody + +Booking details. + +## Example Usage + +```typescript +import { CreateBookingBookingsRequestRequestBody } from "sdk/models/operations"; + +let value: CreateBookingBookingsRequestRequestBody = { + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `tripId` | *string* | :heavy_check_mark: | N/A | ea399ba1-6d95-433f-92d1-83f67b775594 | +| `passengerName` | *string* | :heavy_check_mark: | N/A | John Doe | +| `hasBicycle` | *boolean* | :heavy_minus_sign: | N/A | true | +| `hasDog` | *boolean* | :heavy_minus_sign: | N/A | false | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookinglinks.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookinglinks.md new file mode 100644 index 00000000..8e505848 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookinglinks.md @@ -0,0 +1,17 @@ +# CreateBookingLinks + +## Example Usage + +```typescript +import { CreateBookingLinks } from "sdk/models/operations"; + +let value: CreateBookingLinks = { + self: "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `self` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentlinks.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentlinks.md new file mode 100644 index 00000000..f20641ae --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentlinks.md @@ -0,0 +1,18 @@ +# CreateBookingPaymentLinks + +## Example Usage + +```typescript +import { CreateBookingPaymentLinks } from "sdk/models/operations"; + +let value: CreateBookingPaymentLinks = { + booking: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `booking` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentscurrency.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentscurrency.md new file mode 100644 index 00000000..fc1bb9bb --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentscurrency.md @@ -0,0 +1,15 @@ +# CreateBookingPaymentPaymentsCurrency + +## Example Usage + +```typescript +import { CreateBookingPaymentPaymentsCurrency } from "sdk/models/operations"; + +let value: CreateBookingPaymentPaymentsCurrency = "bam"; +``` + +## Values + +```typescript +"bam" | "bgn" | "chf" | "eur" | "gbp" | "nok" | "sek" +``` \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsrequestrequestbody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsrequestrequestbody.md new file mode 100644 index 00000000..ccbda0e5 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsrequestrequestbody.md @@ -0,0 +1,31 @@ +# CreateBookingPaymentPaymentsRequestRequestBody + +## Example Usage + +```typescript +import { CreateBookingPaymentPaymentsRequestRequestBody } from "sdk/models/operations"; + +let value: CreateBookingPaymentPaymentsRequestRequestBody = { + amount: 49.99, + currency: "eur", + promoCode: "SUMMER20", + source: { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | +| `amount` | *number* | :heavy_check_mark: | N/A | 49.99 | +| `currency` | [operations.CreateBookingPaymentPaymentsCurrency](../../models/operations/createbookingpaymentpaymentscurrency.md) | :heavy_check_mark: | N/A | | +| `promoCode` | *string* | :heavy_minus_sign: | N/A | SUMMER20 | +| `source` | *operations.CreateBookingPaymentPaymentsSource* | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsresponsesource.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsresponsesource.md new file mode 100644 index 00000000..daee501b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentsresponsesource.md @@ -0,0 +1,34 @@ +# CreateBookingPaymentPaymentsResponseSource + + +## Supported Types + +### `operations.CreateBookingPaymentSourcePayments1` + +```typescript +const value: operations.CreateBookingPaymentSourcePayments1 = { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + addressPostCode: "N12 9XX", +}; +``` + +### `operations.CreateBookingPaymentSourcePayments2` + +```typescript +const value: operations.CreateBookingPaymentSourcePayments2 = { + object: "bank_account", + name: "J. Doe", + number: "00012345", + sortCode: "000123", + accountType: "individual", + bankName: "Starling Bank", + country: "gb", +}; +``` + diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentssource.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentssource.md new file mode 100644 index 00000000..42b2b71d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentpaymentssource.md @@ -0,0 +1,34 @@ +# CreateBookingPaymentPaymentsSource + + +## Supported Types + +### `operations.CreateBookingPaymentSource1` + +```typescript +const value: operations.CreateBookingPaymentSource1 = { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + addressPostCode: "N12 9XX", +}; +``` + +### `operations.CreateBookingPaymentSource2` + +```typescript +const value: operations.CreateBookingPaymentSource2 = { + object: "bank_account", + name: "J. Doe", + number: "00012345", + sortCode: "000123", + accountType: "company", + bankName: "Starling Bank", + country: "gb", +}; +``` + diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentrequest.md new file mode 100644 index 00000000..f19843e6 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentrequest.md @@ -0,0 +1,32 @@ +# CreateBookingPaymentRequest + +## Example Usage + +```typescript +import { CreateBookingPaymentRequest } from "sdk/models/operations"; + +let value: CreateBookingPaymentRequest = { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + requestBody: { + amount: 49.99, + currency: "gbp", + promoCode: "SUMMER20", + source: { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + }, + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `bookingId` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | +| `requestBody` | [operations.CreateBookingPaymentPaymentsRequestRequestBody](../../models/operations/createbookingpaymentpaymentsrequestrequestbody.md) | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentresponsebody.md new file mode 100644 index 00000000..a44bec2d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentresponsebody.md @@ -0,0 +1,40 @@ +# CreateBookingPaymentResponseBody + +Payment successful + +## Example Usage + +```typescript +import { CreateBookingPaymentResponseBody } from "sdk/models/operations"; + +let value: CreateBookingPaymentResponseBody = { + id: "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", + amount: 49.99, + currency: "gbp", + source: { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + }, + status: "failed", + links: { + booking: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| `id` | *string* | :heavy_check_mark: | N/A | 2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a | +| `amount` | *number* | :heavy_check_mark: | N/A | 49.99 | +| `currency` | *string* | :heavy_check_mark: | N/A | gbp | +| `source` | *operations.CreateBookingPaymentPaymentsResponseSource* | :heavy_check_mark: | N/A | | +| `status` | [operations.Status](../../models/operations/status.md) | :heavy_check_mark: | N/A | | +| `links` | [operations.CreateBookingPaymentLinks](../../models/operations/createbookingpaymentlinks.md) | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource1.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource1.md new file mode 100644 index 00000000..7c1925c4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource1.md @@ -0,0 +1,31 @@ +# CreateBookingPaymentSource1 + +## Example Usage + +```typescript +import { CreateBookingPaymentSource1 } from "sdk/models/operations"; + +let value: CreateBookingPaymentSource1 = { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + addressPostCode: "N12 9XX", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | +| `object` | *"card"* | :heavy_check_mark: | N/A | | +| `name` | *string* | :heavy_check_mark: | N/A | J. Doe | +| `number` | *string* | :heavy_check_mark: | N/A | 4242424242424242 | +| `cvc` | *string* | :heavy_check_mark: | N/A | 123 | +| `expMonth` | *number* | :heavy_check_mark: | N/A | 12 | +| `expYear` | *number* | :heavy_check_mark: | N/A | 2025 | +| `addressCountry` | *string* | :heavy_check_mark: | N/A | gb | +| `addressPostCode` | *string* | :heavy_minus_sign: | N/A | N12 9XX | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource2.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource2.md new file mode 100644 index 00000000..10860e66 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsource2.md @@ -0,0 +1,29 @@ +# CreateBookingPaymentSource2 + +## Example Usage + +```typescript +import { CreateBookingPaymentSource2 } from "sdk/models/operations"; + +let value: CreateBookingPaymentSource2 = { + object: "bank_account", + name: "J. Doe", + number: "00012345", + sortCode: "000123", + accountType: "company", + bankName: "Starling Bank", + country: "gb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `object` | *"bank_account"* | :heavy_check_mark: | N/A | | +| `name` | *string* | :heavy_check_mark: | N/A | J. Doe | +| `number` | *string* | :heavy_check_mark: | N/A | 00012345 | +| `sortCode` | *string* | :heavy_minus_sign: | N/A | 000123 | +| `accountType` | [operations.CreateBookingPaymentSourceAccountType](../../models/operations/createbookingpaymentsourceaccounttype.md) | :heavy_check_mark: | N/A | | +| `bankName` | *string* | :heavy_check_mark: | N/A | Starling Bank | +| `country` | *string* | :heavy_check_mark: | N/A | gb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourceaccounttype.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourceaccounttype.md new file mode 100644 index 00000000..13045acb --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourceaccounttype.md @@ -0,0 +1,15 @@ +# CreateBookingPaymentSourceAccountType + +## Example Usage + +```typescript +import { CreateBookingPaymentSourceAccountType } from "sdk/models/operations"; + +let value: CreateBookingPaymentSourceAccountType = "individual"; +``` + +## Values + +```typescript +"individual" | "company" +``` \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments1.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments1.md new file mode 100644 index 00000000..3695fceb --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments1.md @@ -0,0 +1,31 @@ +# CreateBookingPaymentSourcePayments1 + +## Example Usage + +```typescript +import { CreateBookingPaymentSourcePayments1 } from "sdk/models/operations"; + +let value: CreateBookingPaymentSourcePayments1 = { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + addressPostCode: "N12 9XX", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | +| `object` | *"card"* | :heavy_check_mark: | N/A | | +| `name` | *string* | :heavy_check_mark: | N/A | J. Doe | +| `number` | *string* | :heavy_check_mark: | N/A | 4242424242424242 | +| `cvc` | *string* | :heavy_check_mark: | N/A | 123 | +| `expMonth` | *number* | :heavy_check_mark: | N/A | 12 | +| `expYear` | *number* | :heavy_check_mark: | N/A | 2025 | +| `addressCountry` | *string* | :heavy_check_mark: | N/A | gb | +| `addressPostCode` | *string* | :heavy_minus_sign: | N/A | N12 9XX | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments2.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments2.md new file mode 100644 index 00000000..5ec7a56d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepayments2.md @@ -0,0 +1,29 @@ +# CreateBookingPaymentSourcePayments2 + +## Example Usage + +```typescript +import { CreateBookingPaymentSourcePayments2 } from "sdk/models/operations"; + +let value: CreateBookingPaymentSourcePayments2 = { + object: "bank_account", + name: "J. Doe", + number: "00012345", + sortCode: "000123", + accountType: "individual", + bankName: "Starling Bank", + country: "gb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | +| `object` | *"bank_account"* | :heavy_check_mark: | N/A | | +| `name` | *string* | :heavy_check_mark: | N/A | J. Doe | +| `number` | *string* | :heavy_check_mark: | N/A | 00012345 | +| `sortCode` | *string* | :heavy_minus_sign: | N/A | 000123 | +| `accountType` | [operations.CreateBookingPaymentSourcePaymentsAccountType](../../models/operations/createbookingpaymentsourcepaymentsaccounttype.md) | :heavy_check_mark: | N/A | | +| `bankName` | *string* | :heavy_check_mark: | N/A | Starling Bank | +| `country` | *string* | :heavy_check_mark: | N/A | gb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepaymentsaccounttype.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepaymentsaccounttype.md new file mode 100644 index 00000000..23d3013c --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingpaymentsourcepaymentsaccounttype.md @@ -0,0 +1,15 @@ +# CreateBookingPaymentSourcePaymentsAccountType + +## Example Usage + +```typescript +import { CreateBookingPaymentSourcePaymentsAccountType } from "sdk/models/operations"; + +let value: CreateBookingPaymentSourcePaymentsAccountType = "individual"; +``` + +## Values + +```typescript +"individual" | "company" +``` \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingresponsebody.md new file mode 100644 index 00000000..58b02515 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/createbookingresponsebody.md @@ -0,0 +1,32 @@ +# CreateBookingResponseBody + +A booking for a train trip. + +## Example Usage + +```typescript +import { CreateBookingResponseBody } from "sdk/models/operations"; + +let value: CreateBookingResponseBody = { + id: "1725ff48-ab45-4bb5-9d02-88745177dedb", + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, + links: { + self: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `id` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | +| `tripId` | *string* | :heavy_check_mark: | N/A | ea399ba1-6d95-433f-92d1-83f67b775594 | +| `passengerName` | *string* | :heavy_check_mark: | N/A | John Doe | +| `hasBicycle` | *boolean* | :heavy_check_mark: | N/A | true | +| `hasDog` | *boolean* | :heavy_check_mark: | N/A | false | +| `links` | [operations.CreateBookingLinks](../../models/operations/createbookinglinks.md) | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/data.md b/frameworks-elysia/sdk-typescript/docs/models/operations/data.md new file mode 100644 index 00000000..3547186d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/data.md @@ -0,0 +1,27 @@ +# Data + +A train station. + +## Example Usage + +```typescript +import { Data } from "sdk/models/operations"; + +let value: Data = { + id: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + name: "Berlin Hauptbahnhof", + address: "Invalidenstrasse 10557 Berlin, Germany", + countryCode: "DE", + timezone: "Europe/Berlin", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------- | -------------------------------------- | -------------------------------------- | -------------------------------------- | -------------------------------------- | +| `id` | *string* | :heavy_check_mark: | N/A | efdbb9d1-02c2-4bc3-afb7-6788d8782b1e | +| `name` | *string* | :heavy_check_mark: | N/A | Berlin Hauptbahnhof | +| `address` | *string* | :heavy_check_mark: | N/A | Invalidenstrasse 10557 Berlin, Germany | +| `countryCode` | *string* | :heavy_check_mark: | N/A | DE | +| `timezone` | *string* | :heavy_check_mark: | N/A | Europe/Berlin | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/deletebookingrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/deletebookingrequest.md new file mode 100644 index 00000000..5082d2e8 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/deletebookingrequest.md @@ -0,0 +1,17 @@ +# DeleteBookingRequest + +## Example Usage + +```typescript +import { DeleteBookingRequest } from "sdk/models/operations"; + +let value: DeleteBookingRequest = { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `bookingId` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookinglinks.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookinglinks.md new file mode 100644 index 00000000..630a166d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookinglinks.md @@ -0,0 +1,17 @@ +# GetBookingLinks + +## Example Usage + +```typescript +import { GetBookingLinks } from "sdk/models/operations"; + +let value: GetBookingLinks = { + self: "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `self` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingrequest.md new file mode 100644 index 00000000..6248731a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingrequest.md @@ -0,0 +1,17 @@ +# GetBookingRequest + +## Example Usage + +```typescript +import { GetBookingRequest } from "sdk/models/operations"; + +let value: GetBookingRequest = { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `bookingId` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingresponsebody.md new file mode 100644 index 00000000..3e2d973f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingresponsebody.md @@ -0,0 +1,32 @@ +# GetBookingResponseBody + +A booking for a train trip. + +## Example Usage + +```typescript +import { GetBookingResponseBody } from "sdk/models/operations"; + +let value: GetBookingResponseBody = { + id: "1725ff48-ab45-4bb5-9d02-88745177dedb", + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, + links: { + self: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| `id` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | +| `tripId` | *string* | :heavy_check_mark: | N/A | ea399ba1-6d95-433f-92d1-83f67b775594 | +| `passengerName` | *string* | :heavy_check_mark: | N/A | John Doe | +| `hasBicycle` | *boolean* | :heavy_check_mark: | N/A | true | +| `hasDog` | *boolean* | :heavy_check_mark: | N/A | false | +| `links` | [operations.GetBookingLinks](../../models/operations/getbookinglinks.md) | :heavy_check_mark: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsdata.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsdata.md new file mode 100644 index 00000000..4c278c44 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsdata.md @@ -0,0 +1,27 @@ +# GetBookingsData + +A booking for a train trip. + +## Example Usage + +```typescript +import { GetBookingsData } from "sdk/models/operations"; + +let value: GetBookingsData = { + id: "1725ff48-ab45-4bb5-9d02-88745177dedb", + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `id` | *string* | :heavy_check_mark: | N/A | 1725ff48-ab45-4bb5-9d02-88745177dedb | +| `tripId` | *string* | :heavy_check_mark: | N/A | ea399ba1-6d95-433f-92d1-83f67b775594 | +| `passengerName` | *string* | :heavy_check_mark: | N/A | John Doe | +| `hasBicycle` | *boolean* | :heavy_check_mark: | N/A | true | +| `hasDog` | *boolean* | :heavy_check_mark: | N/A | false | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingslinks.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingslinks.md new file mode 100644 index 00000000..14deec96 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingslinks.md @@ -0,0 +1,21 @@ +# GetBookingsLinks + +## Example Usage + +```typescript +import { GetBookingsLinks } from "sdk/models/operations"; + +let value: GetBookingsLinks = { + self: "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `self` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | +| `next` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=2 | +| `prev` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=1 | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsrequest.md new file mode 100644 index 00000000..4faff3d9 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsrequest.md @@ -0,0 +1,16 @@ +# GetBookingsRequest + +## Example Usage + +```typescript +import { GetBookingsRequest } from "sdk/models/operations"; + +let value: GetBookingsRequest = {}; +``` + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `page` | *number* | :heavy_minus_sign: | N/A | +| `limit` | *number* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsresponsebody.md new file mode 100644 index 00000000..469a3939 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getbookingsresponsebody.md @@ -0,0 +1,34 @@ +# GetBookingsResponseBody + +A list of bookings + +## Example Usage + +```typescript +import { GetBookingsResponseBody } from "sdk/models/operations"; + +let value: GetBookingsResponseBody = { + data: [ + { + id: "1725ff48-ab45-4bb5-9d02-88745177dedb", + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, + }, + ], + links: { + self: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| `data` | [operations.GetBookingsData](../../models/operations/getbookingsdata.md)[] | :heavy_check_mark: | N/A | +| `links` | [operations.GetBookingsLinks](../../models/operations/getbookingslinks.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsrequest.md new file mode 100644 index 00000000..1623a939 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsrequest.md @@ -0,0 +1,23 @@ +# GetStationsRequest + +## Example Usage + +```typescript +import { GetStationsRequest } from "sdk/models/operations"; + +let value: GetStationsRequest = { + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | +| `page` | *number* | :heavy_minus_sign: | N/A | | +| `limit` | *number* | :heavy_minus_sign: | N/A | | +| `coordinates` | *string* | :heavy_minus_sign: | N/A | 52.5200,13.4050 | +| `search` | *string* | :heavy_minus_sign: | N/A | Milano Centrale | +| `country` | *string* | :heavy_minus_sign: | N/A | DE | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsresponsebody.md new file mode 100644 index 00000000..59321a7a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/getstationsresponsebody.md @@ -0,0 +1,34 @@ +# GetStationsResponseBody + +OK + +## Example Usage + +```typescript +import { GetStationsResponseBody } from "sdk/models/operations"; + +let value: GetStationsResponseBody = { + data: [ + { + id: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + name: "Berlin Hauptbahnhof", + address: "Invalidenstrasse 10557 Berlin, Germany", + countryCode: "DE", + timezone: "Europe/Berlin", + }, + ], + links: { + self: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | +| ---------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | +| `data` | [operations.Data](../../models/operations/data.md)[] | :heavy_check_mark: | N/A | +| `links` | [operations.Links](../../models/operations/links.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsdata.md b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsdata.md new file mode 100644 index 00000000..411803de --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsdata.md @@ -0,0 +1,35 @@ +# GetTripsData + +A train trip. + +## Example Usage + +```typescript +import { GetTripsData } from "sdk/models/operations"; + +let value: GetTripsData = { + id: "ea399ba1-6d95-433f-92d1-83f67b775594", + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + departureTime: new Date("2024-02-01T10:00:00Z"), + arrivalTime: new Date("2024-02-01T16:00:00Z"), + operator: "Deutsche Bahn", + price: 50, + bicyclesAllowed: true, + dogsAllowed: true, +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `id` | *string* | :heavy_check_mark: | N/A | ea399ba1-6d95-433f-92d1-83f67b775594 | +| `origin` | *string* | :heavy_check_mark: | N/A | efdbb9d1-02c2-4bc3-afb7-6788d8782b1e | +| `destination` | *string* | :heavy_check_mark: | N/A | b2e783e1-c824-4d63-b37a-d8d698862f1d | +| `departureTime` | [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) | :heavy_check_mark: | N/A | 2024-02-01T10:00:00Z | +| `arrivalTime` | [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) | :heavy_check_mark: | N/A | 2024-02-01T16:00:00Z | +| `operator` | *string* | :heavy_check_mark: | N/A | Deutsche Bahn | +| `price` | *number* | :heavy_check_mark: | N/A | 50 | +| `bicyclesAllowed` | *boolean* | :heavy_check_mark: | N/A | true | +| `dogsAllowed` | *boolean* | :heavy_check_mark: | N/A | true | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/gettripslinks.md b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripslinks.md new file mode 100644 index 00000000..edcc2165 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripslinks.md @@ -0,0 +1,21 @@ +# GetTripsLinks + +## Example Usage + +```typescript +import { GetTripsLinks } from "sdk/models/operations"; + +let value: GetTripsLinks = { + self: "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `self` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | +| `next` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=2 | +| `prev` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=1 | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsrequest.md b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsrequest.md new file mode 100644 index 00000000..9c429925 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsrequest.md @@ -0,0 +1,25 @@ +# GetTripsRequest + +## Example Usage + +```typescript +import { GetTripsRequest } from "sdk/models/operations"; + +let value: GetTripsRequest = { + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + date: new Date("2024-02-01T09:00:00Z"), +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `page` | *number* | :heavy_minus_sign: | N/A | | +| `limit` | *number* | :heavy_minus_sign: | N/A | | +| `origin` | *string* | :heavy_check_mark: | N/A | efdbb9d1-02c2-4bc3-afb7-6788d8782b1e | +| `destination` | *string* | :heavy_check_mark: | N/A | b2e783e1-c824-4d63-b37a-d8d698862f1d | +| `date` | [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) | :heavy_check_mark: | N/A | 2024-02-01T09:00:00Z | +| `bicycles` | *boolean* | :heavy_minus_sign: | N/A | | +| `dogs` | *boolean* | :heavy_minus_sign: | N/A | | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsresponsebody.md b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsresponsebody.md new file mode 100644 index 00000000..169ac890 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/gettripsresponsebody.md @@ -0,0 +1,38 @@ +# GetTripsResponseBody + +A list of available train trips + +## Example Usage + +```typescript +import { GetTripsResponseBody } from "sdk/models/operations"; + +let value: GetTripsResponseBody = { + data: [ + { + id: "ea399ba1-6d95-433f-92d1-83f67b775594", + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + departureTime: new Date("2024-02-01T10:00:00Z"), + arrivalTime: new Date("2024-02-01T16:00:00Z"), + operator: "Deutsche Bahn", + price: 50, + bicyclesAllowed: true, + dogsAllowed: true, + }, + ], + links: { + self: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", + }, +}; +``` + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `data` | [operations.GetTripsData](../../models/operations/gettripsdata.md)[] | :heavy_check_mark: | N/A | +| `links` | [operations.GetTripsLinks](../../models/operations/gettripslinks.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/links.md b/frameworks-elysia/sdk-typescript/docs/models/operations/links.md new file mode 100644 index 00000000..161fdb60 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/links.md @@ -0,0 +1,21 @@ +# Links + +## Example Usage + +```typescript +import { Links } from "sdk/models/operations"; + +let value: Links = { + self: "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + next: "https://api.example.com/bookings?page=2", + prev: "https://api.example.com/bookings?page=1", +}; +``` + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `self` | *string* | :heavy_check_mark: | N/A | https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb | +| `next` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=2 | +| `prev` | *string* | :heavy_minus_sign: | N/A | https://api.example.com/bookings?page=1 | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/models/operations/status.md b/frameworks-elysia/sdk-typescript/docs/models/operations/status.md new file mode 100644 index 00000000..d98c8c30 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/models/operations/status.md @@ -0,0 +1,15 @@ +# Status + +## Example Usage + +```typescript +import { Status } from "sdk/models/operations"; + +let value: Status = "succeeded"; +``` + +## Values + +```typescript +"pending" | "succeeded" | "failed" +``` \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/sdks/bookings/README.md b/frameworks-elysia/sdk-typescript/docs/sdks/bookings/README.md new file mode 100644 index 00000000..2851f53d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/sdks/bookings/README.md @@ -0,0 +1,312 @@ +# Bookings + +## Overview + +Create and manage bookings for train trips, including passenger details and optional extras. + +### Available Operations + +* [getBookings](#getbookings) - List existing bookings +* [createBooking](#createbooking) - Create a booking +* [getBooking](#getbooking) - Get a booking +* [deleteBooking](#deletebooking) - Delete a booking + +## getBookings + +Returns a list of all trip bookings by the authenticated user. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.bookings.getBookings({}); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { bookingsGetBookings } from "sdk/funcs/bookingsGetBookings.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await bookingsGetBookings(sdk, {}); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("bookingsGetBookings failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.GetBookingsRequest](../../models/operations/getbookingsrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.GetBookingsResponseBody](../../models/operations/getbookingsresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------------- | -------------------------------------- | -------------------------------------- | +| errors.GetBookingsResponseBody | 401 | application/problem+json | +| errors.GetBookingsBookingsResponseBody | 500 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | + +## createBooking + +A booking is a temporary hold on a trip. It is not confirmed until payment is processed. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.bookings.createBooking({ + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, + }); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { bookingsCreateBooking } from "sdk/funcs/bookingsCreateBooking.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await bookingsCreateBooking(sdk, { + tripId: "ea399ba1-6d95-433f-92d1-83f67b775594", + passengerName: "John Doe", + hasBicycle: true, + hasDog: false, + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("bookingsCreateBooking failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.CreateBookingBookingsRequestRequestBody](../../models/operations/createbookingbookingsrequestrequestbody.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.CreateBookingResponseBody](../../models/operations/createbookingresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| ---------------------------------------- | ---------------------------------------- | ---------------------------------------- | +| errors.CreateBookingResponseBody | 404 | application/problem+json | +| errors.CreateBookingBookingsResponseBody | 409 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | + +## getBooking + +Returns the details of a specific booking. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.bookings.getBooking({ + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { bookingsGetBooking } from "sdk/funcs/bookingsGetBooking.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await bookingsGetBooking(sdk, { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("bookingsGetBooking failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.GetBookingRequest](../../models/operations/getbookingrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.GetBookingResponseBody](../../models/operations/getbookingresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| ----------------------------- | ----------------------------- | ----------------------------- | +| errors.GetBookingResponseBody | 404 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | + +## deleteBooking + +Deletes a booking, cancelling the hold on the trip. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + await sdk.bookings.deleteBooking({ + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }); + + +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { bookingsDeleteBooking } from "sdk/funcs/bookingsDeleteBooking.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await bookingsDeleteBooking(sdk, { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }); + if (res.ok) { + const { value: result } = res; + + } else { + console.log("bookingsDeleteBooking failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.DeleteBookingRequest](../../models/operations/deletebookingrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.DeleteBookingResponseBody | 404 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/sdks/payments/README.md b/frameworks-elysia/sdk-typescript/docs/sdks/payments/README.md new file mode 100644 index 00000000..1769d92b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/sdks/payments/README.md @@ -0,0 +1,111 @@ +# Payments + +## Overview + +Pay for bookings using a card or bank account, and view payment status and history. + +### Available Operations + +* [createBookingPayment](#createbookingpayment) - Pay for a booking + +## createBookingPayment + +A payment attempt confirms the booking and enables ticket retrieval. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.payments.createBookingPayment({ + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + requestBody: { + amount: 49.99, + currency: "bgn", + promoCode: "SUMMER20", + source: { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + }, + }, + }); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { paymentsCreateBookingPayment } from "sdk/funcs/paymentsCreateBookingPayment.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await paymentsCreateBookingPayment(sdk, { + bookingId: "1725ff48-ab45-4bb5-9d02-88745177dedb", + requestBody: { + amount: 49.99, + currency: "bgn", + promoCode: "SUMMER20", + source: { + object: "card", + name: "J. Doe", + number: "4242424242424242", + cvc: "123", + expMonth: 12, + expYear: 2025, + addressCountry: "gb", + }, + }, + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("paymentsCreateBookingPayment failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.CreateBookingPaymentRequest](../../models/operations/createbookingpaymentrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.CreateBookingPaymentResponseBody](../../models/operations/createbookingpaymentresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| --------------------------------------- | --------------------------------------- | --------------------------------------- | +| errors.CreateBookingPaymentResponseBody | 404 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/sdks/stations/README.md b/frameworks-elysia/sdk-typescript/docs/sdks/stations/README.md new file mode 100644 index 00000000..16d4c5f2 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/sdks/stations/README.md @@ -0,0 +1,87 @@ +# Stations + +## Overview + +Find and filter train stations across Europe, including their location and local timezone. + +### Available Operations + +* [getStations](#getstations) - Get a list of train stations + +## getStations + +Returns a paginated and searchable list of all train stations. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { stationsGetStations } from "sdk/funcs/stationsGetStations.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await stationsGetStations(sdk, { + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("stationsGetStations failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.GetStationsRequest](../../models/operations/getstationsrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.GetStationsResponseBody](../../models/operations/getstationsresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| ------------------------------ | ------------------------------ | ------------------------------ | +| errors.GetStationsResponseBody | 400 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/docs/sdks/trips/README.md b/frameworks-elysia/sdk-typescript/docs/sdks/trips/README.md new file mode 100644 index 00000000..e2ba3580 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/docs/sdks/trips/README.md @@ -0,0 +1,87 @@ +# Trips + +## Overview + +Timetables and routes for train trips between stations, including pricing and availability. + +### Available Operations + +* [getTrips](#gettrips) - Get available train trips + +## getTrips + +Returns a list of available train trips between the specified origin and destination stations on the given date. + +### Example Usage + + +```typescript +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const result = await sdk.trips.getTrips({ + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + date: new Date("2024-02-01T09:00:00Z"), + }); + + console.log(result); +} + +run(); +``` + +### Standalone function + +The standalone function version of this method: + +```typescript +import { SDKCore } from "sdk/core.js"; +import { tripsGetTrips } from "sdk/funcs/tripsGetTrips.js"; + +// Use `SDKCore` for best tree-shaking performance. +// You can create one instance of it to use across an application. +const sdk = new SDKCore({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function run() { + const res = await tripsGetTrips(sdk, { + origin: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + destination: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + date: new Date("2024-02-01T09:00:00Z"), + }); + if (res.ok) { + const { value: result } = res; + console.log(result); + } else { + console.log("tripsGetTrips failed:", res.error); + } +} + +run(); +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `request` | [operations.GetTripsRequest](../../models/operations/gettripsrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `options` | RequestOptions | :heavy_minus_sign: | Used to set various options for making HTTP requests. | +| `options.fetchOptions` | [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options) | :heavy_minus_sign: | Options that are passed to the underlying HTTP request. This can be used to inject extra headers for examples. All `Request` options, except `method` and `body`, are allowed. | +| `options.retries` | [RetryConfig](../../lib/utils/retryconfig.md) | :heavy_minus_sign: | Enables retrying HTTP requests under certain failure conditions. | + +### Response + +**Promise\<[operations.GetTripsResponseBody](../../models/operations/gettripsresponsebody.md)\>** + +### Errors + +| Error Type | Status Code | Content Type | +| --------------------------- | --------------------------- | --------------------------- | +| errors.GetTripsResponseBody | 400 | application/problem+json | +| errors.APIError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/eslint.config.mjs b/frameworks-elysia/sdk-typescript/eslint.config.mjs new file mode 100644 index 00000000..67bccfec --- /dev/null +++ b/frameworks-elysia/sdk-typescript/eslint.config.mjs @@ -0,0 +1,22 @@ +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { files: ["**/*.{js,mjs,cjs,ts}"] }, + { languageOptions: { globals: globals.browser } }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + rules: { + "no-constant-condition": "off", + "no-useless-escape": "off", + // Handled by typescript compiler + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-object-type": "off", + "@typescript-eslint/no-namespace": "off", + }, + }, +]; diff --git a/frameworks-elysia/sdk-typescript/examples/.env.template b/frameworks-elysia/sdk-typescript/examples/.env.template new file mode 100644 index 00000000..63defb75 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/examples/.env.template @@ -0,0 +1,14 @@ +# sdk SDK Environment Variables +# Copy this file to .env and fill in your actual values +# DO NOT commit the .env file to version control + +# Security Configuration +# The SDK supports loading security credentials from environment variables +# with the prefix: SDK_ +# +# Security environment variables: +SDK_O_AUTH2=your_oauth2_token_here + +# Debug Configuration +# Enable HTTP request/response logging for debugging +SDK_DEBUG=true diff --git a/frameworks-elysia/sdk-typescript/examples/README.md b/frameworks-elysia/sdk-typescript/examples/README.md new file mode 100644 index 00000000..fe153610 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/examples/README.md @@ -0,0 +1,31 @@ +# sdk Examples + +This directory contains example scripts demonstrating how to use the sdk SDK. + +## Prerequisites + +- Node.js (v18 or higher) +- npm + +## Setup + +1. Copy `.env.template` to `.env`: + ```bash + cp .env.template .env + ``` + +2. Edit `.env` and add your actual credentials (API keys, tokens, etc.) + +## Running the Examples + +To run an example file from the examples directory: + +```bash +npm run build && npx tsx example.ts +``` + +## Creating new examples + +Duplicate an existing example file, they won't be overwritten by the generation process. + + diff --git a/frameworks-elysia/sdk-typescript/examples/package.json b/frameworks-elysia/sdk-typescript/examples/package.json new file mode 100644 index 00000000..30f913da --- /dev/null +++ b/frameworks-elysia/sdk-typescript/examples/package.json @@ -0,0 +1,18 @@ +{ + "name": "sdk-examples", + "version": "1.0.0", + "private": true, + "scripts": { + "build:parent": "cd .. && npm i && npm run build && cd -", + "build:examples": "npm i", + "build": "npm run build:parent && npm run build:examples" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "dotenv": "^16.4.5", + "tsx": "^4.19.2" + }, + "dependencies": { + "sdk": "file:.." + } +} \ No newline at end of file diff --git a/frameworks-elysia/sdk-typescript/examples/stationsGetStations.example.ts b/frameworks-elysia/sdk-typescript/examples/stationsGetStations.example.ts new file mode 100644 index 00000000..8510dd2a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/examples/stationsGetStations.example.ts @@ -0,0 +1,30 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import dotenv from "dotenv"; +dotenv.config(); +/** + * Example usage of the sdk SDK + * + * To run this example from the examples directory: + * npm run build && npx tsx stationsGetStations.example.ts + */ + +import { SDK } from "sdk"; + +const sdk = new SDK({ + oAuth2: process.env["SDK_O_AUTH2"] ?? "", +}); + +async function main() { + const result = await sdk.stations.getStations({ + coordinates: "52.5200,13.4050", + search: "Milano Centrale", + country: "DE", + }); + + console.log(result); +} + +main().catch(console.error); diff --git a/frameworks-elysia/sdk-typescript/jsr.json b/frameworks-elysia/sdk-typescript/jsr.json new file mode 100644 index 00000000..288e3f4b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/jsr.json @@ -0,0 +1,27 @@ + + +{ + "name": "sdk", + "version": "0.1.0", + "exports": { + ".": "./src/index.ts", + "./models/errors": "./src/models/errors/index.ts", + "./models/components": "./src/models/components/index.ts", + "./models/operations": "./src/models/operations/index.ts", + "./lib/config": "./src/lib/config.ts", + "./lib/http": "./src/lib/http.ts", + "./lib/retries": "./src/lib/retries.ts", + "./lib/sdks": "./src/lib/sdks.ts", + "./types": "./src/types/index.ts" + }, + "publish": { + "include": [ + "LICENSE", + "README.md", + "RUNTIMES.md", + "USAGE.md", + "jsr.json", + "src/**/*.ts" + ] + } +} diff --git a/frameworks-elysia/sdk-typescript/package.json b/frameworks-elysia/sdk-typescript/package.json new file mode 100644 index 00000000..a0811ff6 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/package.json @@ -0,0 +1,25 @@ +{ + "name": "sdk", + "version": "0.1.0", + "author": "Speakeasy", + "main": "./index.js", + "sideEffects": false, + "scripts": { + "lint": "eslint --cache --max-warnings=0 src", + "build": "tsc", + "prepublishOnly": "npm run build" + }, + "peerDependencies": { + + }, + "devDependencies": { + "@eslint/js": "^9.26.0", + "eslint": "^9.26.0", + "globals": "^15.14.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.26.0" + }, + "dependencies": { + "zod": "^3.25.0 || ^4.0.0" + } +} diff --git a/frameworks-elysia/sdk-typescript/src/core.ts b/frameworks-elysia/sdk-typescript/src/core.ts new file mode 100644 index 00000000..c4486e4a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/core.ts @@ -0,0 +1,13 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { ClientSDK } from "./lib/sdks.js"; + +/** + * A minimal client to use when calling standalone SDK functions. Typically, an + * instance of this class would be instantiated once at the start of an + * application and passed around through some dependency injection mechanism to + * parts of an application that need to make SDK calls. + */ +export class SDKCore extends ClientSDK {} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/bookingsCreateBooking.ts b/frameworks-elysia/sdk-typescript/src/funcs/bookingsCreateBooking.ts new file mode 100644 index 00000000..36e23947 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/bookingsCreateBooking.ts @@ -0,0 +1,192 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeJSON } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Create a booking + * + * @remarks + * A booking is a temporary hold on a trip. It is not confirmed until payment is processed. + */ +export function bookingsCreateBooking( + client: SDKCore, + request: operations.CreateBookingBookingsRequestRequestBody, + options?: RequestOptions, +): APIPromise< + Result< + operations.CreateBookingResponseBody, + | errors.CreateBookingResponseBody + | errors.CreateBookingBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.CreateBookingBookingsRequestRequestBody, + options?: RequestOptions, +): Promise< + [ + Result< + operations.CreateBookingResponseBody, + | errors.CreateBookingResponseBody + | errors.CreateBookingBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => + operations.CreateBookingBookingsRequestRequestBody$outboundSchema.parse( + value, + ), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = encodeJSON("body", payload, { explode: true }); + + const path = pathToFunc("/bookings/")(); + + const headers = new Headers(compactMap({ + "Content-Type": "application/json", + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "create-booking", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 300, + maxInterval: 40000, + exponent: 1.2, + maxElapsedTime: 3000000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "POST", + baseURL: options?.serverURL, + path: path, + headers: headers, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.CreateBookingResponseBody, + | errors.CreateBookingResponseBody + | errors.CreateBookingBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(201, operations.CreateBookingResponseBody$inboundSchema), + M.jsonErr(404, errors.CreateBookingResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.jsonErr(409, errors.CreateBookingBookingsResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/bookingsDeleteBooking.ts b/frameworks-elysia/sdk-typescript/src/funcs/bookingsDeleteBooking.ts new file mode 100644 index 00000000..83819914 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/bookingsDeleteBooking.ts @@ -0,0 +1,189 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKCore } from "../core.js"; +import { encodeSimple } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Delete a booking + * + * @remarks + * Deletes a booking, cancelling the hold on the trip. + */ +export function bookingsDeleteBooking( + client: SDKCore, + request: operations.DeleteBookingRequest, + options?: RequestOptions, +): APIPromise< + Result< + void, + | errors.DeleteBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.DeleteBookingRequest, + options?: RequestOptions, +): Promise< + [ + Result< + void, + | errors.DeleteBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => operations.DeleteBookingRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = null; + + const pathParams = { + bookingId: encodeSimple("bookingId", payload.bookingId, { + explode: false, + charEncoding: "percent", + }), + }; + const path = pathToFunc("/bookings/{bookingId}")(pathParams); + + const headers = new Headers(compactMap({ + Accept: "application/problem+json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "delete-booking", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "DELETE", + baseURL: options?.serverURL, + path: path, + headers: headers, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + void, + | errors.DeleteBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.nil(204, z.void()), + M.jsonErr(404, errors.DeleteBookingResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBooking.ts b/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBooking.ts new file mode 100644 index 00000000..ba7e017f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBooking.ts @@ -0,0 +1,188 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeSimple } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Get a booking + * + * @remarks + * Returns the details of a specific booking. + */ +export function bookingsGetBooking( + client: SDKCore, + request: operations.GetBookingRequest, + options?: RequestOptions, +): APIPromise< + Result< + operations.GetBookingResponseBody, + | errors.GetBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.GetBookingRequest, + options?: RequestOptions, +): Promise< + [ + Result< + operations.GetBookingResponseBody, + | errors.GetBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => operations.GetBookingRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = null; + + const pathParams = { + bookingId: encodeSimple("bookingId", payload.bookingId, { + explode: false, + charEncoding: "percent", + }), + }; + const path = pathToFunc("/bookings/{bookingId}")(pathParams); + + const headers = new Headers(compactMap({ + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "get-booking", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "GET", + baseURL: options?.serverURL, + path: path, + headers: headers, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.GetBookingResponseBody, + | errors.GetBookingResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(200, operations.GetBookingResponseBody$inboundSchema), + M.jsonErr(404, errors.GetBookingResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBookings.ts b/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBookings.ts new file mode 100644 index 00000000..35af58c3 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/bookingsGetBookings.ts @@ -0,0 +1,194 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeFormQuery } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * List existing bookings + * + * @remarks + * Returns a list of all trip bookings by the authenticated user. + */ +export function bookingsGetBookings( + client: SDKCore, + request: operations.GetBookingsRequest, + options?: RequestOptions, +): APIPromise< + Result< + operations.GetBookingsResponseBody, + | errors.GetBookingsResponseBody + | errors.GetBookingsBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.GetBookingsRequest, + options?: RequestOptions, +): Promise< + [ + Result< + operations.GetBookingsResponseBody, + | errors.GetBookingsResponseBody + | errors.GetBookingsBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => operations.GetBookingsRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = null; + + const path = pathToFunc("/bookings/")(); + + const query = encodeFormQuery({ + "limit": payload.limit, + "page": payload.page, + }); + + const headers = new Headers(compactMap({ + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "get-bookings", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "GET", + baseURL: options?.serverURL, + path: path, + headers: headers, + query: query, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.GetBookingsResponseBody, + | errors.GetBookingsResponseBody + | errors.GetBookingsBookingsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(200, operations.GetBookingsResponseBody$inboundSchema), + M.jsonErr(401, errors.GetBookingsResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.jsonErr(500, errors.GetBookingsBookingsResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/paymentsCreateBookingPayment.ts b/frameworks-elysia/sdk-typescript/src/funcs/paymentsCreateBookingPayment.ts new file mode 100644 index 00000000..56b62fc6 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/paymentsCreateBookingPayment.ts @@ -0,0 +1,190 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeJSON, encodeSimple } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Pay for a booking + * + * @remarks + * A payment attempt confirms the booking and enables ticket retrieval. + */ +export function paymentsCreateBookingPayment( + client: SDKCore, + request: operations.CreateBookingPaymentRequest, + options?: RequestOptions, +): APIPromise< + Result< + operations.CreateBookingPaymentResponseBody, + | errors.CreateBookingPaymentResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.CreateBookingPaymentRequest, + options?: RequestOptions, +): Promise< + [ + Result< + operations.CreateBookingPaymentResponseBody, + | errors.CreateBookingPaymentResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => + operations.CreateBookingPaymentRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = encodeJSON("body", payload.RequestBody, { explode: true }); + + const pathParams = { + bookingId: encodeSimple("bookingId", payload.bookingId, { + explode: false, + charEncoding: "percent", + }), + }; + const path = pathToFunc("/bookings/{bookingId}/payment")(pathParams); + + const headers = new Headers(compactMap({ + "Content-Type": "application/json", + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "create-booking-payment", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "POST", + baseURL: options?.serverURL, + path: path, + headers: headers, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.CreateBookingPaymentResponseBody, + | errors.CreateBookingPaymentResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(200, operations.CreateBookingPaymentResponseBody$inboundSchema), + M.jsonErr(404, errors.CreateBookingPaymentResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/stationsGetStations.ts b/frameworks-elysia/sdk-typescript/src/funcs/stationsGetStations.ts new file mode 100644 index 00000000..21ac45d8 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/stationsGetStations.ts @@ -0,0 +1,191 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeFormQuery } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Get a list of train stations + * + * @remarks + * Returns a paginated and searchable list of all train stations. + */ +export function stationsGetStations( + client: SDKCore, + request: operations.GetStationsRequest, + options?: RequestOptions, +): APIPromise< + Result< + operations.GetStationsResponseBody, + | errors.GetStationsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.GetStationsRequest, + options?: RequestOptions, +): Promise< + [ + Result< + operations.GetStationsResponseBody, + | errors.GetStationsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => operations.GetStationsRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = null; + + const path = pathToFunc("/stations/")(); + + const query = encodeFormQuery({ + "coordinates": payload.coordinates, + "country": payload.country, + "limit": payload.limit, + "page": payload.page, + "search": payload.search, + }); + + const headers = new Headers(compactMap({ + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "get-stations", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "GET", + baseURL: options?.serverURL, + path: path, + headers: headers, + query: query, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.GetStationsResponseBody, + | errors.GetStationsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(200, operations.GetStationsResponseBody$inboundSchema), + M.jsonErr(400, errors.GetStationsResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/funcs/tripsGetTrips.ts b/frameworks-elysia/sdk-typescript/src/funcs/tripsGetTrips.ts new file mode 100644 index 00000000..e31946ea --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/funcs/tripsGetTrips.ts @@ -0,0 +1,193 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKCore } from "../core.js"; +import { encodeFormQuery } from "../lib/encodings.js"; +import { matchStatusCode } from "../lib/http.js"; +import * as M from "../lib/matchers.js"; +import { compactMap } from "../lib/primitives.js"; +import { safeParse } from "../lib/schemas.js"; +import { RequestOptions } from "../lib/sdks.js"; +import { extractSecurity, resolveGlobalSecurity } from "../lib/security.js"; +import { pathToFunc } from "../lib/url.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import * as errors from "../models/errors/index.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { SDKError } from "../models/errors/sdkerror.js"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import * as operations from "../models/operations/index.js"; +import { APICall, APIPromise } from "../types/async.js"; +import { Result } from "../types/fp.js"; + +/** + * Get available train trips + * + * @remarks + * Returns a list of available train trips between the specified origin and destination stations on the given date. + */ +export function tripsGetTrips( + client: SDKCore, + request: operations.GetTripsRequest, + options?: RequestOptions, +): APIPromise< + Result< + operations.GetTripsResponseBody, + | errors.GetTripsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + > +> { + return new APIPromise($do( + client, + request, + options, + )); +} + +async function $do( + client: SDKCore, + request: operations.GetTripsRequest, + options?: RequestOptions, +): Promise< + [ + Result< + operations.GetTripsResponseBody, + | errors.GetTripsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >, + APICall, + ] +> { + const parsed = safeParse( + request, + (value) => operations.GetTripsRequest$outboundSchema.parse(value), + "Input validation failed", + ); + if (!parsed.ok) { + return [parsed, { status: "invalid" }]; + } + const payload = parsed.value; + const body = null; + + const path = pathToFunc("/trips/")(); + + const query = encodeFormQuery({ + "bicycles": payload.bicycles, + "date": payload.date, + "destination": payload.destination, + "dogs": payload.dogs, + "limit": payload.limit, + "origin": payload.origin, + "page": payload.page, + }); + + const headers = new Headers(compactMap({ + Accept: "application/json", + })); + + const secConfig = await extractSecurity(client._options.oAuth2); + const securityInput = secConfig == null ? {} : { oAuth2: secConfig }; + const requestSecurity = resolveGlobalSecurity(securityInput); + + const context = { + options: client._options, + baseURL: options?.serverURL ?? client._baseURL ?? "", + operationID: "get-trips", + oAuth2Scopes: null, + + resolvedSecurity: requestSecurity, + + securitySource: client._options.oAuth2, + retryConfig: options?.retries + || client._options.retryConfig + || { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, + }, + retryConnectionErrors: true, + } + || { strategy: "none" }, + retryCodes: options?.retryCodes || ["5XX"], + }; + + const requestRes = client._createRequest(context, { + security: requestSecurity, + method: "GET", + baseURL: options?.serverURL, + path: path, + headers: headers, + query: query, + body: body, + userAgent: client._options.userAgent, + timeoutMs: options?.timeoutMs || client._options.timeoutMs || -1, + }, options); + if (!requestRes.ok) { + return [requestRes, { status: "invalid" }]; + } + const req = requestRes.value; + + const doResult = await client._do(req, { + context, + isErrorStatusCode: (statusCode: number) => + matchStatusCode({ status: statusCode } as Response, ["4XX", "5XX"]), + retryConfig: context.retryConfig, + retryCodes: context.retryCodes, + }); + if (!doResult.ok) { + return [doResult, { status: "request-error", request: req }]; + } + const response = doResult.value; + + const responseFields = { + HttpMeta: { Response: response, Request: req }, + }; + + const [result] = await M.match< + operations.GetTripsResponseBody, + | errors.GetTripsResponseBody + | SDKError + | ResponseValidationError + | ConnectionError + | RequestAbortedError + | RequestTimeoutError + | InvalidRequestError + | UnexpectedClientError + | SDKValidationError + >( + M.json(200, operations.GetTripsResponseBody$inboundSchema), + M.jsonErr(400, errors.GetTripsResponseBody$inboundSchema, { + ctype: "application/problem+json", + }), + M.fail("4XX"), + M.fail("5XX"), + )(response, req, { extraFields: responseFields }); + if (!result.ok) { + return [result, { status: "complete", request: req, response }]; + } + + return [result, { status: "complete", request: req, response }]; +} diff --git a/frameworks-elysia/sdk-typescript/src/hooks/hooks.ts b/frameworks-elysia/sdk-typescript/src/hooks/hooks.ts new file mode 100644 index 00000000..fc9b13b2 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/hooks/hooks.ts @@ -0,0 +1,129 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { RequestInput } from "../lib/http.js"; +import { + AfterErrorContext, + AfterErrorHook, + AfterSuccessContext, + AfterSuccessHook, + BeforeCreateRequestContext, + BeforeCreateRequestHook, + BeforeRequestContext, + BeforeRequestHook, + Hook, + Hooks, + SDKInitHook, + SDKInitOptions, +} from "./types.js"; + +export class SDKHooks implements Hooks { + sdkInitHooks: SDKInitHook[] = []; + beforeCreateRequestHooks: BeforeCreateRequestHook[] = []; + beforeRequestHooks: BeforeRequestHook[] = []; + afterSuccessHooks: AfterSuccessHook[] = []; + afterErrorHooks: AfterErrorHook[] = []; + + constructor() { + const presetHooks: Array = []; + + for (const hook of presetHooks) { + if ("sdkInit" in hook) { + this.registerSDKInitHook(hook); + } + if ("beforeCreateRequest" in hook) { + this.registerBeforeCreateRequestHook(hook); + } + if ("beforeRequest" in hook) { + this.registerBeforeRequestHook(hook); + } + if ("afterSuccess" in hook) { + this.registerAfterSuccessHook(hook); + } + if ("afterError" in hook) { + this.registerAfterErrorHook(hook); + } + } + } + + registerSDKInitHook(hook: SDKInitHook) { + this.sdkInitHooks.push(hook); + } + + registerBeforeCreateRequestHook(hook: BeforeCreateRequestHook) { + this.beforeCreateRequestHooks.push(hook); + } + + registerBeforeRequestHook(hook: BeforeRequestHook) { + this.beforeRequestHooks.push(hook); + } + + registerAfterSuccessHook(hook: AfterSuccessHook) { + this.afterSuccessHooks.push(hook); + } + + registerAfterErrorHook(hook: AfterErrorHook) { + this.afterErrorHooks.push(hook); + } + + sdkInit(opts: SDKInitOptions): SDKInitOptions { + return this.sdkInitHooks.reduce((opts, hook) => hook.sdkInit(opts), opts); + } + + beforeCreateRequest( + hookCtx: BeforeCreateRequestContext, + input: RequestInput, + ): RequestInput { + let inp = input; + + for (const hook of this.beforeCreateRequestHooks) { + inp = hook.beforeCreateRequest(hookCtx, inp); + } + + return inp; + } + + async beforeRequest( + hookCtx: BeforeRequestContext, + request: Request, + ): Promise { + let req = request; + + for (const hook of this.beforeRequestHooks) { + req = await hook.beforeRequest(hookCtx, req); + } + + return req; + } + + async afterSuccess( + hookCtx: AfterSuccessContext, + response: Response, + ): Promise { + let res = response; + + for (const hook of this.afterSuccessHooks) { + res = await hook.afterSuccess(hookCtx, res); + } + + return res; + } + + async afterError( + hookCtx: AfterErrorContext, + response: Response | null, + error: unknown, + ): Promise<{ response: Response | null; error: unknown }> { + let res = response; + let err = error; + + for (const hook of this.afterErrorHooks) { + const result = await hook.afterError(hookCtx, res, err); + res = result.response; + err = result.error; + } + + return { response: res, error: err }; + } +} diff --git a/frameworks-elysia/sdk-typescript/src/hooks/index.ts b/frameworks-elysia/sdk-typescript/src/hooks/index.ts new file mode 100644 index 00000000..f60ec7ac --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/hooks/index.ts @@ -0,0 +1,6 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./hooks.js"; +export * from "./types.js"; diff --git a/frameworks-elysia/sdk-typescript/src/hooks/oauth2scopes.ts b/frameworks-elysia/sdk-typescript/src/hooks/oauth2scopes.ts new file mode 100644 index 00000000..f9184cb4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/hooks/oauth2scopes.ts @@ -0,0 +1,19 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** + * Available scopes for the OAuth2 OAuth 2.0 scheme (authorizationCode flow). + * + * @remarks + * OAuth 2.0 authorization code flow. + */ +export type OAuth2Scope = + /** + * Read access + */ + | "read" + /** + * Write access + */ + | "write"; diff --git a/frameworks-elysia/sdk-typescript/src/hooks/registration.ts b/frameworks-elysia/sdk-typescript/src/hooks/registration.ts new file mode 100644 index 00000000..70649734 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/hooks/registration.ts @@ -0,0 +1,14 @@ +import { Hooks } from "./types.js"; + +/* + * This file is only ever generated once on the first generation and then is free to be modified. + * Any hooks you wish to add should be registered in the initHooks function. Feel free to define them + * in this file or in separate files in the hooks folder. + */ + +// @ts-expect-error remove this line when you add your first hook and hooks is used +export function initHooks(hooks: Hooks) { + // Add hooks by calling hooks.register{ClientInit/BeforeCreateRequest/BeforeRequest/AfterSuccess/AfterError}Hook + // with an instance of a hook that implements that specific Hook interface + // Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance +} diff --git a/frameworks-elysia/sdk-typescript/src/hooks/types.ts b/frameworks-elysia/sdk-typescript/src/hooks/types.ts new file mode 100644 index 00000000..8bfe4fe8 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/hooks/types.ts @@ -0,0 +1,112 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKOptions } from "../lib/config.js"; +import { HTTPClient, RequestInput } from "../lib/http.js"; +import { RetryConfig } from "../lib/retries.js"; +import { SecurityState } from "../lib/security.js"; + +export type HookContext = { + baseURL: string | URL; + operationID: string; + oAuth2Scopes: string[] | null; + securitySource?: any | (() => Promise); + retryConfig: RetryConfig; + resolvedSecurity: SecurityState | null; + options: SDKOptions; +}; + +export type Awaitable = T | Promise; + +export type SDKInitOptions = { + baseURL: URL | null; + client: HTTPClient; +}; + +export type BeforeCreateRequestContext = HookContext & {}; +export type BeforeRequestContext = HookContext & {}; +export type AfterSuccessContext = HookContext & {}; +export type AfterErrorContext = HookContext & {}; + +/** + * SDKInitHook is called when the SDK is initializing. The + * hook can return a new baseURL and HTTP client to be used by the SDK. + */ +export interface SDKInitHook { + sdkInit: (opts: SDKInitOptions) => SDKInitOptions; +} + +export interface BeforeCreateRequestHook { + /** + * A hook that is called before the SDK creates a `Request` object. The hook + * can modify how a request is constructed since certain modifications, like + * changing the request URL, cannot be done on a request object directly. + */ + beforeCreateRequest: ( + hookCtx: BeforeCreateRequestContext, + input: RequestInput, + ) => RequestInput; +} + +export interface BeforeRequestHook { + /** + * A hook that is called before the SDK sends a request. The hook can + * introduce instrumentation code such as logging, tracing and metrics or + * replace the request before it is sent or throw an error to stop the + * request from being sent. + */ + beforeRequest: ( + hookCtx: BeforeRequestContext, + request: Request, + ) => Awaitable; +} + +export interface AfterSuccessHook { + /** + * A hook that is called after the SDK receives a response. The hook can + * introduce instrumentation code such as logging, tracing and metrics or + * modify the response before it is handled or throw an error to stop the + * response from being handled. + */ + afterSuccess: ( + hookCtx: AfterSuccessContext, + response: Response, + ) => Awaitable; +} + +export interface AfterErrorHook { + /** + * A hook that is called after the SDK encounters an error, or a + * non-successful response. The hook can introduce instrumentation code such + * as logging, tracing and metrics or modify the response or error values. + */ + afterError: ( + hookCtx: AfterErrorContext, + response: Response | null, + error: unknown, + ) => Awaitable<{ + response: Response | null; + error: unknown; + }>; +} + +export interface Hooks { + /** Registers a hook to be used by the SDK for initialization event. */ + registerSDKInitHook(hook: SDKInitHook): void; + /** Registers a hook to be used by the SDK for to modify `Request` construction. */ + registerBeforeCreateRequestHook(hook: BeforeCreateRequestHook): void; + /** Registers a hook to be used by the SDK for the before request event. */ + registerBeforeRequestHook(hook: BeforeRequestHook): void; + /** Registers a hook to be used by the SDK for the after success event. */ + registerAfterSuccessHook(hook: AfterSuccessHook): void; + /** Registers a hook to be used by the SDK for the after error event. */ + registerAfterErrorHook(hook: AfterErrorHook): void; +} + +export type Hook = + | SDKInitHook + | BeforeCreateRequestHook + | BeforeRequestHook + | AfterSuccessHook + | AfterErrorHook; diff --git a/frameworks-elysia/sdk-typescript/src/index.ts b/frameworks-elysia/sdk-typescript/src/index.ts new file mode 100644 index 00000000..dbcba164 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/index.ts @@ -0,0 +1,9 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./lib/config.js"; +export * as files from "./lib/files.js"; +export { HTTPClient } from "./lib/http.js"; +export type { Fetcher, HTTPClientOptions } from "./lib/http.js"; +export * from "./sdk/sdk.js"; diff --git a/frameworks-elysia/sdk-typescript/src/lib/base64.ts b/frameworks-elysia/sdk-typescript/src/lib/base64.ts new file mode 100644 index 00000000..0aebd8b0 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/base64.ts @@ -0,0 +1,37 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; + +export function bytesToBase64(u8arr: Uint8Array): string { + return btoa(String.fromCodePoint(...u8arr)); +} + +export function bytesFromBase64(encoded: string): Uint8Array { + return Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0)); +} + +export function stringToBytes(str: string): Uint8Array { + return new TextEncoder().encode(str); +} + +export function stringFromBytes(u8arr: Uint8Array): string { + return new TextDecoder().decode(u8arr); +} + +export function stringToBase64(str: string): string { + return bytesToBase64(stringToBytes(str)); +} + +export function stringFromBase64(b64str: string): string { + return stringFromBytes(bytesFromBase64(b64str)); +} + +export const zodOutbound = z + .instanceof(Uint8Array) + .or(z.string().transform(stringToBytes)); + +export const zodInbound = z + .instanceof(Uint8Array) + .or(z.string().transform(bytesFromBase64)); diff --git a/frameworks-elysia/sdk-typescript/src/lib/config.ts b/frameworks-elysia/sdk-typescript/src/lib/config.ts new file mode 100644 index 00000000..1a45685b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/config.ts @@ -0,0 +1,71 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { HTTPClient } from "./http.js"; +import { Logger } from "./logger.js"; +import { RetryConfig } from "./retries.js"; +import { Params, pathToFunc } from "./url.js"; + +/** + * Contains the list of servers available to the SDK + */ +export const ServerList = [ + /** + * Production + */ + "https://api.example.com", + /** + * Development server + */ + "http://localhost:3000", +] as const; + +export type SDKOptions = { + oAuth2?: string | (() => Promise) | undefined; + + httpClient?: HTTPClient; + /** + * Allows overriding the default server used by the SDK + */ + serverIdx?: number | undefined; + /** + * Allows overriding the default server URL used by the SDK + */ + serverURL?: string | undefined; + /** + * Allows overriding the default user agent used by the SDK + */ + userAgent?: string | undefined; + /** + * Allows overriding the default retry config used by the SDK + */ + retryConfig?: RetryConfig; + timeoutMs?: number; + debugLogger?: Logger; +}; + +export function serverURLFromOptions(options: SDKOptions): URL | null { + let serverURL = options.serverURL; + + const params: Params = {}; + + if (!serverURL) { + const serverIdx = options.serverIdx ?? 0; + if (serverIdx < 0 || serverIdx >= ServerList.length) { + throw new Error(`Invalid server index ${serverIdx}`); + } + serverURL = ServerList[serverIdx] || ""; + } + + const u = pathToFunc(serverURL)(params); + return new URL(u); +} + +export const SDK_METADATA = { + language: "typescript", + openapiDocVersion: "2.0.0", + sdkVersion: "0.1.0", + genVersion: "2.893.0", + userAgent: "speakeasy-sdk/typescript 0.1.0 2.893.0 2.0.0 sdk", +} as const; diff --git a/frameworks-elysia/sdk-typescript/src/lib/dlv.ts b/frameworks-elysia/sdk-typescript/src/lib/dlv.ts new file mode 100644 index 00000000..e81091f5 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/dlv.ts @@ -0,0 +1,53 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/* +MIT License + +Copyright (c) 2024 Jason Miller (http://jasonformat.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +/** + * @param obj The object to walk + * @param key The key path to walk the object with + * @param def A default value to return if the result is undefined + * + * @example + * dlv(obj, "a.b.c.d") + * @example + * dlv(object, ["a", "b", "c", "d"]) + * @example + * dlv(object, "foo.bar.baz", "Hello, default value!") + */ +export function dlv( + obj: any, + key: string | string[], + def?: T, + p?: number, + undef?: never, +): T | undefined { + key = Array.isArray(key) ? key : key.split("."); + for (p = 0; p < key.length; p++) { + const k = key[p]; + obj = k != null && obj ? obj[k] : undef; + } + return obj === undef ? def : obj; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/encodings.ts b/frameworks-elysia/sdk-typescript/src/lib/encodings.ts new file mode 100644 index 00000000..2791d25b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/encodings.ts @@ -0,0 +1,525 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { bytesToBase64 } from "./base64.js"; +import { isPlainObject } from "./is-plain-object.js"; + +export class EncodingError extends Error { + constructor(message: string) { + super(message); + this.name = "EncodingError"; + } +} + +export function encodeMatrix( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +): string | undefined { + let out = ""; + const pairs: [string, unknown][] = options?.explode + ? explode(key, value) + : [[key, value]]; + + if (pairs.every(([_, v]) => v == null)) { + return; + } + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + const encodeValue = (v: unknown) => encodeString(serializeValue(v)); + + pairs.forEach(([pk, pv]) => { + let tmp = ""; + let encValue: string | null | undefined = null; + + if (pv == null) { + return; + } else if (Array.isArray(pv)) { + encValue = mapDefined(pv, (v) => `${encodeValue(v)}`)?.join(","); + } else if (isPlainObject(pv)) { + const mapped = mapDefinedEntries(Object.entries(pv), ([k, v]) => { + return `,${encodeString(k)},${encodeValue(v)}`; + }); + encValue = mapped?.join("").slice(1); + } else { + encValue = `${encodeValue(pv)}`; + } + + if (encValue == null) { + return; + } + + const keyPrefix = encodeString(pk); + tmp = `${keyPrefix}=${encValue}`; + // trim trailing '=' if value was empty + if (tmp === `${keyPrefix}=`) { + tmp = tmp.slice(0, -1); + } + + // If we end up with the nothing then skip forward + if (!tmp) { + return; + } + + out += `;${tmp}`; + }); + + return out; +} + +export function encodeLabel( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +): string | undefined { + let out = ""; + const pairs: [string, unknown][] = options?.explode + ? explode(key, value) + : [[key, value]]; + + if (pairs.every(([_, v]) => v == null)) { + return; + } + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + const encodeValue = (v: unknown) => encodeString(serializeValue(v)); + + pairs.forEach(([pk, pv]) => { + let encValue: string | null | undefined = ""; + + if (pv == null) { + return; + } else if (Array.isArray(pv)) { + encValue = mapDefined(pv, (v) => `${encodeValue(v)}`)?.join("."); + } else if (isPlainObject(pv)) { + const mapped = mapDefinedEntries(Object.entries(pv), ([k, v]) => { + return `.${encodeString(k)}.${encodeValue(v)}`; + }); + encValue = mapped?.join("").slice(1); + } else { + const k = options?.explode && isPlainObject(value) + ? `${encodeString(pk)}=` + : ""; + encValue = `${k}${encodeValue(pv)}`; + } + + out += encValue == null ? "" : `.${encValue}`; + }); + + return out; +} + +type FormEncoder = ( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +) => string | undefined; + +function formEncoder(sep: string): FormEncoder { + return ( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, + ) => { + let out = ""; + const pairs: [string, unknown][] = options?.explode + ? explode(key, value) + : [[key, value]]; + + if (pairs.every(([_, v]) => v == null)) { + return; + } + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + + const encodeValue = (v: unknown) => encodeString(serializeValue(v)); + + const encodedSep = encodeString(sep); + + pairs.forEach(([pk, pv]) => { + let tmp = ""; + let encValue: string | null | undefined = null; + + if (pv == null) { + return; + } else if (Array.isArray(pv)) { + encValue = mapDefined(pv, (v) => `${encodeValue(v)}`)?.join(encodedSep); + } else if (isPlainObject(pv)) { + encValue = mapDefinedEntries(Object.entries(pv), ([k, v]) => { + return `${encodeString(k)}${encodedSep}${encodeValue(v)}`; + })?.join(encodedSep); + } else { + encValue = `${encodeValue(pv)}`; + } + + if (encValue == null) { + return; + } + + tmp = `${encodeString(pk)}=${encValue}`; + + // If we end up with the nothing then skip forward + if (!tmp || tmp === "=") { + return; + } + + out += `&${tmp}`; + }); + + return out.slice(1); + }; +} + +export const encodeForm = formEncoder(","); +export const encodeSpaceDelimited = formEncoder(" "); +export const encodePipeDelimited = formEncoder("|"); + +export function encodeBodyForm( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +): string { + let out = ""; + const pairs: [string, unknown][] = options?.explode + ? explode(key, value) + : [[key, value]]; + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + + const encodeValue = (v: unknown) => encodeString(serializeValue(v)); + + pairs.forEach(([pk, pv]) => { + let tmp = ""; + let encValue = ""; + + if (pv == null) { + return; + } else if (Array.isArray(pv)) { + encValue = JSON.stringify(pv, jsonReplacer); + } else if (isPlainObject(pv)) { + encValue = JSON.stringify(pv, jsonReplacer); + } else { + encValue = `${encodeValue(pv)}`; + } + + tmp = `${encodeString(pk)}=${encValue}`; + + // If we end up with the nothing then skip forward + if (!tmp || tmp === "=") { + return; + } + + out += `&${tmp}`; + }); + + return out.slice(1); +} + +export function encodeDeepObject( + key: string, + value: unknown, + options?: { charEncoding?: "percent" | "none" }, +): string | undefined { + if (value == null) { + return; + } + + if (!isPlainObject(value)) { + throw new EncodingError( + `Value of parameter '${key}' which uses deepObject encoding must be an object or null`, + ); + } + + return encodeDeepObjectObject(key, value, options); +} + +export function encodeDeepObjectObject( + key: string, + value: unknown, + options?: { charEncoding?: "percent" | "none" }, +): string | undefined { + if (value == null) { + return; + } + + let out = ""; + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + + if (!isPlainObject(value)) { + throw new EncodingError(`Expected parameter '${key}' to be an object.`); + } + + Object.entries(value).forEach(([ck, cv]) => { + if (cv == null) { + return; + } + + const pk = `${key}[${ck}]`; + + if (isPlainObject(cv)) { + const objOut = encodeDeepObjectObject(pk, cv, options); + + out += objOut == null ? "" : `&${objOut}`; + + return; + } + + const pairs: unknown[] = Array.isArray(cv) ? cv : [cv]; + const encoded = mapDefined(pairs, (v) => { + return `${encodeString(pk)}=${encodeString(serializeValue(v))}`; + })?.join("&"); + + out += encoded == null ? "" : `&${encoded}`; + }); + + return out.slice(1); +} + +export function encodeJSON( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +): string | undefined { + if (typeof value === "undefined") { + return; + } + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + + const encVal = encodeString(JSON.stringify(value, jsonReplacer)); + + return options?.explode ? encVal : `${encodeString(key)}=${encVal}`; +} + +export const encodeSimple = ( + key: string, + value: unknown, + options?: { explode?: boolean; charEncoding?: "percent" | "none" }, +): string | undefined => { + let out = ""; + const pairs: [string, unknown][] = options?.explode + ? explode(key, value) + : [[key, value]]; + + if (pairs.every(([_, v]) => v == null)) { + return; + } + + const encodeString = (v: string) => { + return options?.charEncoding === "percent" ? encodeURIComponent(v) : v; + }; + const encodeValue = (v: unknown) => encodeString(serializeValue(v)); + + pairs.forEach(([pk, pv]) => { + let tmp: string | null | undefined = ""; + + if (pv == null) { + return; + } else if (Array.isArray(pv)) { + tmp = mapDefined(pv, (v) => `${encodeValue(v)}`)?.join(","); + } else if (isPlainObject(pv)) { + const mapped = mapDefinedEntries(Object.entries(pv), ([k, v]) => { + return `,${encodeString(k)},${encodeValue(v)}`; + }); + tmp = mapped?.join("").slice(1); + } else { + const k = options?.explode && isPlainObject(value) ? `${pk}=` : ""; + tmp = `${k}${encodeValue(pv)}`; + } + + out += tmp ? `,${tmp}` : ""; + }); + + return out.slice(1); +}; + +function explode(key: string, value: unknown): [string, unknown][] { + if (Array.isArray(value)) { + return value.map((v) => [key, v]); + } else if (isPlainObject(value)) { + const o = value ?? {}; + return Object.entries(o).map(([k, v]) => [k, v]); + } else { + return [[key, value]]; + } +} + +function serializeValue(value: unknown): string { + if (value == null) { + return ""; + } else if (value instanceof Date) { + return value.toISOString(); + } else if (value instanceof Uint8Array) { + return bytesToBase64(value); + } else if (typeof value === "object") { + return JSON.stringify(value, jsonReplacer); + } + + return `${value}`; +} + +function jsonReplacer(_: string, value: unknown): unknown { + if (value instanceof Uint8Array) { + return bytesToBase64(value); + } else { + return value; + } +} + +function mapDefined(inp: T[], mapper: (v: T) => R): R[] | null { + const res = inp.reduce((acc, v) => { + if (v == null) { + return acc; + } + + const m = mapper(v); + if (m == null) { + return acc; + } + + acc.push(m); + + return acc; + }, []); + + return res.length ? res : null; +} + +function mapDefinedEntries( + inp: Iterable<[K, V]>, + mapper: (v: [K, V]) => R, +): R[] | null { + const acc: R[] = []; + for (const [k, v] of inp) { + if (v == null) { + continue; + } + + const m = mapper([k, v]); + if (m == null) { + continue; + } + + acc.push(m); + } + + return acc.length ? acc : null; +} + +export function queryJoin(...args: (string | undefined)[]): string { + return args.filter(Boolean).join("&"); +} + +type QueryEncoderOptions = { + explode?: boolean; + charEncoding?: "percent" | "none"; + allowEmptyValue?: string[]; +}; + +type QueryEncoder = ( + key: string, + value: unknown, + options?: QueryEncoderOptions, +) => string | undefined; + +type BulkQueryEncoder = ( + values: Record, + options?: QueryEncoderOptions, +) => string; + +export function queryEncoder(f: QueryEncoder): BulkQueryEncoder { + const bulkEncode = function( + values: Record, + options?: QueryEncoderOptions, + ): string { + const opts: QueryEncoderOptions = { + ...options, + explode: options?.explode ?? true, + charEncoding: options?.charEncoding ?? "percent", + }; + + const allowEmptySet = new Set(options?.allowEmptyValue ?? []); + + const encoded = Object.entries(values).map(([key, value]) => { + if (allowEmptySet.has(key)) { + if ( + value === undefined + || value === null + || value === "" + || (Array.isArray(value) && value.length === 0) + ) { + return `${encodeURIComponent(key)}=`; + } + } + return f(key, value, opts); + }); + return queryJoin(...encoded); + }; + + return bulkEncode; +} + +export const encodeJSONQuery = queryEncoder(encodeJSON); +export const encodeFormQuery = queryEncoder(encodeForm); +export const encodeSpaceDelimitedQuery = queryEncoder(encodeSpaceDelimited); +export const encodePipeDelimitedQuery = queryEncoder(encodePipeDelimited); +export const encodeDeepObjectQuery = queryEncoder(encodeDeepObject); + +function isBlobLike(val: unknown): val is Blob { + if (val instanceof Blob) { + return true; + } + + if (typeof val !== "object" || val == null || !(Symbol.toStringTag in val)) { + return false; + } + + const tag = val[Symbol.toStringTag]; + if (tag !== "Blob" && tag !== "File") { + return false; + } + + return "stream" in val && typeof val.stream === "function"; +} + +export function appendForm( + fd: FormData, + key: string, + value: unknown, + fileName?: string, +): void { + if (value == null) { + return; + } else if (isBlobLike(value)) { + if (fileName) { + fd.append(key, value as Blob, fileName); + } else { + fd.append(key, value as Blob); + } + } else { + fd.append(key, String(value)); + } +} + +export async function normalizeBlob( + value: Pick, +): Promise { + if (value instanceof Blob) { + return value; + } + return new Blob([await value.arrayBuffer()], { type: value.type }); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/env.ts b/frameworks-elysia/sdk-typescript/src/lib/env.ts new file mode 100644 index 00000000..83cc953a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/env.ts @@ -0,0 +1,57 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { dlv } from "./dlv.js"; + +export interface Env { + SDK_O_AUTH2?: string | undefined; + + SDK_DEBUG?: boolean | undefined; +} + +export const envSchema: z.ZodType = z.object({ + SDK_O_AUTH2: z.string().optional(), + + SDK_DEBUG: z.coerce.boolean().optional(), +}); + +/** + * Checks for the existence of the Deno global object to determine the environment. + * @returns {boolean} True if the runtime is Deno, false otherwise. + */ +function isDeno() { + if ("Deno" in globalThis) { + return true; + } + + return false; +} + +let envMemo: Env | undefined = undefined; +/** + * Reads and validates environment variables. + */ +export function env(): Env { + if (envMemo) { + return envMemo; + } + + let envObject: Record = {}; + if (isDeno()) { + envObject = (globalThis as any).Deno?.env?.toObject?.() ?? {}; + } else { + envObject = dlv(globalThis, "process.env") ?? {}; + } + + envMemo = envSchema.parse(envObject); + return envMemo; +} + +/** + * Clears the cached env object. Useful for testing with a fresh environment. + */ +export function resetEnv() { + envMemo = undefined; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/files.ts b/frameworks-elysia/sdk-typescript/src/lib/files.ts new file mode 100644 index 00000000..6ca6b37d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/files.ts @@ -0,0 +1,104 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** + * Consumes a stream and returns a concatenated array buffer. Useful in + * situations where we need to read the whole file because it forms part of a + * larger payload containing other fields, and we can't modify the underlying + * request structure. + */ +export async function readableStreamToArrayBuffer( + readable: ReadableStream, +): Promise { + const reader = readable.getReader(); + const chunks: Uint8Array[] = []; + + let totalLength = 0; + let done = false; + + while (!done) { + const { value, done: doneReading } = await reader.read(); + + if (doneReading) { + done = true; + } else { + chunks.push(value); + totalLength += value.length; + } + } + + const concatenatedChunks = new Uint8Array(totalLength); + let offset = 0; + + for (const chunk of chunks) { + concatenatedChunks.set(chunk, offset); + offset += chunk.length; + } + + return concatenatedChunks.buffer as ArrayBuffer; +} + +/** + * Determines the MIME content type based on a file's extension. + * Returns null if the extension is not recognized. + */ +export function getContentTypeFromFileName(fileName: string): string | null { + if (!fileName) return null; + + const ext = fileName.toLowerCase().split(".").pop(); + if (!ext) return null; + + const mimeTypes: Record = { + json: "application/json", + xml: "application/xml", + html: "text/html", + htm: "text/html", + txt: "text/plain", + csv: "text/csv", + pdf: "application/pdf", + png: "image/png", + jpg: "image/jpeg", + jpeg: "image/jpeg", + gif: "image/gif", + svg: "image/svg+xml", + js: "application/javascript", + css: "text/css", + zip: "application/zip", + tar: "application/x-tar", + gz: "application/gzip", + mp4: "video/mp4", + mp3: "audio/mpeg", + wav: "audio/wav", + webp: "image/webp", + ico: "image/x-icon", + woff: "font/woff", + woff2: "font/woff2", + ttf: "font/ttf", + otf: "font/otf", + }; + + return mimeTypes[ext] || null; +} + +/** + * Creates a Blob from file content with the given MIME type. + * + * Node.js Buffers are Uint8Array subclasses that may share a pooled + * ArrayBuffer (byteOffset > 0, byteLength < buffer.byteLength). Passing + * such a Buffer directly to `new Blob([buf])` can include the entire + * underlying pool on some runtimes, producing a Blob with extra bytes + * that corrupts multipart uploads. + * + * Copying into a standalone Uint8Array ensures the Blob receives only the + * intended bytes regardless of runtime behaviour. + */ +export function bytesToBlob( + content: Uint8Array | ArrayBuffer | Blob | string, + contentType: string, +): Blob { + if (content instanceof Uint8Array) { + return new Blob([new Uint8Array(content)], { type: contentType }); + } + return new Blob([content as BlobPart], { type: contentType }); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/http.ts b/frameworks-elysia/sdk-typescript/src/lib/http.ts new file mode 100644 index 00000000..13cf1fd7 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/http.ts @@ -0,0 +1,323 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export type Fetcher = ( + input: RequestInfo | URL, + init?: RequestInit, +) => Promise; + +export type Awaitable = T | Promise; + +const DEFAULT_FETCHER: Fetcher = (input, init) => { + // If input is a Request and init is undefined, Bun will discard the method, + // headers, body and other options that were set on the request object. + // Node.js and browers would ignore an undefined init value. This check is + // therefore needed for interop with Bun. + if (init == null) { + return fetch(input); + } else { + return fetch(input, init); + } +}; + +export type RequestInput = { + /** + * The URL the request will use. + */ + url: URL; + /** + * Options used to create a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request). + */ + options?: RequestInit | undefined; +}; + +export interface HTTPClientOptions { + fetcher?: Fetcher; +} + +export type BeforeRequestHook = (req: Request) => Awaitable; +export type RequestErrorHook = (err: unknown, req: Request) => Awaitable; +export type ResponseHook = (res: Response, req: Request) => Awaitable; + +export class HTTPClient { + private fetcher: Fetcher; + private requestHooks: BeforeRequestHook[] = []; + private requestErrorHooks: RequestErrorHook[] = []; + private responseHooks: ResponseHook[] = []; + + constructor(private options: HTTPClientOptions = {}) { + this.fetcher = options.fetcher || DEFAULT_FETCHER; + } + + async request(request: Request): Promise { + let req = request; + for (const hook of this.requestHooks) { + const nextRequest = await hook(req); + if (nextRequest) { + req = nextRequest; + } + } + + try { + const res = await this.fetcher(req); + + for (const hook of this.responseHooks) { + await hook(res, req); + } + + return res; + } catch (err) { + for (const hook of this.requestErrorHooks) { + await hook(err, req); + } + + throw err; + } + } + + /** + * Registers a hook that is called before a request is made. The hook function + * can mutate the request or return a new request. This may be useful to add + * additional information to request such as request IDs and tracing headers. + */ + addHook(hook: "beforeRequest", fn: BeforeRequestHook): this; + /** + * Registers a hook that is called when a request cannot be made due to a + * network error. + */ + addHook(hook: "requestError", fn: RequestErrorHook): this; + /** + * Registers a hook that is called when a response has been received from the + * server. + */ + addHook(hook: "response", fn: ResponseHook): this; + addHook( + ...args: + | [hook: "beforeRequest", fn: BeforeRequestHook] + | [hook: "requestError", fn: RequestErrorHook] + | [hook: "response", fn: ResponseHook] + ) { + if (args[0] === "beforeRequest") { + this.requestHooks.push(args[1]); + } else if (args[0] === "requestError") { + this.requestErrorHooks.push(args[1]); + } else if (args[0] === "response") { + this.responseHooks.push(args[1]); + } else { + throw new Error(`Invalid hook type: ${args[0]}`); + } + return this; + } + + /** Removes a hook that was previously registered with `addHook`. */ + removeHook(hook: "beforeRequest", fn: BeforeRequestHook): this; + /** Removes a hook that was previously registered with `addHook`. */ + removeHook(hook: "requestError", fn: RequestErrorHook): this; + /** Removes a hook that was previously registered with `addHook`. */ + removeHook(hook: "response", fn: ResponseHook): this; + removeHook( + ...args: + | [hook: "beforeRequest", fn: BeforeRequestHook] + | [hook: "requestError", fn: RequestErrorHook] + | [hook: "response", fn: ResponseHook] + ): this { + let target: unknown[]; + if (args[0] === "beforeRequest") { + target = this.requestHooks; + } else if (args[0] === "requestError") { + target = this.requestErrorHooks; + } else if (args[0] === "response") { + target = this.responseHooks; + } else { + throw new Error(`Invalid hook type: ${args[0]}`); + } + + const index = target.findIndex((v) => v === args[1]); + if (index >= 0) { + target.splice(index, 1); + } + + return this; + } + + clone(): HTTPClient { + const child = new HTTPClient(this.options); + child.requestHooks = this.requestHooks.slice(); + child.requestErrorHooks = this.requestErrorHooks.slice(); + child.responseHooks = this.responseHooks.slice(); + + return child; + } +} + +export type StatusCodePredicate = number | string | (number | string)[]; + +// A semicolon surrounded by optional whitespace characters is used to separate +// segments in a media type string. +const mediaParamSeparator = /\s*;\s*/g; + +export function matchContentType(response: Response, pattern: string): boolean { + // `*` is a special case which means anything is acceptable. + if (pattern === "*") { + return true; + } + + let contentType = + response.headers.get("content-type")?.trim() || "application/octet-stream"; + contentType = contentType.toLowerCase(); + + const wantParts = pattern.toLowerCase().trim().split(mediaParamSeparator); + const [wantType = "", ...wantParams] = wantParts; + + if (wantType.split("/").length !== 2) { + return false; + } + + const gotParts = contentType.split(mediaParamSeparator); + const [gotType = "", ...gotParams] = gotParts; + + const [type = "", subtype = ""] = gotType.split("/"); + if (!type || !subtype) { + return false; + } + + if ( + wantType !== "*/*" && + gotType !== wantType && + `${type}/*` !== wantType && + `*/${subtype}` !== wantType + ) { + return false; + } + + if (gotParams.length < wantParams.length) { + return false; + } + + const params = new Set(gotParams); + for (const wantParam of wantParams) { + if (!params.has(wantParam)) { + return false; + } + } + + return true; +} + +const codeRangeRE = new RegExp("^[0-9]xx$", "i"); + +export function matchStatusCode( + response: Response, + codes: StatusCodePredicate, +): boolean { + const actual = `${response.status}`; + const expectedCodes = Array.isArray(codes) ? codes : [codes]; + if (!expectedCodes.length) { + return false; + } + + return expectedCodes.some((ec) => { + const code = `${ec}`; + + if (code === "default") { + return true; + } + + if (!codeRangeRE.test(`${code}`)) { + return code === actual; + } + + const expectFamily = code.charAt(0); + if (!expectFamily) { + throw new Error("Invalid status code range"); + } + + const actualFamily = actual.charAt(0); + if (!actualFamily) { + throw new Error(`Invalid response status code: ${actual}`); + } + + return actualFamily === expectFamily; + }); +} + +export function matchResponse( + response: Response, + code: StatusCodePredicate, + contentTypePattern: string, +): boolean { + return ( + matchStatusCode(response, code) && + matchContentType(response, contentTypePattern) + ); +} + +/** + * Uses various heurisitics to determine if an error is a connection error. + */ +export function isConnectionError(err: unknown): boolean { + if (typeof err !== "object" || err == null) { + return false; + } + + // Covers fetch in Deno as well + const isBrowserErr = + err instanceof TypeError && + err.message.toLowerCase().startsWith("failed to fetch"); + + const isNodeErr = + err instanceof TypeError && + err.message.toLowerCase().startsWith("fetch failed"); + + const isBunErr = "name" in err && err.name === "ConnectionError"; + + const isGenericErr = + "code" in err && + typeof err.code === "string" && + err.code.toLowerCase() === "econnreset"; + + return isBrowserErr || isNodeErr || isGenericErr || isBunErr; +} + +/** + * Uses various heurisitics to determine if an error is a timeout error. + */ +export function isTimeoutError(err: unknown): boolean { + if (typeof err !== "object" || err == null) { + return false; + } + + // Fetch in browser, Node.js, Bun, Deno + const isNative = "name" in err && err.name === "TimeoutError"; + const isLegacyNative = "code" in err && err.code === 23; + + // Node.js HTTP client and Axios + const isGenericErr = + "code" in err && + typeof err.code === "string" && + err.code.toLowerCase() === "econnaborted"; + + return isNative || isLegacyNative || isGenericErr; +} + +/** + * Uses various heurisitics to determine if an error is a abort error. + */ +export function isAbortError(err: unknown): boolean { + if (typeof err !== "object" || err == null) { + return false; + } + + // Fetch in browser, Node.js, Bun, Deno + const isNative = "name" in err && err.name === "AbortError"; + const isLegacyNative = "code" in err && err.code === 20; + + // Node.js HTTP client and Axios + const isGenericErr = + "code" in err && + typeof err.code === "string" && + err.code.toLowerCase() === "econnaborted"; + + return isNative || isLegacyNative || isGenericErr; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/is-plain-object.ts b/frameworks-elysia/sdk-typescript/src/lib/is-plain-object.ts new file mode 100644 index 00000000..61070d3d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/is-plain-object.ts @@ -0,0 +1,43 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/* +MIT License + +Copyright (c) Sindre Sorhus (https://sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +// Taken from https://github.com/sindresorhus/is-plain-obj/blob/97f38e8836f86a642cce98fc6ab3058bc36df181/index.js + +export function isPlainObject(value: unknown): value is object { + if (typeof value !== "object" || value === null) { + return false; + } + + const prototype = Object.getPrototypeOf(value); + return ( + (prototype === null || + prototype === Object.prototype || + Object.getPrototypeOf(prototype) === null) && + !(Symbol.toStringTag in value) && + !(Symbol.iterator in value) + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/logger.ts b/frameworks-elysia/sdk-typescript/src/lib/logger.ts new file mode 100644 index 00000000..d181f293 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/logger.ts @@ -0,0 +1,9 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export interface Logger { + group(label?: string): void; + groupEnd(): void; + log(message: any, ...args: any[]): void; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/matchers.ts b/frameworks-elysia/sdk-typescript/src/lib/matchers.ts new file mode 100644 index 00000000..b7ef1986 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/matchers.ts @@ -0,0 +1,346 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { APIError } from "../models/errors/apierror.js"; +import { ResponseValidationError } from "../models/errors/responsevalidationerror.js"; +import { ERR, OK, Result } from "../types/fp.js"; +import { matchResponse, matchStatusCode, StatusCodePredicate } from "./http.js"; +import { isPlainObject } from "./is-plain-object.js"; + +export type Encoding = + | "jsonl" + | "json" + | "text" + | "bytes" + | "stream" + | "sse" + | "nil" + | "fail"; + +const DEFAULT_CONTENT_TYPES: Record = { + jsonl: "application/jsonl", + json: "application/json", + text: "text/plain", + bytes: "application/octet-stream", + stream: "application/octet-stream", + sse: "text/event-stream", + nil: "*", + fail: "*", +}; + +type Schema = { parse(raw: unknown): T }; + +type MatchOptions = { + ctype?: string; + hdrs?: boolean; + key?: string; + sseSentinel?: string; +}; + +export type ValueMatcher = MatchOptions & { + enc: Encoding; + codes: StatusCodePredicate; + schema: Schema; +}; + +export type ErrorMatcher = MatchOptions & { + enc: Encoding; + codes: StatusCodePredicate; + schema: Schema; + err: true; +}; + +export type FailMatcher = { + enc: "fail"; + codes: StatusCodePredicate; +}; + +export type Matcher = ValueMatcher | ErrorMatcher | FailMatcher; + +export function jsonErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "json", codes, schema }; +} +export function json( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "json", codes, schema }; +} + +export function jsonl( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "jsonl", codes, schema }; +} + +export function jsonlErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "jsonl", codes, schema }; +} +export function textErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "text", codes, schema }; +} +export function text( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "text", codes, schema }; +} + +export function bytesErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "bytes", codes, schema }; +} +export function bytes( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "bytes", codes, schema }; +} + +export function streamErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "stream", codes, schema }; +} +export function stream( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "stream", codes, schema }; +} + +export function sseErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "sse", codes, schema }; +} +export function sse( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "sse", codes, schema }; +} + +export function nilErr( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ErrorMatcher { + return { ...options, err: true, enc: "nil", codes, schema }; +} +export function nil( + codes: StatusCodePredicate, + schema: Schema, + options?: MatchOptions, +): ValueMatcher { + return { ...options, enc: "nil", codes, schema }; +} + +export function fail(codes: StatusCodePredicate): FailMatcher { + return { enc: "fail", codes }; +} + +export type MatchedValue = Matchers extends Matcher[] + ? T + : never; +export type MatchedError = Matchers extends Matcher[] + ? E + : never; +export type MatchFunc = ( + response: Response, + request: Request, + options?: { resultKey?: string; extraFields?: Record }, +) => Promise<[result: Result, raw: unknown]>; + +export function match( + ...matchers: Array> +): MatchFunc { + return async function matchFunc( + response: Response, + request: Request, + options?: { resultKey?: string; extraFields?: Record }, + ): Promise< + [result: Result, raw: unknown] + > { + let raw: unknown; + let matcher: Matcher | undefined; + for (const match of matchers) { + const { codes } = match; + const ctpattern = "ctype" in match + ? match.ctype + : DEFAULT_CONTENT_TYPES[match.enc]; + if (ctpattern && matchResponse(response, codes, ctpattern)) { + matcher = match; + break; + } else if (!ctpattern && matchStatusCode(response, codes)) { + matcher = match; + break; + } + } + + if (!matcher) { + return [{ + ok: false, + error: new APIError("Unexpected Status or Content-Type", { + response, + request, + body: await response.text().catch(() => ""), + }), + }, raw]; + } + + const encoding = matcher.enc; + let body = ""; + switch (encoding) { + case "json": + body = await response.text(); + raw = JSON.parse(body); + break; + case "jsonl": + raw = response.body; + break; + case "bytes": + raw = new Uint8Array(await response.arrayBuffer()); + break; + case "stream": + raw = response.body; + break; + case "text": + body = await response.text(); + raw = body; + break; + case "sse": + raw = response.body; + break; + case "nil": + body = await response.text(); + raw = undefined; + break; + case "fail": + body = await response.text(); + raw = body; + break; + default: + throw new Error( + `Unsupported response type: ${encoding satisfies never}`, + ); + } + + if (matcher.enc === "fail") { + return [{ + ok: false, + error: new APIError("API error occurred", { request, response, body }), + }, raw]; + } + + const resultKey = matcher.key || options?.resultKey; + let data: unknown; + + if ("err" in matcher) { + data = { + ...options?.extraFields, + ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null), + ...(isPlainObject(raw) ? raw : null), + request$: request, + response$: response, + body$: body, + }; + } else if (resultKey) { + data = { + ...options?.extraFields, + ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null), + [resultKey]: raw, + }; + } else if (matcher.hdrs) { + data = { + ...options?.extraFields, + ...(matcher.hdrs ? { Headers: unpackHeaders(response.headers) } : null), + ...(isPlainObject(raw) ? raw : null), + }; + } else { + data = raw; + } + + if ("err" in matcher) { + const result = safeParseResponse( + data, + (v: unknown) => matcher.schema.parse(v), + "Response validation failed", + { request, response, body }, + ); + return [result.ok ? { ok: false, error: result.value } : result, raw]; + } else { + return [ + safeParseResponse( + data, + (v: unknown) => matcher.schema.parse(v), + "Response validation failed", + { request, response, body }, + ), + raw, + ]; + } + }; +} + +const headerValRE = /, */; +/** + * Iterates over a Headers object and returns an object with all the header + * entries. Values are represented as an array to account for repeated headers. + */ +export function unpackHeaders(headers: Headers): Record { + const out: Record = {}; + + for (const [k, v] of headers.entries()) { + out[k] = v.split(headerValRE); + } + + return out; +} + +function safeParseResponse( + rawValue: Inp, + fn: (value: Inp) => Out, + errorMessage: string, + httpMeta: { response: Response; request: Request; body: string }, +): Result { + try { + return OK(fn(rawValue)); + } catch (err) { + return ERR( + new ResponseValidationError(errorMessage, { + cause: err, + rawValue, + rawMessage: errorMessage, + ...httpMeta, + }), + ); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/primitives.ts b/frameworks-elysia/sdk-typescript/src/lib/primitives.ts new file mode 100644 index 00000000..d21f1dc4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/primitives.ts @@ -0,0 +1,150 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +class InvariantError extends Error { + constructor(message: string) { + super(message); + this.name = "InvariantError"; + } +} + +export function invariant( + condition: unknown, + message: string, +): asserts condition { + if (!condition) { + throw new InvariantError(message); + } +} + +export type ExactPartial = { + [P in keyof T]?: T[P] | undefined; +}; + +export type Remap = { + [k in keyof Inp as Mapping[k] extends string /* if we have a string mapping for this key then use it */ + ? Mapping[k] + : Mapping[k] extends null /* if the mapping is to `null` then drop the key */ + ? never + : k /* otherwise keep the key as-is */]: Inp[k]; +}; + +/** + * Converts or omits an object's keys according to a mapping. + * + * @param inp An object whose keys will be remapped + * @param mappings A mapping of original keys to new keys. If a key is not present in the mapping, it will be left as is. If a key is mapped to `null`, it will be removed in the resulting object. + * @returns A new object with keys remapped or omitted according to the mappings + */ +export function remap< + Inp extends Record, + const Mapping extends { [k in keyof Inp]?: string | null }, +>(inp: Inp, mappings: Mapping): Remap { + let out: any = {}; + + if (!Object.keys(mappings).length) { + out = inp; + return out; + } + + for (const [k, v] of Object.entries(inp)) { + const j = mappings[k]; + if (j === null) { + continue; + } + out[j ?? k] = v; + } + + return out; +} + +export function combineSignals( + ...signals: Array +): AbortSignal | null { + const filtered: AbortSignal[] = []; + for (const signal of signals) { + if (signal) { + filtered.push(signal); + } + } + + switch (filtered.length) { + case 0: + case 1: + return filtered[0] || null; + default: + if ("any" in AbortSignal && typeof AbortSignal.any === "function") { + return AbortSignal.any(filtered); + } + return abortSignalAny(filtered); + } +} + +export function abortSignalAny(signals: AbortSignal[]): AbortSignal { + const controller = new AbortController(); + const result = controller.signal; + if (!signals.length) { + return controller.signal; + } + + if (signals.length === 1) { + return signals[0] || controller.signal; + } + + for (const signal of signals) { + if (signal.aborted) { + return signal; + } + } + + function abort(this: AbortSignal) { + controller.abort(this.reason); + clean(); + } + + const signalRefs: WeakRef[] = []; + function clean() { + for (const signalRef of signalRefs) { + const signal = signalRef.deref(); + if (signal) { + signal.removeEventListener("abort", abort); + } + } + } + + for (const signal of signals) { + signalRefs.push(new WeakRef(signal)); + signal.addEventListener("abort", abort); + } + + return result; +} + +export function compactMap( + values: Record, +): Record { + const out: Record = {}; + + for (const [k, v] of Object.entries(values)) { + if (typeof v !== "undefined") { + out[k] = v; + } + } + + return out; +} + +export function allRequired>( + v: V, +): + | { + [K in keyof V]: NonNullable; + } + | undefined { + if (Object.values(v).every((x) => x == null)) { + return void 0; + } + + return v as ReturnType>; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/retries.ts b/frameworks-elysia/sdk-typescript/src/lib/retries.ts new file mode 100644 index 00000000..e3ce9aba --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/retries.ts @@ -0,0 +1,218 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { isConnectionError, isTimeoutError } from "./http.js"; + +export type BackoffStrategy = { + initialInterval: number; + maxInterval: number; + exponent: number; + maxElapsedTime: number; +}; + +const defaultBackoff: BackoffStrategy = { + initialInterval: 500, + maxInterval: 60000, + exponent: 1.5, + maxElapsedTime: 3600000, +}; + +export type RetryConfig = + | { strategy: "none" } + | { + strategy: "backoff"; + backoff?: BackoffStrategy; + retryConnectionErrors?: boolean; + }; + +/** + * PermanentError is an error that is not recoverable. Throwing this error will + * cause a retry loop to terminate. + */ +export class PermanentError extends Error { + /** The underlying cause of the error. */ + override readonly cause: unknown; + + constructor(message: string, options?: { cause?: unknown }) { + let msg = message; + if (options?.cause) { + msg += `: ${options.cause}`; + } + + super(msg, options); + this.name = "PermanentError"; + // In older runtimes, the cause field would not have been assigned through + // the super() call. + if (typeof this.cause === "undefined") { + this.cause = options?.cause; + } + + Object.setPrototypeOf(this, PermanentError.prototype); + } +} + +/** + * TemporaryError is an error is used to signal that an HTTP request can be + * retried as part of a retry loop. If retry attempts are exhausted and this + * error is thrown, the response will be returned to the caller. + */ +export class TemporaryError extends Error { + response: Response; + + constructor(message: string, response: Response) { + super(message); + this.response = response; + this.name = "TemporaryError"; + + Object.setPrototypeOf(this, TemporaryError.prototype); + } +} + +export async function retry( + fetchFn: () => Promise, + options: { + config: RetryConfig; + statusCodes: string[]; + }, +): Promise { + switch (options.config.strategy) { + case "backoff": + return retryBackoff( + wrapFetcher(fetchFn, { + statusCodes: options.statusCodes, + retryConnectionErrors: !!options.config.retryConnectionErrors, + }), + options.config.backoff ?? defaultBackoff, + ); + default: + return await fetchFn(); + } +} + +function wrapFetcher( + fn: () => Promise, + options: { + statusCodes: string[]; + retryConnectionErrors: boolean; + }, +): () => Promise { + return async () => { + try { + const res = await fn(); + if (isRetryableResponse(res, options.statusCodes)) { + throw new TemporaryError( + "Response failed with retryable status code", + res, + ); + } + + return res; + } catch (err: unknown) { + if (err instanceof TemporaryError) { + throw err; + } + + if ( + options.retryConnectionErrors && + (isTimeoutError(err) || isConnectionError(err)) + ) { + throw err; + } + + throw new PermanentError("Permanent error", { cause: err }); + } + }; +} + +const codeRangeRE = new RegExp("^[0-9]xx$", "i"); + +function isRetryableResponse(res: Response, statusCodes: string[]): boolean { + const actual = `${res.status}`; + + return statusCodes.some((code) => { + if (!codeRangeRE.test(code)) { + return code === actual; + } + + const expectFamily = code.charAt(0); + if (!expectFamily) { + throw new Error("Invalid status code range"); + } + + const actualFamily = actual.charAt(0); + if (!actualFamily) { + throw new Error(`Invalid response status code: ${actual}`); + } + + return actualFamily === expectFamily; + }); +} + +async function retryBackoff( + fn: () => Promise, + strategy: BackoffStrategy, +): Promise { + const { maxElapsedTime, initialInterval, exponent, maxInterval } = strategy; + + const start = Date.now(); + let x = 0; + + while (true) { + try { + const res = await fn(); + return res; + } catch (err: unknown) { + if (err instanceof PermanentError) { + throw err.cause; + } + const elapsed = Date.now() - start; + if (elapsed > maxElapsedTime) { + if (err instanceof TemporaryError) { + return err.response; + } + + throw err; + } + + let retryInterval = 0; + if (err instanceof TemporaryError) { + retryInterval = retryIntervalFromResponse(err.response); + } + + if (retryInterval <= 0) { + retryInterval = + initialInterval * Math.pow(x, exponent) + Math.random() * 1000; + } + + const d = Math.min(retryInterval, maxInterval); + + await delay(d); + x++; + } + } +} + +function retryIntervalFromResponse(res: Response): number { + const retryVal = res.headers.get("retry-after") || ""; + if (!retryVal) { + return 0; + } + + const parsedNumber = Number(retryVal); + if (Number.isInteger(parsedNumber)) { + return parsedNumber * 1000; + } + + const parsedDate = Date.parse(retryVal); + if (Number.isInteger(parsedDate)) { + const deltaMS = parsedDate - Date.now(); + return deltaMS > 0 ? Math.ceil(deltaMS) : 0; + } + + return 0; +} + +async function delay(delay: number): Promise { + return new Promise((resolve) => setTimeout(resolve, delay)); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/schemas.ts b/frameworks-elysia/sdk-typescript/src/lib/schemas.ts new file mode 100644 index 00000000..47edb972 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/schemas.ts @@ -0,0 +1,91 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { + output, + ZodEffects, + ZodError, + ZodObject, + ZodRawShape, + ZodTypeAny, +} from "zod/v3"; +import { SDKValidationError } from "../models/errors/sdkvalidationerror.js"; +import { ERR, OK, Result } from "../types/fp.js"; + +/** + * Utility function that executes some code which may throw a ZodError. It + * intercepts this error and converts it to an SDKValidationError so as to not + * leak Zod implementation details to user code. + */ +export function parse( + rawValue: Inp, + fn: (value: Inp) => Out, + errorMessage: string, +): Out { + try { + return fn(rawValue); + } catch (err) { + if (err instanceof ZodError) { + throw new SDKValidationError(errorMessage, err, rawValue); + } + throw err; + } +} + +/** + * Utility function that executes some code which may result in a ZodError. It + * intercepts this error and converts it to an SDKValidationError so as to not + * leak Zod implementation details to user code. + */ +export function safeParse( + rawValue: Inp, + fn: (value: Inp) => Out, + errorMessage: string, +): Result { + try { + return OK(fn(rawValue)); + } catch (err) { + return ERR(new SDKValidationError(errorMessage, err, rawValue)); + } +} + +export function collectExtraKeys< + Shape extends ZodRawShape, + Catchall extends ZodTypeAny, + K extends string, +>( + obj: ZodObject, + extrasKey: K, + optional: boolean, +): ZodEffects< + typeof obj, + & output> + & { + [k in K]: Record>; + } +> { + return obj.transform((val) => { + const extras: Record> = {}; + const { shape } = obj; + for (const [key] of Object.entries(val)) { + if (key in shape) { + continue; + } + + const v = val[key]; + if (typeof v === "undefined") { + continue; + } + + extras[key] = v; + delete val[key]; + } + + if (optional && Object.keys(extras).length === 0) { + return val; + } + + return { ...val, [extrasKey]: extras }; + }); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/sdks.ts b/frameworks-elysia/sdk-typescript/src/lib/sdks.ts new file mode 100644 index 00000000..212ccb74 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/sdks.ts @@ -0,0 +1,406 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKHooks } from "../hooks/hooks.js"; +import { HookContext } from "../hooks/types.js"; +import { + ConnectionError, + InvalidRequestError, + RequestAbortedError, + RequestTimeoutError, + UnexpectedClientError, +} from "../models/errors/httpclienterrors.js"; +import { ERR, OK, Result } from "../types/fp.js"; +import { stringToBase64 } from "./base64.js"; +import { SDK_METADATA, SDKOptions, serverURLFromOptions } from "./config.js"; +import { encodeForm } from "./encodings.js"; +import { env } from "./env.js"; +import { + HTTPClient, + isAbortError, + isConnectionError, + isTimeoutError, + matchContentType, +} from "./http.js"; +import { Logger } from "./logger.js"; +import { retry, RetryConfig } from "./retries.js"; +import { SecurityState } from "./security.js"; + +export type RequestOptions = { + /** + * Sets a timeout, in milliseconds, on HTTP requests made by an SDK method. If + * `fetchOptions.signal` is set then it will take precedence over this option. + */ + timeoutMs?: number; + /** + * Set or override a retry policy on HTTP calls. + */ + retries?: RetryConfig; + /** + * Specifies the status codes which should be retried using the given retry policy. + */ + retryCodes?: string[]; + /** + * Overrides the base server URL that will be used by an operation. + */ + serverURL?: string | URL; + /** + * @deprecated `fetchOptions` has been flattened into `RequestOptions`. + * + * Sets various request options on the `fetch` call made by an SDK method. + * + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request#options|Request} + */ + fetchOptions?: Omit; +} & Omit; + +type RequestConfig = { + method: string; + path: string; + baseURL?: string | URL | undefined; + query?: string; + body?: RequestInit["body"]; + headers?: HeadersInit; + security?: SecurityState | null; + uaHeader?: string; + userAgent?: string | undefined; + timeoutMs?: number; +}; + +const gt: unknown = typeof globalThis === "undefined" ? null : globalThis; +const webWorkerLike = typeof gt === "object" + && gt != null + && "importScripts" in gt + && typeof gt["importScripts"] === "function"; +const isBrowserLike = webWorkerLike + || (typeof navigator !== "undefined" && "serviceWorker" in navigator) + || (typeof window === "object" && typeof window.document !== "undefined"); + +export class ClientSDK { + readonly #httpClient: HTTPClient; + readonly #hooks: SDKHooks; + readonly #logger?: Logger | undefined; + public readonly _baseURL: URL | null; + public readonly _options: SDKOptions & { hooks?: SDKHooks }; + + constructor(options: SDKOptions = {}) { + const opt = options as unknown; + if ( + typeof opt === "object" + && opt != null + && "hooks" in opt + && opt.hooks instanceof SDKHooks + ) { + this.#hooks = opt.hooks; + } else { + this.#hooks = new SDKHooks(); + } + const url = serverURLFromOptions(options); + if (url) { + url.pathname = url.pathname.replace(/\/+$/, "") + "/"; + } + + const { baseURL, client } = this.#hooks.sdkInit({ + baseURL: url, + client: options.httpClient || new HTTPClient(), + }); + this._baseURL = baseURL; + this.#httpClient = client; + + this._options = { ...options, hooks: this.#hooks }; + + this.#logger = this._options.debugLogger; + if (!this.#logger && env().SDK_DEBUG) { + this.#logger = console; + } + } + + public _createRequest( + context: HookContext, + conf: RequestConfig, + options?: RequestOptions, + ): Result { + const { method, path, query, headers: opHeaders, security } = conf; + + const base = conf.baseURL ?? this._baseURL; + if (!base) { + return ERR(new InvalidRequestError("No base URL provided for operation")); + } + const baseURL = new URL(base); + let reqURL: URL; + if (path) { + baseURL.pathname = baseURL.pathname.replace(/\/+$/, "") + "/"; + reqURL = new URL(path, baseURL); + } else { + reqURL = baseURL; + } + reqURL.hash = ""; + + let finalQuery = query || ""; + + const secQuery: string[] = []; + for (const [k, v] of Object.entries(security?.queryParams || {})) { + const q = encodeForm(k, v, { charEncoding: "percent" }); + if (typeof q !== "undefined") { + secQuery.push(q); + } + } + if (secQuery.length) { + finalQuery += `&${secQuery.join("&")}`; + } + + if (finalQuery) { + const q = finalQuery.startsWith("&") ? finalQuery.slice(1) : finalQuery; + reqURL.search = `?${q}`; + } + + const headers = new Headers(opHeaders); + + const username = security?.basic.username; + const password = security?.basic.password; + if (username != null || password != null) { + const encoded = stringToBase64( + [username || "", password || ""].join(":"), + ); + headers.set("Authorization", `Basic ${encoded}`); + } + + const securityHeaders = new Headers(security?.headers || {}); + for (const [k, v] of securityHeaders) { + headers.set(k, v); + } + + let cookie = headers.get("cookie") || ""; + for (const [k, v] of Object.entries(security?.cookies || {})) { + cookie += `; ${k}=${v}`; + } + cookie = cookie.startsWith("; ") ? cookie.slice(2) : cookie; + headers.set("cookie", cookie); + + const userHeaders = new Headers( + options?.headers ?? options?.fetchOptions?.headers, + ); + for (const [k, v] of userHeaders) { + headers.set(k, v); + } + + // Only set user agent header in non-browser-like environments since CORS + // policy disallows setting it in browsers e.g. Chrome throws an error. + if (!isBrowserLike) { + headers.set( + conf.uaHeader ?? "user-agent", + conf.userAgent ?? SDK_METADATA.userAgent, + ); + } + + const fetchOptions: Omit = { + ...options?.fetchOptions, + ...options, + }; + if (!fetchOptions?.signal && conf.timeoutMs && conf.timeoutMs > 0) { + const timeoutSignal = AbortSignal.timeout(conf.timeoutMs); + fetchOptions.signal = timeoutSignal; + } + + if (conf.body instanceof ReadableStream) { + Object.assign(fetchOptions, { duplex: "half" }); + } + + let input; + try { + input = this.#hooks.beforeCreateRequest(context, { + url: reqURL, + options: { + ...fetchOptions, + body: conf.body ?? null, + headers, + method, + }, + }); + } catch (err: unknown) { + return ERR( + new UnexpectedClientError("Create request hook failed to execute", { + cause: err, + }), + ); + } + + return OK(new Request(input.url, input.options)); + } + + public async _do( + request: Request, + options: { + context: HookContext; + isErrorStatusCode: (statusCode: number) => boolean; + retryConfig: RetryConfig; + retryCodes: string[]; + }, + ): Promise< + Result< + Response, + | RequestAbortedError + | RequestTimeoutError + | ConnectionError + | UnexpectedClientError + > + > { + const { context, isErrorStatusCode } = options; + + return retry( + async () => { + const req = await this.#hooks.beforeRequest(context, request.clone()); + await logRequest(this.#logger, req).catch((e) => + this.#logger?.log("Failed to log request:", e) + ); + + let response = await this.#httpClient.request(req); + + try { + if (isErrorStatusCode(response.status)) { + const result = await this.#hooks.afterError( + context, + response, + null, + ); + if (result.error) { + throw result.error; + } + response = result.response || response; + } else { + response = await this.#hooks.afterSuccess(context, response); + } + } finally { + await logResponse(this.#logger, response, req) + .catch(e => this.#logger?.log("Failed to log response:", e)); + } + + return response; + }, + { config: options.retryConfig, statusCodes: options.retryCodes }, + ).then( + (r) => OK(r), + (err) => { + switch (true) { + case isAbortError(err): + return ERR( + new RequestAbortedError("Request aborted by client", { + cause: err, + }), + ); + case isTimeoutError(err): + return ERR( + new RequestTimeoutError("Request timed out", { cause: err }), + ); + case isConnectionError(err): + return ERR( + new ConnectionError("Unable to make request", { cause: err }), + ); + default: + return ERR( + new UnexpectedClientError("Unexpected HTTP client error", { + cause: err, + }), + ); + } + }, + ); + } +} + +const jsonLikeContentTypeRE = /^(application|text)\/([^+]+\+)*json.*/; +const jsonlLikeContentTypeRE = + /^(application|text)\/([^+]+\+)*(jsonl|x-ndjson)\b.*/; +async function logRequest(logger: Logger | undefined, req: Request) { + if (!logger) { + return; + } + + const contentType = req.headers.get("content-type"); + const ct = contentType?.split(";")[0] || ""; + + logger.group(`> Request: ${req.method} ${req.url}`); + + logger.group("Headers:"); + for (const [k, v] of req.headers.entries()) { + logger.log(`${k}: ${v}`); + } + logger.groupEnd(); + + logger.group("Body:"); + switch (true) { + case jsonLikeContentTypeRE.test(ct): + logger.log(await req.clone().json()); + break; + case ct.startsWith("text/"): + logger.log(await req.clone().text()); + break; + case ct === "multipart/form-data": { + const body = await req.clone().formData(); + for (const [k, v] of body) { + const vlabel = v instanceof Blob ? "" : v; + logger.log(`${k}: ${vlabel}`); + } + break; + } + default: + logger.log(`<${contentType}>`); + break; + } + logger.groupEnd(); + + logger.groupEnd(); +} + +async function logResponse( + logger: Logger | undefined, + res: Response, + req: Request, +) { + if (!logger) { + return; + } + + const contentType = res.headers.get("content-type"); + const ct = contentType?.split(";")[0] || ""; + + logger.group(`< Response: ${req.method} ${req.url}`); + logger.log("Status Code:", res.status, res.statusText); + + logger.group("Headers:"); + for (const [k, v] of res.headers.entries()) { + logger.log(`${k}: ${v}`); + } + logger.groupEnd(); + + logger.group("Body:"); + switch (true) { + case matchContentType(res, "application/json") + || jsonLikeContentTypeRE.test(ct) && !jsonlLikeContentTypeRE.test(ct): + logger.log(await res.clone().json()); + break; + case matchContentType(res, "application/jsonl") + || jsonlLikeContentTypeRE.test(ct): + case matchContentType(res, "text/event-stream"): + logger.log(`<${contentType}>`); + break; + case matchContentType(res, "text/*"): + logger.log(await res.clone().text()); + break; + case matchContentType(res, "multipart/form-data"): { + const body = await res.clone().formData(); + for (const [k, v] of body) { + const vlabel = v instanceof Blob ? "" : v; + logger.log(`${k}: ${vlabel}`); + } + break; + } + default: + logger.log(`<${contentType}>`); + break; + } + logger.groupEnd(); + + logger.groupEnd(); +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/security.ts b/frameworks-elysia/sdk-typescript/src/lib/security.ts new file mode 100644 index 00000000..36d6d87d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/security.ts @@ -0,0 +1,275 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as components from "../models/components/index.js"; +import { env } from "./env.js"; + +type OAuth2PasswordFlow = { + username: string; + password: string; + clientID?: string | undefined; + clientSecret?: string | undefined; + tokenURL: string; +}; + +export enum SecurityErrorCode { + Incomplete = "incomplete", + UnrecognisedSecurityType = "unrecognized_security_type", +} + +export class SecurityError extends Error { + constructor( + public code: SecurityErrorCode, + message: string, + ) { + super(message); + this.name = "SecurityError"; + } + + static incomplete(): SecurityError { + return new SecurityError( + SecurityErrorCode.Incomplete, + "Security requirements not met in order to perform the operation", + ); + } + static unrecognizedType(type: string): SecurityError { + return new SecurityError( + SecurityErrorCode.UnrecognisedSecurityType, + `Unrecognised security type: ${type}`, + ); + } +} + +export type SecurityState = { + basic: { username?: string | undefined; password?: string | undefined }; + headers: Record; + queryParams: Record; + cookies: Record; + oauth2: ({ type: "password" } & OAuth2PasswordFlow) | { type: "none" }; +}; + +type SecurityInputBasic = { + type: "http:basic"; + value: + | { username?: string | undefined; password?: string | undefined } + | null + | undefined; +}; + +type SecurityInputBearer = { + type: "http:bearer"; + value: string | null | undefined; + fieldName: string; +}; + +type SecurityInputAPIKey = { + type: "apiKey:header" | "apiKey:query" | "apiKey:cookie"; + value: string | null | undefined; + fieldName: string; +}; + +type SecurityInputOIDC = { + type: "openIdConnect"; + value: string | null | undefined; + fieldName: string; +}; + +type SecurityInputOAuth2 = { + type: "oauth2"; + value: string | null | undefined; + fieldName: string; +}; + +type SecurityInputOAuth2ClientCredentials = { + type: "oauth2:client_credentials"; + value: + | { + clientID?: string | undefined; + clientSecret?: string | undefined; + } + | null + | string + | undefined; + fieldName?: string; +}; + +type SecurityInputOAuth2PasswordCredentials = { + type: "oauth2:password"; + value: + | string + | null + | undefined; + fieldName?: string; +}; + +type SecurityInputCustom = { + type: "http:custom"; + value: any | null | undefined; + fieldName?: string; +}; + +export type SecurityInput = + | SecurityInputBasic + | SecurityInputBearer + | SecurityInputAPIKey + | SecurityInputOAuth2 + | SecurityInputOAuth2ClientCredentials + | SecurityInputOAuth2PasswordCredentials + | SecurityInputOIDC + | SecurityInputCustom; + +export function resolveSecurity( + ...options: SecurityInput[][] +): SecurityState | null { + const state: SecurityState = { + basic: {}, + headers: {}, + queryParams: {}, + cookies: {}, + oauth2: { type: "none" }, + }; + + const option = options.find((opts) => { + return opts.every((o) => { + if (o.value == null) { + return false; + } else if (o.type === "http:basic") { + return o.value.username != null || o.value.password != null; + } else if (o.type === "http:custom") { + return null; + } else if (o.type === "oauth2:password") { + return ( + typeof o.value === "string" && !!o.value + ); + } else if (o.type === "oauth2:client_credentials") { + if (typeof o.value == "string") { + return !!o.value; + } + return o.value.clientID != null || o.value.clientSecret != null; + } else if (typeof o.value === "string") { + return !!o.value; + } else { + throw new Error( + `Unrecognized security type: ${o.type} (value type: ${typeof o + .value})`, + ); + } + }); + }); + if (option == null) { + return null; + } + + option.forEach((spec) => { + if (spec.value == null) { + return; + } + + const { type } = spec; + + switch (type) { + case "apiKey:header": + state.headers[spec.fieldName] = spec.value; + break; + case "apiKey:query": + state.queryParams[spec.fieldName] = spec.value; + break; + case "apiKey:cookie": + state.cookies[spec.fieldName] = spec.value; + break; + case "http:basic": + applyBasic(state, spec); + break; + case "http:custom": + break; + case "http:bearer": + applyBearer(state, spec); + break; + case "oauth2": + applyBearer(state, spec); + break; + case "oauth2:password": + applyBearer(state, spec); + break; + case "oauth2:client_credentials": + break; + case "openIdConnect": + applyBearer(state, spec); + break; + default: + throw SecurityError.unrecognizedType((spec satisfies never, type)); + } + }); + + return state; +} + +function applyBasic( + state: SecurityState, + spec: SecurityInputBasic, +) { + if (spec.value == null) { + return; + } + + state.basic = spec.value; +} + +function applyBearer( + state: SecurityState, + spec: + | SecurityInputBearer + | SecurityInputOAuth2 + | SecurityInputOIDC + | SecurityInputOAuth2PasswordCredentials, +) { + if (typeof spec.value !== "string" || !spec.value) { + return; + } + + let value = spec.value; + if (value.slice(0, 7).toLowerCase() !== "bearer ") { + value = `Bearer ${value}`; + } + + if (spec.fieldName !== undefined) { + state.headers[spec.fieldName] = value; + } +} + +export function resolveGlobalSecurity( + security: Partial | null | undefined, + allowedFields?: number[], +): SecurityState | null { + let inputs: SecurityInput[][] = [ + [ + { + fieldName: "Authorization", + type: "oauth2", + value: security?.oAuth2 ?? env().SDK_O_AUTH2, + }, + ], + ]; + + if (allowedFields) { + inputs = allowedFields.map((i) => { + if (i < 0 || i >= inputs.length) { + throw new RangeError(`invalid allowedFields index ${i}`); + } + return inputs[i]!; + }); + } + + return resolveSecurity(...inputs); +} + +export async function extractSecurity< + T extends string | Record, +>(sec: T | (() => Promise) | undefined): Promise { + if (sec == null) { + return; + } + + return typeof sec === "function" ? sec() : sec; +} diff --git a/frameworks-elysia/sdk-typescript/src/lib/url.ts b/frameworks-elysia/sdk-typescript/src/lib/url.ts new file mode 100644 index 00000000..79e7ce66 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/lib/url.ts @@ -0,0 +1,35 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +const hasOwn = Object.prototype.hasOwnProperty; + +export type Params = Partial>; + +export function pathToFunc( + pathPattern: string, + options?: { charEncoding?: "percent" | "none" }, +): (params?: Params) => string { + const paramRE = /\{([a-zA-Z0-9_][a-zA-Z0-9_-]*?)\}/g; + + return function buildURLPath(params: Record = {}): string { + return pathPattern + .replace(paramRE, function (_, placeholder) { + if (!hasOwn.call(params, placeholder)) { + throw new Error(`Parameter '${placeholder}' is required`); + } + + const value = params[placeholder]; + if (typeof value !== "string" && typeof value !== "number") { + throw new Error( + `Parameter '${placeholder}' must be a string or number`, + ); + } + + return options?.charEncoding === "percent" + ? encodeURIComponent(`${value}`) + : `${value}`; + }) + .replace(/^\/+/, ""); + }; +} diff --git a/frameworks-elysia/sdk-typescript/src/models/components/index.ts b/frameworks-elysia/sdk-typescript/src/models/components/index.ts new file mode 100644 index 00000000..2edb51c4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/components/index.ts @@ -0,0 +1,5 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./security.js"; diff --git a/frameworks-elysia/sdk-typescript/src/models/components/security.ts b/frameworks-elysia/sdk-typescript/src/models/components/security.ts new file mode 100644 index 00000000..c0becc2f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/components/security.ts @@ -0,0 +1,32 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; + +export type Security = { + oAuth2?: string | undefined; +}; + +/** @internal */ +export type Security$Outbound = { + OAuth2?: string | undefined; +}; + +/** @internal */ +export const Security$outboundSchema: z.ZodType< + Security$Outbound, + z.ZodTypeDef, + Security +> = z.object({ + oAuth2: z.string().optional(), +}).transform((v) => { + return remap$(v, { + oAuth2: "OAuth2", + }); +}); + +export function securityToJSON(security: Security): string { + return JSON.stringify(Security$outboundSchema.parse(security)); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/apierror.ts b/frameworks-elysia/sdk-typescript/src/models/errors/apierror.ts new file mode 100644 index 00000000..d514b64b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/apierror.ts @@ -0,0 +1,40 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { SDKError } from "./sdkerror.js"; + +/** The fallback error class if no more specific error class is matched */ +export class APIError extends SDKError { + constructor( + message: string, + httpMeta: { + response: Response; + request: Request; + body: string; + }, + ) { + if (message) { + message += `: `; + } + message += `Status ${httpMeta.response.status}`; + const contentType = httpMeta.response.headers.get("content-type") || `""`; + if (contentType !== "application/json") { + message += ` Content-Type ${ + contentType.includes(" ") ? `"${contentType}"` : contentType + }`; + } + const body = httpMeta.body || `""`; + message += body.length > 100 ? "\n" : ". "; + let bodyDisplay = body; + if (body.length > 10000) { + const truncated = body.substring(0, 10000); + const remaining = body.length - 10000; + bodyDisplay = `${truncated}...and ${remaining} more chars`; + } + message += `Body: ${bodyDisplay}`; + message = message.trim(); + super(message, httpMeta); + this.name = "APIError"; + } +} diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/createbooking.ts b/frameworks-elysia/sdk-typescript/src/models/errors/createbooking.ts new file mode 100644 index 00000000..6db97db6 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/createbooking.ts @@ -0,0 +1,130 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Conflict + */ +export type CreateBookingBookingsResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Conflict + */ +export class CreateBookingBookingsResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: CreateBookingBookingsResponseBodyData; + + constructor( + err: CreateBookingBookingsResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "CreateBookingBookingsResponseBody"; + } +} + +/** + * Not Found + */ +export type CreateBookingResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Not Found + */ +export class CreateBookingResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: CreateBookingResponseBodyData; + + constructor( + err: CreateBookingResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "CreateBookingResponseBody"; + } +} + +/** @internal */ +export const CreateBookingBookingsResponseBody$inboundSchema: z.ZodType< + CreateBookingBookingsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new CreateBookingBookingsResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); + +/** @internal */ +export const CreateBookingResponseBody$inboundSchema: z.ZodType< + CreateBookingResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new CreateBookingResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/createbookingpayment.ts b/frameworks-elysia/sdk-typescript/src/models/errors/createbookingpayment.ts new file mode 100644 index 00000000..40810b7e --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/createbookingpayment.ts @@ -0,0 +1,68 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Not Found + */ +export type CreateBookingPaymentResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Not Found + */ +export class CreateBookingPaymentResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: CreateBookingPaymentResponseBodyData; + + constructor( + err: CreateBookingPaymentResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "CreateBookingPaymentResponseBody"; + } +} + +/** @internal */ +export const CreateBookingPaymentResponseBody$inboundSchema: z.ZodType< + CreateBookingPaymentResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new CreateBookingPaymentResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/deletebooking.ts b/frameworks-elysia/sdk-typescript/src/models/errors/deletebooking.ts new file mode 100644 index 00000000..5cac079a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/deletebooking.ts @@ -0,0 +1,68 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Not Found + */ +export type DeleteBookingResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Not Found + */ +export class DeleteBookingResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: DeleteBookingResponseBodyData; + + constructor( + err: DeleteBookingResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "DeleteBookingResponseBody"; + } +} + +/** @internal */ +export const DeleteBookingResponseBody$inboundSchema: z.ZodType< + DeleteBookingResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new DeleteBookingResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/getbooking.ts b/frameworks-elysia/sdk-typescript/src/models/errors/getbooking.ts new file mode 100644 index 00000000..96611bb7 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/getbooking.ts @@ -0,0 +1,68 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Not Found + */ +export type GetBookingResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Not Found + */ +export class GetBookingResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: GetBookingResponseBodyData; + + constructor( + err: GetBookingResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "GetBookingResponseBody"; + } +} + +/** @internal */ +export const GetBookingResponseBody$inboundSchema: z.ZodType< + GetBookingResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new GetBookingResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/getbookings.ts b/frameworks-elysia/sdk-typescript/src/models/errors/getbookings.ts new file mode 100644 index 00000000..714010fd --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/getbookings.ts @@ -0,0 +1,130 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Internal Server Error + */ +export type GetBookingsBookingsResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Internal Server Error + */ +export class GetBookingsBookingsResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: GetBookingsBookingsResponseBodyData; + + constructor( + err: GetBookingsBookingsResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "GetBookingsBookingsResponseBody"; + } +} + +/** + * Unauthorized + */ +export type GetBookingsResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Unauthorized + */ +export class GetBookingsResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: GetBookingsResponseBodyData; + + constructor( + err: GetBookingsResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "GetBookingsResponseBody"; + } +} + +/** @internal */ +export const GetBookingsBookingsResponseBody$inboundSchema: z.ZodType< + GetBookingsBookingsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new GetBookingsBookingsResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); + +/** @internal */ +export const GetBookingsResponseBody$inboundSchema: z.ZodType< + GetBookingsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new GetBookingsResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/getstations.ts b/frameworks-elysia/sdk-typescript/src/models/errors/getstations.ts new file mode 100644 index 00000000..3fff16e2 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/getstations.ts @@ -0,0 +1,68 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Bad Request + */ +export type GetStationsResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Bad Request + */ +export class GetStationsResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: GetStationsResponseBodyData; + + constructor( + err: GetStationsResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "GetStationsResponseBody"; + } +} + +/** @internal */ +export const GetStationsResponseBody$inboundSchema: z.ZodType< + GetStationsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new GetStationsResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/gettrips.ts b/frameworks-elysia/sdk-typescript/src/models/errors/gettrips.ts new file mode 100644 index 00000000..aaa233a4 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/gettrips.ts @@ -0,0 +1,68 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; + +/** + * Bad Request + */ +export type GetTripsResponseBodyData = { + type: string; + title: string; + status: number; + detail: string; +}; + +/** + * Bad Request + */ +export class GetTripsResponseBody extends SDKError { + type: string; + title: string; + status: number; + detail: string; + + /** The original data that was passed to this error instance. */ + data$: GetTripsResponseBodyData; + + constructor( + err: GetTripsResponseBodyData, + httpMeta: { response: Response; request: Request; body: string }, + ) { + const message = "message" in err && typeof err.message === "string" + ? err.message + : `API error occurred: ${JSON.stringify(err)}`; + super(message, httpMeta); + this.data$ = err; + this.type = err.type; + this.title = err.title; + this.status = err.status; + this.detail = err.detail; + + this.name = "GetTripsResponseBody"; + } +} + +/** @internal */ +export const GetTripsResponseBody$inboundSchema: z.ZodType< + GetTripsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + type: z.string(), + title: z.string(), + status: z.number(), + detail: z.string(), + request$: z.instanceof(Request), + response$: z.instanceof(Response), + body$: z.string(), +}) + .transform((v) => { + return new GetTripsResponseBody(v, { + request: v.request$, + response: v.response$, + body: v.body$, + }); + }); diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/httpclienterrors.ts b/frameworks-elysia/sdk-typescript/src/models/errors/httpclienterrors.ts new file mode 100644 index 00000000..b34f6121 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/httpclienterrors.ts @@ -0,0 +1,62 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** + * Base class for all HTTP errors. + */ +export class HTTPClientError extends Error { + /** The underlying cause of the error. */ + override readonly cause: unknown; + override name = "HTTPClientError"; + constructor(message: string, opts?: { cause?: unknown }) { + let msg = message; + if (opts?.cause) { + msg += `: ${opts.cause}`; + } + + super(msg, opts); + // In older runtimes, the cause field would not have been assigned through + // the super() call. + if (typeof this.cause === "undefined") { + this.cause = opts?.cause; + } + } +} + +/** + * An error to capture unrecognised or unexpected errors when making HTTP calls. + */ +export class UnexpectedClientError extends HTTPClientError { + override name = "UnexpectedClientError"; +} + +/** + * An error that is raised when any inputs used to create a request are invalid. + */ +export class InvalidRequestError extends HTTPClientError { + override name = "InvalidRequestError"; +} + +/** + * An error that is raised when a HTTP request was aborted by the client error. + */ +export class RequestAbortedError extends HTTPClientError { + override readonly name = "RequestAbortedError"; +} + +/** + * An error that is raised when a HTTP request timed out due to an AbortSignal + * signal timeout. + */ +export class RequestTimeoutError extends HTTPClientError { + override readonly name = "RequestTimeoutError"; +} + +/** + * An error that is raised when a HTTP client is unable to make a request to + * a server. + */ +export class ConnectionError extends HTTPClientError { + override readonly name = "ConnectionError"; +} diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/index.ts b/frameworks-elysia/sdk-typescript/src/models/errors/index.ts new file mode 100644 index 00000000..5147c3c2 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/index.ts @@ -0,0 +1,16 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./apierror.js"; +export * from "./createbooking.js"; +export * from "./createbookingpayment.js"; +export * from "./deletebooking.js"; +export * from "./getbooking.js"; +export * from "./getbookings.js"; +export * from "./getstations.js"; +export * from "./gettrips.js"; +export * from "./httpclienterrors.js"; +export * from "./responsevalidationerror.js"; +export * from "./sdkerror.js"; +export * from "./sdkvalidationerror.js"; diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/responsevalidationerror.ts b/frameworks-elysia/sdk-typescript/src/models/errors/responsevalidationerror.ts new file mode 100644 index 00000000..d6620ee0 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/responsevalidationerror.ts @@ -0,0 +1,50 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { SDKError } from "./sdkerror.js"; +import { formatZodError } from "./sdkvalidationerror.js"; + +export class ResponseValidationError extends SDKError { + /** + * The raw value that failed validation. + */ + public readonly rawValue: unknown; + + /** + * The raw message that failed validation. + */ + public readonly rawMessage: unknown; + + constructor( + message: string, + extra: { + response: Response; + request: Request; + body: string; + cause: unknown; + rawValue: unknown; + rawMessage: unknown; + }, + ) { + super(message, extra); + this.name = "ResponseValidationError"; + this.cause = extra.cause; + this.rawValue = extra.rawValue; + this.rawMessage = extra.rawMessage; + } + + /** + * Return a pretty-formatted error message if the underlying validation error + * is a ZodError or some other recognized error type, otherwise return the + * default error message. + */ + public pretty(): string { + if (this.cause instanceof z.ZodError) { + return `${this.rawMessage}\n${formatZodError(this.cause)}`; + } else { + return this.toString(); + } + } +} diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/sdkerror.ts b/frameworks-elysia/sdk-typescript/src/models/errors/sdkerror.ts new file mode 100644 index 00000000..efcdf908 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/sdkerror.ts @@ -0,0 +1,35 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** The base class for all HTTP error responses */ +export class SDKError extends Error { + /** HTTP status code */ + public readonly statusCode: number; + /** HTTP body */ + public readonly body: string; + /** HTTP headers */ + public readonly headers: Headers; + /** HTTP content type */ + public readonly contentType: string; + /** Raw response */ + public readonly rawResponse: Response; + + constructor( + message: string, + httpMeta: { + response: Response; + request: Request; + body: string; + }, + ) { + super(message); + this.statusCode = httpMeta.response.status; + this.body = httpMeta.body; + this.headers = httpMeta.response.headers; + this.contentType = httpMeta.response.headers.get("content-type") || ""; + this.rawResponse = httpMeta.response; + + this.name = "SDKError"; + } +} diff --git a/frameworks-elysia/sdk-typescript/src/models/errors/sdkvalidationerror.ts b/frameworks-elysia/sdk-typescript/src/models/errors/sdkvalidationerror.ts new file mode 100644 index 00000000..6826e120 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/errors/sdkvalidationerror.ts @@ -0,0 +1,109 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; + +export class SDKValidationError extends Error { + /** + * The raw value that failed validation. + */ + public readonly rawValue: unknown; + + /** + * The raw message that failed validation. + */ + public readonly rawMessage: unknown; + + // Allows for backwards compatibility for `instanceof` checks of `ResponseValidationError` + static override [Symbol.hasInstance]( + instance: unknown, + ): instance is SDKValidationError { + if (!(instance instanceof Error)) return false; + if (!("rawValue" in instance)) return false; + if (!("rawMessage" in instance)) return false; + if (!("pretty" in instance)) return false; + if (typeof instance.pretty !== "function") return false; + return true; + } + + constructor(message: string, cause: unknown, rawValue: unknown) { + super(`${message}: ${cause}`); + this.name = "SDKValidationError"; + this.cause = cause; + this.rawValue = rawValue; + this.rawMessage = message; + } + + /** + * Return a pretty-formatted error message if the underlying validation error + * is a ZodError or some other recognized error type, otherwise return the + * default error message. + */ + public pretty(): string { + if (this.cause instanceof z.ZodError) { + return `${this.rawMessage}\n${formatZodError(this.cause)}`; + } else { + return this.toString(); + } + } +} + +export function formatZodError(err: z.ZodError, level = 0): string { + let pre = " ".repeat(level); + pre = level > 0 ? `│${pre}` : pre; + pre += " ".repeat(level); + + let message = ""; + const append = (str: string) => (message += `\n${pre}${str}`); + + const len = err.issues.length; + const headline = len === 1 ? `${len} issue found` : `${len} issues found`; + + if (len) { + append(`┌ ${headline}:`); + } + + for (const issue of err.issues) { + let path = issue.path.join("."); + path = path ? `.${path}` : ""; + append(`│ • [${path}]: ${issue.message} (${issue.code})`); + switch (issue.code) { + case "invalid_literal": + case "invalid_type": { + append(`│ Want: ${issue.expected}`); + append(`│ Got: ${issue.received}`); + break; + } + case "unrecognized_keys": { + append(`│ Keys: ${issue.keys.join(", ")}`); + break; + } + case "invalid_enum_value": { + append(`│ Allowed: ${issue.options.join(", ")}`); + append(`│ Got: ${issue.received}`); + break; + } + case "invalid_union_discriminator": { + append(`│ Allowed: ${issue.options.join(", ")}`); + break; + } + case "invalid_union": { + const len = issue.unionErrors.length; + append( + `│ ✖︎ Attemped to deserialize into one of ${len} union members:`, + ); + issue.unionErrors.forEach((err, i) => { + append(`│ ✖︎ Member ${i + 1} of ${len}`); + append(`${formatZodError(err, level + 1)}`); + }); + } + } + } + + if (err.issues.length) { + append(`└─*`); + } + + return message.slice(1); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/createbooking.ts b/frameworks-elysia/sdk-typescript/src/models/operations/createbooking.ts new file mode 100644 index 00000000..c07601c3 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/createbooking.ts @@ -0,0 +1,123 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +/** + * Booking details. + */ +export type CreateBookingBookingsRequestRequestBody = { + tripId: string; + passengerName: string; + hasBicycle?: boolean | undefined; + hasDog?: boolean | undefined; +}; + +export type CreateBookingLinks = { + self: string; +}; + +/** + * A booking for a train trip. + */ +export type CreateBookingResponseBody = { + id: string; + tripId: string; + passengerName: string; + hasBicycle: boolean; + hasDog: boolean; + links: CreateBookingLinks; +}; + +/** @internal */ +export type CreateBookingBookingsRequestRequestBody$Outbound = { + trip_id: string; + passenger_name: string; + has_bicycle?: boolean | undefined; + has_dog?: boolean | undefined; +}; + +/** @internal */ +export const CreateBookingBookingsRequestRequestBody$outboundSchema: z.ZodType< + CreateBookingBookingsRequestRequestBody$Outbound, + z.ZodTypeDef, + CreateBookingBookingsRequestRequestBody +> = z.object({ + tripId: z.string(), + passengerName: z.string(), + hasBicycle: z.boolean().optional(), + hasDog: z.boolean().optional(), +}).transform((v) => { + return remap$(v, { + tripId: "trip_id", + passengerName: "passenger_name", + hasBicycle: "has_bicycle", + hasDog: "has_dog", + }); +}); + +export function createBookingBookingsRequestRequestBodyToJSON( + createBookingBookingsRequestRequestBody: + CreateBookingBookingsRequestRequestBody, +): string { + return JSON.stringify( + CreateBookingBookingsRequestRequestBody$outboundSchema.parse( + createBookingBookingsRequestRequestBody, + ), + ); +} + +/** @internal */ +export const CreateBookingLinks$inboundSchema: z.ZodType< + CreateBookingLinks, + z.ZodTypeDef, + unknown +> = z.object({ + self: z.string(), +}); + +export function createBookingLinksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CreateBookingLinks$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingLinks' from JSON`, + ); +} + +/** @internal */ +export const CreateBookingResponseBody$inboundSchema: z.ZodType< + CreateBookingResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + id: z.string(), + trip_id: z.string(), + passenger_name: z.string(), + has_bicycle: z.boolean(), + has_dog: z.boolean(), + links: z.lazy(() => CreateBookingLinks$inboundSchema), +}).transform((v) => { + return remap$(v, { + "trip_id": "tripId", + "passenger_name": "passengerName", + "has_bicycle": "hasBicycle", + "has_dog": "hasDog", + }); +}); + +export function createBookingResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CreateBookingResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/createbookingpayment.ts b/frameworks-elysia/sdk-typescript/src/models/operations/createbookingpayment.ts new file mode 100644 index 00000000..d17d7f95 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/createbookingpayment.ts @@ -0,0 +1,468 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { ClosedEnum } from "../../types/enums.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +export const CreateBookingPaymentPaymentsCurrency = { + Bam: "bam", + Bgn: "bgn", + Chf: "chf", + Eur: "eur", + Gbp: "gbp", + Nok: "nok", + Sek: "sek", +} as const; +export type CreateBookingPaymentPaymentsCurrency = ClosedEnum< + typeof CreateBookingPaymentPaymentsCurrency +>; + +export const CreateBookingPaymentSourceAccountType = { + Individual: "individual", + Company: "company", +} as const; +export type CreateBookingPaymentSourceAccountType = ClosedEnum< + typeof CreateBookingPaymentSourceAccountType +>; + +export type CreateBookingPaymentSource2 = { + object: "bank_account"; + name: string; + number: string; + sortCode?: string | undefined; + accountType: CreateBookingPaymentSourceAccountType; + bankName: string; + country: string; +}; + +export type CreateBookingPaymentSource1 = { + object: "card"; + name: string; + number: string; + cvc: string; + expMonth: number; + expYear: number; + addressCountry: string; + addressPostCode?: string | undefined; +}; + +export type CreateBookingPaymentPaymentsSource = + | CreateBookingPaymentSource1 + | CreateBookingPaymentSource2; + +export type CreateBookingPaymentPaymentsRequestRequestBody = { + amount: number; + currency: CreateBookingPaymentPaymentsCurrency; + promoCode?: string | null | undefined; + source: CreateBookingPaymentSource1 | CreateBookingPaymentSource2; +}; + +export type CreateBookingPaymentRequest = { + bookingId: string; + requestBody: CreateBookingPaymentPaymentsRequestRequestBody; +}; + +export const CreateBookingPaymentSourcePaymentsAccountType = { + Individual: "individual", + Company: "company", +} as const; +export type CreateBookingPaymentSourcePaymentsAccountType = ClosedEnum< + typeof CreateBookingPaymentSourcePaymentsAccountType +>; + +export type CreateBookingPaymentSourcePayments2 = { + object: "bank_account"; + name: string; + number: string; + sortCode?: string | undefined; + accountType: CreateBookingPaymentSourcePaymentsAccountType; + bankName: string; + country: string; +}; + +export type CreateBookingPaymentSourcePayments1 = { + object: "card"; + name: string; + number: string; + cvc: string; + expMonth: number; + expYear: number; + addressCountry: string; + addressPostCode?: string | undefined; +}; + +export type CreateBookingPaymentPaymentsResponseSource = + | CreateBookingPaymentSourcePayments1 + | CreateBookingPaymentSourcePayments2; + +export const Status = { + Pending: "pending", + Succeeded: "succeeded", + Failed: "failed", +} as const; +export type Status = ClosedEnum; + +export type CreateBookingPaymentLinks = { + booking: string; +}; + +/** + * Payment successful + */ +export type CreateBookingPaymentResponseBody = { + id: string; + amount: number; + currency: string; + source: + | CreateBookingPaymentSourcePayments1 + | CreateBookingPaymentSourcePayments2; + status: Status; + links: CreateBookingPaymentLinks; +}; + +/** @internal */ +export const CreateBookingPaymentPaymentsCurrency$outboundSchema: + z.ZodNativeEnum = z.nativeEnum( + CreateBookingPaymentPaymentsCurrency, + ); + +/** @internal */ +export const CreateBookingPaymentSourceAccountType$outboundSchema: + z.ZodNativeEnum = z.nativeEnum( + CreateBookingPaymentSourceAccountType, + ); + +/** @internal */ +export type CreateBookingPaymentSource2$Outbound = { + object: "bank_account"; + name: string; + number: string; + sort_code?: string | undefined; + account_type: string; + bank_name: string; + country: string; +}; + +/** @internal */ +export const CreateBookingPaymentSource2$outboundSchema: z.ZodType< + CreateBookingPaymentSource2$Outbound, + z.ZodTypeDef, + CreateBookingPaymentSource2 +> = z.object({ + object: z.literal("bank_account"), + name: z.string(), + number: z.string(), + sortCode: z.string().optional(), + accountType: CreateBookingPaymentSourceAccountType$outboundSchema, + bankName: z.string(), + country: z.string(), +}).transform((v) => { + return remap$(v, { + sortCode: "sort_code", + accountType: "account_type", + bankName: "bank_name", + }); +}); + +export function createBookingPaymentSource2ToJSON( + createBookingPaymentSource2: CreateBookingPaymentSource2, +): string { + return JSON.stringify( + CreateBookingPaymentSource2$outboundSchema.parse( + createBookingPaymentSource2, + ), + ); +} + +/** @internal */ +export type CreateBookingPaymentSource1$Outbound = { + object: "card"; + name: string; + number: string; + cvc: string; + exp_month: number; + exp_year: number; + address_country: string; + address_post_code?: string | undefined; +}; + +/** @internal */ +export const CreateBookingPaymentSource1$outboundSchema: z.ZodType< + CreateBookingPaymentSource1$Outbound, + z.ZodTypeDef, + CreateBookingPaymentSource1 +> = z.object({ + object: z.literal("card"), + name: z.string(), + number: z.string(), + cvc: z.string(), + expMonth: z.number(), + expYear: z.number(), + addressCountry: z.string(), + addressPostCode: z.string().optional(), +}).transform((v) => { + return remap$(v, { + expMonth: "exp_month", + expYear: "exp_year", + addressCountry: "address_country", + addressPostCode: "address_post_code", + }); +}); + +export function createBookingPaymentSource1ToJSON( + createBookingPaymentSource1: CreateBookingPaymentSource1, +): string { + return JSON.stringify( + CreateBookingPaymentSource1$outboundSchema.parse( + createBookingPaymentSource1, + ), + ); +} + +/** @internal */ +export type CreateBookingPaymentPaymentsSource$Outbound = + | CreateBookingPaymentSource1$Outbound + | CreateBookingPaymentSource2$Outbound; + +/** @internal */ +export const CreateBookingPaymentPaymentsSource$outboundSchema: z.ZodType< + CreateBookingPaymentPaymentsSource$Outbound, + z.ZodTypeDef, + CreateBookingPaymentPaymentsSource +> = z.union([ + z.lazy(() => CreateBookingPaymentSource1$outboundSchema), + z.lazy(() => CreateBookingPaymentSource2$outboundSchema), +]); + +export function createBookingPaymentPaymentsSourceToJSON( + createBookingPaymentPaymentsSource: CreateBookingPaymentPaymentsSource, +): string { + return JSON.stringify( + CreateBookingPaymentPaymentsSource$outboundSchema.parse( + createBookingPaymentPaymentsSource, + ), + ); +} + +/** @internal */ +export type CreateBookingPaymentPaymentsRequestRequestBody$Outbound = { + amount: number; + currency: string; + promo_code?: string | null | undefined; + source: + | CreateBookingPaymentSource1$Outbound + | CreateBookingPaymentSource2$Outbound; +}; + +/** @internal */ +export const CreateBookingPaymentPaymentsRequestRequestBody$outboundSchema: + z.ZodType< + CreateBookingPaymentPaymentsRequestRequestBody$Outbound, + z.ZodTypeDef, + CreateBookingPaymentPaymentsRequestRequestBody + > = z.object({ + amount: z.number(), + currency: CreateBookingPaymentPaymentsCurrency$outboundSchema, + promoCode: z.nullable(z.string()).optional(), + source: z.union([ + z.lazy(() => CreateBookingPaymentSource1$outboundSchema), + z.lazy(() => CreateBookingPaymentSource2$outboundSchema), + ]), + }).transform((v) => { + return remap$(v, { + promoCode: "promo_code", + }); + }); + +export function createBookingPaymentPaymentsRequestRequestBodyToJSON( + createBookingPaymentPaymentsRequestRequestBody: + CreateBookingPaymentPaymentsRequestRequestBody, +): string { + return JSON.stringify( + CreateBookingPaymentPaymentsRequestRequestBody$outboundSchema.parse( + createBookingPaymentPaymentsRequestRequestBody, + ), + ); +} + +/** @internal */ +export type CreateBookingPaymentRequest$Outbound = { + bookingId: string; + RequestBody: CreateBookingPaymentPaymentsRequestRequestBody$Outbound; +}; + +/** @internal */ +export const CreateBookingPaymentRequest$outboundSchema: z.ZodType< + CreateBookingPaymentRequest$Outbound, + z.ZodTypeDef, + CreateBookingPaymentRequest +> = z.object({ + bookingId: z.string(), + requestBody: z.lazy(() => + CreateBookingPaymentPaymentsRequestRequestBody$outboundSchema + ), +}).transform((v) => { + return remap$(v, { + requestBody: "RequestBody", + }); +}); + +export function createBookingPaymentRequestToJSON( + createBookingPaymentRequest: CreateBookingPaymentRequest, +): string { + return JSON.stringify( + CreateBookingPaymentRequest$outboundSchema.parse( + createBookingPaymentRequest, + ), + ); +} + +/** @internal */ +export const CreateBookingPaymentSourcePaymentsAccountType$inboundSchema: + z.ZodNativeEnum = z + .nativeEnum(CreateBookingPaymentSourcePaymentsAccountType); + +/** @internal */ +export const CreateBookingPaymentSourcePayments2$inboundSchema: z.ZodType< + CreateBookingPaymentSourcePayments2, + z.ZodTypeDef, + unknown +> = z.object({ + object: z.literal("bank_account"), + name: z.string(), + number: z.string(), + sort_code: z.string().optional(), + account_type: CreateBookingPaymentSourcePaymentsAccountType$inboundSchema, + bank_name: z.string(), + country: z.string(), +}).transform((v) => { + return remap$(v, { + "sort_code": "sortCode", + "account_type": "accountType", + "bank_name": "bankName", + }); +}); + +export function createBookingPaymentSourcePayments2FromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => + CreateBookingPaymentSourcePayments2$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingPaymentSourcePayments2' from JSON`, + ); +} + +/** @internal */ +export const CreateBookingPaymentSourcePayments1$inboundSchema: z.ZodType< + CreateBookingPaymentSourcePayments1, + z.ZodTypeDef, + unknown +> = z.object({ + object: z.literal("card"), + name: z.string(), + number: z.string(), + cvc: z.string(), + exp_month: z.number(), + exp_year: z.number(), + address_country: z.string(), + address_post_code: z.string().optional(), +}).transform((v) => { + return remap$(v, { + "exp_month": "expMonth", + "exp_year": "expYear", + "address_country": "addressCountry", + "address_post_code": "addressPostCode", + }); +}); + +export function createBookingPaymentSourcePayments1FromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => + CreateBookingPaymentSourcePayments1$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingPaymentSourcePayments1' from JSON`, + ); +} + +/** @internal */ +export const CreateBookingPaymentPaymentsResponseSource$inboundSchema: + z.ZodType = + z.union([ + z.lazy(() => CreateBookingPaymentSourcePayments1$inboundSchema), + z.lazy(() => CreateBookingPaymentSourcePayments2$inboundSchema), + ]); + +export function createBookingPaymentPaymentsResponseSourceFromJSON( + jsonString: string, +): SafeParseResult< + CreateBookingPaymentPaymentsResponseSource, + SDKValidationError +> { + return safeParse( + jsonString, + (x) => + CreateBookingPaymentPaymentsResponseSource$inboundSchema.parse( + JSON.parse(x), + ), + `Failed to parse 'CreateBookingPaymentPaymentsResponseSource' from JSON`, + ); +} + +/** @internal */ +export const Status$inboundSchema: z.ZodNativeEnum = z + .nativeEnum(Status); + +/** @internal */ +export const CreateBookingPaymentLinks$inboundSchema: z.ZodType< + CreateBookingPaymentLinks, + z.ZodTypeDef, + unknown +> = z.object({ + booking: z.string(), +}); + +export function createBookingPaymentLinksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CreateBookingPaymentLinks$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingPaymentLinks' from JSON`, + ); +} + +/** @internal */ +export const CreateBookingPaymentResponseBody$inboundSchema: z.ZodType< + CreateBookingPaymentResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + id: z.string(), + amount: z.number(), + currency: z.string(), + source: z.union([ + z.lazy(() => CreateBookingPaymentSourcePayments1$inboundSchema), + z.lazy(() => CreateBookingPaymentSourcePayments2$inboundSchema), + ]), + status: Status$inboundSchema, + links: z.lazy(() => CreateBookingPaymentLinks$inboundSchema), +}); + +export function createBookingPaymentResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CreateBookingPaymentResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateBookingPaymentResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/deletebooking.ts b/frameworks-elysia/sdk-typescript/src/models/operations/deletebooking.ts new file mode 100644 index 00000000..a6b04310 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/deletebooking.ts @@ -0,0 +1,31 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; + +export type DeleteBookingRequest = { + bookingId: string; +}; + +/** @internal */ +export type DeleteBookingRequest$Outbound = { + bookingId: string; +}; + +/** @internal */ +export const DeleteBookingRequest$outboundSchema: z.ZodType< + DeleteBookingRequest$Outbound, + z.ZodTypeDef, + DeleteBookingRequest +> = z.object({ + bookingId: z.string(), +}); + +export function deleteBookingRequestToJSON( + deleteBookingRequest: DeleteBookingRequest, +): string { + return JSON.stringify( + DeleteBookingRequest$outboundSchema.parse(deleteBookingRequest), + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/getbooking.ts b/frameworks-elysia/sdk-typescript/src/models/operations/getbooking.ts new file mode 100644 index 00000000..0e87d118 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/getbooking.ts @@ -0,0 +1,101 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +export type GetBookingRequest = { + bookingId: string; +}; + +export type GetBookingLinks = { + self: string; +}; + +/** + * A booking for a train trip. + */ +export type GetBookingResponseBody = { + id: string; + tripId: string; + passengerName: string; + hasBicycle: boolean; + hasDog: boolean; + links: GetBookingLinks; +}; + +/** @internal */ +export type GetBookingRequest$Outbound = { + bookingId: string; +}; + +/** @internal */ +export const GetBookingRequest$outboundSchema: z.ZodType< + GetBookingRequest$Outbound, + z.ZodTypeDef, + GetBookingRequest +> = z.object({ + bookingId: z.string(), +}); + +export function getBookingRequestToJSON( + getBookingRequest: GetBookingRequest, +): string { + return JSON.stringify( + GetBookingRequest$outboundSchema.parse(getBookingRequest), + ); +} + +/** @internal */ +export const GetBookingLinks$inboundSchema: z.ZodType< + GetBookingLinks, + z.ZodTypeDef, + unknown +> = z.object({ + self: z.string(), +}); + +export function getBookingLinksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetBookingLinks$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetBookingLinks' from JSON`, + ); +} + +/** @internal */ +export const GetBookingResponseBody$inboundSchema: z.ZodType< + GetBookingResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + id: z.string(), + trip_id: z.string(), + passenger_name: z.string(), + has_bicycle: z.boolean(), + has_dog: z.boolean(), + links: z.lazy(() => GetBookingLinks$inboundSchema), +}).transform((v) => { + return remap$(v, { + "trip_id": "tripId", + "passenger_name": "passengerName", + "has_bicycle": "hasBicycle", + "has_dog": "hasDog", + }); +}); + +export function getBookingResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetBookingResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetBookingResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/getbookings.ts b/frameworks-elysia/sdk-typescript/src/models/operations/getbookings.ts new file mode 100644 index 00000000..d6173b7b --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/getbookings.ts @@ -0,0 +1,134 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +export type GetBookingsRequest = { + page?: number | undefined; + limit?: number | undefined; +}; + +/** + * A booking for a train trip. + */ +export type GetBookingsData = { + id: string; + tripId: string; + passengerName: string; + hasBicycle: boolean; + hasDog: boolean; +}; + +export type GetBookingsLinks = { + self: string; + next?: string | undefined; + prev?: string | undefined; +}; + +/** + * A list of bookings + */ +export type GetBookingsResponseBody = { + data: Array; + links: GetBookingsLinks; +}; + +/** @internal */ +export type GetBookingsRequest$Outbound = { + page: number; + limit: number; +}; + +/** @internal */ +export const GetBookingsRequest$outboundSchema: z.ZodType< + GetBookingsRequest$Outbound, + z.ZodTypeDef, + GetBookingsRequest +> = z.object({ + page: z.number().default(1), + limit: z.number().default(10), +}); + +export function getBookingsRequestToJSON( + getBookingsRequest: GetBookingsRequest, +): string { + return JSON.stringify( + GetBookingsRequest$outboundSchema.parse(getBookingsRequest), + ); +} + +/** @internal */ +export const GetBookingsData$inboundSchema: z.ZodType< + GetBookingsData, + z.ZodTypeDef, + unknown +> = z.object({ + id: z.string(), + trip_id: z.string(), + passenger_name: z.string(), + has_bicycle: z.boolean(), + has_dog: z.boolean(), +}).transform((v) => { + return remap$(v, { + "trip_id": "tripId", + "passenger_name": "passengerName", + "has_bicycle": "hasBicycle", + "has_dog": "hasDog", + }); +}); + +export function getBookingsDataFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetBookingsData$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetBookingsData' from JSON`, + ); +} + +/** @internal */ +export const GetBookingsLinks$inboundSchema: z.ZodType< + GetBookingsLinks, + z.ZodTypeDef, + unknown +> = z.object({ + self: z.string(), + next: z.string().optional(), + prev: z.string().optional(), +}); + +export function getBookingsLinksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetBookingsLinks$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetBookingsLinks' from JSON`, + ); +} + +/** @internal */ +export const GetBookingsResponseBody$inboundSchema: z.ZodType< + GetBookingsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + data: z.array(z.lazy(() => GetBookingsData$inboundSchema)), + links: z.lazy(() => GetBookingsLinks$inboundSchema), +}); + +export function getBookingsResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetBookingsResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetBookingsResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/getstations.ts b/frameworks-elysia/sdk-typescript/src/models/operations/getstations.ts new file mode 100644 index 00000000..fab7696c --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/getstations.ts @@ -0,0 +1,134 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +export type GetStationsRequest = { + page?: number | undefined; + limit?: number | undefined; + coordinates?: string | undefined; + search?: string | undefined; + country?: string | undefined; +}; + +/** + * A train station. + */ +export type Data = { + id: string; + name: string; + address: string; + countryCode: string; + timezone: string; +}; + +export type Links = { + self: string; + next?: string | undefined; + prev?: string | undefined; +}; + +/** + * OK + */ +export type GetStationsResponseBody = { + data: Array; + links: Links; +}; + +/** @internal */ +export type GetStationsRequest$Outbound = { + page: number; + limit: number; + coordinates?: string | undefined; + search?: string | undefined; + country?: string | undefined; +}; + +/** @internal */ +export const GetStationsRequest$outboundSchema: z.ZodType< + GetStationsRequest$Outbound, + z.ZodTypeDef, + GetStationsRequest +> = z.object({ + page: z.number().default(1), + limit: z.number().default(10), + coordinates: z.string().optional(), + search: z.string().optional(), + country: z.string().optional(), +}); + +export function getStationsRequestToJSON( + getStationsRequest: GetStationsRequest, +): string { + return JSON.stringify( + GetStationsRequest$outboundSchema.parse(getStationsRequest), + ); +} + +/** @internal */ +export const Data$inboundSchema: z.ZodType = z + .object({ + id: z.string(), + name: z.string(), + address: z.string(), + country_code: z.string(), + timezone: z.string(), + }).transform((v) => { + return remap$(v, { + "country_code": "countryCode", + }); + }); + +export function dataFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => Data$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'Data' from JSON`, + ); +} + +/** @internal */ +export const Links$inboundSchema: z.ZodType = z + .object({ + self: z.string(), + next: z.string().optional(), + prev: z.string().optional(), + }); + +export function linksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => Links$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'Links' from JSON`, + ); +} + +/** @internal */ +export const GetStationsResponseBody$inboundSchema: z.ZodType< + GetStationsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + data: z.array(z.lazy(() => Data$inboundSchema)), + links: z.lazy(() => Links$inboundSchema), +}); + +export function getStationsResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetStationsResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetStationsResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/gettrips.ts b/frameworks-elysia/sdk-typescript/src/models/operations/gettrips.ts new file mode 100644 index 00000000..d0b4c2c3 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/gettrips.ts @@ -0,0 +1,159 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { remap as remap$ } from "../../lib/primitives.js"; +import { safeParse } from "../../lib/schemas.js"; +import { Result as SafeParseResult } from "../../types/fp.js"; +import { SDKValidationError } from "../errors/sdkvalidationerror.js"; + +export type GetTripsRequest = { + page?: number | undefined; + limit?: number | undefined; + origin: string; + destination: string; + date: Date; + bicycles?: boolean | undefined; + dogs?: boolean | undefined; +}; + +/** + * A train trip. + */ +export type GetTripsData = { + id: string; + origin: string; + destination: string; + departureTime: Date; + arrivalTime: Date; + operator: string; + price: number; + bicyclesAllowed: boolean; + dogsAllowed: boolean; +}; + +export type GetTripsLinks = { + self: string; + next?: string | undefined; + prev?: string | undefined; +}; + +/** + * A list of available train trips + */ +export type GetTripsResponseBody = { + data: Array; + links: GetTripsLinks; +}; + +/** @internal */ +export type GetTripsRequest$Outbound = { + page: number; + limit: number; + origin: string; + destination: string; + date: string; + bicycles: boolean; + dogs: boolean; +}; + +/** @internal */ +export const GetTripsRequest$outboundSchema: z.ZodType< + GetTripsRequest$Outbound, + z.ZodTypeDef, + GetTripsRequest +> = z.object({ + page: z.number().default(1), + limit: z.number().default(10), + origin: z.string(), + destination: z.string(), + date: z.date().transform(v => v.toISOString()), + bicycles: z.boolean().default(false), + dogs: z.boolean().default(false), +}); + +export function getTripsRequestToJSON( + getTripsRequest: GetTripsRequest, +): string { + return JSON.stringify(GetTripsRequest$outboundSchema.parse(getTripsRequest)); +} + +/** @internal */ +export const GetTripsData$inboundSchema: z.ZodType< + GetTripsData, + z.ZodTypeDef, + unknown +> = z.object({ + id: z.string(), + origin: z.string(), + destination: z.string(), + departure_time: z.string().datetime({ offset: true }).transform(v => + new Date(v) + ), + arrival_time: z.string().datetime({ offset: true }).transform(v => + new Date(v) + ), + operator: z.string(), + price: z.number(), + bicycles_allowed: z.boolean(), + dogs_allowed: z.boolean(), +}).transform((v) => { + return remap$(v, { + "departure_time": "departureTime", + "arrival_time": "arrivalTime", + "bicycles_allowed": "bicyclesAllowed", + "dogs_allowed": "dogsAllowed", + }); +}); + +export function getTripsDataFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetTripsData$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetTripsData' from JSON`, + ); +} + +/** @internal */ +export const GetTripsLinks$inboundSchema: z.ZodType< + GetTripsLinks, + z.ZodTypeDef, + unknown +> = z.object({ + self: z.string(), + next: z.string().optional(), + prev: z.string().optional(), +}); + +export function getTripsLinksFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetTripsLinks$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetTripsLinks' from JSON`, + ); +} + +/** @internal */ +export const GetTripsResponseBody$inboundSchema: z.ZodType< + GetTripsResponseBody, + z.ZodTypeDef, + unknown +> = z.object({ + data: z.array(z.lazy(() => GetTripsData$inboundSchema)), + links: z.lazy(() => GetTripsLinks$inboundSchema), +}); + +export function getTripsResponseBodyFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetTripsResponseBody$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetTripsResponseBody' from JSON`, + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/models/operations/index.ts b/frameworks-elysia/sdk-typescript/src/models/operations/index.ts new file mode 100644 index 00000000..638d1f90 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/models/operations/index.ts @@ -0,0 +1,11 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./createbooking.js"; +export * from "./createbookingpayment.js"; +export * from "./deletebooking.js"; +export * from "./getbooking.js"; +export * from "./getbookings.js"; +export * from "./getstations.js"; +export * from "./gettrips.js"; diff --git a/frameworks-elysia/sdk-typescript/src/sdk/bookings.ts b/frameworks-elysia/sdk-typescript/src/sdk/bookings.ts new file mode 100644 index 00000000..b48f88bd --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/bookings.ts @@ -0,0 +1,81 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { bookingsCreateBooking } from "../funcs/bookingsCreateBooking.js"; +import { bookingsDeleteBooking } from "../funcs/bookingsDeleteBooking.js"; +import { bookingsGetBooking } from "../funcs/bookingsGetBooking.js"; +import { bookingsGetBookings } from "../funcs/bookingsGetBookings.js"; +import { ClientSDK, RequestOptions } from "../lib/sdks.js"; +import * as operations from "../models/operations/index.js"; +import { unwrapAsync } from "../types/fp.js"; + +export class Bookings extends ClientSDK { + /** + * List existing bookings + * + * @remarks + * Returns a list of all trip bookings by the authenticated user. + */ + async getBookings( + request: operations.GetBookingsRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(bookingsGetBookings( + this, + request, + options, + )); + } + + /** + * Create a booking + * + * @remarks + * A booking is a temporary hold on a trip. It is not confirmed until payment is processed. + */ + async createBooking( + request: operations.CreateBookingBookingsRequestRequestBody, + options?: RequestOptions, + ): Promise { + return unwrapAsync(bookingsCreateBooking( + this, + request, + options, + )); + } + + /** + * Get a booking + * + * @remarks + * Returns the details of a specific booking. + */ + async getBooking( + request: operations.GetBookingRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(bookingsGetBooking( + this, + request, + options, + )); + } + + /** + * Delete a booking + * + * @remarks + * Deletes a booking, cancelling the hold on the trip. + */ + async deleteBooking( + request: operations.DeleteBookingRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(bookingsDeleteBooking( + this, + request, + options, + )); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/sdk/index.ts b/frameworks-elysia/sdk-typescript/src/sdk/index.ts new file mode 100644 index 00000000..ecac2264 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/index.ts @@ -0,0 +1,5 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export * from "./sdk.js"; diff --git a/frameworks-elysia/sdk-typescript/src/sdk/payments.ts b/frameworks-elysia/sdk-typescript/src/sdk/payments.ts new file mode 100644 index 00000000..07655a17 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/payments.ts @@ -0,0 +1,27 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { paymentsCreateBookingPayment } from "../funcs/paymentsCreateBookingPayment.js"; +import { ClientSDK, RequestOptions } from "../lib/sdks.js"; +import * as operations from "../models/operations/index.js"; +import { unwrapAsync } from "../types/fp.js"; + +export class Payments extends ClientSDK { + /** + * Pay for a booking + * + * @remarks + * A payment attempt confirms the booking and enables ticket retrieval. + */ + async createBookingPayment( + request: operations.CreateBookingPaymentRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(paymentsCreateBookingPayment( + this, + request, + options, + )); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/sdk/sdk.ts b/frameworks-elysia/sdk-typescript/src/sdk/sdk.ts new file mode 100644 index 00000000..58446642 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/sdk.ts @@ -0,0 +1,31 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { ClientSDK } from "../lib/sdks.js"; +import { Bookings } from "./bookings.js"; +import { Payments } from "./payments.js"; +import { Stations } from "./stations.js"; +import { Trips } from "./trips.js"; + +export class SDK extends ClientSDK { + private _stations?: Stations; + get stations(): Stations { + return (this._stations ??= new Stations(this._options)); + } + + private _trips?: Trips; + get trips(): Trips { + return (this._trips ??= new Trips(this._options)); + } + + private _bookings?: Bookings; + get bookings(): Bookings { + return (this._bookings ??= new Bookings(this._options)); + } + + private _payments?: Payments; + get payments(): Payments { + return (this._payments ??= new Payments(this._options)); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/sdk/stations.ts b/frameworks-elysia/sdk-typescript/src/sdk/stations.ts new file mode 100644 index 00000000..5333111e --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/stations.ts @@ -0,0 +1,27 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { stationsGetStations } from "../funcs/stationsGetStations.js"; +import { ClientSDK, RequestOptions } from "../lib/sdks.js"; +import * as operations from "../models/operations/index.js"; +import { unwrapAsync } from "../types/fp.js"; + +export class Stations extends ClientSDK { + /** + * Get a list of train stations + * + * @remarks + * Returns a paginated and searchable list of all train stations. + */ + async getStations( + request: operations.GetStationsRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(stationsGetStations( + this, + request, + options, + )); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/sdk/trips.ts b/frameworks-elysia/sdk-typescript/src/sdk/trips.ts new file mode 100644 index 00000000..81955925 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/sdk/trips.ts @@ -0,0 +1,27 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { tripsGetTrips } from "../funcs/tripsGetTrips.js"; +import { ClientSDK, RequestOptions } from "../lib/sdks.js"; +import * as operations from "../models/operations/index.js"; +import { unwrapAsync } from "../types/fp.js"; + +export class Trips extends ClientSDK { + /** + * Get available train trips + * + * @remarks + * Returns a list of available train trips between the specified origin and destination stations on the given date. + */ + async getTrips( + request: operations.GetTripsRequest, + options?: RequestOptions, + ): Promise { + return unwrapAsync(tripsGetTrips( + this, + request, + options, + )); + } +} diff --git a/frameworks-elysia/sdk-typescript/src/types/async.ts b/frameworks-elysia/sdk-typescript/src/types/async.ts new file mode 100644 index 00000000..1543b95c --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/async.ts @@ -0,0 +1,69 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export type APICall = + | { + status: "complete"; + request: Request; + response: Response; + } + | { + status: "request-error"; + request: Request; + response?: undefined; + } + | { + status: "invalid"; + request?: undefined; + response?: undefined; + }; + +export class APIPromise implements Promise { + readonly #promise: Promise<[T, APICall]>; + #unwrapped: Promise | null; + + readonly [Symbol.toStringTag] = "APIPromise"; + + constructor(p: [T, APICall] | Promise<[T, APICall]>) { + this.#promise = p instanceof Promise ? p : Promise.resolve(p); + this.#unwrapped = p instanceof Promise ? null : Promise.resolve(p[0]); + } + + #getUnwrapped(): Promise { + return (this.#unwrapped ??= this.#promise.then(([value]) => value)); + } + + then( + onfulfilled?: + | ((value: T) => TResult1 | PromiseLike) + | null + | undefined, + onrejected?: + | ((reason: any) => TResult2 | PromiseLike) + | null + | undefined, + ): Promise { + return this.#promise.then( + onfulfilled ? ([value]) => onfulfilled(value) : void 0, + onrejected, + ); + } + + catch( + onrejected?: + | ((reason: any) => TResult | PromiseLike) + | null + | undefined, + ): Promise { + return this.#getUnwrapped().catch(onrejected); + } + + finally(onfinally?: (() => void) | null | undefined): Promise { + return this.#getUnwrapped().finally(onfinally); + } + + $inspect(): Promise<[T, APICall]> { + return this.#promise; + } +} diff --git a/frameworks-elysia/sdk-typescript/src/types/blobs.ts b/frameworks-elysia/sdk-typescript/src/types/blobs.ts new file mode 100644 index 00000000..cce2892d --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/blobs.ts @@ -0,0 +1,32 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; + +export const blobLikeSchema: z.ZodType = z.custom< + Blob +>(isBlobLike, { + message: "expected a Blob, File or Blob-like object", + fatal: true, +}); + +export function isBlobLike(val: unknown): val is Blob { + if (val instanceof Blob) { + return true; + } + + if (typeof val !== "object" || val == null || !(Symbol.toStringTag in val)) { + return false; + } + + const name = val[Symbol.toStringTag]; + if (typeof name !== "string") { + return false; + } + if (name !== "Blob" && name !== "File") { + return false; + } + + return "stream" in val && typeof val.stream === "function"; +} diff --git a/frameworks-elysia/sdk-typescript/src/types/constdatetime.ts b/frameworks-elysia/sdk-typescript/src/types/constdatetime.ts new file mode 100644 index 00000000..fe62144e --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/constdatetime.ts @@ -0,0 +1,15 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; + +export function constDateTime( + val: string, +): z.ZodType { + return z.custom((v) => { + return ( + typeof v === "string" && new Date(v).getTime() === new Date(val).getTime() + ); + }, `Value must be equivalent to ${val}`); +} diff --git a/frameworks-elysia/sdk-typescript/src/types/enums.ts b/frameworks-elysia/sdk-typescript/src/types/enums.ts new file mode 100644 index 00000000..aba0ffd2 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/enums.ts @@ -0,0 +1,45 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import * as z from "zod/v3"; +import { Unrecognized, unrecognized } from "./unrecognized.js"; + +export type ClosedEnum>> = + T[keyof T]; +export type OpenEnum>> = + | T[keyof T] + | Unrecognized; + +export function inboundSchema>( + enumObj: T, +): z.ZodType, z.ZodTypeDef, unknown> { + const options = Object.values(enumObj); + return z.union([ + ...options.map(x => z.literal(x)), + z.string().transform(x => unrecognized(x)), + ] as any); +} + +export function inboundSchemaInt>( + enumObj: T, +): z.ZodType, z.ZodTypeDef, unknown> { + // For numeric enums, Object.values returns both numbers and string keys + const options = Object.values(enumObj).filter(v => typeof v === "number"); + return z.union([ + ...options.map(x => z.literal(x)), + z.number().int().transform(x => unrecognized(x)), + ] as any); +} + +export function outboundSchema>( + _: T, +): z.ZodType> { + return z.string() as any; +} + +export function outboundSchemaInt>( + _: T, +): z.ZodType> { + return z.number().int() as any; +} diff --git a/frameworks-elysia/sdk-typescript/src/types/fp.ts b/frameworks-elysia/sdk-typescript/src/types/fp.ts new file mode 100644 index 00000000..ccbe51ea --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/fp.ts @@ -0,0 +1,50 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +/** + * A monad that captures the result of a function call or an error if it was not + * successful. Railway programming, enabled by this type, can be a nicer + * alternative to traditional exception throwing because it allows functions to + * declare all _known_ errors with static types and then check for them + * exhaustively in application code. Thrown exception have a type of `unknown` + * and break out of regular control flow of programs making them harder to + * inspect and more verbose work with due to try-catch blocks. + */ +export type Result = + | { ok: true; value: T; error?: never } + | { ok: false; value?: never; error: E }; + +export function OK(value: V): Result { + return { ok: true, value }; +} + +export function ERR(error: E): Result { + return { ok: false, error }; +} + +/** + * unwrap is a convenience function for extracting a value from a result or + * throwing if there was an error. + */ +export function unwrap(r: Result): T { + if (!r.ok) { + throw r.error; + } + return r.value; +} + +/** + * unwrapAsync is a convenience function for resolving a value from a Promise + * of a result or rejecting if an error occurred. + */ +export async function unwrapAsync( + pr: Promise>, +): Promise { + const r = await pr; + if (!r.ok) { + throw r.error; + } + + return r.value; +} diff --git a/frameworks-elysia/sdk-typescript/src/types/index.ts b/frameworks-elysia/sdk-typescript/src/types/index.ts new file mode 100644 index 00000000..abf0b7ab --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/index.ts @@ -0,0 +1,11 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export { blobLikeSchema, isBlobLike } from "./blobs.js"; +export type { ClosedEnum, OpenEnum } from "./enums.js"; +export type { Result } from "./fp.js"; +export type { PageIterator, Paginator } from "./operations.js"; +export { createPageIterator } from "./operations.js"; +export { RFCDate } from "./rfcdate.js"; +export * from "./unrecognized.js"; diff --git a/frameworks-elysia/sdk-typescript/src/types/operations.ts b/frameworks-elysia/sdk-typescript/src/types/operations.ts new file mode 100644 index 00000000..beb81e10 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/operations.ts @@ -0,0 +1,105 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { Result } from "./fp.js"; + +export type Paginator = () => Promise }> | null; + +export type PageIterator = V & { + next: Paginator; + [Symbol.asyncIterator]: () => AsyncIterableIterator; + "~next"?: PageState | undefined; +}; + +export function createPageIterator( + page: V & { next: Paginator }, + halt: (v: V) => boolean, +): { + [Symbol.asyncIterator]: () => AsyncIterableIterator; +} { + return { + [Symbol.asyncIterator]: async function* paginator() { + yield page; + if (halt(page)) { + return; + } + + let p: typeof page | null = page; + for (p = await p.next(); p != null; p = await p.next()) { + yield p; + if (halt(p)) { + return; + } + } + }, + }; +} + +/** + * This utility create a special iterator that yields a single value and + * terminates. It is useful in paginated SDK functions that have early return + * paths when things go wrong. + */ +export function haltIterator( + v: V, +): PageIterator { + return { + ...v, + next: () => null, + [Symbol.asyncIterator]: async function* paginator() { + yield v; + }, + }; +} + +/** + * Converts an async iterator of `Result` into an async iterator of `V`. + * When error results occur, the underlying error value is thrown. + */ +export async function unwrapResultIterator( + iteratorPromise: Promise, PageState>>, +): Promise> { + const resultIter = await iteratorPromise; + + if (!resultIter.ok) { + throw resultIter.error; + } + + return { + ...resultIter.value, + next: unwrapPaginator(resultIter.next), + "~next": resultIter["~next"], + [Symbol.asyncIterator]: async function* paginator() { + for await (const page of resultIter) { + if (!page.ok) { + throw page.error; + } + yield page.value; + } + }, + }; +} + +function unwrapPaginator( + paginator: Paginator>, +): Paginator { + return () => { + const nextResult = paginator(); + if (nextResult == null) { + return null; + } + return nextResult.then((res) => { + if (!res.ok) { + throw res.error; + } + const out = { + ...res.value, + next: unwrapPaginator(res.next), + }; + return out; + }); + }; +} + +export const URL_OVERRIDE = Symbol("URL_OVERRIDE"); diff --git a/frameworks-elysia/sdk-typescript/src/types/rfcdate.ts b/frameworks-elysia/sdk-typescript/src/types/rfcdate.ts new file mode 100644 index 00000000..c79b3f53 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/rfcdate.ts @@ -0,0 +1,54 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +const dateRE = /^\d{4}-\d{2}-\d{2}$/; + +export class RFCDate { + private serialized: string; + + /** + * Creates a new RFCDate instance using today's date. + */ + static today(): RFCDate { + return new RFCDate(new Date()); + } + + /** + * Creates a new RFCDate instance using the provided input. + * If a string is used then in must be in the format YYYY-MM-DD. + * + * @param date A Date object or a date string in YYYY-MM-DD format + * @example + * new RFCDate("2022-01-01") + * @example + * new RFCDate(new Date()) + */ + constructor(date: Date | string) { + if (typeof date === "string" && !dateRE.test(date)) { + throw new RangeError( + "RFCDate: date strings must be in the format YYYY-MM-DD: " + date, + ); + } + + const value = new Date(date); + if (isNaN(+value)) { + throw new RangeError("RFCDate: invalid date provided: " + date); + } + + this.serialized = value.toISOString().slice(0, "YYYY-MM-DD".length); + if (!dateRE.test(this.serialized)) { + throw new TypeError( + `RFCDate: failed to build valid date with given value: ${date} serialized to ${this.serialized}`, + ); + } + } + + toJSON(): string { + return this.toString(); + } + + toString(): string { + return this.serialized; + } +} diff --git a/frameworks-elysia/sdk-typescript/src/types/streams.ts b/frameworks-elysia/sdk-typescript/src/types/streams.ts new file mode 100644 index 00000000..a0163e7a --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/streams.ts @@ -0,0 +1,21 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +export function isReadableStream( + val: unknown, +): val is ReadableStream { + if (typeof val !== "object" || val === null) { + return false; + } + + // Check for the presence of methods specific to ReadableStream + const stream = val as ReadableStream; + + // ReadableStream has methods like getReader, cancel, and tee + return ( + typeof stream.getReader === "function" && + typeof stream.cancel === "function" && + typeof stream.tee === "function" + ); +} diff --git a/frameworks-elysia/sdk-typescript/src/types/unrecognized.ts b/frameworks-elysia/sdk-typescript/src/types/unrecognized.ts new file mode 100644 index 00000000..b7a2a13f --- /dev/null +++ b/frameworks-elysia/sdk-typescript/src/types/unrecognized.ts @@ -0,0 +1,35 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +declare const __brand: unique symbol; +export type Unrecognized = T & { [__brand]: "unrecognized" }; + +function unrecognized(value: T): Unrecognized { + globalCount++; + return value as Unrecognized; +} + +let globalCount = 0; +let refCount = 0; +export function startCountingUnrecognized() { + refCount++; + const start = globalCount; + return { + /** + * Ends counting and returns the delta. + * @param delta - If provided, only this amount is added to the parent counter + * (used for nested unions where we only want to record the winning option's count). + * If not provided, records all counts since start(). + */ + end: (delta?: number) => { + const count = globalCount - start; + // Reset globalCount back to start, then add only the specified delta + globalCount = start + (delta ?? count); + if (--refCount === 0) globalCount = 0; + return count; + }, + }; +} + +export { unrecognized }; diff --git a/frameworks-elysia/sdk-typescript/tsconfig.json b/frameworks-elysia/sdk-typescript/tsconfig.json new file mode 100644 index 00000000..76110f88 --- /dev/null +++ b/frameworks-elysia/sdk-typescript/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "incremental": false, + "target": "ES2020", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "jsx": "react-jsx", + + "module": "Node16", + "moduleResolution": "Node16", + + "allowJs": true, + + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "rootDir": "src", + "outDir": ".", + + + // https://github.com/tsconfig/bases/blob/a1bf7c0fa2e094b068ca3e1448ca2ece4157977e/bases/strictest.json + "strict": true, + "allowUnusedLabels": false, + "allowUnreachableCode": false, + "exactOptionalPropertyTypes": true, + "useUnknownInCatchVariables": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "isolatedModules": true, + "checkJs": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src"], + "exclude": ["node_modules", "src/__tests__"] +} diff --git a/frameworks-elysia/src/app.ts b/frameworks-elysia/src/app.ts new file mode 100644 index 00000000..cdb806dd --- /dev/null +++ b/frameworks-elysia/src/app.ts @@ -0,0 +1,115 @@ +import { Elysia } from "elysia"; +import { stationsController } from "./controllers/stations"; +import { tripsController } from "./controllers/trips"; +import { bookingsController } from "./controllers/bookings"; +import { openapi } from "@elysia/openapi"; +import packageJson from "../package.json"; +import { cors } from "@elysiajs/cors"; + +export const createApp = () => + new Elysia() + .onError(({ error, code }) => { + if (code === "NOT_FOUND") { + return { + type: "https://example.com/errors/not-found", + title: "Not Found", + status: 404, + detail: "The requested resource was not found.", + }; + } + + console.error(error); + }) + .use( + cors({ + origin: "http://localhost:5173", + }) + ) + .use(stationsController) + .use(tripsController) + .use(bookingsController) + .use( + openapi({ + documentation: { + info: { + title: "Train Travel API", + description: + "API for finding and booking train trips across Europe.", + version: packageJson.version, + contact: { + name: "Train Support", + url: "https://example.com/support", + email: "support@example.com", + }, + }, + servers: [ + { + url: "https://api.example.com", + description: "Production", + }, + { + url: "http://localhost:3000", + description: "Development server", + }, + ], + security: [ + { + OAuth2: ["read"], + }, + ], + components: { + securitySchemes: { + OAuth2: { + type: "oauth2", + description: "OAuth 2.0 authorization code flow.", + flows: { + authorizationCode: { + authorizationUrl: "https://example.com/oauth/authorize", + tokenUrl: "https://example.com/oauth/token", + scopes: { + read: "Read access", + write: "Write access", + }, + }, + }, + }, + }, + }, + "x-speakeasy-retries": { + strategy: "backoff", + backoff: { + initialInterval: 500, + maxInterval: 60000, + maxElapsedTime: 3600000, + exponent: 1.5, + }, + statusCodes: ["5XX"], + retryConnectionErrors: true, + }, + tags: [ + { + name: "Stations", + description: + "Find and filter train stations across Europe, including their location and local timezone.", + }, + { + name: "Trips", + description: + "Timetables and routes for train trips between stations, including pricing and availability.", + }, + { + name: "Bookings", + description: + "Create and manage bookings for train trips, including passenger details and optional extras.", + }, + { + name: "Payments", + description: + "Pay for bookings using a card or bank account, and view payment status and history.", + }, + ], + }, + }) + ); + +export type App = ReturnType; diff --git a/frameworks-elysia/src/controllers/bookings.ts b/frameworks-elysia/src/controllers/bookings.ts new file mode 100644 index 00000000..1cec4433 --- /dev/null +++ b/frameworks-elysia/src/controllers/bookings.ts @@ -0,0 +1,349 @@ +import { Elysia, t } from "elysia"; +import { + createBooking, + createBookingPayment, + deleteBooking, + findBooking, + hasTrip, + listBookings, +} from "../train/data"; +import { + bookingPaymentRequestSchema, + bookingPaymentSchema, + bookingSchema, + createBookingRequestSchema, + linksPaginationSchema, + linksSelfSchema, + problemSchema, +} from "../train/schemas"; + +const bookingWithLinksSchema = t.Intersect([ + bookingSchema, + t.Object({ + links: linksSelfSchema, + }), +]); + +const bookingsCollectionSchema = t.Object({ + data: t.Array(bookingSchema), + links: t.Intersect([linksSelfSchema, linksPaginationSchema]), +}); + +const paymentWithLinkSchema = t.Intersect([ + bookingPaymentSchema, + t.Object({ + links: t.Object({ + booking: t.String({ + format: "uri", + example: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + }), + }), + }), +]); + +export const bookingsController = new Elysia({ prefix: "/bookings" }) + .get( + "/", + ({ query }) => { + const page = Number(query.page ?? 1); + const limit = Number(query.limit ?? 10); + const offset = (page - 1) * limit; + const rows = listBookings(); + const pageData = rows.slice(offset, offset + limit); + + return { + data: pageData, + links: { + self: `https://api.example.com/bookings?page=${page}&limit=${limit}`, + next: + offset + limit < rows.length + ? `https://api.example.com/bookings?page=${page + 1}&limit=${limit}` + : undefined, + prev: + page > 1 + ? `https://api.example.com/bookings?page=${page - 1}&limit=${limit}` + : undefined, + }, + }; + }, + { + query: t.Object({ + page: t.Optional(t.Number({ minimum: 1, default: 1 })), + limit: t.Optional(t.Number({ minimum: 1, maximum: 100, default: 10 })), + }), + detail: { + operationId: "get-bookings", + summary: "List existing bookings", + description: + "Returns a list of all trip bookings by the authenticated user.", + tags: ["Bookings"], + responses: { + 200: { + description: "A list of bookings", + content: { + "application/json": { + schema: bookingsCollectionSchema, + }, + }, + }, + 401: { + description: "Unauthorized", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + 500: { + description: "Internal Server Error", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + }, + }, + } + ) + .post( + "/", + ({ body, set, error }) => { + if (!hasTrip(body.trip_id)) { + return error(404, { + type: "https://example.com/errors/not-found", + title: "Not Found", + status: 404, + detail: "Trip not found.", + }); + } + + const booking = createBooking(body); + + set.status = 201; + + return { + ...booking, + links: { + self: `https://api.example.com/bookings/${booking.id}`, + }, + }; + }, + { + type: "json", + body: createBookingRequestSchema, + detail: { + operationId: "create-booking", + summary: "Create a booking", + description: + "A booking is a temporary hold on a trip. It is not confirmed until payment is processed.", + tags: ["Bookings"], + security: [ + { + OAuth2: ["write"], + }, + ], + "x-speakeasy-retries": { + strategy: "backoff", + backoff: { + initialInterval: 300, + maxInterval: 40000, + maxElapsedTime: 3000000, + exponent: 1.2, + }, + statusCodes: ["5XX"], + retryConnectionErrors: true, + }, + responses: { + 201: { + description: "Booking successful", + content: { + "application/json": { + schema: bookingWithLinksSchema, + }, + }, + }, + 404: { + description: "Not Found", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + 409: { + description: "Conflict", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + }, + }, + } + ) + .get( + "/:bookingId", + ({ params, error }) => { + const booking = findBooking(params.bookingId); + + if (!booking) { + return error(404, { + type: "https://example.com/errors/not-found", + title: "Not Found", + status: 404, + detail: "The requested resource was not found.", + }); + } + + return { + ...booking, + links: { + self: `https://api.example.com/bookings/${booking.id}`, + }, + }; + }, + { + params: t.Object({ + bookingId: t.String({ + format: "uuid", + example: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }), + }), + detail: { + operationId: "get-booking", + summary: "Get a booking", + description: "Returns the details of a specific booking.", + tags: ["Bookings"], + responses: { + 200: { + description: "The booking details", + content: { + "application/json": { + schema: bookingWithLinksSchema, + }, + }, + }, + 404: { + description: "Not Found", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + }, + }, + } + ) + .delete( + "/:bookingId", + ({ params, set, error }) => { + const removed = deleteBooking(params.bookingId); + + if (!removed) { + return error(404, { + type: "https://example.com/errors/not-found", + title: "Not Found", + status: 404, + detail: "The requested resource was not found.", + }); + } + + set.status = 204; + return ""; + }, + { + params: t.Object({ + bookingId: t.String({ + format: "uuid", + example: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }), + }), + detail: { + operationId: "delete-booking", + summary: "Delete a booking", + description: "Deletes a booking, cancelling the hold on the trip.", + tags: ["Bookings"], + security: [ + { + OAuth2: ["write"], + }, + ], + responses: { + 204: { + description: "Booking deleted", + }, + 404: { + description: "Not Found", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + }, + }, + } + ) + .post( + "/:bookingId/payment", + ({ params, body, error }) => { + const booking = findBooking(params.bookingId); + + if (!booking) { + return error(404, { + type: "https://example.com/errors/not-found", + title: "Not Found", + status: 404, + detail: "The requested resource was not found.", + }); + } + + const payment = createBookingPayment(params.bookingId, body); + + return { + ...payment, + links: { + booking: `https://api.example.com/bookings/${booking.id}`, + }, + }; + }, + { + type: "json", + params: t.Object({ + bookingId: t.String({ + format: "uuid", + example: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }), + }), + body: bookingPaymentRequestSchema, + detail: { + operationId: "create-booking-payment", + summary: "Pay for a booking", + description: + "A payment attempt confirms the booking and enables ticket retrieval.", + tags: ["Payments"], + responses: { + 200: { + description: "Payment successful", + content: { + "application/json": { + schema: paymentWithLinkSchema, + }, + }, + }, + 404: { + description: "Not Found", + content: { + "application/problem+json": { + schema: problemSchema, + }, + }, + }, + }, + }, + } + ); diff --git a/frameworks-elysia/src/controllers/stations.ts b/frameworks-elysia/src/controllers/stations.ts new file mode 100644 index 00000000..909545ad --- /dev/null +++ b/frameworks-elysia/src/controllers/stations.ts @@ -0,0 +1,73 @@ +import { Elysia, t } from 'elysia'; +import { listStations } from '../train/data'; +import { + linksPaginationSchema, + linksSelfSchema, + problemSchema, + stationSchema, +} from '../train/schemas'; + +const stationsCollectionSchema = t.Object({ + data: t.Array(stationSchema), + links: t.Intersect([linksSelfSchema, linksPaginationSchema]), +}); + +export const stationsController = new Elysia({ prefix: '/stations' }).get( + '/', + ({ query }) => { + const page = Number(query.page ?? 1); + const limit = Number(query.limit ?? 10); + const offset = (page - 1) * limit; + const rows = listStations({ search: query.search, country: query.country }); + const pageData = rows.slice(offset, offset + limit); + + return { + data: pageData, + links: { + self: `https://api.example.com/stations?page=${page}&limit=${limit}`, + next: + offset + limit < rows.length + ? `https://api.example.com/stations?page=${page + 1}&limit=${limit}` + : undefined, + prev: + page > 1 + ? `https://api.example.com/stations?page=${page - 1}&limit=${limit}` + : undefined, + }, + }; + }, + { + query: t.Object({ + page: t.Optional(t.Number({ minimum: 1, default: 1 })), + limit: t.Optional(t.Number({ minimum: 1, maximum: 100, default: 10 })), + coordinates: t.Optional(t.String({ example: '52.5200,13.4050' })), + search: t.Optional(t.String({ example: 'Milano Centrale' })), + country: t.Optional(t.String({ minLength: 2, maxLength: 2, example: 'DE' })), + }), + detail: { + operationId: 'get-stations', + summary: 'Get a list of train stations', + description: + 'Returns a paginated and searchable list of all train stations.', + tags: ['Stations'], + responses: { + 200: { + description: 'OK', + content: { + 'application/json': { + schema: stationsCollectionSchema, + }, + }, + }, + 400: { + description: 'Bad Request', + content: { + 'application/problem+json': { + schema: problemSchema, + }, + }, + }, + }, + }, + }, +); diff --git a/frameworks-elysia/src/controllers/trips.ts b/frameworks-elysia/src/controllers/trips.ts new file mode 100644 index 00000000..c3905f78 --- /dev/null +++ b/frameworks-elysia/src/controllers/trips.ts @@ -0,0 +1,89 @@ +import { Elysia, t } from 'elysia'; +import { listTrips } from '../train/data'; +import { + linksPaginationSchema, + linksSelfSchema, + problemSchema, + tripSchema, +} from '../train/schemas'; + +const tripsCollectionSchema = t.Object({ + data: t.Array(tripSchema), + links: t.Intersect([linksSelfSchema, linksPaginationSchema]), +}); + +export const tripsController = new Elysia({ prefix: '/trips' }).get( + '/', + ({ query, error }) => { + if (!query.origin || !query.destination || !query.date) { + return error(400, { + type: 'https://example.com/errors/bad-request', + title: 'Bad Request', + status: 400, + detail: 'origin, destination, and date are required.', + }); + } + + const page = Number(query.page ?? 1); + const limit = Number(query.limit ?? 10); + const offset = (page - 1) * limit; + const rows = listTrips({ + origin: query.origin, + destination: query.destination, + bicycles: query.bicycles, + dogs: query.dogs, + }); + const pageData = rows.slice(offset, offset + limit); + + return { + data: pageData, + links: { + self: `https://api.example.com/trips?origin=${query.origin}&destination=${query.destination}&date=${query.date}`, + next: + offset + limit < rows.length + ? `https://api.example.com/trips?origin=${query.origin}&destination=${query.destination}&date=${query.date}&page=${page + 1}&limit=${limit}` + : undefined, + prev: + page > 1 + ? `https://api.example.com/trips?origin=${query.origin}&destination=${query.destination}&date=${query.date}&page=${page - 1}&limit=${limit}` + : undefined, + }, + }; + }, + { + query: t.Object({ + page: t.Optional(t.Number({ minimum: 1, default: 1 })), + limit: t.Optional(t.Number({ minimum: 1, maximum: 100, default: 10 })), + origin: t.String({ format: 'uuid', example: 'efdbb9d1-02c2-4bc3-afb7-6788d8782b1e' }), + destination: t.String({ format: 'uuid', example: 'b2e783e1-c824-4d63-b37a-d8d698862f1d' }), + date: t.String({ format: 'date-time', example: '2024-02-01T09:00:00Z' }), + bicycles: t.Optional(t.Boolean({ default: false })), + dogs: t.Optional(t.Boolean({ default: false })), + }), + detail: { + operationId: 'get-trips', + summary: 'Get available train trips', + description: + 'Returns a list of available train trips between the specified origin and destination stations on the given date.', + tags: ['Trips'], + responses: { + 200: { + description: 'A list of available train trips', + content: { + 'application/json': { + schema: tripsCollectionSchema, + }, + }, + }, + 400: { + description: 'Bad Request', + content: { + 'application/problem+json': { + schema: problemSchema, + }, + }, + }, + }, + }, + }, +); diff --git a/frameworks-elysia/src/generateOpenAPIDocument.ts b/frameworks-elysia/src/generateOpenAPIDocument.ts new file mode 100644 index 00000000..de856a49 --- /dev/null +++ b/frameworks-elysia/src/generateOpenAPIDocument.ts @@ -0,0 +1,31 @@ +import * as yaml from "js-yaml"; +import { createApp } from "./app"; + +async function generateOpenAPI() { + try { + const app = createApp(); + const response = await app.handle( + new Request("http://elysia/openapi/json") + ); + + if (!response.ok) { + throw new Error( + `Failed to generate OpenAPI JSON: ${response.status} ${response.statusText}` + ); + } + + const openAPIObject = await response.json(); + + // Convert to YAML + const yamlString = yaml.dump(openAPIObject); + + // Save the YAML string to a file + await Bun.write("openapi.yaml", yamlString); + + console.log("OpenAPI document saved to openapi.yaml"); + } catch (error) { + console.error("Error generating OpenAPI spec:", error); + } +} + +generateOpenAPI(); diff --git a/frameworks-elysia/src/index.ts b/frameworks-elysia/src/index.ts new file mode 100644 index 00000000..89d02217 --- /dev/null +++ b/frameworks-elysia/src/index.ts @@ -0,0 +1,3 @@ +import { createApp } from './app' + +createApp().listen(3000) \ No newline at end of file diff --git a/frameworks-elysia/src/train/data.ts b/frameworks-elysia/src/train/data.ts new file mode 100644 index 00000000..33110768 --- /dev/null +++ b/frameworks-elysia/src/train/data.ts @@ -0,0 +1,159 @@ +import type { + Booking, + BookingPayment, + BookingPaymentRequest, + CreateBookingRequest, + Station, + Trip, +} from './schemas'; + +const stations: Station[] = [ + { + id: 'efdbb9d1-02c2-4bc3-afb7-6788d8782b1e', + name: 'Berlin Hauptbahnhof', + address: 'Invalidenstrasse 10557 Berlin, Germany', + country_code: 'DE', + timezone: 'Europe/Berlin', + }, + { + id: 'b2e783e1-c824-4d63-b37a-d8d698862f1d', + name: 'Paris Gare du Nord', + address: '18 Rue de Dunkerque 75010 Paris, France', + country_code: 'FR', + timezone: 'Europe/Paris', + }, +]; + +const trips: Trip[] = [ + { + id: 'ea399ba1-6d95-433f-92d1-83f67b775594', + origin: 'efdbb9d1-02c2-4bc3-afb7-6788d8782b1e', + destination: 'b2e783e1-c824-4d63-b37a-d8d698862f1d', + departure_time: '2024-02-01T10:00:00Z', + arrival_time: '2024-02-01T16:00:00Z', + price: 50, + operator: 'Deutsche Bahn', + bicycles_allowed: true, + dogs_allowed: true, + }, + { + id: '4d67459c-af07-40bb-bb12-178dbb88e09f', + origin: 'b2e783e1-c824-4d63-b37a-d8d698862f1d', + destination: 'efdbb9d1-02c2-4bc3-afb7-6788d8782b1e', + departure_time: '2024-02-01T12:00:00Z', + arrival_time: '2024-02-01T18:00:00Z', + price: 50, + operator: 'SNCF', + bicycles_allowed: true, + dogs_allowed: true, + }, +]; + +const bookings: Booking[] = [ + { + id: '1725ff48-ab45-4bb5-9d02-88745177dedb', + trip_id: 'ea399ba1-6d95-433f-92d1-83f67b775594', + passenger_name: 'John Doe', + has_bicycle: true, + has_dog: false, + }, +]; + +const payments: BookingPayment[] = []; + +export function listStations(filters: { search?: string; country?: string }): Station[] { + const search = filters.search?.trim().toLowerCase(); + const country = filters.country?.trim().toUpperCase(); + + return stations.filter((station) => { + if (country && station.country_code !== country) { + return false; + } + + if (!search) { + return true; + } + + return ( + station.name.toLowerCase().includes(search) || + station.address.toLowerCase().includes(search) + ); + }); +} + +export function listTrips(filters: { + origin: string; + destination: string; + bicycles?: boolean; + dogs?: boolean; +}): Trip[] { + return trips.filter((trip) => { + if (trip.origin !== filters.origin || trip.destination !== filters.destination) { + return false; + } + + if (filters.bicycles && !trip.bicycles_allowed) { + return false; + } + + if (filters.dogs && !trip.dogs_allowed) { + return false; + } + + return true; + }); +} + +export function listBookings(): Booking[] { + return bookings; +} + +export function findBooking(bookingId: string): Booking | undefined { + return bookings.find((booking) => booking.id === bookingId); +} + +export function createBooking(input: CreateBookingRequest): Booking { + const booking: Booking = { + id: crypto.randomUUID(), + trip_id: input.trip_id, + passenger_name: input.passenger_name, + has_bicycle: input.has_bicycle ?? false, + has_dog: input.has_dog ?? false, + }; + + bookings.push(booking); + + return booking; +} + +export function deleteBooking(bookingId: string): boolean { + const index = bookings.findIndex((booking) => booking.id === bookingId); + + if (index === -1) { + return false; + } + + bookings.splice(index, 1); + return true; +} + +export function createBookingPayment( + bookingId: string, + input: BookingPaymentRequest, +): BookingPayment { + const payment: BookingPayment = { + id: crypto.randomUUID(), + amount: input.amount, + currency: input.currency, + source: input.source, + status: 'succeeded', + }; + + payments.push(payment); + + return payment; +} + +export function hasTrip(tripId: string): boolean { + return trips.some((trip) => trip.id === tripId); +} diff --git a/frameworks-elysia/src/train/schemas.ts b/frameworks-elysia/src/train/schemas.ts new file mode 100644 index 00000000..ecc6c9dd --- /dev/null +++ b/frameworks-elysia/src/train/schemas.ts @@ -0,0 +1,179 @@ +import { t } from "elysia"; + +export const stationSchema = t.Object( + { + id: t.String({ + format: "uuid", + example: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + }), + name: t.String({ example: "Berlin Hauptbahnhof" }), + address: t.String({ example: "Invalidenstrasse 10557 Berlin, Germany" }), + country_code: t.String({ example: "DE" }), + timezone: t.String({ example: "Europe/Berlin" }), + }, + { + description: "A train station.", + } +); + +export const tripSchema = t.Object( + { + id: t.String({ + format: "uuid", + example: "ea399ba1-6d95-433f-92d1-83f67b775594", + }), + origin: t.String({ + format: "uuid", + example: "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", + }), + destination: t.String({ + format: "uuid", + example: "b2e783e1-c824-4d63-b37a-d8d698862f1d", + }), + departure_time: t.String({ + format: "date-time", + example: "2024-02-01T10:00:00Z", + }), + arrival_time: t.String({ + format: "date-time", + example: "2024-02-01T16:00:00Z", + }), + operator: t.String({ example: "Deutsche Bahn" }), + price: t.Number({ example: 50 }), + bicycles_allowed: t.Boolean({ example: true }), + dogs_allowed: t.Boolean({ example: true }), + }, + { + description: "A train trip.", + } +); + +export const bookingSchema = t.Object( + { + id: t.String({ + format: "uuid", + example: "1725ff48-ab45-4bb5-9d02-88745177dedb", + }), + trip_id: t.String({ + format: "uuid", + example: "ea399ba1-6d95-433f-92d1-83f67b775594", + }), + passenger_name: t.String({ example: "John Doe" }), + has_bicycle: t.Boolean({ example: true }), + has_dog: t.Boolean({ example: false }), + }, + { + description: "A booking for a train trip.", + } +); + +export const createBookingRequestSchema = t.Object( + { + trip_id: t.String({ + format: "uuid", + example: "ea399ba1-6d95-433f-92d1-83f67b775594", + }), + passenger_name: t.String({ example: "John Doe" }), + has_bicycle: t.Optional(t.Boolean({ example: true })), + has_dog: t.Optional(t.Boolean({ example: false })), + }, + { + description: "Booking details.", + example: { + trip_id: "ea399ba1-6d95-433f-92d1-83f67b775594", + passenger_name: "John Doe", + has_bicycle: true, + has_dog: false, + }, + } +); + +export const cardPaymentSourceSchema = t.Object({ + object: t.Literal("card"), + name: t.String({ example: "J. Doe" }), + number: t.String({ example: "4242424242424242" }), + cvc: t.String({ minLength: 3, maxLength: 4, example: "123" }), + exp_month: t.Number({ example: 12 }), + exp_year: t.Number({ example: 2025 }), + address_country: t.String({ example: "gb" }), + address_post_code: t.Optional(t.String({ example: "N12 9XX" })), +}); + +export const bankPaymentSourceSchema = t.Object({ + object: t.Literal("bank_account"), + name: t.String({ example: "J. Doe" }), + number: t.String({ example: "00012345" }), + sort_code: t.Optional(t.String({ example: "000123" })), + account_type: t.Union([t.Literal("individual"), t.Literal("company")]), + bank_name: t.String({ example: "Starling Bank" }), + country: t.String({ example: "gb" }), +}); + +export const bookingPaymentRequestSchema = t.Object({ + amount: t.Number({ exclusiveMinimum: 0, example: 49.99 }), + currency: t.Union([ + t.Literal("bam"), + t.Literal("bgn"), + t.Literal("chf"), + t.Literal("eur"), + t.Literal("gbp"), + t.Literal("nok"), + t.Literal("sek"), + ]), + promo_code: t.Optional( + t.Union([t.String({ example: "SUMMER20" }), t.Null()]) + ), + source: t.Union([cardPaymentSourceSchema, bankPaymentSourceSchema]), +}); + +export const bookingPaymentSchema = t.Object({ + id: t.String({ + format: "uuid", + example: "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a", + }), + amount: t.Number({ example: 49.99 }), + currency: t.String({ example: "gbp" }), + source: t.Union([cardPaymentSourceSchema, bankPaymentSourceSchema]), + status: t.Union([ + t.Literal("pending"), + t.Literal("succeeded"), + t.Literal("failed"), + ]), +}); + +export const linksSelfSchema = t.Object({ + self: t.String({ + format: "uri", + example: + "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb", + }), +}); + +export const linksPaginationSchema = t.Object({ + next: t.Optional( + t.String({ + format: "uri", + example: "https://api.example.com/bookings?page=2", + }) + ), + prev: t.Optional( + t.String({ + format: "uri", + example: "https://api.example.com/bookings?page=1", + }) + ), +}); + +export const problemSchema = t.Object({ + type: t.String({ example: "https://example.com/errors/not-found" }), + title: t.String({ example: "Not Found" }), + status: t.Number({ example: 404 }), + detail: t.String({ example: "The requested resource was not found." }), +}); + +export type Station = typeof stationSchema.static; +export type Trip = typeof tripSchema.static; +export type Booking = typeof bookingSchema.static; +export type CreateBookingRequest = typeof createBookingRequestSchema.static; +export type BookingPayment = typeof bookingPaymentSchema.static; +export type BookingPaymentRequest = typeof bookingPaymentRequestSchema.static; diff --git a/frameworks-elysia/tsconfig.json b/frameworks-elysia/tsconfig.json new file mode 100644 index 00000000..23be3eec --- /dev/null +++ b/frameworks-elysia/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "ES2022", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + "types": ["bun-types"], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/frameworks-laravel/README.md b/frameworks-laravel/README.md index 629437bc..69444f87 100644 --- a/frameworks-laravel/README.md +++ b/frameworks-laravel/README.md @@ -86,14 +86,22 @@ All endpoints are prefixed with `/api`. ## Generating API Documentation -Generate API documentation using Scribe: +This example uses [Scribe v5](https://scribe.knuckles.wtf/laravel/). Generate API documentation with: ```bash php artisan scribe:generate ``` ## OpenAPI -The API description is exported by [Scribe](https://scribe.knuckles.wtf/laravel/) and can be found in `./storage/app/private/scribe/openapi.yaml`. +The API description is exported by [Scribe](https://scribe.knuckles.wtf/laravel/) as OpenAPI v3.1 and can be found in `./storage/app/scribe/openapi.yaml`. + +OpenAPI version is configured in `config/scribe.php`: +```php +'openapi' => [ + 'enabled' => true, + 'version' => '3.1.0', +], +``` ## License diff --git a/frameworks-laravel/composer.json b/frameworks-laravel/composer.json index 98560483..cf27435e 100644 --- a/frameworks-laravel/composer.json +++ b/frameworks-laravel/composer.json @@ -13,7 +13,7 @@ }, "require-dev": { "fakerphp/faker": "^1.23", - "knuckleswtf/scribe": "^5.5", + "knuckleswtf/scribe": "^5.6", "laravel/pail": "^1.2.2", "laravel/pint": "^1.24", "laravel/sail": "^1.41", diff --git a/frameworks-laravel/config/scribe.php b/frameworks-laravel/config/scribe.php index 04a5b948..51926e33 100644 --- a/frameworks-laravel/config/scribe.php +++ b/frameworks-laravel/config/scribe.php @@ -146,13 +146,16 @@ ], ], - // Generate an OpenAPI spec (v3.0.1) in addition to docs webpage. + // Generate an OpenAPI spec (v3.1.x) in addition to docs webpage. // For 'static' docs, the collection will be generated to public/docs/openapi.yaml. // For 'laravel' docs, it will be generated to storage/app/scribe/openapi.yaml. // Setting `laravel.add_routes` to true (above) will also add a route for the spec. 'openapi' => [ 'enabled' => true, + // Set OpenAPI output version. + 'version' => '3.1.0', + 'overrides' => [ 'info.contact' => [ 'name' => 'API Support',