mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
On a versioned bucket a delete is a soft delete, and the file preview panel already calls that action Archive and promises the versions stay recoverable. Nothing in the dashboard lets a user see or restore an archived file yet. This is the data layer for that, with no UI: query and mutation shapes written to the studio conventions, endpoints stubbed, returning empty. - `archived-objects-query.ts` — `ArchivedObject` / `ArchivedObjectVersion` types and `archivedObjectsQueryOptions` - `archived-object-restore-mutation.ts` — bring an archived object back - `archived-object-purge-mutation.ts` — delete it and every version, permanently - `archived-object-version-delete-mutation.ts` — remove one retained version - `archivedOverlay.utils.ts` — synthesizes the explorer rows for one folder from the archived list - `archivedVersions.utils.ts` — an archived object's history as one flat list Two prototype problems fixed rather than carried over: The prototype identified the "was current when archived" row by the sentinel `versionId === objectId`, which was load-bearing across three files and would break the moment real version ids arrived. `ArchivedObject` now carries a `currentVersion` record, so merging invents no fields and the distinction is an explicit `wasCurrentAtArchive` flag. The prototype's object had both `name` and `originalPath`, inconsistently — the path normalization existed mostly to strip a duplicated leaf folder that inconsistency produced. There is now a single `path`, and `getArchivedSegments` is the only function that interprets it, so a different API shape is a one-place change. Also drops `deletedBy` and `expiresAt`, which the prototype never rendered. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
import { queryOptions } from '@tanstack/react-query'
|
|
|
|
import { storageKeys } from '../keys'
|
|
import type { ObjectVersionAction } from './object-versions-query'
|
|
import { IS_PLATFORM } from '@/lib/constants'
|
|
import type { ResponseError } from '@/types'
|
|
|
|
export interface ArchivedObjectVersion {
|
|
versionId: string
|
|
size: number
|
|
createdAt: string
|
|
action: ObjectVersionAction
|
|
}
|
|
|
|
export interface ArchivedObject {
|
|
id: string
|
|
/** Full path including the file name. Only `getArchivedSegments` splits it. */
|
|
path: string
|
|
archivedAt: string
|
|
/**
|
|
* The version that was live when the object was archived. S3 puts a delete
|
|
* marker on top of the stack; this UI hides that and surfaces the version
|
|
* underneath as an ordinary history entry.
|
|
*/
|
|
currentVersion: ArchivedObjectVersion
|
|
/** Newest first. */
|
|
noncurrentVersions: ArchivedObjectVersion[]
|
|
}
|
|
|
|
export type ArchivedObjectsVariables = {
|
|
projectRef?: string
|
|
bucketId?: string
|
|
}
|
|
|
|
export type ArchivedObjectsError = ResponseError
|
|
|
|
async function getArchivedObjects(
|
|
{ projectRef, bucketId }: ArchivedObjectsVariables,
|
|
_signal?: AbortSignal
|
|
): Promise<ArchivedObject[]> {
|
|
if (!projectRef) throw new Error('projectRef is required')
|
|
if (!bucketId) throw new Error('bucketId is required')
|
|
|
|
// TODO(storage-versioning): real endpoint once Storage exposes it.
|
|
return []
|
|
}
|
|
|
|
export type ArchivedObjectsData = Awaited<ReturnType<typeof getArchivedObjects>>
|
|
|
|
export const archivedObjectsQueryOptions = ({ projectRef, bucketId }: ArchivedObjectsVariables) =>
|
|
queryOptions({
|
|
queryKey: storageKeys.archivedObjects(projectRef, bucketId),
|
|
queryFn: ({ signal }) => getArchivedObjects({ projectRef, bucketId }, signal),
|
|
enabled: IS_PLATFORM && typeof projectRef !== 'undefined' && typeof bucketId !== 'undefined',
|
|
})
|