state-jet 1.0.0 → 1.0.1

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.
@@ -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;
package/dist/index.js ADDED
@@ -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 devtools_1 = require("./devtools");
7
+ const store = new Map();
8
+ const pendingUpdates = new Map();
9
+ const history = {};
10
+ const useStateGlobal = (key, initialValue, options) => {
11
+ if (!store.has(key)) {
12
+ store.set(key, { value: initialValue, listeners: new Set() });
13
+ }
14
+ const state = (0, react_1.useMemo)(() => {
15
+ if (!store.has(key)) {
16
+ store.set(key, { value: initialValue, listeners: new Set() });
17
+ }
18
+ return store.get(key);
19
+ }, [key]);
20
+ const undo = () => {
21
+ var _a;
22
+ if ((_a = history[key]) === null || _a === void 0 ? void 0 : _a.past.length) {
23
+ history[key].future.unshift(history[key].present);
24
+ history[key].present = history[key].past.pop();
25
+ state.value = history[key].present;
26
+ state.listeners.forEach((listener) => listener());
27
+ (0, devtools_1.undoState)(key);
28
+ }
29
+ };
30
+ const batchUpdate = () => {
31
+ pendingUpdates.forEach((newValue, key) => {
32
+ var _a;
33
+ let nextValue = newValue;
34
+ let stateValue = state.value;
35
+ if (!history[key]) {
36
+ history[key] = { past: [], present: stateValue, future: [] };
37
+ }
38
+ history[key].past.push(stateValue);
39
+ history[key].present = newValue;
40
+ history[key].future = [];
41
+ (_a = options === null || options === void 0 ? void 0 : options.middleware) === null || _a === void 0 ? void 0 : _a.forEach((mw) => {
42
+ const result = mw(key, stateValue, nextValue);
43
+ if (result !== undefined)
44
+ nextValue = result;
45
+ });
46
+ if (typeof nextValue === "function") {
47
+ state.value = (0, immer_1.produce)(state.value, nextValue);
48
+ }
49
+ else if (stateValue !== nextValue) {
50
+ state.value = nextValue;
51
+ state.listeners.forEach((listener) => listener());
52
+ (0, devtools_1.notifyDevTools)(key, nextValue);
53
+ (0, devtools_1.measurePerformance)(key, () => { });
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;
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "state-jet",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
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,44 @@
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
35
  "lint": "eslint src --ext .ts,.tsx",
32
- "prepare": "npm run build"
36
+ "prepare": "npm run clean && npm run build"
33
37
  },
34
38
  "devDependencies": {
35
39
  "eslint": "^8.57.1",
40
+ "immer": "^10.1.1",
41
+ "react": "19.0.0",
42
+ "react-dom": "19.0.0",
36
43
  "typescript": "^5.7.3",
37
- "vitest": "^1.6.1"
44
+ "use-sync-external-store": "^1.4.0",
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
+ "use-sync-external-store": ">=1.2.0"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "@types/react": {
55
+ "optional": true
56
+ },
57
+ "immer": {
58
+ "optional": true
59
+ },
60
+ "react": {
61
+ "optional": true
62
+ },
63
+ "use-sync-external-store": {
64
+ "optional": true
65
+ }
38
66
  }
39
67
  }