@remkoj/optimizely-cms-api 6.0.0-rc.1 → 6.0.0-rc.4

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.
Files changed (36) hide show
  1. package/AGENTS.md +66 -0
  2. package/dist/api-client.d.ts +10 -65
  3. package/dist/api-client.js +18 -124
  4. package/dist/client/client/client.gen.js +107 -126
  5. package/dist/client/client/index.d.ts +2 -0
  6. package/dist/client/client/types.gen.d.ts +6 -3
  7. package/dist/client/client/utils.gen.d.ts +8 -4
  8. package/dist/client/client/utils.gen.js +6 -6
  9. package/dist/client/client.gen.d.ts +2 -2
  10. package/dist/client/client.gen.js +1 -1
  11. package/dist/client/core/auth.gen.d.ts +7 -0
  12. package/dist/client/core/params.gen.d.ts +2 -2
  13. package/dist/client/core/params.gen.js +24 -16
  14. package/dist/client/core/queryKeySerializer.gen.d.ts +1 -1
  15. package/dist/client/core/serverSentEvents.gen.d.ts +1 -1
  16. package/dist/client/core/serverSentEvents.gen.js +4 -6
  17. package/dist/client/core/types.gen.d.ts +6 -1
  18. package/dist/client/core/utils.gen.js +1 -1
  19. package/dist/client/index.d.ts +3 -3
  20. package/dist/client/index.js +63 -21
  21. package/dist/client/sdk.gen.d.ts +221 -118
  22. package/dist/client/sdk.gen.js +431 -180
  23. package/dist/client/transformers.gen.d.ts +35 -13
  24. package/dist/client/transformers.gen.js +341 -99
  25. package/dist/client/types.gen.d.ts +4383 -1300
  26. package/dist/client-config.d.ts +11 -0
  27. package/dist/client-config.js +21 -10
  28. package/dist/config.d.ts +39 -4
  29. package/dist/config.js +44 -18
  30. package/dist/getaccesstoken.js +22 -4
  31. package/dist/index.d.ts +20 -1
  32. package/dist/index.js +18 -4
  33. package/dist/types.d.ts +1 -14
  34. package/dist/types.js +0 -7
  35. package/dist/version.json +3 -3
  36. 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.
@@ -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, type RequestResult, type ResponseStyle } from './client/client';
3
+ import { createClient } from './client/client';
3
4
  import { type CmsIntegrationApiOptions } from "./config";
4
- import { type InstanceApiVersionInfo, OptiCmsVersion } from "./types";
5
- type OperationsType = {
6
- -readonly [KT in keyof typeof Operations]: (typeof Operations)[KT];
7
- };
8
- type OperationsNames = keyof OperationsType;
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 declare class ApiError extends Error {
67
- protected _ctx: {
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;
@@ -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
- function applyOperations(Base) {
47
- // Create the new class
48
- class NewClass extends Base {
49
- constructor(...args) {
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
- // Store instance variables
85
- this._config = config ?? (0, config_1.readEnvConfig)();
86
- this._client = (0, client_1.createClient)((0, client_config_1.createClientConfig)((0, client_1.createConfig)({
87
- baseUrl: 'https://api.cms.optimizely.com/preview3',
88
- }), this._config));
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\.]+)(\/|$)/)?.at(2);
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.data)
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
- class ApiError extends Error {
180
- _ctx;
181
- constructor(data) {
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 url = (0, utils_gen_2.buildUrl)(opts);
41
- return { opts, url };
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
- // @ts-expect-error
45
- const { opts, url } = await beforeRequest(options);
46
- const requestInit = {
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
- response = await _fetch(request);
63
- }
64
- catch (error) {
65
- // Handle fetch exceptions (AbortError, network errors, etc.)
66
- let finalError = error;
67
- for (const fn of interceptors.error.fns) {
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
- finalError = (await fn(error, undefined, request, opts));
56
+ request = await fn(request, opts);
70
57
  }
71
58
  }
72
- finalError = finalError || {};
73
- if (opts.throwOnError) {
74
- throw finalError;
75
- }
76
- // Return error response
77
- return opts.responseStyle === 'data'
78
- ? undefined
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
- const result = {
91
- request,
92
- response,
93
- };
94
- if (response.ok) {
95
- const parseAs = (opts.parseAs === 'auto'
96
- ? (0, utils_gen_2.getParseAs)(response.headers.get('Content-Type'))
97
- : opts.parseAs) ?? 'json';
98
- if (response.status === 204 || response.headers.get('Content-Length') === '0') {
99
- let emptyData;
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
- emptyData = await response[parseAs]();
108
+ data = await response[parseAs]();
105
109
  break;
106
- case 'formData':
107
- emptyData = new FormData();
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
- emptyData = response.body;
111
- break;
112
- case 'json':
113
- default:
114
- emptyData = {};
115
- break;
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
- ? emptyData
134
+ ? data
119
135
  : {
120
- data: emptyData,
136
+ data,
121
137
  ...result,
122
138
  };
123
139
  }
124
- let data;
125
- switch (parseAs) {
126
- case 'arrayBuffer':
127
- case 'blob':
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
- if (parseAs === 'json') {
148
- if (opts.responseValidator) {
149
- await opts.responseValidator(data);
150
- }
151
- if (opts.responseTransformer) {
152
- data = await opts.responseTransformer(data);
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
- return opts.responseStyle === 'data'
156
- ? data
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
- data,
159
- ...result,
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: Request;
80
- response: Response;
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, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions<TData, TResponseStyle, ThrowOnError>, 'method'>) => Promise<ServerSentEventsResult<TData, TError>>;
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;