@coinbase/cdp-sdk
Version:
SDK for interacting with the Coinbase Developer Platform Wallet API
88 lines (77 loc) • 3.25 kB
text/typescript
type ArrayFormat = "indices" | "repeat" | "comma";
interface QueryStringOptions {
arrayFormat?: ArrayFormat;
encode?: boolean;
}
const defaultQsOptions: Required<QueryStringOptions> = {
arrayFormat: "indices",
encode: true,
} as const;
function encodeValue(value: unknown, shouldEncode: boolean): string {
if (value === undefined) {
return "";
}
if (value === null) {
return "";
}
const stringValue = String(value);
return shouldEncode ? encodeURIComponent(stringValue) : stringValue;
}
function stringifyObject(obj: Record<string, unknown>, prefix = "", options: Required<QueryStringOptions>): string[] {
const parts: string[] = [];
for (const [key, value] of Object.entries(obj)) {
const fullKey = prefix ? `${prefix}[${key}]` : key;
if (value === undefined) {
continue;
}
if (Array.isArray(value)) {
if (value.length === 0) {
continue;
}
const effectiveFormat = options.arrayFormat;
if (effectiveFormat === "comma") {
const encodedKey = options.encode ? encodeURIComponent(fullKey) : fullKey;
const encodedValues = value
.filter((item) => item !== undefined && item !== null)
.map((item) => encodeValue(item, options.encode));
if (encodedValues.length > 0) {
parts.push(`${encodedKey}=${encodedValues.join(",")}`);
}
} else {
for (let i = 0; i < value.length; i++) {
const item = value[i];
if (item === undefined) {
continue;
}
if (typeof item === "object" && !Array.isArray(item) && item !== null) {
const arrayKey = effectiveFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
parts.push(...stringifyObject(item as Record<string, unknown>, arrayKey, options));
} else {
const arrayKey = effectiveFormat === "indices" ? `${fullKey}[${i}]` : fullKey;
const encodedKey = options.encode ? encodeURIComponent(arrayKey) : arrayKey;
parts.push(`${encodedKey}=${encodeValue(item, options.encode)}`);
}
}
}
} else if (typeof value === "object" && value !== null) {
if (Object.keys(value as Record<string, unknown>).length === 0) {
continue;
}
parts.push(...stringifyObject(value as Record<string, unknown>, fullKey, options));
} else {
const encodedKey = options.encode ? encodeURIComponent(fullKey) : fullKey;
parts.push(`${encodedKey}=${encodeValue(value, options.encode)}`);
}
}
return parts;
}
export function toQueryString(obj: unknown, options?: QueryStringOptions): string {
if (obj == null || typeof obj !== "object") {
return "";
}
const parts = stringifyObject(obj as Record<string, unknown>, "", {
...defaultQsOptions,
...options,
});
return parts.join("&");
}