dx-data
v3.0.3
Published
Reactive state management for JavaScript & TypeScript. Zero-dependency & ESM-only. DATAX: proxy-based store with swappable reactivity adapters (Vanilla, Angular, etc.) and deep object interception. DATA: lightweight property interceptor with stackable get
Maintainers
Readme
DX Data
Reactive state management for JavaScript & TypeScript. ESM only.
Comes with two tools:
- DATAX — A proxy-based store where every property is transparently reactive. Supports swappable adapters for Vanilla, Angular, or any other framework. Ideal for objects you want to intercept deeply.
- DATA — A lightweight object where you can attach get/set middleware to any property.
🚀 Installation
Install the package via NPM:
npm install dx-data📖 DATAX
Basic usage
import DATAX from 'dx-data';
// Set a value
DATAX.user = { name: 'Ana', age: 30 };
// Read it
console.log(DATAX.user.name); // 'Ana'
// Update it
DATAX.user.name = 'Luis';Intercept a property with .on()
Lets you react to any get or set on a property's sub-properties.
DATAX.on('user',
function(subProperty, value) {
// Called on every set
console.log('Changed:', subProperty, '→', value);
},
function(subProperty) {
// Called on every get (optional)
console.log('Read:', subProperty);
}
);
DATAX.user.name = 'Carlos'; // → Changed: name → CarlosThe setHandler can return false to cancel the mutation:
DATAX.on('user', function(subProperty, value) {
if(subProperty === 'age' && value < 0) return false; // blocked
});Stop intercepting with .off()
DATAX.off('user');Custom reactivity adapter
By default DATAX uses a plain vanilla adapter. You can swap it for any reactive primitive — for example Angular signals:
import { IDATAXReactivityAdapter, IDATAXProperty, DATAXReactivityAdapter } from 'dx-data';
import { signal, WritableSignal } from '@angular/core';
export const AngularReactivityAdapter: IDATAXReactivityAdapter = {
options: { equal: function(){ return false; } },
create: function(initialValue, options){
const sig: WritableSignal<any> = signal(initialValue, (initialValue && typeof initialValue === 'object' ? this.options : options));
return {
get: sig,
set: sig.set,
update: sig.update
};
}
};
// To set the adapter globally
DATAXReactivityAdapter(AngularReactivityAdapter);
// To define state property type definitions
declare module 'dx-data' {
export interface IDATA {
appName:string;
appVersion:string;
appSupportEmail:string;
appSupportPhone:string;
mainTitle:string;
history:any[];
defaultUser:{ [key: string]: any };
defaultPlace:{ [key: string]: any };
}
export interface IDATAX {
lang: IDATAXProperty<string>;
user: IDATAXProperty<{ [key: string]: any }>;
signedUser: IDATAXProperty<boolean>;
place: IDATAXProperty<{ [key: string]: any }>;
logo: IDATAXProperty<string>;
tabs: IDATAXProperty<boolean>;
AIAssistantQuestion: IDATAXProperty<string>;
}
}After this, every DATAX property will automatically act as an Angular signal, removing the need for explicit set or update calls; instead, you can simply use DATAX.property().
📖 DATA
Basic usage
import { DATA } from 'dx-data';
DATA.count = 0;
console.log(DATA.count); // 0Attach interceptors with .on()
const sub = DATA.on('count',
(value) => {
// Called on every set — return a value to replace it
console.log('Setting count to', value);
return value < 0 ? 0 : value; // clamp to 0
},
(value) => {
// Called on every get — return a value to replace it (optional)
return value * 2;
}
);
DATA.count = -5;
console.log(DATA.count); // 0 (clamped) * 2 = 0
DATA.count = 3;
console.log(DATA.count); // 3 * 2 = 6You can stack multiple interceptors on the same property:
DATA.on('count', (value) => {
console.log('Another interceptor:', value);
});Unsubscribe a specific interceptor
const sub = DATA.on('count', (value) => value * 2);
sub.off(); // only this interceptor is removedRemove a property entirely with .off()
DATA.off('count'); // removes property and all interceptorsTypeScript
All types are available via the .d.ts included in the package:
import type { IDATA, IDATAX, IDATAXReactivityAdapter, IDATAUnsubscribe } from 'dx-data';Add
"noPropertyAccessFromIndexSignature": falseto yourtsconfig.jsonto use dot notation on DATAX properties without type errors.
📝 License
MIT License.
Copyright © 2026 OKZGN
