@sanity/sdk-react 2.10.0 → 2.11.1

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.
Files changed (55) hide show
  1. package/dist/index.d.ts +257 -200
  2. package/dist/index.js +368 -257
  3. package/dist/index.js.map +1 -1
  4. package/package.json +21 -24
  5. package/src/_exports/index.ts +2 -0
  6. package/src/_exports/sdk-react.ts +4 -0
  7. package/src/components/SDKProvider.test.tsx +5 -12
  8. package/src/components/SDKProvider.tsx +26 -24
  9. package/src/components/errors/CorsErrorComponent.tsx +2 -2
  10. package/src/config/handles.ts +55 -0
  11. package/src/constants.ts +5 -0
  12. package/src/context/DefaultResourceContext.ts +10 -0
  13. package/src/context/PerspectiveContext.ts +12 -0
  14. package/src/context/ResourceProvider.test.tsx +2 -2
  15. package/src/context/ResourceProvider.tsx +53 -49
  16. package/src/hooks/agent/agentActions.ts +55 -38
  17. package/src/hooks/context/useResource.test.tsx +32 -0
  18. package/src/hooks/context/useResource.ts +24 -0
  19. package/src/hooks/context/useSanityInstance.test.tsx +42 -111
  20. package/src/hooks/context/useSanityInstance.ts +28 -50
  21. package/src/hooks/dashboard/useDispatchIntent.test.ts +5 -1
  22. package/src/hooks/dashboard/useDispatchIntent.ts +3 -3
  23. package/src/hooks/dashboard/useManageFavorite.test.tsx +16 -12
  24. package/src/hooks/dashboard/utils/useResourceIdFromDocumentHandle.ts +1 -5
  25. package/src/hooks/document/{useApplyDocumentActions.test.ts → useApplyDocumentActions.test.tsx} +42 -77
  26. package/src/hooks/document/useApplyDocumentActions.ts +29 -63
  27. package/src/hooks/document/useDocument.ts +5 -7
  28. package/src/hooks/document/useDocumentEvent.ts +4 -3
  29. package/src/hooks/document/useDocumentPermissions.test.tsx +58 -150
  30. package/src/hooks/document/useDocumentPermissions.ts +78 -55
  31. package/src/hooks/document/useEditDocument.test.tsx +25 -60
  32. package/src/hooks/document/useEditDocument.ts +1 -1
  33. package/src/hooks/documents/useDocuments.ts +13 -8
  34. package/src/hooks/helpers/createStateSourceHook.tsx +1 -2
  35. package/src/hooks/helpers/useNormalizedResourceOptions.test.tsx +253 -0
  36. package/src/hooks/helpers/useNormalizedResourceOptions.ts +85 -47
  37. package/src/hooks/organizations/useOrganization.test-d.ts +53 -0
  38. package/src/hooks/organizations/useOrganization.test.ts +65 -0
  39. package/src/hooks/organizations/useOrganization.ts +40 -0
  40. package/src/hooks/organizations/useOrganizations.test-d.ts +55 -0
  41. package/src/hooks/organizations/useOrganizations.test.ts +85 -0
  42. package/src/hooks/organizations/useOrganizations.ts +45 -0
  43. package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +23 -9
  44. package/src/hooks/presence/usePresence.ts +4 -11
  45. package/src/hooks/preview/useDocumentPreview.tsx +4 -7
  46. package/src/hooks/projection/useDocumentProjection.ts +5 -7
  47. package/src/hooks/projects/useProject.test-d.ts +49 -0
  48. package/src/hooks/projects/useProject.ts +33 -41
  49. package/src/hooks/projects/useProjects.test-d.ts +49 -0
  50. package/src/hooks/projects/useProjects.ts +17 -23
  51. package/src/hooks/query/useQuery.ts +1 -1
  52. package/src/hooks/releases/useActiveReleases.ts +6 -6
  53. package/src/hooks/releases/usePerspective.ts +7 -12
  54. package/src/hooks/users/useUser.ts +1 -1
  55. package/src/hooks/users/useUsers.ts +1 -1
