diff --git a/packages/cli/ete-tests/package.json b/packages/cli/ete-tests/package.json
index 199b00ca898..a67311c1f82 100644
--- a/packages/cli/ete-tests/package.json
+++ b/packages/cli/ete-tests/package.json
@@ -34,12 +34,15 @@
"@fern-api/logging-execa": "workspace:*",
"@fern-typescript/fetcher": "workspace:*",
"execa": "^5.1.1",
+ "express": "^4.20.0",
"js-yaml": "^4.1.0",
"node-fetch": "2.7.0",
+ "openapi-types": "^12.1.3",
"strip-ansi": "^7.1.0",
"tmp-promise": "^3.0.3"
},
"devDependencies": {
+ "@types/express": "^4.17.21",
"@types/jest": "^29.5.12",
"@types/js-yaml": "^4.0.8",
"@types/node": "18.7.18",
diff --git a/packages/cli/ete-tests/src/tests/generate/generate.test.ts b/packages/cli/ete-tests/src/tests/generate/generate.test.ts
index f144caa6c08..1ec0985eae4 100644
--- a/packages/cli/ete-tests/src/tests/generate/generate.test.ts
+++ b/packages/cli/ete-tests/src/tests/generate/generate.test.ts
@@ -3,10 +3,8 @@ import stripAnsi from "strip-ansi";
import { runFernCli } from "../../utils/runFernCli";
import { init } from "../init/init";
import { exec } from "child_process";
-import { CONSOLE_LOGGER } from "../../../../task-context/node_modules/@fern-api/logger/src";
const fixturesDir = join(AbsoluteFilePath.of(__dirname), RelativeFilePath.of("fixtures"));
-// const FIXTURES = ["docs"];
describe("fern generate", () => {
it("default api (fern init)", async () => {
@@ -50,7 +48,11 @@ describe("fern generate", () => {
);
}, 180_000);
- it("missing docs page", async () => {
+ // TODO: Re-enable this test if and when it doesn't require the user to be logged in.
+ // It's otherwise flaky on developer machines that haven't logged in with the fern CLI.
+ //
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip("missing docs page", async () => {
const { stdout } = await runFernCli(["generate", "--docs"], {
cwd: join(fixturesDir, RelativeFilePath.of("docs-missing-page")),
reject: false
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/__snapshots__/update-api.test.ts.snap b/packages/cli/ete-tests/src/tests/update-api-unioned/__snapshots__/update-api.test.ts.snap
deleted file mode 100644
index 1a7f41a12f6..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/__snapshots__/update-api.test.ts.snap
+++ /dev/null
@@ -1,797 +0,0 @@
-// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-
-exports[`fern api update unioned > fern api update unioned 1`] = `
-[
- {
- "contents": "default-group: local
-api:
- path: ./openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
-",
- "name": "generators.yml",
- "type": "file",
- },
- {
- "contents": "{
- "info": {
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- }
- },
- "servers": [
- {
- "url": "https://api.example.com",
- "description": "Production"
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\\nand local timezone.\\n"
- },
- {
- "name": "Train Tracks",
- "description": "Find and filter all the different rail roads available across Europe, including their location\\nand local timezone.\\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\\nand availability.\\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\\nand optional extras.\\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\\nstatus and history.\\n\\n> warn\\n> Bookings usually expire within 1 hour so you'll need to make your payment\\n> before the expiry date \\n"
- }
- ],
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
- "components": {
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "Paris Gare du Nord",
- "Berlin Hauptbahnhof"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "anyOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either \`individual\` or \`company\`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of \`pending\`, \`succeeded\`, or \`failed\`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a \`limit\` to\\nconvey the expiring limit, \`remaining\` to convey the remaining quota units,\\nand \`reset\` to convey the time window reset time.\\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \\nThe value is in seconds and can be an integer or a date in the future. \\nIf the value is an integer, it indicates the number of seconds to wait. \\nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \\n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}",
- "name": "openapi.json",
- "type": "file",
- },
-]
-`;
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/fern.config.json b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/fern.config.json
deleted file mode 100644
index 2e3e1df85fd..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/fern.config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "version": "*",
- "organization": "fern"
-}
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/generators.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/generators.yml
deleted file mode 100644
index cf0562dda16..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/generators.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-default-group: local
-api:
- path: ./openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/openapi.json b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/openapi.json
deleted file mode 100644
index 3a835787863..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec1/openapi.json
+++ /dev/null
@@ -1,778 +0,0 @@
-{
- "info": {
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- }
- },
- "servers": [
- {
- "url": "https://api.example.com",
- "description": "Production"
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Train Tracks",
- "description": "Find and filter all the different rail roads available across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\nand availability.\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\nand optional extras.\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\nstatus and history.\n\n> warn\n> Bookings usually expire within 1 hour so you'll need to make your payment\n> before the expiry date \n"
- }
- ],
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
- "components": {
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "Paris Gare du Nord",
- "Berlin Hauptbahnhof"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "anyOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either `individual` or `company`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of `pending`, `succeeded`, or `failed`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a `limit` to\nconvey the expiring limit, `remaining` to convey the remaining quota units,\nand `reset` to convey the time window reset time.\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \nThe value is in seconds and can be an integer or a date in the future. \nIf the value is an integer, it indicates the number of seconds to wait. \nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/generators.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/generators.yml
deleted file mode 100644
index cf0562dda16..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/generators.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-default-group: local
-api:
- path: ./openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/openapi.json b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/openapi.json
deleted file mode 100644
index a7705520202..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/spec2/openapi.json
+++ /dev/null
@@ -1,1435 +0,0 @@
-{
- "info": {
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- }
- },
- "servers": [
- {
- "url": "https://api.example.com",
- "description": "Production"
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Train Tracks",
- "description": "Find and filter all the different rail roads available across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\nand availability.\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\nand optional extras.\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\nstatus and history.\n\n> warn\n> Bookings usually expire within 1 hour so you'll need to make your payment\n> before the expiry date \n"
- }
- ],
- "paths": {
- "/trips": {
- "get": {
- "summary": "Get available train trips",
- "description": "Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.",
- "operationId": "get-trips",
- "tags": [
- "Trips"
- ],
- "parameters": [
- {
- "name": "origin",
- "in": "query",
- "description": "The ID of the origin station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- },
- {
- "name": "destination",
- "in": "query",
- "description": "The ID of the destination station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- },
- {
- "name": "date",
- "in": "query",
- "description": "The date and time of the trip in ISO 8601 format in origin station's timezone.",
- "required": true,
- "schema": {
- "type": "string",
- "format": "date-time"
- },
- "example": "2024-02-01T09:00:00Z"
- },
- {
- "name": "bicycles",
- "in": "query",
- "description": "Only return trips where bicycles are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- },
- {
- "name": "dogs",
- "in": "query",
- "description": "Only return trips where dogs are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A list of available train trips",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "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
- }
- ],
- "links": {
- "self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01",
- "next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "trips",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/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",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true
- },
- {
- "id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "passenger_name": "Jane Smith",
- "has_bicycle": false,
- "has_dog": false
- }
- ],
- "links": {
- "self": "https://api.example.com/bookings",
- "next": "https://api.example.com/bookings?page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "bookings",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "post": {
- "operationId": "create-booking",
- "summary": "Create a booking",
- "description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.",
- "tags": [
- "Bookings"
- ],
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- },
- "application/xml": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "Booking successful",
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "409": {
- "$ref": "#/components/responses/Conflict"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to retrieve.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "get": {
- "summary": "Get a booking",
- "description": "Returns the details of a specific booking.",
- "operationId": "get-booking",
- "tags": [
- "Bookings"
- ],
- "responses": {
- "200": {
- "description": "The booking details",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "delete": {
- "summary": "Delete a booking",
- "description": "Deletes a booking, cancelling the hold on the trip.",
- "operationId": "delete-booking",
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "tags": [
- "Bookings"
- ],
- "responses": {
- "204": {
- "description": "Booking deleted"
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}/payment": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to pay for.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "post": {
- "summary": "Pay for a Booking",
- "description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.",
- "operationId": "create-booking-payment",
- "tags": [
- "Payments"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/BookingPayment"
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "4242424242424242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_line1": "123 Fake Street",
- "address_line2": "4th Floor",
- "address_city": "London",
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "number": "00012345",
- "sort_code": "000123",
- "account_type": "individual",
- "bank_name": "Starling Bank",
- "country": "gb"
- }
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Payment successful",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/BookingPayment"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Booking"
- }
- }
- }
- ]
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "************4242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "account_type": "individual",
- "number": "*********2345",
- "sort_code": "000123",
- "bank_name": "Starling Bank",
- "country": "gb"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- }
- },
- "components": {
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "Paris Gare du Nord",
- "Berlin Hauptbahnhof"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "anyOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either `individual` or `company`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of `pending`, `succeeded`, or `failed`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a `limit` to\nconvey the expiring limit, `remaining` to convey the remaining quota units,\nand `reset` to convey the time window reset time.\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \nThe value is in seconds and can be an integer or a date in the future. \nIf the value is an integer, it indicates the number of seconds to wait. \nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/api.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/api.yml
deleted file mode 100644
index a939faab6cf..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/api.yml
+++ /dev/null
@@ -1 +0,0 @@
-name: api
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec1/__package__.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec1/__package__.yml
deleted file mode 100644
index 7e022f0d628..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec1/__package__.yml
+++ /dev/null
@@ -1 +0,0 @@
-export: spec1
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec2/__package__.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec2/__package__.yml
deleted file mode 100644
index aad3c796b2f..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/definition/spec2/__package__.yml
+++ /dev/null
@@ -1 +0,0 @@
-export: spec2
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/dependencies.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/dependencies.yml
deleted file mode 100644
index 45e0bfea97e..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/dependencies.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-dependencies:
- spec1: ../spec1
- spec2: ../spec2
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/generators.yml b/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/generators.yml
deleted file mode 100644
index c8ae78dfffa..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/fixtures/fern/unioned/generators.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-default-group: local
-groups:
- local:
- generators:
- - name: fernapi/fern-typescript-node-sdk
- version: 0.9.5
- output:
- location: local-file-system
- path: ../sdks/typescript
diff --git a/packages/cli/ete-tests/src/tests/update-api-unioned/update-api.test.ts b/packages/cli/ete-tests/src/tests/update-api-unioned/update-api.test.ts
deleted file mode 100644
index dcb813457d3..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-unioned/update-api.test.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { AbsoluteFilePath, getDirectoryContents, getDirectoryContentsForSnapshot } from "@fern-api/fs-utils";
-import { cp } from "fs/promises";
-import path from "path";
-import tmp from "tmp-promise";
-import { runFernCli } from "../../utils/runFernCli";
-
-const FIXTURES_DIR = path.join(__dirname, "fixtures");
-
-describe("fern api update unioned", () => {
- it("fern api update unioned", async () => {
- // Create tmpdir and copy contents
- const tmpDir = await tmp.dir();
- const directory = AbsoluteFilePath.of(tmpDir.path);
-
- await cp(FIXTURES_DIR, directory, { recursive: true });
-
- const outputPath = AbsoluteFilePath.of(path.join(directory, "fern", "spec1"));
-
- await runFernCli(["api", "update"], {
- cwd: directory
- });
-
- expect(await getDirectoryContentsForSnapshot(outputPath)).toMatchSnapshot();
- }, 60_000);
-});
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/__snapshots__/update-api.test.ts.snap b/packages/cli/ete-tests/src/tests/update-api-v2/__snapshots__/update-api.test.ts.snap
deleted file mode 100644
index c74de106748..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/__snapshots__/update-api.test.ts.snap
+++ /dev/null
@@ -1,1797 +0,0 @@
-// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-
-exports[`fern api update unioned > fern api update unioned 1`] = `
-[
- {
- "contents": "{
- "openapi": "3.1.0",
- "info": {
- "title": "Train Travel API",
- "description": "API for finding and booking train trips across Europe.\\n\\n## Run in Postman\\n\\nExperiment with this API in Postman, using our Postman Collection.\\n\\n[![Run In Postman](https://run.pstmn.io/button.svg =128pxx32px)](https://app.getpostman.com/run-collection/9265903-7a75a0d0-b108-4436-ba54-c6139698dc08?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D9265903-7a75a0d0-b108-4436-ba54-c6139698dc08%26entityType%3Dcollection%26workspaceId%3Df507f69d-9564-419c-89a2-cb8e4c8c7b8f)\\n",
- "version": "1.0.0",
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- },
- "x-feedbackLink": {
- "label": "Submit Feedback",
- "url": "https://github.com/bump-sh-examples/train-travel-api/issues/new"
- }
- },
- "servers": [
- {
- "url": "https://try.microcks.io/rest/Train+Travel+API/1.0.0",
- "description": "Mock Server",
- "x-internal": false
- },
- {
- "url": "https://api.example.com",
- "description": "Production",
- "x-internal": false
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\\nand local timezone.\\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\\nand availability.\\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\\nand optional extras.\\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\\nstatus and history.\\n\\n> warn\\n> Bookings usually expire within 1 hour so you'll need to make your payment\\n> before the expiry date \\n"
- }
- ],
- "paths": {
- "/stations": {
- "get": {
- "summary": "Get a list of train stations",
- "description": "Returns a paginated and searchable list of all train stations.",
- "operationId": "get-stations",
- "tags": [
- "Stations"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- },
- {
- "name": "coordinates",
- "in": "query",
- "description": "The latitude and longitude of the user's location, to narrow down the search results to sites within a proximity of this location.\\n",
- "required": false,
- "schema": {
- "type": "string"
- },
- "example": "52.5200,13.4050"
- },
- {
- "name": "search",
- "in": "query",
- "description": "A search term to filter the list of stations by name or address.\\n",
- "required": false,
- "schema": {
- "type": "string",
- "examples": [
- "Milano Centrale",
- "Paris"
- ]
- }
- },
- {
- "name": "country",
- "in": "query",
- "description": "Filter stations by country code",
- "required": false,
- "schema": {
- "type": "string",
- "format": "iso-country-code"
- },
- "example": "DE"
- }
- ],
- "responses": {
- "200": {
- "description": "OK",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "name": "Berlin Hauptbahnhof",
- "address": "Invalidenstraße 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"
- }
- ],
- "links": {
- "self": "https://api.example.com/stations&page=2",
- "next": "https://api.example.com/stations?page=3",
- "prev": "https://api.example.com/stations?page=1"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "stations",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/trips": {
- "get": {
- "summary": "Get available train trips",
- "description": "Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.\\n",
- "operationId": "get-trips",
- "tags": [
- "Trips"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- },
- {
- "name": "origin",
- "in": "query",
- "description": "The ID of the origin station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- },
- {
- "name": "destination",
- "in": "query",
- "description": "The ID of the destination station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- },
- {
- "name": "date",
- "in": "query",
- "description": "The date and time of the trip in ISO 8601 format in origin station's timezone.",
- "required": true,
- "schema": {
- "type": "string",
- "format": "date-time"
- },
- "example": "2024-02-01T09:00:00Z"
- },
- {
- "name": "bicycles",
- "in": "query",
- "description": "Only return trips where bicycles are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- },
- {
- "name": "dogs",
- "in": "query",
- "description": "Only return trips where dogs are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A list of available train trips",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "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
- }
- ],
- "links": {
- "self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01",
- "next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "trips",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings": {
- "get": {
- "operationId": "get-bookings",
- "summary": "List existing bookings",
- "description": "Returns a list of all trip bookings by the authenticated user.",
- "tags": [
- "Bookings"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- }
- ],
- "responses": {
- "200": {
- "description": "A list of bookings",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true
- },
- {
- "id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "passenger_name": "Jane Smith",
- "has_bicycle": false,
- "has_dog": false
- }
- ],
- "links": {
- "self": "https://api.example.com/bookings",
- "next": "https://api.example.com/bookings?page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "bookings",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "post": {
- "operationId": "create-booking",
- "summary": "Create a booking",
- "description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.",
- "tags": [
- "Bookings"
- ],
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- },
- "application/xml": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "Booking successful",
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "409": {
- "$ref": "#/components/responses/Conflict"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to retrieve.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "get": {
- "summary": "Get a booking",
- "description": "Returns the details of a specific booking.",
- "operationId": "get-booking",
- "tags": [
- "Bookings"
- ],
- "responses": {
- "200": {
- "description": "The booking details",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "delete": {
- "summary": "Delete a booking",
- "description": "Deletes a booking, cancelling the hold on the trip.",
- "operationId": "delete-booking",
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "tags": [
- "Bookings"
- ],
- "responses": {
- "204": {
- "description": "Booking deleted"
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}/payment": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to pay for.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "post": {
- "summary": "Pay for a Booking",
- "description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.",
- "operationId": "create-booking-payment",
- "tags": [
- "Payments"
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/BookingPayment"
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "4242424242424242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_line1": "123 Fake Street",
- "address_line2": "4th Floor",
- "address_city": "London",
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "number": "00012345",
- "sort_code": "000123",
- "account_type": "individual",
- "bank_name": "Starling Bank",
- "country": "gb"
- }
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Payment successful",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/BookingPayment"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Booking"
- }
- }
- }
- ]
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "************4242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "account_type": "individual",
- "number": "*********2345",
- "sort_code": "000123",
- "bank_name": "Starling Bank",
- "country": "gb"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- }
- },
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
- "components": {
- "parameters": {
- "page": {
- "name": "page",
- "in": "query",
- "description": "The page number to return",
- "required": false,
- "schema": {
- "type": "integer",
- "minimum": 1,
- "default": 1
- },
- "example": 1
- },
- "limit": {
- "name": "limit",
- "in": "query",
- "description": "The number of items to return per page",
- "required": false,
- "schema": {
- "type": "integer",
- "minimum": 1,
- "maximum": 100,
- "default": 10
- },
- "example": 10
- }
- },
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Problem": {
- "type": "object",
- "xml": {
- "name": "problem",
- "namespace": "urn:ietf:rfc:7807"
- },
- "properties": {
- "type": {
- "type": "string",
- "description": "A URI reference that identifies the problem type",
- "examples": [
- "https://example.com/probs/out-of-credit"
- ]
- },
- "title": {
- "type": "string",
- "description": "A short, human-readable summary of the problem type",
- "examples": [
- "You do not have enough credit."
- ]
- },
- "detail": {
- "type": "string",
- "description": "A human-readable explanation specific to this occurrence of the problem",
- "examples": [
- "Your current balance is 30, but that costs 50."
- ]
- },
- "instance": {
- "type": "string",
- "description": "A URI reference that identifies the specific occurrence of the problem",
- "examples": [
- "/account/12345/msgs/abc"
- ]
- },
- "status": {
- "type": "integer",
- "description": "The HTTP status code",
- "examples": [
- 400
- ]
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "oneOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "type": "object",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either \`individual\` or \`company\`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of \`pending\`, \`succeeded\`, or \`failed\`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "Cache-Control": {
- "description": "The Cache-Control header communicates directives for caching mechanisms in both requests and responses. \\nIt is used to specify the caching directives in responses to prevent caches from storing sensitive information.\\n",
- "schema": {
- "type": "string",
- "description": "A comma-separated list of directives as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html).",
- "examples": [
- "max-age=3600",
- "max-age=604800, public",
- "no-store",
- "no-cache",
- "private"
- ]
- }
- },
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a \`limit\` to\\nconvey the expiring limit, \`remaining\` to convey the remaining quota units,\\nand \`reset\` to convey the time window reset time.\\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \\nThe value is in seconds and can be an integer or a date in the future. \\nIf the value is an integer, it indicates the number of seconds to wait. \\nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \\n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}",
- "name": "openapi.json",
- "type": "file",
- },
-]
-`;
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/fern.config.json b/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/fern.config.json
deleted file mode 100644
index 2e3e1df85fd..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/fern.config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "version": "*",
- "organization": "fern"
-}
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/generators.yml b/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/generators.yml
deleted file mode 100644
index 53695c89415..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/generators.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-default-group: local
-
-api:
- specs:
- - openapi: ./spec1/openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
- - openapi: ./spec2/openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
-
-groups:
- local:
- generators:
- - name: fernapi/fern-typescript-node-sdk
- version: 0.9.5
- output:
- location: local-file-system
- path: ../sdks/typescript
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec1/openapi.json b/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec1/openapi.json
deleted file mode 100644
index 97cfa9cecb8..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec1/openapi.json
+++ /dev/null
@@ -1,1673 +0,0 @@
-{
- "openapi": "3.1.0",
- "info": {
- "title": "Train Travel API",
- "description": "API for finding and booking train trips across Europe.\n\n## Run in Postman\n\nExperiment with this API in Postman, using our Postman Collection.\n\n[](https://app.getpostman.com/run-collection/9265903-7a75a0d0-b108-4436-ba54-c6139698dc08?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D9265903-7a75a0d0-b108-4436-ba54-c6139698dc08%26entityType%3Dcollection%26workspaceId%3Df507f69d-9564-419c-89a2-cb8e4c8c7b8f)\n",
- "version": "1.0.0",
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- },
- "x-feedbackLink": {
- "label": "Submit Feedback",
- "url": "https://github.com/bump-sh-examples/train-travel-api/issues/new"
- }
- },
- "servers": [
- {
- "url": "https://api.example.com",
- "description": "Production"
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\nand availability.\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\nand optional extras.\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\nstatus and history.\n\n> warn\n> Bookings usually expire within 1 hour so you'll need to make your payment\n> before the expiry date \n"
- }
- ],
- "paths": {
- "/stations": {
- "get": {
- "summary": "Get a list of train stations",
- "description": "Returns a paginated and searchable list of all train stations.",
- "operationId": "get-stations",
- "tags": [
- "Stations"
- ],
- "parameters": [
- {
- "name": "page",
- "in": "query",
- "description": "The page number to return",
- "required": false,
- "schema": {
- "type": "integer",
- "minimum": 1,
- "default": 1
- },
- "example": 1
- },
- {
- "name": "coordinates",
- "in": "query",
- "description": "The latitude and longitude of the user's location, to narrow down the search results to sites within a proximity of this location.\n",
- "required": false,
- "schema": {
- "type": "string"
- },
- "example": "52.5200,13.4050"
- },
- {
- "name": "search",
- "in": "query",
- "description": "A search term to filter the list of stations by name or address.\n",
- "required": false,
- "schema": {
- "type": "string",
- "examples": [
- "Milano Centrale",
- "Paris"
- ]
- }
- }
- ],
- "responses": {
- "200": {
- "description": "OK",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "name": "Berlin Hauptbahnhof",
- "address": "Invalidenstraße 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"
- }
- ],
- "links": {
- "self": "https://api.example.com/stations&page=2",
- "next": "https://api.example.com/stations?page=3",
- "prev": "https://api.example.com/stations?page=1"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "stations",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/trips": {
- "get": {
- "summary": "Get available train trips",
- "description": "Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.\n",
- "operationId": "get-trips",
- "tags": [
- "Trips"
- ],
- "parameters": [
- {
- "name": "origin",
- "in": "query",
- "description": "The ID of the origin station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- },
- {
- "name": "destination",
- "in": "query",
- "description": "The ID of the destination station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- },
- {
- "name": "date",
- "in": "query",
- "description": "The date and time of the trip in ISO 8601 format in origin station's timezone.",
- "required": true,
- "schema": {
- "type": "string",
- "format": "date-time"
- },
- "example": "2024-02-01T09:00:00Z"
- },
- {
- "name": "bicycles",
- "in": "query",
- "description": "Only return trips where bicycles are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- },
- {
- "name": "dogs",
- "in": "query",
- "description": "Only return trips where dogs are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A list of available train trips",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "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
- }
- ],
- "links": {
- "self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01",
- "next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "trips",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/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",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true
- },
- {
- "id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "passenger_name": "Jane Smith",
- "has_bicycle": false,
- "has_dog": false
- }
- ],
- "links": {
- "self": "https://api.example.com/bookings",
- "next": "https://api.example.com/bookings?page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "bookings",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "post": {
- "operationId": "create-booking",
- "summary": "Create a booking",
- "description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.",
- "tags": [
- "Bookings"
- ],
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- },
- "application/xml": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "Booking successful",
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "409": {
- "$ref": "#/components/responses/Conflict"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to retrieve.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "get": {
- "summary": "Get a booking",
- "description": "Returns the details of a specific booking.",
- "operationId": "get-booking",
- "tags": [
- "Bookings"
- ],
- "responses": {
- "200": {
- "description": "The booking details",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "delete": {
- "summary": "Delete a booking",
- "description": "Deletes a booking, cancelling the hold on the trip.",
- "operationId": "delete-booking",
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "tags": [
- "Bookings"
- ],
- "responses": {
- "204": {
- "description": "Booking deleted"
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}/payment": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to pay for.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "post": {
- "summary": "Pay for a Booking",
- "description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.",
- "operationId": "create-booking-payment",
- "tags": [
- "Payments"
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/BookingPayment"
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "4242424242424242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_line1": "123 Fake Street",
- "address_line2": "4th Floor",
- "address_city": "London",
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "number": "00012345",
- "sort_code": "000123",
- "account_type": "individual",
- "bank_name": "Starling Bank",
- "country": "gb"
- }
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Payment successful",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/BookingPayment"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Booking"
- }
- }
- }
- ]
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "************4242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "account_type": "individual",
- "number": "*********2345",
- "sort_code": "000123",
- "bank_name": "Starling Bank",
- "country": "gb"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- }
- },
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
- "components": {
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Problem": {
- "xml": {
- "name": "problem",
- "namespace": "urn:ietf:rfc:7807"
- },
- "properties": {
- "type": {
- "type": "string",
- "description": "A URI reference that identifies the problem type",
- "example": "https://example.com/probs/out-of-credit"
- },
- "title": {
- "type": "string",
- "description": "A short, human-readable summary of the problem type",
- "example": "You do not have enough credit."
- },
- "detail": {
- "type": "string",
- "description": "A human-readable explanation specific to this occurrence of the problem",
- "example": "Your current balance is 30, but that costs 50."
- },
- "instance": {
- "type": "string",
- "description": "A URI reference that identifies the specific occurrence of the problem",
- "example": "/account/12345/msgs/abc"
- },
- "status": {
- "type": "integer",
- "description": "The HTTP status code",
- "example": 400
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "Paris Gare du Nord",
- "Berlin Hauptbahnhof"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "anyOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either `individual` or `company`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of `pending`, `succeeded`, or `failed`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a `limit` to\nconvey the expiring limit, `remaining` to convey the remaining quota units,\nand `reset` to convey the time window reset time.\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \nThe value is in seconds and can be an integer or a date in the future. \nIf the value is an integer, it indicates the number of seconds to wait. \nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec2/openapi.json b/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec2/openapi.json
deleted file mode 100644
index ecaa3eed856..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/fixtures/fern/spec2/openapi.json
+++ /dev/null
@@ -1,1329 +0,0 @@
-{
- "info": {
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- }
- },
- "servers": [
- {
- "url": "https://api.example.com",
- "description": "Production"
- }
- ],
- "security": [
- {
- "OAuth2": ["read"]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Train Tracks",
- "description": "Find and filter all the different rail roads available across Europe, including their location\nand local timezone.\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\nand availability.\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\nand optional extras.\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\nstatus and history.\n\n> warn\n> Bookings usually expire within 1 hour so you'll need to make your payment\n> before the expiry date \n"
- }
- ],
- "paths": {
- "/trips": {
- "get": {
- "summary": "Get available train trips",
- "description": "Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.",
- "operationId": "get-trips",
- "tags": ["Trips"],
- "parameters": [
- {
- "name": "origin",
- "in": "query",
- "description": "The ID of the origin station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- },
- {
- "name": "destination",
- "in": "query",
- "description": "The ID of the destination station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- },
- {
- "name": "date",
- "in": "query",
- "description": "The date and time of the trip in ISO 8601 format in origin station's timezone.",
- "required": true,
- "schema": {
- "type": "string",
- "format": "date-time"
- },
- "example": "2024-02-01T09:00:00Z"
- },
- {
- "name": "bicycles",
- "in": "query",
- "description": "Only return trips where bicycles are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- },
- {
- "name": "dogs",
- "in": "query",
- "description": "Only return trips where dogs are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- }
- ],
- "responses": {
- "200": {
- "description": "A list of available train trips",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "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
- }
- ],
- "links": {
- "self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01",
- "next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "trips",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/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",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true
- },
- {
- "id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "passenger_name": "Jane Smith",
- "has_bicycle": false,
- "has_dog": false
- }
- ],
- "links": {
- "self": "https://api.example.com/bookings",
- "next": "https://api.example.com/bookings?page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "bookings",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "post": {
- "operationId": "create-booking",
- "summary": "Create a booking",
- "description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.",
- "tags": ["Bookings"],
- "security": [
- {
- "OAuth2": ["write"]
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- },
- "application/xml": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "Booking successful",
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "409": {
- "$ref": "#/components/responses/Conflict"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to retrieve.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "get": {
- "summary": "Get a booking",
- "description": "Returns the details of a specific booking.",
- "operationId": "get-booking",
- "tags": ["Bookings"],
- "responses": {
- "200": {
- "description": "The booking details",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "delete": {
- "summary": "Delete a booking",
- "description": "Deletes a booking, cancelling the hold on the trip.",
- "operationId": "delete-booking",
- "security": [
- {
- "OAuth2": ["write"]
- }
- ],
- "tags": ["Bookings"],
- "responses": {
- "204": {
- "description": "Booking deleted"
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}/payment": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to pay for.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "post": {
- "summary": "Pay for a Booking",
- "description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.",
- "operationId": "create-booking-payment",
- "tags": ["Payments"],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/BookingPayment"
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "4242424242424242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_line1": "123 Fake Street",
- "address_line2": "4th Floor",
- "address_city": "London",
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "number": "00012345",
- "sort_code": "000123",
- "account_type": "individual",
- "bank_name": "Starling Bank",
- "country": "gb"
- }
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Payment successful",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/BookingPayment"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Booking"
- }
- }
- }
- ]
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "************4242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "account_type": "individual",
- "number": "*********2345",
- "sort_code": "000123",
- "bank_name": "Starling Bank",
- "country": "gb"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- }
- },
- "components": {
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": ["id", "name", "address", "country_code"],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": ["efdbb9d1-02c2-4bc3-afb7-6788d8782b1e", "b2e783e1-c824-4d63-b37a-d8d698862f1d"]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": ["Berlin Hauptbahnhof", "Paris Gare du Nord"]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": ["Invalidenstraße 10557 Berlin, Germany", "18 Rue de Dunkerque 75010 Paris, France"]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": ["DE", "FR"]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": ["Europe/Berlin", "Europe/Paris"]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": ["4f4e4e1-c824-4d63-b37a-d8d698862f1d"]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": ["Berlin Hauptbahnhof", "Paris Gare du Nord"]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": ["Paris Gare du Nord", "Berlin Hauptbahnhof"]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": ["2024-02-01T10:00:00Z"]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": ["2024-02-01T16:00:00Z"]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": ["Deutsche Bahn", "SNCF"]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [50]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": ["3f3e3e1-c824-4d63-b37a-d8d698862f1d"]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": ["4f4e4e1-c824-4d63-b37a-d8d698862f1d"]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": ["John Doe"]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [49.99]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": ["bam", "bgn", "chf", "eur", "gbp", "nok", "sek", "try"]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "anyOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": ["Francis Bourgeois"]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": ["4242424242424242"]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [12]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [2025]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": ["name", "number", "cvc", "exp_month", "exp_year", "address_country"]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": ["individual", "company"],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either `individual` or `company`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": ["Starling Bank"]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": ["name", "number", "account_type", "bank_name", "country"]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of `pending`, `succeeded`, or `failed`.",
- "type": "string",
- "enum": ["pending", "succeeded", "failed"],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": ["https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"]
- }
- }
- }
- },
- "headers": {
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a `limit` to\nconvey the expiring limit, `remaining` to convey the remaining quota units,\nand `reset` to convey the time window reset time.\n",
- "schema": {
- "type": "string",
- "examples": ["limit=10, remaining=0, reset=10"]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \nThe value is in seconds and can be an integer or a date in the future. \nIf the value is an integer, it indicates the number of seconds to wait. \nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- }
- }
- }
- }
- }
-}
diff --git a/packages/cli/ete-tests/src/tests/update-api-v2/update-api.test.ts b/packages/cli/ete-tests/src/tests/update-api-v2/update-api.test.ts
deleted file mode 100644
index dcb813457d3..00000000000
--- a/packages/cli/ete-tests/src/tests/update-api-v2/update-api.test.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { AbsoluteFilePath, getDirectoryContents, getDirectoryContentsForSnapshot } from "@fern-api/fs-utils";
-import { cp } from "fs/promises";
-import path from "path";
-import tmp from "tmp-promise";
-import { runFernCli } from "../../utils/runFernCli";
-
-const FIXTURES_DIR = path.join(__dirname, "fixtures");
-
-describe("fern api update unioned", () => {
- it("fern api update unioned", async () => {
- // Create tmpdir and copy contents
- const tmpDir = await tmp.dir();
- const directory = AbsoluteFilePath.of(tmpDir.path);
-
- await cp(FIXTURES_DIR, directory, { recursive: true });
-
- const outputPath = AbsoluteFilePath.of(path.join(directory, "fern", "spec1"));
-
- await runFernCli(["api", "update"], {
- cwd: directory
- });
-
- expect(await getDirectoryContentsForSnapshot(outputPath)).toMatchSnapshot();
- }, 60_000);
-});
diff --git a/packages/cli/ete-tests/src/tests/update-api/__snapshots__/update-api.test.ts.snap b/packages/cli/ete-tests/src/tests/update-api/__snapshots__/update-api.test.ts.snap
index caf63fbb409..bc1d3b57b55 100644
--- a/packages/cli/ete-tests/src/tests/update-api/__snapshots__/update-api.test.ts.snap
+++ b/packages/cli/ete-tests/src/tests/update-api/__snapshots__/update-api.test.ts.snap
@@ -4,1794 +4,92 @@ exports[`fern api update > fern api update 1`] = `
[
{
"contents": "{
- "openapi": "3.1.0",
+ "version": "*",
+ "organization": "fern"
+}",
+ "name": "fern.config.json",
+ "type": "file",
+ },
+ {
+ "contents": "default-group: local
+api:
+ path: ./openapi/openapi.json
+ origin: http://localhost:4567/openapi.json
+groups:
+ local:
+ generators:
+ - name: fernapi/fern-typescript-node-sdk
+ version: 0.9.5
+ output:
+ location: local-file-system
+ path: ../sdks/typescript",
+ "name": "generators.yml",
+ "type": "file",
+ },
+ {
+ "contents": [
+ {
+ "contents": "{
+ "openapi": "3.0.0",
"info": {
- "title": "Train Travel API",
- "description": "API for finding and booking train trips across Europe.\\n\\n## Run in Postman\\n\\nExperiment with this API in Postman, using our Postman Collection.\\n\\n[![Run In Postman](https://run.pstmn.io/button.svg =128pxx32px)](https://app.getpostman.com/run-collection/9265903-7a75a0d0-b108-4436-ba54-c6139698dc08?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D9265903-7a75a0d0-b108-4436-ba54-c6139698dc08%26entityType%3Dcollection%26workspaceId%3Df507f69d-9564-419c-89a2-cb8e4c8c7b8f)\\n",
- "version": "1.0.0",
- "contact": {
- "name": "Train Support",
- "url": "https://example.com/support",
- "email": "support@example.com"
- },
- "license": {
- "name": "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International",
- "identifier": "CC-BY-NC-SA-4.0"
- },
- "x-feedbackLink": {
- "label": "Submit Feedback",
- "url": "https://github.com/bump-sh-examples/train-travel-api/issues/new"
- }
+ "title": "Test API",
+ "version": "1.0.0"
},
- "servers": [
- {
- "url": "https://try.microcks.io/rest/Train+Travel+API/1.0.0",
- "description": "Mock Server",
- "x-internal": false
- },
- {
- "url": "https://api.example.com",
- "description": "Production",
- "x-internal": false
- }
- ],
- "security": [
- {
- "OAuth2": [
- "read"
- ]
- }
- ],
- "x-topics": [
- {
- "title": "Getting started",
- "content": {
- "$ref": "./docs/getting-started.md"
- }
- }
- ],
- "tags": [
- {
- "name": "Stations",
- "description": "Find and filter train stations across Europe, including their location\\nand local timezone.\\n"
- },
- {
- "name": "Trips",
- "description": "Timetables and routes for train trips between stations, including pricing\\nand availability.\\n"
- },
- {
- "name": "Bookings",
- "description": "Create and manage bookings for train trips, including passenger details\\nand optional extras.\\n"
- },
- {
- "name": "Payments",
- "description": "Pay for bookings using a card or bank account, and view payment\\nstatus and history.\\n\\n> warn\\n> Bookings usually expire within 1 hour so you'll need to make your payment\\n> before the expiry date \\n"
- }
- ],
"paths": {
- "/stations": {
+ "/testdata": {
"get": {
- "summary": "Get a list of train stations",
- "description": "Returns a paginated and searchable list of all train stations.",
- "operationId": "get-stations",
- "tags": [
- "Stations"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- },
- {
- "name": "coordinates",
- "in": "query",
- "description": "The latitude and longitude of the user's location, to narrow down the search results to sites within a proximity of this location.\\n",
- "required": false,
- "schema": {
- "type": "string"
- },
- "example": "52.5200,13.4050"
- },
- {
- "name": "search",
- "in": "query",
- "description": "A search term to filter the list of stations by name or address.\\n",
- "required": false,
- "schema": {
- "type": "string",
- "examples": [
- "Milano Centrale",
- "Paris"
- ]
- }
- },
- {
- "name": "country",
- "in": "query",
- "description": "Filter stations by country code",
- "required": false,
- "schema": {
- "type": "string",
- "format": "iso-country-code"
- },
- "example": "DE"
- }
- ],
+ "summary": "Retrieve test data",
+ "operationId": "getTestData",
"responses": {
"200": {
- "description": "OK",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
+ "description": "Successful response",
"content": {
"application/json": {
"schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "name": "Berlin Hauptbahnhof",
- "address": "Invalidenstraße 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"
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
}
- ],
- "links": {
- "self": "https://api.example.com/stations&page=2",
- "next": "https://api.example.com/stations?page=3",
- "prev": "https://api.example.com/stations?page=1"
}
}
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "stations",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Station"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
}
}
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
}
}
}
},
- "/trips": {
+ "/filtered": {
"get": {
- "summary": "Get available train trips",
- "description": "Returns a list of available train trips between the specified origin and destination stations on the given date, and allows for filtering by bicycle and dog allowances.\\n",
- "operationId": "get-trips",
- "tags": [
- "Trips"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- },
- {
- "name": "origin",
- "in": "query",
- "description": "The ID of the origin station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- },
- {
- "name": "destination",
- "in": "query",
- "description": "The ID of the destination station",
- "required": true,
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- },
- {
- "name": "date",
- "in": "query",
- "description": "The date and time of the trip in ISO 8601 format in origin station's timezone.",
- "required": true,
- "schema": {
- "type": "string",
- "format": "date-time"
- },
- "example": "2024-02-01T09:00:00Z"
- },
- {
- "name": "bicycles",
- "in": "query",
- "description": "Only return trips where bicycles are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- },
- {
- "name": "dogs",
- "in": "query",
- "description": "Only return trips where dogs are known to be allowed",
- "required": false,
- "schema": {
- "type": "boolean",
- "default": false
- }
- }
- ],
+ "summary": "This endpoint should be filtered out",
+ "operationId": "filtered",
"responses": {
"200": {
- "description": "A list of available train trips",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
+ "description": "Successful response",
"content": {
"application/json": {
"schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string"
}
- ]
- },
- "example": {
- "data": [
- {
- "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
- }
- ],
- "links": {
- "self": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01",
- "next": "https://api.example.com/trips?origin=efdbb9d1-02c2-4bc3-afb7-6788d8782b1e&destination=b2e783e1-c824-4d63-b37a-d8d698862f1d&date=2024-02-01&page=2"
}
}
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "trips",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Trip"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
}
}
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings": {
- "get": {
- "operationId": "get-bookings",
- "summary": "List existing bookings",
- "description": "Returns a list of all trip bookings by the authenticated user.",
- "tags": [
- "Bookings"
- ],
- "parameters": [
- {
- "$ref": "#/components/parameters/page"
- },
- {
- "$ref": "#/components/parameters/limit"
- }
- ],
- "responses": {
- "200": {
- "description": "A list of bookings",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "data": [
- {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true
- },
- {
- "id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "trip_id": "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "passenger_name": "Jane Smith",
- "has_bicycle": false,
- "has_dog": false
- }
- ],
- "links": {
- "self": "https://api.example.com/bookings",
- "next": "https://api.example.com/bookings?page=2"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Wrapper-Collection"
- },
- {
- "properties": {
- "data": {
- "type": "array",
- "xml": {
- "name": "bookings",
- "wrapped": true
- },
- "items": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "post": {
- "operationId": "create-booking",
- "summary": "Create a booking",
- "description": "A booking is a temporary hold on a trip. It is not confirmed until the payment is processed.",
- "tags": [
- "Bookings"
- ],
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- },
- "application/xml": {
- "schema": {
- "$ref": "#/components/schemas/Booking"
- }
- }
- }
- },
- "responses": {
- "201": {
- "description": "Booking successful",
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "409": {
- "$ref": "#/components/responses/Conflict"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to retrieve.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "get": {
- "summary": "Get a booking",
- "description": "Returns the details of a specific booking.",
- "operationId": "get-booking",
- "tags": [
- "Bookings"
- ],
- "responses": {
- "200": {
- "description": "The booking details",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- },
- "application/xml": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Self"
- }
- }
- }
- ]
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- },
- "delete": {
- "summary": "Delete a booking",
- "description": "Deletes a booking, cancelling the hold on the trip.",
- "operationId": "delete-booking",
- "security": [
- {
- "OAuth2": [
- "write"
- ]
- }
- ],
- "tags": [
- "Bookings"
- ],
- "responses": {
- "204": {
- "description": "Booking deleted"
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "404": {
- "$ref": "#/components/responses/NotFound"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- },
- "/bookings/{bookingId}/payment": {
- "parameters": [
- {
- "name": "bookingId",
- "in": "path",
- "required": true,
- "description": "The ID of the booking to pay for.",
- "schema": {
- "type": "string",
- "format": "uuid"
- },
- "example": "1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- ],
- "post": {
- "summary": "Pay for a Booking",
- "description": "A payment is an attempt to pay for the booking, which will confirm the booking for the user and enable them to get their tickets.",
- "operationId": "create-booking-payment",
- "tags": [
- "Payments"
- ],
- "requestBody": {
- "required": true,
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/BookingPayment"
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "4242424242424242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_line1": "123 Fake Street",
- "address_line2": "4th Floor",
- "address_city": "London",
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "number": "00012345",
- "sort_code": "000123",
- "account_type": "individual",
- "bank_name": "Starling Bank",
- "country": "gb"
- }
- }
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Payment successful",
- "headers": {
- "Cache-Control": {
- "$ref": "#/components/headers/Cache-Control"
- },
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/BookingPayment"
- },
- {
- "properties": {
- "links": {
- "$ref": "#/components/schemas/Links-Booking"
- }
- }
- }
- ]
- },
- "examples": {
- "Card": {
- "summary": "Card Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 49.99,
- "currency": "gbp",
- "source": {
- "object": "card",
- "name": "J. Doe",
- "number": "************4242",
- "cvc": 123,
- "exp_month": 12,
- "exp_year": 2025,
- "address_country": "gb",
- "address_post_code": "N12 9XX"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb/payment"
- }
- }
- },
- "Bank": {
- "summary": "Bank Account Payment",
- "value": {
- "id": "2e3b4f5a-6b7c-8d9e-0f1a-2b3c4d5e6f7a",
- "amount": 100.5,
- "currency": "gbp",
- "source": {
- "object": "bank_account",
- "name": "J. Doe",
- "account_type": "individual",
- "number": "*********2345",
- "sort_code": "000123",
- "bank_name": "Starling Bank",
- "country": "gb"
- },
- "status": "succeeded",
- "links": {
- "booking": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- }
- }
- },
- "400": {
- "$ref": "#/components/responses/BadRequest"
- },
- "401": {
- "$ref": "#/components/responses/Unauthorized"
- },
- "403": {
- "$ref": "#/components/responses/Forbidden"
- },
- "429": {
- "$ref": "#/components/responses/TooManyRequests"
- },
- "500": {
- "$ref": "#/components/responses/InternalServerError"
- }
- }
- }
- }
- },
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
- "components": {
- "parameters": {
- "page": {
- "name": "page",
- "in": "query",
- "description": "The page number to return",
- "required": false,
- "schema": {
- "type": "integer",
- "minimum": 1,
- "default": 1
- },
- "example": 1
- },
- "limit": {
- "name": "limit",
- "in": "query",
- "description": "The number of items to return per page",
- "required": false,
- "schema": {
- "type": "integer",
- "minimum": 1,
- "maximum": 100,
- "default": 10
- },
- "example": 10
- }
- },
- "securitySchemes": {
- "OAuth2": {
- "type": "oauth2",
- "description": "OAuth 2.0 authorization code following RFC8725 best practices.",
- "flows": {
- "authorizationCode": {
- "authorizationUrl": "https://example.com/oauth/authorize",
- "tokenUrl": "https://example.com/oauth/token",
- "scopes": {
- "read": "Read access",
- "write": "Write access"
- }
- }
- }
- }
- },
- "schemas": {
- "Station": {
- "type": "object",
- "xml": {
- "name": "station"
- },
- "required": [
- "id",
- "name",
- "address",
- "country_code"
- ],
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the station.",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "name": {
- "type": "string",
- "description": "The name of the station",
- "examples": [
- "Berlin Hauptbahnhof",
- "Paris Gare du Nord"
- ]
- },
- "address": {
- "type": "string",
- "description": "The address of the station.",
- "examples": [
- "Invalidenstraße 10557 Berlin, Germany",
- "18 Rue de Dunkerque 75010 Paris, France"
- ]
- },
- "country_code": {
- "type": "string",
- "description": "The country code of the station.",
- "format": "iso-country-code",
- "examples": [
- "DE",
- "FR"
- ]
- },
- "timezone": {
- "type": "string",
- "description": "The timezone of the station in the [IANA Time Zone Database format](https://www.iana.org/time-zones).",
- "examples": [
- "Europe/Berlin",
- "Europe/Paris"
- ]
- }
- }
- },
- "Links-Self": {
- "type": "object",
- "properties": {
- "self": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Links-Pagination": {
- "type": "object",
- "properties": {
- "next": {
- "type": "string",
- "format": "uri"
- },
- "prev": {
- "type": "string",
- "format": "uri"
- }
- }
- },
- "Problem": {
- "type": "object",
- "xml": {
- "name": "problem",
- "namespace": "urn:ietf:rfc:7807"
- },
- "properties": {
- "type": {
- "type": "string",
- "description": "A URI reference that identifies the problem type",
- "examples": [
- "https://example.com/probs/out-of-credit"
- ]
- },
- "title": {
- "type": "string",
- "description": "A short, human-readable summary of the problem type",
- "examples": [
- "You do not have enough credit."
- ]
- },
- "detail": {
- "type": "string",
- "description": "A human-readable explanation specific to this occurrence of the problem",
- "examples": [
- "Your current balance is 30, but that costs 50."
- ]
- },
- "instance": {
- "type": "string",
- "description": "A URI reference that identifies the specific occurrence of the problem",
- "examples": [
- "/account/12345/msgs/abc"
- ]
- },
- "status": {
- "type": "integer",
- "description": "The HTTP status code",
- "examples": [
- 400
- ]
- }
- }
- },
- "Trip": {
- "type": "object",
- "xml": {
- "name": "trip"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "origin": {
- "type": "string",
- "description": "The starting station of the trip",
- "examples": [
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "b2e783e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "destination": {
- "type": "string",
- "description": "The destination station of the trip",
- "examples": [
- "b2e783e1-c824-4d63-b37a-d8d698862f1d",
- "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e"
- ]
- },
- "departure_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip departs",
- "examples": [
- "2024-02-01T10:00:00Z"
- ]
- },
- "arrival_time": {
- "type": "string",
- "format": "date-time",
- "description": "The date and time when the trip arrives",
- "examples": [
- "2024-02-01T16:00:00Z"
- ]
- },
- "operator": {
- "type": "string",
- "description": "The name of the operator of the trip",
- "examples": [
- "Deutsche Bahn",
- "SNCF"
- ]
- },
- "price": {
- "type": "number",
- "description": "The cost of the trip",
- "examples": [
- 50
- ]
- },
- "bicycles_allowed": {
- "type": "boolean",
- "description": "Indicates whether bicycles are allowed on the trip"
- },
- "dogs_allowed": {
- "type": "boolean",
- "description": "Indicates whether dogs are allowed on the trip"
- }
- }
- },
- "Booking": {
- "type": "object",
- "xml": {
- "name": "booking"
- },
- "properties": {
- "id": {
- "type": "string",
- "format": "uuid",
- "description": "Unique identifier for the booking",
- "readOnly": true,
- "examples": [
- "3f3e3e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "trip_id": {
- "type": "string",
- "format": "uuid",
- "description": "Identifier of the booked trip",
- "examples": [
- "4f4e4e1-c824-4d63-b37a-d8d698862f1d"
- ]
- },
- "passenger_name": {
- "type": "string",
- "description": "Name of the passenger",
- "examples": [
- "John Doe"
- ]
- },
- "has_bicycle": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a bicycle."
- },
- "has_dog": {
- "type": "boolean",
- "description": "Indicates whether the passenger has a dog."
- }
- }
- },
- "Wrapper-Collection": {
- "description": "This is a generic request/response wrapper which contains both data and links which serve as hypermedia controls (HATEOAS).",
- "type": "object",
- "properties": {
- "data": {
- "description": "The wrapper for a collection is an array of objects.",
- "type": "array",
- "items": {
- "type": "object"
- }
- },
- "links": {
- "description": "A set of hypermedia links which serve as controls for the client.",
- "type": "object",
- "readOnly": true
- }
- },
- "xml": {
- "name": "data"
- }
- },
- "BookingPayment": {
- "type": "object",
- "properties": {
- "id": {
- "description": "Unique identifier for the payment. This will be a unique identifier for the payment, and is used to reference the payment in other objects.",
- "type": "string",
- "format": "uuid",
- "readOnly": true
- },
- "amount": {
- "description": "Amount intended to be collected by this payment. A positive decimal figure describing the amount to be collected.",
- "type": "number",
- "exclusiveMinimum": 0,
- "examples": [
- 49.99
- ]
- },
- "currency": {
- "description": "Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.",
- "type": "string",
- "enum": [
- "bam",
- "bgn",
- "chf",
- "eur",
- "gbp",
- "nok",
- "sek",
- "try"
- ]
- },
- "source": {
- "unevaluatedProperties": false,
- "description": "The payment source to take the payment from. This can be a card or a bank account. Some of these properties will be hidden on read to protect PII leaking.",
- "oneOf": [
- {
- "title": "Card",
- "description": "A card (debit or credit) to take payment from.",
- "type": "object",
- "properties": {
- "object": {
- "type": "string",
- "const": "card"
- },
- "name": {
- "type": "string",
- "description": "Cardholder's full name as it appears on the card.",
- "examples": [
- "Francis Bourgeois"
- ]
- },
- "number": {
- "type": "string",
- "description": "The card number, as a string without any separators. On read all but the last four digits will be masked for security.",
- "examples": [
- "4242424242424242"
- ]
- },
- "cvc": {
- "type": "integer",
- "description": "Card security code, 3 or 4 digits usually found on the back of the card.",
- "minLength": 3,
- "maxLength": 4,
- "writeOnly": true,
- "example": 123
- },
- "exp_month": {
- "type": "integer",
- "format": "int64",
- "description": "Two-digit number representing the card's expiration month.",
- "examples": [
- 12
- ]
- },
- "exp_year": {
- "type": "integer",
- "format": "int64",
- "description": "Four-digit number representing the card's expiration year.",
- "examples": [
- 2025
- ]
- },
- "address_line1": {
- "type": "string",
- "writeOnly": true
- },
- "address_line2": {
- "type": "string",
- "writeOnly": true
- },
- "address_city": {
- "type": "string"
- },
- "address_country": {
- "type": "string"
- },
- "address_post_code": {
- "type": "string"
- }
- },
- "required": [
- "name",
- "number",
- "cvc",
- "exp_month",
- "exp_year",
- "address_country"
- ]
- },
- {
- "title": "Bank Account",
- "description": "A bank account to take payment from. Must be able to make payments in the currency specified in the payment.",
- "type": "object",
- "properties": {
- "object": {
- "const": "bank_account",
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "number": {
- "type": "string",
- "description": "The account number for the bank account, in string form. Must be a current account."
- },
- "sort_code": {
- "type": "string",
- "description": "The sort code for the bank account, in string form. Must be a six-digit number."
- },
- "account_type": {
- "enum": [
- "individual",
- "company"
- ],
- "type": "string",
- "description": "The type of entity that holds the account. This can be either \`individual\` or \`company\`."
- },
- "bank_name": {
- "type": "string",
- "description": "The name of the bank associated with the routing number.",
- "examples": [
- "Starling Bank"
- ]
- },
- "country": {
- "type": "string",
- "description": "Two-letter country code (ISO 3166-1 alpha-2)."
- }
- },
- "required": [
- "name",
- "number",
- "account_type",
- "bank_name",
- "country"
- ]
- }
- ]
- },
- "status": {
- "description": "The status of the payment, one of \`pending\`, \`succeeded\`, or \`failed\`.",
- "type": "string",
- "enum": [
- "pending",
- "succeeded",
- "failed"
- ],
- "readOnly": true
- }
- }
- },
- "Links-Booking": {
- "type": "object",
- "properties": {
- "booking": {
- "type": "string",
- "format": "uri",
- "examples": [
- "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- ]
- }
- }
- }
- },
- "headers": {
- "Cache-Control": {
- "description": "The Cache-Control header communicates directives for caching mechanisms in both requests and responses. \\nIt is used to specify the caching directives in responses to prevent caches from storing sensitive information.\\n",
- "schema": {
- "type": "string",
- "description": "A comma-separated list of directives as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html).",
- "examples": [
- "max-age=3600",
- "max-age=604800, public",
- "no-store",
- "no-cache",
- "private"
- ]
- }
- },
- "RateLimit": {
- "description": "The RateLimit header communicates quota policies. It contains a \`limit\` to\\nconvey the expiring limit, \`remaining\` to convey the remaining quota units,\\nand \`reset\` to convey the time window reset time.\\n",
- "schema": {
- "type": "string",
- "examples": [
- "limit=10, remaining=0, reset=10"
- ]
- }
- },
- "Retry-After": {
- "description": "The Retry-After header indicates how long the user agent should wait before making a follow-up request. \\nThe value is in seconds and can be an integer or a date in the future. \\nIf the value is an integer, it indicates the number of seconds to wait. \\nIf the value is a date, it indicates the time at which the user agent should make a follow-up request. \\n",
- "schema": {
- "type": "string"
- },
- "examples": {
- "integer": {
- "value": "120",
- "summary": "Retry after 120 seconds"
- },
- "date": {
- "value": "Fri, 31 Dec 2021 23:59:59 GMT",
- "summary": "Retry after the specified date"
- }
- }
- }
- },
- "responses": {
- "BadRequest": {
- "description": "Bad Request",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/bad-request",
- "title": "Bad Request",
- "status": 400,
- "detail": "The request is invalid or missing required parameters."
- }
- }
- }
- },
- "Conflict": {
- "description": "Conflict",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/conflict",
- "title": "Conflict",
- "status": 409,
- "detail": "There is a conflict with an existing resource."
- }
- }
- }
- },
- "Forbidden": {
- "description": "Forbidden",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/forbidden",
- "title": "Forbidden",
- "status": 403,
- "detail": "Access is forbidden with the provided credentials."
- }
- }
- }
- },
- "InternalServerError": {
- "description": "Internal Server Error",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/internal-server-error",
- "title": "Internal Server Error",
- "status": 500,
- "detail": "An unexpected error occurred."
- }
- }
- }
- },
- "NotFound": {
- "description": "Not Found",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/not-found",
- "title": "Not Found",
- "status": 404,
- "detail": "The requested resource was not found."
- }
- }
- }
- },
- "TooManyRequests": {
- "description": "Too Many Requests",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- },
- "Retry-After": {
- "$ref": "#/components/headers/Retry-After"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/too-many-requests",
- "title": "Too Many Requests",
- "status": 429,
- "detail": "You have exceeded the rate limit."
- }
- }
- }
- },
- "Unauthorized": {
- "description": "Unauthorized",
- "headers": {
- "RateLimit": {
- "$ref": "#/components/headers/RateLimit"
- }
- },
- "content": {
- "application/problem+json": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
- },
- "application/problem+xml": {
- "schema": {
- "$ref": "#/components/schemas/Problem"
- },
- "example": {
- "type": "https://example.com/errors/unauthorized",
- "title": "Unauthorized",
- "status": 401,
- "detail": "You do not have the necessary permissions."
- }
}
}
}
}
}
}",
- "name": "openapi.json",
- "type": "file",
+ "name": "openapi.json",
+ "type": "file",
+ },
+ ],
+ "name": "openapi",
+ "type": "directory",
},
]
`;
diff --git a/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/generators.yml b/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/generators.yml
index ecdc5f49d5d..5739e3068cb 100644
--- a/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/generators.yml
+++ b/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/generators.yml
@@ -1,7 +1,7 @@
default-group: local
api:
path: ./openapi/openapi.json
- origin: https://bump.sh/bump-examples/doc/train-travel-api.json
+ origin: http://localhost:4567/openapi.json
groups:
local:
generators:
@@ -9,4 +9,4 @@ groups:
version: 0.9.5
output:
location: local-file-system
- path: ../sdks/typescript
+ path: ../sdks/typescript
\ No newline at end of file
diff --git a/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/openapi/openapi.json b/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/openapi/openapi.json
index 11a1b14d2b3..a7705520202 100644
--- a/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/openapi/openapi.json
+++ b/packages/cli/ete-tests/src/tests/update-api/fixtures/fern/openapi/openapi.json
@@ -764,60 +764,6 @@
}
}
},
- "webhooks": {
- "newBooking": {
- "post": {
- "operationId": "new-booking",
- "summary": "New Booking",
- "description": "Subscribe to new bookings being created, to update integrations for your users. Related data is available via the links provided in the request.\n",
- "tags": [
- "Bookings"
- ],
- "requestBody": {
- "content": {
- "application/json": {
- "schema": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Booking"
- },
- {
- "properties": {
- "links": {
- "allOf": [
- {
- "$ref": "#/components/schemas/Links-Self"
- },
- {
- "$ref": "#/components/schemas/Links-Pagination"
- }
- ]
- }
- }
- }
- ]
- },
- "example": {
- "id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "trip_id": "efdbb9d1-02c2-4bc3-afb7-6788d8782b1e",
- "passenger_name": "John Doe",
- "has_bicycle": true,
- "has_dog": true,
- "links": {
- "self": "https://api.example.com/bookings/1725ff48-ab45-4bb5-9d02-88745177dedb"
- }
- }
- }
- }
- },
- "responses": {
- "200": {
- "description": "Return a 200 status to indicate that the data was received successfully."
- }
- }
- }
- }
- },
"components": {
"securitySchemes": {
"OAuth2": {
diff --git a/packages/cli/ete-tests/src/tests/update-api/update-api.test.ts b/packages/cli/ete-tests/src/tests/update-api/update-api.test.ts
index ea74ad5053d..3ad7098cbfe 100644
--- a/packages/cli/ete-tests/src/tests/update-api/update-api.test.ts
+++ b/packages/cli/ete-tests/src/tests/update-api/update-api.test.ts
@@ -1,25 +1,29 @@
-import { AbsoluteFilePath, getDirectoryContents, getDirectoryContentsForSnapshot } from "@fern-api/fs-utils";
+import { AbsoluteFilePath, getDirectoryContentsForSnapshot } from "@fern-api/fs-utils";
import { cp } from "fs/promises";
import path from "path";
import tmp from "tmp-promise";
import { runFernCli } from "../../utils/runFernCli";
+import { setupOpenAPIServer } from "../../utils/setupOpenAPIServer";
const FIXTURES_DIR = path.join(__dirname, "fixtures");
describe("fern api update", () => {
it("fern api update", async () => {
- // Create tmpdir and copy contents
+ // Start express server that will respond with the OpenAPI spec.
+ const { cleanup } = setupOpenAPIServer();
+
const tmpDir = await tmp.dir();
const directory = AbsoluteFilePath.of(tmpDir.path);
+ const outputPath = AbsoluteFilePath.of(path.join(directory, "fern"));
await cp(FIXTURES_DIR, directory, { recursive: true });
-
- const outputPath = AbsoluteFilePath.of(path.join(directory, "fern", "openapi"));
-
await runFernCli(["api", "update"], {
cwd: directory
});
expect(await getDirectoryContentsForSnapshot(outputPath)).toMatchSnapshot();
+
+ // Shutdown the server now that we're done.
+ await cleanup();
}, 60_000);
});
diff --git a/packages/cli/ete-tests/src/utils/setupOpenAPIServer.ts b/packages/cli/ete-tests/src/utils/setupOpenAPIServer.ts
new file mode 100644
index 00000000000..d917a38e1fe
--- /dev/null
+++ b/packages/cli/ete-tests/src/utils/setupOpenAPIServer.ts
@@ -0,0 +1,78 @@
+import { OpenAPI } from "openapi-types";
+import express from "express";
+import * as http from "http";
+
+const TEST_OPENAPI_DOCUMENT: OpenAPI.Document = {
+ openapi: "3.0.0",
+ info: {
+ title: "Test API",
+ version: "1.0.0"
+ },
+ paths: {
+ "/testdata": {
+ get: {
+ summary: "Retrieve test data",
+ operationId: "getTestData",
+ responses: {
+ "200": {
+ description: "Successful response",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ message: { type: "string" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/filtered": {
+ get: {
+ summary: "This endpoint should be filtered out",
+ operationId: "filtered",
+ responses: {
+ "200": {
+ description: "Successful response",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ message: { type: "string" }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+};
+
+export function setupOpenAPIServer(): { server: http.Server; cleanup: () => Promise } {
+ const app = express();
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ app.get("/openapi.json", (req: any, res: any) => {
+ res.json(TEST_OPENAPI_DOCUMENT);
+ });
+
+ const server = app.listen(4567);
+ const cleanup = async () => {
+ return new Promise((resolve, reject) => {
+ server.close((err) => {
+ if (err) {
+ reject(err);
+ } else {
+ resolve();
+ }
+ });
+ });
+ };
+ return { server, cleanup };
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d7a5001123f..6a7a17c668d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4174,8 +4174,6 @@ importers:
specifier: ^2.1.4
version: 2.1.4(@types/node@18.7.18)(jsdom@20.0.3)(sass@1.72.0)(terser@5.31.5)
- packages/cli/cli/dist/local: {}
-
packages/cli/configuration:
dependencies:
'@fern-api/core-utils':
@@ -4647,12 +4645,18 @@ importers:
execa:
specifier: ^5.1.1
version: 5.1.1
+ express:
+ specifier: ^4.20.0
+ version: 4.21.1
js-yaml:
specifier: ^4.1.0
version: 4.1.0
node-fetch:
specifier: 2.7.0
version: 2.7.0
+ openapi-types:
+ specifier: ^12.1.3
+ version: 12.1.3
strip-ansi:
specifier: ^7.1.0
version: 7.1.0
@@ -4660,6 +4664,9 @@ importers:
specifier: ^3.0.3
version: 3.0.3
devDependencies:
+ '@types/express':
+ specifier: ^4.17.21
+ version: 4.17.21
'@types/jest':
specifier: ^29.5.12
version: 29.5.12
@@ -8076,6 +8083,9 @@ packages:
'@fern-fern/ir-sdk@53.18.0':
resolution: {integrity: sha512-KXHiAn8wjL9VIjjR9z8fXso0O2oaCMUSy9BSYRiGjEOmbIBUhplxSXjM3wSEXQ19hiPpsRYJTCCjnaZVP0OVrw==}
+ '@fern-fern/ir-sdk@53.23.0':
+ resolution: {integrity: sha512-9U6uGs9WFDnVg57VyM7s6LKCkA30JOYDQwuLrNh50Meme0m8ce4GDZ/naVncfhrGjWfxt7PSjy1vlVLBi+PKZA==}
+
'@fern-fern/ir-sdk@53.24.0':
resolution: {integrity: sha512-cR/GIvqLaK8Oeql0WLv8nUsYNfplBHXKHoHv49CJfRP0xMr/RLmiQCZm2RAH+hnMha282oEMXYQeZDoZhatjKw==}
@@ -14121,7 +14131,7 @@ snapshots:
'@babel/core': 7.25.2
'@babel/helper-compilation-targets': 7.25.7
'@babel/helper-plugin-utils': 7.25.7
- debug: 4.3.6
+ debug: 4.3.7
lodash.debounce: 4.0.8
resolve: 1.22.8
transitivePeerDependencies:
@@ -15302,6 +15312,8 @@ snapshots:
'@fern-fern/ir-sdk@53.18.0': {}
+ '@fern-fern/ir-sdk@53.23.0': {}
+
'@fern-fern/ir-sdk@53.24.0': {}
'@fern-fern/ir-sdk@53.7.0': {}
@@ -16302,7 +16314,7 @@ snapshots:
'@typescript-eslint/type-utils@5.30.5(eslint@8.56.0)(typescript@4.6.4)':
dependencies:
'@typescript-eslint/utils': 5.30.5(eslint@8.56.0)(typescript@4.6.4)
- debug: 4.3.6
+ debug: 4.3.7
eslint: 8.56.0
tsutils: 3.21.0(typescript@4.6.4)
optionalDependencies:
@@ -16322,7 +16334,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 5.30.5
'@typescript-eslint/visitor-keys': 5.30.5
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.3
@@ -16336,7 +16348,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 5.32.0
'@typescript-eslint/visitor-keys': 5.32.0
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
semver: 7.6.3
@@ -16350,7 +16362,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 6.20.0
'@typescript-eslint/visitor-keys': 6.20.0
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
@@ -16365,7 +16377,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 6.21.0
'@typescript-eslint/visitor-keys': 6.21.0
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.3
@@ -18891,7 +18903,7 @@ snapshots:
istanbul-lib-source-maps@4.0.1:
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
istanbul-lib-coverage: 3.2.0
source-map: 0.6.1
transitivePeerDependencies:
@@ -20063,7 +20075,7 @@ snapshots:
micromark@4.0.0:
dependencies:
'@types/debug': 4.1.8
- debug: 4.3.6
+ debug: 4.3.7
decode-named-character-reference: 1.0.2
devlop: 1.1.0
micromark-core-commonmark: 2.0.1