@sanity/client 7.8.1 → 7.8.2-datasets.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.
@@ -774,6 +774,10 @@ declare type ClientConfigResource =
774
774
  type: 'dashboard'
775
775
  id: string
776
776
  }
777
+ | {
778
+ type: 'project'
779
+ id: string
780
+ }
777
781
 
778
782
  /** @public */
779
783
  export declare class ClientError extends Error {
@@ -1905,6 +1909,7 @@ export declare interface GroqAgentActionParam {
1905
1909
  type: 'groq'
1906
1910
  query: string
1907
1911
  params?: Record<string, string>
1912
+ perspective?: ClientPerspective
1908
1913
  }
1909
1914
 
1910
1915
  /**
@@ -4005,10 +4010,8 @@ export declare class ProjectsClient {
4005
4010
  declare interface PromptJsonResponse<T extends Record<string, Any> = Record<string, Any>> {
4006
4011
  /**
4007
4012
  *
4008
- * When true, the response body will be json according to the instruction.
4009
- * When false, the response is the raw text response to the instruction.
4010
- *
4011
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4013
+ * When format is 'json', the response will be json according to the instruction.
4014
+ * Note: In addition to setting this to 'json', `instruction` MUST include the word 'JSON', or 'json' for this to work.
4012
4015
  */
4013
4016
  format: 'json'
4014
4017
  }
