Skip to content

Commit

Permalink
fix(releases): handling cases where no create release permissions whi…
Browse files Browse the repository at this point in the history
…lst at limit of release in project (#8644)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
  • Loading branch information
jordanl17 and renovate[bot] authored Feb 17, 2025
1 parent dc2d261 commit 37846d5
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 15 deletions.
7 changes: 7 additions & 0 deletions packages/sanity/src/core/error/types/isErrorWithDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type ErrorWithDetails = {details?: {type?: string}}

export const isErrorWithDetails = (error: unknown): error is ErrorWithDetails =>
typeof error === 'object' &&
error !== null &&
'details' in error &&
typeof (error as {details: unknown}).details === 'object'
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ export function ReleasesUpsellProvider(props: {children: React.ReactNode}) {
)

const onReleaseLimitReached = useCallback(
(limit: number) => {
(limit: number, suppressDialogOpening: boolean = false) => {
setReleaseLimit(limit)

if ((activeReleases?.length || 0) >= limit) {
if (!suppressDialogOpening && (activeReleases?.length || 0) >= limit) {
handleOpenDialog()
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/src/core/releases/contexts/upsell/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface ReleasesUpsellContextValue {
mode: 'upsell' | 'default' | 'disabled'
upsellDialogOpen: boolean
guardWithReleaseLimitUpsell: (callback: () => void, throwError?: boolean) => false | void
onReleaseLimitReached: (limit: number) => void
onReleaseLimitReached: (limit: number, suppressDialogOpening: boolean) => void
telemetryLogs: {
dialogSecondaryClicked: () => void
dialogPrimaryClicked: () => void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from '@sanity/client'

import {getPublishedId, getVersionId} from '../../util'
import {type ReleasesUpsellContextValue} from '../contexts/upsell/types'
import {getReleaseIdFromReleaseDocumentId, type ReleaseDocument} from '../index'
import {type RevertDocument} from '../tool/components/releaseCTAButtons/ReleaseRevertButton/useDocumentRevertStates'
import {isReleaseLimitError} from './isReleaseLimitError'
Expand Down Expand Up @@ -51,7 +52,7 @@ const METADATA_PROPERTY_NAME = 'metadata'

export function createReleaseOperationsStore(options: {
client: SanityClient
onReleaseLimitReached: (limit: number) => void
onReleaseLimitReached: ReleasesUpsellContextValue['onReleaseLimitReached']
}): ReleaseOperationsStore {
const {client} = options
const requestAction = createRequestAction(options.onReleaseLimitReached)
Expand Down Expand Up @@ -344,7 +345,9 @@ type ReleaseAction =
| CreateVersionReleaseApiAction
| UnpublishVersionReleaseApiAction

export function createRequestAction(onReleaseLimitReached: (limit: number) => void) {
export function createRequestAction(
onReleaseLimitReached: ReleasesUpsellContextValue['onReleaseLimitReached'],
) {
return async function requestAction(
client: SanityClient,
actions: ReleaseAction | ReleaseAction[],
Expand All @@ -363,7 +366,7 @@ export function createRequestAction(onReleaseLimitReached: (limit: number) => vo
} catch (e) {
if (isReleaseLimitError(e)) {
// free accounts do not return limit, 0 is implied
onReleaseLimitReached(e.details.limit || 0)
onReleaseLimitReached(e.details.limit || 0, !!options?.dryRun)
}

throw e
Expand Down
11 changes: 3 additions & 8 deletions packages/sanity/src/core/releases/store/isReleaseLimitError.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
type ErrorWithDetails = {details?: {type?: string}}
type ReleaseLimitError = {details: {type: 'releaseLimitExceededError'; limit: number}}
import {isErrorWithDetails} from '../../error/types/isErrorWithDetails'

const hasDetails = (error: unknown): error is ErrorWithDetails =>
typeof error === 'object' &&
error !== null &&
'details' in error &&
typeof (error as {details: unknown}).details === 'object'
type ReleaseLimitError = {details: {type: 'releaseLimitExceededError'; limit: number}}

export const isReleaseLimitError = (error: unknown): error is ReleaseLimitError =>
hasDetails(error) && error.details?.type === 'releaseLimitExceededError'
isErrorWithDetails(error) && error.details?.type === 'releaseLimitExceededError'
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import {isErrorWithDetails} from '../../error/types/isErrorWithDetails'

export interface useReleasePermissionsValue {
checkWithPermissionGuard: <T extends (...args: any[]) => Promise<void> | void>(
action: T,
...args: Parameters<T>
) => Promise<boolean>
}

type ReleasePermissionError = {details: {type: 'insufficientPermissionsError'}}

export const isReleasePermissionError = (error: unknown): error is ReleasePermissionError =>
isErrorWithDetails(error) && error.details?.type === 'insufficientPermissionsError'

/**
* @internal
*/
Expand All @@ -27,7 +34,7 @@ export function useReleasePermissions(): useReleasePermissionsValue {
})
return true
} catch (e) {
return false
return !isReleasePermissionError(e)
}
}
return {
Expand Down

0 comments on commit 37846d5

Please sign in to comment.