memorio 4.5.0 โ†’ 4.6.4

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.
@@ -4,6 +4,77 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ## v4.6.1 (Security Patch) - 2026-08-14 โ€” CRITICAL Security Fix
8
+
9
+ ### ๐Ÿ” Security NOTICE (v4.6.0)
10
+
11
+ **CRITICAL**: A Gitea Personal Access Token was accidentally committed to `.npmrc` in v4.6.0
12
+
13
+ **Affected**: `v4.6.0` tag and all builds from that version
14
+
15
+ **Action Required**:
16
+ - **IMMEDIATE**: Revoke ALL tokens on Gitea Packages by admin access
17
+ - **GENERATE**: Create new PAT with scope `write:package` only
18
+ - **CONFIGURE**: Add as secret `PAT` in GitHub Actions or Gitea Actions
19
+ - **UPGRADE**: Use v4.6.1 where the token is replaced with `${PAT}` environment variable
20
+
21
+ The hardcoded token `2f398d5d7a734781e96108fdd0dbbabad41ef77a` has been removed in v4.6.1.
22
+
23
+ ### ๐Ÿ› Bug Fixes
24
+
25
+ - **SECURITY**: Removed hardcoded Gitea PAT from `.npmrc` (exposed token remediated)
26
+ - Replaced with environment variable `${PAT}` for secure authentication
27
+
28
+ ### ๐Ÿ“ Documentation Updates
29
+
30
+ - `.npmrc`: Token replaced with environment variable reference
31
+ - `.gitea/workflows/npm.yml`: Configured to use secrets `GITEA_USER` and `PAT`
32
+
33
+ ---
34
+
35
+ ## v4.6.0 (Previous - SECURITY ISSUE) - 2026-08-13 โ€” Refactoring & Documentation
36
+
37
+ **โš ๏ธ WARNING**: This version had a hardcoded PAT token that was later remediated in v4.6.1**
38
+
39
+ ### ๐Ÿ› Bug Fixes
40
+
41
+ - Fixed circular import in `idb/index.ts` โ†’ `core/global`
42
+ - Fixed dead `globalThis._propertyAccessLog` reference in `observer`
43
+ - Fixed `dispatch.remove(f)` tuple bug in `functions/dispatch.ts`
44
+ - Fixed `logger.isDebugEnabled` using wrong module reference
45
+ - Removed dead `propertyAccessLog` / `pushPropertyAccess` from `core/internal.ts`
46
+ - Removed duplicate path-tracking block in `state` get handler
47
+ - Removed redundant `?? key` fallback in `state` set handler
48
+
49
+ ### ๐Ÿ”ง Code Refactoring
50
+
51
+ - **Self-contained modules**: All modules now work independently without internal `globalThis.memorio.*` reads/writes
52
+ - **Module-local state**: Created `core/internal.ts` for module-local singletons
53
+ - **Bootstrap-only global**: `core/global.ts` now only publishes to `globalThis.memorio` at initialization
54
+ - **Removed dead code**: `core/constructor.ts` deleted (unused)
55
+ - **Extracted helpers**: `_read`/`_write`/`_remove` in `store` and `session` to eliminate duplication
56
+ - **Fixed circular imports**: `dispatch` โ†’ `observer` via `globalThis.events`
57
+
58
+ ### ๐Ÿ“ Documentation Updates
59
+
60
+ - `docs/README.md`: Added Classic `import { state } from 'memorio'` section, improved badges layout, enhanced "Why memorio?" comparison table
61
+ - `docs/markdown/STORE.md`: Added classic import note
62
+ - `docs/markdown/IMPORT.md`: New file for named export guide
63
+ - `docs/SUMMARY.md`: Updated to include `IMPORT.md`
64
+ - `README.md`: Badge corrections, header cleanup, removed unverified bundle size claims
65
+
66
+ ### ๐Ÿ†• GitHub Actions / Gitea Workflows
67
+
68
+ - Added `.gitea/workflows/npm.yml` for automatic npm package publishing to Gitea Packages on `v*` tags
69
+ - Requires `GITEA_USER` and `PAT` secrets
70
+
71
+ ### ๐Ÿงช Tests
72
+
73
+ - **Result: 9 suites ยท 101 passed ยท 4 skipped ยท 1 todo**
74
+ - All lint and typecheck clean
75
+
76
+ ---
77
+
7
78
  ## v3.0.2 (Current) - 2026-05-19 โ€” Bug Fix, Security & API Expansion
8
79
 
