diff options
Diffstat (limited to 'std/node/querystring.ts')
-rw-r--r-- | std/node/querystring.ts | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/std/node/querystring.ts b/std/node/querystring.ts new file mode 100644 index 000000000..a5b2e7f05 --- /dev/null +++ b/std/node/querystring.ts @@ -0,0 +1,70 @@ +interface ParseOptions { + decodeURIComponent?: (string: string) => string; + maxKeys?: number; +} + +export function parse( + str: string, + sep = "&", + eq = "=", + { decodeURIComponent = unescape, maxKeys = 1000 }: ParseOptions = {} +): { [key: string]: string[] | string } { + const entries = str + .split(sep) + .map(entry => entry.split(eq).map(decodeURIComponent)); + const final: { [key: string]: string[] | string } = {}; + + let i = 0; + while (true) { + if ((Object.keys(final).length === maxKeys && !!maxKeys) || !entries[i]) { + break; + } + + const [key, val] = entries[i]; + if (final[key]) { + if (Array.isArray(final[key])) { + (final[key] as string[]).push(val); + } else { + final[key] = [final[key] as string, val]; + } + } else { + final[key] = val; + } + + i++; + } + + return final; +} + +interface StringifyOptions { + encodeURIComponent?: (string: string) => string; +} + +export function stringify( + obj: object, + sep = "&", + eq = "=", + { encodeURIComponent = escape }: StringifyOptions = {} +): string { + const final = []; + + for (const entry of Object.entries(obj)) { + if (Array.isArray(entry[1])) { + for (const val of entry[1]) { + final.push(encodeURIComponent(entry[0]) + eq + encodeURIComponent(val)); + } + } else if (typeof entry[1] !== "object" && entry[1] !== undefined) { + final.push(entry.map(encodeURIComponent).join(eq)); + } else { + final.push(encodeURIComponent(entry[0]) + eq); + } + } + + return final.join(sep); +} + +export const decode = parse; +export const encode = stringify; +export const unescape = decodeURIComponent; +export const escape = encodeURIComponent; |