Skip to content

Installation

bash
npm install @statesync/vue @statesync/core

Purpose

@statesync/vue applies snapshots to Vue reactive() objects and ref() values.

API

createVueSnapshotApplier(stateOrRef, options?)

OptionTypeDefaultDescription
target'reactive' | 'ref''reactive'Which Vue primitive to target
mode'patch' | 'replace''patch'Apply strategy (see below)
pickKeysReadonlyArray<keyof State>Only update these keys (mutually exclusive with omitKeys)
omitKeysReadonlyArray<keyof State>Protect these keys from updates
toState(data, ctx) => Partial<State>identityMap snapshot data to state shape. ctx contains { state } for reactive or { ref } for ref target
strictbooleantrueThrow if toState returns a non-object

Interfaces

ts
interface VueRefLike<State> {
  value: State;
}

type VueTargetKind = 'ref' | 'reactive';

Apply semantics

target: 'reactive' (default)

Works like Valtio — mutates the reactive object in place (reference preserved):

ModeBehavior
'patch'state[key] = value for each filtered key
'replace'delete state[key] for stale keys + state[key] = value

target: 'ref'

Works like Svelte — replaces .value with a new object:

ModeBehavior
'patch'ref.value = { ...ref.value, ...patch }
'replace'ref.value = rebuiltState (preserving omitted keys)

Example (reactive)

ts
import { createRevisionSync } from '@statesync/core';
import { createVueSnapshotApplier } from '@statesync/vue';
import { reactive } from 'vue';

const state = reactive({ count: 0, name: 'world', isEditing: false });

const applier = createVueSnapshotApplier(state, {
  mode: 'patch',
  omitKeys: ['isEditing'],
});

const sync = createRevisionSync({
  topic: 'app-config',
  subscriber,
  provider,
  applier,
});

await sync.start();

Example (ref)

ts
import { createVueSnapshotApplier } from '@statesync/vue';
import { ref } from 'vue';

const state = ref({ count: 0, name: 'world' });

const applier = createVueSnapshotApplier(state, {
  target: 'ref',
  mode: 'patch',
});

Using in a Vue component

vue
<script setup>
import { onMounted, onUnmounted, reactive } from 'vue';
import { createRevisionSync } from '@statesync/core';
import { createVueSnapshotApplier } from '@statesync/vue';

const state = reactive({ theme: 'light', locale: 'en' });

const applier = createVueSnapshotApplier(state, { mode: 'patch' });
const sync = createRevisionSync({ topic: 'prefs', subscriber, provider, applier });

onMounted(() => sync.start());
onUnmounted(() => sync.stop());
</script>

<template>
  <p>Theme: {{ state.theme }}</p>
</template>

Can be used alongside @statesync/pinia

Pinia stores use reactive() internally — the Vue adapter works with both standalone Vue state and Pinia stores. For Pinia-specific features ($patch, $state), use the dedicated @statesync/pinia adapter.

See also

Released under the MIT License.