Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const eslintConfig = defineConfig([
]),
{
rules: {
"react-hooks/set-state-in-effect": "off"
}
}
"react-hooks/set-state-in-effect": "off",
},
},
])

export default eslintConfig
9 changes: 8 additions & 1 deletion hooks/use-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "@aws-sdk/client-s3"
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
import { useS3 } from "@/contexts/s3-context"
import { decodeS3UrlEncodedObjectList, decodeS3UrlEncodedObjectVersions } from "@/lib/s3-object-encoding"

function attachIncludeDeletedHeader(command: ListObjectsV2Command) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -101,11 +102,13 @@ export function useObject(bucket: string) {
MaxKeys: pageSize,
Delimiter: "/",
ContinuationToken: continuationToken,
EncodingType: "url",
})
if (options?.includeDeleted) {
attachIncludeDeletedHeader(command)
}
return client.send(command)
const response = await client.send(command)
return decodeS3UrlEncodedObjectList(response)
},
[client],
)
Expand All @@ -121,8 +124,10 @@ export function useObject(bucket: string) {
Bucket: bucketName,
Prefix: prefix,
ContinuationToken: continuationToken,
EncodingType: "url",
}),
)
decodeS3UrlEncodedObjectList(data)

data.Contents?.forEach((item) => {
if (item.Key) callback(item.Key)
Expand Down Expand Up @@ -256,8 +261,10 @@ export function useObject(bucket: string) {
Bucket: bucket,
Prefix: key,
Delimiter: "/",
EncodingType: "url",
}),
)
decodeS3UrlEncodedObjectVersions(res)
const Versions = (res.Versions ?? []).filter((v) => v.Key === key)
const DeleteMarkers = (res.DeleteMarkers ?? []).filter((m) => m.Key === key)
Versions.sort((a, b) => new Date(b.LastModified!).getTime() - new Date(a.LastModified!).getTime())
Expand Down
5 changes: 5 additions & 0 deletions lib/delete-task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ListObjectVersionsCommand,
S3Client,
} from "@aws-sdk/client-s3"
import { decodeS3UrlEncodedObjectList, decodeS3UrlEncodedObjectVersions } from "./s3-object-encoding"
import type { ManagedTask, TaskHandler, TaskLifecycleStatus } from "./task-manager"
import { createTaskId } from "./task-id"

Expand Down Expand Up @@ -116,9 +117,11 @@ export function createDeleteTaskHelpers(s3Client: S3Client, config: DeleteTaskCo
Prefix: prefix,
KeyMarker: keyMarker,
VersionIdMarker: versionIdMarker,
EncodingType: "url",
}),
{ abortSignal: abortController.signal },
)
decodeS3UrlEncodedObjectVersions(data)

const objectsToDelete: { Key: string; VersionId?: string }[] = []
data.Versions?.forEach((v) => {
Expand Down Expand Up @@ -151,9 +154,11 @@ export function createDeleteTaskHelpers(s3Client: S3Client, config: DeleteTaskCo
Bucket: bucketName,
Prefix: prefix,
ContinuationToken: continuationToken,
EncodingType: "url",
}),
{ abortSignal: abortController.signal },
)
decodeS3UrlEncodedObjectList(data)

const objectsToDelete = (data.Contents ?? []).filter((item) => item.Key).map((item) => ({ Key: item.Key! }))

Expand Down
73 changes: 73 additions & 0 deletions lib/s3-object-encoding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
type S3KeyedItem = {
Key?: string
}

type S3PrefixedItem = {
Prefix?: string
}

type S3ObjectListResponse = {
EncodingType?: string
Prefix?: string
Delimiter?: string
StartAfter?: string
Contents?: S3KeyedItem[]
CommonPrefixes?: S3PrefixedItem[]
}

type S3ObjectVersionsResponse = {
EncodingType?: string
Prefix?: string
Delimiter?: string
KeyMarker?: string
NextKeyMarker?: string
Versions?: S3KeyedItem[]
DeleteMarkers?: S3KeyedItem[]
CommonPrefixes?: S3PrefixedItem[]
}

function decodeS3UrlValue(value: string | undefined): string | undefined {
if (value == null) return value

try {
return decodeURIComponent(value)
} catch {
return value
}
}

export function decodeS3UrlEncodedObjectList<T extends S3ObjectListResponse>(response: T): T {
if (response.EncodingType !== "url") return response

response.Prefix = decodeS3UrlValue(response.Prefix)
response.Delimiter = decodeS3UrlValue(response.Delimiter)
response.StartAfter = decodeS3UrlValue(response.StartAfter)
response.Contents?.forEach((item) => {
item.Key = decodeS3UrlValue(item.Key)
})
response.CommonPrefixes?.forEach((item) => {
item.Prefix = decodeS3UrlValue(item.Prefix)
})

return response
}

export function decodeS3UrlEncodedObjectVersions<T extends S3ObjectVersionsResponse>(response: T): T {
if (response.EncodingType !== "url") return response

response.Prefix = decodeS3UrlValue(response.Prefix)
response.Delimiter = decodeS3UrlValue(response.Delimiter)
response.KeyMarker = decodeS3UrlValue(response.KeyMarker)
response.NextKeyMarker = decodeS3UrlValue(response.NextKeyMarker)
response.Versions?.forEach((item) => {
item.Key = decodeS3UrlValue(item.Key)
})
response.DeleteMarkers?.forEach((item) => {
item.Key = decodeS3UrlValue(item.Key)
})
response.CommonPrefixes?.forEach((item) => {
item.Prefix = decodeS3UrlValue(item.Prefix)
})

return response
}
199 changes: 0 additions & 199 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading