88 lines
2.0 KiB
TypeScript
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')
|
|
}
|