@@ -0,0 +1,32 @@
1
+ import {renderHook as reactRenderHook} from '@testing-library/react'
2
+ import {type ReactNode} from 'react'
3
+ import {describe, expect, it} from 'vitest'
4
+
5
+ import {renderHook} from '../../../test/test-utils'
6
+ import {ResourceProvider} from '../../context/ResourceProvider'
7
+ import {useResource} from './useResource'
8
+
9
+ describe('useResource', () => {
10
+ it('returns the resource from the instance config when no explicit resource is set', () => {
11
+ // test-utils wraps with ResourceProvider projectId="test" dataset="test"
12
+ const {result} = renderHook(() => useResource())
13
+ expect(result.current).toEqual({projectId: 'test', dataset: 'test'})
14
+ })
15
+
16
+ it('returns the explicit resource when ResourceProvider has a resource prop', () => {
17
+ const resource = {projectId: 'explicit-project', dataset: 'explicit-dataset'}
18
+ const {result} = reactRenderHook(() => useResource(), {
19
+ wrapper: ({children}: {children: ReactNode}) => (
20
+ <ResourceProvider resource={resource} fallback={null}>
21
+ {children}
22
+ </ResourceProvider>
23
+ ),
24
+ })
25
+ expect(result.current).toEqual(resource)
26
+ })
27
+
28
+ it('returns undefined when no resource or instance config is available', () => {
29
+ const {result} = reactRenderHook(() => useResource())
30
+ expect(result.current).toBeUndefined()
31
+ })
32
+ })
@@ -0,0 +1,24 @@
1
+ import {type DocumentResource} from '@sanity/sdk'
2
+
3
+ import {useEffectiveContextResource} from '../helpers/useNormalizedResourceOptions'
4
+
5
+ /**
6
+ * Returns the currently active `DocumentResource` for the nearest resource context.
7
+ *
8
+ * Resolves in priority order:
9
+ * 1. A `resource` prop on the nearest `<ResourceProvider>`
10
+ * 2. The `projectId`/`dataset` from the current `SanityInstance` config
11
+ * 3. `undefined` when neither is available
12
+ *
13
+ * @public
14
+ * @category Platform
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * const resource = useResource()
19
+ * console.log(resource?.projectId, resource?.dataset)
20
+ * ```
21
+ */
22
+ export function useResource(): DocumentResource | undefined {
23
+ return useEffectiveContextResource()
24
+ }
@@ -1,7 +1,7 @@
1
1
  import {createSanityInstance, type SanityConfig, type SanityInstance} from '@sanity/sdk'
2
2
  import {renderHook} from '@testing-library/react'
3
3
  import {type ReactNode} from 'react'
4
- import {describe, expect, it} from 'vitest'
4
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'
5
5
 
6
6
  import {SanityInstanceContext} from '../../context/SanityInstanceContext'
7
7
  import {useSanityInstance} from './useSanityInstance'
@@ -37,137 +37,68 @@ describe('useSanityInstance', () => {
37
37
  }).toThrow('SanityInstance context not found')
38
38
  })
39
39
 
