summaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
Diffstat (limited to 'std')
-rw-r--r--std/node/README.md2
-rw-r--r--std/node/module.ts5
-rw-r--r--std/node/querystring.ts70
-rw-r--r--std/node/querystring_test.ts30
4 files changed, 106 insertions, 1 deletions
diff --git a/std/node/README.md b/std/node/README.md
index 37084ed25..1c561be4f 100644
--- a/std/node/README.md
+++ b/std/node/README.md
@@ -27,7 +27,7 @@ deno standard library as it's a compatiblity module.
- [x] path
- [ ] perf_hooks
- [x] process _partly_
-- [ ] querystring
+- [x] querystring
- [ ] readline
- [ ] repl
- [ ] stream
diff --git a/std/node/module.ts b/std/node/module.ts
index 3520d804b..01f1f0477 100644
--- a/std/node/module.ts
+++ b/std/node/module.ts
@@ -27,6 +27,7 @@ import * as nodePath from "./path.ts";
import * as nodeTimers from "./timers.ts";
import * as nodeOs from "./os.ts";
import * as nodeEvents from "./events.ts";
+import * as nodeQueryString from "./querystring.ts";
import * as path from "../path/mod.ts";
import { assert } from "../testing/asserts.ts";
@@ -593,6 +594,10 @@ nativeModulePolyfill.set("os", createNativeModule("os", nodeOs));
nativeModulePolyfill.set("path", createNativeModule("path", nodePath));
nativeModulePolyfill.set("timers", createNativeModule("timers", nodeTimers));
nativeModulePolyfill.set("util", createNativeModule("util", nodeUtil));
+nativeModulePolyfill.set(
+ "querystring",
+ createNativeModule("querystring", nodeQueryString)
+);
function loadNativeModule(
_filename: string,
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;
diff --git a/std/node/querystring_test.ts b/std/node/querystring_test.ts
new file mode 100644
index 000000000..d8cb1ec35
--- /dev/null
+++ b/std/node/querystring_test.ts
@@ -0,0 +1,30 @@
+const { test } = Deno;
+import { assertEquals } from "../testing/asserts.ts";
+import { stringify, parse } from "./querystring.ts";
+
+test({
+ name: "stringify",
+ fn() {
+ assertEquals(
+ stringify({
+ a: "hello",
+ b: 5,
+ c: true,
+ d: ["foo", "bar"]
+ }),
+ "a=hello&b=5&c=true&d=foo&d=bar"
+ );
+ }
+});
+
+test({
+ name: "parse",
+ fn() {
+ assertEquals(parse("a=hello&b=5&c=true&d=foo&d=bar"), {
+ a: "hello",
+ b: "5",
+ c: "true",
+ d: ["foo", "bar"]
+ });
+ }
+});