@sanity/sdk 2.10.0 → 2.11.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/dist/_chunks-dts/utils.d.ts +200 -28
- package/dist/_chunks-es/_internal.js +3 -14
- package/dist/_chunks-es/_internal.js.map +1 -1
- package/dist/_chunks-es/createGroqSearchFilter.js +7 -14
- package/dist/_chunks-es/createGroqSearchFilter.js.map +1 -1
- package/dist/_chunks-es/version.js +1 -1
- package/dist/_exports/_internal.d.ts +16 -2
- package/dist/_exports/_internal.js +3 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +168 -88
- package/dist/index.js.map +1 -1
- package/package.json +7 -9
- package/src/_exports/_internal.ts +1 -0
- package/src/_exports/index.ts +25 -2
- package/src/agent/agentActions.ts +21 -25
- package/src/client/clientStore.test.ts +10 -46
- package/src/client/clientStore.ts +7 -14
- package/src/comlink/node/actions/getOrCreateNode.test.ts +5 -2
- package/src/comlink/node/actions/releaseNode.test.ts +3 -3
- package/src/config/sanityConfig.ts +0 -1
- package/src/document/documentStore.ts +2 -7
- package/src/document/sharedListener.ts +3 -5
- package/src/organization/organization.test-d.ts +102 -0
- package/src/organization/organization.test.ts +138 -0
- package/src/organization/organization.ts +166 -0
- package/src/organizations/organizations.test-d.ts +77 -0
- package/src/organizations/organizations.test.ts +150 -0
- package/src/organizations/organizations.ts +132 -0
- package/src/presence/presenceStore.test.ts +5 -5
- package/src/preview/previewProjectionUtils.ts +2 -3
- package/src/project/project.test-d.ts +93 -0
- package/src/project/project.test.ts +108 -10
- package/src/project/project.ts +152 -26
- package/src/projection/subscribeToStateAndFetchBatches.ts +4 -9
- package/src/projects/projects.test-d.ts +38 -0
- package/src/projects/projects.test.ts +104 -38
- package/src/projects/projects.ts +74 -14
- package/src/query/queryStore.ts +2 -3
- package/src/releases/releasesStore.test.ts +1 -1
- package/src/releases/releasesStore.ts +2 -2
- package/src/store/createSanityInstance.ts +3 -3
- package/src/telemetry/devMode.test.ts +8 -0
- package/src/telemetry/devMode.ts +10 -9
- package/src/telemetry/initTelemetry.test.ts +0 -17
- package/src/telemetry/initTelemetry.ts +2 -12
package/src/projects/projects.ts
CHANGED
|
@@ -1,35 +1,95 @@
|
|
|
1
1
|
import {switchMap} from 'rxjs'
|
|
2
2
|
|
|
3
3
|
import {getClientState} from '../client/clientStore'
|
|
4
|
+
import {type Project} from '../project/project'
|
|
5
|
+
import {type SanityInstance} from '../store/createSanityInstance'
|
|
6
|
+
import {type StateSource} from '../store/createStateSourceAction'
|
|
4
7
|
import {createFetcherStore} from '../utils/createFetcherStore'
|
|
5
8
|
|
|
6
9
|
const API_VERSION = 'v2025-02-19'
|
|
7
10
|
|
|
11
|
+
/** @public */
|
|
12
|
+
export interface ProjectsOptions<
|
|
13
|
+
IncludeMembers extends boolean = false,
|
|
14
|
+
IncludeFeatures extends boolean = true,
|
|
15
|
+
> {
|
|
16
|
+
organizationId?: string
|
|
17
|
+
includeMembers?: IncludeMembers
|
|
18
|
+
includeFeatures?: IncludeFeatures
|
|
19
|
+
onlyExplicitMembership?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizeProjectsOptions(options?: ProjectsOptions<boolean, boolean>) {
|
|
23
|
+
return {
|
|
24
|
+
organizationId: options?.organizationId,
|
|
25
|
+
includeMembers: options?.includeMembers ?? false,
|
|
26
|
+
includeFeatures: options?.includeFeatures ?? true,
|
|
27
|
+
onlyExplicitMembership: options?.onlyExplicitMembership ?? false,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** @internal */
|
|
32
|
+
export function getProjectsCacheKey(
|
|
33
|
+
_instance: SanityInstance,
|
|
34
|
+
options?: ProjectsOptions<boolean, boolean>,
|
|
35
|
+
): string {
|
|
36
|
+
const {organizationId, includeMembers, includeFeatures, onlyExplicitMembership} =
|
|
37
|
+
normalizeProjectsOptions(options)
|
|
38
|
+
const orgKey = organizationId ? `:org:${organizationId}` : ''
|
|
39
|
+
const membersKey = includeMembers ? ':members' : ''
|
|
40
|
+
const featuresKey = includeFeatures ? ':features' : ''
|
|
41
|
+
const explicitKey = onlyExplicitMembership ? ':explicit' : ''
|
|
42
|
+
return `projects${orgKey}${membersKey}${featuresKey}${explicitKey}`
|
|
43
|
+
}
|
|
44
|
+
|
|
8
45
|
const projects = createFetcherStore({
|
|
9
46
|
name: 'Projects',
|
|
10
|
-
getKey:
|
|
11
|
-
|
|
12
|
-
const membersKey = options?.includeMembers === false ? ':no-members' : ''
|
|
13
|
-
return `projects${orgKey}${membersKey}`
|
|
14
|
-
},
|
|
15
|
-
fetcher: (instance) => (options?: {organizationId?: string; includeMembers?: boolean}) =>
|
|
47
|
+
getKey: getProjectsCacheKey,
|
|
48
|
+
fetcher: (instance) => (options?: ProjectsOptions<boolean, boolean>) =>
|
|
16
49
|
getClientState(instance, {
|
|
17
50
|
apiVersion: API_VERSION,
|
|
18
51
|
scope: 'global',
|
|
19
|
-
requestTagPrefix: 'sanity.sdk.projects',
|
|
20
52
|
}).observable.pipe(
|
|
21
53
|
switchMap((client) => {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
54
|
+
const normalized = normalizeProjectsOptions(options)
|
|
55
|
+
const query = Object.fromEntries(
|
|
56
|
+
Object.entries(normalized)
|
|
57
|
+
.filter(([, value]) => value !== undefined)
|
|
58
|
+
.map(([key, value]) => [key, String(value)]),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return client.observable.request({
|
|
62
|
+
uri: '/projects',
|
|
63
|
+
query,
|
|
64
|
+
tag: 'projects.get',
|
|
27
65
|
})
|
|
28
66
|
}),
|
|
29
67
|
),
|
|
30
68
|
})
|
|
31
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Public signature for the projects state source. The conditional generics
|
|
72
|
+
* cannot flow through `BoundStoreAction`, so we declare the signature here
|
|
73
|
+
* and assign the (already-correct) runtime function to it.
|
|
74
|
+
*/
|
|
75
|
+
type GetProjectsState = <
|
|
76
|
+
IncludeMembers extends boolean = false,
|
|
77
|
+
IncludeFeatures extends boolean = true,
|
|
78
|
+
>(
|
|
79
|
+
instance: SanityInstance,
|
|
80
|
+
options?: ProjectsOptions<IncludeMembers, IncludeFeatures>,
|
|
81
|
+
) => StateSource<Project<IncludeMembers, IncludeFeatures>[] | undefined>
|
|
82
|
+
|
|
83
|
+
type ResolveProjects = <
|
|
84
|
+
IncludeMembers extends boolean = false,
|
|
85
|
+
IncludeFeatures extends boolean = true,
|
|
86
|
+
>(
|
|
87
|
+
instance: SanityInstance,
|
|
88
|
+
options?: ProjectsOptions<IncludeMembers, IncludeFeatures>,
|
|
89
|
+
) => Promise<Project<IncludeMembers, IncludeFeatures>[]>
|
|
90
|
+
|
|
32
91
|
/** @public */
|
|
33
|
-
export const getProjectsState = projects.getState
|
|
92
|
+
export const getProjectsState: GetProjectsState = projects.getState
|
|
93
|
+
|
|
34
94
|
/** @public */
|
|
35
|
-
export const resolveProjects = projects.resolveState
|
|
95
|
+
export const resolveProjects: ResolveProjects = projects.resolveState
|
package/src/query/queryStore.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
} from 'rxjs'
|
|
25
25
|
|
|
26
26
|
import {getClientState} from '../client/clientStore'
|
|
27
|
-
import {type DatasetHandle
|
|
27
|
+
import {type DatasetHandle} from '../config/sanityConfig'
|
|
28
28
|
/*
|
|
29
29
|
* Although this is an import dependency cycle, it is not a logical cycle:
|
|
30
30
|
* 1. queryStore uses getPerspectiveState when resolving release perspectives
|
|
@@ -230,8 +230,7 @@ const listenToLiveClientAndSetLastLiveEventIds = ({
|
|
|
230
230
|
}: StoreContext<QueryStoreState, BoundResourceKey>) => {
|
|
231
231
|
const liveMessages$ = getClientState(instance, {
|
|
232
232
|
apiVersion: QUERY_STORE_API_VERSION,
|
|
233
|
-
|
|
234
|
-
...(resource && !isDatasetResource(resource) ? {resource} : {}),
|
|
233
|
+
resource,
|
|
235
234
|
}).observable.pipe(
|
|
236
235
|
switchMap((client) =>
|
|
237
236
|
defer(() =>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {type SanityDocument} from '@sanity/types'
|
|
2
2
|
import {map} from 'rxjs'
|
|
3
3
|
|
|
4
|
-
import {type DocumentResource
|
|
4
|
+
import {type DocumentResource} from '../config/sanityConfig'
|
|
5
5
|
/*
|
|
6
6
|
* Although this is an import dependency cycle, it is not a logical cycle:
|
|
7
7
|
* 1. releasesStore uses queryStore as a data source
|
|
@@ -84,7 +84,7 @@ const subscribeToReleases = ({
|
|
|
84
84
|
const {observable: releases$} = getQueryState<ReleaseDocument[]>(instance, {
|
|
85
85
|
query: RELEASES_QUERY,
|
|
86
86
|
perspective: 'raw',
|
|
87
|
-
resource
|
|
87
|
+
resource,
|
|
88
88
|
tag: 'releases',
|
|
89
89
|
})
|
|
90
90
|
return releases$
|
|
@@ -5,7 +5,6 @@ import {pickProperties} from '../utils/object'
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Represents a Sanity.io resource instance with its own configuration and lifecycle
|
|
8
|
-
* @remarks Instances form a hierarchy through parent/child relationships
|
|
9
8
|
*
|
|
10
9
|
* @public
|
|
11
10
|
*/
|
|
@@ -18,7 +17,6 @@ export interface SanityInstance {
|
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* Resolved configuration for this instance
|
|
21
|
-
* @remarks Merges values from parent instances where appropriate
|
|
22
20
|
*/
|
|
23
21
|
readonly config: SanityConfig
|
|
24
22
|
|
|
@@ -44,13 +42,14 @@ export interface SanityInstance {
|
|
|
44
42
|
/**
|
|
45
43
|
* Gets the parent instance in the hierarchy
|
|
46
44
|
* @returns Parent instance or undefined if this is the root
|
|
45
|
+
* @deprecated The parent/child instance hierarchy is deprecated. Use a single SanityInstance instead.
|
|
47
46
|
*/
|
|
48
47
|
getParent(): SanityInstance | undefined
|
|
49
48
|
|
|
50
49
|
/**
|
|
51
50
|
* Creates a child instance with merged configuration
|
|
52
51
|
* @param config - Configuration to merge with parent values
|
|
53
|
-
* @
|
|
52
|
+
* @deprecated The parent/child instance hierarchy is deprecated. Use a single SanityInstance instead.
|
|
54
53
|
*/
|
|
55
54
|
createChild(config: SanityConfig): SanityInstance
|
|
56
55
|
|
|
@@ -59,6 +58,7 @@ export interface SanityInstance {
|
|
|
59
58
|
* matches the given target config using a shallow comparison.
|
|
60
59
|
* @param targetConfig - A partial configuration object containing key-value pairs to match.
|
|
61
60
|
* @returns The first matching instance or undefined if no match is found.
|
|
61
|
+
* @deprecated The parent/child instance hierarchy is deprecated. Use a single SanityInstance instead.
|
|
62
62
|
*/
|
|
63
63
|
match(targetConfig: Partial<SanityConfig>): SanityInstance | undefined
|
|
64
64
|
}
|
|
@@ -30,6 +30,14 @@ describe('isDevMode', () => {
|
|
|
30
30
|
expect(isDevMode()).toBe(true)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
+
it('returns true on localhost even when NODE_ENV is production', () => {
|
|
34
|
+
vi.stubEnv('NODE_ENV', 'production')
|
|
35
|
+
vi.stubGlobal('window', {
|
|
36
|
+
location: {href: 'http://localhost:3000/'},
|
|
37
|
+
})
|
|
38
|
+
expect(isDevMode()).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
|
|
33
41
|
it('returns false for a non-local URL', () => {
|
|
34
42
|
vi.stubEnv('NODE_ENV', 'test')
|
|
35
43
|
vi.stubGlobal('window', {
|
package/src/telemetry/devMode.ts
CHANGED
|
@@ -17,21 +17,22 @@ function isLocalUrl(win: Window): boolean {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Determines whether the SDK should enable dev-mode telemetry
|
|
20
|
+
* Determines whether the SDK should enable dev-mode telemetry for the
|
|
21
|
+
* SDK consumer (i.e. a developer building an app with `@sanity/sdk`).
|
|
21
22
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Browser: returns true only when the URL is `localhost` or `127.0.0.1`.
|
|
24
|
+
* The URL check is the primary signal because consumer bundlers may or
|
|
25
|
+
* may not forward `NODE_ENV` to the browser reliably.
|
|
26
|
+
*
|
|
27
|
+
* Node (scripts / non-browser): falls back to `NODE_ENV === 'development'`.
|
|
28
|
+
*
|
|
29
|
+
* Bracket-notation `process.env['NODE_ENV']` is used to avoid bundler
|
|
30
|
+
* dead-code replacement.
|
|
26
31
|
*
|
|
27
32
|
* @returns True if the SDK is running in a development environment
|
|
28
33
|
* @internal
|
|
29
34
|
*/
|
|
30
35
|
export function isDevMode(): boolean {
|
|
31
|
-
if (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'production') {
|
|
32
|
-
return false
|
|
33
|
-
}
|
|
34
|
-
|
|
35
36
|
if (typeof window !== 'undefined') {
|
|
36
37
|
return isLocalUrl(window)
|
|
37
38
|
}
|
|
@@ -205,21 +205,4 @@ describe('initTelemetry', () => {
|
|
|
205
205
|
|
|
206
206
|
instance.dispose()
|
|
207
207
|
})
|
|
208
|
-
|
|
209
|
-
it('finds manager through parent-child instance chain', async () => {
|
|
210
|
-
vi.mocked(isDevMode).mockReturnValue(true)
|
|
211
|
-
|
|
212
|
-
const root = createSanityInstance()
|
|
213
|
-
const child = root.createChild({})
|
|
214
|
-
|
|
215
|
-
initTelemetry(root, 'abc123')
|
|
216
|
-
await flushPromises()
|
|
217
|
-
|
|
218
|
-
trackHookMounted(child, 'useUsers')
|
|
219
|
-
|
|
220
|
-
const manager = vi.mocked(createTelemetryManager).mock.results[0].value
|
|
221
|
-
expect(manager.logHookFirstUsed).toHaveBeenCalledWith('useUsers')
|
|
222
|
-
|
|
223
|
-
root.dispose()
|
|
224
|
-
})
|
|
225
208
|
})
|
|
@@ -187,19 +187,9 @@ export function trackHookMounted(instance: SanityInstance, hookName: string): vo
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
function findManager(instance: SanityInstance): TelemetryManager | undefined {
|
|
190
|
-
|
|
191
|
-
while (current) {
|
|
192
|
-
const manager = telemetryManagers.get(current)
|
|
193
|
-
if (manager) return manager
|
|
194
|
-
current = typeof current.getParent === 'function' ? current.getParent() : undefined
|
|
195
|
-
}
|
|
196
|
-
return undefined
|
|
190
|
+
return telemetryManagers.get(instance)
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
function getRootInstance(instance: SanityInstance): SanityInstance {
|
|
200
|
-
|
|
201
|
-
while (typeof current.getParent === 'function' && current.getParent()) {
|
|
202
|
-
current = current.getParent()!
|
|
203
|
-
}
|
|
204
|
-
return current
|
|
194
|
+
return instance
|
|
205
195
|
}
|