40
- it('should include the requested config in error message when no instance found', () => {
41
- const requestedConfig = {projectId: 'test', dataset: 'test'}
42
-
43
- // Expect the hook to throw and include the requested config in the error
44
- expect(() => {
45
- renderHook(() => useSanityInstance(requestedConfig), {
46
- wrapper: createWrapper(null),
47
- })
48
- }).toThrow(JSON.stringify(requestedConfig, null, 2))
49
- })
50
-
51
- it('should find a matching instance with provided config', () => {
52
- // Create a parent instance
53
- const parentInstance = createSanityInstance({
54
- projectId: 'parent-project',
55
- dataset: 'parent-dataset',
56
- })
57
-
58
- // Create a child instance
59
- const childInstance = parentInstance.createChild({dataset: 'child-dataset'})
60
-
61
- // Render the hook with the child instance and request the parent config
62
- const {result} = renderHook(
63
- () => useSanityInstance({projectId: 'parent-project', dataset: 'parent-dataset'}),
64
- {wrapper: createWrapper(childInstance)},
65
- )
66
-
67
- // Should match and return the parent instance
68
- expect(result.current).toBe(parentInstance)
69
- })
70
-
71
- it('should throw an error if no matching instance is found for config', () => {
72
- // Create an instance
73
- const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
74
-
75
- // Request a config that doesn't match
76
- const requestedConfig: SanityConfig = {
77
- projectId: 'non-existent',
78
- dataset: 'not-found',
79
- }
80
-
81
- // Expect the hook to throw for a non-matching config
82
- expect(() => {
83
- renderHook(() => useSanityInstance(requestedConfig), {
84
- wrapper: createWrapper(instance),
85
- })
86
- }).toThrow('Could not find a matching Sanity instance')
87
- })
88
-
89
- it('should include the requested config in error message when no matching instance', () => {
90
- const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
91
- const requestedConfig = {projectId: 'different', dataset: 'different'}
92
-
93
- // Expect the error to include the requested config details
94
- expect(() => {
95
- renderHook(() => useSanityInstance(requestedConfig), {
96
- wrapper: createWrapper(instance),
97
- })
98
- }).toThrow(JSON.stringify(requestedConfig, null, 2))
99
- })
100
-
101
40
  it('should return the current instance when no config is provided', () => {
102
- // Create a hierarchy of instances
103
- const grandparent = createSanityInstance({projectId: 'gp', dataset: 'gp-ds'})
104
- const parent = grandparent.createChild({projectId: 'p'})
105
- const child = parent.createChild({dataset: 'child-ds'})
41
+ // Create a Sanity instance
42
+ const instance = createSanityInstance({projectId: 'gp', dataset: 'gp-ds'})
106
43
 
107
- // Render the hook with the child instance and no config
44
+ // Render the hook with the wrapper that provides the context
108
45
  const {result} = renderHook(() => useSanityInstance(), {
109
- wrapper: createWrapper(child),
46
+ wrapper: createWrapper(instance),
110
47
  })
111
48
 
112
- // Should return the child instance
113
- expect(result.current).toBe(child)
49
+ // Should return the instance
50
+ expect(result.current).toBe(instance)
114
51
  })
115
52
 
