ump-plugin-shared-data
v0.0.1
Published
UMP Shared Data — in-memory, observable key→JSON store shared between JS and native
Downloads
144
Readme
ump-plugin-shared-data
In-memory, observable shared key–value store across the JS layer and native host code (iOS / Android / HarmonyOS). A write on one side notifies subscribers on the other. Values are JSON-serializable; the store is process-lifetime (not persisted) — it is real-time shared state between JS and native, not a storage layer.
This is distinct from ump-plugin-storage (async, persisted KV) and
localStorage (sync, persisted): those persist to disk; this one is in-memory
and observable.
JS
import { SharedData } from 'ump-plugin-shared-data';
SharedData.set('user', { id: 1, name: 'a' }); // JSON.stringify + broadcast
SharedData.get('user'); // { id: 1, name: 'a' } (null if absent)
SharedData.keys(); // ['user']
const off = SharedData.subscribe('user', (v) => console.log('user ->', v));
SharedData.subscribeAll((key, v) => console.log(key, '->', v));
off(); // unsubscribe
SharedData.remove('user'); // subscribers fire with null
SharedData.set('user', undefined); // top-level undefined === remove- Values: any JSON-serializable value (string / number / boolean / object / array / null).
get/set/remove/keysare synchronous.- A write broadcasts to all subscribers, including the side that wrote it (echo). Equal-value writes are de-duped — writing the same JSON fires nothing.
setthrows if the value is not JSON-serializable (e.g. a cycle).
Native
Native callers exchange JSON strings (parse with the platform's JSON
library). setJSON validates the string at the boundary and rejects invalid
JSON without storing.
iOS (Objective-C / Swift)
#import "UMPSharedData.h"
[UMPSharedData setJSON:@"user" value:@"{\"id\":1}"]; // returns NO if invalid JSON
NSString *json = [UMPSharedData getJSON:@"user"]; // JSON string or nil
NSArray<NSString *> *ks = [UMPSharedData keys];
id token = [UMPSharedData observe:@"user" onChange:^(NSString * _Nullable json) {
// fires on the writer's thread; hop to main for UIKit. json is nil on removal.
}];
[UMPSharedData unobserve:token]; // idempotentAndroid (Kotlin)
UMPSharedData.setJSON("user", "{\"id\":1}") // false if invalid JSON
UMPSharedData.getJSON("user") // String? (null if absent)
UMPSharedData.keys() // Array<String>
val token = UMPSharedData.observe("user") { json ->
// posted to the Looper captured at observe() time. json is null on removal.
}
UMPSharedData.unobserve(token) // idempotentHarmonyOS (ArkTS)
import { UMPSharedData } from './UMPSharedData';
UMPSharedData.setJSON('user', '{"id":1}'); // false if invalid JSON
UMPSharedData.getJSON('user'); // string | null
UMPSharedData.keys(); // string[]observe on HarmonyOS is deferred to v2 (it needs a NAPI threadsafe-function
to hop the store's writer-thread callback into ArkTS). iOS and Android support
observe/unobserve today.
Architecture
The store is a thread-safe singleton (ump::SharedDataStore) in runtime/core,
so JS, native, and every platform reach the same data. The plugin is glue: a
JSI registrar exposes __ump_shareddata_* to JS and a kSharedData event
channel; per-platform helpers wrap the store's C ABI. Writes broadcast outside
the store lock; JS subscribers are delivered on the JS thread via the plugin
event bus; native subscribers fire on the writer's thread.
Design: docs/superpowers/specs/2026-06-04-shared-data-plugin-design.md
