memorio 1.1.0 → 1.1.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 +60 -80
- package/index.js +1 -1
- package/package.json +8 -7
package/README.md
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
# Memorio
|
|
2
2
|
|
|
3
|
-
> A lightweight, type-safe state management library for
|
|
3
|
+
> A lightweight, type-safe state management library for JavaScript applications
|
|
4
|
+
|
|
5
|
+
[](https://npmjs.org/package/memorio)
|
|
6
|
+
[](https://npmjs.org/package/memorio)
|
|
7
|
+
[](https://snyk.io/advisor/npm-package/memorio)
|
|
4
8
|
|
|
5
9
|

|
|
6
10
|

|
|
7
11
|

|
|
8
12
|

|
|
9
13
|

|
|
10
|
-

|
|
11
14
|
|
|
12
15
|

|
|
13
16
|

|
|
14
17
|
|
|
18
|
+

|
|
19
|
+
|
|
15
20
|
## Table of Contents
|
|
16
21
|
|
|
17
22
|
- [Features](#features)
|
|
@@ -33,17 +38,12 @@
|
|
|
33
38
|
- Session management for temporary data
|
|
34
39
|
- Type-safe with full TypeScript support
|
|
35
40
|
- Comprehensive test coverage
|
|
36
|
-
- Zero dependencies
|
|
37
41
|
- Easy debugging with proxy-based state
|
|
38
42
|
|
|
39
43
|
## Installation
|
|
40
44
|
|
|
41
45
|
```bash
|
|
42
|
-
npm
|
|
43
|
-
# or
|
|
44
|
-
yarn add memorio
|
|
45
|
-
# or
|
|
46
|
-
pnpm add memorio
|
|
46
|
+
npm i -D memorio
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
### All test suites are passing
|
|
@@ -59,16 +59,29 @@ Total: 25 tests passed across 5 test suites
|
|
|
59
59
|
## Quick Start
|
|
60
60
|
|
|
61
61
|
```javascript
|
|
62
|
+
/*
|
|
63
|
+
IMPORTANT!
|
|
64
|
+
Add import only at first start of your SPA. Became global!.
|
|
65
|
+
You don't need to import any time you need to use memorio
|
|
66
|
+
*/
|
|
67
|
+
|
|
62
68
|
import 'memorio';
|
|
63
69
|
|
|
64
70
|
// State Management
|
|
65
71
|
state.counter = 0;
|
|
72
|
+
state.active = false;
|
|
73
|
+
state.name = "john";
|
|
66
74
|
state.user = { name: 'John', age: 30 };
|
|
75
|
+
state.hours = [2,3,10,23]
|
|
67
76
|
|
|
68
77
|
// Observer Pattern
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
// Example: if you change the state.counter you get a console.log
|
|
79
|
+
observer(
|
|
80
|
+
'state.counter',
|
|
81
|
+
(newValue, oldValue) => {
|
|
82
|
+
console.log(`Counter changed from ${oldValue} to ${newValue}`);
|
|
83
|
+
}
|
|
84
|
+
);
|
|
72
85
|
|
|
73
86
|
// Store (Persistent Storage)
|
|
74
87
|
store.set('preferences', { theme: 'dark' });
|
|
@@ -110,58 +123,47 @@ state.removeAll();
|
|
|
110
123
|
|
|
111
124
|
Observe state changes with React-like syntax:
|
|
112
125
|
|
|
113
|
-
```javascript
|
|
114
|
-
// Basic observer
|
|
115
|
-
observer('state.user', (newValue, oldValue) => {
|
|
116
|
-
console.log('User updated:', newValue);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// With React useState
|
|
120
|
-
const [user, setUser] = useState();
|
|
121
|
-
observer('state.user', () => {
|
|
122
|
-
setUser(state.user);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// With React useEffect
|
|
126
|
-
useEffect(() => {
|
|
127
|
-
console.log('User changed:', state.user);
|
|
128
|
-
}, [state.user]);
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Another example of use of Observer
|
|
132
|
-
|
|
133
126
|
```js
|
|
134
|
-
import 'memorio';
|
|
135
127
|
|
|
136
|
-
//
|
|
128
|
+
// Basic observer
|
|
137
129
|
observer(
|
|
138
|
-
'state.
|
|
139
|
-
|
|
130
|
+
'state.user',
|
|
131
|
+
(newValue, oldValue) => {
|
|
132
|
+
console.log('User updated:', newValue);
|
|
133
|
+
}
|
|
140
134
|
);
|
|
141
135
|
|
|
142
|
-
// Store a value in the state that changes every 5 seconds
|
|
143
|
-
setInterval(() => state.count = Date.now(), 5000);
|
|
144
136
|
```
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
138
|
+
1. You can use in a function outside React
|
|
139
|
+
2. In a javascript function
|
|
140
|
+
3. in a setTimeout
|
|
149
141
|
|
|
150
142
|
```js
|
|
151
|
-
// Set a store:
|
|
152
|
-
store.set("test", { test: "test" })
|
|
153
|
-
|
|
154
|
-
// Get a store:
|
|
155
|
-
store.get("test") // Output: { test: "test" }
|
|
156
143
|
|
|
157
|
-
//
|
|
158
|
-
|
|
144
|
+
// With React useState
|
|
145
|
+
const [user, setUser] = useState();
|
|
146
|
+
observer(
|
|
147
|
+
'state.user',
|
|
148
|
+
() => {
|
|
149
|
+
setUser(state.user);
|
|
150
|
+
}
|
|
151
|
+
);
|
|
159
152
|
|
|
160
|
-
//
|
|
161
|
-
|
|
153
|
+
// With React useEffect to avoid multiple observer after update
|
|
154
|
+
useEffect(
|
|
155
|
+
() => {
|
|
156
|
+
observer(
|
|
157
|
+
'state.user',
|
|
158
|
+
() => {
|
|
159
|
+
setUser(state.user);
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
}, []
|
|
163
|
+
);
|
|
162
164
|
```
|
|
163
165
|
|
|
164
|
-
|
|
166
|
+
## Store
|
|
165
167
|
|
|
166
168
|
Persistent storage for your application:
|
|
167
169
|
|
|
@@ -182,16 +184,18 @@ const size = store.size();
|
|
|
182
184
|
store.removeAll();
|
|
183
185
|
```
|
|
184
186
|
|
|
185
|
-
|
|
187
|
+
## Session
|
|
186
188
|
|
|
187
189
|
Temporary storage that persists during page sessions:
|
|
188
190
|
|
|
189
|
-
```
|
|
191
|
+
```js
|
|
190
192
|
// Setting session data
|
|
191
|
-
session.set(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
session.set(
|
|
194
|
+
'userSession', {
|
|
195
|
+
id: 'user123',
|
|
196
|
+
lastActive: Date.now()
|
|
197
|
+
}
|
|
198
|
+
);
|
|
195
199
|
|
|
196
200
|
// Getting session data
|
|
197
201
|
const userData = session.get('userSession');
|
|
@@ -204,18 +208,6 @@ session.remove('userSession');
|
|
|
204
208
|
|
|
205
209
|
// Clearing all session data
|
|
206
210
|
session.removeAll();
|
|
207
|
-
|
|
208
|
-
// Remove all stored data if necessary
|
|
209
|
-
// store.removeAll();
|
|
210
|
-
|
|
211
|
-
return (
|
|
212
|
-
<div>
|
|
213
|
-
<h1 id="name">...</h1>
|
|
214
|
-
</div>
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
export default App;
|
|
219
211
|
```
|
|
220
212
|
|
|
221
213
|
---
|
|
@@ -243,16 +235,4 @@ Security scans and reports are available at:
|
|
|
243
235
|
|
|
244
236
|
MIT (c) [Dario Passariello](https://dario.passariello.ca/)
|
|
245
237
|
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## Contributing
|
|
249
|
-
|
|
250
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
251
|
-
|
|
252
|
-
## Support
|
|
253
|
-
|
|
254
|
-
Need help? Feel free to [open an issue](https://github.com/a51-dev/a51.memorio/issues).
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
258
238
|
Created with by [Dario Passariello](https://dario.passariello.ca/) - Copyright (c) 2025
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{var c={name:"memorio",version:"1.1.
|
|
1
|
+
"use strict";(()=>{var c={name:"memorio",version:"1.1.2",type:"module",main:"index.js",scripts:{build:"node ./esbuild.config.mjs",watch:"esbuild init.ts --bundle --outdir=dist --serve","----------":"",updates:"npx npm-check-updates -u && npm i","-----------":"",test:"set NODE_OPTIONS=--experimental-vm-modules && jest","test:watch":"set NODE_OPTIONS=--experimental-vm-modules && jest --watch","test:coverage":"set NODE_OPTIONS=--experimental-vm-modules && jest --coverage","test:watchAll":"set NODE_OPTIONS=--experimental-vm-modules && jest --watchAll",tsc:"tsc -b .",eslint:"eslint .","------------":"","publish:npm":"npm run build && npm publish ./dist"},types:"index.d.ts",typings:"./types/*",description:"Memorio, State + Observer and Store for a easy life ",license:"MIT",copyright:"Dario Passariello, BigLogic ca - a51.dev is a BigLogic project",homepage:"https://a51.gitbook.io/memorio",author:{name:"Dario Passariello",url:"https://dario.passariello.ca/",email:"dariopassariello@gmail.com"},support:{name:"Dario Passariello",url:"https://github.com/passariello/",email:"dariopassariello@gmail.com"},contributors:[{name:"Dario Passariello",email:"dariopassarielloa@gmail.com"},{name:"Valeria Cala Scaglitta",email:"valeriacalascaglitta@gmail.com"}],keywords:["biglogic","a51","memorio","state","store","observer","dario","passariello"],repository:{type:"git",url:"git+https://github.com/a51-dev/a51.memorio.git",help:"https://github.com/a51-dev/a51.memorio#readme"},bugs:{url:"https://github.com/a51-dev/a51.memorio/issues"},funding:[{type:"patreon",url:"https://www.patreon.com/passariello"}],typing:["types/*"],dependencies:{"dphelper.types":"0.0.19"},devDependencies:{"@eslint/js":"9.34.0","@types/jest":"30.0.0","@types/node":"^24.3.1","@typescript-eslint/eslint-plugin":"8.42.0","@typescript-eslint/parser":"8.42.0","dphelper.types":"0.0.19",esbuild:"^0.25.9","esbuild-plugin-clean":"^1.0.1","esbuild-plugin-copy":"^2.1.1",eslint:"9.34.0",jest:"30.1.3","jest-environment-jsdom":"30.1.2","ts-jest":"29.4.1","ts-loader":"^9.5.4","ts-node":"10.9.2",tslib:"^2.8.1",typescript:"5.9.2"}};Object.defineProperty(globalThis,"memorio",{value:{},writable:!1,configurable:!1,enumerable:!1});Object.defineProperty(globalThis,"events",{value:{},writable:!0,configurable:!1,enumerable:!1});Object.defineProperty(memorio,"version",{writable:!1,configurable:!1,enumerable:!1,value:c.version});Object.defineProperty(memorio,"dispatch",{writable:!1,configurable:!1,enumerable:!1,value:{set:(e,t={})=>{dispatchEvent(new CustomEvent(String(e),t))},listen:(e,t=null,i=!1)=>{observer.list?.[e]?.length>0&&observer.remove(e);let l=r=>t?setTimeout(()=>t(r),1):null;globalThis.addEventListener(e,l),globalThis.events[e]=l},remove:e=>{globalThis.removeEventListener(e,globalThis.events[e]),delete globalThis.events[e]}}});Object.defineProperty(memorio,"objPath",{writable:!1,configurable:!1,enumerable:!1,value:(e,t,i=".")=>t.concat(e).join(i)});var u=(e,t,i=[])=>{let l=r=>{let o=r.split(".");o.forEach((s,n)=>{let a=o.slice(0,n+1).join(".");globalThis.memorio.dispatch.set(a,{detail:{name:a}})})};return new Proxy(e,{get(r,o){if(o==="list"){let s={};for(let n in r)typeof r[n]!="function"&&!["list","remove","removeAll"].includes(n)&&(s[n]=r[n]);return s}if(o==="remove")return function(s){return s in r&&!["list","remove","removeAll"].includes(s)?(delete r[s],!0):!1};if(o==="removeAll")return function(){for(let s in r)typeof r[s]!="function"&&!["list","remove","removeAll"].includes(s)&&delete r[s];return!0};if(Object.isFrozen(r[o]))return r[o];try{let s=Reflect.get(r,o);return s&&typeof s=="object"&&["Array","Object"].includes(s.constructor.name)?u(s,t,i.concat(o)):s}catch(s){console.error("Error: ",s);return}},set(r,o,s){if(r[o]&&typeof r[o]=="object"&&Object.isFrozen(r[o])){console.error(`Error: state '${o}' is locked`);return}try{let n=globalThis.memorio.objPath(o,i);return t({action:"set",path:n,target:r,newValue:s,previousValue:Reflect.get(r,o)}),l("state."+n),Reflect.set(r,o,s),r[o]&&typeof r[o]=="object"&&Reflect.defineProperty(r[o],"lock",{value(){Object.defineProperty(r,o,{writable:!1,enumerable:!1}),Object.freeze(r[o])}}),!0}catch(n){return console.error("Error in set trap:",n),!1}},deleteProperty(r,o){try{let s=globalThis.memorio.objPath(o,i);return t({action:"delete",path:s,target:r}),Reflect.deleteProperty(r,o)}catch(s){return console.error("Error in deleteProperty trap:",s),!1}}})},g={};globalThis?.state?globalThis.state=state:globalThis.state=u(g,()=>{});var f=new WeakSet;f.add(state);setInterval(()=>{if(!f.has(state)){alert("memorio State is compromised, check if you override it and please reload the page");for(let e=1;e<99999;e++)clearInterval(e);stop()}},1e3);Object.defineProperty(globalThis,"state",{enumerable:!1,configurable:!1});globalThis.observer||(globalThis.observer=null);Object.defineProperty(globalThis,"observer",{enumerable:!1});observer=(e,t=null,i=!0)=>{if((r=>r.split(".")[0]!=="state"?(console.error(`Observer Error: You need to declare 'state.' or 'store.'. The '${r}' string is incorrect!`),!1):!0)(e)){if(!e&&!t){console.error("Observer Error: You need to setup observer correctly, Some parameters are missed!");return}if(!e&&t){console.error("Observer Error: You need to declare what state need to be monitored as string like 'state.test'.");return}if(e&&!t){globalThis.memorio.dispatch.listen(String(e),{detail:{name:String(e)}}),console.debug("called: ",e);return}if(e&&t){if(typeof e!="string"||typeof t!="function"){console.error("Observer Error: name of state need to be a 'string' like 'state.test' and the callback need to be a 'function'");return}globalThis.memorio.dispatch.listen(e,t,i);return}}};Object.defineProperties(observer,{list:{get:()=>globalThis.events},remove:{value:e=>{e&&(globalThis.events[e]="")}},removeAll:{get:()=>{Object.entries(observer.list).forEach(e=>{globalThis.events[e[0]]})}}});Object.freeze(observer);Object.defineProperty(globalThis,"store",{value:new Proxy({},{}),enumerable:!1,configurable:!1});Object.defineProperties(store,{get:{value(e){if(e)try{let t=localStorage.getItem(e);return t&&JSON.parse(t)}catch(t){console.error(`Error parsing store item '${e}':`,t)}}},set:{value(e,t){if(e)try{t==null?localStorage.setItem(e,JSON.stringify(null)):typeof t=="object"||typeof t=="number"||typeof t=="boolean"||typeof t=="string"?localStorage.setItem(e,JSON.stringify(t)):typeof t=="function"&&console.error("It's not secure to store functions.")}catch(i){console.error(`Error setting store item '${e}':`,i)}}},remove:{value(e){if(e&&localStorage.getItem(e))return localStorage.removeItem(e),!0}},delete:{value(e){store.remove(e)}},removeAll:{value(){return localStorage.clear(),!0}},clearAll:{value(){return store.removeAll(),!0}},quota:{value(){"storage"in navigator&&"estimate"in navigator.storage&&navigator.storage.estimate().then(({usage:e,quota:t})=>{e&&t&&console.debug(`Using ${e/1024} out of ${t/1024} Mb.`)}).catch(e=>{console.error("Error estimating quota:",e)})}},size:{value(){let e=0;for(let t in localStorage)if(localStorage.hasOwnProperty(t)){let i=localStorage.getItem(t);i&&(e+=i.length)}return e}}});Object.freeze(store);Object.defineProperty(globalThis,"session",{value:new Proxy({},{}),enumerable:!1,configurable:!1});Object.defineProperties(session,{get:{value(e){if(e)try{let t=sessionStorage.getItem(e);return t&&JSON.parse(t)}catch(t){console.error(`Error parsing session item '${e}':`,t)}}},set:{value(e,t){if(e)try{t==null?sessionStorage.setItem(e,JSON.stringify(null)):typeof t=="object"||typeof t=="number"||typeof t=="boolean"||typeof t=="string"?sessionStorage.setItem(e,JSON.stringify(t)):typeof t=="function"&&console.error("It's not secure to session functions.")}catch(i){console.error(`Error setting session item '${e}':`,i)}}},remove:{value(e){if(e&&sessionStorage.getItem(e))return sessionStorage.removeItem(e),!0}},delete:{value(e){session.remove(e)}},removeAll:{value(){return sessionStorage.clear(),!0}},clearAll:{value(){return session.removeAll(),!0}},quota:{value(){"storage"in navigator&&"estimate"in navigator.storage&&navigator.storage.estimate().then(({usage:e,quota:t})=>{e&&t&&console.debug(`Using ${e/1024} out of ${t/1024} Mb.`)}).catch(e=>{console.error("Error estimating quota:",e)})}},size:{value(){let e=0;for(let t in sessionStorage)if(sessionStorage.hasOwnProperty(t)){let i=sessionStorage.getItem(t);i&&(e+=i.length)}return e}}});Object.freeze(session);Object.defineProperty(window,"cache",{value:new Proxy({},{}),enumerable:!1,configurable:!1});})();
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorio",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "node ./esbuild.config.mjs",
|
|
8
8
|
"watch": "esbuild init.ts --bundle --outdir=dist --serve",
|
|
9
|
+
"----------": "",
|
|
10
|
+
"updates": "npx npm-check-updates -u && npm i",
|
|
9
11
|
"-----------": "",
|
|
10
12
|
"test": "set NODE_OPTIONS=--experimental-vm-modules && jest",
|
|
11
13
|
"test:watch": "set NODE_OPTIONS=--experimental-vm-modules && jest --watch",
|
|
@@ -13,8 +15,7 @@
|
|
|
13
15
|
"test:watchAll": "set NODE_OPTIONS=--experimental-vm-modules && jest --watchAll",
|
|
14
16
|
"tsc": "tsc -b .",
|
|
15
17
|
"eslint": "eslint .",
|
|
16
|
-
"
|
|
17
|
-
"----------": "",
|
|
18
|
+
"------------": "",
|
|
18
19
|
"publish:npm": "npm run build && npm publish ./dist"
|
|
19
20
|
},
|
|
20
21
|
"types": "index.d.ts",
|
|
@@ -76,15 +77,15 @@
|
|
|
76
77
|
"devDependencies": {
|
|
77
78
|
"@eslint/js": "9.34.0",
|
|
78
79
|
"@types/jest": "30.0.0",
|
|
79
|
-
"@types/node": "^24.3.
|
|
80
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
81
|
-
"@typescript-eslint/parser": "8.
|
|
80
|
+
"@types/node": "^24.3.1",
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "8.42.0",
|
|
82
|
+
"@typescript-eslint/parser": "8.42.0",
|
|
82
83
|
"dphelper.types": "0.0.19",
|
|
83
84
|
"esbuild": "^0.25.9",
|
|
84
85
|
"esbuild-plugin-clean": "^1.0.1",
|
|
85
86
|
"esbuild-plugin-copy": "^2.1.1",
|
|
86
87
|
"eslint": "9.34.0",
|
|
87
|
-
"jest": "30.1.
|
|
88
|
+
"jest": "30.1.3",
|
|
88
89
|
"jest-environment-jsdom": "30.1.2",
|
|
89
90
|
"ts-jest": "29.4.1",
|
|
90
91
|
"ts-loader": "^9.5.4",
|