9
80
  ### ๐Ÿ› Bug Fixes
@@ -0,0 +1,139 @@
1
+ # Classic `import` support
2
+
3
+ Memorio supports two equivalent styles: the original global side-effect import,
4
+ and the new named exports. Both share the same instances (one source of truth).
5
+
6
+ ```typescript
7
+ // Global style (original)
8
+ import 'memorio'
9
+ state.user = { name: 'Sara' }
10
+
11
+ // Classic import style (new)
12
+ import { state } from 'memorio'
13
+ state.user = { name: 'Sara' }
14
+ ```
15
+
16
+ `state` in both examples is the exact same Proxy object.
17
+
18
+ ---
19
+
20
+ ## Why two styles?
21
+
22
+ | Style | When to use |
23
+ |-------|-------------|
24
+ | `import 'memorio'` | Zero-config, global access everywhere, legacy scripts |
25
+ | `import { state } from 'memorio'` | Explicit dependencies, tree-shakeable bundles, TypeScript IntelliSense |
26
+
27
+ ---
28
+
29
+ ## ESM named imports
30
+
31
+ All modules are available as named exports:
32
+
33
+ ```typescript
34
+ import {
35
+ state,
36
+ store,
37
+ session,
38
+ cache,
39
+ idb,
40
+ observer,
41
+ useObserver,
42
+ dispatch,
43
+ message,
44
+ devtools,
45
+ logger
46
+ } from 'memorio'
47
+ ```
48
+
49
+ Platform helpers:
50
+
51
+ ```typescript
52
+ import {
53
+ isBrowser,
54
+ isNode,
55
+ isDeno,
56
+ isEdge,
57
+ getCapabilities,
58
+ createContext,
59
+ listContexts,
60
+ deleteContext
61
+ } from 'memorio'
62
+ ```
63
+
64
+ Internal utilities (for tests/debug):
65
+
66
+ ```typescript
67
+ import internal, { propertyName } from 'memorio'
68
+ import { setContext, getContext } from 'memorio'
69
+ ```
70
+
71
+ Default export (the public `memorio` namespace):
72
+
73
+ ```typescript
74
+ import memorio from 'memorio'
75
+ memorio.help()
76
+ ```
77
+
78
+ ---
79
+
80
+ ## CJS usage
81
+
82
+ ```javascript
83
+ const { state, store, memorio } = require('memorio')
84
+ ```
85
+
86
+ ---
87
+
88
+ ## React / useObserver
89
+
90
+ `useObserver` works the same way via named import:
91
+
92
+ ```tsx
93
+ import { useObserver, state } from 'memorio'
94
+
95
+ function Counter() {
96
+ const [, forceUpdate] = useReducer(x => x + 1, 0)
97
+
98
+ useObserver(forceUpdate, [state.counter])
99
+
100
+ return <div>Count: {state.counter}</div>
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Context isolation
107
+
108
+ ```typescript
109
+ import { createContext, listContexts, deleteContext, isolate } from 'memorio'
110
+
111
+ const ctx = createContext('tenant-123')
112
+ ctx.state.user = { name: 'Isolated' }
113
+ ctx.store.set('settings', { theme: 'dark' })
114
+
115
+ listContexts() // ['tenant-123']
116
+ deleteContext('tenant-123')
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Same-instance guarantee
122
+
123
+ Named exports point to the same instances published on `globalThis` by
124
+ `core/global` at bootstrap. Mutating via named export mutates the global,
125
+ and vice versa.
126
+
127
+ ```typescript
128
+ import { state } from 'memorio'
129
+
130
+ state.importedFlag = true
131
+ console.debug(globalThis.state.importedFlag) // true
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Migration from global-only
137
+
138
+ No code changes required. Existing `import 'memorio'` + `state.foo = 1`
139
+ continues to work unchanged. Named exports are additive.
@@ -41,8 +41,8 @@ Memorio automatically detects the environment on import:
41
41
  import 'memorio';
42
42
 
43
43
  // Check current platform
44
- console.debug(memorio.platform); // 'browser' | 'node' | 'deno' | 'edge'
45
- console.debug(memorio.isPersistent); // true if using real storage
44
+ console.debug(memorio.getCapabilities().platform); // 'browser' | 'node' | 'deno' | 'edge'
45
+ console.debug(store.isPersistent); // true if using real localStorage
46
46
  ```
47
47
 
48
48
  ### Available Platform APIs
@@ -257,5 +257,9 @@ Same as browser - localStorage and sessionStorage are available.
257
257
  | Property | Type | Description |
