UNPKG

@vaadin/hilla-react-signals

Version:

Signals for Hilla React

62 lines 2.79 kB
import { nanoid } from 'nanoid'; import { createReplaceStateEvent, createSetStateEvent, isReplaceStateEvent, isSetStateEvent, isSnapshotStateEvent, } from './events.js'; import { $createOperation, $processServerResponse, $resolveOperation, $setValueQuietly, $update, FullStackSignal, } from './FullStackSignal.js'; export class ValueSignal extends FullStackSignal { #pendingRequests = new Map(); set(value) { const { parentClientSignalId } = this.server.config; const signalId = parentClientSignalId !== undefined ? this.id : undefined; const event = createSetStateEvent(value, signalId, parentClientSignalId); const promise = this[$update](event); this[$setValueQuietly](value); return this[$createOperation]({ id: event.id, promise }); } replace(expected, newValue) { const { parentClientSignalId } = this.server.config; const signalId = parentClientSignalId !== undefined ? this.id : undefined; const event = createReplaceStateEvent(expected, newValue, signalId, parentClientSignalId); const promise = this[$update](event); return this[$createOperation]({ id: event.id, promise }); } update(callback) { const newValue = callback(this.value); const event = createReplaceStateEvent(this.value, newValue); const promise = this[$update](event); const pendingRequest = { id: nanoid(), callback, canceled: false }; this.#pendingRequests.set(event.id, pendingRequest); return { ...this[$createOperation]({ id: pendingRequest.id, promise }), cancel: () => { pendingRequest.canceled = true; }, }; } [$processServerResponse](event) { const record = this.#pendingRequests.get(event.id); if (record) { this.#pendingRequests.delete(event.id); if (!(event.accepted || record.canceled)) { this.update(record.callback); } } let reason; if (event.accepted || isSnapshotStateEvent(event)) { this.#applyAcceptedEvent(event); } else { reason = `Server rejected the operation with id '${event.id}'. See the server log for more details.`; } [record?.id, event.id].filter(Boolean).forEach((id) => this[$resolveOperation](id, reason)); } #applyAcceptedEvent(event) { if (isSetStateEvent(event) || isSnapshotStateEvent(event)) { this.value = event.value; } else if (isReplaceStateEvent(event)) { if (JSON.stringify(this.value) === JSON.stringify(event.expected)) { this.value = event.value; } } } } //# sourceMappingURL=ValueSignal.js.map