{"version":3,"file":"serializer.cjs","sources":["../../src/serializer.ts"],"sourcesContent":["import { isPlainObject } from '@tanstack/router-core'\nimport type { StartSerializer } from '@tanstack/router-core'\n\nexport const startSerializer: StartSerializer = {\n  stringify: (value: any) =>\n    JSON.stringify(value, function replacer(key, val) {\n      const ogVal = this[key]\n      const serializer = serializers.find((t) => t.stringifyCondition(ogVal))\n\n      if (serializer) {\n        return serializer.stringify(ogVal)\n      }\n\n      return val\n    }),\n  parse: (value: string) =>\n    JSON.parse(value, function parser(key, val) {\n      const ogVal = this[key]\n      if (isPlainObject(ogVal)) {\n        const serializer = serializers.find((t) => t.parseCondition(ogVal))\n\n        if (serializer) {\n          return serializer.parse(ogVal)\n        }\n      }\n\n      return val\n    }),\n  encode: (value: any) => {\n    // When encoding, dive first\n    if (Array.isArray(value)) {\n      return value.map((v) => startSerializer.encode(v))\n    }\n\n    if (isPlainObject(value)) {\n      return Object.fromEntries(\n        Object.entries(value).map(([key, v]) => [\n          key,\n          startSerializer.encode(v),\n        ]),\n      )\n    }\n\n    const serializer = serializers.find((t) => t.stringifyCondition(value))\n    if (serializer) {\n      return serializer.stringify(value)\n    }\n\n    return value\n  },\n  decode: (value: any) => {\n    // Attempt transform first\n    if (isPlainObject(value)) {\n      const serializer = serializers.find((t) => t.parseCondition(value))\n      if (serializer) {\n        return serializer.parse(value)\n      }\n    }\n\n    if (Array.isArray(value)) {\n      return value.map((v) => startSerializer.decode(v))\n    }\n\n    if (isPlainObject(value)) {\n      return Object.fromEntries(\n        Object.entries(value).map(([key, v]) => [\n          key,\n          startSerializer.decode(v),\n        ]),\n      )\n    }\n\n    return value\n  },\n}\n\nconst createSerializer = <TKey extends string, TInput, TSerialized>(\n  key: TKey,\n  check: (value: any) => value is TInput,\n  toValue: (value: TInput) => TSerialized,\n  fromValue: (value: TSerialized) => TInput,\n) => ({\n  key,\n  stringifyCondition: check,\n  stringify: (value: any) => ({ [`$${key}`]: toValue(value) }),\n  parseCondition: (value: any) => Object.hasOwn(value, `$${key}`),\n  parse: (value: any) => fromValue(value[`$${key}`]),\n})\n\n// Keep these ordered by predicted frequency\n// Make sure to keep DefaultSerializable in sync with these serializers\n// Also, make sure that they are unit tested in serializer.test.tsx\nconst serializers = [\n  createSerializer(\n    // Key\n    'undefined',\n    // Check\n    (v): v is undefined => v === undefined,\n    // To\n    () => 0,\n    // From\n    () => undefined,\n  ),\n  createSerializer(\n    // Key\n    'date',\n    // Check\n    (v): v is Date => v instanceof Date,\n    // To\n    (v) => v.toISOString(),\n    // From\n    (v) => new Date(v),\n  ),\n  createSerializer(\n    // Key\n    'error',\n    // Check\n    (v): v is Error => v instanceof Error,\n    // To\n    (v) => ({\n      ...v,\n      message: v.message,\n      stack: process.env.NODE_ENV === 'development' ? v.stack : undefined,\n      cause: v.cause,\n    }),\n    // From\n    (v) => Object.assign(new Error(v.message), v),\n  ),\n  createSerializer(\n    // Key\n    'formData',\n    // Check\n    (v): v is FormData => v instanceof FormData,\n    // To\n    (v) => {\n      const entries: Record<\n        string,\n        Array<FormDataEntryValue> | FormDataEntryValue\n      > = {}\n      v.forEach((value, key) => {\n        const entry = entries[key]\n        if (entry !== undefined) {\n          if (Array.isArray(entry)) {\n            entry.push(value)\n          } else {\n            entries[key] = [entry, value]\n          }\n        } else {\n          entries[key] = value\n        }\n      })\n      return entries\n    },\n    // From\n    (v) => {\n      const formData = new FormData()\n      Object.entries(v).forEach(([key, value]) => {\n        if (Array.isArray(value)) {\n          value.forEach((val) => formData.append(key, val))\n        } else {\n          formData.append(key, value)\n        }\n      })\n      return formData\n    },\n  ),\n  createSerializer(\n    // Key\n    'bigint',\n    // Check\n    (v): v is bigint => typeof v === 'bigint',\n    // To\n    (v) => v.toString(),\n    // From\n    (v) => BigInt(v),\n  ),\n] as const\n"],"names":["isPlainObject"],"mappings":"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"}