@01.software/sdk 0.30.1 → 0.31.0
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/README.md +74 -20
- package/dist/client.cjs +81 -16
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +6 -6
- package/dist/client.d.ts +6 -6
- package/dist/client.js +81 -16
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-B9d9kr1d.d.ts → collection-client-ByzY3hWK.d.ts} +3 -3
- package/dist/{collection-client-QPbwimkU.d.cts → collection-client-DFXXz0vk.d.cts} +3 -3
- package/dist/{const-VZuk2tWc.d.cts → const-AytzliEu.d.cts} +4 -4
- package/dist/{const-B75IFDRi.d.ts → const-BGCP-OJL.d.ts} +4 -4
- package/dist/{index-B2WbhEgT.d.cts → index-BGEhoDUs.d.cts} +1 -1
- package/dist/{index-B2WbhEgT.d.ts → index-BGEhoDUs.d.ts} +1 -1
- package/dist/index.cjs +156 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +156 -19
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-DPjO_IbQ.d.cts → payload-types-Wa4-eC6x.d.cts} +790 -534
- package/dist/{payload-types-DPjO_IbQ.d.ts → payload-types-Wa4-eC6x.d.ts} +790 -534
- package/dist/query.cjs +63 -13
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +6 -6
- package/dist/query.d.ts +6 -6
- package/dist/query.js +63 -13
- package/dist/query.js.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +142 -17
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +32 -7
- package/dist/server.d.ts +32 -7
- package/dist/server.js +142 -17
- package/dist/server.js.map +1 -1
- package/dist/{types-Dlb2mwpX.d.cts → types-BX2mqDf6.d.ts} +46 -6
- package/dist/{types-1fBLrYU7.d.ts → types-CVA10VC-.d.ts} +6 -2
- package/dist/{types-BwT0eeaz.d.cts → types-CmLG-7RL.d.cts} +6 -2
- package/dist/{types-DuSKPiY5.d.ts → types-DChFjQGz.d.cts} +46 -6
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/webhook.d.cts +3 -3
- package/dist/webhook.d.ts +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ export function App() {
|
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
```typescript
|
|
45
|
-
// Main entry - browser client, query builder,
|
|
45
|
+
// Main entry - browser client, query builder, commerce helpers, utilities
|
|
46
46
|
import { createClient } from '@01.software/sdk'
|
|
47
47
|
|
|
48
48
|
// Server-only entry - keep Secret Key code out of browser-facing imports
|
|
@@ -72,21 +72,21 @@ types lightweight. Server, React Query, and UI features live behind explicit
|
|
|
72
72
|
sub-paths so consumers install feature peers only when they import the matching
|
|
73
73
|
entry.
|
|
74
74
|
|
|
75
|
-
| Import
|
|
76
|
-
|
|
|
77
|
-
| `@01.software/sdk`
|
|
78
|
-
| `@01.software/sdk/client`
|
|
79
|
-
| `@01.software/sdk/server`
|
|
80
|
-
| `@01.software/sdk/query`
|
|
81
|
-
| `@01.software/sdk/realtime`
|
|
82
|
-
| `@01.software/sdk/analytics/react`
|
|
83
|
-
| `@01.software/sdk/ui/rich-text`
|
|
84
|
-
| `@01.software/sdk/ui/form`
|
|
85
|
-
| `@01.software/sdk/ui/code-block`
|
|
86
|
-
| `@01.software/sdk/ui/canvas`
|
|
87
|
-
| `@01.software/sdk/ui/canvas/server` | canvas server helpers
|
|
88
|
-
| `@01.software/sdk/ui/video`
|
|
89
|
-
| `@01.software/sdk/ui/image`
|
|
75
|
+
| Import | Feature(s) | Install when used |
|
|
76
|
+
| ----------------------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
|
77
|
+
| `@01.software/sdk` | browser-safe `createClient`, commerce helpers, collection helpers, types | none |
|
|
78
|
+
| `@01.software/sdk/client` | browser-safe `createClient` entry | none |
|
|
79
|
+
| `@01.software/sdk/server` | `createServerClient`, server-only collection, commerce, and preview APIs | none; keep `secretKey` code on the server |
|
|
80
|
+
| `@01.software/sdk/query` | React Query hooks, cache helpers, `getQueryClient` | `@tanstack/react-query`, `react`, `react-dom` |
|
|
81
|
+
| `@01.software/sdk/realtime` | `RealtimeConnection`, `useRealtimeQuery` | `@tanstack/react-query`, `react`, `react-dom` |
|
|
82
|
+
| `@01.software/sdk/analytics/react` | `<Analytics />` | `react`, `react-dom` |
|
|
83
|
+
| `@01.software/sdk/ui/rich-text` | `RichTextContent`, `StyledRichTextContent` | `react`, `react-dom`, `@payloadcms/richtext-lexical` |
|
|
84
|
+
| `@01.software/sdk/ui/form` | `FormRenderer` | `react`, `react-dom` |
|
|
85
|
+
| `@01.software/sdk/ui/code-block` | `CodeBlock`, `highlight` | `react`, `react-dom`, `shiki`, `hast-util-to-jsx-runtime` |
|
|
86
|
+
| `@01.software/sdk/ui/canvas` | `CanvasRenderer`, `CanvasFrame`, `useCanvas`, `prefetchCanvas` | `react`, `react-dom`, `@tanstack/react-query`, `@xyflow/react`, `quickjs-emscripten`, `postcss`, `sucrase` |
|
|
87
|
+
| `@01.software/sdk/ui/canvas/server` | canvas server helpers | none |
|
|
88
|
+
| `@01.software/sdk/ui/video` | `VideoPlayer` | `react`, `react-dom`, `@mux/mux-player-react` |
|
|
89
|
+
| `@01.software/sdk/ui/image` | `Image` | `react`, `react-dom` |
|
|
90
90
|
|
|
91
91
|
If a feature is not listed here, it does not need a separate peer install.
|
|
92
92
|
For the full component-to-peer mapping, see
|
|
@@ -157,6 +157,20 @@ await serverQuery.prefetchQuery({
|
|
|
157
157
|
Always import `createServerClient` from `@01.software/sdk/server` so generated
|
|
158
158
|
code and bundlers do not blur the Secret Key boundary.
|
|
159
159
|
|
|
160
|
+
Server-rendered preview routes can use `server.preview.detail()` with the
|
|
161
|
+
short-lived preview token issued by Console:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const preview = await server.preview.detail(
|
|
165
|
+
{ collection: 'products', id: previewId },
|
|
166
|
+
{ previewToken },
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
For product pages, `server.commerce.product.previewDetail({ id }, {
|
|
171
|
+
previewToken })` returns the same shaped product detail as `detail()`, but allows
|
|
172
|
+
the saved draft/unpublished record addressed by the preview token.
|
|
173
|
+
|
|
160
174
|
## Getting product detail
|
|
161
175
|
|
|
162
176
|
The recommended way to fetch a single product is the shaped helper:
|
|
@@ -204,6 +218,12 @@ const href = buildProductHref(product, {
|
|
|
204
218
|
})
|
|
205
219
|
```
|
|
206
220
|
|
|
221
|
+
Selection media follows the resolved selection: a complete variant uses that
|
|
222
|
+
variant's media first; a partial option selection uses selected option-value
|
|
223
|
+
media first, then matching variant media, before falling back to listing or
|
|
224
|
+
product media. This keeps listing-card selection links and detail-page images
|
|
225
|
+
aligned without rebuilding media priority in storefront code.
|
|
226
|
+
|
|
207
227
|
`availableValuesByOptionSlug` / `availableValuesByOptionId` include
|
|
208
228
|
`availableStock`, `isUnlimited`, and `availableForSale` per value so option UIs
|
|
209
229
|
can render stock state without recalculating from variants.
|
|
@@ -246,6 +266,14 @@ Use IDs from `detail.options[].id` and `detail.options[].values[].id` when
|
|
|
246
266
|
building selection state. Slugs remain useful for display and old inbound URLs,
|
|
247
267
|
but new outbound URLs should use the codec output.
|
|
248
268
|
|
|
269
|
+
For listing cards, pass the listing group returned by
|
|
270
|
+
`buildProductListingGroupsByOption()` or the listing-groups endpoint into
|
|
271
|
+
`buildProductHref(product, group, { detail })`. The detail object lets the SDK
|
|
272
|
+
emit canonical `variant=<variantId>` or `opt.<optionId>=<valueId>` params. When
|
|
273
|
+
full detail is not available on a product-list page, pass the group without
|
|
274
|
+
`detail`; `buildProductHref()` still emits the best available selection hint and
|
|
275
|
+
the detail page can resolve it through `resolveProductSelection()`.
|
|
276
|
+
|
|
249
277
|
Do not use bare option query keys such as `?size=large`. The SDK rejects them
|
|
250
278
|
as ambiguous because product pages commonly share URLs with unrelated search,
|
|
251
279
|
filter, analytics, or framework parameters. Namespacing selection keys under
|
|
@@ -253,6 +281,32 @@ filter, analytics, or framework parameters. Namespacing selection keys under
|
|
|
253
281
|
parameters while still allowing unrelated parameters such as `utm_campaign` to
|
|
254
282
|
coexist without being interpreted as selection state.
|
|
255
283
|
|
|
284
|
+
### Product listing card helper
|
|
285
|
+
|
|
286
|
+
`buildProductListingCard(item, options?)` turns a single
|
|
287
|
+
`commerce.product.listingGroups()` response item into a render-ready
|
|
288
|
+
`ProductListingCard`. The card carries product-level hero media
|
|
289
|
+
(`product.thumbnail` -> first `product.images` -> `null`), an aggregated
|
|
290
|
+
price range across all option-value groups, and a `swatches[]` array
|
|
291
|
+
derived from groups when there is more than one. Single-group products
|
|
292
|
+
emit `swatches: []`; storefronts that disagree can read `item.groups`
|
|
293
|
+
directly.
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
import {
|
|
297
|
+
buildProductListingCard,
|
|
298
|
+
type ProductListingCard,
|
|
299
|
+
} from '@01.software/sdk'
|
|
300
|
+
|
|
301
|
+
const cards: ProductListingCard[] = response.docs.map((item) =>
|
|
302
|
+
buildProductListingCard(item, { basePath: '/shop' }),
|
|
303
|
+
)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Each swatch carries a hint-only option-value href
|
|
307
|
+
(`?opt.<optionId>=<valueId>`); the detail page resolves it through
|
|
308
|
+
`resolveProductSelection(detail, { search })`.
|
|
309
|
+
|
|
256
310
|
## Advanced: direct Payload queries (escape hatch)
|
|
257
311
|
|
|
258
312
|
Most consumers should use the helper APIs above (`commerce.product.detail`, etc.). The query builder below is the escape hatch for advanced cases the helpers do not cover: bulk operations, custom filter combinations, or fields the helper response does not expose.
|
|
@@ -283,7 +337,7 @@ await client.collections.from('products').find({
|
|
|
283
337
|
|
|
284
338
|
### `joins` — Payload join-field reverse-relations
|
|
285
339
|
|
|
286
|
-
`joins` is the correct control for Payload `type: 'join'` virtual reverse-relation fields. In this platform's schema, `products.variants`, `products.options`, `
|
|
340
|
+
`joins` is the correct control for Payload `type: 'join'` virtual reverse-relation fields. In this platform's public SDK schema, `products.variants`, `products.options`, `customers.orders`, `customers.addresses`, `posts.comments`, `article-authors.articles`, `orders.{items,transactions,fulfillments,returns}`, and similar reverse-relations are all join fields — you must use `joins` (not `depth`/`populate`) to control their pagination, sorting, filtering, and count. Internal backing joins such as product collection memberships are intentionally omitted from public SDK collection types.
|
|
287
341
|
|
|
288
342
|
```typescript
|
|
289
343
|
// Canonical product detail query — variants/options are join fields on Products
|
|
@@ -843,9 +897,9 @@ Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`: 73)
|
|
|
843
897
|
| Tenant | `tenants`, `tenant-metadata`, `tenant-logos` |
|
|
844
898
|
| Products | `products`, `product-variants`, `product-options`, `product-option-values`, `product-categories`, `product-tags`, `product-collections`, `brands`, `brand-logos` |
|
|
845
899
|
| Orders | `orders`, `order-items`, `returns`, `return-items`, `fulfillments`, `fulfillment-items`, `transactions` |
|
|
846
|
-
| Customers | `customers`, `customer-profiles`, `customer-
|
|
900
|
+
| Customers | `customers`, `customer-profiles`, `customer-addresses` |
|
|
847
901
|
| Carts | `carts`, `cart-items` |
|
|
848
|
-
| Commerce | `discounts`, `shipping-policies`
|
|
902
|
+
| Commerce | `discounts`, `shipping-policies`, `shipping-zones` |
|
|
849
903
|
| Content | `documents`, `document-categories`, `document-types`, `articles`, `article-authors`, `article-categories`, `article-tags`, `links`, `link-categories`, `link-tags` |
|
|
850
904
|
| Playlists / Tracks | `playlists`, `playlist-categories`, `playlist-tags`, `tracks`, `track-categories`, `track-tags` |
|
|
851
905
|
| Galleries | `galleries`, `gallery-categories`, `gallery-tags`, `gallery-items` |
|
|
@@ -854,7 +908,7 @@ Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`: 73)
|
|
|
854
908
|
| Live Streams | `live-streams` |
|
|
855
909
|
| Media | `images` |
|
|
856
910
|
| Forms | `forms`, `form-submissions` |
|
|
857
|
-
| Community | `posts`, `comments`, `reactions`, `reaction-types`, `bookmarks`, `post-categories`
|
|
911
|
+
| Community | `posts`, `comments`, `reactions`, `reaction-types`, `bookmarks`, `post-categories`, `customer-profile-lists` |
|
|
858
912
|
| Events | `event-calendars`, `events`, `event-categories`, `event-occurrences`, `event-tags` |
|
|
859
913
|
|
|
860
914
|
Server-only collections: `customer-groups`, `reports`, and `community-bans`
|
package/dist/client.cjs
CHANGED
|
@@ -72,8 +72,16 @@ var ValidationError = class extends SDKError {
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
var ApiError = class extends SDKError {
|
|
75
|
-
constructor(message, status, details, userMessage, suggestion) {
|
|
76
|
-
super(
|
|
75
|
+
constructor(message, status, details, userMessage, suggestion, requestId) {
|
|
76
|
+
super(
|
|
77
|
+
"API_ERROR",
|
|
78
|
+
message,
|
|
79
|
+
status,
|
|
80
|
+
details,
|
|
81
|
+
userMessage,
|
|
82
|
+
suggestion,
|
|
83
|
+
requestId
|
|
84
|
+
);
|
|
77
85
|
this.name = "ApiError";
|
|
78
86
|
}
|
|
79
87
|
};
|
|
@@ -104,19 +112,43 @@ var UsageLimitError = class extends SDKError {
|
|
|
104
112
|
};
|
|
105
113
|
var AuthError = class extends SDKError {
|
|
106
114
|
constructor(message, details, userMessage, suggestion, requestId) {
|
|
107
|
-
super(
|
|
115
|
+
super(
|
|
116
|
+
"auth_error",
|
|
117
|
+
message,
|
|
118
|
+
401,
|
|
119
|
+
details,
|
|
120
|
+
userMessage,
|
|
121
|
+
suggestion,
|
|
122
|
+
requestId
|
|
123
|
+
);
|
|
108
124
|
this.name = "AuthError";
|
|
109
125
|
}
|
|
110
126
|
};
|
|
111
127
|
var PermissionError = class extends SDKError {
|
|
112
128
|
constructor(message, details, userMessage, suggestion, requestId) {
|
|
113
|
-
super(
|
|
129
|
+
super(
|
|
130
|
+
"permission_error",
|
|
131
|
+
message,
|
|
132
|
+
403,
|
|
133
|
+
details,
|
|
134
|
+
userMessage,
|
|
135
|
+
suggestion,
|
|
136
|
+
requestId
|
|
137
|
+
);
|
|
114
138
|
this.name = "PermissionError";
|
|
115
139
|
}
|
|
116
140
|
};
|
|
117
141
|
var NotFoundError = class extends SDKError {
|
|
118
142
|
constructor(message, details, userMessage, suggestion, requestId) {
|
|
119
|
-
super(
|
|
143
|
+
super(
|
|
144
|
+
"not_found",
|
|
145
|
+
message,
|
|
146
|
+
404,
|
|
147
|
+
details,
|
|
148
|
+
userMessage,
|
|
149
|
+
suggestion,
|
|
150
|
+
requestId
|
|
151
|
+
);
|
|
120
152
|
this.name = "NotFoundError";
|
|
121
153
|
}
|
|
122
154
|
};
|
|
@@ -128,14 +160,22 @@ var ConflictError = class extends SDKError {
|
|
|
128
160
|
};
|
|
129
161
|
var RateLimitError = class extends SDKError {
|
|
130
162
|
constructor(message, retryAfter, details, userMessage, suggestion, requestId) {
|
|
131
|
-
super(
|
|
163
|
+
super(
|
|
164
|
+
"rate_limit_exceeded",
|
|
165
|
+
message,
|
|
166
|
+
429,
|
|
167
|
+
details,
|
|
168
|
+
userMessage,
|
|
169
|
+
suggestion,
|
|
170
|
+
requestId
|
|
171
|
+
);
|
|
132
172
|
this.name = "RateLimitError";
|
|
133
173
|
this.retryAfter = retryAfter;
|
|
134
174
|
}
|
|
135
175
|
};
|
|
136
176
|
var createNetworkError = (message, status, details, userMessage, suggestion) => new NetworkError(message, status, details, userMessage, suggestion);
|
|
137
177
|
var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
|
|
138
|
-
var createApiError = (message, status, details, userMessage, suggestion) => new ApiError(message, status, details, userMessage, suggestion);
|
|
178
|
+
var createApiError = (message, status, details, userMessage, suggestion, requestId) => new ApiError(message, status, details, userMessage, suggestion, requestId);
|
|
139
179
|
var createConfigError = (message, details, userMessage, suggestion) => new ConfigError(message, details, userMessage, suggestion);
|
|
140
180
|
var createTimeoutError = (message, details, userMessage, suggestion) => new TimeoutError(message, details, userMessage, suggestion);
|
|
141
181
|
var createUsageLimitError = (message, usage, details, userMessage, suggestion) => new UsageLimitError(message, usage, details, userMessage, suggestion);
|
|
@@ -143,7 +183,14 @@ var createAuthError = (message, details, userMessage, suggestion, requestId) =>
|
|
|
143
183
|
var createPermissionError = (message, details, userMessage, suggestion, requestId) => new PermissionError(message, details, userMessage, suggestion, requestId);
|
|
144
184
|
var createNotFoundError = (message, details, userMessage, suggestion, requestId) => new NotFoundError(message, details, userMessage, suggestion, requestId);
|
|
145
185
|
var createConflictError = (message, details, userMessage, suggestion, requestId) => new ConflictError(message, details, userMessage, suggestion, requestId);
|
|
146
|
-
var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(
|
|
186
|
+
var createRateLimitError = (message, retryAfter, details, userMessage, suggestion, requestId) => new RateLimitError(
|
|
187
|
+
message,
|
|
188
|
+
retryAfter,
|
|
189
|
+
details,
|
|
190
|
+
userMessage,
|
|
191
|
+
suggestion,
|
|
192
|
+
requestId
|
|
193
|
+
);
|
|
147
194
|
|
|
148
195
|
// src/core/internal/utils/credentials.ts
|
|
149
196
|
function requirePublishableKeyForSecret(apiName, publishableKey, secretKey) {
|
|
@@ -183,6 +230,22 @@ function debugLog(debug, type, message, data) {
|
|
|
183
230
|
console.groupEnd();
|
|
184
231
|
}
|
|
185
232
|
}
|
|
233
|
+
function redactSensitiveHeader(value) {
|
|
234
|
+
const prefix = value.toLowerCase().startsWith("bearer ") ? "Bearer " : "";
|
|
235
|
+
return value.length > 20 ? `${prefix}...****${value.slice(-8)}` : "****";
|
|
236
|
+
}
|
|
237
|
+
function redactSensitiveHeaders(headers) {
|
|
238
|
+
const redacted = Object.fromEntries(headers.entries());
|
|
239
|
+
if (redacted.authorization) {
|
|
240
|
+
redacted.authorization = redactSensitiveHeader(redacted.authorization);
|
|
241
|
+
}
|
|
242
|
+
if (redacted["x-preview-token"]) {
|
|
243
|
+
redacted["x-preview-token"] = redactSensitiveHeader(
|
|
244
|
+
redacted["x-preview-token"]
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return redacted;
|
|
248
|
+
}
|
|
186
249
|
function getErrorSuggestion(status) {
|
|
187
250
|
if (status === 400)
|
|
188
251
|
return "The request data failed validation. Check field values and types.";
|
|
@@ -257,6 +320,12 @@ async function parseErrorBody(response) {
|
|
|
257
320
|
return fallback;
|
|
258
321
|
}
|
|
259
322
|
}
|
|
323
|
+
function getParsedErrorSuggestion(status, parsed) {
|
|
324
|
+
if (status === 403 && parsed.reason === "origin_not_allowed") {
|
|
325
|
+
return "Add the request origin to the tenant Browser API origins, then retry the browser request.";
|
|
326
|
+
}
|
|
327
|
+
return getErrorSuggestion(status);
|
|
328
|
+
}
|
|
260
329
|
async function delay(ms) {
|
|
261
330
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
262
331
|
}
|
|
@@ -270,7 +339,7 @@ function createHttpStatusError(status, parsed, details, requestId) {
|
|
|
270
339
|
...parsed.errors && { errors: parsed.errors },
|
|
271
340
|
...parsed.body && { body: parsed.body }
|
|
272
341
|
};
|
|
273
|
-
const suggestion =
|
|
342
|
+
const suggestion = getParsedErrorSuggestion(status, parsed);
|
|
274
343
|
if (status === 400 || status === 422) {
|
|
275
344
|
return attachRequestId(
|
|
276
345
|
createValidationError(
|
|
@@ -376,11 +445,7 @@ async function httpFetch(url, options) {
|
|
|
376
445
|
if (!headers.has("Content-Type") && requestInit.body && !(requestInit.body instanceof FormData)) {
|
|
377
446
|
headers.set("Content-Type", "application/json");
|
|
378
447
|
}
|
|
379
|
-
const redactedHeaders =
|
|
380
|
-
if (redactedHeaders["authorization"]) {
|
|
381
|
-
const token = redactedHeaders["authorization"];
|
|
382
|
-
redactedHeaders["authorization"] = token.length > 20 ? `Bearer ...****${token.slice(-8)}` : "****";
|
|
383
|
-
}
|
|
448
|
+
const redactedHeaders = redactSensitiveHeaders(headers);
|
|
384
449
|
debugLog(debug, "request", url, {
|
|
385
450
|
method: requestInit.method || "GET",
|
|
386
451
|
headers: redactedHeaders,
|
|
@@ -398,7 +463,7 @@ async function httpFetch(url, options) {
|
|
|
398
463
|
debugLog(debug, "response", url, {
|
|
399
464
|
status: response.status,
|
|
400
465
|
statusText: response.statusText,
|
|
401
|
-
headers:
|
|
466
|
+
headers: redactSensitiveHeaders(response.headers)
|
|
402
467
|
});
|
|
403
468
|
if (!response.ok) {
|
|
404
469
|
if (isUsageLimitExceededResponse(response)) {
|
|
@@ -831,7 +896,7 @@ async function parseApiResponse(response, endpoint) {
|
|
|
831
896
|
if (reason === "validation_failed") {
|
|
832
897
|
throw attachRequestId(createValidationError(errorMessage, data, errorMessage), requestId);
|
|
833
898
|
}
|
|
834
|
-
if (reason === "token_expired" || reason === "token_invalid" || reason === "key_invalid" || reason === "key_revoked") {
|
|
899
|
+
if (reason === "token_expired" || reason === "token_invalid" || reason === "preview_token_invalid" || reason === "preview_token_required" || reason === "key_invalid" || reason === "key_revoked") {
|
|
835
900
|
throw attachRequestId(createAuthError(errorMessage, data, errorMessage), requestId);
|
|
836
901
|
}
|
|
837
902
|
if (reason === "forbidden") {
|