UNPKG

@tanstack/offline-transactions

Version:

Offline-first transaction capabilities for TanStack DB

140 lines (139 loc) 4.16 kB
class TransactionSerializer { constructor(collections) { this.collections = collections; this.collectionIdToKey = /* @__PURE__ */ new Map(); for (const [key, collection] of Object.entries(collections)) { this.collectionIdToKey.set(collection.id, key); } } serialize(transaction) { const serialized = { ...transaction, createdAt: transaction.createdAt.toISOString(), mutations: transaction.mutations.map( (mutation) => this.serializeMutation(mutation) ) }; return JSON.stringify(serialized); } deserialize(data) { const parsed = JSON.parse(data); const createdAt = new Date(parsed.createdAt); if (isNaN(createdAt.getTime())) { throw new Error( `Failed to deserialize transaction: invalid createdAt value "${parsed.createdAt}"` ); } return { ...parsed, createdAt, mutations: parsed.mutations.map( (mutationData) => this.deserializeMutation(mutationData) ) }; } serializeMutation(mutation) { const registryKey = this.collectionIdToKey.get(mutation.collection.id); if (!registryKey) { throw new Error( `Collection with id ${mutation.collection.id} not found in registry` ); } return { globalKey: mutation.globalKey, type: mutation.type, modified: this.serializeValue(mutation.modified), original: this.serializeValue(mutation.original), changes: this.serializeValue(mutation.changes), collectionId: registryKey // Store registry key instead of collection.id }; } deserializeMutation(data) { const collection = this.collections[data.collectionId]; if (!collection) { throw new Error(`Collection with id ${data.collectionId} not found`); } const modified = this.deserializeValue(data.modified); const key = modified ? collection.getKeyFromItem(modified) : null; return { globalKey: data.globalKey, type: data.type, modified, original: this.deserializeValue(data.original), changes: this.deserializeValue(data.changes) ?? {}, collection, // These fields would need to be reconstructed by the executor mutationId: ``, // Will be regenerated key, metadata: void 0, syncMetadata: {}, optimistic: true, createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() }; } serializeValue(value) { if (value === null || value === void 0) { return value; } if (value instanceof Date) { return { __type: `Date`, value: value.toISOString() }; } if (typeof value === `object`) { const result = Array.isArray(value) ? [] : {}; for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { result[key] = this.serializeValue(value[key]); } } return result; } return value; } deserializeValue(value) { if (value === null || value === void 0) { return value; } if (typeof value === `object` && value.__type === `Date`) { if (value.value === void 0 || value.value === null) { throw new Error(`Corrupted Date marker: missing value field`); } const date = new Date(value.value); if (isNaN(date.getTime())) { throw new Error( `Failed to deserialize Date marker: invalid date value "${value.value}"` ); } return date; } if (typeof value === `object`) { const result = Array.isArray(value) ? [] : {}; for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { result[key] = this.deserializeValue(value[key]); } } return result; } return value; } serializeError(error) { return { name: error.name, message: error.message, stack: error.stack }; } deserializeError(data) { const error = new Error(data.message); error.name = data.name; error.stack = data.stack; return error; } } export { TransactionSerializer }; //# sourceMappingURL=TransactionSerializer.js.map