116
- it('should match child instance when it satisfies the config', () => {
117
- // Create a parent instance
118
- const parent = createSanityInstance({projectId: 'parent', dataset: 'parent-ds'})
53
+ describe('deprecated config parameter', () => {
54
+ let warnSpy: ReturnType<typeof vi.spyOn>
119
55
 
120
- // Create a child instance that inherits projectId
121
- const child = parent.createChild({dataset: 'child-ds'})
56
+ beforeEach(() => {
57
+ warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
58
+ })
122
59
 
123
- // Render the hook with the child instance and request by the child's dataset
124
- const {result} = renderHook(() => useSanityInstance({dataset: 'child-ds'}), {
125
- wrapper: createWrapper(child),
60
+ afterEach(() => {
61
+ warnSpy.mockRestore()
126
62
  })
127
63
 
128
- // Should match and return the child instance
129
- expect(result.current).toBe(child)
130
- })
64
+ it('should return the current context instance regardless of config', () => {
65
+ const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
66
+ const requestedConfig: SanityConfig = {projectId: 'test-project', dataset: 'test-dataset'}
131
67
 
132
- it('should match partial config correctly', () => {
133
- // Create an instance with multiple config values
134
- const instance = createSanityInstance({
135
- projectId: 'test-proj',
136
- dataset: 'test-ds',
68
+ const {result} = renderHook(() => useSanityInstance(requestedConfig), {
69
+ wrapper: createWrapper(instance),
70
+ })
71
+
72
+ expect(result.current).toBe(instance)
137
73
  })
138
74
 
139
- // Should match when requesting just one property
140
- const {result} = renderHook(() => useSanityInstance({dataset: 'test-ds'}), {
141
- wrapper: createWrapper(instance),
75
+ it('should throw if no instance in context even when config is provided', () => {
76
+ expect(() => {
77
+ renderHook(() => useSanityInstance({projectId: 'test'}), {
78
+ wrapper: createWrapper(null),
79
+ })
80
+ }).toThrow('SanityInstance context not found')
142
81
  })
143
82
 
144
- expect(result.current).toBe(instance)
145
- })
83
+ it('warns once when a config argument is passed', () => {
84
+ const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
85
+ const {rerender} = renderHook(() => useSanityInstance({projectId: 'test-project'}), {
86
+ wrapper: createWrapper(instance),
87
+ })
146
88
 
147
- it("should match deeper in hierarchy when current instance doesn't match", () => {
148
- // Create a three-level hierarchy
149
- const root = createSanityInstance({projectId: 'root', dataset: 'root-ds'})
150
- const middle = root.createChild({projectId: 'middle'})
151
- const leaf = middle.createChild({dataset: 'leaf-ds'})
89
+ expect(warnSpy).toHaveBeenCalledTimes(1)
90
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('[useSanityInstance]'))
152
91
 
153
- // Request config matching the root from the leaf
154
- const {result} = renderHook(() => useSanityInstance({projectId: 'root', dataset: 'root-ds'}), {
155
- wrapper: createWrapper(leaf),
92
+ rerender()
93
+ rerender()
94
+ expect(warnSpy).toHaveBeenCalledTimes(1)
156
95
  })
157
96
 
158
- // Should find and return the root instance
159
- expect(result.current).toBe(root)
160
- })
97
+ it('does not warn when no config is passed', () => {
98
+ const instance = createSanityInstance({projectId: 'test-project', dataset: 'test-dataset'})
99
+ renderHook(() => useSanityInstance(), {wrapper: createWrapper(instance)})
161
100
 
162
- it('should match undefined values in config', () => {
163
- // Create instance with only projectId
164
- const rootInstance = createSanityInstance({projectId: 'test'})
165
-
166
- // Match specifically looking for undefined dataset
167
- const {result} = renderHook(() => useSanityInstance({dataset: undefined}), {
168
- wrapper: createWrapper(rootInstance),
101
+ expect(warnSpy).not.toHaveBeenCalled()
169
102
  })
170
-
171
- expect(result.current).toBe(rootInstance)
172
103
  })
173
104
  })
@@ -3,78 +3,56 @@ import {useContext} from 'react'
3
3
 
4
4
  import {SanityInstanceContext} from '../../context/SanityInstanceContext'
5
5
 
6
+ const warnedCallers = new Set<string>()
7
+
6
8
  /**
7
- * Retrieves the current Sanity instance or finds a matching instance from the hierarchy
9
+ * Retrieves the current Sanity instance from context
8
10
  *
9
11
  * @public
10
12
  *
11
13
  * @category Platform
12
- * @param config - Optional configuration to match against when finding an instance
13
- * @returns The current or matching Sanity instance
14
+ * @param config - Deprecated. Formerly used to match against the instance hierarchy.
15
+ * @returns The current Sanity instance
14
16
  *
15
17
  * @remarks
16
- * This hook accesses the nearest Sanity instance from the React context. When provided with
17
- * a configuration object, it traverses up the instance hierarchy to find the closest instance
18
- * that matches the specified configuration using shallow comparison of properties.
19
- *
18
+ * This hook accesses the nearest Sanity instance from the React context.
20
19
  * The hook must be used within a component wrapped by a `ResourceProvider` or `SanityApp`.
21
20
  *
22
- * Use this hook when you need to:
23
- * - Access the current SanityInstance from context
24
- * - Find a specific instance with matching project/dataset configuration
25
- * - Access a parent instance with specific configuration values
26
- *
27
21
  * @example Get the current instance
28
22
  * ```tsx
29
- * // Get the current instance from context
30
23
  * const instance = useSanityInstance()
31
24
  * console.log(instance.config.projectId)
32
25
  * ```
33
26
  *
34
- * @example Find an instance with specific configuration
35
- * ```tsx
36
- * // Find an instance matching the given project and dataset
37
- * const instance = useSanityInstance({
38
- * projectId: 'abc123',
39
- * dataset: 'production'
40
- * })
41
- *
42
- * // Use instance for API calls
43
- * const fetchDocument = (docId) => {
44
- * // Instance is guaranteed to have the matching config
45
- * return client.fetch(`*[_id == $id][0]`, { id: docId })
46
- * }
47
- * ```
48
- *
49
- * @example Match partial configuration
50
- * ```tsx
51
- * // Find an instance with specific auth configuration
52
- * const instance = useSanityInstance({
53
- * auth: { requireLogin: true }
54
- * })
55
- * ```
56
- *
57
27
  * @throws Error if no SanityInstance is found in context
58
- * @throws Error if no matching instance is found for the provided config
59
28
  */
60
- export const useSanityInstance = (config?: SanityConfig): SanityInstance => {
61
- const instance = useContext(SanityInstanceContext)
62
-
63
- if (!instance) {
64
- throw new Error(
65
- `SanityInstance context not found. ${config ? `Requested config: ${JSON.stringify(config, null, 2)}. ` : ''}Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.`,
66
- )
29
+ export const useSanityInstance = (
30
+ /**
31
+ * @deprecated Passing a config to match against the instance hierarchy is deprecated.
32
+ * Use `useSanityInstance()` without arguments instead.
33
+ */
34
+ config?: SanityConfig,
35
+ ): SanityInstance => {
36
+ if (config !== undefined) {
37
+ const caller = new Error().stack?.split('\n')[2]?.trim() ?? 'unknown'
38
+ if (!warnedCallers.has(caller)) {
39
+ warnedCallers.add(caller)
40
+ // eslint-disable-next-line no-console
41
+ console.warn(
42
+ '[useSanityInstance] Passing a config argument is deprecated and has no effect. ' +
43
+ 'SDK apps use a single instance for all resources, so the config argument is no longer needed. ' +
44
+ 'Call useSanityInstance() without arguments instead, or useResource() to get your currently active resource.',
45
+ )
46
+ }
67
47
  }
68
48
 
69
- if (!config) return instance
49
+ const instance = useContext(SanityInstanceContext)
70
50
 
71
- const match = instance.match(config)
72
- if (!match) {
51
+ if (!instance) {
73
52
  throw new Error(
74
- `Could not find a matching Sanity instance for the requested configuration: ${JSON.stringify(config, null, 2)}.
75
- Please ensure there is a ResourceProvider component with a matching configuration in the component hierarchy.`,
53
+ `SanityInstance context not found. Please ensure that your component is wrapped in a ResourceProvider or a SanityApp component.`,
76
54
  )
77
55
  }
78
56
 
79
- return match
57
+ return instance
80
58
  }
@@ -1,4 +1,5 @@
1
1
  import {type DocumentHandle} from '@sanity/sdk'
2
+ import {renderHook as reactRenderHook} from '@testing-library/react'
2
3
  import {beforeEach, describe, expect, it, vi} from 'vitest'
3
4
 
4
5
  import {renderHook} from '../../../test/test-utils'
@@ -227,12 +228,14 @@ describe('useDispatchIntent', () => {
227
228
 
228
229
  describe('error handling', () => {
229
230
  it('should throw error when neither resource nor projectId/dataset is provided', () => {
231
+ const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
230
232
  const invalidHandle = {
231
233
  documentId: 'test-document-id',
232
234
  documentType: 'test-document-type',
233
235
  }
234
236
 
235
- const {result} = renderHook(() =>
237
+ // Use a minimal wrapper with no resource context so the normalization has nothing to fall back to
238
+ const {result} = reactRenderHook(() =>
236
239
  useDispatchIntent({
237
240
  action: 'edit',
238
241
  documentHandle: invalidHandle as unknown as DocumentHandle,
@@ -242,6 +245,7 @@ describe('useDispatchIntent', () => {
242
245
  expect(() => result.current.dispatchIntent()).toThrow(
243
246
  'useDispatchIntent: Unable to determine resource. Either `resource`, `resourceName`, or both `projectId` and `dataset` must be provided in documentHandle.',
244
247
  )
248
+ consoleErrorSpy.mockRestore()
245
249
  })
246
250
  })
247
251
  })
@@ -1,9 +1,9 @@
1
1
  import {SDK_CHANNEL_NAME, SDK_NODE_NAME} from '@sanity/message-protocol'
2
- import {type DocumentHandle, type FrameMessage} from '@sanity/sdk'
2
+ import {type FrameMessage} from '@sanity/sdk'
3
3
  import {useCallback} from 'react'
4
4
 
5
+ import {type DocumentHandle} from '../../config/handles'
5
6
  import {useWindowConnection} from '../comlink/useWindowConnection'
6
- import {type WithResourceNameSupport} from '../helpers/useNormalizedResourceOptions'
7
7
  import {useResourceIdFromDocumentHandle} from './utils/useResourceIdFromDocumentHandle'
8
8
 
9
9
  /**
@@ -42,7 +42,7 @@ interface DispatchIntent {
42
42
  interface UseDispatchIntentParams {
43
43
  action?: 'edit'
44
44
  intentId?: string
45
- documentHandle: WithResourceNameSupport<DocumentHandle>
45
+ documentHandle: DocumentHandle
46
46
  parameters?: Record<string, unknown>
47
47
  }
48
48
 
@@ -2,12 +2,15 @@ import {type Message} from '@sanity/comlink'
2
2
  import {type FavoriteStatusResponse, getFavoritesState, resolveFavoritesState} from '@sanity/sdk'
3
3
  import {act, renderHook} from '@testing-library/react'
4
4
  import {BehaviorSubject} from 'rxjs'
5
- import {beforeEach, describe, expect, it, vi} from 'vitest'
5
+ import {beforeEach, describe, expect, it, type Mock, vi} from 'vitest'
6
6
 
7
7
  import {ResourceProvider} from '../../context/ResourceProvider'
8
8
  import {useWindowConnection, type WindowConnection} from '../comlink/useWindowConnection'
9
9
  import {useManageFavorite} from './useManageFavorite'
10
10
 
11
+ type MockFetch = (type: string, data?: unknown, options?: unknown) => Promise<{success: boolean}>
12
+ type MockSendMessage = (type: string, data?: unknown) => void
13
+
11
14
  vi.mock(import('@sanity/sdk'), async (importOriginal) => {
12
15
  const actual = await importOriginal()
13
16
  return {
@@ -23,8 +26,8 @@ vi.mock('../comlink/useWindowConnection', () => ({
23
26
 
24
27
  describe('useManageFavorite', () => {
25
28
  let favoriteStatusSubject: BehaviorSubject<FavoriteStatusResponse>
26
- let mockFetch: ReturnType<typeof vi.fn>
27
- let mockSendMessage: ReturnType<typeof vi.fn>
29
+ let mockFetch: Mock<MockFetch>
30
+ let mockSendMessage: Mock<MockSendMessage>
28
31
 
29
32
  const mockDocumentHandle = {
30
33
  documentId: 'mock-id',
@@ -56,15 +59,16 @@ describe('useManageFavorite', () => {
56
59
  })
57
60
 
58
61
  // Mock useWindowConnection
59
- mockFetch = vi.fn().mockResolvedValue({success: true})
60
- mockSendMessage = vi.fn()
61
- vi.mocked(useWindowConnection).mockImplementation(() => {
62
- return {
63
- fetch: (type: string, data?: unknown, options: unknown = {}) =>
64
- mockFetch(type, data, options),
65
- sendMessage: mockSendMessage,
66
- }
67
- })
62
+ mockFetch = vi.fn<MockFetch>().mockResolvedValue({success: true})
63
+ mockSendMessage = vi.fn<MockSendMessage>()
64
+ vi.mocked(useWindowConnection).mockImplementation(
65
+ () =>
66
+ ({
67
+ fetch: (type: string, data?: unknown, options: unknown = {}) =>
68
+ mockFetch(type, data, options),
69
+ sendMessage: mockSendMessage,
70
+ }) as unknown as WindowConnection<Message>,
71
+ )
68
72
  })
69
73
 
70
74
  afterEach(() => {
@@ -19,13 +19,9 @@ export function useResourceIdFromDocumentHandle(
19
19
  documentHandle: DocumentHandle,
20
20
  ): DashboardMessageResource {
21
21
  const options = useNormalizedResourceOptions(documentHandle)
22
- const {projectId, dataset, resource} = options
22
+ const {resource} = options
23
23
  let resourceId: string = ''
24
24
  let resourceType: 'media-library' | 'canvas' | undefined
25
- if (projectId && dataset) {
26
- resourceId = `${projectId}.${dataset}`
27
- }
28
-
29
25
  if (resource) {
30
26
  if (isDatasetResource(resource)) {
31
27
  resourceId = `${resource.projectId}.${resource.dataset}`