@remkoj/optimizely-cms-api 6.0.0-rc.1 → 6.0.0-rc.3
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.
- package/AGENTS.md +66 -0
- package/dist/api-client.d.ts +10 -65
- package/dist/api-client.js +18 -124
- package/dist/client/client/client.gen.js +107 -126
- package/dist/client/client/index.d.ts +2 -0
- package/dist/client/client/types.gen.d.ts +6 -3
- package/dist/client/client/utils.gen.d.ts +8 -4
- package/dist/client/client/utils.gen.js +6 -6
- package/dist/client/client.gen.d.ts +2 -2
- package/dist/client/client.gen.js +1 -1
- package/dist/client/core/auth.gen.d.ts +7 -0
- package/dist/client/core/params.gen.d.ts +2 -2
- package/dist/client/core/params.gen.js +24 -16
- package/dist/client/core/queryKeySerializer.gen.d.ts +1 -1
- package/dist/client/core/serverSentEvents.gen.d.ts +1 -1
- package/dist/client/core/serverSentEvents.gen.js +4 -6
- package/dist/client/core/types.gen.d.ts +6 -1
- package/dist/client/core/utils.gen.js +1 -1
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.js +63 -21
- package/dist/client/sdk.gen.d.ts +221 -118
- package/dist/client/sdk.gen.js +431 -180
- package/dist/client/transformers.gen.d.ts +35 -13
- package/dist/client/transformers.gen.js +341 -99
- package/dist/client/types.gen.d.ts +4383 -1300
- package/dist/client-config.d.ts +11 -0
- package/dist/client-config.js +21 -10
- package/dist/config.d.ts +39 -4
- package/dist/config.js +44 -18
- package/dist/getaccesstoken.js +22 -4
- package/dist/index.d.ts +20 -1
- package/dist/index.js +18 -4
- package/dist/types.d.ts +1 -14
- package/dist/types.js +0 -7
- package/dist/version.json +3 -3
- package/package.json +19 -8
package/AGENTS.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# @remkoj/optimizely-cms-api — usage
|
|
2
|
+
|
|
3
|
+
CMS Integration REST API client for Optimizely SaaS CMS. CommonJS module.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @remkoj/optimizely-cms-api
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Environment variables
|
|
12
|
+
|
|
13
|
+
| Variable | Required | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `OPTIMIZELY_CMS_URL` | yes | CMS instance URL, e.g. `https://<tenant>.cms.optimizely.com` |
|
|
16
|
+
| `OPTIMIZELY_CMS_CLIENT_ID` | yes | OAuth client ID |
|
|
17
|
+
| `OPTIMIZELY_CMS_CLIENT_SECRET` | yes | OAuth client secret |
|
|
18
|
+
| `OPTIMIZELY_CMS_API_BASEURL` | no | Override the API base URL |
|
|
19
|
+
| `OPTIMIZELY_CMS_USER_ID` | no | Impersonate a specific user (`actAs`) |
|
|
20
|
+
| `OPTIMIZELY_DEBUG` | no | Set to `"1"` to enable request/response logging |
|
|
21
|
+
|
|
22
|
+
## Creating a client
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createClient, readEnvConfig } from '@remkoj/optimizely-cms-api'
|
|
26
|
+
|
|
27
|
+
// From environment variables (recommended)
|
|
28
|
+
const client = createClient()
|
|
29
|
+
|
|
30
|
+
// With explicit config
|
|
31
|
+
const client = createClient({
|
|
32
|
+
base: new URL('https://<tenant>.cms.optimizely.com'),
|
|
33
|
+
clientId: '...',
|
|
34
|
+
clientSecret: '...',
|
|
35
|
+
debug: false
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Key exports
|
|
40
|
+
|
|
41
|
+
| Export | Description |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `createClient(config?)` | Creates a new API client instance. Reads env vars when config is omitted. |
|
|
44
|
+
| `readEnvConfig()` | Reads and validates env vars into `CmsIntegrationApiOptions`. |
|
|
45
|
+
| `readPartialEnvConfig()` | Reads env vars without requiring client credentials. |
|
|
46
|
+
| `isClientInstance(value)` | Type guard for `CmsIntegrationApiClient`. |
|
|
47
|
+
| `IntegrationApi.*` | All generated CMS API types (re-exported from `types.gen.ts`). |
|
|
48
|
+
| `ContentRoots` | Enum of well-known content root node GUIDs (SystemRoot, Trash, etc.). |
|
|
49
|
+
| `ApiClient` | Base client class. |
|
|
50
|
+
| `ApiError` | Error thrown when an API operation fails. |
|
|
51
|
+
| `ApiClientInstance` | Type alias for a client instance. |
|
|
52
|
+
|
|
53
|
+
## Types
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import type { CmsIntegrationApiOptions, ApiClientInstance } from '@remkoj/optimizely-cms-api'
|
|
57
|
+
import { IntegrationApi } from '@remkoj/optimizely-cms-api'
|
|
58
|
+
|
|
59
|
+
// Use IntegrationApi.ContentType, IntegrationApi.DisplayTemplate, etc.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Constraints
|
|
63
|
+
|
|
64
|
+
- CommonJS module — works with both `require()` and `import`.
|
|
65
|
+
- `ApiError` exposes `.status`, `.statusText`, `.data`, `.request`, `.response`.
|
|
66
|
+
- `ContentRoots` values are GUIDs as strings.
|
package/dist/api-client.d.ts
CHANGED
|
@@ -1,46 +1,17 @@
|
|
|
1
|
+
import { ApiClient as AbstractApiClient } from "@remkoj/hey-api-wrapper";
|
|
1
2
|
import * as Operations from './client/sdk.gen';
|
|
2
|
-
import { createClient
|
|
3
|
+
import { createClient } from './client/client';
|
|
3
4
|
import { type CmsIntegrationApiOptions } from "./config";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type OperationReturnType<RT extends (...args: any) => any> = ReturnType<RT> extends RequestResult<any, any, boolean, ResponseStyle> ? Promise<NonNullable<Awaited<ReturnType<RT>>['data']>> : never;
|
|
10
|
-
type ApiClientFunctions = {
|
|
11
|
-
readonly [KT in OperationsNames]: OperationsType[KT] extends Function ? (options?: Parameters<OperationsType[KT]>[0]) => OperationReturnType<OperationsType[KT]> : never;
|
|
12
|
-
};
|
|
13
|
-
type BaseClass = {
|
|
14
|
-
new (...args: any[]): BaseApiClient;
|
|
15
|
-
};
|
|
16
|
-
type NonConstructorKeys<T> = ({
|
|
17
|
-
[P in keyof T]: T[P] extends new () => any ? never : P;
|
|
18
|
-
})[keyof T];
|
|
19
|
-
type OmitConstructor<TBase extends BaseClass> = Pick<TBase, NonConstructorKeys<TBase>>;
|
|
20
|
-
export type ClassWithMixin<TBase extends BaseClass, Mixin> = OmitConstructor<TBase> & {
|
|
21
|
-
new (...args: ConstructorParameters<TBase>): InstanceType<TBase> & Mixin;
|
|
22
|
-
};
|
|
23
|
-
declare class BaseApiClient {
|
|
24
|
-
protected _config: CmsIntegrationApiOptions;
|
|
25
|
-
protected _client: ReturnType<typeof createClient>;
|
|
5
|
+
import type { OpenAPIV3_1 } from "openapi-types";
|
|
6
|
+
/**
|
|
7
|
+
* Base implementation of the ApiClient wrapper for the Optimizely CMS Rest API
|
|
8
|
+
*/
|
|
9
|
+
declare class BaseApiClient extends AbstractApiClient<CmsIntegrationApiOptions, ReturnType<typeof createClient>> {
|
|
26
10
|
constructor(config?: CmsIntegrationApiOptions);
|
|
27
|
-
/**
|
|
28
|
-
* Get the runtime configuration of the target CMS version.
|
|
29
|
-
*
|
|
30
|
-
* If this differs from the cmsVersion the client may not work fully or not
|
|
31
|
-
* at all.
|
|
32
|
-
*
|
|
33
|
-
* @deprecated This is based on the OPTIMIZELY_CMS_SCHEMA environment that is ignored by API client
|
|
34
|
-
*/
|
|
35
|
-
get runtimeCmsVersion(): OptiCmsVersion;
|
|
36
11
|
/**
|
|
37
12
|
* The URL of the CMS instance
|
|
38
13
|
*/
|
|
39
14
|
get cmsUrl(): URL | undefined;
|
|
40
|
-
/**
|
|
41
|
-
* Marker to indicate if the client has debugging enabled
|
|
42
|
-
*/
|
|
43
|
-
get debug(): boolean;
|
|
44
15
|
/**
|
|
45
16
|
* Detect the API Version from the URL, returning the runtime version. When
|
|
46
17
|
* this version differs from the `apiVersion` property errors can be expected.
|
|
@@ -54,37 +25,11 @@ declare class BaseApiClient {
|
|
|
54
25
|
* The CMS version for which this client was build
|
|
55
26
|
*/
|
|
56
27
|
get cmsVersion(): string;
|
|
57
|
-
|
|
58
|
-
* Retrieve the version information
|
|
59
|
-
*
|
|
60
|
-
* @returns The version information from the running instance
|
|
61
|
-
*/
|
|
62
|
-
getInstanceInfo(): Promise<InstanceApiVersionInfo>;
|
|
63
|
-
getOpenApiSpec(): Promise<any>;
|
|
28
|
+
getOpenApiSpec(): Promise<OpenAPIV3_1.Document>;
|
|
64
29
|
getSchemaItemBase(): URL | undefined;
|
|
65
30
|
}
|
|
66
|
-
export
|
|
67
|
-
|
|
68
|
-
error: unknown;
|
|
69
|
-
request: Request;
|
|
70
|
-
response: Response;
|
|
71
|
-
};
|
|
72
|
-
constructor(data: {
|
|
73
|
-
error: unknown;
|
|
74
|
-
request: Request;
|
|
75
|
-
response: Response;
|
|
76
|
-
});
|
|
77
|
-
get data(): unknown;
|
|
78
|
-
/**
|
|
79
|
-
* @deprecated use data() instead
|
|
80
|
-
*/
|
|
81
|
-
get body(): unknown;
|
|
82
|
-
get request(): unknown;
|
|
83
|
-
get response(): unknown;
|
|
84
|
-
get status(): number;
|
|
85
|
-
get statusText(): string;
|
|
86
|
-
}
|
|
87
|
-
export declare const ApiClient: ClassWithMixin<typeof BaseApiClient, ApiClientFunctions>;
|
|
31
|
+
export { ApiError } from "@remkoj/hey-api-wrapper";
|
|
32
|
+
export declare const ApiClient: import("@remkoj/hey-api-wrapper/dist/types").ClassWithMixin<typeof BaseApiClient, import("@remkoj/hey-api-wrapper/dist/types").ApiClientFunctions<typeof Operations>>;
|
|
88
33
|
export type ApiClientStatic = typeof ApiClient;
|
|
89
34
|
export type CmsIntegrationApiClient = InstanceType<typeof ApiClient>;
|
|
90
35
|
export default ApiClient;
|
package/dist/api-client.js
CHANGED
|
@@ -37,77 +37,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.ApiClient = exports.ApiError = void 0;
|
|
40
|
+
const hey_api_wrapper_1 = require("@remkoj/hey-api-wrapper");
|
|
40
41
|
const Operations = __importStar(require("./client/sdk.gen"));
|
|
41
42
|
const client_1 = require("./client/client");
|
|
42
|
-
const config_1 = require("./config");
|
|
43
|
-
const types_1 = require("./types");
|
|
44
43
|
const client_config_1 = require("./client-config");
|
|
44
|
+
const config_1 = require("./config");
|
|
45
45
|
const version_json_1 = __importDefault(require("./version.json"));
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
super(...args);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// Bind the operations
|
|
54
|
-
Object.getOwnPropertyNames(Operations).filter(isApiClientFunction).forEach(propName => {
|
|
55
|
-
async function wrapper(args) {
|
|
56
|
-
const operationArgs = {
|
|
57
|
-
throwOnError: false,
|
|
58
|
-
...args,
|
|
59
|
-
//@ts-expect-error
|
|
60
|
-
client: this._client
|
|
61
|
-
};
|
|
62
|
-
//@ts-expect-error
|
|
63
|
-
const result = await Operations[propName](operationArgs);
|
|
64
|
-
if (result.data)
|
|
65
|
-
return result.data;
|
|
66
|
-
throw new ApiError(result);
|
|
67
|
-
}
|
|
68
|
-
//@ts-expect-error
|
|
69
|
-
NewClass.prototype[propName] = wrapper;
|
|
70
|
-
});
|
|
71
|
-
// Return the new class
|
|
72
|
-
return NewClass;
|
|
73
|
-
}
|
|
74
|
-
function createIsFunctionValidator(baseType) {
|
|
75
|
-
return (propName) => {
|
|
76
|
-
return typeof (baseType[propName]) == 'function';
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
const isApiClientFunction = createIsFunctionValidator(Operations);
|
|
80
|
-
class BaseApiClient {
|
|
81
|
-
_config;
|
|
82
|
-
_client;
|
|
46
|
+
/**
|
|
47
|
+
* Base implementation of the ApiClient wrapper for the Optimizely CMS Rest API
|
|
48
|
+
*/
|
|
49
|
+
class BaseApiClient extends hey_api_wrapper_1.ApiClient {
|
|
83
50
|
constructor(config) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// Configure Client
|
|
90
|
-
if (this._config.debug) {
|
|
91
|
-
this._client.interceptors.request.use(async (request) => {
|
|
92
|
-
console.log(`🔍 [CMS API] Sending ${request.method} request to ${request.url}`);
|
|
93
|
-
return request;
|
|
94
|
-
});
|
|
95
|
-
this._client.interceptors.response.use((response, request) => {
|
|
96
|
-
console.log(`✨ [CMS API] Received response ${response.status} ${response.statusText} of type ${response.headers.get('Content-Type') ?? 'unknown'} for ${request.url}`);
|
|
97
|
-
return response;
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Get the runtime configuration of the target CMS version.
|
|
103
|
-
*
|
|
104
|
-
* If this differs from the cmsVersion the client may not work fully or not
|
|
105
|
-
* at all.
|
|
106
|
-
*
|
|
107
|
-
* @deprecated This is based on the OPTIMIZELY_CMS_SCHEMA environment that is ignored by API client
|
|
108
|
-
*/
|
|
109
|
-
get runtimeCmsVersion() {
|
|
110
|
-
return this._config.cmsVersion ?? types_1.OptiCmsVersion.CMSSAAS;
|
|
51
|
+
const apiConfig = config ?? (0, config_1.readEnvConfig)();
|
|
52
|
+
const apiClient = (0, client_1.createClient)((0, client_config_1.createClientConfig)((0, client_1.createConfig)({
|
|
53
|
+
baseUrl: 'https://api.cms.optimizely.com/v1',
|
|
54
|
+
}), config));
|
|
55
|
+
super(apiConfig, apiClient);
|
|
111
56
|
}
|
|
112
57
|
/**
|
|
113
58
|
* The URL of the CMS instance
|
|
@@ -118,19 +63,13 @@ class BaseApiClient {
|
|
|
118
63
|
const baseUrl = this._client.getConfig().baseUrl;
|
|
119
64
|
return baseUrl ? new URL(baseUrl) : undefined;
|
|
120
65
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Marker to indicate if the client has debugging enabled
|
|
123
|
-
*/
|
|
124
|
-
get debug() {
|
|
125
|
-
return this._config.debug ?? false;
|
|
126
|
-
}
|
|
127
66
|
/**
|
|
128
67
|
* Detect the API Version from the URL, returning the runtime version. When
|
|
129
68
|
* this version differs from the `apiVersion` property errors can be expected.
|
|
130
69
|
*/
|
|
131
70
|
get version() {
|
|
132
71
|
const baseUrl = this._client.getConfig().baseUrl;
|
|
133
|
-
const detectedVersion = baseUrl?.match(/^https{0,1}:\/\/.+?\/(_cms\/){0,1}([a-z0-9
|
|
72
|
+
const detectedVersion = baseUrl?.match(/^https{0,1}:\/\/.+?\/(_cms\/){0,1}([a-z0-9.]+)(\/|$)/)?.at(2);
|
|
134
73
|
return detectedVersion || "";
|
|
135
74
|
}
|
|
136
75
|
/**
|
|
@@ -145,29 +84,14 @@ class BaseApiClient {
|
|
|
145
84
|
get cmsVersion() {
|
|
146
85
|
return version_json_1.default.cms;
|
|
147
86
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Retrieve the version information
|
|
150
|
-
*
|
|
151
|
-
* @returns The version information from the running instance
|
|
152
|
-
*/
|
|
153
|
-
async getInstanceInfo() {
|
|
154
|
-
const result = await this._client.get({
|
|
155
|
-
url: '/info'
|
|
156
|
-
});
|
|
157
|
-
if (result.data) {
|
|
158
|
-
const data = result.data;
|
|
159
|
-
data.baseUrl = this._client.getConfig().baseUrl;
|
|
160
|
-
return data;
|
|
161
|
-
}
|
|
162
|
-
throw new ApiError(result);
|
|
163
|
-
}
|
|
164
87
|
async getOpenApiSpec() {
|
|
165
88
|
const result = await this._client.get({
|
|
166
89
|
url: '/docs/content-openapi.json',
|
|
90
|
+
throwOnError: false
|
|
167
91
|
});
|
|
168
|
-
if (result
|
|
92
|
+
if (this.isDataResponse(result))
|
|
169
93
|
return result.data;
|
|
170
|
-
throw new ApiError(result);
|
|
94
|
+
throw new hey_api_wrapper_1.ApiError(result);
|
|
171
95
|
}
|
|
172
96
|
getSchemaItemBase() {
|
|
173
97
|
let baseUrl = this._client.getConfig().baseUrl;
|
|
@@ -176,37 +100,7 @@ class BaseApiClient {
|
|
|
176
100
|
return baseUrl ? new URL(baseUrl) : undefined;
|
|
177
101
|
}
|
|
178
102
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (typeof data.error == 'string')
|
|
183
|
-
super(data.error);
|
|
184
|
-
else
|
|
185
|
-
super(`Optimizely CMS API Error: ${data.response.status} ${data.response.statusText}`);
|
|
186
|
-
this._ctx = data;
|
|
187
|
-
}
|
|
188
|
-
get data() {
|
|
189
|
-
return this._ctx.error;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* @deprecated use data() instead
|
|
193
|
-
*/
|
|
194
|
-
get body() {
|
|
195
|
-
return this._ctx.error;
|
|
196
|
-
}
|
|
197
|
-
get request() {
|
|
198
|
-
return this._ctx.request;
|
|
199
|
-
}
|
|
200
|
-
get response() {
|
|
201
|
-
return this._ctx.response;
|
|
202
|
-
}
|
|
203
|
-
get status() {
|
|
204
|
-
return this._ctx.response.status;
|
|
205
|
-
}
|
|
206
|
-
get statusText() {
|
|
207
|
-
return this._ctx.response.statusText;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
exports.ApiError = ApiError;
|
|
211
|
-
exports.ApiClient = applyOperations(BaseApiClient);
|
|
103
|
+
var hey_api_wrapper_2 = require("@remkoj/hey-api-wrapper");
|
|
104
|
+
Object.defineProperty(exports, "ApiError", { enumerable: true, get: function () { return hey_api_wrapper_2.ApiError; } });
|
|
105
|
+
exports.ApiClient = (0, hey_api_wrapper_1.withOperations)(BaseApiClient, Operations);
|
|
212
106
|
exports.default = exports.ApiClient;
|
|
@@ -22,10 +22,7 @@ const createClient = (config = {}) => {
|
|
|
22
22
|
serializedBody: undefined,
|
|
23
23
|
};
|
|
24
24
|
if (opts.security) {
|
|
25
|
-
await (0, utils_gen_2.setAuthParams)(
|
|
26
|
-
...opts,
|
|
27
|
-
security: opts.security,
|
|
28
|
-
});
|
|
25
|
+
await (0, utils_gen_2.setAuthParams)(opts);
|
|
29
26
|
}
|
|
30
27
|
if (opts.requestValidator) {
|
|
31
28
|
await opts.requestValidator(opts);
|
|
@@ -37,154 +34,139 @@ const createClient = (config = {}) => {
|
|
|
37
34
|
if (opts.body === undefined || opts.serializedBody === '') {
|
|
38
35
|
opts.headers.delete('Content-Type');
|
|
39
36
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
37
|
+
const resolvedOpts = opts;
|
|
38
|
+
const url = (0, utils_gen_2.buildUrl)(resolvedOpts);
|
|
39
|
+
return { opts: resolvedOpts, url };
|
|
42
40
|
};
|
|
43
41
|
const request = async (options) => {
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
redirect: 'follow',
|
|
48
|
-
...opts,
|
|
49
|
-
body: (0, utils_gen_1.getValidRequestBody)(opts),
|
|
50
|
-
};
|
|
51
|
-
let request = new Request(url, requestInit);
|
|
52
|
-
for (const fn of interceptors.request.fns) {
|
|
53
|
-
if (fn) {
|
|
54
|
-
request = await fn(request, opts);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// fetch must be assigned here, otherwise it would throw the error:
|
|
58
|
-
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
|
59
|
-
const _fetch = opts.fetch;
|
|
42
|
+
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
|
43
|
+
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
|
44
|
+
let request;
|
|
60
45
|
let response;
|
|
61
46
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
const { opts, url } = await beforeRequest(options);
|
|
48
|
+
const requestInit = {
|
|
49
|
+
redirect: 'follow',
|
|
50
|
+
...opts,
|
|
51
|
+
body: (0, utils_gen_1.getValidRequestBody)(opts),
|
|
52
|
+
};
|
|
53
|
+
request = new Request(url, requestInit);
|
|
54
|
+
for (const fn of interceptors.request.fns) {
|
|
68
55
|
if (fn) {
|
|
69
|
-
|
|
56
|
+
request = await fn(request, opts);
|
|
70
57
|
}
|
|
71
58
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
error: finalError,
|
|
81
|
-
request,
|
|
82
|
-
response: undefined,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
for (const fn of interceptors.response.fns) {
|
|
86
|
-
if (fn) {
|
|
87
|
-
response = await fn(response, request, opts);
|
|
59
|
+
// fetch must be assigned here, otherwise it would throw the error:
|
|
60
|
+
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
|
61
|
+
const _fetch = opts.fetch;
|
|
62
|
+
response = await _fetch(request);
|
|
63
|
+
for (const fn of interceptors.response.fns) {
|
|
64
|
+
if (fn) {
|
|
65
|
+
response = await fn(response, request, opts);
|
|
66
|
+
}
|
|
88
67
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
68
|
+
const result = {
|
|
69
|
+
request,
|
|
70
|
+
response,
|
|
71
|
+
};
|
|
72
|
+
if (response.ok) {
|
|
73
|
+
const parseAs = (opts.parseAs === 'auto'
|
|
74
|
+
? (0, utils_gen_2.getParseAs)(response.headers.get('Content-Type'))
|
|
75
|
+
: opts.parseAs) ?? 'json';
|
|
76
|
+
if (response.status === 204 || response.headers.get('Content-Length') === '0') {
|
|
77
|
+
let emptyData;
|
|
78
|
+
switch (parseAs) {
|
|
79
|
+
case 'arrayBuffer':
|
|
80
|
+
case 'blob':
|
|
81
|
+
case 'text':
|
|
82
|
+
emptyData = await response[parseAs]();
|
|
83
|
+
break;
|
|
84
|
+
case 'formData':
|
|
85
|
+
emptyData = new FormData();
|
|
86
|
+
break;
|
|
87
|
+
case 'stream':
|
|
88
|
+
emptyData = response.body;
|
|
89
|
+
break;
|
|
90
|
+
case 'json':
|
|
91
|
+
default:
|
|
92
|
+
emptyData = {};
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
return opts.responseStyle === 'data'
|
|
96
|
+
? emptyData
|
|
97
|
+
: {
|
|
98
|
+
data: emptyData,
|
|
99
|
+
...result,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
let data;
|
|
100
103
|
switch (parseAs) {
|
|
101
104
|
case 'arrayBuffer':
|
|
102
105
|
case 'blob':
|
|
106
|
+
case 'formData':
|
|
103
107
|
case 'text':
|
|
104
|
-
|
|
108
|
+
data = await response[parseAs]();
|
|
105
109
|
break;
|
|
106
|
-
case '
|
|
107
|
-
|
|
110
|
+
case 'json': {
|
|
111
|
+
// Some servers return 200 with no Content-Length and empty body.
|
|
112
|
+
// response.json() would throw; read as text and parse if non-empty.
|
|
113
|
+
const text = await response.text();
|
|
114
|
+
data = text ? JSON.parse(text) : {};
|
|
108
115
|
break;
|
|
116
|
+
}
|
|
109
117
|
case 'stream':
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
return opts.responseStyle === 'data'
|
|
119
|
+
? response.body
|
|
120
|
+
: {
|
|
121
|
+
data: response.body,
|
|
122
|
+
...result,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (parseAs === 'json') {
|
|
126
|
+
if (opts.responseValidator) {
|
|
127
|
+
await opts.responseValidator(data);
|
|
128
|
+
}
|
|
129
|
+
if (opts.responseTransformer) {
|
|
130
|
+
data = await opts.responseTransformer(data);
|
|
131
|
+
}
|
|
116
132
|
}
|
|
117
133
|
return opts.responseStyle === 'data'
|
|
118
|
-
?
|
|
134
|
+
? data
|
|
119
135
|
: {
|
|
120
|
-
data
|
|
136
|
+
data,
|
|
121
137
|
...result,
|
|
122
138
|
};
|
|
123
139
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
case 'formData':
|
|
129
|
-
case 'text':
|
|
130
|
-
data = await response[parseAs]();
|
|
131
|
-
break;
|
|
132
|
-
case 'json': {
|
|
133
|
-
// Some servers return 200 with no Content-Length and empty body.
|
|
134
|
-
// response.json() would throw; read as text and parse if non-empty.
|
|
135
|
-
const text = await response.text();
|
|
136
|
-
data = text ? JSON.parse(text) : {};
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
case 'stream':
|
|
140
|
-
return opts.responseStyle === 'data'
|
|
141
|
-
? response.body
|
|
142
|
-
: {
|
|
143
|
-
data: response.body,
|
|
144
|
-
...result,
|
|
145
|
-
};
|
|
140
|
+
const textError = await response.text();
|
|
141
|
+
let jsonError;
|
|
142
|
+
try {
|
|
143
|
+
jsonError = JSON.parse(textError);
|
|
146
144
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
catch {
|
|
146
|
+
// noop
|
|
147
|
+
}
|
|
148
|
+
throw jsonError ?? textError;
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
let finalError = error;
|
|
152
|
+
for (const fn of interceptors.error.fns) {
|
|
153
|
+
if (fn) {
|
|
154
|
+
finalError = await fn(finalError, response, request, options);
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
finalError = finalError || {};
|
|
158
|
+
if (throwOnError) {
|
|
159
|
+
throw finalError;
|
|
160
|
+
}
|
|
161
|
+
// TODO: we probably want to return error and improve types
|
|
162
|
+
return responseStyle === 'data'
|
|
163
|
+
? undefined
|
|
157
164
|
: {
|
|
158
|
-
|
|
159
|
-
|
|
165
|
+
error: finalError,
|
|
166
|
+
request,
|
|
167
|
+
response,
|
|
160
168
|
};
|
|
161
169
|
}
|
|
162
|
-
const textError = await response.text();
|
|
163
|
-
let jsonError;
|
|
164
|
-
try {
|
|
165
|
-
jsonError = JSON.parse(textError);
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
// noop
|
|
169
|
-
}
|
|
170
|
-
const error = jsonError ?? textError;
|
|
171
|
-
let finalError = error;
|
|
172
|
-
for (const fn of interceptors.error.fns) {
|
|
173
|
-
if (fn) {
|
|
174
|
-
finalError = (await fn(error, response, request, opts));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
finalError = finalError || {};
|
|
178
|
-
if (opts.throwOnError) {
|
|
179
|
-
throw finalError;
|
|
180
|
-
}
|
|
181
|
-
// TODO: we probably want to return error and improve types
|
|
182
|
-
return opts.responseStyle === 'data'
|
|
183
|
-
? undefined
|
|
184
|
-
: {
|
|
185
|
-
error: finalError,
|
|
186
|
-
...result,
|
|
187
|
-
};
|
|
188
170
|
};
|
|
189
171
|
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
190
172
|
const makeSseFn = (method) => async (options) => {
|
|
@@ -192,7 +174,6 @@ const createClient = (config = {}) => {
|
|
|
192
174
|
return (0, serverSentEvents_gen_1.createSseClient)({
|
|
193
175
|
...opts,
|
|
194
176
|
body: opts.body,
|
|
195
|
-
headers: opts.headers,
|
|
196
177
|
method,
|
|
197
178
|
onRequest: async (url, init) => {
|
|
198
179
|
let request = new Request(url, init);
|
|
@@ -3,6 +3,8 @@ export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
|
|
|
3
3
|
export { formDataBodySerializer, jsonBodySerializer, urlSearchParamsBodySerializer, } from '../core/bodySerializer.gen';
|
|
4
4
|
export { buildClientParams } from '../core/params.gen';
|
|
5
5
|
export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen';
|
|
6
|
+
export type { ServerSentEventsResult } from '../core/serverSentEvents.gen';
|
|
7
|
+
export type { ClientMeta } from '../core/types.gen';
|
|
6
8
|
export { createClient } from './client.gen';
|
|
7
9
|
export type { Client, ClientOptions, Config, CreateClientConfig, Options, RequestOptions, RequestResult, ResolvedRequestOptions, ResponseStyle, TDataShape, } from './types.gen';
|
|
8
10
|
export { createConfig, mergeHeaders } from './utils.gen';
|
|
@@ -63,6 +63,7 @@ export interface RequestOptions<TData = unknown, TResponseStyle extends Response
|
|
|
63
63
|
url: Url;
|
|
64
64
|
}
|
|
65
65
|
export interface ResolvedRequestOptions<TResponseStyle extends ResponseStyle = 'fields', ThrowOnError extends boolean = boolean, Url extends string = string> extends RequestOptions<unknown, TResponseStyle, ThrowOnError, Url> {
|
|
66
|
+
headers: Headers;
|
|
66
67
|
serializedBody?: string;
|
|
67
68
|
}
|
|
68
69
|
export type RequestResult<TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean, TResponseStyle extends ResponseStyle = 'fields'> = ThrowOnError extends true ? Promise<TResponseStyle extends 'data' ? TData extends Record<string, unknown> ? TData[keyof TData] : TData : {
|
|
@@ -76,8 +77,10 @@ export type RequestResult<TData = unknown, TError = unknown, ThrowOnError extend
|
|
|
76
77
|
data: undefined;
|
|
77
78
|
error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
|
|
78
79
|
}) & {
|
|
79
|
-
request
|
|
80
|
-
|
|
80
|
+
/** request may be undefined, because error may be from building the request object itself */
|
|
81
|
+
request?: Request;
|
|
82
|
+
/** response may be undefined, because error may be from building the request object itself or from a network error */
|
|
83
|
+
response?: Response;
|
|
81
84
|
}>;
|
|
82
85
|
export interface ClientOptions {
|
|
83
86
|
baseUrl?: string;
|
|
@@ -85,7 +88,7 @@ export interface ClientOptions {
|
|
|
85
88
|
throwOnError?: boolean;
|
|
86
89
|
}
|
|
87
90
|
type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
|
88
|
-
type SseFn = <TData = unknown,
|
|
91
|
+
type SseFn = <TData = unknown, _TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<never, TResponseStyle, ThrowOnError>, 'method'>) => Promise<ServerSentEventsResult<TData>>;
|
|
89
92
|
type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'> & Pick<Required<RequestOptions<TData, TResponseStyle, ThrowOnError>>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
|
90
93
|
type BuildUrlFn = <TData extends {
|
|
91
94
|
body?: unknown;
|