@sanity/client 7.26.2 → 8.1.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 +63 -341
- package/dist/browserUpload-2tz6Sdqp.js +87 -0
- package/dist/browserUpload-2tz6Sdqp.js.map +1 -0
- package/dist/browserUpload-CwpNx7Vl.js +87 -0
- package/dist/browserUpload-CwpNx7Vl.js.map +1 -0
- package/dist/config-3wiPP-sZ.js +126 -0
- package/dist/config-3wiPP-sZ.js.map +1 -0
- package/dist/csm.d.ts +122 -335
- package/dist/csm.js +79 -91
- package/dist/csm.js.map +1 -1
- package/dist/dist-C9ExSk2R.js +73 -0
- package/dist/dist-C9ExSk2R.js.map +1 -0
- package/dist/dist-Z8cIRxoB.js +69 -0
- package/dist/dist-Z8cIRxoB.js.map +1 -0
- package/dist/index.d.ts +112 -6722
- package/dist/index.js +2950 -2848
- package/dist/index.js.map +1 -1
- package/dist/{index.d.cts → index.node.d.ts} +4529 -5322
- package/dist/index.node.js +3264 -0
- package/dist/index.node.js.map +1 -0
- package/dist/isRecord-Kfmt-nk-.js +7 -0
- package/dist/isRecord-Kfmt-nk-.js.map +1 -0
- package/dist/media-library.d.ts +9 -100
- package/dist/media-library.js +36 -14
- package/dist/media-library.js.map +1 -1
- package/dist/request-BhMuKj0D.js +373 -0
- package/dist/request-BhMuKj0D.js.map +1 -0
- package/dist/request-SnMg7nUX.js +355 -0
- package/dist/request-SnMg7nUX.js.map +1 -0
- package/dist/resolveEditInfo-Cz-smq3a.js +339 -0
- package/dist/resolveEditInfo-Cz-smq3a.js.map +1 -0
- package/dist/rolldown-runtime-vyAXikos.js +9 -0
- package/dist/stega.d.ts +78 -7137
- package/dist/stega.js +27 -20
- package/dist/stega.js.map +1 -1
- package/dist/stegaClean-C18wLWau.js +21 -0
- package/dist/stegaClean-C18wLWau.js.map +1 -0
- package/dist/stegaEncodeSourceMap-DbM2fTN4.js +373 -0
- package/dist/stegaEncodeSourceMap-DbM2fTN4.js.map +1 -0
- package/dist/stegaEncodeSourceMap-YR3NQ3iz.js +163 -0
- package/dist/stegaEncodeSourceMap-YR3NQ3iz.js.map +1 -0
- package/dist/{index.browser.d.cts → types-BODIEY7F.d.ts} +4196 -5258
- package/dist/types-CfGzbXrl.d.ts +108 -0
- package/package.json +80 -142
- package/src/SanityClient.ts +101 -137
- package/src/agent/actions/AgentActionsClient.ts +12 -12
- package/src/agent/actions/commonTypes.ts +2 -1
- package/src/agent/actions/generate.ts +26 -6
- package/src/agent/actions/patch.ts +27 -7
- package/src/agent/actions/prompt.ts +19 -5
- package/src/agent/actions/transform.ts +23 -5
- package/src/agent/actions/translate.ts +23 -5
- package/src/assets/AssetsClient.ts +121 -24
- package/src/csm/applySourceDocuments.ts +5 -5
- package/src/csm/createEditUrl.ts +1 -1
- package/src/csm/draftUtils.ts +23 -5
- package/src/csm/index.ts +2 -2
- package/src/csm/studioPath.ts +2 -1
- package/src/csm/types.ts +8 -2
- package/src/data/dataMethods.ts +784 -349
- package/src/data/eventsource.ts +82 -49
- package/src/data/listen.ts +18 -23
- package/src/data/live.ts +60 -35
- package/src/data/resolveEventSourceFetch.ts +104 -0
- package/src/datasets/DatasetsClient.ts +58 -41
- package/src/defineCreateClient.ts +38 -22
- package/src/functions/FunctionsClient.ts +66 -0
- package/src/functions/invoke.ts +176 -0
- package/src/http/browserMiddleware.ts +7 -1
- package/src/http/browserUpload.ts +163 -0
- package/src/http/errors.ts +61 -6
- package/src/http/nodeMiddleware.ts +94 -30
- package/src/http/request.ts +304 -87
- package/src/http/requestOptions.ts +131 -15
- package/src/{index.browser.ts → index.node.ts} +9 -4
- package/src/index.ts +4 -3
- package/src/mediaLibrary/MediaLibraryVideoClient.ts +27 -12
- package/src/projects/ProjectsClient.ts +18 -16
- package/src/releases/ReleasesClient.ts +38 -33
- package/src/stega/index.ts +1 -2
- package/src/stega/stegaEncodeSourceMap.ts +5 -0
- package/src/stega/types.ts +2 -2
- package/src/types.ts +328 -103
- package/src/users/UsersClient.ts +10 -14
- package/src/util/shareReplayLatest.ts +1 -1
- package/src/validators.ts +1 -1
- package/src/warnings.ts +13 -2
- package/dist/_chunks-cjs/config.cjs +0 -206
- package/dist/_chunks-cjs/config.cjs.map +0 -1
- package/dist/_chunks-cjs/isRecord.cjs +0 -6
- package/dist/_chunks-cjs/isRecord.cjs.map +0 -1
- package/dist/_chunks-cjs/resolveEditInfo.cjs +0 -334
- package/dist/_chunks-cjs/resolveEditInfo.cjs.map +0 -1
- package/dist/_chunks-cjs/stegaClean.cjs +0 -46
- package/dist/_chunks-cjs/stegaClean.cjs.map +0 -1
- package/dist/_chunks-cjs/stegaEncodeSourceMap.cjs +0 -388
- package/dist/_chunks-cjs/stegaEncodeSourceMap.cjs.map +0 -1
- package/dist/_chunks-es/config.js +0 -207
- package/dist/_chunks-es/config.js.map +0 -1
- package/dist/_chunks-es/isRecord.js +0 -7
- package/dist/_chunks-es/isRecord.js.map +0 -1
- package/dist/_chunks-es/resolveEditInfo.js +0 -335
- package/dist/_chunks-es/resolveEditInfo.js.map +0 -1
- package/dist/_chunks-es/stegaClean.js +0 -47
- package/dist/_chunks-es/stegaClean.js.map +0 -1
- package/dist/_chunks-es/stegaEncodeSourceMap.js +0 -389
- package/dist/_chunks-es/stegaEncodeSourceMap.js.map +0 -1
- package/dist/csm.cjs +0 -99
- package/dist/csm.cjs.map +0 -1
- package/dist/csm.d.cts +0 -391
- package/dist/index.browser.cjs +0 -3106
- package/dist/index.browser.cjs.map +0 -1
- package/dist/index.browser.d.ts +0 -6802
- package/dist/index.browser.js +0 -3082
- package/dist/index.browser.js.map +0 -1
- package/dist/index.cjs +0 -2946
- package/dist/index.cjs.map +0 -1
- package/dist/media-library.cjs +0 -20
- package/dist/media-library.cjs.map +0 -1
- package/dist/media-library.d.cts +0 -117
- package/dist/stega.browser.cjs +0 -29
- package/dist/stega.browser.cjs.map +0 -1
- package/dist/stega.browser.d.cts +0 -7200
- package/dist/stega.browser.d.ts +0 -7200
- package/dist/stega.browser.js +0 -24
- package/dist/stega.browser.js.map +0 -1
- package/dist/stega.cjs +0 -29
- package/dist/stega.cjs.map +0 -1
- package/dist/stega.d.cts +0 -7200
- package/src/data/eventsourcePolyfill.ts +0 -7
- package/umd/.gitkeep +0 -1
- package/umd/sanityClient.js +0 -6543
- package/umd/sanityClient.min.js +0 -6
package/README.md
CHANGED
|
@@ -60,14 +60,12 @@ export async function updateDocumentTitle(_id, title) {
|
|
|
60
60
|
- [API](#api)
|
|
61
61
|
- [Creating a client instance](#creating-a-client-instance)
|
|
62
62
|
- [ESM](#esm)
|
|
63
|
-
- [CommonJS](#commonjs)
|
|
64
63
|
- [TypeScript](#typescript)
|
|
65
64
|
- [Next.js App Router](#nextjs-app-router)
|
|
66
65
|
- [Bun](#bun)
|
|
67
66
|
- [Deno](#deno)
|
|
68
67
|
- [Edge Runtime](#edge-runtime)
|
|
69
68
|
- [Browser ESM CDN](#browser-esm-cdn)
|
|
70
|
-
- [UMD](#umd)
|
|
71
69
|
- [Specifying API version](#specifying-api-version)
|
|
72
70
|
- [Request tags](#request-tags)
|
|
73
71
|
- [Performing queries](#performing-queries)
|
|
@@ -147,24 +145,12 @@ export async function updateDocumentTitle(_id, title) {
|
|
|
147
145
|
- [Getting video playback information](#getting-video-playback-information)
|
|
148
146
|
- [Working with signed playback information](#working-with-signed-playback-information)
|
|
149
147
|
- [Downloading MP4 renditions](#downloading-mp4-renditions)
|
|
148
|
+
- [Invoking functions](#invoking-functions)
|
|
149
|
+
- [Choosing a stack](#choosing-a-stack)
|
|
150
|
+
- [Scoping to an organization](#scoping-to-an-organization)
|
|
151
|
+
- [Return values and timeouts](#return-values-and-timeouts)
|
|
150
152
|
- [License](#license)
|
|
151
|
-
- [
|
|
152
|
-
- [The default `useCdn` is changed to `true`](#the-default-usecdn-is-changed-to-true)
|
|
153
|
-
- [From `v4`](#from-v4)
|
|
154
|
-
- [No longer shipping `ES5`](#no-longer-shipping-es5)
|
|
155
|
-
- [Node.js `v12` no longer supported](#nodejs-v12-no-longer-supported)
|
|
156
|
-
- [The `default` export is replaced with the named export `createClient`](#the-default-export-is-replaced-with-the-named-export-createclient)
|
|
157
|
-
- [`client.assets.delete` is removed](#clientassetsdelete-is-removed)
|
|
158
|
-
- [`client.assets.getImageUrl` is removed, replace with `@sanity/image-url`](#clientassetsgetimageurl-is-removed-replace-with-sanityimage-url)
|
|
159
|
-
- [`SanityClient` static properties moved to named exports](#sanityclient-static-properties-moved-to-named-exports)
|
|
160
|
-
- [`client.clientConfig` is removed, replace with `client.config()`](#clientclientconfig-is-removed-replace-with-clientconfig)
|
|
161
|
-
- [`client.isPromiseAPI()` is removed, replace with an `instanceof` check](#clientispromiseapi-is-removed-replace-with-an-instanceof-check)
|
|
162
|
-
- [`client.observable.isObservableAPI()` is removed, replace with an `instanceof` check](#clientobservableisobservableapi-is-removed-replace-with-an-instanceof-check)
|
|
163
|
-
- [`client._requestObservable` is removed, replace with `client.observable.request`](#client_requestobservable-is-removed-replace-with-clientobservablerequest)
|
|
164
|
-
- [`client._dataRequest` is removed, replace with `client.dataRequest`](#client_datarequest-is-removed-replace-with-clientdatarequest)
|
|
165
|
-
- [`client._create_` is removed, replace with one of `client.create`, `client.createIfNotExists` or `client.createOrReplace`](#client_create_-is-removed-replace-with-one-of-clientcreate-clientcreateifnotexists-or-clientcreateorreplace)
|
|
166
|
-
- [`client.patch.replace` is removed, replace with `client.createOrReplace`](#clientpatchreplace-is-removed-replace-with-clientcreateorreplace)
|
|
167
|
-
- [`client.auth` is removed, replace with `client.request`](#clientauth-is-removed-replace-with-clientrequest)
|
|
153
|
+
- [Migrate](#migrate)
|
|
168
154
|
|
|
169
155
|
## Requirements
|
|
170
156
|
|
|
@@ -208,24 +194,6 @@ const data = await client.fetch(`count(*)`)
|
|
|
208
194
|
console.log(`Number of documents: ${data}`)
|
|
209
195
|
```
|
|
210
196
|
|
|
211
|
-
#### [CommonJS]
|
|
212
|
-
|
|
213
|
-
```js
|
|
214
|
-
const {createClient} = require('@sanity/client')
|
|
215
|
-
|
|
216
|
-
const client = createClient({
|
|
217
|
-
projectId: 'your-project-id',
|
|
218
|
-
dataset: 'your-dataset-name',
|
|
219
|
-
useCdn: true, // set to `false` to bypass the edge cache
|
|
220
|
-
apiVersion: '2025-02-06', // use current date (YYYY-MM-DD) to target the latest API version. Note: this should always be hard coded. Setting API version based on a dynamic value (e.g. new Date()) may break your application at a random point in the future.
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
client
|
|
224
|
-
.fetch(`count(*)`)
|
|
225
|
-
.then((data) => console.log(`Number of documents: ${data}`))
|
|
226
|
-
.catch(console.error)
|
|
227
|
-
```
|
|
228
|
-
|
|
229
197
|
#### [TypeScript]
|
|
230
198
|
|
|
231
199
|
```ts
|
|
@@ -437,51 +405,6 @@ const data = await client.fetch(`count(*)`)
|
|
|
437
405
|
console.log(`Number of documents: ${data}`)
|
|
438
406
|
```
|
|
439
407
|
|
|
440
|
-
#### [UMD][unpkg-dist]
|
|
441
|
-
|
|
442
|
-
Loading the UMD script creates a `SanityClient` global that have the same exports as `import * as SanityClient from '@sanity/client'`:
|
|
443
|
-
|
|
444
|
-
```html
|
|
445
|
-
<script src="https://unpkg.com/@sanity/client"></script>
|
|
446
|
-
<!-- Unminified build for debugging -->
|
|
447
|
-
<!--<script src="https://unpkg.com/@sanity/client/umd/sanityClient.js"></script>-->
|
|
448
|
-
<script>
|
|
449
|
-
const {createClient} = SanityClient
|
|
450
|
-
|
|
451
|
-
const client = createClient({
|
|
452
|
-
projectId: 'your-project-id',
|
|
453
|
-
dataset: 'your-dataset-name',
|
|
454
|
-
useCdn: true, // set to `false` to bypass the edge cache
|
|
455
|
-
apiVersion: '2025-02-06', // use current date (YYYY-MM-DD) to target the latest API version. Note: this should always be hard coded. Setting API version based on a dynamic value (e.g. new Date()) may break your application at a random point in the future.
|
|
456
|
-
})
|
|
457
|
-
|
|
458
|
-
client.fetch(`count(*)`).then((data) => console.log(`Number of documents: ${data}`))
|
|
459
|
-
</script>
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
The `require-unpkg` library lets you consume `npm` packages from `unpkg.com` similar to how `esm.sh` lets you `import()` anything:
|
|
463
|
-
|
|
464
|
-
```html
|
|
465
|
-
<div id="results"></div>
|
|
466
|
-
<script src="https://unpkg.com/require-unpkg"></script>
|
|
467
|
-
<script>
|
|
468
|
-
;(async () => {
|
|
469
|
-
// const {createClient} = await require('@sanity/client')
|
|
470
|
-
const [$, {createClient}] = await require(['jquery', '@sanity/client'])
|
|
471
|
-
|
|
472
|
-
const client = createClient({
|
|
473
|
-
projectId: 'your-project-id',
|
|
474
|
-
dataset: 'your-dataset-name',
|
|
475
|
-
useCdn: true, // set to `false` to bypass the edge cache
|
|
476
|
-
apiVersion: '2025-02-06', // use current date (YYYY-MM-DD) to target the latest API version. Note: this should always be hard coded. Setting API version based on a dynamic value (e.g. new Date()) may break your application at a random point in the future.
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
const data = await client.fetch(`count(*)`)
|
|
480
|
-
$('#results').text(`Number of documents: ${data}`)
|
|
481
|
-
})()
|
|
482
|
-
</script>
|
|
483
|
-
```
|
|
484
|
-
|
|
485
408
|
### Specifying API version
|
|
486
409
|
|
|
487
410
|
Sanity uses ISO dates (YYYY-MM-DD) in UTC timezone for versioning. The explanation for this can be found [in the documentation][api-versioning]
|
|
@@ -1011,6 +934,8 @@ Likewise, you can also have the client return the document _before_ the mutation
|
|
|
1011
934
|
|
|
1012
935
|
If it's not relevant to know what mutations that was applied, you can also set `includeMutation` to `false` in the options, which will save some additional bandwidth by omitting the `mutation` property from the received events.
|
|
1013
936
|
|
|
937
|
+
On Cloudflare Workers, `client.listen()` and `client.live.events()` need a [`compatibility_date`](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) of `2024-11-11` or later (or the `cache_option_enabled` compatibility flag). Both open a server-sent events connection, which sets the `cache` field on the request; earlier compatibility dates throw rather than ignore it. Other runtimes are unaffected.
|
|
938
|
+
|
|
1014
939
|
### Fetch a single document
|
|
1015
940
|
|
|
1016
941
|
This will fetch a document from the [Doc endpoint](https://www.sanity.io/docs/http-doc). This endpoint cuts through any caching/indexing middleware that may involve delayed processing. As it is less scalable/performant than the other query mechanisms, it should be used sparingly. Performing a query is usually a better option.
|
|
@@ -2528,307 +2453,105 @@ if (playbackInfo.renditions?.length) {
|
|
|
2528
2453
|
|
|
2529
2454
|
Available resolutions depend on the source video but typically include `1080p`, `480p`, and `270p`.
|
|
2530
2455
|
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
MIT © [Sanity.io](https://www.sanity.io/)
|
|
2456
|
+
### Invoking functions
|
|
2534
2457
|
|
|
2535
|
-
|
|
2458
|
+
Call a Sanity Pubsub Function on demand. These APIs are available on the `client.functions` namespace.
|
|
2536
2459
|
|
|
2537
|
-
|
|
2460
|
+
Only `sanity.function.pubsub` functions can be invoked this way. Every other type is driven by its own trigger.
|
|
2538
2461
|
|
|
2539
|
-
|
|
2462
|
+
Functions are addressed by the `name` they are declared with in your blueprint. Names are unique within a stack. The client needs a `stackId` in order to resolve. Configure it once on the client, or pass it per call.
|
|
2540
2463
|
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
```diff
|
|
2464
|
+
```js
|
|
2544
2465
|
import {createClient} from '@sanity/client'
|
|
2545
2466
|
|
|
2546
|
-
|
|
2467
|
+
const client = createClient({
|
|
2547
2468
|
projectId: 'your-project-id',
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2469
|
+
apiVersion: '2025-02-19',
|
|
2470
|
+
token: 'valid-token',
|
|
2471
|
+
stackId: 'your-stack-id',
|
|
2551
2472
|
})
|
|
2552
|
-
```
|
|
2553
|
-
|
|
2554
|
-
## From `v4`
|
|
2555
|
-
|
|
2556
|
-
### No longer shipping `ES5`
|
|
2557
|
-
|
|
2558
|
-
The target is changed to [modern browsers] that supports `ES6` `class`, `{...rest}` syntax and more. You may need to update your bundler to a recent major version. Or you could configure your bundler to transpile `@sanity/client`, and `get-it`, which is the engine that powers `@sanity/client` and uses the same output target.
|
|
2559
|
-
|
|
2560
|
-
### Node.js `v12` no longer supported
|
|
2561
|
-
|
|
2562
|
-
Upgrade to the [LTS release, or one of the Maintenance releases](https://github.com/nodejs/release#release-schedule).
|
|
2563
|
-
|
|
2564
|
-
### The `default` export is replaced with the named export `createClient`
|
|
2565
|
-
|
|
2566
|
-
Before:
|
|
2567
|
-
|
|
2568
|
-
```ts
|
|
2569
|
-
import createClient from '@sanity/client'
|
|
2570
|
-
const client = createClient()
|
|
2571
|
-
```
|
|
2572
|
-
|
|
2573
|
-
```ts
|
|
2574
|
-
import SanityClient from '@sanity/client'
|
|
2575
|
-
const client = new SanityClient()
|
|
2576
|
-
```
|
|
2577
|
-
|
|
2578
|
-
After:
|
|
2579
|
-
|
|
2580
|
-
```ts
|
|
2581
|
-
import {createClient} from '@sanity/client'
|
|
2582
|
-
const client = createClient()
|
|
2583
|
-
```
|
|
2584
|
-
|
|
2585
|
-
### `client.assets.delete` is removed
|
|
2586
|
-
|
|
2587
|
-
Before:
|
|
2588
|
-
|
|
2589
|
-
```ts
|
|
2590
|
-
client.assets.delete('image', 'abc123_foobar-123x123-png')
|
|
2591
|
-
client.assets.delete('image', 'image-abc123_foobar-123x123-png')
|
|
2592
|
-
client.assets.delete({_id: 'image-abc123_foobar-123x123-png'})
|
|
2593
|
-
```
|
|
2594
|
-
|
|
2595
|
-
After:
|
|
2596
|
-
|
|
2597
|
-
```ts
|
|
2598
|
-
client.delete('image-abc123_foobar-123x123-png')
|
|
2599
|
-
```
|
|
2600
|
-
|
|
2601
|
-
### `client.assets.getImageUrl` is removed, replace with [`@sanity/image-url`](https://github.com/sanity-io/image-url)
|
|
2602
|
-
|
|
2603
|
-
Before:
|
|
2604
|
-
|
|
2605
|
-
```ts
|
|
2606
|
-
import createClient from '@sanity/client'
|
|
2607
|
-
const client = createClient({projectId: 'abc123', dataset: 'foo'})
|
|
2608
|
-
|
|
2609
|
-
client.assets.getImageUrl('image-abc123_foobar-123x123-png')
|
|
2610
|
-
client.assets.getImageUrl('image-abc123_foobar-123x123-png', {auto: 'format'})
|
|
2611
|
-
client.assets.getImageUrl({_ref: 'image-abc123_foobar-123x123-png'})
|
|
2612
|
-
client.assets.getImageUrl({_ref: 'image-abc123_foobar-123x123-png'}, {auto: 'format'})
|
|
2613
|
-
```
|
|
2614
|
-
|
|
2615
|
-
After:
|
|
2616
|
-
|
|
2617
|
-
```bash
|
|
2618
|
-
npm install @sanity/image-url
|
|
2619
|
-
```
|
|
2620
|
-
|
|
2621
|
-
```ts
|
|
2622
|
-
import imageUrlBuilder from '@sanity/image-url'
|
|
2623
|
-
const builder = imageUrlBuilder({projectId: 'abc123', dataset: 'foo'})
|
|
2624
|
-
const urlFor = (source) => builder.image(source)
|
|
2625
|
-
|
|
2626
|
-
urlFor('image-abc123_foobar-123x123-png').url()
|
|
2627
|
-
urlFor('image-abc123_foobar-123x123-png').auto('format').url()
|
|
2628
|
-
urlFor({_ref: 'image-abc123_foobar-123x123-png'}).url()
|
|
2629
|
-
urlFor({_ref: 'image-abc123_foobar-123x123-png'}).auto('format').url()
|
|
2630
|
-
```
|
|
2631
|
-
|
|
2632
|
-
### `SanityClient` static properties moved to named exports
|
|
2633
2473
|
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
import SanityClient from '@sanity/client'
|
|
2638
|
-
|
|
2639
|
-
const {Patch, Transaction, ClientError, ServerError, requester} = SanityClient
|
|
2640
|
-
```
|
|
2641
|
-
|
|
2642
|
-
After:
|
|
2643
|
-
|
|
2644
|
-
```ts
|
|
2645
|
-
import {Patch, Transaction, ClientError, ServerError, requester} from '@sanity/client'
|
|
2646
|
-
```
|
|
2647
|
-
|
|
2648
|
-
### `client.clientConfig` is removed, replace with `client.config()`
|
|
2649
|
-
|
|
2650
|
-
Before:
|
|
2651
|
-
|
|
2652
|
-
```ts
|
|
2653
|
-
import createClient from '@sanity/client'
|
|
2654
|
-
const client = createClient()
|
|
2655
|
-
|
|
2656
|
-
console.log(client.clientConfig.projectId)
|
|
2657
|
-
```
|
|
2658
|
-
|
|
2659
|
-
After:
|
|
2660
|
-
|
|
2661
|
-
```ts
|
|
2662
|
-
import {createClient} from '@sanity/client'
|
|
2663
|
-
const client = createClient()
|
|
2664
|
-
|
|
2665
|
-
console.log(client.config().projectId)
|
|
2666
|
-
```
|
|
2667
|
-
|
|
2668
|
-
### `client.isPromiseAPI()` is removed, replace with an `instanceof` check
|
|
2669
|
-
|
|
2670
|
-
Before:
|
|
2671
|
-
|
|
2672
|
-
```ts
|
|
2673
|
-
import createClient from '@sanity/client'
|
|
2674
|
-
const client = createClient()
|
|
2675
|
-
|
|
2676
|
-
console.log(client.isPromiseAPI())
|
|
2677
|
-
console.log(client.clientConfig.isPromiseAPI)
|
|
2678
|
-
console.log(client.config().isPromiseAPI)
|
|
2679
|
-
```
|
|
2680
|
-
|
|
2681
|
-
After:
|
|
2682
|
-
|
|
2683
|
-
```ts
|
|
2684
|
-
import {createClient, SanityClient} from '@sanity/client'
|
|
2685
|
-
const client = createClient()
|
|
2686
|
-
|
|
2687
|
-
console.log(client instanceof SanityClient)
|
|
2688
|
-
```
|
|
2689
|
-
|
|
2690
|
-
### `client.observable.isObservableAPI()` is removed, replace with an `instanceof` check
|
|
2691
|
-
|
|
2692
|
-
Before:
|
|
2693
|
-
|
|
2694
|
-
```ts
|
|
2695
|
-
import createClient from '@sanity/client'
|
|
2696
|
-
const client = createClient()
|
|
2697
|
-
|
|
2698
|
-
console.log(client.observable.isObservableAPI())
|
|
2474
|
+
const result = await client.functions.invoke('my-function', {
|
|
2475
|
+
event: {data: {hello: 'world'}},
|
|
2476
|
+
})
|
|
2699
2477
|
```
|
|
2700
2478
|
|
|
2701
|
-
|
|
2479
|
+
The payload given as `event.data` is what the function receives as `event.data`. It defaults to `{}` when omitted.
|
|
2702
2480
|
|
|
2703
|
-
|
|
2704
|
-
import {createClient, ObservableSanityClient} from '@sanity/client'
|
|
2705
|
-
const client = createClient()
|
|
2706
|
-
|
|
2707
|
-
console.log(client.observable instanceof ObservableSanityClient)
|
|
2708
|
-
```
|
|
2481
|
+
Both Promise and Observable forms are available:
|
|
2709
2482
|
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
Before:
|
|
2483
|
+
- `client.functions.invoke(name, request)` resolves with the function's return value
|
|
2484
|
+
- `client.observable.functions.invoke(name, request)` emits it and completes
|
|
2713
2485
|
|
|
2714
2486
|
```ts
|
|
2715
|
-
|
|
2716
|
-
const
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
```
|
|
2720
|
-
|
|
2721
|
-
After:
|
|
2722
|
-
|
|
2723
|
-
```ts
|
|
2724
|
-
import {createClient} from '@sanity/client'
|
|
2725
|
-
const client = createClient()
|
|
2726
|
-
|
|
2727
|
-
client.observable.request({uri: '/ping'}).subscribe()
|
|
2487
|
+
// The return value is typed through the generic; it is not validated at runtime
|
|
2488
|
+
const summary = await client.functions.invoke<{words: number}>('summarize', {
|
|
2489
|
+
event: {data: {documentId: 'abc123'}},
|
|
2490
|
+
})
|
|
2728
2491
|
```
|
|
2729
2492
|
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
Before:
|
|
2493
|
+
#### Choosing a stack
|
|
2733
2494
|
|
|
2734
|
-
|
|
2735
|
-
import createClient from '@sanity/client'
|
|
2736
|
-
const client = createClient()
|
|
2495
|
+
`stackId` on the request wins over `stackId` in the client config, which lets one client reach functions in more than one stack:
|
|
2737
2496
|
|
|
2738
|
-
|
|
2497
|
+
```js
|
|
2498
|
+
await client.functions.invoke('my-function', {stackId: 'another-stack-id'})
|
|
2739
2499
|
```
|
|
2740
2500
|
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
```ts
|
|
2744
|
-
import {createClient} from '@sanity/client'
|
|
2745
|
-
const client = createClient()
|
|
2746
|
-
|
|
2747
|
-
client.dataRequest(endpoint, body, options)
|
|
2748
|
-
```
|
|
2501
|
+
Resolving the name takes one extra request per call: the client reads the stack to find the function, then invokes it. If neither the request nor the config supplies a `stackId`, the call rejects without touching the network.
|
|
2749
2502
|
|
|
2750
|
-
|
|
2503
|
+
Invoking a name the stack doesn't declare or a non-pubsub function rejects.
|
|
2751
2504
|
|
|
2752
|
-
|
|
2505
|
+
#### Scoping to an organization
|
|
2753
2506
|
|
|
2754
|
-
|
|
2755
|
-
import createClient from '@sanity/client'
|
|
2756
|
-
const client = createClient()
|
|
2507
|
+
Project scope is the default. For an organization-scoped stack, set `organizationId`:
|
|
2757
2508
|
|
|
2758
|
-
|
|
2759
|
-
client
|
|
2760
|
-
|
|
2509
|
+
```js
|
|
2510
|
+
const client = createClient({
|
|
2511
|
+
projectId: 'your-project-id',
|
|
2512
|
+
apiVersion: '2025-02-19',
|
|
2513
|
+
token: 'valid-token',
|
|
2514
|
+
stackId: 'your-stack-id',
|
|
2515
|
+
organizationId: 'your-organization-id',
|
|
2516
|
+
})
|
|
2761
2517
|
```
|
|
2762
2518
|
|
|
2763
|
-
|
|
2519
|
+
It can also be passed per call, and wins over the client config:
|
|
2764
2520
|
|
|
2765
|
-
```
|
|
2766
|
-
|
|
2767
|
-
const client = createClient()
|
|
2768
|
-
|
|
2769
|
-
client.create(doc, options)
|
|
2770
|
-
client.createIfNotExists(doc, options)
|
|
2771
|
-
client.createOrReplace(doc, options)
|
|
2521
|
+
```js
|
|
2522
|
+
await client.functions.invoke('my-function', {organizationId: 'another-organization-id'})
|
|
2772
2523
|
```
|
|
2773
2524
|
|
|
2774
|
-
|
|
2525
|
+
An `organizationId` takes precedence over `projectId`, since a stack is only ever resolvable at one scope. `projectId` becomes optional in that case, provided the client is also configured with `useProjectHostname: false`.
|
|
2775
2526
|
|
|
2776
|
-
|
|
2527
|
+
Scope has to match the token. A project-scoped token gets `403` on an organization-scoped stack; mint one that matches with `sanity blueprints mint-deploy-token --organization-id <id>`.
|
|
2777
2528
|
|
|
2778
|
-
|
|
2779
|
-
import createClient from '@sanity/client'
|
|
2780
|
-
const client = createClient()
|
|
2529
|
+
#### Return values and timeouts
|
|
2781
2530
|
|
|
2782
|
-
|
|
2783
|
-
```
|
|
2531
|
+
The request stays open until the function finishes, and resolves with whatever it returned. A function that returns nothing resolves to `undefined`.
|
|
2784
2532
|
|
|
2785
|
-
|
|
2533
|
+
Requests time out after five minutes by default, so a longer-running function needs an explicit `timeout` (in milliseconds, `0` to disable it). A call can be aborted with an `AbortSignal` like any other request:
|
|
2786
2534
|
|
|
2787
|
-
```
|
|
2788
|
-
|
|
2789
|
-
const client = createClient()
|
|
2535
|
+
```js
|
|
2536
|
+
const controller = new AbortController()
|
|
2790
2537
|
|
|
2791
|
-
client.
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
name: 'Tropical Habanero',
|
|
2795
|
-
ingredients: [],
|
|
2538
|
+
const result = await client.functions.invoke('slow-function', {
|
|
2539
|
+
timeout: 0, // or e.g. 600000 for a ten minute deadline
|
|
2540
|
+
signal: controller.signal,
|
|
2796
2541
|
})
|
|
2797
2542
|
```
|
|
2798
2543
|
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
Before:
|
|
2802
|
-
|
|
2803
|
-
```ts
|
|
2804
|
-
import createClient from '@sanity/client'
|
|
2805
|
-
const client = createClient()
|
|
2544
|
+
## License
|
|
2806
2545
|
|
|
2807
|
-
|
|
2808
|
-
* Fetch available login providers
|
|
2809
|
-
*/
|
|
2810
|
-
const loginProviders = await client.auth.getLoginProviders()
|
|
2811
|
-
/**
|
|
2812
|
-
* Revoke the configured session/token
|
|
2813
|
-
*/
|
|
2814
|
-
await client.auth.logout()
|
|
2815
|
-
```
|
|
2546
|
+
MIT © [Sanity.io](https://www.sanity.io/)
|
|
2816
2547
|
|
|
2817
|
-
|
|
2548
|
+
# Migrate
|
|
2818
2549
|
|
|
2819
|
-
|
|
2820
|
-
import {createclient, type AuthProviderResponse} from '@sanity/client'
|
|
2821
|
-
const client = createClient()
|
|
2550
|
+
Migration guides for major version upgrades:
|
|
2822
2551
|
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
const loginProviders = await client.request<AuthProviderResponse>({uri: '/auth/providers'})
|
|
2827
|
-
/**
|
|
2828
|
-
* Revoke the configured session/token
|
|
2829
|
-
*/
|
|
2830
|
-
await client.request<void>({uri: '/auth/logout', method: 'POST'})
|
|
2831
|
-
```
|
|
2552
|
+
- From `v7`: [docs/MIGRATE-v7.md](docs/MIGRATE-v7.md)
|
|
2553
|
+
- From `v5`: [docs/MIGRATE-v5.md](docs/MIGRATE-v5.md)
|
|
2554
|
+
- From `v4`: [docs/MIGRATE-v4.md](docs/MIGRATE-v4.md)
|
|
2832
2555
|
|
|
2833
2556
|
[modern browsers]: https://browsersl.ist/#q=%3E+0.2%25+and+supports+es6-module+and+supports+es6-module-dynamic-import+and+not+dead+and+not+IE+11
|
|
2834
2557
|
[Deno]: https://deno.land/
|
|
@@ -2836,7 +2559,6 @@ await client.request<void>({uri: '/auth/logout', method: 'POST'})
|
|
|
2836
2559
|
[Bun]: https://bun.sh/
|
|
2837
2560
|
[gzip-badge]: https://img.shields.io/bundlephobia/minzip/@sanity/client?label=gzip%20size&style=flat-square
|
|
2838
2561
|
[size-badge]: https://img.shields.io/bundlephobia/min/@sanity/client?label=size&style=flat-square
|
|
2839
|
-
[unpkg-dist]: https://unpkg.com/@sanity/client/umd/
|
|
2840
2562
|
[bundlephobia]: https://bundlephobia.com/package/@sanity/client
|
|
2841
2563
|
[esm.sh]: https://esm.sh
|
|
2842
2564
|
[Node.js]: https://nodejs.org/en/
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { a as ServerError, n as parseJsonText, r as ClientError, s as httpResponseFromFetch } from "./request-SnMg7nUX.js";
|
|
2
|
+
import { Observable } from "rxjs";
|
|
3
|
+
import { createDebug } from "obug";
|
|
4
|
+
const log = createDebug("sanity:client");
|
|
5
|
+
let nextRequestId = 1;
|
|
6
|
+
/**
|
|
7
|
+
* Run an asset upload through `XMLHttpRequest` so we can surface per-chunk
|
|
8
|
+
* upload progress events. get-it v9 / fetch has no equivalent hook in the
|
|
9
|
+
* browser, so the observable asset-upload API falls back to this path when
|
|
10
|
+
* `XMLHttpRequest` is available.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
function uploadWithProgress(options) {
|
|
15
|
+
return new Observable((subscriber) => {
|
|
16
|
+
let xhr = new XMLHttpRequest(), requestId = nextRequestId++, { url, method, headers, body, withCredentials, timeout, signal } = options;
|
|
17
|
+
log("[%d] %s %s (XHR upload with progress)", requestId, method, url), xhr.open(method, url), xhr.withCredentials = withCredentials, typeof timeout == "number" && timeout > 0 && (xhr.timeout = timeout);
|
|
18
|
+
for (let [key, value] of Object.entries(headers)) xhr.setRequestHeader(key, value);
|
|
19
|
+
xhr.upload.onprogress = (e) => {
|
|
20
|
+
subscriber.next({
|
|
21
|
+
type: "progress",
|
|
22
|
+
stage: "upload",
|
|
23
|
+
percent: e.lengthComputable ? Math.round(e.loaded / e.total * 100) : 0,
|
|
24
|
+
total: e.total || void 0,
|
|
25
|
+
loaded: e.loaded,
|
|
26
|
+
lengthComputable: e.lengthComputable
|
|
27
|
+
});
|
|
28
|
+
}, xhr.onload = () => {
|
|
29
|
+
if (log("[%d] %s %s — %d", requestId, method, url, xhr.status), xhr.status >= 400) {
|
|
30
|
+
let errorHeaders = parseXhrResponseHeaders(xhr.getAllResponseHeaders()), canonical = httpResponseFromFetch({
|
|
31
|
+
status: xhr.status,
|
|
32
|
+
statusText: xhr.statusText,
|
|
33
|
+
headers: errorHeaders,
|
|
34
|
+
body: parseJsonText(xhr.responseText, errorHeaders),
|
|
35
|
+
url: xhr.responseURL
|
|
36
|
+
}, url, method);
|
|
37
|
+
subscriber.error(xhr.status >= 500 ? new ServerError(canonical) : new ClientError(canonical));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let responseBody;
|
|
41
|
+
try {
|
|
42
|
+
responseBody = JSON.parse(xhr.responseText);
|
|
43
|
+
} catch {
|
|
44
|
+
subscriber.error(/* @__PURE__ */ Error("Failed to parse upload response as JSON"));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
subscriber.next({
|
|
48
|
+
type: "response",
|
|
49
|
+
body: responseBody
|
|
50
|
+
}), subscriber.complete();
|
|
51
|
+
}, xhr.onerror = () => {
|
|
52
|
+
log("[%d] %s %s — network error", requestId, method, url), subscriber.error(/* @__PURE__ */ Error("XHR upload network error"));
|
|
53
|
+
}, xhr.ontimeout = () => {
|
|
54
|
+
log("[%d] %s %s — timed out after %dms", requestId, method, url, timeout), subscriber.error(new DOMException(`The operation timed out after ${timeout}ms while attempting to reach ${url}`, "TimeoutError"));
|
|
55
|
+
}, xhr.onabort = () => {
|
|
56
|
+
subscriber.error(new DOMException("Upload aborted", "AbortError"));
|
|
57
|
+
};
|
|
58
|
+
let onSignalAbort = () => xhr.abort();
|
|
59
|
+
if (signal) {
|
|
60
|
+
if (signal.aborted) {
|
|
61
|
+
subscriber.error(new DOMException("Upload aborted", "AbortError"));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
signal.addEventListener("abort", onSignalAbort, { once: !0 });
|
|
65
|
+
}
|
|
66
|
+
return xhr.send(body), () => {
|
|
67
|
+
signal?.removeEventListener("abort", onSignalAbort), xhr.abort();
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parse `XMLHttpRequest.getAllResponseHeaders()` output (CRLF-separated
|
|
73
|
+
* `name: value` lines) into a `Headers` instance.
|
|
74
|
+
*/
|
|
75
|
+
function parseXhrResponseHeaders(raw) {
|
|
76
|
+
let headers = new Headers();
|
|
77
|
+
for (let line of raw.split("\r\n")) {
|
|
78
|
+
let separator = line.indexOf(":");
|
|
79
|
+
if (!(separator <= 0)) try {
|
|
80
|
+
headers.append(line.slice(0, separator).trim(), line.slice(separator + 1).trim());
|
|
81
|
+
} catch {}
|
|
82
|
+
}
|
|
83
|
+
return headers;
|
|
84
|
+
}
|
|
85
|
+
export { uploadWithProgress };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=browserUpload-2tz6Sdqp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserUpload-2tz6Sdqp.js","names":[],"sources":["../src/http/browserUpload.ts"],"sourcesContent":["import {createDebug} from 'obug'\nimport {Observable} from 'rxjs'\n\nimport type {UploadEvent} from '../types'\nimport {ClientError, httpResponseFromFetch, ServerError} from './errors'\nimport {parseJsonText} from './request'\n\nconst log = createDebug('sanity:client')\n\nlet nextRequestId = 1\n\n/**\n * Options for a browser-side asset upload that needs progress events.\n *\n * @internal\n */\nexport interface BrowserUploadOptions {\n url: string\n method: string\n headers: Record<string, string>\n body: unknown\n withCredentials: boolean\n /** Milliseconds before the upload is aborted; `false` and `0` both disable the timeout. */\n timeout?: number | false\n signal?: AbortSignal\n}\n\n/**\n * Run an asset upload through `XMLHttpRequest` so we can surface per-chunk\n * upload progress events. get-it v9 / fetch has no equivalent hook in the\n * browser, so the observable asset-upload API falls back to this path when\n * `XMLHttpRequest` is available.\n *\n * @internal\n */\nexport function uploadWithProgress<T>(options: BrowserUploadOptions): Observable<UploadEvent<T>> {\n return new Observable<UploadEvent<T>>((subscriber) => {\n const xhr = new XMLHttpRequest()\n const requestId = nextRequestId++\n const {url, method, headers, body, withCredentials, timeout, signal} = options\n\n log('[%d] %s %s (XHR upload with progress)', requestId, method, url)\n\n xhr.open(method, url)\n xhr.withCredentials = withCredentials\n if (typeof timeout === 'number' && timeout > 0) {\n xhr.timeout = timeout\n }\n\n for (const [key, value] of Object.entries(headers)) {\n xhr.setRequestHeader(key, value)\n }\n\n xhr.upload.onprogress = (e) => {\n subscriber.next({\n type: 'progress',\n stage: 'upload',\n percent: e.lengthComputable ? Math.round((e.loaded / e.total) * 100) : 0,\n total: e.total || undefined,\n loaded: e.loaded,\n lengthComputable: e.lengthComputable,\n })\n }\n\n xhr.onload = () => {\n log('[%d] %s %s — %d', requestId, method, url, xhr.status)\n\n if (xhr.status >= 400) {\n // Same typed errors as the fetch transport, so consumers can keep\n // detecting `ClientError`/`ServerError` and reading `statusCode`,\n // `responseBody` and the structured API `details` on failed uploads.\n const errorHeaders = parseXhrResponseHeaders(xhr.getAllResponseHeaders())\n const canonical = httpResponseFromFetch(\n {\n status: xhr.status,\n statusText: xhr.statusText,\n headers: errorHeaders,\n body: parseJsonText(xhr.responseText, errorHeaders),\n url: xhr.responseURL,\n },\n url,\n method,\n )\n subscriber.error(\n xhr.status >= 500 ? new ServerError(canonical) : new ClientError(canonical),\n )\n return\n }\n\n let responseBody: T\n try {\n responseBody = JSON.parse(xhr.responseText) as T\n } catch {\n subscriber.error(new Error('Failed to parse upload response as JSON'))\n return\n }\n\n subscriber.next({type: 'response', body: responseBody})\n subscriber.complete()\n }\n\n xhr.onerror = () => {\n log('[%d] %s %s — network error', requestId, method, url)\n subscriber.error(new Error('XHR upload network error'))\n }\n\n xhr.ontimeout = () => {\n log('[%d] %s %s — timed out after %dms', requestId, method, url, timeout)\n // Same error shape as the fetch transport's timeout rejection.\n subscriber.error(\n new DOMException(\n `The operation timed out after ${timeout}ms while attempting to reach ${url}`,\n 'TimeoutError',\n ),\n )\n }\n\n xhr.onabort = () => {\n subscriber.error(new DOMException('Upload aborted', 'AbortError'))\n }\n\n const onSignalAbort = () => xhr.abort()\n if (signal) {\n if (signal.aborted) {\n // `xhr.abort()` before `send()` fires no `abort` event per spec, so\n // error out directly instead of relying on `onabort`.\n subscriber.error(new DOMException('Upload aborted', 'AbortError'))\n return undefined\n }\n signal.addEventListener('abort', onSignalAbort, {once: true})\n }\n\n xhr.send(body as XMLHttpRequestBodyInit)\n\n // Unsubscribing cancels the in-flight upload, mirroring how the fetch\n // path aborts its request (`_observe`). After settle this is a no-op —\n // except for detaching from the caller's signal, which may be long-lived\n // and must not accumulate a listener per upload.\n return () => {\n signal?.removeEventListener('abort', onSignalAbort)\n xhr.abort()\n }\n })\n}\n\n/**\n * Parse `XMLHttpRequest.getAllResponseHeaders()` output (CRLF-separated\n * `name: value` lines) into a `Headers` instance.\n */\nfunction parseXhrResponseHeaders(raw: string): Headers {\n const headers = new Headers()\n for (const line of raw.split('\\r\\n')) {\n const separator = line.indexOf(':')\n if (separator <= 0) continue\n try {\n headers.append(line.slice(0, separator).trim(), line.slice(separator + 1).trim())\n } catch {\n // Skip header lines the Headers constructor rejects — better a partial\n // header record on the error than no error details at all.\n }\n }\n return headers\n}\n"],"mappings":";;;AAOA,MAAM,MAAM,YAAY,eAAe;AAEvC,IAAI,gBAAgB;;;;;;;;;AA0BpB,SAAgB,mBAAsB,SAA2D;CAC/F,OAAO,IAAI,YAA4B,eAAe;EACpD,IAAM,MAAM,IAAI,eAAe,GACzB,YAAY,iBACZ,EAAC,KAAK,QAAQ,SAAS,MAAM,iBAAiB,SAAS,WAAU;EAMvE,AAJA,IAAI,yCAAyC,WAAW,QAAQ,GAAG,GAEnE,IAAI,KAAK,QAAQ,GAAG,GACpB,IAAI,kBAAkB,iBAClB,OAAO,WAAY,YAAY,UAAU,MAC3C,IAAI,UAAU;EAGhB,KAAK,IAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAC/C,IAAI,iBAAiB,KAAK,KAAK;EAmEjC,AAhEA,IAAI,OAAO,cAAc,MAAM;GAC7B,WAAW,KAAK;IACd,MAAM;IACN,OAAO;IACP,SAAS,EAAE,mBAAmB,KAAK,MAAO,EAAE,SAAS,EAAE,QAAS,GAAG,IAAI;IACvE,OAAO,EAAE,SAAS,KAAA;IAClB,QAAQ,EAAE;IACV,kBAAkB,EAAE;GACtB,CAAC;EACH,GAEA,IAAI,eAAe;GAGjB,IAFA,IAAI,mBAAmB,WAAW,QAAQ,KAAK,IAAI,MAAM,GAErD,IAAI,UAAU,KAAK;IAIrB,IAAM,eAAe,wBAAwB,IAAI,sBAAsB,CAAC,GAClE,YAAY,sBAChB;KACE,QAAQ,IAAI;KACZ,YAAY,IAAI;KAChB,SAAS;KACT,MAAM,cAAc,IAAI,cAAc,YAAY;KAClD,KAAK,IAAI;IACX,GACA,KACA,MACF;IACA,WAAW,MACT,IAAI,UAAU,MAAM,IAAI,YAAY,SAAS,IAAI,IAAI,YAAY,SAAS,CAC5E;IACA;GACF;GAEA,IAAI;GACJ,IAAI;IACF,eAAe,KAAK,MAAM,IAAI,YAAY;GAC5C,QAAQ;IACN,WAAW,MAAM,gBAAI,MAAM,yCAAyC,CAAC;IACrE;GACF;GAGA,AADA,WAAW,KAAK;IAAC,MAAM;IAAY,MAAM;GAAY,CAAC,GACtD,WAAW,SAAS;EACtB,GAEA,IAAI,gBAAgB;GAElB,AADA,IAAI,8BAA8B,WAAW,QAAQ,GAAG,GACxD,WAAW,MAAM,gBAAI,MAAM,0BAA0B,CAAC;EACxD,GAEA,IAAI,kBAAkB;GAGpB,AAFA,IAAI,qCAAqC,WAAW,QAAQ,KAAK,OAAO,GAExE,WAAW,MACT,IAAI,aACF,iCAAiC,QAAQ,+BAA+B,OACxE,cACF,CACF;EACF,GAEA,IAAI,gBAAgB;GAClB,WAAW,MAAM,IAAI,aAAa,kBAAkB,YAAY,CAAC;EACnE;EAEA,IAAM,sBAAsB,IAAI,MAAM;EACtC,IAAI,QAAQ;GACV,IAAI,OAAO,SAAS;IAGlB,WAAW,MAAM,IAAI,aAAa,kBAAkB,YAAY,CAAC;IACjE;GACF;GACA,OAAO,iBAAiB,SAAS,eAAe,EAAC,MAAM,GAAI,CAAC;EAC9D;EAQA,OANA,IAAI,KAAK,IAA8B,SAM1B;GAEX,AADA,QAAQ,oBAAoB,SAAS,aAAa,GAClD,IAAI,MAAM;EACZ;CACF,CAAC;AACH;;;;;AAMA,SAAS,wBAAwB,KAAsB;CACrD,IAAM,UAAU,IAAI,QAAQ;CAC5B,KAAK,IAAM,QAAQ,IAAI,MAAM,MAAM,GAAG;EACpC,IAAM,YAAY,KAAK,QAAQ,GAAG;EAC9B,mBAAa,IACjB,IAAI;GACF,QAAQ,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC,KAAK,GAAG,KAAK,MAAM,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC;EAClF,QAAQ,CAGR;CACF;CACA,OAAO;AACT"}
|