Files
supabase/apps/studio/components/interfaces/Storage/EditBucketModal.utils.ts
T
Francesco SansalvadoreandClaude Sonnet 5 b8d03d2214 feat(storage): wire object versioning into the bucket modals
Mounts the versioning form section in the create and edit bucket modals behind
`useIsStorageVersioningEnabled`. Form state only for now — the Storage API does
not accept the fields yet, and both call sites are marked with TODOs.

- Both modals spread `bucketVersioningFormFields` into their schema and call
  `superRefineBucketVersioning` from `superRefine`
- Create prefills the project defaults (30 days / 10 versions)
- Edit adds a confirmation before suspending an actively versioning bucket, and
  derives its prefill through `getVersioningFormDefaults`
- `EditBucketModal.utils.ts` replaces the prefill and next-state derivations
  with pure, tested helpers instead of stacked nested ternaries
- `storage_bucket_created` now reports whether versioning was enabled

Both forms move to `mode: 'onChange'` so the numeric versioning bounds surface as
the user types rather than only on submit. This also replaces the prototype's
`trigger()`-inside-`onChange`, which validated against pre-update form state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-05 15:04:12 +02:00

64 lines
2.2 KiB
TypeScript

import type { BucketVersioningFormValues } from './BucketVersioningFields.schema'
import {
PROJECT_VERSIONING_DEFAULTS,
type BucketVersioningState,
type ExpirationMode,
} from './StorageVersioning.constants'
/** A bucket's persisted object versioning settings, as the edit form reads them. */
export interface BucketVersioningSettings {
versioning: BucketVersioningState
/** `null` when no age condition is part of the lifecycle policy. */
versionExpiryDays: number | null
/** `null` when no version cap is part of the lifecycle policy. */
maxNoncurrentVersions: number | null
expirationMode: ExpirationMode
}
/**
* A never-versioned bucket has no stored policy, so it prefills the project
* defaults. A versioned or suspended one shows its own policy, and an unset
* condition stays unset (`''`) — prefilling there would silently add a bound the
* user never chose.
*/
export const getVersioningFormDefaults = (
settings: BucketVersioningSettings
): BucketVersioningFormValues => {
const hasEverBeenVersioned = settings.versioning !== 'disabled'
if (!hasEverBeenVersioned) {
return {
enable_versioning: false,
version_expiry_days: PROJECT_VERSIONING_DEFAULTS.versionExpiryDays,
max_noncurrent_versions: PROJECT_VERSIONING_DEFAULTS.maxNoncurrentVersions,
expiration_mode: 'and',
}
}
return {
enable_versioning: settings.versioning === 'enabled',
version_expiry_days: settings.versionExpiryDays ?? '',
max_noncurrent_versions: settings.maxNoncurrentVersions ?? '',
expiration_mode: settings.expirationMode,
}
}
/**
* Turning versioning off suspends rather than disables: S3 has no path back to
* `disabled` once a bucket has been versioned. A never-versioned bucket stays
* `disabled`.
*/
export const getNextVersioningState = (
currentState: BucketVersioningState,
isVersioningEnabled: boolean
): BucketVersioningState => {
if (isVersioningEnabled) return 'enabled'
return currentState === 'disabled' ? 'disabled' : 'suspended'
}
/** True when saving would stop an actively versioning bucket — worth confirming. */
export const isSuspendingVersioning = (
currentState: BucketVersioningState,
isVersioningEnabled: boolean
) => currentState === 'enabled' && !isVersioningEnabled