@sanity/client 8.2.0 → 8.4.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 +2 -2
- package/dist/{browserUpload-2tz6Sdqp.js → browserUpload-C7PwCs-C.js} +6 -9
- package/dist/browserUpload-C7PwCs-C.js.map +1 -0
- package/dist/{browserUpload-CwpNx7Vl.js → browserUpload-D-2Rmfjo.js} +6 -9
- package/dist/browserUpload-D-2Rmfjo.js.map +1 -0
- package/dist/{config-3wiPP-sZ.js → config-CgJ16jET.js} +4 -2
- package/dist/config-CgJ16jET.js.map +1 -0
- package/dist/csm.js +1 -1
- package/dist/{dist-C9ExSk2R.js → dist-C5K_YcEU.js} +3 -2
- package/dist/{dist-C9ExSk2R.js.map → dist-C5K_YcEU.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +942 -115
- package/dist/index.js.map +1 -1
- package/dist/index.node.d.ts +3345 -16
- package/dist/index.node.js +865 -59
- package/dist/index.node.js.map +1 -1
- package/dist/media-library.d.ts +1 -1
- package/dist/rolldown-runtime-4YWMqDIC.js +9 -0
- package/dist/{stegaEncodeSourceMap-DbM2fTN4.js → stegaEncodeSourceMap-CO1HKnm2.js} +2 -2
- package/dist/{stegaEncodeSourceMap-DbM2fTN4.js.map → stegaEncodeSourceMap-CO1HKnm2.js.map} +1 -1
- package/dist/{types-nJhm5Nyq.d.ts → types-DiPF0ENT.d.ts} +3346 -17
- package/package.json +3 -3
- package/src/SanityClient.ts +7 -0
- package/src/assets/AssetsClient.ts +5 -0
- package/src/collaboration/types.ts +59 -8
- package/src/config.ts +1 -0
- package/src/context/ContextClient.ts +1006 -0
- package/src/context/openapi.json +5345 -0
- package/src/context/reads.ts +206 -0
- package/src/context/store.ts +100 -0
- package/src/context/types.gen.ts +2428 -0
- package/src/context/types.ts +228 -0
- package/src/data/dataMethods.ts +4 -1
- package/src/defineCreateClient.ts +1 -0
- package/src/functions/FunctionsClient.ts +52 -9
- package/src/functions/invoke.ts +47 -6
- package/src/http/browserUpload.ts +0 -12
- package/src/types.ts +29 -3
- package/src/util/createVersionId.ts +15 -5
- package/src/validators.ts +1 -0
- package/dist/browserUpload-2tz6Sdqp.js.map +0 -1
- package/dist/browserUpload-CwpNx7Vl.js.map +0 -1
- package/dist/config-3wiPP-sZ.js.map +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ListenOptions,
|
|
3
|
+
RequestOptions as MainRequestOptions,
|
|
4
|
+
ResumableListenOptions,
|
|
5
|
+
UploadBody,
|
|
6
|
+
} from '../types'
|
|
7
|
+
import type {components, paths} from './types.gen'
|
|
8
|
+
|
|
9
|
+
/** Options accepted by every Context method. @beta */
|
|
10
|
+
export type RequestOptions = {signal?: AbortSignal; tag?: string}
|
|
11
|
+
|
|
12
|
+
/** @internal */
|
|
13
|
+
export const possibleStoreRequestOptions = ['headers', 'signal', 'tag', 'timeout', 'token'] as const
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Request options honored by `context.fetch`.
|
|
17
|
+
*
|
|
18
|
+
* @beta
|
|
19
|
+
*/
|
|
20
|
+
export type ContextRequestOptions = Pick<
|
|
21
|
+
MainRequestOptions,
|
|
22
|
+
(typeof possibleStoreRequestOptions)[number]
|
|
23
|
+
>
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Listener options for `context.listen`.
|
|
27
|
+
*
|
|
28
|
+
* `includeAllVersions` is left out: Context documents are written by the
|
|
29
|
+
* Context API with no drafts or versions, so it would never make a
|
|
30
|
+
* difference.
|
|
31
|
+
*
|
|
32
|
+
* @beta
|
|
33
|
+
*/
|
|
34
|
+
export type ContextListenOptions =
|
|
35
|
+
| Omit<ListenOptions, 'includeAllVersions'>
|
|
36
|
+
| Omit<ResumableListenOptions, 'includeAllVersions'>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A file import. The client stages the upload, PUTs the bytes straight to
|
|
40
|
+
* storage with a signed URL, and confirms. The Context API never holds the
|
|
41
|
+
* file content.
|
|
42
|
+
* @beta
|
|
43
|
+
*/
|
|
44
|
+
export type CreateFileImportParams = {
|
|
45
|
+
type: 'file'
|
|
46
|
+
/** Same shapes `assets.upload` accepts, minus node streams: the bytes go
|
|
47
|
+
* out through `fetch`, which has no portable stream support. */
|
|
48
|
+
file: Exclude<UploadBody, NodeJS.ReadableStream>
|
|
49
|
+
filename: string
|
|
50
|
+
contentType?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type KnowledgeBasesPath = '/{apiVersion}/context/knowledge-bases'
|
|
54
|
+
type ConversationPath =
|
|
55
|
+
'/{apiVersion}/context/organizations/{organizationId}/conversations/{threadId}'
|
|
56
|
+
type KnowledgeBasePath = '/{apiVersion}/context/knowledge-bases/{knowledgeBaseId}'
|
|
57
|
+
type ImportsPath = `${KnowledgeBasePath}/imports`
|
|
58
|
+
type ImportPath = `${KnowledgeBasePath}/imports/{importId}`
|
|
59
|
+
type UploadsPath = `${KnowledgeBasePath}/imports/uploads`
|
|
60
|
+
type EntryRebuildPath = `${KnowledgeBasePath}/entries/{entryPath}/rebuild`
|
|
61
|
+
type SourcesPath = `${KnowledgeBasePath}/sources`
|
|
62
|
+
type SourcePath = `${KnowledgeBasePath}/sources/{sourceId}`
|
|
63
|
+
type SourceContentPath = `${KnowledgeBasePath}/sources/{sourceId}/content`
|
|
64
|
+
type IssuesApplyPath = `${KnowledgeBasePath}/issues/apply`
|
|
65
|
+
type InstructionPath = `${KnowledgeBasePath}/instructions/{instructionId}`
|
|
66
|
+
type JobPath = `${KnowledgeBasePath}/jobs/{jobId}`
|
|
67
|
+
type IssueResolvePath = `${KnowledgeBasePath}/issues/{issueId}/resolve`
|
|
68
|
+
type IssueDismissPath = `${KnowledgeBasePath}/issues/{issueId}/dismiss`
|
|
69
|
+
type IssueReopenPath = `${KnowledgeBasePath}/issues/{issueId}/reopen`
|
|
70
|
+
type InstructionsPath = `${KnowledgeBasePath}/instructions`
|
|
71
|
+
|
|
72
|
+
type JsonResponse<T> = T extends {content: {'application/json': infer R}} ? R : never
|
|
73
|
+
type JsonBody<T> = T extends {
|
|
74
|
+
requestBody: {content: {'application/json': infer R}}
|
|
75
|
+
}
|
|
76
|
+
? R
|
|
77
|
+
: never
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* A knowledge base: one buildable body of knowledge inside Context.
|
|
81
|
+
* @beta
|
|
82
|
+
*/
|
|
83
|
+
export type KnowledgeBase = JsonResponse<paths[KnowledgeBasePath]['get']['responses']['200']>
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Parameters for creating a knowledge base.
|
|
87
|
+
* @beta
|
|
88
|
+
*/
|
|
89
|
+
export type CreateKnowledgeBaseParams = JsonBody<paths[KnowledgeBasesPath]['post']>
|
|
90
|
+
/** @beta */
|
|
91
|
+
export type EditKnowledgeBaseParams = JsonBody<paths[KnowledgeBasePath]['patch']>
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Parameters for importing content. Discriminated on `type`:
|
|
95
|
+
* inline text, a website crawl, or a Sanity dataset bind.
|
|
96
|
+
* @beta
|
|
97
|
+
*/
|
|
98
|
+
export type CreateImportParams = JsonBody<paths[ImportsPath]['post']>
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Accepted async work. Poll the job with `jobs.get` until it reaches a
|
|
102
|
+
* terminal state.
|
|
103
|
+
* @beta
|
|
104
|
+
*/
|
|
105
|
+
export type JobAccepted = JsonResponse<
|
|
106
|
+
paths[`${KnowledgeBasePath}/build`]['post']['responses']['202']
|
|
107
|
+
>
|
|
108
|
+
|
|
109
|
+
/** @beta */
|
|
110
|
+
export type Job = JsonResponse<paths[JobPath]['get']['responses']['200']>
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Accepted entry rebuild: the job to poll plus every entry the rebuild
|
|
114
|
+
* touches.
|
|
115
|
+
* @beta
|
|
116
|
+
*/
|
|
117
|
+
export type RebuildEntryResponse = JsonResponse<paths[EntryRebuildPath]['post']['responses']['202']>
|
|
118
|
+
|
|
119
|
+
/** @beta */
|
|
120
|
+
export type ApplyIssuesParams = JsonBody<paths[IssuesApplyPath]['post']>
|
|
121
|
+
/** @beta */
|
|
122
|
+
export type ApplyIssuesResponse = JsonResponse<paths[IssuesApplyPath]['post']['responses']['202']>
|
|
123
|
+
/** @beta */
|
|
124
|
+
export type ResolveIssueParams = JsonBody<paths[IssueResolvePath]['post']>
|
|
125
|
+
/** @beta */
|
|
126
|
+
export type ResolveIssueResponse = JsonResponse<paths[IssueResolvePath]['post']['responses']['200']>
|
|
127
|
+
/** @beta */
|
|
128
|
+
export type DismissIssueResponse = JsonResponse<paths[IssueDismissPath]['post']['responses']['200']>
|
|
129
|
+
/** @beta */
|
|
130
|
+
export type ReopenIssueResponse = JsonResponse<paths[IssueReopenPath]['post']['responses']['200']>
|
|
131
|
+
|
|
132
|
+
/** @beta */
|
|
133
|
+
export type CreateInstructionParams = JsonBody<paths[InstructionsPath]['post']>
|
|
134
|
+
/**
|
|
135
|
+
* A standing instruction, as the instruction endpoints return it.
|
|
136
|
+
* @beta
|
|
137
|
+
*/
|
|
138
|
+
export type Instruction = JsonResponse<paths[InstructionPath]['patch']['responses']['200']>
|
|
139
|
+
/** The created instruction, wrapped the way the create endpoint returns it. @beta */
|
|
140
|
+
export type CreateInstructionResponse = JsonResponse<
|
|
141
|
+
paths[InstructionsPath]['post']['responses']['201']
|
|
142
|
+
>
|
|
143
|
+
/** @beta */
|
|
144
|
+
export type EditInstructionParams = JsonBody<paths[InstructionPath]['patch']>
|
|
145
|
+
|
|
146
|
+
/** @beta */
|
|
147
|
+
export type KnowledgeBasesResponse = JsonResponse<
|
|
148
|
+
paths[KnowledgeBasesPath]['get']['responses']['200']
|
|
149
|
+
>
|
|
150
|
+
|
|
151
|
+
/** @beta */
|
|
152
|
+
export type ImportsResponse = JsonResponse<paths[ImportsPath]['get']['responses']['200']>
|
|
153
|
+
/** @beta */
|
|
154
|
+
export type Import = ImportsResponse['data'][number]
|
|
155
|
+
/** @beta */
|
|
156
|
+
export type ImportDetail = JsonResponse<paths[ImportPath]['get']['responses']['200']>
|
|
157
|
+
/** @beta */
|
|
158
|
+
export type ImportDownloadResponse = JsonResponse<
|
|
159
|
+
paths[`${ImportPath}/download`]['get']['responses']['200']
|
|
160
|
+
>
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The staged half of a file upload: PUT the bytes to `uploadUrl`, then
|
|
164
|
+
* confirm with the complete endpoint. `imports.create({type: 'file'})` does
|
|
165
|
+
* all of this in one call.
|
|
166
|
+
* @beta
|
|
167
|
+
*/
|
|
168
|
+
export type StagedUpload = JsonResponse<paths[UploadsPath]['post']['responses']['201']>
|
|
169
|
+
|
|
170
|
+
/** @beta */
|
|
171
|
+
export type SourcesResponse = JsonResponse<paths[SourcesPath]['get']['responses']['200']>
|
|
172
|
+
/** @beta */
|
|
173
|
+
export type Source = SourcesResponse['data'][number]
|
|
174
|
+
/** @beta */
|
|
175
|
+
export type SourceDetail = JsonResponse<paths[SourcePath]['get']['responses']['200']>
|
|
176
|
+
/** @beta */
|
|
177
|
+
export type SourceContentResponse = JsonResponse<
|
|
178
|
+
paths[SourceContentPath]['get']['responses']['200']
|
|
179
|
+
>
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* A recorded conversation: one agent thread's transcript plus the
|
|
183
|
+
* classification recorded on it. Standalone org-level telemetry — dimensions
|
|
184
|
+
* (MCP endpoints, app, the customer's own keys) live in the `metadata` bag.
|
|
185
|
+
* @beta
|
|
186
|
+
*/
|
|
187
|
+
export type Conversation = JsonResponse<paths[ConversationPath]['put']['responses']['200']>
|
|
188
|
+
/**
|
|
189
|
+
* Body for the conversation ingest upsert. Messages replace the stored
|
|
190
|
+
* transcript wholesale; `metadata` and model fields only overwrite when
|
|
191
|
+
* present.
|
|
192
|
+
* @beta
|
|
193
|
+
*/
|
|
194
|
+
export type SaveConversationParams = JsonBody<paths[ConversationPath]['put']>
|
|
195
|
+
/** Exactly one of a verdict (`coreMetrics`) or a failure (`classificationError`). @beta */
|
|
196
|
+
export type ClassifyConversationParams = JsonBody<paths[ConversationPath]['patch']>
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The raw `sanity.context.entry` document shape, as stored in the
|
|
200
|
+
* organization's document store. For typing GROQ reads.
|
|
201
|
+
* @beta
|
|
202
|
+
*/
|
|
203
|
+
export type EntryDoc = components['schemas']['EntryDoc']
|
|
204
|
+
/** @beta */
|
|
205
|
+
export type IssueDoc = components['schemas']['IssueDoc']
|
|
206
|
+
/** @beta */
|
|
207
|
+
export type InstructionDoc = components['schemas']['InstructionDoc']
|
|
208
|
+
/**
|
|
209
|
+
* The raw `sanity.context.mcp` document shape (an MCP endpoint
|
|
210
|
+
* configuration), as stored in the organization's document store. For
|
|
211
|
+
* typing GROQ reads.
|
|
212
|
+
* @beta
|
|
213
|
+
*/
|
|
214
|
+
export type McpDoc = components['schemas']['McpDoc']
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* The metadata view of an entry, as `entries.list` projects it. Bodies stay
|
|
218
|
+
* behind `entries.get` (or a GROQ read through `context.fetch`).
|
|
219
|
+
* @beta
|
|
220
|
+
*/
|
|
221
|
+
export type Entry = Pick<EntryDoc, '_id' | 'path' | 'title' | 'tldr' | 'status'>
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The raw `sanity.context.conversation` document shape, as stored in the
|
|
225
|
+
* organization's document store. For typing GROQ reads.
|
|
226
|
+
* @beta
|
|
227
|
+
*/
|
|
228
|
+
export type ConversationDoc = components['schemas']['ConversationDoc']
|
package/src/data/dataMethods.ts
CHANGED
|
@@ -1128,7 +1128,7 @@ export function _prepareRequest(client: Client, options: RequestObservableOption
|
|
|
1128
1128
|
*
|
|
1129
1129
|
* @internal
|
|
1130
1130
|
*/
|
|
1131
|
-
function _observe<R>(
|
|
1131
|
+
export function _observe<R>(
|
|
1132
1132
|
userSignal: AbortSignal | undefined,
|
|
1133
1133
|
run: (signal: AbortSignal) => Promise<R>,
|
|
1134
1134
|
): Observable<R> {
|
|
@@ -1291,6 +1291,9 @@ const resourceDataBase = (config: InitializedClientConfig): string => {
|
|
|
1291
1291
|
case 'canvas': {
|
|
1292
1292
|
return `/canvases/${id}`
|
|
1293
1293
|
}
|
|
1294
|
+
case 'knowledge-base': {
|
|
1295
|
+
return `/knowledge-bases/${id}`
|
|
1296
|
+
}
|
|
1294
1297
|
case 'media-library': {
|
|
1295
1298
|
return `/media-libraries/${id}`
|
|
1296
1299
|
}
|
|
@@ -2,7 +2,7 @@ import {lastValueFrom, type Observable} from 'rxjs'
|
|
|
2
2
|
|
|
3
3
|
import type {ObservableSanityClient, SanityClient} from '../SanityClient'
|
|
4
4
|
import type {HttpRequest} from '../types'
|
|
5
|
-
import {_invoke, type InvokeFunctionRequest} from './invoke'
|
|
5
|
+
import {_invoke, type InvokeFunctionOptions, type InvokeFunctionRequest} from './invoke'
|
|
6
6
|
|
|
7
7
|
/** @public */
|
|
8
8
|
export class ObservableFunctionsClient {
|
|
@@ -17,16 +17,36 @@ export class ObservableFunctionsClient {
|
|
|
17
17
|
* Invoke a deployed function by its blueprint name.
|
|
18
18
|
*
|
|
19
19
|
* The name is resolved within the stack given by `stackId` on the request or
|
|
20
|
-
* the client config.
|
|
20
|
+
* the client config. Starts the invocation and emits `undefined` as soon as
|
|
21
|
+
* it is accepted; pass `{sync: true}` to wait for the function's return value
|
|
22
|
+
* instead.
|
|
21
23
|
*
|
|
22
24
|
* @param functionName - name of the function, as declared in the blueprint
|
|
23
25
|
* @param request - payload and request options
|
|
26
|
+
* @param options - invocation options
|
|
24
27
|
*/
|
|
28
|
+
invoke(
|
|
29
|
+
functionName: string,
|
|
30
|
+
request?: InvokeFunctionRequest,
|
|
31
|
+
options?: InvokeFunctionOptions & {sync?: false},
|
|
32
|
+
): Observable<undefined>
|
|
33
|
+
invoke<R = unknown>(
|
|
34
|
+
functionName: string,
|
|
35
|
+
request: InvokeFunctionRequest | undefined,
|
|
36
|
+
options: InvokeFunctionOptions & {sync: true},
|
|
37
|
+
): Observable<R>
|
|
38
|
+
invoke<R = unknown>(
|
|
39
|
+
functionName: string,
|
|
40
|
+
request?: InvokeFunctionRequest,
|
|
41
|
+
options?: InvokeFunctionOptions,
|
|
42
|
+
): Observable<R | undefined>
|
|
43
|
+
// Implementation signature — not part of the public API.
|
|
25
44
|
invoke<R = unknown>(
|
|
26
45
|
functionName: string,
|
|
27
46
|
request?: InvokeFunctionRequest,
|
|
47
|
+
options?: InvokeFunctionOptions,
|
|
28
48
|
): Observable<R | undefined> {
|
|
29
|
-
return _invoke<R>(this.#client, this.#httpRequest, functionName, request)
|
|
49
|
+
return _invoke<R>(this.#client, this.#httpRequest, functionName, request, options)
|
|
30
50
|
}
|
|
31
51
|
}
|
|
32
52
|
|
|
@@ -44,23 +64,46 @@ export class FunctionsClient {
|
|
|
44
64
|
*
|
|
45
65
|
* The name is resolved within the stack given by `stackId` on the request or
|
|
46
66
|
* the client config, which costs one extra request per call. Rejects if the
|
|
47
|
-
* stack has no function by that name, or if the name resolves to
|
|
48
|
-
*
|
|
67
|
+
* stack has no function by that name, or if the name resolves to a function
|
|
68
|
+
* type that cannot be invoked the way it was asked for.
|
|
49
69
|
*
|
|
50
70
|
* The lookup is scoped to `projectId`, or to `organizationId` when one is set
|
|
51
71
|
* for a stack deployed at organization scope.
|
|
52
72
|
*
|
|
53
|
-
* The
|
|
54
|
-
*
|
|
55
|
-
*
|
|
73
|
+
* The invocation is started by default: the promise resolves with `undefined`
|
|
74
|
+
* as soon as the call is accepted, without waiting for the function to run.
|
|
75
|
+
* Pass `{sync: true}` to keep the request open until the function finishes
|
|
76
|
+
* and resolve with its return value — long-running functions may then need an
|
|
77
|
+
* explicit `timeout`. Only `sanity.function.pubsub` functions can be invoked
|
|
78
|
+
* synchronously.
|
|
56
79
|
*
|
|
57
80
|
* @param functionName - name of the function, as declared in the blueprint
|
|
58
81
|
* @param request - payload and request options
|
|
82
|
+
* @param options - invocation options
|
|
59
83
|
*/
|
|
84
|
+
invoke(
|
|
85
|
+
functionName: string,
|
|
86
|
+
request?: InvokeFunctionRequest,
|
|
87
|
+
options?: InvokeFunctionOptions & {sync?: false},
|
|
88
|
+
): Promise<undefined>
|
|
89
|
+
invoke<R = unknown>(
|
|
90
|
+
functionName: string,
|
|
91
|
+
request: InvokeFunctionRequest | undefined,
|
|
92
|
+
options: InvokeFunctionOptions & {sync: true},
|
|
93
|
+
): Promise<R>
|
|
94
|
+
invoke<R = unknown>(
|
|
95
|
+
functionName: string,
|
|
96
|
+
request?: InvokeFunctionRequest,
|
|
97
|
+
options?: InvokeFunctionOptions,
|
|
98
|
+
): Promise<R | undefined>
|
|
99
|
+
// Implementation signature — not part of the public API.
|
|
60
100
|
invoke<R = unknown>(
|
|
61
101
|
functionName: string,
|
|
62
102
|
request?: InvokeFunctionRequest,
|
|
103
|
+
options?: InvokeFunctionOptions,
|
|
63
104
|
): Promise<R | undefined> {
|
|
64
|
-
return lastValueFrom(
|
|
105
|
+
return lastValueFrom(
|
|
106
|
+
_invoke<R>(this.#client, this.#httpRequest, functionName, request, options),
|
|
107
|
+
)
|
|
65
108
|
}
|
|
66
109
|
}
|
package/src/functions/invoke.ts
CHANGED
|
@@ -6,7 +6,15 @@ import type {HttpRequest, InitializedClientConfig} from '../types'
|
|
|
6
6
|
|
|
7
7
|
/** Function resource types in a blueprint are namespaced under this prefix. */
|
|
8
8
|
const FUNCTION_RESOURCE_PREFIX = 'sanity.function.'
|
|
9
|
-
const
|
|
9
|
+
const SYNC_INVOCABLE_FUNCTION_TYPES = ['sanity.function.pubsub']
|
|
10
|
+
const ASYNC_INVOCABLE_FUNCTION_TYPES = [
|
|
11
|
+
'sanity.function.durable',
|
|
12
|
+
'sanity.function.pubsub',
|
|
13
|
+
'sanity.function.queue',
|
|
14
|
+
]
|
|
15
|
+
const INVOCABLE_FUNCTION_TYPES = [
|
|
16
|
+
...new Set([...SYNC_INVOCABLE_FUNCTION_TYPES, ...ASYNC_INVOCABLE_FUNCTION_TYPES]),
|
|
17
|
+
]
|
|
10
18
|
|
|
11
19
|
/** @public */
|
|
12
20
|
export interface InvokeFunctionEvent {
|
|
@@ -37,6 +45,18 @@ export interface InvokeFunctionRequest {
|
|
|
37
45
|
signal?: AbortSignal
|
|
38
46
|
}
|
|
39
47
|
|
|
48
|
+
/** @public */
|
|
49
|
+
export interface InvokeFunctionOptions {
|
|
50
|
+
/**
|
|
51
|
+
* Wait for the function to finish and resolve with its return value.
|
|
52
|
+
*
|
|
53
|
+
* Defaults to `false`: the invocation is started, the request resolves as soon
|
|
54
|
+
* as it is accepted, and the value is always `undefined`. Only function types
|
|
55
|
+
* that support running inline can be invoked synchronously.
|
|
56
|
+
*/
|
|
57
|
+
sync?: boolean
|
|
58
|
+
}
|
|
59
|
+
|
|
40
60
|
/**
|
|
41
61
|
* Subset of a stack resource the client needs in order to resolve a name.
|
|
42
62
|
*
|
|
@@ -109,6 +129,7 @@ function _resolveFunctionId(
|
|
|
109
129
|
stackId: string,
|
|
110
130
|
headers: Record<string, string>,
|
|
111
131
|
request: InvokeFunctionRequest | undefined,
|
|
132
|
+
sync: boolean,
|
|
112
133
|
): Observable<string> {
|
|
113
134
|
return _requestObservable<{resources?: StackResource[]}>(client, httpRequest, {
|
|
114
135
|
method: 'GET',
|
|
@@ -132,9 +153,15 @@ function _resolveFunctionId(
|
|
|
132
153
|
)
|
|
133
154
|
}
|
|
134
155
|
|
|
135
|
-
if (match.type
|
|
156
|
+
if (!INVOCABLE_FUNCTION_TYPES.includes(match.type)) {
|
|
136
157
|
throw new Error(`Function invocation is not supported for ${match.type}`)
|
|
137
158
|
}
|
|
159
|
+
if (sync && !SYNC_INVOCABLE_FUNCTION_TYPES.includes(match.type)) {
|
|
160
|
+
throw new Error(`Synchronous function invocation is not supported for ${match.type}`)
|
|
161
|
+
}
|
|
162
|
+
if (!sync && !ASYNC_INVOCABLE_FUNCTION_TYPES.includes(match.type)) {
|
|
163
|
+
throw new Error(`Asynchronous function invocation is not supported for ${match.type}`)
|
|
164
|
+
}
|
|
138
165
|
|
|
139
166
|
return match.externalId
|
|
140
167
|
}),
|
|
@@ -147,6 +174,7 @@ export function _invoke<R = unknown>(
|
|
|
147
174
|
httpRequest: HttpRequest,
|
|
148
175
|
functionName: string,
|
|
149
176
|
request?: InvokeFunctionRequest,
|
|
177
|
+
options?: InvokeFunctionOptions,
|
|
150
178
|
): Observable<R | undefined> {
|
|
151
179
|
// Deferred so a bad config surfaces as an error on the returned observable
|
|
152
180
|
// (and so a rejected promise) rather than throwing at the call site.
|
|
@@ -154,17 +182,30 @@ export function _invoke<R = unknown>(
|
|
|
154
182
|
const config = client.config()
|
|
155
183
|
const headers = scopeHeaders(config, request)
|
|
156
184
|
const stackId = resolveStackId(config, request)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
185
|
+
const sync = options?.sync ?? false
|
|
186
|
+
|
|
187
|
+
return _resolveFunctionId(
|
|
188
|
+
client,
|
|
189
|
+
httpRequest,
|
|
190
|
+
functionName,
|
|
191
|
+
stackId,
|
|
192
|
+
headers,
|
|
193
|
+
request,
|
|
194
|
+
sync,
|
|
195
|
+
).pipe(
|
|
196
|
+
// An async invocation is only acknowledged (202, no body), and a sync
|
|
197
|
+
// function that returns nothing answers 204, which the transport parses
|
|
160
198
|
// to an `undefined` body. The status code is not observable from here —
|
|
161
199
|
// the `HttpRequest` boundary resolves to the body alone — so an empty
|
|
162
200
|
// response and a function that returned nothing both surface as
|
|
163
201
|
// `undefined`.
|
|
202
|
+
//
|
|
203
|
+
// The route is async by default, so `sync=false` is left off the wire
|
|
204
|
+
// rather than spelled out.
|
|
164
205
|
mergeMap((functionId) =>
|
|
165
206
|
_requestObservable<R | undefined>(client, httpRequest, {
|
|
166
207
|
method: 'POST',
|
|
167
|
-
url: `/functions/${functionId}/invoke`,
|
|
208
|
+
url: `/functions/${functionId}/invoke${sync ? '?sync=true' : ''}`,
|
|
168
209
|
headers,
|
|
169
210
|
body: {event: {data: request?.event?.data ?? {}}},
|
|
170
211
|
timeout: request?.timeout,
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {createDebug} from 'obug'
|
|
2
1
|
import {Observable} from 'rxjs'
|
|
3
2
|
|
|
4
3
|
import type {UploadEvent} from '../types'
|
|
5
4
|
import {ClientError, httpResponseFromFetch, ServerError} from './errors'
|
|
6
5
|
import {parseJsonText} from './request'
|
|
7
6
|
|
|
8
|
-
const log = createDebug('sanity:client')
|
|
9
|
-
|
|
10
|
-
let nextRequestId = 1
|
|
11
|
-
|
|
12
7
|
/**
|
|
13
8
|
* Options for a browser-side asset upload that needs progress events.
|
|
14
9
|
*
|
|
@@ -36,11 +31,8 @@ export interface BrowserUploadOptions {
|
|
|
36
31
|
export function uploadWithProgress<T>(options: BrowserUploadOptions): Observable<UploadEvent<T>> {
|
|
37
32
|
return new Observable<UploadEvent<T>>((subscriber) => {
|
|
38
33
|
const xhr = new XMLHttpRequest()
|
|
39
|
-
const requestId = nextRequestId++
|
|
40
34
|
const {url, method, headers, body, withCredentials, timeout, signal} = options
|
|
41
35
|
|
|
42
|
-
log('[%d] %s %s (XHR upload with progress)', requestId, method, url)
|
|
43
|
-
|
|
44
36
|
xhr.open(method, url)
|
|
45
37
|
xhr.withCredentials = withCredentials
|
|
46
38
|
if (typeof timeout === 'number' && timeout > 0) {
|
|
@@ -63,8 +55,6 @@ export function uploadWithProgress<T>(options: BrowserUploadOptions): Observable
|
|
|
63
55
|
}
|
|
64
56
|
|
|
65
57
|
xhr.onload = () => {
|
|
66
|
-
log('[%d] %s %s — %d', requestId, method, url, xhr.status)
|
|
67
|
-
|
|
68
58
|
if (xhr.status >= 400) {
|
|
69
59
|
// Same typed errors as the fetch transport, so consumers can keep
|
|
70
60
|
// detecting `ClientError`/`ServerError` and reading `statusCode`,
|
|
@@ -100,12 +90,10 @@ export function uploadWithProgress<T>(options: BrowserUploadOptions): Observable
|
|
|
100
90
|
}
|
|
101
91
|
|
|
102
92
|
xhr.onerror = () => {
|
|
103
|
-
log('[%d] %s %s — network error', requestId, method, url)
|
|
104
93
|
subscriber.error(new Error('XHR upload network error'))
|
|
105
94
|
}
|
|
106
95
|
|
|
107
96
|
xhr.ontimeout = () => {
|
|
108
|
-
log('[%d] %s %s — timed out after %dms', requestId, method, url, timeout)
|
|
109
97
|
// Same error shape as the fetch transport's timeout rejection.
|
|
110
98
|
subscriber.error(
|
|
111
99
|
new DOMException(
|
package/src/types.ts
CHANGED
|
@@ -109,6 +109,10 @@ type ClientConfigResource =
|
|
|
109
109
|
type: 'canvas'
|
|
110
110
|
id: string
|
|
111
111
|
}
|
|
112
|
+
| {
|
|
113
|
+
type: 'knowledge-base'
|
|
114
|
+
id: string
|
|
115
|
+
}
|
|
112
116
|
| {
|
|
113
117
|
type: 'media-library'
|
|
114
118
|
id: string
|
|
@@ -314,6 +318,17 @@ export interface ClientConfig {
|
|
|
314
318
|
collaboration?: {
|
|
315
319
|
organizationId?: string
|
|
316
320
|
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Organization-scoped configuration for Context APIs.
|
|
324
|
+
*
|
|
325
|
+
* Currently this is used by `context.insights` methods.
|
|
326
|
+
*
|
|
327
|
+
* @beta
|
|
328
|
+
*/
|
|
329
|
+
context?: {
|
|
330
|
+
organizationId?: string
|
|
331
|
+
}
|
|
317
332
|
}
|
|
318
333
|
|
|
319
334
|
/** @public */
|
|
@@ -620,6 +635,7 @@ export type DatasetAclMode = 'public' | 'private' | 'custom'
|
|
|
620
635
|
/** @public */
|
|
621
636
|
export type DatasetCreateOptions = {
|
|
622
637
|
aclMode?: DatasetAclMode
|
|
638
|
+
description?: string
|
|
623
639
|
embeddings?: {
|
|
624
640
|
enabled: boolean
|
|
625
641
|
projection?: string
|
|
@@ -629,6 +645,7 @@ export type DatasetCreateOptions = {
|
|
|
629
645
|
/** @public */
|
|
630
646
|
export type DatasetEditOptions = {
|
|
631
647
|
aclMode?: DatasetAclMode
|
|
648
|
+
description?: string
|
|
632
649
|
}
|
|
633
650
|
|
|
634
651
|
/** @public */
|
|
@@ -645,17 +662,21 @@ export type EmbeddingsSettingsBody = {
|
|
|
645
662
|
}
|
|
646
663
|
|
|
647
664
|
/** @public */
|
|
648
|
-
export type DatasetResponse = {datasetName: string; aclMode: DatasetAclMode}
|
|
665
|
+
export type DatasetResponse = {datasetName: string; aclMode: DatasetAclMode; description: string}
|
|
649
666
|
/** @public */
|
|
650
667
|
export type DatasetsResponse = {
|
|
651
668
|
name: string
|
|
652
669
|
aclMode: DatasetAclMode
|
|
670
|
+
description: string
|
|
653
671
|
createdAt: string
|
|
654
672
|
createdByUserId: string
|
|
655
673
|
addonFor: string | null
|
|
656
674
|
datasetProfile: string
|
|
657
675
|
features: string[]
|
|
658
|
-
tags:
|
|
676
|
+
tags: {
|
|
677
|
+
name: string
|
|
678
|
+
title: string
|
|
679
|
+
}[]
|
|
659
680
|
}[]
|
|
660
681
|
|
|
661
682
|
/** @public */
|
|
@@ -2297,7 +2318,11 @@ export type {
|
|
|
2297
2318
|
TranslateTarget,
|
|
2298
2319
|
TranslateTargetInclude,
|
|
2299
2320
|
} from './agent/actions/translate'
|
|
2300
|
-
export type {
|
|
2321
|
+
export type {
|
|
2322
|
+
InvokeFunctionEvent,
|
|
2323
|
+
InvokeFunctionOptions,
|
|
2324
|
+
InvokeFunctionRequest,
|
|
2325
|
+
} from './functions/invoke'
|
|
2301
2326
|
export type {
|
|
2302
2327
|
CollaborationCommentCreate,
|
|
2303
2328
|
CollaborationCommentDocument,
|
|
@@ -2312,6 +2337,7 @@ export type {
|
|
|
2312
2337
|
CollaborationCommentTarget,
|
|
2313
2338
|
CollaborationCommentUpdate,
|
|
2314
2339
|
CollaborationCommentRange,
|
|
2340
|
+
CollaborationCommentFieldValue,
|
|
2315
2341
|
} from './collaboration/types'
|
|
2316
2342
|
export type {
|
|
2317
2343
|
ContentSourceMapParsedPath,
|
|
@@ -5,20 +5,30 @@ import {
|
|
|
5
5
|
isDraftId,
|
|
6
6
|
isVersionId,
|
|
7
7
|
} from '@sanity/client/csm'
|
|
8
|
-
import {customAlphabet} from 'nanoid'
|
|
9
8
|
|
|
10
9
|
import type {IdentifiedSanityDocumentStub, SanityDocumentStub} from '../types'
|
|
11
10
|
import {validateVersionIdMatch} from '../validators'
|
|
12
11
|
|
|
12
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
13
|
+
|
|
13
14
|
/**
|
|
14
15
|
* @internal
|
|
15
16
|
*
|
|
16
17
|
* ~24 years (or 7.54e+8 seconds) needed, in order to have a 1% probability of at least one collision if 10 ID's are generated every hour.
|
|
17
18
|
*/
|
|
18
|
-
export
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
)
|
|
19
|
+
export function generateReleaseId() {
|
|
20
|
+
let id = ''
|
|
21
|
+
|
|
22
|
+
while (id.length < 8) {
|
|
23
|
+
const bytes = crypto.getRandomValues(new Uint8Array(8 - id.length))
|
|
24
|
+
for (const byte of bytes) {
|
|
25
|
+
const index = byte & 63
|
|
26
|
+
if (index < alphabet.length) id += alphabet[index]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return id
|
|
31
|
+
}
|
|
22
32
|
|
|
23
33
|
/** @internal */
|
|
24
34
|
export const getDocumentVersionId = (publishedId: string, releaseId?: string) =>
|
package/src/validators.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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"}
|