@@ -4115,13 +4118,9 @@ declare interface PromptRequestBase {
4115
4118
 
4116
4119
  declare interface PromptTextResponse {
4117
4120
  /**
4118
- *
4119
- * When true, the response body will be json according to the instruction.
4120
- * When false, the response is the raw text response to the instruction.
4121
- *
4122
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4121
+ * When format is 'string', the response will be a raw text response to the instruction.
4123
4122
  */
4124
- format?: 'text'
4123
+ format?: 'string'
4125
4124
  }
4126
4125
 
4127
4126
  /**
@@ -774,6 +774,10 @@ declare type ClientConfigResource =
774
774
  type: 'dashboard'
775
775
  id: string
776
776
  }
777
+ | {
778
+ type: 'project'
779
+ id: string
780
+ }
777
781
 
778
782
  /** @public */
779
783
  export declare class ClientError extends Error {
@@ -1905,6 +1909,7 @@ export declare interface GroqAgentActionParam {
1905
1909
  type: 'groq'
1906
1910
  query: string
1907
1911
  params?: Record<string, string>
1912
+ perspective?: ClientPerspective
1908
1913
  }
1909
1914
 
1910
1915
  /**
@@ -4005,10 +4010,8 @@ export declare class ProjectsClient {
4005
4010
  declare interface PromptJsonResponse<T extends Record<string, Any> = Record<string, Any>> {
4006
4011
  /**
4007
4012
  *
4008
- * When true, the response body will be json according to the instruction.
4009
- * When false, the response is the raw text response to the instruction.
4010
- *
4011
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4013
+ * When format is 'json', the response will be json according to the instruction.
4014
+ * Note: In addition to setting this to 'json', `instruction` MUST include the word 'JSON', or 'json' for this to work.
4012
4015
  */
4013
4016
  format: 'json'
4014
4017
  }
@@ -4115,13 +4118,9 @@ declare interface PromptRequestBase {
4115
4118
 
4116
4119
  declare interface PromptTextResponse {
4117
4120
  /**
4118
- *
4119
- * When true, the response body will be json according to the instruction.
4120
- * When false, the response is the raw text response to the instruction.
4121
- *
4122
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4121
+ * When format is 'string', the response will be a raw text response to the instruction.
4123
4122
  */
4124
- format?: 'text'
4123
+ format?: 'string'
4125
4124
  }
4126
4125
 
4127
4126
  /**
package/dist/stega.d.cts CHANGED
@@ -774,6 +774,10 @@ declare type ClientConfigResource =
774
774
  type: 'dashboard'
775
775
  id: string
776
776
  }
777
+ | {
778
+ type: 'project'
779
+ id: string
780
+ }
777
781
 
778
782
  /** @public */
779
783
  export declare class ClientError extends Error {
@@ -1905,6 +1909,7 @@ export declare interface GroqAgentActionParam {
1905
1909
  type: 'groq'
1906
1910
  query: string
1907
1911
  params?: Record<string, string>
1912
+ perspective?: ClientPerspective
1908
1913
  }
1909
1914
 
1910
1915
  /**
@@ -4005,10 +4010,8 @@ export declare class ProjectsClient {
4005
4010
  declare interface PromptJsonResponse<T extends Record<string, Any> = Record<string, Any>> {
4006
4011
  /**
4007
4012
  *
4008
- * When true, the response body will be json according to the instruction.
4009
- * When false, the response is the raw text response to the instruction.
4010
- *
4011
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4013
+ * When format is 'json', the response will be json according to the instruction.
4014
+ * Note: In addition to setting this to 'json', `instruction` MUST include the word 'JSON', or 'json' for this to work.
4012
4015
  */
4013
4016
  format: 'json'
4014
4017
  }
@@ -4115,13 +4118,9 @@ declare interface PromptRequestBase {
4115
4118
 
4116
4119
  declare interface PromptTextResponse {
4117
4120
  /**
4118
- *
4119
- * When true, the response body will be json according to the instruction.
4120
- * When false, the response is the raw text response to the instruction.
4121
- *
4122
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4121
+ * When format is 'string', the response will be a raw text response to the instruction.
4123
4122
  */
4124
- format?: 'text'
4123
+ format?: 'string'
4125
4124
  }
4126
4125
 
4127
4126
  /**
package/dist/stega.d.ts CHANGED
@@ -774,6 +774,10 @@ declare type ClientConfigResource =
774
774
  type: 'dashboard'
775
775
  id: string
776
776
  }
777
+ | {
778
+ type: 'project'
779
+ id: string
780
+ }
777
781
 
778
782
  /** @public */
779
783
  export declare class ClientError extends Error {
@@ -1905,6 +1909,7 @@ export declare interface GroqAgentActionParam {
1905
1909
  type: 'groq'
1906
1910
  query: string
1907
1911
  params?: Record<string, string>
1912
+ perspective?: ClientPerspective
1908
1913
  }
1909
1914
 
1910
1915
  /**
@@ -4005,10 +4010,8 @@ export declare class ProjectsClient {
4005
4010
  declare interface PromptJsonResponse<T extends Record<string, Any> = Record<string, Any>> {
4006
4011
  /**
4007
4012
  *
4008
- * When true, the response body will be json according to the instruction.
4009
- * When false, the response is the raw text response to the instruction.
4010
- *
4011
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4013
+ * When format is 'json', the response will be json according to the instruction.
4014
+ * Note: In addition to setting this to 'json', `instruction` MUST include the word 'JSON', or 'json' for this to work.
4012
4015
  */
4013
4016
  format: 'json'
4014
4017
  }
@@ -4115,13 +4118,9 @@ declare interface PromptRequestBase {
4115
4118
 
4116
4119
  declare interface PromptTextResponse {
4117
4120
  /**
4118
- *
4119
- * When true, the response body will be json according to the instruction.
4120
- * When false, the response is the raw text response to the instruction.
4121
- *
4122
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
4121
+ * When format is 'string', the response will be a raw text response to the instruction.
4123
4122
  */
4124
- format?: 'text'
4123
+ format?: 'string'
4125
4124
  }
4126
4125
 
4127
4126
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "7.8.1",
3
+ "version": "7.8.2-datasets.0",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -1,3 +1,5 @@
1
+ import type {ClientPerspective} from '@sanity/client'
2
+
1
3
  /**
2
4
  * Include a string in the instruction: do not have to escape $ signs in the string.
3
5
  *
@@ -128,6 +130,7 @@ export interface GroqAgentActionParam {
128
130
  type: 'groq'
129
131
  query: string
130
132
  params?: Record<string, string>
133
+ perspective?: ClientPerspective
131
134
  }
132
135
 
133
136
  /** @beta */
@@ -105,23 +105,17 @@ export interface PromptRequestBase {
105
105
  interface PromptJsonResponse<T extends Record<string, Any> = Record<string, Any>> {
106
106
  /**
107
107
  *
108
- * When true, the response body will be json according to the instruction.
109
- * When false, the response is the raw text response to the instruction.
110
- *
111
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
108
+ * When format is 'json', the response will be json according to the instruction.
109
+ * Note: In addition to setting this to 'json', `instruction` MUST include the word 'JSON', or 'json' for this to work.
112
110
  */
113
111
  format: 'json'
114
112
  }
115
113
 
116
114
  interface PromptTextResponse {
117
115
  /**
118
- *
119
- * When true, the response body will be json according to the instruction.
120
- * When false, the response is the raw text response to the instruction.
121
- *
122
- * Note: In addition to setting this to true, `instruction` MUST include the word 'JSON', or 'json' for this to work.
116
+ * When format is 'string', the response will be a raw text response to the instruction.
123
117
  */
124
- format?: 'text'
118
+ format?: 'string'
125
119
  }
126
120
 
127
121
  /** @beta */
@@ -184,6 +184,11 @@ function buildAssetUploadUrl(config: InitializedClientConfig, assetType: 'image'
184
184
  if (config['~experimental_resource']) {
185
185
  const {type, id} = config['~experimental_resource']
186
186
  switch (type) {
187
+ case 'project': {
188
+ throw new Error(
189
+ 'Assets are not supported for project resources, yet. Configure the client with `{projectId: <projectId>}` instead.',
190
+ )
191
+ }
187
192
  case 'dataset': {
188
193
  throw new Error(
189
194
  'Assets are not supported for dataset resources, yet. Configure the client with `{projectId: <projectId>, dataset: <datasetId>}` instead.',
@@ -664,10 +664,40 @@ export function _getDataUrl(client: Client, operation: string, path?: string): s
664
664
  const config = client.config()
665
665
  if (config['~experimental_resource']) {
666
666
  validators.resourceConfig(config)
667
+
668
+ // Special handling for dataset-related operations
669
+ if (operation === '' && path?.startsWith('datasets')) {
670
+ const {type, id} = config['~experimental_resource']
671
+
672
+ if (type === 'dataset') {
673
+ // For dataset resource performing dataset management operations,
674
+ // we need to use the project base URL
675
+ const segments = id.split('.')
676
+ if (segments.length !== 2) {
677
+ throw new Error('Invalid dataset resource ID. Expected format "project.dataset".')
678
+ }
679
+ const projectId = segments[0]
680
+ const base = `/projects/${projectId}`
681
+ const uri = [path].filter(Boolean).join('/')
682
+ return `${base}/${uri}`.replace(/\/($|\?)/, '$1')
683
+ } else if (type === 'project') {
684
+ // For project resource, use project base directly
685
+ const base = `/projects/${id}`
686
+ const uri = [path].filter(Boolean).join('/')
687
+ return `${base}/${uri}`.replace(/\/($|\?)/, '$1')
688
+ }
689
+ }
690
+
691
+ // For all other resource operations, use the standard resource base
667
692
  const resourceBase = resourceDataBase(config)
668
- const uri = path !== undefined ? `${operation}/${path}` : operation
693
+ const uri = [operation, path].filter(Boolean).join('/')
669
694
  return `${resourceBase}/${uri}`.replace(/\/($|\?)/, '$1')
670
695
  }
696
+
697
+ if (operation === '') {
698
+ return `/${path || ''}`
699
+ }
700
+
671
701
  const catalog = validators.hasDataset(config)
672
702
  const baseUri = `/${operation}/${catalog}`
673
703
  const uri = path !== undefined ? `${baseUri}/${path}` : baseUri
@@ -753,6 +783,9 @@ const resourceDataBase = (config: InitializedClientConfig): string => {
753
783
  case 'dashboard': {
754
784
  return `/dashboards/${id}`
755
785
  }
786
+ case 'project': {
787
+ return `/projects/${id}`
788
+ }
756
789
  default:
757
790
  // @ts-expect-error - handle all supported resource types
758
791
  throw new Error(`Unsupported resource type: ${type.toString()}`)
@@ -1,6 +1,6 @@
1
1
  import {lastValueFrom, type Observable} from 'rxjs'
2
2
 
3
- import {_request} from '../data/dataMethods'
3
+ import {_getDataUrl, _request} from '../data/dataMethods'
4
4
  import type {ObservableSanityClient, SanityClient} from '../SanityClient'
5
5
  import type {DatasetAclMode, DatasetResponse, DatasetsResponse, HttpRequest} from '../types'
6
6
  import * as validate from '../validators'
@@ -47,8 +47,19 @@ export class ObservableDatasetsClient {
47
47
  * Fetch a list of datasets for the configured project
48
48
  */
49
49
  list(): Observable<DatasetsResponse> {
50
+ const config = this.#client.config()
51
+ const resource = config['~experimental_resource']
52
+
53
+ if (resource) {
54
+ // Only allow project resource type for listing datasets
55
+ if (resource.type !== 'project') {
56
+ throw new Error('`dataset.list()` requires a resource type of "project".')
57
+ }
58
+ }
59
+
60
+ const uri = _getDataUrl(this.#client, '', 'datasets')
50
61
  return _request<DatasetsResponse>(this.#client, this.#httpRequest, {
51
- uri: '/datasets',
62
+ uri,
52
63
  tag: null,
53
64
  })
54
65
  }
@@ -70,7 +81,6 @@ export class DatasetsClient {
70
81
  * @param options - Options for the dataset
71
82
  */
72
83
  create(name: string, options?: {aclMode?: DatasetAclMode}): Promise<DatasetResponse> {
73
- validate.resourceGuard('dataset', this.#client.config())
74
84
  return lastValueFrom(
75
85
  _modify<DatasetResponse>(this.#client, this.#httpRequest, 'PUT', name, options),
76
86
  )
@@ -83,7 +93,6 @@ export class DatasetsClient {
83
93
  * @param options - New options for the dataset
84
94
  */
85
95
  edit(name: string, options?: {aclMode?: DatasetAclMode}): Promise<DatasetResponse> {
86
- validate.resourceGuard('dataset', this.#client.config())
87
96
  return lastValueFrom(
88
97
  _modify<DatasetResponse>(this.#client, this.#httpRequest, 'PATCH', name, options),
89
98
  )
@@ -95,7 +104,6 @@ export class DatasetsClient {
95
104
  * @param name - Name of the dataset to delete
96
105
  */
97
106
  delete(name: string): Promise<{deleted: true}> {
98
- validate.resourceGuard('dataset', this.#client.config())
99
107
  return lastValueFrom(_modify<{deleted: true}>(this.#client, this.#httpRequest, 'DELETE', name))
100
108
  }
101
109
 
@@ -103,9 +111,19 @@ export class DatasetsClient {
103
111
  * Fetch a list of datasets for the configured project
104
112
  */
105
113
  list(): Promise<DatasetsResponse> {
106
- validate.resourceGuard('dataset', this.#client.config())
114
+ const config = this.#client.config()
115
+ const resource = config['~experimental_resource']
116
+
117
+ if (resource) {
118
+ // Only allow project resource type for listing datasets
119
+ if (resource.type !== 'project') {
120
+ throw new Error('`dataset.list()` requires a resource type of "project".')
121
+ }
122
+ }
123
+
124
+ const uri = _getDataUrl(this.#client, '', 'datasets')
107
125
  return lastValueFrom(
108
- _request<DatasetsResponse>(this.#client, this.#httpRequest, {uri: '/datasets', tag: null}),
126
+ _request<DatasetsResponse>(this.#client, this.#httpRequest, {uri, tag: null}),
109
127
  )
110
128
  }
111
129
  }
@@ -117,11 +135,32 @@ function _modify<R = unknown>(
117
135
  name: string,
118
136
  options?: {aclMode?: DatasetAclMode},
119
137
  ) {
120
- validate.resourceGuard('dataset', client.config())
121
138
  validate.dataset(name)
139
+
140
+ const config = client.config()
141
+ const resource = config['~experimental_resource']
142
+
143
+ // For individual dataset operations, only "dataset" resource type makes sense
144
+ if (resource) {
145
+ if (resource.type === 'dataset') {
146
+ // Validate the resource ID format and ensure the name matches
147
+ const segments = resource.id.split('.')
148
+ if (segments.length !== 2) {
149
+ throw new Error('Dataset resource ID must be in the format "project.dataset"')
150
+ }
151
+ const datasetName = segments[1]
152
+ if (name !== datasetName) {
153
+ throw new Error(`Dataset name "${name}" does not match resource dataset "${datasetName}"`)
154
+ }
155
+ } else {
156
+ throw new Error('Dataset create/edit/delete operations require a resource type of "dataset"')
157
+ }
158
+ }
159
+
160
+ const uri = _getDataUrl(client, '', `datasets/${name}`)
122
161
  return _request<R>(client, httpRequest, {
123
162
  method,
124
- uri: `/datasets/${name}`,
163
+ uri,
125
164
  body: options,
126
165
  tag: null,
127
166
  })
@@ -3,7 +3,6 @@ import {lastValueFrom, type Observable} from 'rxjs'
3
3
  import {_request} from '../data/dataMethods'
4
4
  import type {ObservableSanityClient, SanityClient} from '../SanityClient'
5
5
  import type {HttpRequest, SanityProject} from '../types'
6
- import * as validate from '../validators'
7
6
 
8
7
  /** @internal */
9
8
  export class ObservableProjectsClient {
@@ -25,7 +24,6 @@ export class ObservableProjectsClient {
25
24
  list(options?: {
26
25
  includeMembers?: boolean
27
26
  }): Observable<SanityProject[] | Omit<SanityProject, 'members'>[]> {
28
- validate.resourceGuard('projects', this.#client.config())
29
27
  const uri = options?.includeMembers === false ? '/projects?includeMembers=false' : '/projects'
30
28
  return _request<SanityProject[]>(this.#client, this.#httpRequest, {uri})
31
29
  }
@@ -36,7 +34,6 @@ export class ObservableProjectsClient {
36
34
  * @param projectId - ID of the project to fetch
37
35
  */
38
36
  getById(projectId: string): Observable<SanityProject> {
39
- validate.resourceGuard('projects', this.#client.config())
40
37
  return _request<SanityProject>(this.#client, this.#httpRequest, {uri: `/projects/${projectId}`})
41
38
  }
42
39
  }
@@ -59,7 +56,6 @@ export class ProjectsClient {
59
56
  list(options?: {includeMembers?: true}): Promise<SanityProject[]>
60
57
  list(options?: {includeMembers?: false}): Promise<Omit<SanityProject, 'members'>[]>
61
58
  list(options?: {includeMembers?: boolean}): Promise<SanityProject[]> {
62
- validate.resourceGuard('projects', this.#client.config())
63
59
  const uri = options?.includeMembers === false ? '/projects?includeMembers=false' : '/projects'
64
60
  return lastValueFrom(_request<SanityProject[]>(this.#client, this.#httpRequest, {uri}))
65
61
  }
@@ -70,7 +66,6 @@ export class ProjectsClient {
70
66
  * @param projectId - ID of the project to fetch
71
67
  */
72
68
  getById(projectId: string): Promise<SanityProject> {
73
- validate.resourceGuard('projects', this.#client.config())
74
69
  return lastValueFrom(
75
70
  _request<SanityProject>(this.#client, this.#httpRequest, {uri: `/projects/${projectId}`}),
76
71
  )
@@ -86,13 +86,41 @@ function isValidDate(dateString: string) {
86
86
  return /^\d{4}-\d{2}-\d{2}/.test(dateString) ? Boolean(Date.parse(dateString)) : false
87
87
  }
88
88
 
89
+ const allowedProtocols = new Set([
90
+ 'app:',
91
+ 'data:',
92
+ 'discord:',
93
+ 'file:',
94
+ 'ftp:',
95
+ 'ftps:',
96
+ 'geo:',
97
+ 'http:',
98
+ 'https:',
99
+ 'imap:',
100
+ 'javascript:',
101
+ 'magnet:',
102
+ 'mailto:',
103
+ 'maps:',
104
+ 'ms-excel:',
105
+ 'ms-powerpoint:',
106
+ 'ms-word:',
107
+ 'slack:',
108
+ 'sms:',
109
+ 'spotify:',
110
+ 'steam:',
111
+ 'teams:',
112
+ 'tel:',
113
+ 'vscode:',
114
+ 'zoom:',
115
+ ])
116
+
89
117
  function isValidURL(url: string) {
90
118
  try {
91
- new URL(url, url.startsWith('/') ? 'https://acme.com' : undefined)
119
+ const {protocol} = new URL(url, url.startsWith('/') ? 'https://acme.com' : undefined)
120
+ return allowedProtocols.has(protocol) || protocol.startsWith('web+')
92
121
  } catch {
93
122
  return false
94
123
  }
95
- return true
96
124
  }
97
125
 
98
126
  function hasTypeLike(path: ContentSourceMapParsedPath): boolean {
package/src/types.ts CHANGED
@@ -70,6 +70,10 @@ type ClientConfigResource =
70
70
  type: 'dashboard'
71
71
  id: string
72
72
  }
73
+ | {
74
+ type: 'project'
75
+ id: string
76
+ }
73
77
 
74
78
  /** @public */
75
79
  export interface ClientConfig {
package/src/validators.ts CHANGED
@@ -113,6 +113,7 @@ export const resourceConfig = (config: InitializedClientConfig): void => {
113
113
  }
114
114
  return
115
115
  }
116
+ case 'project':
116
117
  case 'dashboard':
117
118
  case 'media-library':
118
119
  case 'canvas': {