feat: enhance configuration handling and add type definitions for query and URL serializers
This commit is contained in:
@@ -4,28 +4,32 @@ import { deepClone } from '@/shared/helpers/deep-clone'
|
||||
import type {
|
||||
FLuentUrlPlainObject,
|
||||
FluentUrlConfig,
|
||||
QuerySerializer,
|
||||
NormalizeOptionsArgs,
|
||||
PlainObjectConstraint,
|
||||
} from '@/shared/types'
|
||||
|
||||
export function normalizeConfig(
|
||||
config?: Partial<FluentUrlConfig>,
|
||||
): FluentUrlConfig {
|
||||
export function normalizeConfig<
|
||||
PQO extends PlainObjectConstraint,
|
||||
SQO extends PlainObjectConstraint,
|
||||
>(config?: Partial<FluentUrlConfig<PQO, SQO>>): FluentUrlConfig<PQO, SQO> {
|
||||
return {
|
||||
parseQuery: config?.parseQuery ?? parseQuery,
|
||||
parseQueryOptions: config?.parseQueryOptions,
|
||||
stringifyQuery: config?.stringifyQuery ?? stringifyQuery,
|
||||
stringifyQueryOptions: config?.stringifyQueryOptions,
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeOptions(args: {
|
||||
urlOptions?: Partial<FLuentUrlPlainObject> | string
|
||||
parseQuery: QuerySerializer['parseQuery']
|
||||
}): FLuentUrlPlainObject {
|
||||
const { urlOptions: urlOrOptions, parseQuery } = args
|
||||
|
||||
export function normalizeOptions<T extends PlainObjectConstraint>({
|
||||
urlOrOptions,
|
||||
parseQuery,
|
||||
parseQueryOptions,
|
||||
}: NormalizeOptionsArgs<T>): FLuentUrlPlainObject {
|
||||
if (typeof urlOrOptions === 'string') {
|
||||
return parseUrl({
|
||||
str: urlOrOptions,
|
||||
parseQuery: parseQuery,
|
||||
parseQuery,
|
||||
parseQueryOptions,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -39,13 +43,18 @@ export function normalizeOptions(args: {
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeConfig(
|
||||
current: FluentUrlConfig,
|
||||
merge?: Partial<FluentUrlConfig>,
|
||||
): FluentUrlConfig {
|
||||
export function mergeConfig<
|
||||
PQO extends PlainObjectConstraint,
|
||||
SQO extends PlainObjectConstraint,
|
||||
>(
|
||||
current: FluentUrlConfig<PQO, SQO>,
|
||||
merge?: Partial<FluentUrlConfig<PQO, SQO>>,
|
||||
): FluentUrlConfig<PQO, SQO> {
|
||||
return {
|
||||
parseQuery: merge?.parseQuery ?? current.parseQuery,
|
||||
parseQueryOptions: merge?.parseQueryOptions,
|
||||
stringifyQuery: merge?.stringifyQuery ?? current.stringifyQuery,
|
||||
stringifyQueryOptions: merge?.stringifyQueryOptions,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,17 @@ import { deepClone } from '@/shared/helpers/deep-clone'
|
||||
import type {
|
||||
FLuentUrlPlainObject,
|
||||
FluentUrlConfig,
|
||||
ParseQueryOptions,
|
||||
PlainObjectConstraint,
|
||||
QueriesPlainObject,
|
||||
StringifyQueryOptions,
|
||||
} from '@/shared/types'
|
||||
|
||||
export class FluentUrl {
|
||||
private readonly config: FluentUrlConfig
|
||||
export class FluentUrl<
|
||||
PQO extends PlainObjectConstraint = ParseQueryOptions,
|
||||
SQO extends PlainObjectConstraint = StringifyQueryOptions,
|
||||
> {
|
||||
private readonly config: FluentUrlConfig<PQO, SQO>
|
||||
private readonly protocol?: string
|
||||
private readonly hostname?: string
|
||||
private readonly paths: string[]
|
||||
@@ -23,14 +29,15 @@ export class FluentUrl {
|
||||
|
||||
constructor(
|
||||
urlOrOptions?: Partial<FLuentUrlPlainObject> | string,
|
||||
config?: Partial<FluentUrlConfig>,
|
||||
config?: Partial<FluentUrlConfig<PQO, SQO>>,
|
||||
) {
|
||||
this.config = normalizeConfig(config)
|
||||
|
||||
const { protocol, hostname, paths, port, fragment, queries } =
|
||||
normalizeOptions({
|
||||
urlOptions: urlOrOptions,
|
||||
urlOrOptions,
|
||||
parseQuery: this.config.parseQuery,
|
||||
parseQueryOptions: this.config.parseQueryOptions,
|
||||
})
|
||||
|
||||
this.protocol = protocol
|
||||
@@ -76,8 +83,8 @@ export class FluentUrl {
|
||||
|
||||
public clone(
|
||||
options?: Partial<FLuentUrlPlainObject>,
|
||||
config?: Partial<FluentUrlConfig>,
|
||||
): FluentUrl {
|
||||
config?: Partial<FluentUrlConfig<PQO, SQO>>,
|
||||
): FluentUrl<PQO, SQO> {
|
||||
return new FluentUrl(
|
||||
mergeOptions(
|
||||
{
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
import type { QuerySerializer } from '@/shared/types'
|
||||
import type {
|
||||
ParseQuery,
|
||||
PlainObjectConstraint,
|
||||
StringifyQuery,
|
||||
} from '@/shared/types'
|
||||
|
||||
export const parseQuery: QuerySerializer['parseQuery'] = () => {
|
||||
export function parseQuery<T extends PlainObjectConstraint>(): ReturnType<
|
||||
ParseQuery<T>
|
||||
> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
export const stringifyQuery: QuerySerializer['stringifyQuery'] = () => {
|
||||
export function stringifyQuery<T extends PlainObjectConstraint>(): ReturnType<
|
||||
StringifyQuery<T>
|
||||
> {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { FLuentUrlPlainObject, UrlSerializer } from '@/shared/types'
|
||||
import type {
|
||||
FLuentUrlPlainObject,
|
||||
ParseUrlArgs,
|
||||
PlainObjectConstraint,
|
||||
StringifyUrlArgs,
|
||||
} from '@/shared/types'
|
||||
|
||||
const URLTypesObj = {
|
||||
absolute: 'absolute',
|
||||
@@ -11,7 +16,11 @@ type URLTypes = (typeof URLTypesObj)[keyof typeof URLTypesObj]
|
||||
const defaultProtocol = 'https'
|
||||
const defaultHost = 'example.com'
|
||||
|
||||
export const parseUrl: UrlSerializer['parseUrl'] = ({ str, parseQuery }) => {
|
||||
export function parseUrl<T extends PlainObjectConstraint>({
|
||||
str,
|
||||
parseQuery,
|
||||
parseQueryOptions,
|
||||
}: ParseUrlArgs<T>): FLuentUrlPlainObject {
|
||||
const urlString = str.trim()
|
||||
|
||||
const urlType: URLTypes = urlString.startsWith('//')
|
||||
@@ -64,11 +73,15 @@ export const parseUrl: UrlSerializer['parseUrl'] = ({ str, parseQuery }) => {
|
||||
url.hash !== '' ? url.hash.replace('#', '') : undefined
|
||||
|
||||
urlPlainObject.queries =
|
||||
url.search !== '' ? parseQuery(url.search) : Object.create(null)
|
||||
url.search !== ''
|
||||
? parseQuery(url.search, parseQueryOptions)
|
||||
: Object.create(null)
|
||||
|
||||
return urlPlainObject
|
||||
}
|
||||
|
||||
export const stringifyUrl: UrlSerializer['stringifyUrl'] = (_args) => {
|
||||
export function stringifyUrl<T extends PlainObjectConstraint>(
|
||||
_args: StringifyUrlArgs<T>,
|
||||
): string {
|
||||
throw new Error('Not implemented')
|
||||
}
|
||||
|
||||
@@ -9,23 +9,50 @@ export interface FLuentUrlPlainObject {
|
||||
queries: QueriesPlainObject
|
||||
}
|
||||
|
||||
export interface QuerySerializer {
|
||||
parseQuery: (str: string) => QueriesPlainObject
|
||||
stringifyQuery: (obj: QueriesPlainObject) => string
|
||||
export type PlainObjectConstraint = Record<string, any>
|
||||
|
||||
export interface ParseQueryOptions extends PlainObjectConstraint {
|
||||
[k: string]: any
|
||||
}
|
||||
|
||||
export interface UrlSerializer {
|
||||
parseUrl: (args: {
|
||||
str: string
|
||||
parseQuery: QuerySerializer['parseQuery']
|
||||
}) => FLuentUrlPlainObject
|
||||
stringifyUrl: (args: {
|
||||
obj: FLuentUrlPlainObject
|
||||
stringifyQuery: QuerySerializer['stringifyQuery']
|
||||
}) => string
|
||||
export type ParseQuery<T extends PlainObjectConstraint> = (
|
||||
str: string,
|
||||
options?: T,
|
||||
) => QueriesPlainObject
|
||||
|
||||
export interface StringifyQueryOptions extends PlainObjectConstraint {
|
||||
[k: string]: any
|
||||
}
|
||||
|
||||
export interface FluentUrlConfig {
|
||||
parseQuery: QuerySerializer['parseQuery']
|
||||
stringifyQuery: QuerySerializer['stringifyQuery']
|
||||
export type StringifyQuery<T extends PlainObjectConstraint> = (
|
||||
obj: QueriesPlainObject,
|
||||
options?: T,
|
||||
) => string
|
||||
|
||||
export interface ParseUrlArgs<T extends PlainObjectConstraint> {
|
||||
str: string
|
||||
parseQuery: ParseQuery<T>
|
||||
parseQueryOptions?: T
|
||||
}
|
||||
|
||||
export interface StringifyUrlArgs<T extends PlainObjectConstraint> {
|
||||
obj: FLuentUrlPlainObject
|
||||
stringifyQuery: StringifyQuery<T>
|
||||
stringifyQueryOptions?: T
|
||||
}
|
||||
|
||||
export interface FluentUrlConfig<
|
||||
PQO extends PlainObjectConstraint,
|
||||
SQO extends PlainObjectConstraint,
|
||||
> {
|
||||
parseQuery: ParseQuery<PQO>
|
||||
parseQueryOptions?: PQO
|
||||
stringifyQuery: StringifyQuery<SQO>
|
||||
stringifyQueryOptions?: SQO
|
||||
}
|
||||
|
||||
export interface NormalizeOptionsArgs<T extends PlainObjectConstraint> {
|
||||
urlOrOptions?: Partial<FLuentUrlPlainObject> | string
|
||||
parseQuery: ParseQuery<T>
|
||||
parseQueryOptions?: T
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user