UNPKG

@tanstack/offline-transactions

Version:

Offline-first transaction capabilities for TanStack DB

169 lines (168 loc) 5.23 kB
function setDataProperty(object, key, value) { if (key !== `__proto__`) object[key] = value; else Object.defineProperty(object, key, { value, enumerable: true, configurable: true, writable: true }); } 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, valueEncoding: 2, createdAt: transaction.createdAt.toISOString(), mutations: transaction.mutations.map( (mutation) => this.serializeMutation(mutation) ) }; return JSON.stringify(serialized); } deserialize(data) { const { valueEncoding, ...parsed } = JSON.parse(data); if (valueEncoding !== void 0 && valueEncoding !== 2) { throw new Error( `Unsupported transaction value encoding: ${valueEncoding}` ); } 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, valueEncoding === 2) ) }; } 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, escapedObjects) { const collection = this.collections[data.collectionId]; if (!collection) { throw new Error(`Collection with id ${data.collectionId} not found`); } const modified = this.deserializeValue(data.modified, escapedObjects); const key = modified ? collection.getKeyFromItem(modified) : null; return { globalKey: data.globalKey, type: data.type, modified, original: this.deserializeValue(data.original, escapedObjects), changes: this.deserializeValue(data.changes, escapedObjects) ?? {}, 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)) { setDataProperty(result, key, this.serializeValue(value[key])); } } return !Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, `__type`) ? { __type: `Object`, value: result } : result; } return value; } deserializeValue(value, escapedObjects) { 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`) { if (escapedObjects && value.__type === `Object`) { if (value.value === null || typeof value.value !== `object` || Array.isArray(value.value)) { throw new Error(`Corrupted Object marker: expected an object value`); } value = value.value; } const result = Array.isArray(value) ? [] : {}; for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { setDataProperty( result, key, this.deserializeValue(value[key], escapedObjects) ); } } 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