diff --git a/src/handlers/get.ts b/src/handlers/get.ts index 2fb0251..7e00d63 100644 --- a/src/handlers/get.ts +++ b/src/handlers/get.ts @@ -1,13 +1,13 @@ import { CACHE } from '../constants/cache'; import responses from '../responses'; import { VIRTUAL_DIRS } from '../constants/r2Prefixes'; +import { isCacheEnabled } from '../utils/cache'; import { - isCacheEnabled, isDirectoryPath, hasTrailingSlash, mapUrlPathToBucketPath, - parseUrl, -} from '../util'; +} from '../utils/path'; +import { parseUrl } from '../utils/request'; import { Handler } from './handler'; import { listDirectory, diff --git a/src/handlers/post.ts b/src/handlers/post.ts index 06269e9..4750e97 100644 --- a/src/handlers/post.ts +++ b/src/handlers/post.ts @@ -1,5 +1,5 @@ import responses from '../responses'; -import { parseUrl } from '../util'; +import { parseUrl } from '../utils/request'; import { Handler } from './handler'; import { cachePurge } from './strategies/cachePurge'; diff --git a/src/handlers/strategies/cachePurge.ts b/src/handlers/strategies/cachePurge.ts index c6eb80c..c559301 100644 --- a/src/handlers/strategies/cachePurge.ts +++ b/src/handlers/strategies/cachePurge.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { mapBucketPathToUrlPath } from '../../util'; +import { mapBucketPathToUrlPath } from '../../utils/path'; import { CACHE } from '../../constants/cache'; import responses from '../../responses'; import { Context } from '../../context'; diff --git a/src/handlers/strategies/directoryListing.ts b/src/handlers/strategies/directoryListing.ts index 40b8186..56c679c 100644 --- a/src/handlers/strategies/directoryListing.ts +++ b/src/handlers/strategies/directoryListing.ts @@ -5,7 +5,7 @@ import { _Object, } from '@aws-sdk/client-s3'; import Handlebars from 'handlebars'; -import { niceBytes } from '../../util'; +import { toReadableBytes } from '../../utils/object'; import { getFile } from './serveFile'; // Imports the Precompiled Handlebars Template @@ -106,7 +106,7 @@ export function renderDirectoryListing( displayNamePaddingRight = ' '.repeat(50 - name!.length); } - const bytes = niceBytes(object.Size!); + const bytes = toReadableBytes(object.Size!); tableElements.push({ href: `${urlPathname}${encodeURIComponent(name ?? '')}`, diff --git a/src/handlers/strategies/serveFile.ts b/src/handlers/strategies/serveFile.ts index 3a20515..8b32382 100644 --- a/src/handlers/strategies/serveFile.ts +++ b/src/handlers/strategies/serveFile.ts @@ -1,4 +1,4 @@ -import { objectHasBody } from '../../util'; +import { objectHasBody } from '../../utils/object'; import { CACHE_HEADERS } from '../../constants/cache'; import responses from '../../responses'; import { R2_RETRY_LIMIT } from '../../constants/limits'; diff --git a/src/utils/cache.ts b/src/utils/cache.ts new file mode 100644 index 0000000..2b187c3 --- /dev/null +++ b/src/utils/cache.ts @@ -0,0 +1,10 @@ +import { Env } from '../env'; + +/** + * @param env Worker env + * @returns True if we want to either cache files or + * directory listings + */ +export function isCacheEnabled(env: Env): boolean { + return env.ENVIRONMENT !== 'e2e-tests'; +} diff --git a/src/utils/object.ts b/src/utils/object.ts new file mode 100644 index 0000000..535afab --- /dev/null +++ b/src/utils/object.ts @@ -0,0 +1,25 @@ +const byteUnits = ['B', 'KB', 'MB', 'GB', 'TB']; + +/** + * Checks whether or not an R2 object or R2ObjectBody has a body + */ +export function objectHasBody( + object: R2Object | R2ObjectBody +): object is R2ObjectBody { + return (object).body !== undefined; +} + +/** + * Converts raw size into human readable bytes + * @returns Something like `4.5 KB` or `8.7 MB` + */ +export function toReadableBytes(bytes: number): string { + let l = 0; + let n = parseInt(bytes.toString(), 10) || 0; + + while (n >= 1000 && ++l) { + n = n / 1000; + } + + return n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + byteUnits[l]; +} diff --git a/src/util.ts b/src/utils/path.ts similarity index 84% rename from src/util.ts rename to src/utils/path.ts index 77128f1..ecf35b5 100644 --- a/src/util.ts +++ b/src/utils/path.ts @@ -4,36 +4,8 @@ import { DOWNLOAD_PATH_PREFIX, REDIRECT_MAP, URL_TO_BUCKET_PATH_MAP, -} from './constants/r2Prefixes'; -import { Env } from './env'; - -const units = ['B', 'KB', 'MB', 'GB', 'TB']; - -/** - * @param env Worker env - * @returns True if we want to either cache files or - * directory listings - */ -export function isCacheEnabled(env: Env): boolean { - return env.ENVIRONMENT !== 'e2e-tests'; -} - -/** - * @param request Request object - * @returns {@link URL} instance if url is valid, a 400 - * response otherwise - */ -export function parseUrl(request: Request): URL | undefined { - let url: URL | undefined; - - try { - url = new URL(request.url); - } catch (e) { - console.error(e); - } - - return url; -} +} from '../constants/r2Prefixes'; +import { Env } from '../env'; /** * Maps a path in a url to the path to the resource @@ -229,31 +201,3 @@ export function isExtensionless(path: string): boolean { export function isDirectoryPath(path: string): boolean { return hasTrailingSlash(path) || isExtensionless(path); } - -/** - * Converts raw size into human readable bytes - * @param bytes Bytes - * @returns Something like `4.5 KB` or `8.7 MB` - */ -export function niceBytes(bytes: number): string { - let l = 0; - let n = parseInt(bytes.toString(), 10) || 0; - - while (n >= 1000 && ++l) { - n = n / 1000; - } - - return n.toFixed(n < 10 && l > 0 ? 1 : 0) + ' ' + units[l]; -} - -/** - * Checks whether or not an R2 object - * or R2ObjectBody has a body - * @param object R2 object - * @returns True if it has a body - */ -export function objectHasBody( - object: R2Object | R2ObjectBody -): object is R2ObjectBody { - return (object).body !== undefined; -} diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..186032d --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,16 @@ +/** + * @param request Request object + * @returns {@link URL} instance if url is valid, a 400 + * response otherwise + */ +export function parseUrl(request: Request): URL | undefined { + let url: URL | undefined; + + try { + url = new URL(request.url); + } catch (e) { + console.error(e); + } + + return url; +} diff --git a/tests/unit/index.test.ts b/tests/unit/index.test.ts index c44bb5f..96970a4 100644 --- a/tests/unit/index.test.ts +++ b/tests/unit/index.test.ts @@ -1 +1,2 @@ -import './util.test'; +import './utils/object.test'; +import './utils/path.test'; diff --git a/tests/unit/utils/object.test.ts b/tests/unit/utils/object.test.ts new file mode 100644 index 0000000..a86a9a4 --- /dev/null +++ b/tests/unit/utils/object.test.ts @@ -0,0 +1,15 @@ +import assert from 'node:assert'; +import { describe, it } from 'node:test'; +import { toReadableBytes } from '../../../src/utils/object'; + +describe('toReadableBytes', () => { + it('converts 10 to `10 B`', () => { + const result = toReadableBytes(10); + assert.strictEqual(result, '10 B'); + }); + + it('converts 1024 to `1.0 KB`', () => { + const result = toReadableBytes(1024); + assert.strictEqual(result, '1.0 KB'); + }); +}); diff --git a/tests/unit/util.test.ts b/tests/unit/utils/path.test.ts similarity index 94% rename from tests/unit/util.test.ts rename to tests/unit/utils/path.test.ts index 0ec3d2c..d2ffabd 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/utils/path.test.ts @@ -1,12 +1,11 @@ import assert from 'node:assert'; import { describe, it } from 'node:test'; import { - isDirectoryPath, - mapBucketPathToUrlPath, mapUrlPathToBucketPath, - niceBytes, -} from '../../src/util'; -import { REDIRECT_MAP } from '../../src/constants/r2Prefixes'; + mapBucketPathToUrlPath, + isDirectoryPath, +} from '../../../src/utils/path'; +import { REDIRECT_MAP } from '../../../src/constants/r2Prefixes'; describe('mapUrlPathToBucketPath', () => { it('expects all items in REDIRECT_MAP to be pathes in the length of 3', () => { @@ -234,15 +233,3 @@ describe('isDirectoryPath', () => { assert.strictEqual(isDirectoryPath('/docs/latest/api'), true); }); }); - -describe('niceBytes', () => { - it('converts 10 to `10 B`', () => { - const result = niceBytes(10); - assert.strictEqual(result, '10 B'); - }); - - it('converts 1024 to `1.0 KB`', () => { - const result = niceBytes(1024); - assert.strictEqual(result, '1.0 KB'); - }); -});