ustor 0.0.9 → 0.2.0
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/LICENSE +21 -0
- package/README.md +585 -142
- package/dist/index.cjs +125 -0
- package/dist/index.es.js +119 -26
- package/dist/index.min.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/react.cjs +1 -0
- package/dist/react.es.js +1 -0
- package/package.json +59 -19
- package/types/index.d.ts +30 -0
- package/types/react.d.ts +17 -0
- package/dist/index.js +0 -32
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = {};
|
|
4
|
+
const _s = Symbol();
|
|
5
|
+
const cache = new WeakMap();
|
|
6
|
+
const mutators = /^(copyWithin|fill|pop|push|reverse|shift|sort|splice|unshift)$/;
|
|
7
|
+
|
|
8
|
+
const is = (v) => !!v?.[_s];
|
|
9
|
+
const isObject = (v) => {
|
|
10
|
+
const proto = v && Object.getPrototypeOf(v);
|
|
11
|
+
return v != null && (proto === null || proto?.constructor === Object);
|
|
12
|
+
};
|
|
13
|
+
const resolve = (v) => Array.isArray(v) || isObject(v) ? store(v) : v;
|
|
14
|
+
|
|
15
|
+
const arrayStore = (values) => {
|
|
16
|
+
const version = api.signal(0);
|
|
17
|
+
let depth = 0,
|
|
18
|
+
changed = false;
|
|
19
|
+
const track = () => api.get(version);
|
|
20
|
+
const notify = () => {
|
|
21
|
+
changed = false;
|
|
22
|
+
api.set(version, api.get(version) + 1);
|
|
23
|
+
};
|
|
24
|
+
const proxy = new Proxy(values, {
|
|
25
|
+
get: (target, key, receiver) => {
|
|
26
|
+
if (key === _s) return true;
|
|
27
|
+
track();
|
|
28
|
+
const value = Reflect.get(target, key, receiver);
|
|
29
|
+
if (typeof key === "string" && mutators.test(key) && typeof value === "function") {
|
|
30
|
+
return (...args) => {
|
|
31
|
+
depth++;
|
|
32
|
+
try {
|
|
33
|
+
return value.apply(receiver, args);
|
|
34
|
+
} finally {
|
|
35
|
+
if (!--depth && changed) notify();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
},
|
|
41
|
+
set: (target, key, value) => {
|
|
42
|
+
const next = resolve(value);
|
|
43
|
+
if (Object.is(target[key], next)) return true;
|
|
44
|
+
if (!Reflect.set(target, key, next)) return false;
|
|
45
|
+
if (depth) changed = true;
|
|
46
|
+
else notify();
|
|
47
|
+
return true;
|
|
48
|
+
},
|
|
49
|
+
deleteProperty: (target, key) => {
|
|
50
|
+
if (!Object.hasOwn(target, key)) return true;
|
|
51
|
+
if (!Reflect.deleteProperty(target, key)) return false;
|
|
52
|
+
if (depth) changed = true;
|
|
53
|
+
else notify();
|
|
54
|
+
return true;
|
|
55
|
+
},
|
|
56
|
+
ownKeys: (target) => {
|
|
57
|
+
track();
|
|
58
|
+
return Reflect.ownKeys(target);
|
|
59
|
+
},
|
|
60
|
+
has: (target, key) => {
|
|
61
|
+
track();
|
|
62
|
+
return Reflect.has(target, key);
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
cache.set(values, proxy);
|
|
66
|
+
values.forEach((item, i) => {
|
|
67
|
+
values[i] = resolve(item);
|
|
68
|
+
});
|
|
69
|
+
return proxy;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const objectStore = (values, proto) => {
|
|
73
|
+
const state = Object.create(proto === undefined ? Object.getPrototypeOf(values) : proto);
|
|
74
|
+
cache.set(values, state);
|
|
75
|
+
Reflect.ownKeys(values).forEach((key) => {
|
|
76
|
+
const desc = Object.getOwnPropertyDescriptor(values, key),
|
|
77
|
+
accessor = desc.get || desc.set,
|
|
78
|
+
getter = desc.get?.bind(state),
|
|
79
|
+
memoize = getter && api.memo,
|
|
80
|
+
signal = accessor ? undefined : api.is(desc.value) ? desc.value : api.signal(resolve(desc.value));
|
|
81
|
+
let memo;
|
|
82
|
+
const getSignal = () => getter ? (memo ||= memoize(getter)) : signal;
|
|
83
|
+
Object.defineProperty(state, key, {
|
|
84
|
+
get: accessor
|
|
85
|
+
? getter
|
|
86
|
+
? () => memoize ? (api.getMemo || api.get)(getSignal()) : getter()
|
|
87
|
+
: undefined
|
|
88
|
+
: () => api.get(signal),
|
|
89
|
+
set: accessor
|
|
90
|
+
? desc.set?.bind(state)
|
|
91
|
+
: desc.writable === false
|
|
92
|
+
? undefined
|
|
93
|
+
: (v) => api.set(signal, resolve(v)),
|
|
94
|
+
enumerable: desc.enumerable,
|
|
95
|
+
});
|
|
96
|
+
if (
|
|
97
|
+
(!accessor || memoize) &&
|
|
98
|
+
typeof key === "string" &&
|
|
99
|
+
!key.startsWith("$") &&
|
|
100
|
+
!Object.hasOwn(values, "$" + key)
|
|
101
|
+
) {
|
|
102
|
+
Object.defineProperty(state, "$" + key, {
|
|
103
|
+
get: getSignal,
|
|
104
|
+
enumerable: false,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
Object.defineProperty(state, _s, { value: true });
|
|
109
|
+
return Object.seal(state);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const store = (values, proto) => {
|
|
113
|
+
if (is(values)) return values;
|
|
114
|
+
if (!Array.isArray(values) && !isObject(values)) return values;
|
|
115
|
+
const cached = cache.get(values);
|
|
116
|
+
if (cached) return cached;
|
|
117
|
+
if (!(api.signal && api.get && api.set && api.is)) {
|
|
118
|
+
throw new Error("ustor: configure api.signal, api.get, api.set and api.is");
|
|
119
|
+
}
|
|
120
|
+
return Array.isArray(values) ? arrayStore(values) : objectStore(values, proto);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
exports.api = api;
|
|
124
|
+
exports.is = is;
|
|
125
|
+
exports.store = store;
|
package/dist/index.es.js
CHANGED
|
@@ -1,28 +1,121 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
1
|
+
const api = {};
|
|
2
|
+
const _s = Symbol();
|
|
3
|
+
const cache = new WeakMap();
|
|
4
|
+
const mutators = /^(copyWithin|fill|pop|push|reverse|shift|sort|splice|unshift)$/;
|
|
5
|
+
|
|
6
|
+
const is = (v) => !!v?.[_s];
|
|
7
|
+
const isObject = (v) => {
|
|
8
|
+
const proto = v && Object.getPrototypeOf(v);
|
|
9
|
+
return v != null && (proto === null || proto?.constructor === Object);
|
|
10
|
+
};
|
|
11
|
+
const resolve = (v) => Array.isArray(v) || isObject(v) ? store(v) : v;
|
|
12
|
+
|
|
13
|
+
const arrayStore = (values) => {
|
|
14
|
+
const version = api.signal(0);
|
|
15
|
+
let depth = 0,
|
|
16
|
+
changed = false;
|
|
17
|
+
const track = () => api.get(version);
|
|
18
|
+
const notify = () => {
|
|
19
|
+
changed = false;
|
|
20
|
+
api.set(version, api.get(version) + 1);
|
|
21
|
+
};
|
|
22
|
+
const proxy = new Proxy(values, {
|
|
23
|
+
get: (target, key, receiver) => {
|
|
24
|
+
if (key === _s) return true;
|
|
25
|
+
track();
|
|
26
|
+
const value = Reflect.get(target, key, receiver);
|
|
27
|
+
if (typeof key === "string" && mutators.test(key) && typeof value === "function") {
|
|
28
|
+
return (...args) => {
|
|
29
|
+
depth++;
|
|
30
|
+
try {
|
|
31
|
+
return value.apply(receiver, args);
|
|
32
|
+
} finally {
|
|
33
|
+
if (!--depth && changed) notify();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
},
|
|
39
|
+
set: (target, key, value) => {
|
|
40
|
+
const next = resolve(value);
|
|
41
|
+
if (Object.is(target[key], next)) return true;
|
|
42
|
+
if (!Reflect.set(target, key, next)) return false;
|
|
43
|
+
if (depth) changed = true;
|
|
44
|
+
else notify();
|
|
45
|
+
return true;
|
|
46
|
+
},
|
|
47
|
+
deleteProperty: (target, key) => {
|
|
48
|
+
if (!Object.hasOwn(target, key)) return true;
|
|
49
|
+
if (!Reflect.deleteProperty(target, key)) return false;
|
|
50
|
+
if (depth) changed = true;
|
|
51
|
+
else notify();
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
ownKeys: (target) => {
|
|
55
|
+
track();
|
|
56
|
+
return Reflect.ownKeys(target);
|
|
57
|
+
},
|
|
58
|
+
has: (target, key) => {
|
|
59
|
+
track();
|
|
60
|
+
return Reflect.has(target, key);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
cache.set(values, proxy);
|
|
64
|
+
values.forEach((item, i) => {
|
|
65
|
+
values[i] = resolve(item);
|
|
66
|
+
});
|
|
67
|
+
return proxy;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const objectStore = (values, proto) => {
|
|
71
|
+
const state = Object.create(proto === undefined ? Object.getPrototypeOf(values) : proto);
|
|
72
|
+
cache.set(values, state);
|
|
73
|
+
Reflect.ownKeys(values).forEach((key) => {
|
|
74
|
+
const desc = Object.getOwnPropertyDescriptor(values, key),
|
|
75
|
+
accessor = desc.get || desc.set,
|
|
76
|
+
getter = desc.get?.bind(state),
|
|
77
|
+
memoize = getter && api.memo,
|
|
78
|
+
signal = accessor ? undefined : api.is(desc.value) ? desc.value : api.signal(resolve(desc.value));
|
|
79
|
+
let memo;
|
|
80
|
+
const getSignal = () => getter ? (memo ||= memoize(getter)) : signal;
|
|
81
|
+
Object.defineProperty(state, key, {
|
|
82
|
+
get: accessor
|
|
83
|
+
? getter
|
|
84
|
+
? () => memoize ? (api.getMemo || api.get)(getSignal()) : getter()
|
|
85
|
+
: undefined
|
|
86
|
+
: () => api.get(signal),
|
|
87
|
+
set: accessor
|
|
88
|
+
? desc.set?.bind(state)
|
|
89
|
+
: desc.writable === false
|
|
90
|
+
? undefined
|
|
91
|
+
: (v) => api.set(signal, resolve(v)),
|
|
92
|
+
enumerable: desc.enumerable,
|
|
93
|
+
});
|
|
94
|
+
if (
|
|
95
|
+
(!accessor || memoize) &&
|
|
96
|
+
typeof key === "string" &&
|
|
97
|
+
!key.startsWith("$") &&
|
|
98
|
+
!Object.hasOwn(values, "$" + key)
|
|
99
|
+
) {
|
|
100
|
+
Object.defineProperty(state, "$" + key, {
|
|
101
|
+
get: getSignal,
|
|
102
|
+
enumerable: false,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
Object.defineProperty(state, _s, { value: true });
|
|
107
|
+
return Object.seal(state);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const store = (values, proto) => {
|
|
111
|
+
if (is(values)) return values;
|
|
112
|
+
if (!Array.isArray(values) && !isObject(values)) return values;
|
|
113
|
+
const cached = cache.get(values);
|
|
114
|
+
if (cached) return cached;
|
|
115
|
+
if (!(api.signal && api.get && api.set && api.is)) {
|
|
116
|
+
throw new Error("ustor: configure api.signal, api.get, api.set and api.is");
|
|
117
|
+
}
|
|
118
|
+
return Array.isArray(values) ? arrayStore(values) : objectStore(values, proto);
|
|
119
|
+
};
|
|
27
120
|
|
|
28
121
|
export { api, is, store };
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var ustor=function(e){
|
|
1
|
+
var ustor=function(e){const t={},r=Symbol(),n=new WeakMap,s=/^(copyWithin|fill|pop|push|reverse|shift|sort|splice|unshift)$/,o=e=>!!e?.[r],i=e=>{const t=e&&Object.getPrototypeOf(e);return null!=e&&(null===t||t?.constructor===Object)},c=e=>Array.isArray(e)||i(e)?a(e):e,a=(e,a)=>{if(o(e))return e;if(!Array.isArray(e)&&!i(e))return e;const l=n.get(e);if(l)return l;if(!(t.signal&&t.get&&t.set&&t.is))throw new Error("ustor: configure api.signal, api.get, api.set and api.is");return Array.isArray(e)?(e=>{const o=t.signal(0);let i=0,a=!1;const l=()=>t.get(o),u=()=>{a=!1,t.set(o,t.get(o)+1)},f=new Proxy(e,{get:(e,t,n)=>{if(t===r)return!0;l();const o=Reflect.get(e,t,n);return"string"==typeof t&&s.test(t)&&"function"==typeof o?(...e)=>{i++;try{return o.apply(n,e)}finally{! --i&&a&&u()}}:o},set:(e,t,r)=>{const n=c(r);return!!Object.is(e[t],n)||!!Reflect.set(e,t,n)&&(i?a=!0:u(),!0)},deleteProperty:(e,t)=>!Object.hasOwn(e,t)||!!Reflect.deleteProperty(e,t)&&(i?a=!0:u(),!0),ownKeys:e=>(l(),Reflect.ownKeys(e)),has:(e,t)=>(l(),Reflect.has(e,t))});return n.set(e,f),e.forEach(((t,r)=>{e[r]=c(t)})),f})(e):((e,s)=>{const o=Object.create(void 0===s?Object.getPrototypeOf(e):s);return n.set(e,o),Reflect.ownKeys(e).forEach((r=>{const n=Object.getOwnPropertyDescriptor(e,r),s=n.get||n.set,i=n.get?.bind(o),a=i&&t.memo,l=s?void 0:t.is(n.value)?n.value:t.signal(c(n.value));let u;const f=()=>i?u||=a(i):l;Object.defineProperty(o,r,{get:s?i?()=>a?(t.getMemo||t.get)(f()):i():void 0:()=>t.get(l),set:s?n.set?.bind(o):!1===n.writable?void 0:e=>t.set(l,c(e)),enumerable:n.enumerable}),s&&!a||"string"!=typeof r||r.startsWith("$")||Object.hasOwn(e,"$"+r)||Object.defineProperty(o,"$"+r,{get:f,enumerable:!1})})),Object.defineProperty(o,r,{value:!0}),Object.seal(o)})(e,a)};return e.api=t,e.is=o,e.store=a,e}({});
|
package/dist/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ustor={})}(this,(function(e){
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ustor={})}(this,(function(e){const t={},r=Symbol(),n=new WeakMap,s=/^(copyWithin|fill|pop|push|reverse|shift|sort|splice|unshift)$/,o=e=>!!e?.[r],i=e=>{const t=e&&Object.getPrototypeOf(e);return null!=e&&(null===t||t?.constructor===Object)},c=e=>Array.isArray(e)||i(e)?a(e):e,a=(e,a)=>{if(o(e))return e;if(!Array.isArray(e)&&!i(e))return e;const f=n.get(e);if(f)return f;if(!(t.signal&&t.get&&t.set&&t.is))throw new Error("ustor: configure api.signal, api.get, api.set and api.is");return Array.isArray(e)?(e=>{const o=t.signal(0);let i=0,a=!1;const f=()=>t.get(o),l=()=>{a=!1,t.set(o,t.get(o)+1)},u=new Proxy(e,{get:(e,t,n)=>{if(t===r)return!0;f();const o=Reflect.get(e,t,n);return"string"==typeof t&&s.test(t)&&"function"==typeof o?(...e)=>{i++;try{return o.apply(n,e)}finally{! --i&&a&&l()}}:o},set:(e,t,r)=>{const n=c(r);return!!Object.is(e[t],n)||!!Reflect.set(e,t,n)&&(i?a=!0:l(),!0)},deleteProperty:(e,t)=>!Object.hasOwn(e,t)||!!Reflect.deleteProperty(e,t)&&(i?a=!0:l(),!0),ownKeys:e=>(f(),Reflect.ownKeys(e)),has:(e,t)=>(f(),Reflect.has(e,t))});return n.set(e,u),e.forEach(((t,r)=>{e[r]=c(t)})),u})(e):((e,s)=>{const o=Object.create(void 0===s?Object.getPrototypeOf(e):s);return n.set(e,o),Reflect.ownKeys(e).forEach((r=>{const n=Object.getOwnPropertyDescriptor(e,r),s=n.get||n.set,i=n.get?.bind(o),a=i&&t.memo,f=s?void 0:t.is(n.value)?n.value:t.signal(c(n.value));let l;const u=()=>i?l||=a(i):f;Object.defineProperty(o,r,{get:s?i?()=>a?(t.getMemo||t.get)(u()):i():void 0:()=>t.get(f),set:s?n.set?.bind(o):!1===n.writable?void 0:e=>t.set(f,c(e)),enumerable:n.enumerable}),s&&!a||"string"!=typeof r||r.startsWith("$")||Object.hasOwn(e,"$"+r)||Object.defineProperty(o,"$"+r,{get:u,enumerable:!1})})),Object.defineProperty(o,r,{value:!0}),Object.seal(o)})(e,a)};e.api=t,e.is=o,e.store=a}));
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("react");const r={},t=t=>{const c=e.useCallback((e=>{if(!r.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let c=!0;return r.effect((()=>{t(),c?c=!1:e()}))}),[t]);return e.useSyncExternalStore(c,t,t)};exports.useSignal=c=>{const s=e.useCallback((()=>r.get(c)),[c]);return t(s)},exports.useStore=t;
|
package/dist/react.es.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useCallback as t,useSyncExternalStore as r}from"react";const e={},o=o=>{const c=t((t=>{if(!e.effect)throw new Error("ustor/react: configure api.effect with cleanup support");let r=!0;return e.effect((()=>{o(),r?r=!1:t()}))}),[o]);return r(c,o,o)},c=r=>{const c=t((()=>e.get(r)),[r]);return o(c)};export{c as useSignal,o as useStore};
|
package/package.json
CHANGED
|
@@ -1,43 +1,75 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ustor",
|
|
3
|
-
"description": "A
|
|
4
|
-
"version": "0.0
|
|
3
|
+
"description": "A tiny, dependency-free reactive store with pluggable signal adapters and optional React hooks.",
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"source": "./src/index.js",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.es.js",
|
|
9
10
|
"unpkg": "./dist/index.min.js",
|
|
10
11
|
"umd:main": "./dist/index.umd.js",
|
|
12
|
+
"sideEffects": false,
|
|
11
13
|
"exports": {
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./types/index.d.ts",
|
|
16
|
+
"browser": "./dist/index.es.js",
|
|
17
|
+
"import": "./dist/index.es.js",
|
|
18
|
+
"require": "./dist/index.cjs",
|
|
19
|
+
"default": "./dist/index.es.js"
|
|
20
|
+
},
|
|
21
|
+
"./react": {
|
|
22
|
+
"types": "./types/react.d.ts",
|
|
23
|
+
"import": "./dist/react.es.js",
|
|
24
|
+
"require": "./dist/react.cjs",
|
|
25
|
+
"default": "./dist/react.es.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json"
|
|
17
28
|
},
|
|
18
29
|
"repository": {
|
|
19
30
|
"type": "git",
|
|
20
31
|
"url": "git+https://github.com/kethan/ustor.git"
|
|
21
32
|
},
|
|
22
33
|
"files": [
|
|
23
|
-
"dist"
|
|
34
|
+
"dist",
|
|
35
|
+
"types"
|
|
24
36
|
],
|
|
25
37
|
"scripts": {
|
|
26
|
-
"build": "rollup --config rollup.config.js",
|
|
27
|
-
"test": "vitest"
|
|
38
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && rollup --config rollup.config.js",
|
|
39
|
+
"test": "npm run build && npm run typecheck && vitest --run && node test.package.cjs",
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.nodenext.json",
|
|
41
|
+
"test:watch": "vitest",
|
|
42
|
+
"test:coverage": "vitest --run --coverage",
|
|
43
|
+
"profile": "node --expose-gc scripts/profile.mjs",
|
|
44
|
+
"profile:smoke": "node --expose-gc scripts/profile.mjs --updates=5000 --array-updates=500 --seconds=0.5 --cycles=500 --sample-ms=100",
|
|
45
|
+
"prepack": "npm run build"
|
|
28
46
|
},
|
|
29
47
|
"devDependencies": {
|
|
30
|
-
"@preact/signals-core": "^1.
|
|
31
|
-
"@rollup/plugin-terser": "^0.
|
|
48
|
+
"@preact/signals-core": "^1.14.4",
|
|
49
|
+
"@rollup/plugin-terser": "^1.0.2",
|
|
50
|
+
"@tanstack/store": "^0.11.2",
|
|
51
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
52
|
+
"@vue/reactivity": "^3.5.44",
|
|
53
|
+
"@webreflection/alien-signals": "^0.4.2",
|
|
54
|
+
"@webreflection/signal": "^2.1.2",
|
|
55
|
+
"@webreflection/signals": "^0.2.8",
|
|
56
|
+
"alien-signals": "^3.2.1",
|
|
57
|
+
"jsdom": "^30.1.3",
|
|
58
|
+
"mobx": "^7.1.1",
|
|
59
|
+
"nanostores": "^1.5.5",
|
|
32
60
|
"oby": "^15.1.2",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
61
|
+
"react": "^19.3.1",
|
|
62
|
+
"react-dom": "^19.3.1",
|
|
63
|
+
"rollup": "^4.65.0",
|
|
35
64
|
"rollup-plugin-bundle-size": "^1.0.3",
|
|
65
|
+
"rxjs": "^7.8.2",
|
|
36
66
|
"s-js": "^0.4.9",
|
|
37
67
|
"sinuous": "^0.32.1",
|
|
38
|
-
"solid-js": "^1.9.
|
|
68
|
+
"solid-js": "^1.9.17",
|
|
69
|
+
"typescript": "^7.0.2",
|
|
39
70
|
"ulive": "^1.0.7",
|
|
40
|
-
"
|
|
71
|
+
"usignal": "^0.10.0",
|
|
72
|
+
"vitest": "^5.0.5"
|
|
41
73
|
},
|
|
42
74
|
"keywords": [
|
|
43
75
|
"ustor",
|
|
@@ -53,7 +85,15 @@
|
|
|
53
85
|
"reactive"
|
|
54
86
|
],
|
|
55
87
|
"author": "Kethan Surana",
|
|
56
|
-
"license": "
|
|
88
|
+
"license": "MIT",
|
|
89
|
+
"peerDependencies": {
|
|
90
|
+
"react": ">=18"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"react": {
|
|
94
|
+
"optional": true
|
|
95
|
+
}
|
|
96
|
+
},
|
|
57
97
|
"bugs": {
|
|
58
98
|
"url": "https://github.com/kethan/ustor/issues"
|
|
59
99
|
},
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SignalApi<Signal = any, Memo = any> {
|
|
2
|
+
signal(value: any): Signal;
|
|
3
|
+
get(signal: Signal): any;
|
|
4
|
+
set(signal: Signal, value: any): void;
|
|
5
|
+
is(value: unknown): boolean;
|
|
6
|
+
memo?(fn: () => any): Memo;
|
|
7
|
+
getMemo?(memo: Memo): any;
|
|
8
|
+
effect?(fn: () => void): () => void;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type SignalAliases<T> = T extends readonly unknown[] ? unknown : {
|
|
13
|
+
readonly [K in keyof T as K extends string
|
|
14
|
+
? K extends `$${string}` ? never : `$${K}`
|
|
15
|
+
: never]?: any;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type Store<T> = T extends (...args: any[]) => any
|
|
19
|
+
? T
|
|
20
|
+
: T extends readonly unknown[]
|
|
21
|
+
? { [K in keyof T]: Store<T[K]> }
|
|
22
|
+
: T extends object
|
|
23
|
+
? { [K in keyof T]: Store<T[K]> } & SignalAliases<T>
|
|
24
|
+
: T;
|
|
25
|
+
|
|
26
|
+
export declare const api: SignalApi;
|
|
27
|
+
|
|
28
|
+
export declare function is(value: unknown): value is object;
|
|
29
|
+
|
|
30
|
+
export declare function store<T>(values: T, proto?: object | null): Store<T>;
|
package/types/react.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SignalValue<Signal> = Signal extends { state: readonly (infer Value)[] }
|
|
2
|
+
? Value
|
|
3
|
+
: Signal extends { value: infer Value }
|
|
4
|
+
? Value
|
|
5
|
+
: Signal extends { get(): infer Value }
|
|
6
|
+
? Value
|
|
7
|
+
: Signal extends () => infer Value
|
|
8
|
+
? Value
|
|
9
|
+
: Signal extends readonly [() => infer Value, ...any[]]
|
|
10
|
+
? Value
|
|
11
|
+
: unknown;
|
|
12
|
+
|
|
13
|
+
/** Subscribe to a selector that returns a primitive or stable reference. */
|
|
14
|
+
export declare function useStore<Value>(selector: () => Value): Value;
|
|
15
|
+
|
|
16
|
+
/** Subscribe to one underlying signal exposed as state.$property. */
|
|
17
|
+
export declare function useSignal<Signal>(signal: Signal): SignalValue<Signal>;
|
package/dist/index.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
let api = {},
|
|
4
|
-
_s = Symbol("s"),
|
|
5
|
-
is = (v) => v[_s],
|
|
6
|
-
isObject = (v) => v && v.constructor === Object,
|
|
7
|
-
resolve = (v) => Array.isArray(v) ? store(v) : isObject(v) ? Object.seal(store(v)) : v,
|
|
8
|
-
store = (values, proto) => {
|
|
9
|
-
if ((is(values) && !proto) || !(api.signal && api.get && api.set && api.is)) return values;
|
|
10
|
-
if (Array.isArray(values)) values.forEach((item, i) => values[i] = is(item) ? item : store(item));
|
|
11
|
-
if (isObject(values)) {
|
|
12
|
-
let state = Object.create(proto || Object.getPrototypeOf(values));
|
|
13
|
-
Object.entries(Object.getOwnPropertyDescriptors(values)).forEach(
|
|
14
|
-
([key, desc]) => {
|
|
15
|
-
let signal = api.is(desc.value) ? desc.value : api.signal(resolve(desc.value)),
|
|
16
|
-
memo = desc.get ? (api.memo ? api.memo(desc.get.bind(state)) : desc.get.bind(state)()) : signal;
|
|
17
|
-
Object.defineProperty(state, key, {
|
|
18
|
-
get: () => desc.get ? memo : api.get(memo),
|
|
19
|
-
set: desc.get ? desc.set?.bind(state) : v => api.set(signal, resolve(v)),
|
|
20
|
-
enumerable: true,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
Object.defineProperty(state, _s, { value: true });
|
|
25
|
-
return state;
|
|
26
|
-
}
|
|
27
|
-
return values;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
exports.api = api;
|
|
31
|
-
exports.is = is;
|
|
32
|
-
exports.store = store;
|