memorio 1.0.2 โ 1.1.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.
- package/README.md +63 -122
- package/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
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
4
|
|
|
5
|
-

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
10
|

|
|
11
|
-

|
|
12
11
|
|
|
13
12
|

|
|
14
13
|

|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Table of Contents
|
|
17
16
|
|
|
18
17
|
- [Features](#features)
|
|
19
18
|
- [Installation](#installation)
|
|
@@ -27,27 +26,23 @@
|
|
|
27
26
|
- [Security](#security)
|
|
28
27
|
- [License](#license)
|
|
29
28
|
|
|
30
|
-
##
|
|
29
|
+
## Features
|
|
31
30
|
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
31
|
+
- Reactive state management with observer pattern
|
|
32
|
+
- Persistent storage with Store API
|
|
33
|
+
- Session management for temporary data
|
|
34
|
+
- Type-safe with full TypeScript support
|
|
35
|
+
- Comprehensive test coverage
|
|
36
|
+
- Zero dependencies
|
|
37
|
+
- Easy debugging with proxy-based state
|
|
39
38
|
|
|
40
|
-
##
|
|
39
|
+
## Installation
|
|
41
40
|
|
|
42
41
|
```bash
|
|
43
|
-
npm
|
|
44
|
-
# or
|
|
45
|
-
yarn add memorio
|
|
46
|
-
# or
|
|
47
|
-
pnpm add memorio
|
|
42
|
+
npm i -D memorio
|
|
48
43
|
```
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
### All test suites are passing
|
|
51
46
|
|
|
52
47
|
- Basic functionality tests
|
|
53
48
|
- State management tests
|
|
@@ -57,9 +52,14 @@ pnpm add memorio
|
|
|
57
52
|
|
|
58
53
|
Total: 25 tests passed across 5 test suites
|
|
59
54
|
|
|
60
|
-
##
|
|
55
|
+
## Quick Start
|
|
61
56
|
|
|
62
57
|
```javascript
|
|
58
|
+
/*
|
|
59
|
+
IMPORTANT!
|
|
60
|
+
Add import only at first start of your SPA. Became global!.
|
|
61
|
+
You don't need to import any time you need to use memorio
|
|
62
|
+
*/
|
|
63
63
|
import 'memorio';
|
|
64
64
|
|
|
65
65
|
// State Management
|
|
@@ -67,9 +67,12 @@ state.counter = 0;
|
|
|
67
67
|
state.user = { name: 'John', age: 30 };
|
|
68
68
|
|
|
69
69
|
// Observer Pattern
|
|
70
|
-
observer(
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
observer(
|
|
71
|
+
'state.counter',
|
|
72
|
+
(newValue, oldValue) => {
|
|
73
|
+
console.log(`Counter changed from ${oldValue} to ${newValue}`);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
73
76
|
|
|
74
77
|
// Store (Persistent Storage)
|
|
75
78
|
store.set('preferences', { theme: 'dark' });
|
|
@@ -80,7 +83,7 @@ session.set('token', 'user-jwt-token');
|
|
|
80
83
|
const token = session.get('token');
|
|
81
84
|
```
|
|
82
85
|
|
|
83
|
-
##
|
|
86
|
+
## API Reference
|
|
84
87
|
|
|
85
88
|
### State Management
|
|
86
89
|
|
|
@@ -113,20 +116,28 @@ Observe state changes with React-like syntax:
|
|
|
113
116
|
|
|
114
117
|
```javascript
|
|
115
118
|
// Basic observer
|
|
116
|
-
observer(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
observer(
|
|
120
|
+
'state.user',
|
|
121
|
+
(newValue, oldValue) => {
|
|
122
|
+
console.log('User updated:', newValue);
|
|
123
|
+
}
|
|
124
|
+
);
|
|
119
125
|
|
|
120
126
|
// With React useState
|
|
121
127
|
const [user, setUser] = useState();
|
|
122
|
-
observer(
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
observer(
|
|
129
|
+
'state.user',
|
|
130
|
+
() => {
|
|
131
|
+
setUser(state.user);
|
|
132
|
+
}
|
|
133
|
+
);
|
|
125
134
|
|
|
126
135
|
// With React useEffect
|
|
127
|
-
useEffect(
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
useEffect(
|
|
137
|
+
() => {
|
|
138
|
+
console.log('User changed:', user);
|
|
139
|
+
}, [user]
|
|
140
|
+
);
|
|
130
141
|
```
|
|
131
142
|
|
|
132
143
|
### Another example of use of Observer
|
|
@@ -189,10 +200,12 @@ Temporary storage that persists during page sessions:
|
|
|
189
200
|
|
|
190
201
|
```javascript
|
|
191
202
|
// Setting session data
|
|
192
|
-
session.set(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
203
|
+
session.set(
|
|
204
|
+
'userSession', {
|
|
205
|
+
id: 'user123',
|
|
206
|
+
lastActive: Date.now()
|
|
207
|
+
}
|
|
208
|
+
);
|
|
196
209
|
|
|
197
210
|
// Getting session data
|
|
198
211
|
const userData = session.get('userSession');
|
|
@@ -205,86 +218,13 @@ session.remove('userSession');
|
|
|
205
218
|
|
|
206
219
|
// Clearing all session data
|
|
207
220
|
session.removeAll();
|
|
208
|
-
|
|
209
|
-
// Remove all stored data if necessary
|
|
210
|
-
// store.removeAll();
|
|
211
|
-
|
|
212
|
-
return (
|
|
213
|
-
<div>
|
|
214
|
-
<h1 id="name">...</h1>
|
|
215
|
-
</div>
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export default App;
|
|
220
221
|
```
|
|
221
222
|
|
|
222
223
|
---
|
|
223
224
|
|
|
224
|
-
##
|
|
225
|
-
|
|
226
|
-
Session storage provides a way to store data for the duration of a page session. The data persists as long as the browser is open and survives over page reloads, but is lost when the browser tab or window is closed.
|
|
227
|
-
|
|
228
|
-
```js
|
|
229
|
-
// Set a session value:
|
|
230
|
-
session.set("userId", "12345")
|
|
231
|
-
|
|
232
|
-
// Get a session value:
|
|
233
|
-
session.get("userId") // Output: "12345"
|
|
225
|
+
## Testing
|
|
234
226
|
|
|
235
|
-
|
|
236
|
-
session.remove("userId")
|
|
237
|
-
|
|
238
|
-
// Get the number of items in session:
|
|
239
|
-
session.size() // Output: number of stored items
|
|
240
|
-
|
|
241
|
-
// Remove all session values:
|
|
242
|
-
session.removeAll()
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Example use Session in React
|
|
246
|
-
|
|
247
|
-
```js
|
|
248
|
-
import { useEffect } from 'react';
|
|
249
|
-
import 'memorio';
|
|
250
|
-
|
|
251
|
-
function UserSession() {
|
|
252
|
-
useEffect(() => {
|
|
253
|
-
// Store user session data
|
|
254
|
-
session.set('userSession', {
|
|
255
|
-
id: '12345',
|
|
256
|
-
lastActive: Date.now(),
|
|
257
|
-
preferences: {
|
|
258
|
-
theme: 'dark',
|
|
259
|
-
language: 'en'
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// Retrieve session data
|
|
264
|
-
const userData = session.get('userSession');
|
|
265
|
-
console.log('User session:', userData);
|
|
266
|
-
|
|
267
|
-
// Clean up on component unmount
|
|
268
|
-
return () => {
|
|
269
|
-
session.remove('userSession');
|
|
270
|
-
};
|
|
271
|
-
}, []);
|
|
272
|
-
|
|
273
|
-
return (
|
|
274
|
-
<div>
|
|
275
|
-
{/* Your component JSX */}
|
|
276
|
-
</div>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export default UserSession;
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
## ๐งช Testing
|
|
286
|
-
|
|
287
|
-
โ
All test suites are passing:
|
|
227
|
+
## Test suites are passing
|
|
288
228
|
|
|
289
229
|
- Basic functionality tests
|
|
290
230
|
- State management tests
|
|
@@ -294,26 +234,27 @@ export default UserSession;
|
|
|
294
234
|
|
|
295
235
|
Total: 25 tests passed across 5 test suites
|
|
296
236
|
|
|
297
|
-
##
|
|
237
|
+
## Security
|
|
298
238
|
|
|
299
239
|
Security scans and reports are available at:
|
|
240
|
+
|
|
300
241
|
- [Socket.dev](https://socket.dev/npm/package/memorio)
|
|
301
242
|
- [Snyk.io](https://security.snyk.io/package/npm/memorio)
|
|
302
243
|
|
|
303
|
-
##
|
|
244
|
+
## License
|
|
304
245
|
|
|
305
|
-
MIT
|
|
246
|
+
MIT (c) [Dario Passariello](https://dario.passariello.ca/)
|
|
306
247
|
|
|
307
248
|
---
|
|
308
249
|
|
|
309
|
-
##
|
|
250
|
+
## Contributing
|
|
310
251
|
|
|
311
252
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
312
253
|
|
|
313
|
-
##
|
|
254
|
+
## Support
|
|
314
255
|
|
|
315
256
|
Need help? Feel free to [open an issue](https://github.com/a51-dev/a51.memorio/issues).
|
|
316
257
|
|
|
317
258
|
---
|
|
318
259
|
|
|
319
|
-
Created with
|
|
260
|
+
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
|
+
"use strict";(()=>{var c={name:"memorio",version:"1.1.1",type:"module",main:"index.js",scripts:{build:"node ./esbuild.config.mjs",watch:"esbuild init.ts --bundle --outdir=dist --serve","-----------":"",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 .",updates:"npx npm-check-updates -u && npm i","----------":"","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.0","@typescript-eslint/eslint-plugin":"8.41.0","@typescript-eslint/parser":"8.41.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.2","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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorio",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"esbuild-plugin-clean": "^1.0.1",
|
|
85
85
|
"esbuild-plugin-copy": "^2.1.1",
|
|
86
86
|
"eslint": "9.34.0",
|
|
87
|
-
"jest": "30.
|
|
88
|
-
"jest-environment-jsdom": "30.
|
|
87
|
+
"jest": "30.1.2",
|
|
88
|
+
"jest-environment-jsdom": "30.1.2",
|
|
89
89
|
"ts-jest": "29.4.1",
|
|
90
90
|
"ts-loader": "^9.5.4",
|
|
91
91
|
"ts-node": "10.9.2",
|