Skip to content

Commit 1709d95

Browse files
authored
fix(auth): ensure that authStore is a true shared resource store (#371)
1 parent 9487cb2 commit 1709d95

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

packages/core/src/auth/authStore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export interface AuthStoreState {
157157

158158
export const authStore = createResource<AuthStoreState>({
159159
name: 'Auth',
160+
isShared: true,
160161
getInitialState(instance) {
161162
const {
162163
apiHost,

packages/core/src/resources/createResource.ts

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ import {getEnv} from '../utils/getEnv'
77

88
const resourceCache = new WeakMap<SdkIdentity, Map<string, InitializedResource<unknown>>>()
99

10+
// Create a singleton identity for the shared auth store
11+
const SHARED_IDENTITY: SdkIdentity = {
12+
id: 'shared',
13+
resourceId: 'shared.shared',
14+
projectId: 'shared',
15+
dataset: 'shared',
16+
} as const
17+
1018
type Teardown = () => void
1119

1220
export interface Resource<TState> {
@@ -16,6 +24,7 @@ export interface Resource<TState> {
1624
this: {instance: SanityInstance; state: ResourceState<TState>},
1725
instance: SanityInstance,
1826
) => Teardown
27+
isShared?: boolean
1928
}
2029

2130
export function createResource<TState>(resource: Resource<TState>): Resource<TState> {
@@ -62,8 +71,9 @@ export function initializeResource<TState>(
6271
instance: SanityInstance,
6372
resource: Resource<TState>,
6473
): InitializedResource<TState> {
65-
const fullName =
66-
resource.name === 'Auth' ? 'Auth-global' : `${resource.name}-${instance.identity.resourceId}`
74+
const fullName = resource.isShared
75+
? `${resource.name}-shared`
76+
: `${resource.name}-${instance.identity.resourceId}`
6777
const initialState = resource.getInitialState(instance)
6878
const state = createResourceState(initialState, {
6979
name: fullName,
@@ -74,16 +84,30 @@ export function initializeResource<TState>(
7484
return {state, dispose}
7585
}
7686

87+
// Track which instances are using which shared resources
88+
const instanceSharedResources = new Map<SdkIdentity, Set<string>>()
89+
7790
export function getOrCreateResource<TState>(
7891
instance: SanityInstance,
7992
resource: Resource<TState>,
8093
): InitializedResource<TState> {
81-
const fullName =
82-
resource.name === 'Auth' ? 'Auth-global' : `${resource.name}-${instance.identity.resourceId}`
83-
if (!resourceCache.has(instance.identity)) {
84-
resourceCache.set(instance.identity, new Map())
94+
const identityKey = resource.isShared ? SHARED_IDENTITY : instance.identity
95+
const fullName = resource.isShared
96+
? `${resource.name}-shared`
97+
: `${resource.name}-${instance.identity.resourceId}`
98+
99+
if (resource.isShared) {
100+
// Track that this instance is using this shared resource
101+
if (!instanceSharedResources.has(instance.identity)) {
102+
instanceSharedResources.set(instance.identity, new Set())
103+
}
104+
instanceSharedResources.get(instance.identity)!.add(fullName)
85105
}
86-
const initializedResources = resourceCache.get(instance.identity)!
106+
107+
if (!resourceCache.has(identityKey)) {
108+
resourceCache.set(identityKey, new Map())
109+
}
110+
const initializedResources = resourceCache.get(identityKey)!
87111
const cached = initializedResources.get(fullName)
88112
if (cached) return cached as InitializedResource<TState>
89113

@@ -93,10 +117,50 @@ export function getOrCreateResource<TState>(
93117
}
94118

95119
export function disposeResources(identity: SdkIdentity): void {
120+
// Handle instance-specific resources (not shared)
96121
const resources = resourceCache.get(identity)
97-
if (!resources) return
122+
if (resources) {
123+
for (const resource of resources.values()) {
124+
resource.dispose()
125+
}
126+
resourceCache.delete(identity)
127+
}
128+
129+
// Handle shared resources this instance may have been using
130+
const usedSharedResources = instanceSharedResources.get(identity)
131+
if (usedSharedResources) {
132+
const sharedResources = resourceCache.get(SHARED_IDENTITY)
133+
if (sharedResources) {
134+
for (const fullName of usedSharedResources) {
135+
const resource = sharedResources.get(fullName)
136+
if (resource) {
137+
// Remove this instance from tracking
138+
usedSharedResources.delete(fullName)
139+
140+
// Check if any other instances are still using this shared resource
141+
let stillInUse = false
142+
for (const [otherIdentity, otherUsed] of instanceSharedResources.entries()) {
143+
if (otherIdentity !== identity && otherUsed.has(fullName)) {
144+
stillInUse = true
145+
break
146+
}
147+
}
148+
149+
// If no other instances are using it, dispose and clean up
150+
if (!stillInUse) {
151+
resource.dispose()
152+
sharedResources.delete(fullName)
153+
}
154+
}
155+
}
156+
157+
// Clean up shared resources map if empty
158+
if (sharedResources.size === 0) {
159+
resourceCache.delete(SHARED_IDENTITY)
160+
}
161+
}
98162

99-
for (const resource of resources.values()) {
100-
resource.dispose()
163+
// Clean up instance tracking
164+
instanceSharedResources.delete(identity)
101165
}
102166
}

0 commit comments

Comments
 (0)