chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
'use client'
|
||||
|
||||
import type React from 'react'
|
||||
import { createContext, useEffect, useMemo } from 'react'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { requestJson } from '@/lib/api/client/request'
|
||||
import { listCreatorOrganizationsContract } from '@/lib/api/contracts/organizations'
|
||||
import { client } from '@/lib/auth/auth-client'
|
||||
import {
|
||||
type AppSession,
|
||||
extractSessionDataFromAuthClientResult,
|
||||
} from '@/lib/auth/session-response'
|
||||
import { sessionKeys, useSessionQuery } from '@/hooks/queries/session'
|
||||
|
||||
export type SessionHookResult = {
|
||||
data: AppSession
|
||||
isPending: boolean
|
||||
error: Error | null
|
||||
refetch: () => Promise<void>
|
||||
}
|
||||
|
||||
export const SessionContext = createContext<SessionHookResult | null>(null)
|
||||
|
||||
const logger = createLogger('SessionProvider')
|
||||
|
||||
export function SessionProvider({ children }: { children: React.ReactNode }) {
|
||||
const queryClient = useQueryClient()
|
||||
const query = useSessionQuery()
|
||||
const { data, isPending, error, refetch } = query
|
||||
|
||||
useEffect(() => {
|
||||
let isCancelled = false
|
||||
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
const wasUpgraded = params.get('upgraded') === 'true'
|
||||
|
||||
if (!wasUpgraded) {
|
||||
return
|
||||
}
|
||||
|
||||
params.delete('upgraded')
|
||||
const newUrl = params.toString()
|
||||
? `${window.location.pathname}?${params.toString()}`
|
||||
: window.location.pathname
|
||||
window.history.replaceState({}, '', newUrl)
|
||||
|
||||
const refreshAfterUpgrade = async () => {
|
||||
const res = await client.getSession({ query: { disableCookieCache: true } })
|
||||
const fresh = extractSessionDataFromAuthClientResult(res) as AppSession
|
||||
|
||||
if (isCancelled) return null
|
||||
|
||||
await queryClient.cancelQueries({ queryKey: sessionKeys.detail() })
|
||||
queryClient.setQueryData(sessionKeys.detail(), fresh)
|
||||
return fresh
|
||||
}
|
||||
|
||||
const initializeSession = async () => {
|
||||
let session: AppSession = null
|
||||
try {
|
||||
session = await refreshAfterUpgrade()
|
||||
} catch (e) {
|
||||
logger.warn('Failed to refresh session after subscription upgrade', { error: e })
|
||||
}
|
||||
|
||||
if (isCancelled) {
|
||||
return
|
||||
}
|
||||
|
||||
// Refresh the plan surfaces even if the cookie-bypass read above failed: they
|
||||
// query server truth (not the session cookie cache), so they still reconcile.
|
||||
queryClient.invalidateQueries({ queryKey: ['organizations'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['subscription'] })
|
||||
|
||||
const activeOrganizationId = session?.session?.activeOrganizationId ?? null
|
||||
if (!session || activeOrganizationId) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const orgData = await requestJson(listCreatorOrganizationsContract, {}).catch(() => null)
|
||||
if (!orgData) return
|
||||
|
||||
const organizationId = orgData.organizations?.[0]?.id
|
||||
|
||||
if (!organizationId || isCancelled) {
|
||||
return
|
||||
}
|
||||
|
||||
await client.organization.setActive({ organizationId })
|
||||
|
||||
if (!isCancelled) {
|
||||
const res = await client.getSession({ query: { disableCookieCache: true } })
|
||||
const fresh = extractSessionDataFromAuthClientResult(res) as AppSession
|
||||
if (!isCancelled) {
|
||||
await queryClient.cancelQueries({ queryKey: sessionKeys.detail() })
|
||||
queryClient.setQueryData(sessionKeys.detail(), fresh)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn('Failed to activate organization after subscription upgrade', { error })
|
||||
}
|
||||
}
|
||||
|
||||
void initializeSession()
|
||||
|
||||
return () => {
|
||||
isCancelled = true
|
||||
}
|
||||
}, [queryClient])
|
||||
|
||||
useEffect(() => {
|
||||
if (isPending) return
|
||||
|
||||
import('posthog-js')
|
||||
.then(({ default: posthog }) => {
|
||||
try {
|
||||
if (typeof posthog.identify !== 'function') return
|
||||
|
||||
if (data?.user) {
|
||||
posthog.identify(data.user.id, {
|
||||
email: data.user.email,
|
||||
name: data.user.name,
|
||||
email_verified: data.user.emailVerified,
|
||||
created_at: data.user.createdAt,
|
||||
})
|
||||
if (
|
||||
typeof posthog.startSessionRecording === 'function' &&
|
||||
typeof posthog.sessionRecordingStarted === 'function' &&
|
||||
!posthog.sessionRecordingStarted()
|
||||
) {
|
||||
posthog.startSessionRecording()
|
||||
}
|
||||
} else {
|
||||
posthog.reset()
|
||||
}
|
||||
} catch {}
|
||||
})
|
||||
.catch(() => {})
|
||||
}, [data, isPending])
|
||||
|
||||
const value = useMemo<SessionHookResult>(
|
||||
() => ({
|
||||
data: data ?? null,
|
||||
isPending,
|
||||
error,
|
||||
refetch: async () => {
|
||||
await refetch()
|
||||
},
|
||||
}),
|
||||
[data, isPending, error, refetch]
|
||||
)
|
||||
|
||||
return <SessionContext.Provider value={value}>{children}</SessionContext.Provider>
|
||||
}
|
||||
Reference in New Issue
Block a user