Files
fluent-url/lib/core/serializer/url-serializer.ts

88 lines
2.0 KiB
TypeScript

import type {
FLuentUrlPlainObject,
ParseUrlArgs,
PlainObjectConstraint,
StringifyUrlArgs,
} from '@/shared/types'
const URLTypesObj = {
absolute: 'absolute',
relative: 'relative',
protocolRelative: 'protocol-relative',
} as const
type URLTypes = (typeof URLTypesObj)[keyof typeof URLTypesObj]
const defaultProtocol = 'https'
const defaultHost = 'example.com'
export function parseUrl<T extends PlainObjectConstraint>({
str,
parseQuery,
parseQueryOptions,
}: ParseUrlArgs<T>): FLuentUrlPlainObject {
const urlString = str.trim()
const urlType: URLTypes = urlString.startsWith('//')
? URLTypesObj.protocolRelative
: urlString.startsWith('/')
? URLTypesObj.relative
: URLTypesObj.absolute
let newUrlString = urlString
if (urlType === URLTypesObj.protocolRelative) {
newUrlString = `${defaultProtocol}:${newUrlString}`
}
if (urlType === URLTypesObj.relative) {
newUrlString = `${defaultProtocol}://${defaultHost}${newUrlString}`
}
let url: URL
try {
url = new URL(newUrlString)
} catch {
throw new Error('Invalid URL')
}
const urlPlainObject: FLuentUrlPlainObject = {
paths: [],
queries: {},
}
if (urlType === URLTypesObj.absolute) {
urlPlainObject.protocol =
url.protocol !== '' ? url.protocol.replace(':', '') : undefined
}
if (
urlType === URLTypesObj.absolute ||
urlType === URLTypesObj.protocolRelative
) {
urlPlainObject.hostname = url.hostname || undefined
}
urlPlainObject.paths =
url.pathname === '/' ? [] : url.pathname.split('/').filter((p) => p !== '')
urlPlainObject.port = url.port !== '' ? Number(url.port) : undefined
urlPlainObject.fragment =
url.hash !== '' ? url.hash.replace('#', '') : undefined
urlPlainObject.queries =
url.search !== ''
? parseQuery(url.search, parseQueryOptions)
: Object.create(null)
return urlPlainObject
}
export function stringifyUrl<T extends PlainObjectConstraint>(
_args: StringifyUrlArgs<T>,
): string {
throw new Error('Not implemented')
}