@tldraw/state
Version:
tldraw infinite canvas SDK (state).
137 lines (136 loc) • 4.65 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var HistoryBuffer_exports = {};
__export(HistoryBuffer_exports, {
HistoryBuffer: () => HistoryBuffer
});
module.exports = __toCommonJS(HistoryBuffer_exports);
var import_types = require("./types");
class HistoryBuffer {
/**
* Creates a new HistoryBuffer with the specified capacity.
*
* capacity - Maximum number of diffs to store in the buffer
* @example
* ```ts
* const buffer = new HistoryBuffer<number>(10) // Store up to 10 diffs
* ```
*/
constructor(capacity) {
this.capacity = capacity;
this.buffer = new Array(capacity);
}
/**
* Current write position in the circular buffer.
* @internal
*/
index = 0;
/**
* Circular buffer storing range tuples. Uses undefined to represent empty slots.
* @internal
*/
buffer;
/**
* Adds a diff entry to the history buffer, representing a change between two epochs.
*
* If the diff is undefined, the operation is ignored. If the diff is RESET_VALUE,
* the entire buffer is cleared to indicate that historical tracking should restart.
*
* @param lastComputedEpoch - The epoch when the previous value was computed
* @param currentEpoch - The epoch when the current value was computed
* @param diff - The diff representing the change, or RESET_VALUE to clear history
* @example
* ```ts
* const buffer = new HistoryBuffer<string>(5)
* buffer.pushEntry(0, 1, 'added text')
* buffer.pushEntry(1, 2, RESET_VALUE) // Clears the buffer
* ```
*/
pushEntry(lastComputedEpoch, currentEpoch, diff) {
if (diff === void 0) {
return;
}
if (diff === import_types.RESET_VALUE) {
this.clear();
return;
}
this.buffer[this.index] = [lastComputedEpoch, currentEpoch, diff];
this.index = (this.index + 1) % this.capacity;
}
/**
* Clears all entries from the history buffer and resets the write position.
* This is called when a RESET_VALUE diff is encountered.
*
* @example
* ```ts
* const buffer = new HistoryBuffer<string>(5)
* buffer.pushEntry(0, 1, 'change')
* buffer.clear()
* console.log(buffer.getChangesSince(0)) // RESET_VALUE
* ```
*/
clear() {
this.index = 0;
this.buffer.fill(void 0);
}
/**
* Retrieves all diffs that occurred since the specified epoch.
*
* The method searches backwards through the circular buffer to find changes
* that occurred after the given epoch. If insufficient history is available
* or the requested epoch is too old, returns RESET_VALUE indicating that
* a complete state rebuild is required.
*
* @param sinceEpoch - The epoch from which to retrieve changes
* @returns Array of diffs since the epoch, or RESET_VALUE if history is insufficient
* @example
* ```ts
* const buffer = new HistoryBuffer<string>(5)
* buffer.pushEntry(0, 1, 'first')
* buffer.pushEntry(1, 2, 'second')
* const changes = buffer.getChangesSince(0) // ['first', 'second']
* const recentChanges = buffer.getChangesSince(1) // ['second']
* const tooOld = buffer.getChangesSince(-100) // RESET_VALUE
* ```
*/
getChangesSince(sinceEpoch) {
const { index, capacity, buffer } = this;
for (let i = 0; i < capacity; i++) {
const offset = (index - 1 + capacity - i) % capacity;
const elem = buffer[offset];
if (!elem) {
return import_types.RESET_VALUE;
}
const [fromEpoch, toEpoch] = elem;
if (i === 0 && sinceEpoch >= toEpoch) {
return [];
}
if (fromEpoch <= sinceEpoch && sinceEpoch < toEpoch) {
const len = i + 1;
const result = new Array(len);
for (let j = 0; j < len; j++) {
result[j] = buffer[(offset + j) % capacity][2];
}
return result;
}
}
return import_types.RESET_VALUE;
}
}
//# sourceMappingURL=HistoryBuffer.js.map