Skip to content

Commit

Permalink
Merge pull request #2 from OtterJS/fix/type-is-types
Browse files Browse the repository at this point in the history
fix(type-is): type declaration of `typeIs` not accepting Request/Response-like objects
  • Loading branch information
Lordfirespeed authored Aug 15, 2024
2 parents b396a99 + ba8a145 commit e4bd387
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changeset/fresh-hairs-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@otterhttp/content-type": minor
"@otterhttp/type-is": minor
---

Fix type declaration of `typeIs` not accepting Request/Response-like objects
13 changes: 7 additions & 6 deletions packages/content-type/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'node:http'

type Request = { headers: IncomingHttpHeaders }
type Response = { getHeader: <HeaderName extends string>(name: HeaderName) => OutgoingHttpHeaders[HeaderName] }
export type TypeParseableObject = Request | Response
export type TypeParseable = string | TypeParseableObject

/**
* RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1
Expand Down Expand Up @@ -55,16 +57,15 @@ function qstring(val: unknown) {
return `"${str.replace(QUOTE_REGEXP, '\\$1')}"`
}

function getContentType(obj: Request | Response) {
function getContentType(obj: TypeParseableObject) {
let header: number | string | string[] | undefined

if ('getHeader' in obj && typeof obj.getHeader === 'function') {
// res-like
header = obj.getHeader('content-type')
} else if ('headers' in obj && typeof obj.headers === 'object') {
// req-like
const h = obj.headers
header = h?.['content-type']
header = obj.headers['content-type']
}

if (typeof header !== 'string') {
Expand Down Expand Up @@ -115,11 +116,11 @@ export function format(obj: { type: string; parameters?: Record<string, unknown>
/**
* Parse media type to object.
*/
export function parse(string: string | Request | Response): ContentType {
if (!string) throw new TypeError('argument string is required')
export function parse(value: TypeParseable): ContentType {
if (!value) throw new TypeError('argument string is required')

// support req/res-like objects as argument
const header = typeof string === 'object' ? getContentType(string) : string
const header = typeof value === 'object' ? getContentType(value) : value

if (typeof header !== 'string') throw new TypeError('argument string is required to be a string')

Expand Down
17 changes: 9 additions & 8 deletions packages/type-is/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as typer from '@otterhttp/content-type'
import { type TypeParseable, format as formatType, parse as parseType } from '@otterhttp/content-type'
import mime from 'mime'

function normalizeType(value: string) {
function normalizeType(value: TypeParseable) {
// parse the type
const type = typer.parse(value)
const type = parseType(value)
type.parameters = {}
// reformat it
return typer.format(type)
return formatType(type)
}

function tryNormalizeType(value: string | undefined) {
function tryNormalizeType(value: TypeParseable | undefined) {
if (!value) return null

try {
Expand All @@ -22,10 +22,11 @@ function tryNormalizeType(value: string | undefined) {
function mimeMatch(expected: string | null, actual: string | null): boolean {
// invalid type
if (expected == null) return false
if (actual == null) return false

// split types
const actualParts = (actual as string).split('/')
const expectedParts = (expected as string).split('/')
const actualParts = actual.split('/')
const expectedParts = expected.split('/')

// invalid format
if (actualParts.length !== 2 || expectedParts.length !== 2) return false
Expand Down Expand Up @@ -68,7 +69,7 @@ function normalize(type: string): string | null {
* a special shortcut like `multipart` or `urlencoded`,
* or a mime type.
*/
export const typeIs = (value: string | undefined, types?: readonly string[]) => {
export function typeIs(value: TypeParseable | undefined, types?: readonly string[]) {
let i: number
// remove parameters and normalize
const val = tryNormalizeType(value)
Expand Down

0 comments on commit e4bd387

Please sign in to comment.