Skip to content

Commit

Permalink
feat: Add server-side parser utility
Browse files Browse the repository at this point in the history
Thanks to @r1chm8 for the idea in #348.
  • Loading branch information
franky47 committed Sep 11, 2023
1 parent d46f4cd commit e225975
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
6 changes: 2 additions & 4 deletions src/app/demos/server-side-parsing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { counterParser } from './parser'

type PageProps = {
searchParams: {
counter?: string
counter?: string | string[]
}
}

export default function ServerSideParsingDemo({ searchParams }: PageProps) {
const counter =
counterParser.parse(searchParams.counter ?? '') ??
counterParser.defaultValue
const counter = counterParser.parseServerSide(searchParams.counter)
console.log('Server side counter: %d', counter)
return (
<>
Expand Down
50 changes: 49 additions & 1 deletion src/lib/parsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,39 @@ export type ParserBuilder<T> = Parser<T> &
withDefault(defaultValue: NonNullable<T>): Parser<T> &
Options & {
readonly defaultValue: NonNullable<T>

/**
* Use the parser in Server Components
*
* `parse` is intended to be used only by the hook, but you can use this
* method to hydrate query values on server-side rendered pages.
* See the `server-side-parsing` demo for an example.
*
* Note that when multiple queries are presented to the parser
* (eg: `/?a=1&a=2`), only the **first** will be parsed, to mimic the
* behaviour of URLSearchParams:
* https://url.spec.whatwg.org/#dom-urlsearchparams-get
*
* @param value as coming from page props
*/
parseServerSide(value: string | string[] | undefined): NonNullable<T>
}

/**
* Use the parser in Server Components
*
* `parse` is intended to be used only by the hook, but you can use this
* method to hydrate query values on server-side rendered pages.
* See the `server-side-parsing` demo for an example.
*
* Note that when multiple queries are presented to the parser
* (eg: `/?a=1&a=2`), only the **first** will be parsed, to mimic the
* behaviour of URLSearchParams:
* https://url.spec.whatwg.org/#dom-urlsearchparams-get
*
* @param value as coming from page props
*/
parseServerSide(value: string | string[] | undefined): T | null
}

/**
Expand All @@ -40,10 +72,26 @@ export type ParserBuilder<T> = Parser<T> &
export function createParser<T>(parser: Parser<T>): ParserBuilder<T> {
return {
...parser,
parseServerSide(value = '') {
let str = ''
if (Array.isArray(value)) {
// Follow the spec:
// https://url.spec.whatwg.org/#dom-urlsearchparams-get
str = value[0]
}
if (typeof value === 'string') {
str = value
}
return this.parse(str)
},
withDefault(defaultValue) {
const nullableParse = this.parseServerSide.bind(this)
return {
...this,
defaultValue
defaultValue,
parseServerSide(value = '') {
return nullableParse(value) ?? defaultValue
}
}
},
withOptions(options: Options) {
Expand Down

0 comments on commit e225975

Please sign in to comment.