258
258
  |----------|------|-------------|
259
259
  | `memorio.version` | `string` | Memorio version |
260
- | `memorio.platform` | `string` | Current platform |
260
+ | `memorio.getCapabilities().platform` | `string` | Current platform |
261
+ | `memorio.isBrowser()` / `isNode()` / `isDeno()` / `isEdge()` | `boolean` | Platform checks |
261
262
  | `memorio._sessionId` | `string` | Unique session identifier |
263
+
264
+ > **Classic `import`**: context APIs are also named exports.
265
+ > `import { createContext, listContexts, deleteContext, isolate } from 'memorio'`.
package/markdown/STATE.md CHANGED
@@ -16,6 +16,9 @@ import 'memorio';
16
16
 
17
17
  That's it. `state` is now global.
18
18
 
19
+ > **Classic `import`**: `state` is also a named export.
20
+ > `import { state } from 'memorio'` returns the exact same proxy as `globalThis.state`.
21
+
19
22
  ---
20
23
 
21
24
  ## Quick Examples
package/markdown/STORE.md CHANGED
@@ -15,6 +15,9 @@ npm install memorio
15
15
  import 'memorio';
16
16
  ```
17
17
 
18
+ > **Classic `import`**: `store` is also a named export.
19
+ > `import { store } from 'memorio'` returns the exact same instance as `globalThis.store`.
20
+
18
21
  ---
19
22
 
20
23
  ## Quick Examples
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "memorio",
3
3
  "codeName": "memorio",
4
- "version": "4.5.0",
4
+ "version": "4.6.4",
5
5
  "description": "Memorio, State + Observer, Store and iDB for an easy life - Cross-platform compatible",
6
6
  "main": "./index.cjs",
7
- "browser": "./index.cjs",
7
+ "browser": "./index.js",
8
8
  "module": "./index.js",
9
+ "type": "module",
9
10
  "types": "./index.d.ts",
10
11
  "typing": "./types/*",
11
12
  "license": "MIT",
@@ -50,6 +51,10 @@
50
51
  "files": [
51
52
  "**/*"
52
53
  ],
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "sideEffects": true,
53
58
  "support": {
54
59
  "name": "Dario Passariello",
55
60
  "url": "https://dario.passariello.ca/",
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Named exports for classic `import` usage.
3
+ *
4
+ * Every export below points to the exact same instance
5
+ * already defined on globalThis by the core modules.
6
+ * `import { state } from 'memorio'` === `globalThis.state`.
7
+ *
8
+ * @see index.ts (runtime re-export)
9
+ */
10
+
11
+ /// <reference path="./memorio.d.ts" />
12
+ /// <reference path="./state.d.ts" />
13
+ /// <reference path="./store.d.ts" />
14
+ /// <reference path="./session.d.ts" />
15
+ /// <reference path="./cache.d.ts" />
16
+ /// <reference path="./idb.d.ts" />
17
+ /// <reference path="./observer.d.ts" />
18
+ /// <reference path="./useObserver.d.ts" />
19
+
20
+ export const memorio: _memorio
21
+ export const state: _state
22
+ export const store: _store
23
+ export const session: _session
24
+ export const cache: _cache
25
+ export const idb: _idb
26
+ export const observer: _observer
27
+ export const useObserver: _useObserver
28
+ export const dispatch: _dispatch
29
+ export const events: Record<string, any>
30
+
31
+ export const isBrowser: () => boolean
32
+ export const isNode: () => boolean
33
+ export const isDeno: () => boolean
34
+ export const isEdge: () => boolean
35
+ export const getCapabilities: (...args: unknown[]) => any
36
+ export const createContext: _memorio['createContext']
37
+ export const listContexts: _memorio['listContexts']
38
+ export const deleteContext: _memorio['deleteContext']
39
+ export const isolate: _memorio['isolate']
40
+ export const message: (...args: unknown[]) => void
41
+ export const help: () => void
42
+
43
+ export const propertyName: (container: any, object: any) => string | null
44
+ export const internal: {
45
+ debug: boolean
46
+ tracking: boolean
47
+ trackedPaths: Set<string>
48
+ locked: boolean
49
+ lastAccessedPath: string
50
+ stateVersion: number
51
+ currentContext: string | null
52
+ clearTrackedPaths(): void
53
+ bumpStateVersion(): number
54
+ }
55
+ export const setContext: (id: string) => void
56
+ export const getContext: () => string | null
57
+
58
+ export default memorio