diff --git a/templates/default/procedure-call.ejs b/templates/default/procedure-call.ejs index 90af47bdd..b124d36e2 100644 --- a/templates/default/procedure-call.ejs +++ b/templates/default/procedure-call.ejs @@ -81,6 +81,13 @@ const describeReturnType = () => { const isValidIdentifier = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name); +const getSuccessResponseTypes = () => { + const successResponses = responseBodyInfo.responses.filter(response => response.isSuccess); + + return config.Ts.UnionType(successResponses.map((response) => response.type)) || "any"; +} + + %> /** <%~ routeDocs.description %> @@ -91,7 +98,7 @@ const isValidIdentifier = (name) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name); */ <% if (isValidIdentifier(route.routeName.usage)) { %><%~ route.routeName.usage %><%~ route.namespace ? ': ' : ' = ' %><% } else { %>"<%~ route.routeName.usage %>"<%~ route.namespace ? ': ' : ' = ' %><% } %>(<%~ wrapperArgs %>)<%~ config.toJS ? `: ${describeReturnType()}` : "" %> => - <%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ type %>, <%~ errorType %>>({ + <%~ config.singleHttpClient ? 'this.http.request' : 'this.request' %><<%~ `${getSuccessResponseTypes()}` %>, <%~ errorType %>>({ path: `<%~ path %>`, method: '<%~ _.upperCase(method) %>', <%~ queryTmpl ? `query: ${queryTmpl},` : '' %> diff --git a/tests/__snapshots__/extended.test.ts.snap b/tests/__snapshots__/extended.test.ts.snap index e95bc232a..35fdc610d 100644 --- a/tests/__snapshots__/extended.test.ts.snap +++ b/tests/__snapshots__/extended.test.ts.snap @@ -8124,7 +8124,7 @@ export class Api< * @request GET:/v2 */ getVersionDetailsv2: (params: RequestParams = {}) => - this.request({ + this.request({ path: \`/v2\`, method: "GET", format: "json", @@ -8490,7 +8490,7 @@ export class Api< * @request GET:/v2 */ getVersionDetailsv2: (params: RequestParams = {}) => - this.request({ + this.request({ path: \`/v2\`, method: "GET", format: "json", @@ -9600,7 +9600,7 @@ export class Api< { job, ...query }: SignRetrieveParams, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/scope/\${job}\`, method: "GET", format: "json", @@ -9618,7 +9618,7 @@ export class Api< { job, ...query }: SignRetrieveHeadParams, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/scope/\${job}\`, method: "HEAD", ...params, @@ -11330,7 +11330,7 @@ export class Api< parameters: TdeCertificate, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/subscriptions/\${subscriptionId}/resourceGroups/\${resourceGroupName}/providers/Microsoft.Sql/managedInstances/\${managedInstanceName}/tdeCertificates\`, method: "POST", query: query, @@ -51037,7 +51037,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - OauthAuthorizationsGetOrCreateAuthorizationForAppData, + OauthAuthorizationsGetOrCreateAuthorizationForAppData | Authorization, BasicError | ValidationError >({ path: \`/authorizations/clients/\${clientId}\`, @@ -51067,7 +51067,8 @@ export class Api< params: RequestParams = {}, ) => this.request< - OauthAuthorizationsGetOrCreateAuthorizationForAppAndFingerprintData, + | OauthAuthorizationsGetOrCreateAuthorizationForAppAndFingerprintData + | Authorization, ValidationError >({ path: \`/authorizations/clients/\${clientId}/\${fingerprint}\`, @@ -52857,7 +52858,7 @@ export class Api< data: ActivityMarkNotificationsAsReadPayload, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/notifications\`, method: "PUT", body: data, @@ -53024,7 +53025,7 @@ export class Api< data: ActionsCreateOrUpdateOrgSecretPayload, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/orgs/\${org}/actions/secrets/\${secretName}\`, method: "PUT", body: data, @@ -54145,7 +54146,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - OrgsConvertMemberToOutsideCollaboratorData, + OrgsConvertMemberToOutsideCollaboratorData | void, OrgsConvertMemberToOutsideCollaboratorError >({ path: \`/orgs/\${org}/outside_collaborators/\${username}\`, @@ -55127,7 +55128,7 @@ export class Api< }: TeamsCheckPermissionsForRepoInOrgParams, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/orgs/\${org}/teams/\${teamSlug}/repos/\${owner}/\${repo}\`, method: "GET", format: "json", @@ -56228,7 +56229,7 @@ export class Api< data: ActionsCreateOrUpdateRepoSecretPayload, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/actions/secrets/\${secretName}\`, method: "PUT", body: data, @@ -59430,7 +59431,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - ReactionsCreateForCommitCommentData, + ReactionsCreateForCommitCommentData | Reaction, | { documentation_url: string; message: string; @@ -59493,7 +59494,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - ReactionsCreateForIssueCommentData, + ReactionsCreateForIssueCommentData | Reaction, | { documentation_url: string; message: string; @@ -59527,7 +59528,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - ReactionsCreateForPullRequestReviewCommentData, + ReactionsCreateForPullRequestReviewCommentData | Reaction, | { documentation_url: string; message: string; @@ -59786,7 +59787,10 @@ export class Api< data: ReposAddCollaboratorPayload, params: RequestParams = {}, ) => - this.request({ + this.request< + ReposAddCollaboratorData | void, + BasicError | ValidationError + >({ path: \`/repos/\${owner}/\${repo}/collaborators/\${username}\`, method: "PUT", body: data, @@ -60022,7 +60026,13 @@ export class Api< data: ReposCreateDeploymentPayload, params: RequestParams = {}, ) => - this.request({ + this.request< + | ReposCreateDeploymentData + | { + message?: string; + }, + ReposCreateDeploymentError + >({ path: \`/repos/\${owner}/\${repo}/deployments\`, method: "POST", body: data, @@ -60115,7 +60125,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - ReposCreateOrUpdateFileContentsData, + ReposCreateOrUpdateFileContentsData | FileCommit, BasicError | ValidationError >({ path: \`/repos/\${owner}/\${repo}/contents/\${path}\`, @@ -61644,7 +61654,7 @@ export class Api< { owner, repo, ...query }: ReposListContributorsParams, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/contributors\`, method: "GET", query: query, @@ -63579,7 +63589,7 @@ export class Api< }: TeamsCheckPermissionsForRepoLegacyParams, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/teams/\${teamId}/repos/\${owner}/\${repo}\`, method: "GET", format: "json", diff --git a/tests/__snapshots__/simple.test.ts.snap b/tests/__snapshots__/simple.test.ts.snap index 710b23008..8fe38864b 100644 --- a/tests/__snapshots__/simple.test.ts.snap +++ b/tests/__snapshots__/simple.test.ts.snap @@ -6199,7 +6199,7 @@ export class Api< field?: string; /** base64safe encoded public signing key */ sub?: string; - }, + } | void, Error >({ path: \`/scope/\${job}\`, @@ -20357,7 +20357,7 @@ export class Api< this.request< { message?: string; - }, + } | void, BasicError >({ path: \`/notifications\`, @@ -24051,7 +24051,7 @@ export class Api< repo: string, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/orgs/\${org}/teams/\${teamSlug}/repos/\${owner}/\${repo}\`, method: "GET", format: "json", @@ -27670,7 +27670,7 @@ export class Api< }, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/collaborators/\${username}\`, method: "PUT", body: data, @@ -28505,7 +28505,7 @@ export class Api< }, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/contributors\`, method: "GET", query: query, @@ -28621,7 +28621,10 @@ export class Api< params: RequestParams = {}, ) => this.request< - Deployment, + | Deployment + | { + message?: string; + }, | { /** @example ""https://docs.github.com/rest/reference/repos#create-a-deployment"" */ documentation_url?: string; @@ -35792,7 +35795,7 @@ export class Api< repo: string, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/teams/\${teamId}/repos/\${owner}/\${repo}\`, method: "GET", format: "json", diff --git a/tests/spec/axios/__snapshots__/basic.test.ts.snap b/tests/spec/axios/__snapshots__/basic.test.ts.snap index ba768ef9a..46697b47c 100644 --- a/tests/spec/axios/__snapshots__/basic.test.ts.snap +++ b/tests/spec/axios/__snapshots__/basic.test.ts.snap @@ -4741,7 +4741,7 @@ export class Api< body: MergesBody, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/merges\`, method: "POST", body: body, diff --git a/tests/spec/axiosSingleHttpClient/__snapshots__/basic.test.ts.snap b/tests/spec/axiosSingleHttpClient/__snapshots__/basic.test.ts.snap index ca053dec1..f66c4c4ef 100644 --- a/tests/spec/axiosSingleHttpClient/__snapshots__/basic.test.ts.snap +++ b/tests/spec/axiosSingleHttpClient/__snapshots__/basic.test.ts.snap @@ -4745,7 +4745,7 @@ export class Api { body: MergesBody, params: RequestParams = {}, ) => - this.http.request({ + this.http.request({ path: \`/repos/\${owner}/\${repo}/merges\`, method: "POST", body: body, diff --git a/tests/spec/defaultAsSuccess/__snapshots__/basic.test.ts.snap b/tests/spec/defaultAsSuccess/__snapshots__/basic.test.ts.snap index 3b1386313..8653e8187 100644 --- a/tests/spec/defaultAsSuccess/__snapshots__/basic.test.ts.snap +++ b/tests/spec/defaultAsSuccess/__snapshots__/basic.test.ts.snap @@ -341,10 +341,11 @@ export class Api< params: RequestParams = {}, ) => this.request< - { - /** pending or done */ - status?: string; - }, + | { + /** pending or done */ + status?: string; + } + | Error, Error >({ path: \`/key\`, @@ -363,12 +364,13 @@ export class Api< */ keyRegister: (body: AuthentiqID, params: RequestParams = {}) => this.request< - { - /** revoke key */ - secret?: string; - /** registered */ - status?: string; - }, + | { + /** revoke key */ + secret?: string; + /** registered */ + status?: string; + } + | Error, Error >({ path: \`/key\`, @@ -394,10 +396,11 @@ export class Api< params: RequestParams = {}, ) => this.request< - { - /** done */ - status?: string; - }, + | { + /** done */ + status?: string; + } + | Error, Error >({ path: \`/key/\${pk}\`, @@ -416,13 +419,14 @@ export class Api< */ getKey: (pk: string, params: RequestParams = {}) => this.request< - { - /** @format date-time */ - since?: string; - status?: string; - /** base64safe encoded public signing key */ - sub?: string; - }, + | { + /** @format date-time */ + since?: string; + status?: string; + /** base64safe encoded public signing key */ + sub?: string; + } + | Error, Error >({ path: \`/key/\${pk}\`, @@ -439,7 +443,7 @@ export class Api< * @request HEAD:/key/{PK} */ headKey: (pk: string, params: RequestParams = {}) => - this.request({ + this.request({ path: \`/key/\${pk}\`, method: "HEAD", ...params, @@ -454,10 +458,11 @@ export class Api< */ keyUpdate: (pk: string, body: AuthentiqID, params: RequestParams = {}) => this.request< - { - /** confirmed */ - status?: string; - }, + | { + /** confirmed */ + status?: string; + } + | Error, Error >({ path: \`/key/\${pk}\`, @@ -476,10 +481,11 @@ export class Api< */ keyBind: (pk: string, body: AuthentiqID, params: RequestParams = {}) => this.request< - { - /** confirmed */ - status?: string; - }, + | { + /** confirmed */ + status?: string; + } + | Error, Error >({ path: \`/key/\${pk}\`, @@ -506,10 +512,11 @@ export class Api< params: RequestParams = {}, ) => this.request< - { - /** sent */ - status?: string; - }, + | { + /** sent */ + status?: string; + } + | Error, Error >({ path: \`/login\`, @@ -537,12 +544,13 @@ export class Api< params: RequestParams = {}, ) => this.request< - { - /** 20-character ID */ - job?: string; - /** waiting */ - status?: string; - }, + | { + /** 20-character ID */ + job?: string; + /** waiting */ + status?: string; + } + | Error, Error >({ path: \`/scope\`, @@ -562,10 +570,11 @@ export class Api< */ signDelete: (job: string, params: RequestParams = {}) => this.request< - { - /** done */ - status?: string; - }, + | { + /** done */ + status?: string; + } + | Error, Error >({ path: \`/scope/\${job}\`, @@ -583,12 +592,14 @@ export class Api< */ signRetrieve: (job: string, params: RequestParams = {}) => this.request< - { - exp?: number; - field?: string; - /** base64safe encoded public signing key */ - sub?: string; - }, + | { + exp?: number; + field?: string; + /** base64safe encoded public signing key */ + sub?: string; + } + | void + | Error, Error >({ path: \`/scope/\${job}\`, @@ -605,7 +616,7 @@ export class Api< * @request HEAD:/scope/{job} */ signRetrieveHead: (job: string, params: RequestParams = {}) => - this.request({ + this.request({ path: \`/scope/\${job}\`, method: "HEAD", ...params, @@ -620,10 +631,11 @@ export class Api< */ signConfirm: (job: string, params: RequestParams = {}) => this.request< - { - /** confirmed */ - status?: string; - }, + | { + /** confirmed */ + status?: string; + } + | Error, Error >({ path: \`/scope/\${job}\`, @@ -642,12 +654,13 @@ export class Api< */ signUpdate: (job: string, params: RequestParams = {}) => this.request< - { - /** result is JWT or JSON?? */ - jwt?: string; - /** ready */ - status?: string; - }, + | { + /** result is JWT or JSON?? */ + jwt?: string; + /** ready */ + status?: string; + } + | Error, Error >({ path: \`/scope/\${job}\`, diff --git a/tests/spec/extractRequestParams/__snapshots__/basic.test.ts.snap b/tests/spec/extractRequestParams/__snapshots__/basic.test.ts.snap index 985bf2f25..df12b6ea0 100644 --- a/tests/spec/extractRequestParams/__snapshots__/basic.test.ts.snap +++ b/tests/spec/extractRequestParams/__snapshots__/basic.test.ts.snap @@ -746,7 +746,7 @@ export class Api< field?: string; /** base64safe encoded public signing key */ sub?: string; - }, + } | void, Error >({ path: \`/scope/\${job}\`, diff --git a/tests/spec/multipleSuccessResponses/__snapshots__/basic.test.ts.snap b/tests/spec/multipleSuccessResponses/__snapshots__/basic.test.ts.snap new file mode 100644 index 000000000..17e0eab1f --- /dev/null +++ b/tests/spec/multipleSuccessResponses/__snapshots__/basic.test.ts.snap @@ -0,0 +1,349 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`basic > Multiple responses 1`] = ` +"/* eslint-disable */ +/* tslint:disable */ +// @ts-nocheck +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +/** Authentiq ID in JWT format, self-signed. */ +export interface AuthentiqID { + /** device token for push messages */ + devtoken?: string; + /** UUID and public signing key */ + sub: string; +} + +/** Claim in JWT format, self- or issuer-signed. */ +export interface Claims { + email?: string; + phone?: string; + /** claim scope */ + scope: string; + /** UUID */ + sub: string; + type?: string; +} + +export interface Error { + detail?: string; + error: number; + title?: string; + /** unique uri for this error */ + type?: string; +} + +/** PushToken in JWT format, self-signed. */ +export interface PushToken { + /** audience (URI) */ + aud: string; + exp?: number; + iat?: number; + /** issuer (URI) */ + iss: string; + nbf?: number; + /** UUID and public signing key */ + sub: string; +} + +export type QueryParamsType = Record; +export type ResponseFormat = keyof Omit; + +export interface FullRequestParams extends Omit { + /** set parameter to \`true\` for call \`securityWorker\` for this request */ + secure?: boolean; + /** request path */ + path: string; + /** content type of request body */ + type?: ContentType; + /** query params */ + query?: QueryParamsType; + /** format of response (i.e. response.json() -> format: "json") */ + format?: ResponseFormat; + /** request body */ + body?: unknown; + /** base url */ + baseUrl?: string; + /** request cancellation token */ + cancelToken?: CancelToken; +} + +export type RequestParams = Omit< + FullRequestParams, + "body" | "method" | "query" | "path" +>; + +export interface ApiConfig { + baseUrl?: string; + baseApiParams?: Omit; + securityWorker?: ( + securityData: SecurityDataType | null, + ) => Promise | RequestParams | void; + customFetch?: typeof fetch; +} + +export interface HttpResponse + extends Response { + data: D; + error: E; +} + +type CancelToken = Symbol | string | number; + +export enum ContentType { + Json = "application/json", + JsonApi = "application/vnd.api+json", + FormData = "multipart/form-data", + UrlEncoded = "application/x-www-form-urlencoded", + Text = "text/plain", +} + +export class HttpClient { + public baseUrl: string = "https://6-dot-authentiqio.appspot.com"; + private securityData: SecurityDataType | null = null; + private securityWorker?: ApiConfig["securityWorker"]; + private abortControllers = new Map(); + private customFetch = (...fetchParams: Parameters) => + fetch(...fetchParams); + + private baseApiParams: RequestParams = { + credentials: "same-origin", + headers: {}, + redirect: "follow", + referrerPolicy: "no-referrer", + }; + + constructor(apiConfig: ApiConfig = {}) { + Object.assign(this, apiConfig); + } + + public setSecurityData = (data: SecurityDataType | null) => { + this.securityData = data; + }; + + protected encodeQueryParam(key: string, value: any) { + const encodedKey = encodeURIComponent(key); + return \`\${encodedKey}=\${encodeURIComponent(typeof value === "number" ? value : \`\${value}\`)}\`; + } + + protected addQueryParam(query: QueryParamsType, key: string) { + return this.encodeQueryParam(key, query[key]); + } + + protected addArrayQueryParam(query: QueryParamsType, key: string) { + const value = query[key]; + return value.map((v: any) => this.encodeQueryParam(key, v)).join("&"); + } + + protected toQueryString(rawQuery?: QueryParamsType): string { + const query = rawQuery || {}; + const keys = Object.keys(query).filter( + (key) => "undefined" !== typeof query[key], + ); + return keys + .map((key) => + Array.isArray(query[key]) + ? this.addArrayQueryParam(query, key) + : this.addQueryParam(query, key), + ) + .join("&"); + } + + protected addQueryParams(rawQuery?: QueryParamsType): string { + const queryString = this.toQueryString(rawQuery); + return queryString ? \`?\${queryString}\` : ""; + } + + private contentFormatters: Record any> = { + [ContentType.Json]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.JsonApi]: (input: any) => + input !== null && (typeof input === "object" || typeof input === "string") + ? JSON.stringify(input) + : input, + [ContentType.Text]: (input: any) => + input !== null && typeof input !== "string" + ? JSON.stringify(input) + : input, + [ContentType.FormData]: (input: any) => { + if (input instanceof FormData) { + return input; + } + + return Object.keys(input || {}).reduce((formData, key) => { + const property = input[key]; + formData.append( + key, + property instanceof Blob + ? property + : typeof property === "object" && property !== null + ? JSON.stringify(property) + : \`\${property}\`, + ); + return formData; + }, new FormData()); + }, + [ContentType.UrlEncoded]: (input: any) => this.toQueryString(input), + }; + + protected mergeRequestParams( + params1: RequestParams, + params2?: RequestParams, + ): RequestParams { + return { + ...this.baseApiParams, + ...params1, + ...(params2 || {}), + headers: { + ...(this.baseApiParams.headers || {}), + ...(params1.headers || {}), + ...((params2 && params2.headers) || {}), + }, + }; + } + + protected createAbortSignal = ( + cancelToken: CancelToken, + ): AbortSignal | undefined => { + if (this.abortControllers.has(cancelToken)) { + const abortController = this.abortControllers.get(cancelToken); + if (abortController) { + return abortController.signal; + } + return void 0; + } + + const abortController = new AbortController(); + this.abortControllers.set(cancelToken, abortController); + return abortController.signal; + }; + + public abortRequest = (cancelToken: CancelToken) => { + const abortController = this.abortControllers.get(cancelToken); + + if (abortController) { + abortController.abort(); + this.abortControllers.delete(cancelToken); + } + }; + + public request = async ({ + body, + secure, + path, + type, + query, + format, + baseUrl, + cancelToken, + ...params + }: FullRequestParams): Promise> => { + const secureParams = + ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) && + this.securityWorker && + (await this.securityWorker(this.securityData))) || + {}; + const requestParams = this.mergeRequestParams(params, secureParams); + const queryString = query && this.toQueryString(query); + const payloadFormatter = this.contentFormatters[type || ContentType.Json]; + const responseFormat = format || requestParams.format; + + return this.customFetch( + \`\${baseUrl || this.baseUrl || ""}\${path}\${queryString ? \`?\${queryString}\` : ""}\`, + { + ...requestParams, + headers: { + ...(requestParams.headers || {}), + ...(type && type !== ContentType.FormData + ? { "Content-Type": type } + : {}), + }, + signal: + (cancelToken + ? this.createAbortSignal(cancelToken) + : requestParams.signal) || null, + body: + typeof body === "undefined" || body === null + ? null + : payloadFormatter(body), + }, + ).then(async (response) => { + const r = response as HttpResponse; + r.data = null as unknown as T; + r.error = null as unknown as E; + + const responseToParse = responseFormat ? response.clone() : response; + const data = !responseFormat + ? r + : await responseToParse[responseFormat]() + .then((data) => { + if (r.ok) { + r.data = data; + } else { + r.error = data; + } + return r; + }) + .catch((e) => { + r.error = e; + return r; + }); + + if (cancelToken) { + this.abortControllers.delete(cancelToken); + } + + if (!response.ok) throw data; + return data; + }); + }; +} + +/** + * @title Authentiq + * @version 6 + * @license Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html) + * @termsOfService http://authentiq.com/terms/ + * @baseUrl https://6-dot-authentiqio.appspot.com + * @contact Authentiq team (http://authentiq.io/support) + * + * Strong authentication, without the passwords. + */ +export class Api< + SecurityDataType extends unknown, +> extends HttpClient { + scope = { + /** + * @description authority updates a JWT with its signature See: https://github.com/skion/authentiq/wiki/JWT-Examples + * + * @tags scope, put + * @name SignUpdate + * @request PUT:/scope/{job} + */ + signUpdate: (job: string, params: RequestParams = {}) => + this.request< + { + /** result is JWT or JSON?? */ + jwt?: string; + /** ready */ + status?: string; + } | void, + Error + >({ + path: \`/scope/\${job}\`, + method: "PUT", + ...params, + }), + }; +} +" +`; diff --git a/tests/spec/multipleSuccessResponses/basic.test.ts b/tests/spec/multipleSuccessResponses/basic.test.ts new file mode 100644 index 000000000..dc966c36a --- /dev/null +++ b/tests/spec/multipleSuccessResponses/basic.test.ts @@ -0,0 +1,32 @@ +import * as fs from "node:fs/promises"; +import * as os from "node:os"; +import * as path from "node:path"; +import { afterAll, beforeAll, describe, expect, test } from "vitest"; +import { generateApi } from "../../../src/index.js"; + +describe("basic", async () => { + let tmpdir = ""; + + beforeAll(async () => { + tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), "swagger-typescript-api")); + }); + + afterAll(async () => { + await fs.rm(tmpdir, { recursive: true }); + }); + + test("Multiple responses", async () => { + await generateApi({ + fileName: "schema", + input: path.resolve(import.meta.dirname, "schema.json"), + output: tmpdir, + silent: true, + }); + + const content = await fs.readFile(path.join(tmpdir, "schema.ts"), { + encoding: "utf8", + }); + + expect(content).toMatchSnapshot(); + }); +}); diff --git a/tests/spec/multipleSuccessResponses/schema.json b/tests/spec/multipleSuccessResponses/schema.json new file mode 100644 index 000000000..27de768ad --- /dev/null +++ b/tests/spec/multipleSuccessResponses/schema.json @@ -0,0 +1,225 @@ +{ + "swagger": "2.0", + "schemes": ["https"], + "host": "6-dot-authentiqio.appspot.com", + "basePath": "/", + "info": { + "contact": { + "email": "hello@authentiq.com", + "name": "Authentiq team", + "url": "http://authentiq.io/support" + }, + "description": "Strong authentication, without the passwords.", + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "termsOfService": "http://authentiq.com/terms/", + "title": "Authentiq", + "version": "6", + "x-apisguru-categories": ["security"], + "x-logo": { + "backgroundColor": "#F26641", + "url": "https://api.apis.guru/v2/cache/logo/https_www.authentiq.com_theme_images_authentiq-logo-a-inverse.svg" + }, + "x-origin": [ + { + "format": "swagger", + "url": "https://raw.githubusercontent.com/AuthentiqID/authentiq-docs/master/docs/swagger/issuer.yaml", + "version": "2.0" + } + ], + "x-preferred": true, + "x-providerName": "6-dot-authentiqio.appspot.com" + }, + "parameters": { + "AuthentiqID": { + "description": "Authentiq ID to register", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/AuthentiqID" + } + }, + "JobID": { + "description": "Job ID (20 chars)", + "in": "path", + "name": "job", + "required": true, + "type": "string" + }, + "PK": { + "description": "Public Signing Key - Authentiq ID (43 chars)", + "in": "path", + "name": "PK", + "required": true, + "type": "string" + }, + "PushToken": { + "description": "Push Token.", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/PushToken" + } + }, + "Scope": { + "description": "Claims of scope", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/Claims" + } + } + }, + "responses": { + "ErrorResponse": { + "description": "Error response", + "schema": { + "$ref": "#/definitions/Error" + } + } + }, + "paths": { + "/scope/{job}": { + "put": { + "consumes": ["application/jwt"], + "description": "authority updates a JWT with its signature\nSee: https://github.com/skion/authentiq/wiki/JWT-Examples\n", + "operationId": "sign_update", + "parameters": [ + { + "$ref": "#/parameters/JobID" + } + ], + "produces": ["application/jwt"], + "responses": { + "200": { + "description": "Successfully updated", + "schema": { + "properties": { + "jwt": { + "description": "result is JWT or JSON??", + "type": "string" + }, + "status": { + "description": "ready", + "type": "string" + } + }, + "type": "object" + } + }, + "204": { + "description": "No content" + }, + "404": { + "description": "Job not found `unknown-job`", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "409": { + "description": "Job not confirmed yet `confirm-first`", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "$ref": "#/responses/ErrorResponse" + } + }, + "tags": ["scope", "put"] + } + } + }, + "definitions": { + "AuthentiqID": { + "description": "Authentiq ID in JWT format, self-signed.\n", + "properties": { + "devtoken": { + "description": "device token for push messages", + "type": "string" + }, + "sub": { + "description": "UUID and public signing key", + "type": "string" + } + }, + "required": ["sub"] + }, + "Claims": { + "description": "Claim in JWT format, self- or issuer-signed. \n", + "properties": { + "email": { + "description": "", + "type": "string" + }, + "phone": { + "description": "", + "type": "string" + }, + "scope": { + "description": "claim scope", + "type": "string" + }, + "sub": { + "description": "UUID", + "type": "string" + }, + "type": { + "description": "", + "type": "string" + } + }, + "required": ["sub", "scope"] + }, + "Error": { + "properties": { + "detail": { + "type": "string" + }, + "error": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "type": { + "description": "unique uri for this error", + "type": "string" + } + }, + "required": ["error"] + }, + "PushToken": { + "description": "PushToken in JWT format, self-signed. \n", + "properties": { + "aud": { + "description": "audience (URI)", + "type": "string" + }, + "exp": { + "type": "integer" + }, + "iat": { + "type": "integer" + }, + "iss": { + "description": "issuer (URI)", + "type": "string" + }, + "nbf": { + "type": "integer" + }, + "sub": { + "description": "UUID and public signing key", + "type": "string" + } + }, + "required": ["sub", "iss", "aud"] + } + } +} diff --git a/tests/spec/patch/__snapshots__/basic.test.ts.snap b/tests/spec/patch/__snapshots__/basic.test.ts.snap index a307e33c9..88e03b6a7 100644 --- a/tests/spec/patch/__snapshots__/basic.test.ts.snap +++ b/tests/spec/patch/__snapshots__/basic.test.ts.snap @@ -4602,7 +4602,7 @@ export class Api< body: MergesBody, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/merges\`, method: "POST", body: body, diff --git a/tests/spec/responses/__snapshots__/basic.test.ts.snap b/tests/spec/responses/__snapshots__/basic.test.ts.snap index c368fa923..17eba6aa1 100644 --- a/tests/spec/responses/__snapshots__/basic.test.ts.snap +++ b/tests/spec/responses/__snapshots__/basic.test.ts.snap @@ -677,7 +677,7 @@ export class Api< field?: string; /** base64safe encoded public signing key */ sub?: string; - }, + } | void, Error >({ path: \`/scope/\${job}\`, diff --git a/tests/spec/sortTypes-false/__snapshots__/basic.test.ts.snap b/tests/spec/sortTypes-false/__snapshots__/basic.test.ts.snap index 69d5302ed..c020df940 100644 --- a/tests/spec/sortTypes-false/__snapshots__/basic.test.ts.snap +++ b/tests/spec/sortTypes-false/__snapshots__/basic.test.ts.snap @@ -4583,7 +4583,7 @@ export class Api< body: MergesBody, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/merges\`, method: "POST", body: body, diff --git a/tests/spec/sortTypes/__snapshots__/basic.test.ts.snap b/tests/spec/sortTypes/__snapshots__/basic.test.ts.snap index 785d970ce..8d22564df 100644 --- a/tests/spec/sortTypes/__snapshots__/basic.test.ts.snap +++ b/tests/spec/sortTypes/__snapshots__/basic.test.ts.snap @@ -4583,7 +4583,7 @@ export class Api< body: MergesBody, params: RequestParams = {}, ) => - this.request({ + this.request({ path: \`/repos/\${owner}/\${repo}/merges\`, method: "POST", body: body, diff --git a/tests/spec/typeSuffixPrefix/__snapshots__/basic.test.ts.snap b/tests/spec/typeSuffixPrefix/__snapshots__/basic.test.ts.snap index aef88befe..3fd9347e6 100644 --- a/tests/spec/typeSuffixPrefix/__snapshots__/basic.test.ts.snap +++ b/tests/spec/typeSuffixPrefix/__snapshots__/basic.test.ts.snap @@ -4952,7 +4952,7 @@ export class Api< params: RequestParams = {}, ) => this.request< - SwaggerTypeMergesSuccessfulGeneratedDataContract, + SwaggerTypeMergesSuccessfulGeneratedDataContract | void, void | SwaggerTypeMergesConflictGeneratedDataContract >({ path: \`/repos/\${owner}/\${repo}/merges\`,