{"version":3,"file":"TransactionSerializer.cjs","sources":["../../../src/outbox/TransactionSerializer.ts"],"sourcesContent":["import type {\n  OfflineTransaction,\n  SerializedError,\n  SerializedMutation,\n  SerializedOfflineTransaction,\n} from '../types'\nimport type { Collection, PendingMutation } from '@tanstack/db'\n\nexport class TransactionSerializer {\n  private collections: Record<string, Collection<any, any, any, any, any>>\n  private collectionIdToKey: Map<string, string>\n\n  constructor(\n    collections: Record<string, Collection<any, any, any, any, any>>,\n  ) {\n    this.collections = collections\n    // Create reverse lookup from collection.id to registry key\n    this.collectionIdToKey = new Map()\n    for (const [key, collection] of Object.entries(collections)) {\n      this.collectionIdToKey.set(collection.id, key)\n    }\n  }\n\n  serialize(transaction: OfflineTransaction): string {\n    const serialized: SerializedOfflineTransaction = {\n      ...transaction,\n      createdAt: transaction.createdAt.toISOString(),\n      mutations: transaction.mutations.map((mutation) =>\n        this.serializeMutation(mutation),\n      ),\n    }\n    return JSON.stringify(serialized)\n  }\n\n  deserialize(data: string): OfflineTransaction {\n    // Parse without a reviver - let deserializeValue handle dates in mutation data\n    // using the { __type: 'Date' } marker system\n    const parsed: SerializedOfflineTransaction = JSON.parse(data)\n\n    const createdAt = new Date(parsed.createdAt)\n    if (isNaN(createdAt.getTime())) {\n      throw new Error(\n        `Failed to deserialize transaction: invalid createdAt value \"${parsed.createdAt}\"`,\n      )\n    }\n\n    return {\n      ...parsed,\n      createdAt,\n      mutations: parsed.mutations.map((mutationData) =>\n        this.deserializeMutation(mutationData),\n      ),\n    }\n  }\n\n  private serializeMutation(mutation: PendingMutation): SerializedMutation {\n    const registryKey = this.collectionIdToKey.get(mutation.collection.id)\n    if (!registryKey) {\n      throw new Error(\n        `Collection with id ${mutation.collection.id} not found in registry`,\n      )\n    }\n\n    return {\n      globalKey: mutation.globalKey,\n      type: mutation.type,\n      modified: this.serializeValue(mutation.modified),\n      original: this.serializeValue(mutation.original),\n      changes: this.serializeValue(mutation.changes),\n      collectionId: registryKey, // Store registry key instead of collection.id\n    }\n  }\n\n  private deserializeMutation(data: SerializedMutation): PendingMutation {\n    const collection = this.collections[data.collectionId]\n    if (!collection) {\n      throw new Error(`Collection with id ${data.collectionId} not found`)\n    }\n\n    const modified = this.deserializeValue(data.modified)\n\n    // Extract the key from the modified data using the collection's getKey function\n    // This is needed for optimistic state restoration to work correctly\n    const key = modified ? collection.getKeyFromItem(modified) : null\n\n    // Create a partial PendingMutation - we can't fully reconstruct it but\n    // we provide what we can. The executor will need to handle the rest.\n    return {\n      globalKey: data.globalKey,\n      type: data.type as any,\n      modified,\n      original: this.deserializeValue(data.original),\n      changes: this.deserializeValue(data.changes) ?? {},\n      collection,\n      // These fields would need to be reconstructed by the executor\n      mutationId: ``, // Will be regenerated\n      key,\n      metadata: undefined,\n      syncMetadata: {},\n      optimistic: true,\n      createdAt: new Date(),\n      updatedAt: new Date(),\n    } as PendingMutation\n  }\n\n  private serializeValue(value: any): any {\n    if (value === null || value === undefined) {\n      return value\n    }\n\n    if (value instanceof Date) {\n      return { __type: `Date`, value: value.toISOString() }\n    }\n\n    if (typeof value === `object`) {\n      const result: any = Array.isArray(value) ? [] : {}\n      for (const key in value) {\n        if (Object.prototype.hasOwnProperty.call(value, key)) {\n          result[key] = this.serializeValue(value[key])\n        }\n      }\n      return result\n    }\n\n    return value\n  }\n\n  private deserializeValue(value: any): any {\n    if (value === null || value === undefined) {\n      return value\n    }\n\n    if (typeof value === `object` && value.__type === `Date`) {\n      if (value.value === undefined || value.value === null) {\n        throw new Error(`Corrupted Date marker: missing value field`)\n      }\n      const date = new Date(value.value)\n      if (isNaN(date.getTime())) {\n        throw new Error(\n          `Failed to deserialize Date marker: invalid date value \"${value.value}\"`,\n        )\n      }\n      return date\n    }\n\n    if (typeof value === `object`) {\n      const result: any = Array.isArray(value) ? [] : {}\n      for (const key in value) {\n        if (Object.prototype.hasOwnProperty.call(value, key)) {\n          result[key] = this.deserializeValue(value[key])\n        }\n      }\n      return result\n    }\n\n    return value\n  }\n\n  serializeError(error: Error): SerializedError {\n    return {\n      name: error.name,\n      message: error.message,\n      stack: error.stack,\n    }\n  }\n\n  deserializeError(data: SerializedError): Error {\n    const error = new Error(data.message)\n    error.name = data.name\n    error.stack = data.stack\n    return error\n  }\n}\n"],"names":[],"mappings":";;AAQO,MAAM,sBAAsB;AAAA,EAIjC,YACE,aACA;AACA,SAAK,cAAc;AAEnB,SAAK,wCAAwB,IAAA;AAC7B,eAAW,CAAC,KAAK,UAAU,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC3D,WAAK,kBAAkB,IAAI,WAAW,IAAI,GAAG;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,UAAU,aAAyC;AACjD,UAAM,aAA2C;AAAA,MAC/C,GAAG;AAAA,MACH,WAAW,YAAY,UAAU,YAAA;AAAA,MACjC,WAAW,YAAY,UAAU;AAAA,QAAI,CAAC,aACpC,KAAK,kBAAkB,QAAQ;AAAA,MAAA;AAAA,IACjC;AAEF,WAAO,KAAK,UAAU,UAAU;AAAA,EAClC;AAAA,EAEA,YAAY,MAAkC;AAG5C,UAAM,SAAuC,KAAK,MAAM,IAAI;AAE5D,UAAM,YAAY,IAAI,KAAK,OAAO,SAAS;AAC3C,QAAI,MAAM,UAAU,QAAA,CAAS,GAAG;AAC9B,YAAM,IAAI;AAAA,QACR,+DAA+D,OAAO,SAAS;AAAA,MAAA;AAAA,IAEnF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,WAAW,OAAO,UAAU;AAAA,QAAI,CAAC,iBAC/B,KAAK,oBAAoB,YAAY;AAAA,MAAA;AAAA,IACvC;AAAA,EAEJ;AAAA,EAEQ,kBAAkB,UAA+C;AACvE,UAAM,cAAc,KAAK,kBAAkB,IAAI,SAAS,WAAW,EAAE;AACrE,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR,sBAAsB,SAAS,WAAW,EAAE;AAAA,MAAA;AAAA,IAEhD;AAEA,WAAO;AAAA,MACL,WAAW,SAAS;AAAA,MACpB,MAAM,SAAS;AAAA,MACf,UAAU,KAAK,eAAe,SAAS,QAAQ;AAAA,MAC/C,UAAU,KAAK,eAAe,SAAS,QAAQ;AAAA,MAC/C,SAAS,KAAK,eAAe,SAAS,OAAO;AAAA,MAC7C,cAAc;AAAA;AAAA,IAAA;AAAA,EAElB;AAAA,EAEQ,oBAAoB,MAA2C;AACrE,UAAM,aAAa,KAAK,YAAY,KAAK,YAAY;AACrD,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,sBAAsB,KAAK,YAAY,YAAY;AAAA,IACrE;AAEA,UAAM,WAAW,KAAK,iBAAiB,KAAK,QAAQ;AAIpD,UAAM,MAAM,WAAW,WAAW,eAAe,QAAQ,IAAI;AAI7D,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK,iBAAiB,KAAK,QAAQ;AAAA,MAC7C,SAAS,KAAK,iBAAiB,KAAK,OAAO,KAAK,CAAA;AAAA,MAChD;AAAA;AAAA,MAEA,YAAY;AAAA;AAAA,MACZ;AAAA,MACA,UAAU;AAAA,MACV,cAAc,CAAA;AAAA,MACd,YAAY;AAAA,MACZ,+BAAe,KAAA;AAAA,MACf,+BAAe,KAAA;AAAA,IAAK;AAAA,EAExB;AAAA,EAEQ,eAAe,OAAiB;AACtC,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AAEA,QAAI,iBAAiB,MAAM;AACzB,aAAO,EAAE,QAAQ,QAAQ,OAAO,MAAM,cAAY;AAAA,IACpD;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,SAAc,MAAM,QAAQ,KAAK,IAAI,CAAA,IAAK,CAAA;AAChD,iBAAW,OAAO,OAAO;AACvB,YAAI,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,GAAG;AACpD,iBAAO,GAAG,IAAI,KAAK,eAAe,MAAM,GAAG,CAAC;AAAA,QAC9C;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,OAAiB;AACxC,QAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,UAAU,YAAY,MAAM,WAAW,QAAQ;AACxD,UAAI,MAAM,UAAU,UAAa,MAAM,UAAU,MAAM;AACrD,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAC9D;AACA,YAAM,OAAO,IAAI,KAAK,MAAM,KAAK;AACjC,UAAI,MAAM,KAAK,QAAA,CAAS,GAAG;AACzB,cAAM,IAAI;AAAA,UACR,0DAA0D,MAAM,KAAK;AAAA,QAAA;AAAA,MAEzE;AACA,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,SAAc,MAAM,QAAQ,KAAK,IAAI,CAAA,IAAK,CAAA;AAChD,iBAAW,OAAO,OAAO;AACvB,YAAI,OAAO,UAAU,eAAe,KAAK,OAAO,GAAG,GAAG;AACpD,iBAAO,GAAG,IAAI,KAAK,iBAAiB,MAAM,GAAG,CAAC;AAAA,QAChD;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,OAA+B;AAC5C,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,OAAO,MAAM;AAAA,IAAA;AAAA,EAEjB;AAAA,EAEA,iBAAiB,MAA8B;AAC7C,UAAM,QAAQ,IAAI,MAAM,KAAK,OAAO;AACpC,UAAM,OAAO,KAAK;AAClB,UAAM,QAAQ,KAAK;AACnB,WAAO;AAAA,EACT;AACF;;"}