state-jet 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -0,0 +1,14 @@
1
+ # ⚡ fast-state: Ultra-Lightweight Global State for React
2
+
3
+ A zero-boilerplate, ultra-fast global state management library for React. No context, reducers, or providers—just simple reactive state.
4
+
5
+ ## 🚀 Why fast-state?
6
+ - ✅ **No Context, No Providers** – Works outside React, reducing unnecessary re-renders.
7
+ - ✅ **Automatic Re-Renders** – Only components using specific state values update.
8
+ - ✅ **Super Lightweight** – Less than **1KB** minified!
9
+ - ✅ **SSR & Next.js Support** – Works on both client and server.
10
+
11
+ ## 🛠 Installation
12
+ ```bash
13
+ npm install state-jet
14
+ ```
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = App;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const index_1 = require("../src/index");
6
+ const middleware_1 = require("../src/middleware");
7
+ const counter = (0, index_1.useStateGlobal)("counter", 0, { middleware: [middleware_1.loggerMiddleware] });
8
+ function App() {
9
+ const { undo, redo } = counter;
10
+ const count = counter.useStore();
11
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => counter.set(count + 1), children: "+" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => counter.set(count - 1), children: "-" }), (0, jsx_runtime_1.jsx)("button", { onClick: undo, children: "Undo" }), (0, jsx_runtime_1.jsx)("button", { onClick: redo, children: "Redo" }), (0, jsx_runtime_1.jsxs)("p", { children: ["Count: ", count] })] }));
12
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncCRDT = exports.mergeCRDT = void 0;
4
+ const store_1 = require("./store");
5
+ const mergeCRDT = (localState, remoteState) => {
6
+ return Object.assign(Object.assign(Object.assign({}, localState), remoteState), { lastUpdated: Date.now() });
7
+ };
8
+ exports.mergeCRDT = mergeCRDT;
9
+ const syncCRDT = (key, remoteState) => {
10
+ const localState = (0, store_1.useStateGlobal)(key).useStore();
11
+ const merged = (0, exports.mergeCRDT)(localState, remoteState);
12
+ (0, store_1.useStateGlobal)(key).set(merged);
13
+ };
14
+ exports.syncCRDT = syncCRDT;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.derivedState = void 0;
4
+ const derivedState = (dependencies, computeFn) => {
5
+ const derived = { value: computeFn(...dependencies.map((d) => d.useStore())) };
6
+ dependencies.forEach(dep => dep.useStore().listeners.add(() => {
7
+ derived.value = computeFn(...dependencies.map(d => d.useStore()));
8
+ }));
9
+ return () => derived.value;
10
+ };
11
+ exports.derivedState = derivedState;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redoState = exports.undoState = exports.measurePerformance = exports.notifyDevTools = void 0;
4
+ const stateHistory = {};
5
+ const stateIndex = {};
6
+ const performanceData = {};
7
+ const devtoolsEnabled = typeof window !== "undefined" && window.__STATE_JET_DEVTOOLS__;
8
+ const notifyDevTools = (key, value) => {
9
+ if (!stateHistory[key])
10
+ stateHistory[key] = [];
11
+ if (stateIndex[key] === undefined)
12
+ stateIndex[key] = -1;
13
+ // Remove future states when a new state is set
14
+ stateHistory[key] = stateHistory[key].slice(0, stateIndex[key] + 1);
15
+ stateHistory[key].push(value);
16
+ stateIndex[key]++;
17
+ if (devtoolsEnabled && window.__STATE_JET_DEVTOOLS__.updateState) {
18
+ window.__STATE_JET_DEVTOOLS__.updateState(key, value, stateHistory[key]);
19
+ }
20
+ };
21
+ exports.notifyDevTools = notifyDevTools;
22
+ const measurePerformance = (key, callback) => {
23
+ const start = performance.now();
24
+ callback();
25
+ const duration = performance.now() - start;
26
+ if (!performanceData[key])
27
+ performanceData[key] = [];
28
+ performanceData[key].push(duration);
29
+ if (devtoolsEnabled && window.__STATE_JET_DEVTOOLS__.updatePerformance) {
30
+ window.__STATE_JET_DEVTOOLS__.updatePerformance(key, duration);
31
+ }
32
+ };
33
+ exports.measurePerformance = measurePerformance;
34
+ const undoState = (key) => {
35
+ if (stateIndex[key] > 0) {
36
+ stateIndex[key]--;
37
+ return stateHistory[key][stateIndex[key]];
38
+ }
39
+ };
40
+ exports.undoState = undoState;
41
+ const redoState = (key) => {
42
+ if (stateIndex[key] < stateHistory[key].length - 1) {
43
+ stateIndex[key]++;
44
+ return stateHistory[key][stateIndex[key]];
45
+ }
46
+ };
47
+ exports.redoState = redoState;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadEncryptedState = exports.saveEncryptedState = exports.decrypt = exports.encrypt = void 0;
4
+ const encrypt = (data) => btoa(JSON.stringify(data));
5
+ exports.encrypt = encrypt;
6
+ const decrypt = (data) => JSON.parse(atob(data));
7
+ exports.decrypt = decrypt;
8
+ const saveEncryptedState = (key, value) => {
9
+ localStorage.setItem(key, (0, exports.encrypt)(value));
10
+ };
11
+ exports.saveEncryptedState = saveEncryptedState;
12
+ const loadEncryptedState = (key) => {
13
+ const data = localStorage.getItem(key);
14
+ return data ? (0, exports.decrypt)(data) : null;
15
+ };
16
+ exports.loadEncryptedState = loadEncryptedState;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncCRDT = exports.loadEncryptedState = exports.saveEncryptedState = exports.decrypt = exports.encrypt = exports.optimisticUpdate = exports.restoreState = exports.saveState = exports.useStateGlobal = void 0;
4
+ var store_1 = require("./store");
5
+ Object.defineProperty(exports, "useStateGlobal", { enumerable: true, get: function () { return store_1.useStateGlobal; } });
6
+ var persistence_1 = require("./persistence");
7
+ Object.defineProperty(exports, "saveState", { enumerable: true, get: function () { return persistence_1.saveState; } });
8
+ Object.defineProperty(exports, "restoreState", { enumerable: true, get: function () { return persistence_1.restoreState; } });
9
+ var optimistic_1 = require("./optimistic");
10
+ Object.defineProperty(exports, "optimisticUpdate", { enumerable: true, get: function () { return optimistic_1.optimisticUpdate; } });
11
+ var encryption_1 = require("./encryption");
12
+ Object.defineProperty(exports, "encrypt", { enumerable: true, get: function () { return encryption_1.encrypt; } });
13
+ Object.defineProperty(exports, "decrypt", { enumerable: true, get: function () { return encryption_1.decrypt; } });
14
+ Object.defineProperty(exports, "saveEncryptedState", { enumerable: true, get: function () { return encryption_1.saveEncryptedState; } });
15
+ Object.defineProperty(exports, "loadEncryptedState", { enumerable: true, get: function () { return encryption_1.loadEncryptedState; } });
16
+ var crdt_1 = require("./crdt");
17
+ Object.defineProperty(exports, "syncCRDT", { enumerable: true, get: function () { return crdt_1.syncCRDT; } });
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.debounceMiddleware = exports.reducerMiddleware = exports.optimisticMiddleware = exports.validateAgeMiddleware = exports.apiSyncMiddleware = exports.loggerMiddleware = void 0;
13
+ const loggerMiddleware = (key, prev, next) => {
14
+ console.log(`[state-jet] ${key}: ${prev} → ${next}`);
15
+ };
16
+ exports.loggerMiddleware = loggerMiddleware;
17
+ const apiSyncMiddleware = (key, prev, next) => __awaiter(void 0, void 0, void 0, function* () {
18
+ yield fetch("/api/sync", { method: "POST", body: JSON.stringify({ key, next }) });
19
+ });
20
+ exports.apiSyncMiddleware = apiSyncMiddleware;
21
+ const validateAgeMiddleware = (key, prev, next) => {
22
+ if (key === "age" && next < 0) {
23
+ console.warn("Age cannot be negative!");
24
+ return prev;
25
+ }
26
+ return next;
27
+ };
28
+ exports.validateAgeMiddleware = validateAgeMiddleware;
29
+ const optimisticMiddleware = (apiUrl) => {
30
+ return (key, prev, next, set) => __awaiter(void 0, void 0, void 0, function* () {
31
+ set(next); // Optimistically update state
32
+ try {
33
+ yield fetch(apiUrl, {
34
+ method: "POST",
35
+ body: JSON.stringify({ key, value: next }),
36
+ headers: { "Content-Type": "application/json" },
37
+ });
38
+ }
39
+ catch (error) {
40
+ console.warn(`[state-jet] Rollback: Failed to sync ${key}`);
41
+ set(prev); // Rollback state on failure
42
+ }
43
+ });
44
+ };
45
+ exports.optimisticMiddleware = optimisticMiddleware;
46
+ const reducerMiddleware = (key, prev, action) => {
47
+ switch (action.type) {
48
+ case "INCREMENT":
49
+ return prev + 1;
50
+ case "DECREMENT":
51
+ return prev - 1;
52
+ case "RESET":
53
+ return 0;
54
+ default:
55
+ return prev;
56
+ }
57
+ };
58
+ exports.reducerMiddleware = reducerMiddleware;
59
+ const debounceMiddleware = (delay) => {
60
+ let timer;
61
+ return (key, prev, next) => {
62
+ clearTimeout(timer);
63
+ timer = setTimeout(() => {
64
+ console.log(`[state-jet] Debounced: ${key} → ${next}`);
65
+ }, delay);
66
+ return prev; // Prevent immediate update
67
+ };
68
+ };
69
+ exports.debounceMiddleware = debounceMiddleware;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.optimisticUpdate = void 0;
4
+ const optimisticUpdate = (setState, apiCall, fallback) => {
5
+ const prevState = setState.useStore();
6
+ setState.set(apiCall(prevState));
7
+ apiCall()
8
+ .catch(() => setState.set(fallback ? fallback(prevState) : prevState));
9
+ };
10
+ exports.optimisticUpdate = optimisticUpdate;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.restoreState = exports.saveState = void 0;
4
+ const saveState = (key, value, encrypt = false) => {
5
+ if (typeof window !== "undefined") {
6
+ let data = JSON.stringify(value);
7
+ if (encrypt)
8
+ data = btoa(data);
9
+ localStorage.setItem(key, data);
10
+ }
11
+ };
12
+ exports.saveState = saveState;
13
+ const restoreState = (key) => {
14
+ if (typeof window !== "undefined") {
15
+ const data = localStorage.getItem(key);
16
+ return data ? JSON.parse(atob(data)) : undefined;
17
+ }
18
+ };
19
+ exports.restoreState = restoreState;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useStateGlobal = void 0;
4
+ const react_1 = require("react");
5
+ const immer_1 = require("immer");
6
+ const persistence_1 = require("./persistence");
7
+ const devtools_1 = require("./devtools");
8
+ const store = new Map();
9
+ const pendingUpdates = new Map();
10
+ const history = {};
11
+ const useStateGlobal = (key, initialValue, options) => {
12
+ if (!store.has(key)) {
13
+ store.set(key, { value: initialValue, listeners: new Set() });
14
+ if (options === null || options === void 0 ? void 0 : options.persist)
15
+ (0, persistence_1.restoreState)(key);
16
+ }
17
+ const state = store.get(key);
18
+ const undo = () => {
19
+ var _a;
20
+ if ((_a = history[key]) === null || _a === void 0 ? void 0 : _a.past.length) {
21
+ history[key].future.unshift(history[key].present);
22
+ history[key].present = history[key].past.pop();
23
+ state.value = history[key].present;
24
+ state.listeners.forEach((listener) => listener());
25
+ (0, devtools_1.undoState)(key);
26
+ }
27
+ };
28
+ const batchUpdate = () => {
29
+ pendingUpdates.forEach((newValue, key) => {
30
+ var _a;
31
+ let nextValue = newValue;
32
+ let stateValue = state.value;
33
+ if (!history[key]) {
34
+ history[key] = { past: [], present: stateValue, future: [] };
35
+ }
36
+ history[key].past.push(stateValue);
37
+ history[key].present = newValue;
38
+ history[key].future = [];
39
+ (_a = options === null || options === void 0 ? void 0 : options.middleware) === null || _a === void 0 ? void 0 : _a.forEach((mw) => {
40
+ const result = mw(key, stateValue, nextValue);
41
+ if (result !== undefined)
42
+ nextValue = result;
43
+ });
44
+ if (typeof nextValue === "function") {
45
+ state.value = (0, immer_1.produce)(state.value, nextValue);
46
+ }
47
+ else if (stateValue !== nextValue) {
48
+ state.value = nextValue;
49
+ state.listeners.forEach((listener) => listener());
50
+ (0, devtools_1.notifyDevTools)(key, nextValue);
51
+ (0, devtools_1.measurePerformance)(key, () => { });
52
+ if (options === null || options === void 0 ? void 0 : options.persist)
53
+ (0, persistence_1.saveState)(key, nextValue, options.encrypt);
54
+ }
55
+ });
56
+ pendingUpdates.clear();
57
+ };
58
+ const redo = () => {
59
+ var _a;
60
+ if ((_a = history[key]) === null || _a === void 0 ? void 0 : _a.future.length) {
61
+ history[key].past.push(history[key].present);
62
+ history[key].present = history[key].future.shift();
63
+ state.value = history[key].present;
64
+ state.listeners.forEach((listener) => listener());
65
+ (0, devtools_1.redoState)(key);
66
+ }
67
+ };
68
+ const useStore = () => {
69
+ return (0, react_1.useSyncExternalStore)((callback) => {
70
+ state.listeners.add(callback);
71
+ return () => state.listeners.delete(callback);
72
+ }, () => state.value);
73
+ };
74
+ const set = (newValue) => {
75
+ pendingUpdates.set(key, newValue);
76
+ if (window === null || window === void 0 ? void 0 : window.requestAnimationFrame)
77
+ window.requestAnimationFrame(batchUpdate);
78
+ };
79
+ return {
80
+ useStore,
81
+ set,
82
+ undo,
83
+ redo
84
+ };
85
+ };
86
+ exports.useStateGlobal = useStateGlobal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-jet",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Ultra-lightweight global state management for React",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,16 +24,40 @@
24
24
  ],
