api-def 0.15.0-alpha.0 → 0.15.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,12 +3,16 @@ import type { ApiResponse } from "../ApiTypes";
3
3
  import type RequestContext from "../RequestContext";
4
4
  import type RequestBackend from "./RequestBackend";
5
5
  import type { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
6
+ import { type WebSocketConstructor, type WebSocketResponse } from "./WebSocketRequest";
6
7
  export declare const isAxiosError: (error: Error) => error is AxiosError;
7
- export default class AxiosRequestBackend implements RequestBackend<AxiosResponse> {
8
+ type AxiosBackendResponse = AxiosResponse | WebSocketResponse;
9
+ export default class AxiosRequestBackend implements RequestBackend<AxiosBackendResponse> {
8
10
  readonly id = "axios";
9
- constructor(axiosLibrary: any);
10
- extractResponseFromError(error: Error): Promise<AxiosResponse | null | undefined>;
11
- convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ConvertedApiResponse<T>>;
12
- makeRequest(context: RequestContext): RequestOperation<AxiosResponse>;
11
+ webSocketConstructor: WebSocketConstructor | undefined;
12
+ constructor(axiosLibrary: any, webSocketConstructor?: WebSocketConstructor);
13
+ extractResponseFromError(error: Error): Promise<AxiosBackendResponse | null | undefined>;
14
+ convertResponse<T>(context: RequestContext, response: AxiosBackendResponse): Promise<ConvertedApiResponse<T>>;
15
+ makeRequest(context: RequestContext): RequestOperation<AxiosBackendResponse>;
13
16
  getErrorInfo(_error: Error, _response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
14
17
  }
18
+ export {};
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isAxiosError = void 0;
4
4
  const ApiUtils_1 = require("../ApiUtils");
5
+ const WebSocketRequest_1 = require("./WebSocketRequest");
5
6
  let axios;
6
7
  const isAxiosError = (error) => {
7
8
  return "isAxiosError" in error;
@@ -32,9 +33,13 @@ const getCacheHeaders = (browserCache) => {
32
33
  }
33
34
  };
34
35
  class AxiosRequestBackend {
35
- constructor(axiosLibrary) {
36
+ constructor(axiosLibrary, webSocketConstructor) {
36
37
  this.id = "axios";
38
+ this.webSocketConstructor = (0, WebSocketRequest_1.getGlobalWebSocketConstructor)();
37
39
  axios = axiosLibrary;
40
+ if (webSocketConstructor !== undefined) {
41
+ this.webSocketConstructor = webSocketConstructor;
42
+ }
38
43
  }
39
44
  async extractResponseFromError(error) {
40
45
  if ((0, exports.isAxiosError)(error)) {
@@ -43,17 +48,30 @@ class AxiosRequestBackend {
43
48
  return undefined;
44
49
  }
45
50
  async convertResponse(context, response) {
46
- const contentType = response.headers["content-type"];
51
+ if (context.responseType === "websocket") {
52
+ const webSocketResponse = response;
53
+ return {
54
+ method: context.method,
55
+ url: webSocketResponse.url,
56
+ data: webSocketResponse.webSocket,
57
+ headers: webSocketResponse.headers,
58
+ status: webSocketResponse.status,
59
+ state: context.requestConfig.state,
60
+ stats: context.stats,
61
+ };
62
+ }
63
+ const axiosResponse = response;
64
+ const contentType = axiosResponse.headers["content-type"];
47
65
  const responseType = context.responseType ?? (0, ApiUtils_1.inferResponseType)(contentType == null ? contentType : String(contentType));
48
66
  let data;
49
67
  if (responseType === "stream") {
50
68
  // For streaming responses, we create an async iterator from the response data
51
- if (!response.data) {
69
+ if (!axiosResponse.data) {
52
70
  throw new Error("[api-def] Response data is null for streaming response");
53
71
  }
54
72
  data = {
55
73
  async *[Symbol.asyncIterator]() {
56
- const stream = response.data;
74
+ const stream = axiosResponse.data;
57
75
  if (stream[Symbol.asyncIterator]) {
58
76
  yield* stream;
59
77
  }
@@ -68,22 +86,22 @@ class AxiosRequestBackend {
68
86
  };
69
87
  }
70
88
  else {
71
- data = response.data;
89
+ data = axiosResponse.data;
72
90
  }
73
91
  return {
74
92
  method: context.method,
75
- url: response.request.res?.responseUrl ?? response.request?._redirectable?._currentUrl,
93
+ url: axiosResponse.request.res?.responseUrl ?? axiosResponse.request?._redirectable?._currentUrl,
76
94
  data: data,
77
- headers: response.headers,
78
- status: response.status,
95
+ headers: axiosResponse.headers,
96
+ status: axiosResponse.status,
79
97
  state: context.requestConfig.state,
80
- __lowercaseHeaders: response._lowerCaseResponseHeaders,
98
+ __lowercaseHeaders: axiosResponse._lowerCaseResponseHeaders,
81
99
  stats: context.stats,
82
100
  };
83
101
  }
84
102
  makeRequest(context) {
85
103
  if (context.responseType === "websocket") {
86
- throw new Error("[api-def] WebSocket responseType is only supported by FetchRequestBackend");
104
+ return (0, WebSocketRequest_1.makeWebSocketRequest)(context, this.webSocketConstructor);
87
105
  }
88
106
  const { requestConfig } = context;
89
107
  const url = context.requestUrl;
@@ -3,14 +3,18 @@ import type RequestContext from "../RequestContext";
3
3
  import { type Fetch } from "../Utils";
4
4
  import type RequestBackend from "./RequestBackend";
5
5
  import type { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend";
6
- export default class FetchRequestBackend implements RequestBackend<Response> {
6
+ import { type WebSocketConstructor, type WebSocketResponse } from "./WebSocketRequest";
7
+ type FetchBackendResponse = Response | WebSocketResponse;
8
+ export default class FetchRequestBackend implements RequestBackend<FetchBackendResponse> {
7
9
  fetch: (((input: RequestInfo | URL, init?: RequestInit) => Promise<Response>) & typeof fetch) | undefined;
10
+ webSocketConstructor: WebSocketConstructor | undefined;
8
11
  readonly id = "fetch";
9
- constructor(fetchLibrary?: Fetch);
10
- extractResponseFromError(error: Error): Promise<Response | null | undefined>;
11
- convertResponse<T>(context: RequestContext, response: Response & {
12
+ constructor(fetchLibrary?: Fetch, webSocketConstructor?: WebSocketConstructor);
13
+ extractResponseFromError(error: Error): Promise<FetchBackendResponse | null | undefined>;
14
+ convertResponse<T>(context: RequestContext, response: FetchBackendResponse & {
12
15
  __text?: string;
13
16
  }): Promise<ConvertedApiResponse<T>>;
14
- makeRequest(context: RequestContext): RequestOperation<Response>;
17
+ makeRequest(context: RequestContext): RequestOperation<FetchBackendResponse>;
15
18
  getErrorInfo(_error: Error, _response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
16
19
  }
20
+ export {};
@@ -37,11 +37,13 @@ const ApiUtils_1 = require("../ApiUtils");
37
37
  const RequestError_1 = require("../RequestError");
38
38
  const Utils = __importStar(require("../Utils"));
39
39
  const Utils_1 = require("../Utils");
40
+ const WebSocketRequest_1 = require("./WebSocketRequest");
40
41
  class FetchError extends Error {
41
42
  }
42
43
  class FetchRequestBackend {
43
- constructor(fetchLibrary) {
44
+ constructor(fetchLibrary, webSocketConstructor) {
44
45
  this.fetch = (0, Utils_1.getGlobalFetch)();
46
+ this.webSocketConstructor = (0, WebSocketRequest_1.getGlobalWebSocketConstructor)();
45
47
  this.id = "fetch";
46
48
  if (fetchLibrary !== undefined) {
47
49
  this.fetch = fetchLibrary;
@@ -50,6 +52,9 @@ class FetchRequestBackend {
50
52
  this.fetch = fetchLibrary.bind((0, Utils_1.getGlobal)());
51
53
  }
52
54
  }
55
+ if (webSocketConstructor !== undefined) {
56
+ this.webSocketConstructor = webSocketConstructor;
57
+ }
53
58
  }
54
59
  async extractResponseFromError(error) {
55
60
  if ("response" in error) {
@@ -73,7 +78,13 @@ class FetchRequestBackend {
73
78
  let text;
74
79
  let data;
75
80
  try {
76
- if (responseType === "arraybuffer") {
81
+ if (responseType === "websocket") {
82
+ data = response.webSocket;
83
+ if (!data) {
84
+ throw new Error("[api-def] WebSocket response did not include a webSocket");
85
+ }
86
+ }
87
+ else if (responseType === "arraybuffer") {
77
88
  data = await response.arrayBuffer();
78
89
  }
79
90
  else if (responseType === "json") {
@@ -83,12 +94,6 @@ class FetchRequestBackend {
83
94
  else if (responseType === "stream") {
84
95
  data = response.body;
85
96
  }
86
- else if (responseType === "websocket") {
87
- data = response.webSocket;
88
- if (!data) {
89
- throw new Error("[api-def] WebSocket upgrade response did not include a webSocket");
90
- }
91
- }
92
97
  else {
93
98
  data = await response.text();
94
99
  }
@@ -116,13 +121,15 @@ class FetchRequestBackend {
116
121
  const abortSignal = abortController ? abortController.signal : undefined;
117
122
  let softAbort = false;
118
123
  let responded = false;
124
+ if (context.responseType === "websocket") {
125
+ responded = true;
126
+ return (0, WebSocketRequest_1.makeWebSocketRequest)(context, this.webSocketConstructor);
127
+ }
119
128
  const body = context.getParsedBody();
120
129
  const bodyJsonify = body !== null && typeof body === "object" && !Utils.isFormDataLike(body) && !(body instanceof URLSearchParams);
121
130
  const headers = Utils.assign({
122
131
  // logic from axios
123
132
  "Content-Type": bodyJsonify ? "application/json;charset=utf-8" : undefined,
124
- Connection: context.responseType === "websocket" ? "Upgrade" : undefined,
125
- Upgrade: context.responseType === "websocket" ? "websocket" : undefined,
126
133
  }, requestConfig.headers);
127
134
  const parsedHeaders = Object.keys(headers).reduce((parsedHeaders, key) => {
128
135
  const value = headers[key];
@@ -157,7 +164,7 @@ class FetchRequestBackend {
157
164
  }
158
165
  const promise = this.fetch(request).then((response) => {
159
166
  responded = true;
160
- if (!response.ok && !(context.responseType === "websocket" && response.status === 101)) {
167
+ if (!response.ok) {
161
168
  const error = new FetchError("Fetch failed");
162
169
  error.response = response;
163
170
  throw error;
@@ -0,0 +1,11 @@
1
+ import type RequestContext from "../RequestContext";
2
+ import type { RequestOperation } from "./RequestBackend";
3
+ export type WebSocketConstructor = new (url: string | URL, protocols?: string | string[]) => WebSocket;
4
+ export type WebSocketResponse = {
5
+ status: 101;
6
+ headers: Headers;
7
+ url: string;
8
+ webSocket: WebSocket;
9
+ };
10
+ export declare const getGlobalWebSocketConstructor: () => WebSocketConstructor | undefined;
11
+ export declare const makeWebSocketRequest: (context: RequestContext, webSocketConstructor: WebSocketConstructor | undefined) => RequestOperation<WebSocketResponse>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeWebSocketRequest = exports.getGlobalWebSocketConstructor = void 0;
4
+ const getGlobalWebSocketConstructor = () => {
5
+ return typeof WebSocket !== "undefined" ? WebSocket : undefined;
6
+ };
7
+ exports.getGlobalWebSocketConstructor = getGlobalWebSocketConstructor;
8
+ const makeWebSocketRequest = (context, webSocketConstructor) => {
9
+ if (!webSocketConstructor) {
10
+ throw new Error("[api-def] No WebSocket constructor was provided");
11
+ }
12
+ const url = context.requestUrl;
13
+ if (url.protocol === "http:") {
14
+ url.protocol = "ws:";
15
+ }
16
+ else if (url.protocol === "https:") {
17
+ url.protocol = "wss:";
18
+ }
19
+ const protocolHeader = context.requestConfig.headers?.["Sec-WebSocket-Protocol"];
20
+ const protocols = typeof protocolHeader === "string"
21
+ ? protocolHeader.split(",").map((protocol) => protocol.trim())
22
+ : typeof protocolHeader === "number" || typeof protocolHeader === "boolean"
23
+ ? String(protocolHeader)
24
+ : undefined;
25
+ const webSocket = new webSocketConstructor(url.href, protocols);
26
+ return {
27
+ promise: Promise.resolve({
28
+ status: 101,
29
+ headers: new Headers(),
30
+ url: url.href,
31
+ webSocket,
32
+ }),
33
+ canceler: () => webSocket.close(),
34
+ };
35
+ };
36
+ exports.makeWebSocketRequest = makeWebSocketRequest;
@@ -3,12 +3,16 @@ import type { ApiResponse } from "../ApiTypes.js";
3
3
  import type RequestContext from "../RequestContext.js";
4
4
  import type RequestBackend from "./RequestBackend.js";
5
5
  import type { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend.js";
6
+ import { type WebSocketConstructor, type WebSocketResponse } from "./WebSocketRequest.js";
6
7
  export declare const isAxiosError: (error: Error) => error is AxiosError;
7
- export default class AxiosRequestBackend implements RequestBackend<AxiosResponse> {
8
+ type AxiosBackendResponse = AxiosResponse | WebSocketResponse;
9
+ export default class AxiosRequestBackend implements RequestBackend<AxiosBackendResponse> {
8
10
  readonly id = "axios";
9
- constructor(axiosLibrary: any);
10
- extractResponseFromError(error: Error): Promise<AxiosResponse | null | undefined>;
11
- convertResponse<T>(context: RequestContext, response: AxiosResponse): Promise<ConvertedApiResponse<T>>;
12
- makeRequest(context: RequestContext): RequestOperation<AxiosResponse>;
11
+ webSocketConstructor: WebSocketConstructor | undefined;
12
+ constructor(axiosLibrary: any, webSocketConstructor?: WebSocketConstructor);
13
+ extractResponseFromError(error: Error): Promise<AxiosBackendResponse | null | undefined>;
14
+ convertResponse<T>(context: RequestContext, response: AxiosBackendResponse): Promise<ConvertedApiResponse<T>>;
15
+ makeRequest(context: RequestContext): RequestOperation<AxiosBackendResponse>;
13
16
  getErrorInfo(_error: Error, _response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
14
17
  }
18
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { inferResponseType } from "../ApiUtils.js";
2
+ import { getGlobalWebSocketConstructor, makeWebSocketRequest, } from "./WebSocketRequest.js";
2
3
  let axios;
3
4
  export const isAxiosError = (error) => {
4
5
  return "isAxiosError" in error;
@@ -28,9 +29,13 @@ const getCacheHeaders = (browserCache) => {
28
29
  }
29
30
  };
30
31
  export default class AxiosRequestBackend {
31
- constructor(axiosLibrary) {
32
+ constructor(axiosLibrary, webSocketConstructor) {
32
33
  this.id = "axios";
34
+ this.webSocketConstructor = getGlobalWebSocketConstructor();
33
35
  axios = axiosLibrary;
36
+ if (webSocketConstructor !== undefined) {
37
+ this.webSocketConstructor = webSocketConstructor;
38
+ }
34
39
  }
35
40
  async extractResponseFromError(error) {
36
41
  if (isAxiosError(error)) {
@@ -39,17 +44,30 @@ export default class AxiosRequestBackend {
39
44
  return undefined;
40
45
  }
41
46
  async convertResponse(context, response) {
42
- const contentType = response.headers["content-type"];
47
+ if (context.responseType === "websocket") {
48
+ const webSocketResponse = response;
49
+ return {
50
+ method: context.method,
51
+ url: webSocketResponse.url,
52
+ data: webSocketResponse.webSocket,
53
+ headers: webSocketResponse.headers,
54
+ status: webSocketResponse.status,
55
+ state: context.requestConfig.state,
56
+ stats: context.stats,
57
+ };
58
+ }
59
+ const axiosResponse = response;
60
+ const contentType = axiosResponse.headers["content-type"];
43
61
  const responseType = context.responseType ?? inferResponseType(contentType == null ? contentType : String(contentType));
44
62
  let data;
45
63
  if (responseType === "stream") {
46
64
  // For streaming responses, we create an async iterator from the response data
47
- if (!response.data) {
65
+ if (!axiosResponse.data) {
48
66
  throw new Error("[api-def] Response data is null for streaming response");
49
67
  }
50
68
  data = {
51
69
  async *[Symbol.asyncIterator]() {
52
- const stream = response.data;
70
+ const stream = axiosResponse.data;
53
71
  if (stream[Symbol.asyncIterator]) {
54
72
  yield* stream;
55
73
  }
@@ -64,22 +82,22 @@ export default class AxiosRequestBackend {
64
82
  };
65
83
  }
66
84
  else {
67
- data = response.data;
85
+ data = axiosResponse.data;
68
86
  }
69
87
  return {
70
88
  method: context.method,
71
- url: response.request.res?.responseUrl ?? response.request?._redirectable?._currentUrl,
89
+ url: axiosResponse.request.res?.responseUrl ?? axiosResponse.request?._redirectable?._currentUrl,
72
90
  data: data,
73
- headers: response.headers,
74
- status: response.status,
91
+ headers: axiosResponse.headers,
92
+ status: axiosResponse.status,
75
93
  state: context.requestConfig.state,
76
- __lowercaseHeaders: response._lowerCaseResponseHeaders,
94
+ __lowercaseHeaders: axiosResponse._lowerCaseResponseHeaders,
77
95
  stats: context.stats,
78
96
  };
79
97
  }
80
98
  makeRequest(context) {
81
99
  if (context.responseType === "websocket") {
82
- throw new Error("[api-def] WebSocket responseType is only supported by FetchRequestBackend");
100
+ return makeWebSocketRequest(context, this.webSocketConstructor);
83
101
  }
84
102
  const { requestConfig } = context;
85
103
  const url = context.requestUrl;
@@ -3,14 +3,18 @@ import type RequestContext from "../RequestContext.js";
3
3
  import { type Fetch } from "../Utils.js";
4
4
  import type RequestBackend from "./RequestBackend.js";
5
5
  import type { ConvertedApiResponse, RequestBackendErrorInfo, RequestOperation } from "./RequestBackend.js";
6
- export default class FetchRequestBackend implements RequestBackend<Response> {
6
+ import { type WebSocketConstructor, type WebSocketResponse } from "./WebSocketRequest.js";
7
+ type FetchBackendResponse = Response | WebSocketResponse;
8
+ export default class FetchRequestBackend implements RequestBackend<FetchBackendResponse> {
7
9
  fetch: (((input: RequestInfo | URL, init?: RequestInit) => Promise<Response>) & typeof fetch) | undefined;
10
+ webSocketConstructor: WebSocketConstructor | undefined;
8
11
  readonly id = "fetch";
9
- constructor(fetchLibrary?: Fetch);
10
- extractResponseFromError(error: Error): Promise<Response | null | undefined>;
11
- convertResponse<T>(context: RequestContext, response: Response & {
12
+ constructor(fetchLibrary?: Fetch, webSocketConstructor?: WebSocketConstructor);
13
+ extractResponseFromError(error: Error): Promise<FetchBackendResponse | null | undefined>;
14
+ convertResponse<T>(context: RequestContext, response: FetchBackendResponse & {
12
15
  __text?: string;
13
16
  }): Promise<ConvertedApiResponse<T>>;
14
- makeRequest(context: RequestContext): RequestOperation<Response>;
17
+ makeRequest(context: RequestContext): RequestOperation<FetchBackendResponse>;
15
18
  getErrorInfo(_error: Error, _response: ApiResponse | undefined | null): RequestBackendErrorInfo | undefined;
16
19
  }
20
+ export {};
@@ -2,11 +2,13 @@ import { inferResponseType } from "../ApiUtils.js";
2
2
  import { convertToRequestError, RequestErrorCode } from "../RequestError.js";
3
3
  import * as Utils from "../Utils.js";
4
4
  import { getGlobal, getGlobalFetch } from "../Utils.js";
5
+ import { getGlobalWebSocketConstructor, makeWebSocketRequest, } from "./WebSocketRequest.js";
5
6
  class FetchError extends Error {
6
7
  }
7
8
  export default class FetchRequestBackend {
8
- constructor(fetchLibrary) {
9
+ constructor(fetchLibrary, webSocketConstructor) {
9
10
  this.fetch = getGlobalFetch();
11
+ this.webSocketConstructor = getGlobalWebSocketConstructor();
10
12
  this.id = "fetch";
11
13
  if (fetchLibrary !== undefined) {
12
14
  this.fetch = fetchLibrary;
@@ -15,6 +17,9 @@ export default class FetchRequestBackend {
15
17
  this.fetch = fetchLibrary.bind(getGlobal());
16
18
  }
17
19
  }
20
+ if (webSocketConstructor !== undefined) {
21
+ this.webSocketConstructor = webSocketConstructor;
22
+ }
18
23
  }
19
24
  async extractResponseFromError(error) {
20
25
  if ("response" in error) {
@@ -38,7 +43,13 @@ export default class FetchRequestBackend {
38
43
  let text;
39
44
  let data;
40
45
  try {
41
- if (responseType === "arraybuffer") {
46
+ if (responseType === "websocket") {
47
+ data = response.webSocket;
48
+ if (!data) {
49
+ throw new Error("[api-def] WebSocket response did not include a webSocket");
50
+ }
51
+ }
52
+ else if (responseType === "arraybuffer") {
42
53
  data = await response.arrayBuffer();
43
54
  }
44
55
  else if (responseType === "json") {
@@ -48,12 +59,6 @@ export default class FetchRequestBackend {
48
59
  else if (responseType === "stream") {
49
60
  data = response.body;
50
61
  }
51
- else if (responseType === "websocket") {
52
- data = response.webSocket;
53
- if (!data) {
54
- throw new Error("[api-def] WebSocket upgrade response did not include a webSocket");
55
- }
56
- }
57
62
  else {
58
63
  data = await response.text();
59
64
  }
@@ -81,13 +86,15 @@ export default class FetchRequestBackend {
81
86
  const abortSignal = abortController ? abortController.signal : undefined;
82
87
  let softAbort = false;
83
88
  let responded = false;
89
+ if (context.responseType === "websocket") {
90
+ responded = true;
91
+ return makeWebSocketRequest(context, this.webSocketConstructor);
92
+ }
84
93
  const body = context.getParsedBody();
85
94
  const bodyJsonify = body !== null && typeof body === "object" && !Utils.isFormDataLike(body) && !(body instanceof URLSearchParams);
86
95
  const headers = Utils.assign({
87
96
  // logic from axios
88
97
  "Content-Type": bodyJsonify ? "application/json;charset=utf-8" : undefined,
89
- Connection: context.responseType === "websocket" ? "Upgrade" : undefined,
90
- Upgrade: context.responseType === "websocket" ? "websocket" : undefined,
91
98
  }, requestConfig.headers);
92
99
  const parsedHeaders = Object.keys(headers).reduce((parsedHeaders, key) => {
93
100
  const value = headers[key];
@@ -122,7 +129,7 @@ export default class FetchRequestBackend {
122
129
  }
123
130
  const promise = this.fetch(request).then((response) => {
124
131
  responded = true;
125
- if (!response.ok && !(context.responseType === "websocket" && response.status === 101)) {
132
+ if (!response.ok) {
126
133
  const error = new FetchError("Fetch failed");
127
134
  error.response = response;
128
135
  throw error;
@@ -0,0 +1,11 @@
1
+ import type RequestContext from "../RequestContext.js";
2
+ import type { RequestOperation } from "./RequestBackend.js";
3
+ export type WebSocketConstructor = new (url: string | URL, protocols?: string | string[]) => WebSocket;
4
+ export type WebSocketResponse = {
5
+ status: 101;
6
+ headers: Headers;
7
+ url: string;
8
+ webSocket: WebSocket;
9
+ };
10
+ export declare const getGlobalWebSocketConstructor: () => WebSocketConstructor | undefined;
11
+ export declare const makeWebSocketRequest: (context: RequestContext, webSocketConstructor: WebSocketConstructor | undefined) => RequestOperation<WebSocketResponse>;
@@ -0,0 +1,31 @@
1
+ export const getGlobalWebSocketConstructor = () => {
2
+ return typeof WebSocket !== "undefined" ? WebSocket : undefined;
3
+ };
4
+ export const makeWebSocketRequest = (context, webSocketConstructor) => {
5
+ if (!webSocketConstructor) {
6
+ throw new Error("[api-def] No WebSocket constructor was provided");
7
+ }
8
+ const url = context.requestUrl;
9
+ if (url.protocol === "http:") {
10
+ url.protocol = "ws:";
11
+ }
12
+ else if (url.protocol === "https:") {
13
+ url.protocol = "wss:";
14
+ }
15
+ const protocolHeader = context.requestConfig.headers?.["Sec-WebSocket-Protocol"];
16
+ const protocols = typeof protocolHeader === "string"
17
+ ? protocolHeader.split(",").map((protocol) => protocol.trim())
18
+ : typeof protocolHeader === "number" || typeof protocolHeader === "boolean"
19
+ ? String(protocolHeader)
20
+ : undefined;
21
+ const webSocket = new webSocketConstructor(url.href, protocols);
22
+ return {
23
+ promise: Promise.resolve({
24
+ status: 101,
25
+ headers: new Headers(),
26
+ url: url.href,
27
+ webSocket,
28
+ }),
29
+ canceler: () => webSocket.close(),
30
+ };
31
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-def",
3
- "version": "0.15.0-alpha.0",
3
+ "version": "0.15.0-alpha.1",
4
4
  "description": "Typed API definitions with middleware support",
5
5
  "main": "cjs/index.js",
6
6
  "types": "esm/index.d.ts",