diff --git a/src/lib/helpers/files.test.ts b/src/lib/helpers/files.test.ts new file mode 100644 index 0000000000..1e27a7b8af --- /dev/null +++ b/src/lib/helpers/files.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from 'vitest'; +import { + DEPLOYMENT_ARCHIVE_EXTENSIONS, + getInvalidDeploymentArchiveReason +} from './files'; + +describe('deployment archive extensions', () => { + it('should include the compound tar.gz extension for the file picker accept attribute', () => { + // On macOS a bare '.gz' accept token does not match 'code.tar.gz' files + // (compound tar+gzip UTI), greying them out in the picker. + expect(DEPLOYMENT_ARCHIVE_EXTENSIONS).toContain('tar.gz'); + expect(DEPLOYMENT_ARCHIVE_EXTENSIONS).toContain('gz'); + }); + + it('should accept .tar.gz archives and reject other files', () => { + const ok = [new File(['x'], 'code.tar.gz')]; + expect(getInvalidDeploymentArchiveReason(ok)).toBeNull(); + + const upper = [new File(['x'], 'CODE.TAR.GZ')]; + expect(getInvalidDeploymentArchiveReason(upper)).toBeNull(); + + const zip = [new File(['x'], 'code.zip')]; + expect(getInvalidDeploymentArchiveReason(zip)).toBe('invalid_extension'); + }); +}); diff --git a/src/lib/helpers/files.ts b/src/lib/helpers/files.ts index 1efd2319ef..6c4b95e219 100644 --- a/src/lib/helpers/files.ts +++ b/src/lib/helpers/files.ts @@ -80,6 +80,16 @@ export async function gzipUpload(files: FileList) { return uploadFile; } +/** + * Extensions accepted for manual deployment archives. + * + * 'tar.gz' must be listed alongside 'gz': the file picker `accept` attribute is + * built from these extensions, and on macOS a bare '.gz' token does not match + * 'code.tar.gz' files (their UTI is the compound tar+gzip type), so the picker + * greys them out. + */ +export const DEPLOYMENT_ARCHIVE_EXTENSIONS = ['gz', 'tar.gz']; + export function getInvalidDeploymentArchiveReason( files: FileList | File[] | null | undefined, maxSize?: number diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte index f49a5ded72..daf6b76311 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte @@ -22,7 +22,8 @@ import { getInvalidDeploymentArchiveReason, InvalidFileType, - removeFile + removeFile, + DEPLOYMENT_ARCHIVE_EXTENSIONS } from '$lib/helpers/files'; import { isCloud } from '$lib/system'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; @@ -224,7 +225,7 @@ diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte index 0ae9ada858..f18fc12ea0 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte @@ -7,7 +7,8 @@ import { getInvalidDeploymentArchiveReason, InvalidFileType, - removeFile + removeFile, + DEPLOYMENT_ARCHIVE_EXTENSIONS } from '$lib/helpers/files'; import { addNotification } from '$lib/stores/notifications'; import { IconInfo } from '@appwrite.io/pink-icons-svelte'; @@ -93,7 +94,7 @@ Upload a tar.gz file containing your function source code