25
25
  "author": "venkateshsundaram",
26
26
  "license": "MIT",
27
+ "bugs": {
28
+ "url": "https://github.com/venkateshsundaram/state-jet/issues"
29
+ },
27
30
  "scripts": {
28
31
  "build": "tsc",
29
32
  "test": "vitest",
33
+ "clean": "rm -rf dist/*",
30
34
  "publish:npm": "npm publish --access public",
31
- "lint": "eslint src --ext .ts,.tsx",
32
- "prepare": "npm run build"
35
+ "lint": "eslint src --ext .ts,.tsx"
33
36
  },
34
37
  "devDependencies": {
38
+ "@types/react": "^19.0.3",
39
+ "@types/react-dom": "^19.0.2",
35
40
  "eslint": "^8.57.1",
41
+ "immer": "^10.1.1",
42
+ "react": "19.0.0",
43
+ "react-dom": "19.0.0",
36
44
  "typescript": "^5.7.3",
37
- "vitest": "^1.6.1"
45
+ "vitest": "^2.1.8"
46
+ },
47
+ "peerDependencies": {
48
+ "@types/react": ">=18.0.0",
49
+ "immer": ">=9.0.6",
50
+ "react": ">=18.0.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "@types/react": {
54
+ "optional": true
55
+ },
56
+ "immer": {
57
+ "optional": true
58
+ },
59
+ "react": {
60
+ "optional": true
61
+ }
38
62
  }
39
63
  }