@sanity/client 7.9.0 → 7.11.0-cors-check.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 CHANGED
@@ -142,6 +142,9 @@ export async function updateDocumentTitle(_id, title) {
142
142
  - [Example: Storing language in a field](#example-storing-language-in-a-field)
143
143
  - [Prompt the LLM](#prompt-the-llm)
144
144
  - [Patch with a schema-aware API](#patch-with-a-schema-aware-api)
145
+ - [Media Library API](#media-library-api)
146
+ - [Getting video playback information](#getting-video-playback-information)
147
+ - [Working with signed playback information](#working-with-signed-playback-information)
145
148
  - [License](#license)
146
149
  - [From `v5`](#from-v5)
147
150
  - [The default `useCdn` is changed to `true`](#the-default-usecdn-is-changed-to-true)
@@ -2273,6 +2276,104 @@ const result = await client.agent.action.patch({
2273
2276
  })
2274
2277
  ```
2275
2278
 
2279
+ ### Media Library API
2280
+
2281
+ The Media Library provides centralized asset management for your organization. Store, organize, and manage digital assets across multiple applications and datasets with programmatic access through the `client.mediaLibrary` interface.
2282
+
2283
+ 👉 Read more about [Media Library in Sanity](https://www.sanity.io/docs/media-library)
2284
+
2285
+ #### Getting video playback information
2286
+
2287
+ ```js
2288
+ const client = createClient({
2289
+ token: 'valid-token',
2290
+ useCdn: false,
2291
+ '~experimental_resource': {
2292
+ type: 'media-library',
2293
+ id: 'mediaLibraryId',
2294
+ },
2295
+ })
2296
+
2297
+ // Basic usage with video asset ID
2298
+ const playbackInfo = await client.mediaLibrary.video.getPlaybackInfo('video-30rh9U3GDEK3ToiId1Zje4uvalC-mp4')
2299
+
2300
+ // With transformations
2301
+ const playbackInfo = await client.mediaLibrary.video.getPlaybackInfo('video-30rh9U3GDEK3ToiId1Zje4uvalC-mp4', {
2302
+ transformations: {
2303
+ thumbnail: { width: 300, format: 'webp', fit: 'smartcrop' },
2304
+ animated: { width: 200, fps: 15, format: 'webp' }
2305
+ },
2306
+ expiration: 3600 // seconds
2307
+ })
2308
+
2309
+ // Using Global Dataset Reference (GDR)
2310
+ const playbackInfo = await client.mediaLibrary.video.getPlaybackInfo({
2311
+ _ref: 'media-library:mlZxz9rvqf76:30rh9U3GDEK3ToiId1Zje4uvalC'
2312
+ })
2313
+ ```
2314
+
2315
+ The response contains playback URLs and metadata:
2316
+
2317
+ ```js
2318
+ // Public playback response
2319
+ {
2320
+ id: "30rh9U3GDEK3ToiId1Zje4uvalC",
2321
+ stream: { url: "https://stream.m.sanity-cdn.com/..." },
2322
+ thumbnail: { url: "https://image.m.sanity-cdn.com/..." },
2323
+ animated: { url: "https://image.m.sanity-cdn.com/..." },
2324
+ storyboard: { url: "https://storyboard.m.sanity-cdn.com/..." },
2325
+ duration: 120.5,
2326
+ aspectRatio: 1.77
2327
+ }
2328
+
2329
+ // Signed playback response (when video requires authentication)
2330
+ {
2331
+ id: "30rh9U3GDEK3ToiId1Zje4uvalC",
2332
+ stream: {
2333
+ url: "https://stream.m.sanity-cdn.com/...",
2334
+ token: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
2335
+ },
2336
+ thumbnail: {
2337
+ url: "https://image.m.sanity-cdn.com/...",
2338
+ token: "eyJ0a2VuIjoiVGh1bWJuYWlsVG9rZW4tMTIz..."
2339
+ },
2340
+ animated: {
2341
+ url: "https://image.m.sanity-cdn.com/...",
2342
+ token: "eyJ0a2VuIjoiQW5pbWF0ZWRUb2tlbi1kZWY..."
2343
+ },
2344
+ storyboard: {
2345
+ url: "https://storyboard.m.sanity-cdn.com/...",
2346
+ token: "eyJ0a2VuIjoiU3Rvcnlib2FyZFRva2VuLTc4..."
2347
+ },
2348
+ duration: 120.5,
2349
+ aspectRatio: 1.77
2350
+ }
2351
+ ```
2352
+
2353
+ #### Working with signed playback information
2354
+
2355
+ ```js
2356
+ import {getPlaybackTokens, isSignedPlaybackInfo} from '@sanity/client/media-library'
2357
+
2358
+ const playbackInfo = await client.mediaLibrary.video.getPlaybackInfo('video-30rh9U3GDEK3ToiId1Zje4uvalC-mp4')
2359
+
2360
+ // Check if the response requires signed URLs
2361
+ if (isSignedPlaybackInfo(playbackInfo)) {
2362
+ // Extract tokens for use with video players
2363
+ const tokens = getPlaybackTokens(playbackInfo)
2364
+ console.log(tokens)
2365
+ // {
2366
+ // stream: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
2367
+ // thumbnail: "eyJ0a2VuIjoiVGh1bWJuYWlsVG9rZW4tMTIz...",
2368
+ // animated: "eyJ0a2VuIjoiQW5pbWF0ZWRUb2tlbi1kZWY...",
2369
+ // storyboard: "eyJ0a2VuIjoiU3Rvcnlib2FyZFRva2VuLTc4..."
2370
+ // }
2371
+
2372
+ // Use with Mux Player or other compatible players
2373
+ // The tokens authenticate access to the video resources
2374
+ }
2375
+ ```
2376
+
2276
2377
  ## License
2277
2378
 
2278
2379
  MIT © [Sanity.io](https://www.sanity.io/)
@@ -929,11 +929,19 @@ function _getDocument(client, httpRequest, id, opts = {}) {
929
929
  uri: _getDataUrl(client, "doc", docId),
930
930
  json: !0,
931
931
  tag: opts.tag,
932
- signal: opts.signal
932
+ signal: opts.signal,
933
+ query: opts.includeAllVersions !== void 0 ? { includeAllVersions: opts.includeAllVersions } : void 0
933
934
  };
934
- return _requestObservable(client, httpRequest, options).pipe(
935
+ return _requestObservable(
936
+ client,
937
+ httpRequest,
938
+ options
939
+ ).pipe(
935
940
  operators.filter(isResponse),
936
- operators.map((event) => event.body.documents && event.body.documents[0])
941
+ operators.map((event) => {
942
+ const documents = event.body.documents;
943
+ return documents ? opts.includeAllVersions ? documents : documents[0] : opts.includeAllVersions ? [] : void 0;
944
+ })
937
945
  );
938
946
  }
939
947
  function _getDocuments(client, httpRequest, ids, opts = {}) {
@@ -1473,26 +1481,33 @@ class LiveClient {
1473
1481
  "welcome",
1474
1482
  "reconnect",
1475
1483
  "goaway"
1476
- ]).pipe(
1477
- reconnectOnConnectionFailure(),
1478
- operators.map((event) => {
1479
- if (event.type === "message") {
1480
- const { data, ...rest } = event;
1481
- return { ...rest, tags: data.tags };
1482
- }
1483
- return event;
1484
- })
1485
- ), checkCors = fetchObservable(url, {
1484
+ ]), checkCors$ = fetchObservable(url, {
1486
1485
  method: "OPTIONS",
1487
1486
  mode: "cors",
1488
1487
  credentials: esOptions.withCredentials ? "include" : "omit",
1489
1488
  headers: esOptions.headers
1490
1489
  }).pipe(
1491
- rxjs.mergeMap(() => rxjs.EMPTY),
1492
1490
  rxjs.catchError(() => {
1493
1491
  throw new CorsOriginError({ projectId: projectId2 });
1492
+ }),
1493
+ operators.shareReplay(1)
1494
+ // run only once
1495
+ ), observable = events.pipe(
1496
+ rxjs.catchError((err) => (console.log("[live] err from catchError", err), checkCors$.pipe(
1497
+ rxjs.mergeMap(() => (console.log("[live] err from checkCors$", err), rxjs.of(err))),
1498
+ rxjs.mergeMap(() => {
1499
+ throw console.log("[live] throwing err from checkCors$", err), err;
1500
+ })
1501
+ ))),
1502
+ reconnectOnConnectionFailure(),
1503
+ operators.map((event) => {
1504
+ if (console.log("event", event), event.type === "message") {
1505
+ const { data, ...rest } = event;
1506
+ return { ...rest, tags: data.tags };
1507
+ }
1508
+ return event;
1494
1509
  })
1495
- ), observable = rxjs.concat(checkCors, events).pipe(
1510
+ ).pipe(
1496
1511
  operators.finalize(() => eventsCache.delete(key)),
1497
1512
  shareReplayLatest({
1498
1513
  predicate: (event) => event.type === "welcome"
@@ -1616,6 +1631,80 @@ function _modify(client, httpRequest, method, name, options) {
1616
1631
  tag: null
1617
1632
  });
1618
1633
  }
1634
+ class ObservableMediaLibraryVideoClient {
1635
+ #client;
1636
+ #httpRequest;
1637
+ constructor(client, httpRequest) {
1638
+ this.#client = client, this.#httpRequest = httpRequest;
1639
+ }
1640
+ /**
1641
+ * Get video playback information for a media library asset
1642
+ *
1643
+ * @param assetIdentifier - Asset instance identifier (GDR, video-prefixed ID, or container ID)
1644
+ * @param options - Options for transformations and expiration
1645
+ */
1646
+ getPlaybackInfo(assetIdentifier, options = {}) {
1647
+ const configMediaLibraryId = this.#client.config()["~experimental_resource"]?.id, { instanceId, libraryId } = parseAssetInstanceId(assetIdentifier), effectiveLibraryId = libraryId || configMediaLibraryId;
1648
+ if (!effectiveLibraryId)
1649
+ throw new Error(
1650
+ "Could not determine Media Library ID - you need to provide a valid Media Library ID in the client config or a Media Library GDR"
1651
+ );
1652
+ const uri = buildVideoPlaybackInfoUrl(instanceId, effectiveLibraryId), queryParams = buildQueryParams(options);
1653
+ return _request(this.#client, this.#httpRequest, {
1654
+ method: "GET",
1655
+ uri,
1656
+ query: queryParams
1657
+ });
1658
+ }
1659
+ }
1660
+ class MediaLibraryVideoClient {
1661
+ #client;
1662
+ #httpRequest;
1663
+ constructor(client, httpRequest) {
1664
+ this.#client = client, this.#httpRequest = httpRequest;
1665
+ }
1666
+ /**
1667
+ * Get video playback information for a media library asset
1668
+ *
1669
+ * @param assetIdentifier - Asset instance identifier (GDR, video-prefixed ID, or container ID)
1670
+ * @param options - Options for transformations and expiration
1671
+ */
1672
+ getPlaybackInfo(assetIdentifier, options = {}) {
1673
+ return rxjs.lastValueFrom(
1674
+ new ObservableMediaLibraryVideoClient(
1675
+ this.#client.observable,
1676
+ this.#httpRequest
1677
+ ).getPlaybackInfo(assetIdentifier, options)
1678
+ );
1679
+ }
1680
+ }
1681
+ const ML_GDR_PATTERN = /^media-library:(ml[^:]+):([^:]+)$/;
1682
+ function isSanityReference(assetIdentifier) {
1683
+ return typeof assetIdentifier == "object" && "_ref" in assetIdentifier;
1684
+ }
1685
+ function parseAssetInstanceId(assetIdentifier) {
1686
+ const ref = isSanityReference(assetIdentifier) ? assetIdentifier._ref : assetIdentifier, match = ML_GDR_PATTERN.exec(ref);
1687
+ if (match) {
1688
+ const [, libraryId, instanceId] = match;
1689
+ return { libraryId, instanceId };
1690
+ }
1691
+ if (typeof assetIdentifier == "string" && assetIdentifier.startsWith("video-"))
1692
+ return { instanceId: assetIdentifier };
1693
+ throw new Error(
1694
+ `Invalid video asset instance identifier "${ref}": must be a valid video instance id or a Global Dataset Reference (GDR) to the video asset in the Media Library`
1695
+ );
1696
+ }
1697
+ function buildVideoPlaybackInfoUrl(instanceId, libraryId) {
1698
+ return `/media-libraries/${libraryId}/video/${instanceId}/playback-info`;
1699
+ }
1700
+ function buildQueryParams(options) {
1701
+ const params = {};
1702
+ if (options.transformations) {
1703
+ const { thumbnail, animated, storyboard } = options.transformations;
1704
+ thumbnail && (thumbnail.width && (params.thumbnailWidth = thumbnail.width), thumbnail.height && (params.thumbnailHeight = thumbnail.height), thumbnail.time !== void 0 && (params.thumbnailTime = thumbnail.time), thumbnail.fit && (params.thumbnailFit = thumbnail.fit), thumbnail.format && (params.thumbnailFormat = thumbnail.format)), animated && (animated.width && (params.animatedWidth = animated.width), animated.height && (params.animatedHeight = animated.height), animated.start !== void 0 && (params.animatedStart = animated.start), animated.end !== void 0 && (params.animatedEnd = animated.end), animated.fps && (params.animatedFps = animated.fps), animated.format && (params.animatedFormat = animated.format)), storyboard && storyboard.format && (params.storyboardFormat = storyboard.format);
1705
+ }
1706
+ return options.expiration && (params.expiration = options.expiration), params;
1707
+ }
1619
1708
  class ObservableProjectsClient {
1620
1709
  #client;
1621
1710
  #httpRequest;
@@ -1623,8 +1712,8 @@ class ObservableProjectsClient {
1623
1712
  this.#client = client, this.#httpRequest = httpRequest;
1624
1713
  }
1625
1714
  list(options) {
1626
- const uri = options?.includeMembers === !1 ? "/projects?includeMembers=false" : "/projects";
1627
- return _request(this.#client, this.#httpRequest, { uri });
1715
+ const query = {}, uri = "/projects";
1716
+ return options?.includeMembers === !1 && (query.includeMembers = "false"), options?.organizationId && (query.organizationId = options.organizationId), _request(this.#client, this.#httpRequest, { uri, query });
1628
1717
  }
1629
1718
  /**
1630
1719
  * Fetch a project by project ID
@@ -1642,8 +1731,8 @@ class ProjectsClient {
1642
1731
  this.#client = client, this.#httpRequest = httpRequest;
1643
1732
  }
1644
1733
  list(options) {
1645
- const uri = options?.includeMembers === !1 ? "/projects?includeMembers=false" : "/projects";
1646
- return rxjs.lastValueFrom(_request(this.#client, this.#httpRequest, { uri }));
1734
+ const query = {}, uri = "/projects";
1735
+ return options?.includeMembers === !1 && (query.includeMembers = "false"), options?.organizationId && (query.organizationId = options.organizationId), rxjs.lastValueFrom(_request(this.#client, this.#httpRequest, { uri, query }));
1647
1736
  }
1648
1737
  /**
1649
1738
  * Fetch a project by project ID
@@ -2190,6 +2279,7 @@ class ObservableSanityClient {
2190
2279
  assets;
2191
2280
  datasets;
2192
2281
  live;
2282
+ mediaLibrary;
2193
2283
  projects;
2194
2284
  users;
2195
2285
  agent;
@@ -2204,7 +2294,9 @@ class ObservableSanityClient {
2204
2294
  */
2205
2295
  listen = _listen;
2206
2296
  constructor(httpRequest, config = defaultConfig) {
2207
- this.config(config), this.#httpRequest = httpRequest, this.assets = new ObservableAssetsClient(this, this.#httpRequest), this.datasets = new ObservableDatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ObservableProjectsClient(this, this.#httpRequest), this.users = new ObservableUsersClient(this, this.#httpRequest), this.agent = {
2297
+ this.config(config), this.#httpRequest = httpRequest, this.assets = new ObservableAssetsClient(this, this.#httpRequest), this.datasets = new ObservableDatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.mediaLibrary = {
2298
+ video: new ObservableMediaLibraryVideoClient(this, this.#httpRequest)
2299
+ }, this.projects = new ObservableProjectsClient(this, this.#httpRequest), this.users = new ObservableUsersClient(this, this.#httpRequest), this.agent = {
2208
2300
  action: new ObservableAgentsActionClient(this, this.#httpRequest)
2209
2301
  }, this.releases = new ObservableReleasesClient(this, this.#httpRequest);
2210
2302
  }
@@ -2249,14 +2341,19 @@ class ObservableSanityClient {
2249
2341
  options
2250
2342
  );
2251
2343
  }
2252
- /**
2253
- * Fetch a single document with the given ID.
2254
- *
2255
- * @param id - Document ID to fetch
2256
- * @param options - Request options
2257
- */
2258
2344
  getDocument(id, options) {
2259
- return _getDocument(this, this.#httpRequest, id, options);
2345
+ if (options?.includeAllVersions === !0)
2346
+ return _getDocument(this, this.#httpRequest, id, {
2347
+ ...options,
2348
+ includeAllVersions: !0
2349
+ });
2350
+ const opts = {
2351
+ signal: options?.signal,
2352
+ tag: options?.tag,
2353
+ releaseId: options?.releaseId,
2354
+ ...options && "includeAllVersions" in options ? { includeAllVersions: !1 } : {}
2355
+ };
2356
+ return _getDocument(this, this.#httpRequest, id, opts);
2260
2357
  }
2261
2358
  /**
2262
2359
  * Fetch multiple documents in one request.
@@ -2442,6 +2539,7 @@ class SanityClient {
2442
2539
  assets;
2443
2540
  datasets;
2444
2541
  live;
2542
+ mediaLibrary;
2445
2543
  projects;
2446
2544
  users;
2447
2545
  agent;
@@ -2460,7 +2558,9 @@ class SanityClient {
2460
2558
  */
2461
2559
  listen = _listen;
2462
2560
  constructor(httpRequest, config = defaultConfig) {
2463
- this.config(config), this.#httpRequest = httpRequest, this.assets = new AssetsClient(this, this.#httpRequest), this.datasets = new DatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.projects = new ProjectsClient(this, this.#httpRequest), this.users = new UsersClient(this, this.#httpRequest), this.agent = {
2561
+ this.config(config), this.#httpRequest = httpRequest, this.assets = new AssetsClient(this, this.#httpRequest), this.datasets = new DatasetsClient(this, this.#httpRequest), this.live = new LiveClient(this), this.mediaLibrary = {
2562
+ video: new MediaLibraryVideoClient(this, this.#httpRequest)
2563
+ }, this.projects = new ProjectsClient(this, this.#httpRequest), this.users = new UsersClient(this, this.#httpRequest), this.agent = {
2464
2564
  action: new AgentActionsClient(this, this.#httpRequest)
2465
2565
  }, this.releases = new ReleasesClient(this, this.#httpRequest), this.observable = new ObservableSanityClient(httpRequest, config);
2466
2566
  }
@@ -2507,14 +2607,21 @@ class SanityClient {
2507
2607
  )
2508
2608
  );
2509
2609
  }
2510
- /**
2511
- * Fetch a single document with the given ID.
2512
- *
2513
- * @param id - Document ID to fetch
2514
- * @param options - Request options
2515
- */
2516
2610
  getDocument(id, options) {
2517
- return rxjs.lastValueFrom(_getDocument(this, this.#httpRequest, id, options));
2611
+ if (options?.includeAllVersions === !0)
2612
+ return rxjs.lastValueFrom(
2613
+ _getDocument(this, this.#httpRequest, id, {
2614
+ ...options,
2615
+ includeAllVersions: !0
2616
+ })
2617
+ );
2618
+ const opts = {
2619
+ signal: options?.signal,
2620
+ tag: options?.tag,
2621
+ releaseId: options?.releaseId,
2622
+ ...options && "includeAllVersions" in options ? { includeAllVersions: !1 } : {}
2623
+ };
2624
+ return rxjs.lastValueFrom(_getDocument(this, this.#httpRequest, id, opts));
2518
2625
  }
2519
2626
  /**
2520
2627
  * Fetch multiple documents in one request.