atomaric 0.0.60 → 0.0.62
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/build/atomaric.js +314 -198
- package/build/atomaric.umd.cjs +1 -1
- package/package.json +8 -10
- package/types/index.d.ts +6 -2
- package/src/class.ts +0 -295
- package/src/globals.d.ts +0 -52
- package/src/index.ts +0 -2
- package/src/lib.ts +0 -36
- package/src/makeDeepProxyObject.ts +0 -35
- package/src/makeDoFillerActions.ts +0 -225
- package/src/test.tsx +0 -207
package/build/atomaric.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(g,j){typeof exports=="object"&&typeof module<"u"?j(exports):typeof define=="function"&&define.amd?define(["exports"],j):(g=typeof globalThis<"u"?globalThis:g||self,j(g.atomaric={}))})(this,function(g){"use strict";let j=()=>{throw"call configureAtomaric() before all!"};const T={},ue=e=>{T.useSyncExternalStore=j=e.useSyncExternalStore,T.keyPathSeparator=e.keyPathSeparator,T.securifyKeyLevel=e.securifyKeyLevel,T.securifyValueLevel=e.securifyValueLevel},X=e=>j(e.subscribe,e.get),Y=e=>e.set,le=e=>e.setDeferred,fe=e=>e.get,ae=e=>e.do,de=e=>[X(e),Y(e)],ge=(e,t)=>new ee(e,t),ye=(e,t)=>{const c=(l,h,A)=>new Proxy(l,{get:(s,n,i)=>{const u=A===0&&t.get!=null?t.get(s,n,i):s[n];return typeof u=="object"&&u!==null?c(Array.isArray(u)?u.slice(0):{...u},h.concat(Array.isArray(s)?+n:n),A+1):u},set:(s,n,i)=>(t.onSet(s,h,n,i,s[n])&&(s[n]=i),!0)});return c(e,[],0)},he=(e,t,c)=>{let l=null;if(typeof e=="number")l=E(t,s=>({increment:n=>{s.set(+s.get()+(n??0))}}));else if(typeof e=="boolean")l=E(t,s=>({toggle:()=>{s.set(!s.get())}}));else if(Array.isArray(e))l=E(t,s=>({push:(...n)=>{s.set(s.get().concat(n))},unshift:(...n)=>{s.set(n.concat(s.get()))},update:n=>{const i=s.get(),u=Z(i,n);u!==i&&s.set(u)},filter:n=>{s.set(s.get().filter(n??pe))},add:n=>{s.get().includes(n)||s.set(s.get().concat([n]))},remove:n=>{const i=s.get().indexOf(n);if(i<0)return;const u=s.get().slice(0);u.splice(i,1),s.set(u)},toggle:(n,i)=>{const u=s.get().slice(),d=u.indexOf(n);d<0?i?u.unshift(n):u.push(n):u.splice(d,1),s.set(u)}}));else if(e instanceof Set)l=E(t,s=>({add:n=>{s.set(new Set(s.get()).add(n))},delete:n=>{const i=new Set(s.get());i.delete(n),s.set(i)},toggle:n=>{const i=new Set(s.get());i.has(n)?i.delete(n):i.add(n),s.set(i)},clear:()=>{s.set(new Set)}}));else if(e instanceof Object){const s=T.keyPathSeparator||".";l=E(t,n=>({setPartial:i=>n.set(u=>({...u,...typeof i=="function"?i(n.get()):i})),update:i=>{const u=n.get(),d=Z(u,i);d!==u&&n.set(d)},setDeepPartial:(i,u,d,m=s)=>{if(!m)return;if(i.includes(m)){let V=i.split(m);const w=V[V.length-1];V=V.slice(0,-1);const U={...n.get()};let y=U,P=d;for(const x of V){P=P==null?void 0:P[Array.isArray(P)?"0":x];const D=y[K(y,x)]??(Array.isArray(P)?[]:{});if(D==null||typeof D!="object"){if(d==null)throw"Incorrect path for setDeepPartial";const I=typeof u=="function"?u(void 0):u;n.get()[i]!==I&&n.do.setPartial({[i]:I});return}y=y[K(y,x)]=Array.isArray(D)?[...D]:{...D}}const S=y[w];y[w]=typeof u=="function"?u(y[w]):u,S!==y[w]&&n.set(U);return}const p=n.get()[i],b=typeof u=="function"?u(p):u;b!==p&&n.do.setPartial({[i]:b})}}))}const h=typeof c=="object"&&c!=null&&"do"in c?c.do((s,n)=>t.set(s,n),()=>t.get(),t,(s,n,i)=>t.setDeferred(s,n,i)):null,A={};return h&&Object.keys(h).forEach(s=>Object.defineProperty(A,s,{get:()=>h[s]})),l&&Object.keys(l).forEach(s=>Object.defineProperty(A,s,{get:()=>l[s]})),A},pe=e=>e,E=(e,t,c)=>t(e),Z=(e,t)=>{const c=Array.isArray(e)?e.slice(0):{...e};let l=!1;const h=ye(e,{onSet:(A,s,n,i,u)=>{if(i===u)return!0;let d=c;l=!0;for(const m of s){const p=d[m];d=d[m]=Array.isArray(p)?p.slice(0):{...p}}return d[n]=i,!0}});return t(h),l?c:e},K=(e,t)=>Array.isArray(e)?`${+t}`:t;var O=(e=>(e[e.None=0]="None",e[e.Simple=1]="Simple",e[e.Middle=2]="Middle",e[e.Strong=3]="Strong",e))(O||{});class ee{constructor(t,c){const l=r=>u=r,h=()=>u,A=new Set,s=r=>r(p());let n=!0,i=!1,u=t,d,m=()=>{},p=()=>h(),b=null,V=()=>{const r=he(t,w,c);return V=()=>r,r};const w=new Proxy(this,{get:(r,a)=>a==="do"?V():r[a],set:we}),U=()=>{n=!0,i!==!0&&m(p()),i=!1;try{W.postMessage({key:f,value:h()})}catch{}},y=(r,a)=>{const $=typeof r=="function"?r(p()):r;$!==p()&&(l($),i=a,n&&(n=!1,A.forEach(s),queueMicrotask(U)))};this.set=(r,a)=>y(r,a),this.get=()=>p(),this.initialValue=t,this.isInitialValue=()=>t===h(),this.subscribe=r=>(A.add(r),()=>{A.delete(r)}),this.reset=()=>{y(t,!0)};const P=(r,a)=>{y(r,a),d=void 0};if(this.setDeferred=(r,a=500,$,v=!0)=>{v&&d===void 0&&y(r,$),clearTimeout(d),d=setTimeout(P,a,r,$)},c==null)return w;let S=null,x=null,D=!0,I=!0,Q=!1,F=0,_=0,se=-1,R=t instanceof Set?r=>new Set(r):r=>r,L=t instanceof Set?r=>{if(r instanceof Set)return Array.from(r);throw console.error(r),"The value is not Set instance"}:r=>r;if(typeof c=="string")S=c;else if("storeKey"in c)D=c.warnOnDuplicateStoreKey??D,I=c.listenStorageChanges??I,S=c.storeKey,R=c.unzipValue??R,L=c.zipValue??L,Q=c.unchangable??Q,F=c.securifyKeyLevel??T.securifyKeyLevel??F,_=c.securifyValueLevel??T.securifyValueLevel??_,x=c.exp??x;else return w;const k=F?M(S,3):S,f=`${_?G:z}${k}`;if(F){const r=`${z}${S}`;r in o&&(o[f]=o[r],delete o[r])}else{const r=`${z}${M(S,3)}`;r in o&&(o[f]=o[r],delete o[r])}if(_){delete o[`${z}${k}`];const r=L,a=R;R=$=>{try{return a(B($,_)[0])}catch{return delete o[f],""}},L=$=>{try{return M([r($)],_)}catch{return delete o[f],""}}}else delete o[`${G}${k}`];const ce=x===null||!(x(w,f in o)instanceof Date)?r=>M([L(r)],0):r=>(b??(b={}),b.exp=x(w,f in o).getTime(),b.exp-Date.now()<24*60*60*1e3&&(clearTimeout(se),clearTimeout(te[f]),se=setTimeout(()=>this.reset(),b.exp-Date.now())),b.exp=Math.trunc(b.exp/1e3),M([L(r),b],0)),ie=r=>{const a=B(r,0);return b=a[1],R(a[0])};let oe=!0;if(H[f]=w,o[`atom/${S}`]&&(o[f]||(o[f]=`[${o[`atom/${S}`]}]`),delete o[`atom/${S}`]),p=()=>{if(p=h,oe){oe=!1;try{l(f in o?ie(o[f]):t)}catch{console.warn("Invalid json value",o[f])}}return h()},m=r=>{if(r===t){this.reset();return}o[f]=ce(r)},this.reset=()=>{delete o[f],y(t,!0)},D&&C[f]!==void 0&&console.warn("Duplicate Atom key",S),I)if(Q){let r=!1,a;q[f]=this,C[f]=()=>{clearTimeout(a),a=setTimeout(()=>r=!1,10),!r&&(r=!0,o[f]=ce(h()))}}else C[f]=r=>{if(r.newValue===null){this.reset();return}try{y(ie(r.newValue))}catch{console.warn("Invalid json value",r.newValue)}};return w}}let W;try{W=new BroadcastChannel("updateHere"),W.addEventListener("message",e=>{var t;(t=q[e.data.key])==null||t.set(e.data.value,!0)})}catch{}const o=localStorage,C={},q={},we=(e,t)=>{throw`${t} is readonly property`};window.addEventListener("storage",e=>{var t;e.key===null||e.newValue===e.oldValue||(t=C[e.key])==null||t.call(C,e)});const Se=o.setItem.bind(o),Ae=o.removeItem.bind(o);o.setItem=(e,t)=>{q[e]===void 0&&Se.call(o,e,t)},o.removeItem=e=>{q[e]===void 0&&Ae.call(o,e)};const be=/"exp":\s*(\d+)/,z="atom\\",G="atom`s\\",H={},te={},re=/[a-z]/gi,N=5,J={};for(let e=54;e<80;e++){if(e===68||e===72||e===55)continue;const t=String.fromCharCode(e+43).toUpperCase(),c=String.fromCharCode(e+43).toLowerCase();J[t]=c,J[c]=t}const ne=e=>J[e]??e,M=(()=>{const e={0:t=>JSON.stringify(t),1:t=>btoa(encodeURI(e[0](t))),2:t=>{const c=e[1](t);return`${c.slice(0,N)}${c.slice(N).replace(re,ne)}`},3:t=>btoa(e[2](t))};return(t,c)=>{try{return e[c](t)}catch(l){if(c===0)throw l;return e[0](t)}}})(),B=(()=>{const e={0:t=>JSON.parse(t),1:t=>e[0](decodeURI(atob(t))),2:t=>e[1](`${t.slice(0,N)}${t.slice(N).replace(re,ne)}`),3:t=>e[2](atob(t))};return(t,c)=>{try{return e[c](t)}catch(l){if(c===0)throw l;return e[0](t)}}})();setTimeout(()=>{Object.keys(o).forEach(e=>{var l;if(typeof o[e]!="string"||!e.startsWith(z)&&!e.startsWith(G))return;const t=+((l=o[e].match(be))==null?void 0:l[1]);if(!t||t*1e3-Date.now()>24*60*60*1e3)return;const c=B(o[e],0);!Array.isArray(c)||c[1]==null||!("exp"in c[1])||c[1].exp!==t||(te[e]=setTimeout(()=>{H[e]?H[e].reset():delete o[e]},t*1e3-Date.now()))})},1e3),g.Atom=ee,g.AtomSecureLevel=O,g.atom=ge,g.configureAtomaric=ue,g.configuredOptions=T,g.useAtom=de,g.useAtomDo=ae,g.useAtomGet=fe,g.useAtomSet=Y,g.useAtomSetDeferred=le,g.useAtomValue=X,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atomaric",
|
|
3
3
|
"description": "Manage your project state",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.62",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"types": "./src/index.ts",
|
|
6
|
+
"main": "./build/atomaric.umd.cjs",
|
|
7
|
+
"module": "./build/atomaric.js",
|
|
8
|
+
"types": "./types/index.d.ts",
|
|
10
9
|
"exports": {
|
|
11
10
|
".": {
|
|
12
|
-
"types": "./
|
|
13
|
-
"
|
|
14
|
-
"
|
|
11
|
+
"types": "./types/index.d.ts",
|
|
12
|
+
"require": "./build/atomaric.umd.cjs",
|
|
13
|
+
"import": "./build/atomaric.js"
|
|
15
14
|
}
|
|
16
15
|
},
|
|
17
16
|
"files": [
|
|
18
17
|
"build",
|
|
19
|
-
"types"
|
|
20
|
-
"src"
|
|
18
|
+
"types"
|
|
21
19
|
],
|
|
22
20
|
"keywords": [
|
|
23
21
|
"react",
|
package/types/index.d.ts
CHANGED
|
@@ -34,14 +34,16 @@ export type AtomOptions<Value, Actions extends Record<string, Function> = {}> =
|
|
|
34
34
|
| {
|
|
35
35
|
/** save in localStorage by this key */
|
|
36
36
|
storeKey: AtomStoreKey;
|
|
37
|
+
securifyKeyLevel?: AtomSecureLevel;
|
|
38
|
+
securifyValueLevel?: AtomSecureLevel;
|
|
37
39
|
}
|
|
38
40
|
| {
|
|
39
41
|
/** declare your custom actions */
|
|
40
42
|
do: (
|
|
41
|
-
set:
|
|
43
|
+
set: AtomSetMethod<Value>,
|
|
42
44
|
get: () => Value,
|
|
43
45
|
self: Atom<Value>,
|
|
44
|
-
setDeferred:
|
|
46
|
+
setDeferred: AtomSetDeferredMethod<Value>,
|
|
45
47
|
) => Actions;
|
|
46
48
|
}
|
|
47
49
|
);
|
|
@@ -175,4 +177,6 @@ export function atom<Value, Actions extends Record<string, Function> = {}>(
|
|
|
175
177
|
export function configureAtomaric(options: {
|
|
176
178
|
useSyncExternalStore: typeof useSyncExternalStore;
|
|
177
179
|
keyPathSeparator: ObjectActionsSetDeepPartial;
|
|
180
|
+
securifyKeyLevel?: AtomSecureLevel;
|
|
181
|
+
securifyValueLevel?: AtomSecureLevel;
|
|
178
182
|
}): void;
|
package/src/class.ts
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AtomOptions,
|
|
3
|
-
AtomSetDeferredMethod,
|
|
4
|
-
AtomSetMethod,
|
|
5
|
-
AtomStoreKey,
|
|
6
|
-
AtomSubscribeMethod,
|
|
7
|
-
Atom as AtomType,
|
|
8
|
-
DefaultActions,
|
|
9
|
-
} from '../types';
|
|
10
|
-
import { makeDoFillerActions } from './makeDoFillerActions';
|
|
11
|
-
|
|
12
|
-
type Subscriber<Value> = (value: Value) => void;
|
|
13
|
-
|
|
14
|
-
type Tools = { exp?: number };
|
|
15
|
-
|
|
16
|
-
export class Atom<Value, Actions extends Record<string, Function> = {}> implements AtomType<Value, Actions> {
|
|
17
|
-
get;
|
|
18
|
-
set: AtomSetMethod<Value>;
|
|
19
|
-
setDeferred: AtomSetDeferredMethod<Value>;
|
|
20
|
-
reset: () => void;
|
|
21
|
-
subscribe: AtomSubscribeMethod<Value>;
|
|
22
|
-
initialValue;
|
|
23
|
-
isInitialValue;
|
|
24
|
-
do!: Actions & DefaultActions<Value>;
|
|
25
|
-
|
|
26
|
-
constructor(initialValue: Value, storeKeyOrOptions: AtomStoreKey | AtomOptions<Value, Actions> | undefined) {
|
|
27
|
-
const updateCurrentValue = (value: Value) => (______current_value_____ = value);
|
|
28
|
-
const getCurrentValue = () => ______current_value_____;
|
|
29
|
-
const subscribers = new Set<Subscriber<Value>>();
|
|
30
|
-
const invokeSubscriber = (sub: Subscriber<Value>) => sub(get());
|
|
31
|
-
|
|
32
|
-
let isQueueWait = true;
|
|
33
|
-
let lastIsPreventSave = false as boolean | nil;
|
|
34
|
-
|
|
35
|
-
let ______current_value_____ = initialValue;
|
|
36
|
-
let debounceTimeout: ReturnType<typeof setTimeout> | number | undefined;
|
|
37
|
-
let save: (val: Value) => void = () => {};
|
|
38
|
-
let get = () => getCurrentValue();
|
|
39
|
-
let tools: Tools | null | undefined = null;
|
|
40
|
-
|
|
41
|
-
let doFiller = () => {
|
|
42
|
-
const doActions = makeDoFillerActions<Value, Actions>(initialValue, proxiedSelf, storeKeyOrOptions);
|
|
43
|
-
doFiller = () => doActions;
|
|
44
|
-
return doActions;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const proxiedSelf = new Proxy(this, {
|
|
48
|
-
get: (self, prop) => (prop === 'do' ? doFiller() : self[prop as 'do']),
|
|
49
|
-
set: retFalse,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const promiseResolver = () => {
|
|
53
|
-
isQueueWait = true;
|
|
54
|
-
if (lastIsPreventSave !== true) save(get());
|
|
55
|
-
lastIsPreventSave = false;
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
updateHere.postMessage({ key, value: getCurrentValue() });
|
|
59
|
-
} catch (e) {}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const set: typeof this.set = (value, isPreventSave) => {
|
|
63
|
-
const nextValue = typeof value === 'function' ? (value as (value: Value) => Value)(get()) : value;
|
|
64
|
-
|
|
65
|
-
if (nextValue === get()) return;
|
|
66
|
-
|
|
67
|
-
updateCurrentValue(nextValue);
|
|
68
|
-
lastIsPreventSave = isPreventSave;
|
|
69
|
-
|
|
70
|
-
if (isQueueWait) {
|
|
71
|
-
isQueueWait = false;
|
|
72
|
-
subscribers.forEach(invokeSubscriber);
|
|
73
|
-
|
|
74
|
-
queueMicrotask(promiseResolver);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
this.set = (value, isPreventSave) => set(value, isPreventSave);
|
|
79
|
-
this.get = () => get();
|
|
80
|
-
this.initialValue = initialValue;
|
|
81
|
-
this.isInitialValue = () => initialValue === getCurrentValue();
|
|
82
|
-
|
|
83
|
-
this.subscribe = sub => {
|
|
84
|
-
subscribers.add(sub);
|
|
85
|
-
return () => {
|
|
86
|
-
subscribers.delete(sub);
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
this.reset = () => {
|
|
91
|
-
set(initialValue, true);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const deferredTimeOut = (value: Value, isPreventSave: boolean) => {
|
|
95
|
-
set(value, isPreventSave);
|
|
96
|
-
debounceTimeout = undefined;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
this.setDeferred = (value, debounceMs = 500, isPreventSave, isInitInvoke = true) => {
|
|
100
|
-
if (isInitInvoke && debounceTimeout === undefined) set(value, isPreventSave);
|
|
101
|
-
clearTimeout(debounceTimeout);
|
|
102
|
-
debounceTimeout = setTimeout(deferredTimeOut, debounceMs, value, isPreventSave);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
if (storeKeyOrOptions == null) return proxiedSelf;
|
|
106
|
-
|
|
107
|
-
////////////////////////
|
|
108
|
-
//////////////////////// storaged value
|
|
109
|
-
////////////////////////
|
|
110
|
-
|
|
111
|
-
let storeKey = null;
|
|
112
|
-
let exp = null;
|
|
113
|
-
let warnOnDuplicateStoreKey = true;
|
|
114
|
-
let listenStorageChanges = true;
|
|
115
|
-
let isUnchangable = false;
|
|
116
|
-
let expTimeout = -1 as never as ReturnType<typeof setTimeout>;
|
|
117
|
-
|
|
118
|
-
let unzipValue: AtomOptions<Value, Actions>['unzipValue'] =
|
|
119
|
-
initialValue instanceof Set ? strValue => new Set(strValue) : val => val;
|
|
120
|
-
|
|
121
|
-
let zipValue: AtomOptions<Value, Actions>['zipValue'] =
|
|
122
|
-
initialValue instanceof Set
|
|
123
|
-
? val => {
|
|
124
|
-
if (val instanceof Set) return Array.from(val);
|
|
125
|
-
|
|
126
|
-
console.error(val);
|
|
127
|
-
throw 'The value is not Set instance';
|
|
128
|
-
}
|
|
129
|
-
: val => val;
|
|
130
|
-
|
|
131
|
-
if (typeof storeKeyOrOptions === 'string') {
|
|
132
|
-
storeKey = storeKeyOrOptions;
|
|
133
|
-
} else if ('storeKey' in storeKeyOrOptions) {
|
|
134
|
-
warnOnDuplicateStoreKey = storeKeyOrOptions.warnOnDuplicateStoreKey ?? warnOnDuplicateStoreKey;
|
|
135
|
-
listenStorageChanges = storeKeyOrOptions.listenStorageChanges ?? listenStorageChanges;
|
|
136
|
-
storeKey = storeKeyOrOptions.storeKey;
|
|
137
|
-
|
|
138
|
-
unzipValue = storeKeyOrOptions.unzipValue ?? unzipValue;
|
|
139
|
-
zipValue = storeKeyOrOptions.zipValue ?? zipValue;
|
|
140
|
-
isUnchangable = storeKeyOrOptions.unchangable ?? isUnchangable;
|
|
141
|
-
exp = storeKeyOrOptions.exp ?? exp;
|
|
142
|
-
} else return proxiedSelf;
|
|
143
|
-
|
|
144
|
-
const key = `${prefix}${storeKey}`;
|
|
145
|
-
const stringifyValue =
|
|
146
|
-
exp === null || !(exp(proxiedSelf, key in localStorage) instanceof Date)
|
|
147
|
-
? (value: Value) => JSON.stringify([zipValue(value)])
|
|
148
|
-
: (value: Value) => {
|
|
149
|
-
tools ??= {};
|
|
150
|
-
tools.exp = exp(proxiedSelf, key in localStorage).getTime();
|
|
151
|
-
|
|
152
|
-
if (tools.exp - Date.now() < 24 * 60 * 60 * 1000) {
|
|
153
|
-
clearTimeout(expTimeout);
|
|
154
|
-
clearTimeout(initResetTimeouts[key]);
|
|
155
|
-
expTimeout = setTimeout(() => this.reset(), tools.exp - Date.now());
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
tools.exp = Math.trunc(tools.exp / 1000);
|
|
159
|
-
|
|
160
|
-
return JSON.stringify([zipValue(value), tools]);
|
|
161
|
-
};
|
|
162
|
-
|
|
163
|
-
const parseValue = (value: string): Value => {
|
|
164
|
-
const val = JSON.parse(value);
|
|
165
|
-
tools = val[1];
|
|
166
|
-
|
|
167
|
-
return unzipValue(val[0]);
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
let isInactualValue = true;
|
|
171
|
-
registeredAtoms[key] = proxiedSelf;
|
|
172
|
-
|
|
173
|
-
if (localStorage[`atom/${storeKey}`]) {
|
|
174
|
-
localStorage[key] ||= `[${localStorage[`atom/${storeKey}`]}]`;
|
|
175
|
-
delete localStorage[`atom/${storeKey}`];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
get = () => {
|
|
179
|
-
get = getCurrentValue;
|
|
180
|
-
|
|
181
|
-
if (isInactualValue) {
|
|
182
|
-
isInactualValue = false;
|
|
183
|
-
try {
|
|
184
|
-
updateCurrentValue(key in localStorage ? parseValue(localStorage[key]) : initialValue);
|
|
185
|
-
} catch (e) {
|
|
186
|
-
console.warn('Invalid json value', localStorage[key]);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return getCurrentValue();
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
save = value => {
|
|
194
|
-
if (value === initialValue) {
|
|
195
|
-
this.reset();
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
localStorage[key] = stringifyValue(value);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
this.reset = () => {
|
|
202
|
-
delete localStorage[key];
|
|
203
|
-
set(initialValue, true);
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
if (warnOnDuplicateStoreKey && update[key] !== undefined) console.warn('Duplicate Atom key', storeKey);
|
|
207
|
-
|
|
208
|
-
if (listenStorageChanges) {
|
|
209
|
-
if (isUnchangable) {
|
|
210
|
-
let isCantChange = false;
|
|
211
|
-
let timeout: ReturnType<typeof setTimeout>;
|
|
212
|
-
|
|
213
|
-
unchangableAtoms[key] = this as never;
|
|
214
|
-
update[key] = () => {
|
|
215
|
-
clearTimeout(timeout);
|
|
216
|
-
timeout = setTimeout(() => (isCantChange = false), 10);
|
|
217
|
-
|
|
218
|
-
if (isCantChange) return;
|
|
219
|
-
isCantChange = true;
|
|
220
|
-
|
|
221
|
-
localStorage[key] = stringifyValue(getCurrentValue());
|
|
222
|
-
};
|
|
223
|
-
} else
|
|
224
|
-
update[key] = event => {
|
|
225
|
-
if (event.newValue === null) {
|
|
226
|
-
this.reset();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
try {
|
|
231
|
-
set(parseValue(event.newValue));
|
|
232
|
-
} catch (_e) {
|
|
233
|
-
console.warn('Invalid json value', event.newValue);
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return proxiedSelf;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
let updateHere: BroadcastChannel;
|
|
243
|
-
try {
|
|
244
|
-
updateHere = new BroadcastChannel('updateHere');
|
|
245
|
-
updateHere.addEventListener('message', event => {
|
|
246
|
-
unchangableAtoms[event.data.key]?.set(event.data.value, true);
|
|
247
|
-
});
|
|
248
|
-
} catch (e) {}
|
|
249
|
-
|
|
250
|
-
const localStorage = window.localStorage;
|
|
251
|
-
const update: Partial<Record<string, (event: StorageEvent) => void>> = {};
|
|
252
|
-
const unchangableAtoms: Partial<Record<string, Atom<unknown>>> = {};
|
|
253
|
-
const retFalse = (_self: any, prop: string) => {
|
|
254
|
-
throw `${prop} is readonly property`;
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
window.addEventListener('storage', event => {
|
|
258
|
-
if (event.key === null || event.newValue === event.oldValue) return;
|
|
259
|
-
update[event.key]?.(event);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
const setItem = localStorage.setItem.bind(localStorage);
|
|
263
|
-
const removeItem = localStorage.removeItem.bind(localStorage);
|
|
264
|
-
|
|
265
|
-
localStorage.setItem = (key, value) => {
|
|
266
|
-
if (unchangableAtoms[key] !== undefined) return;
|
|
267
|
-
setItem.call(localStorage, key, value);
|
|
268
|
-
};
|
|
269
|
-
localStorage.removeItem = key => {
|
|
270
|
-
if (unchangableAtoms[key] !== undefined) return;
|
|
271
|
-
removeItem.call(localStorage, key);
|
|
272
|
-
};
|
|
273
|
-
const expMatcherReg = /"exp":\s*(\d+)/;
|
|
274
|
-
const prefix = `atom\\`;
|
|
275
|
-
const registeredAtoms: Record<string, Atom<any>> = {};
|
|
276
|
-
const initResetTimeouts: Record<string, ReturnType<typeof setTimeout>> = {};
|
|
277
|
-
|
|
278
|
-
setTimeout(() => {
|
|
279
|
-
Object.keys(localStorage).forEach(key => {
|
|
280
|
-
if (!key.startsWith(prefix) || typeof localStorage[key] !== 'string') return;
|
|
281
|
-
const secTs = +localStorage[key].match(expMatcherReg)?.[1]!;
|
|
282
|
-
|
|
283
|
-
if (!secTs || secTs * 1000 - Date.now() > 24 * 60 * 60 * 1000) return;
|
|
284
|
-
|
|
285
|
-
const jsonValue = JSON.parse(localStorage[key]);
|
|
286
|
-
|
|
287
|
-
if (!Array.isArray(jsonValue) || jsonValue[1] == null || !('exp' in jsonValue[1]) || jsonValue[1].exp !== secTs)
|
|
288
|
-
return;
|
|
289
|
-
|
|
290
|
-
initResetTimeouts[key] = setTimeout(() => {
|
|
291
|
-
if (registeredAtoms[key]) registeredAtoms[key].reset();
|
|
292
|
-
else delete localStorage[key];
|
|
293
|
-
}, secTs * 1000 - Date.now());
|
|
294
|
-
});
|
|
295
|
-
}, 1000);
|
package/src/globals.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { knownStameskaIconNames } from 'shared/values/index/known-icons';
|
|
2
|
-
|
|
3
|
-
enum NotANumber {
|
|
4
|
-
nan = 'NaN',
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
declare global {
|
|
8
|
-
type num = 0 | 1;
|
|
9
|
-
type str = '' | '1';
|
|
10
|
-
type nil = null | undefined;
|
|
11
|
-
type und = undefined;
|
|
12
|
-
type TimeOut = ReturnType<typeof setTimeout> | und | number;
|
|
13
|
-
type intStr = `${'-' | ''}${number}`;
|
|
14
|
-
type doubleStr = `${'-' | ''}${intStr}.${number}`;
|
|
15
|
-
type numberStr = `${'-' | ''}${intStr}${`.${number}` | ''}`;
|
|
16
|
-
type StringBySlash = `${string}/${string}`;
|
|
17
|
-
type func = (arg: unknown, ...args: unknown[]) => unknown | void;
|
|
18
|
-
|
|
19
|
-
type KRecord<Key extends string | number, Value> = (Record<`${Key}`, Value> | Record<Key, Value>) &
|
|
20
|
-
Record<`${Key}` | Key, Value>;
|
|
21
|
-
type PRecord<Key extends string | number, Value> = Partial<KRecord<Key, Value>>;
|
|
22
|
-
|
|
23
|
-
/** Record with <Required key, Partial key, Value> */
|
|
24
|
-
type RPRecord<ReqiredKey extends string | number, Key extends string | number, Value> = KRecord<ReqiredKey, Value> &
|
|
25
|
-
Partial<KRecord<Exclude<Key, ReqiredKey>, Value>>;
|
|
26
|
-
|
|
27
|
-
type RKey<Key extends number> = Key | `${Key}`;
|
|
28
|
-
|
|
29
|
-
type OmitOwn<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
|
30
|
-
type WithRewrites<T, P> = Pick<T, Exclude<keyof T, keyof P>> & Pick<P, keyof P>;
|
|
31
|
-
|
|
32
|
-
type NaN = NotANumber;
|
|
33
|
-
type NaNumber = number | NotANumber;
|
|
34
|
-
type FalsyValue = false | '' | 0 | nil;
|
|
35
|
-
|
|
36
|
-
type PropagationStopperEvent = { stopPropagation(): void };
|
|
37
|
-
type PropagationStopper = (event: PropagationStopperEvent) => void;
|
|
38
|
-
|
|
39
|
-
type DefaultPreventerEvent = { preventDefault(): void };
|
|
40
|
-
type DefaultPreventer = (event: DefaultPreventerEvent) => void;
|
|
41
|
-
|
|
42
|
-
type PreventerAndStopperCallback = (event: DefaultPreventerEvent & PropagationStopperEvent) => void;
|
|
43
|
-
|
|
44
|
-
type NonUndefined<T> = T extends undefined ? never : T;
|
|
45
|
-
type NonNull<T> = T extends null ? never : T;
|
|
46
|
-
type NonNil<T> = T extends nil ? never : T;
|
|
47
|
-
|
|
48
|
-
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
|
49
|
-
type XOR<T, U> = (Without<T, U> & U) | (Without<U, T> & T);
|
|
50
|
-
|
|
51
|
-
type KnownStameskaIconName = keyof typeof knownStameskaIconNames;
|
|
52
|
-
}
|
package/src/index.ts
DELETED
package/src/lib.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { useSyncExternalStore } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
atom as atomType,
|
|
4
|
-
configureAtomaric as configureAtomaricType,
|
|
5
|
-
useAtomDo as useAtomDoType,
|
|
6
|
-
useAtomGet as useAtomGetType,
|
|
7
|
-
useAtomSetDeferred as useAtomSetDeferredType,
|
|
8
|
-
useAtomSet as useAtomSetType,
|
|
9
|
-
useAtom as useAtomType,
|
|
10
|
-
useAtomValue as useAtomValueType,
|
|
11
|
-
} from '../types';
|
|
12
|
-
import { Atom } from './class';
|
|
13
|
-
|
|
14
|
-
let useSyncExtStore = (() => {
|
|
15
|
-
throw 'call configureAtomaric() before all!';
|
|
16
|
-
}) as typeof useSyncExternalStore;
|
|
17
|
-
|
|
18
|
-
export const configuredOptions: Partial<Parameters<typeof configureAtomaricType>[0]> = {};
|
|
19
|
-
|
|
20
|
-
export const configureAtomaric: typeof configureAtomaricType = options => {
|
|
21
|
-
configuredOptions.useSyncExternalStore = useSyncExtStore = options.useSyncExternalStore;
|
|
22
|
-
configuredOptions.keyPathSeparator = options.keyPathSeparator;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const useAtomValue: typeof useAtomValueType = atom => {
|
|
26
|
-
return useSyncExtStore(atom.subscribe, atom.get);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
export const useAtomSet: typeof useAtomSetType = atom => atom.set;
|
|
30
|
-
export const useAtomSetDeferred: typeof useAtomSetDeferredType = atom => atom.setDeferred;
|
|
31
|
-
export const useAtomGet: typeof useAtomGetType = atom => atom.get;
|
|
32
|
-
export const useAtomDo: typeof useAtomDoType = atom => atom.do;
|
|
33
|
-
|
|
34
|
-
export const useAtom: typeof useAtomType = atom => [useAtomValue(atom), useAtomSet(atom)];
|
|
35
|
-
|
|
36
|
-
export const atom: typeof atomType = (value, storeKeyOrOptions) => new Atom(value, storeKeyOrOptions);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export const makeDeepProxyObject = <T extends object>(
|
|
2
|
-
target: T,
|
|
3
|
-
handler: ProxyHandler<T> & {
|
|
4
|
-
onSet: <I extends object>(
|
|
5
|
-
target: I,
|
|
6
|
-
path: (string | number)[],
|
|
7
|
-
setKey: number | string,
|
|
8
|
-
value: unknown,
|
|
9
|
-
prevValue: unknown,
|
|
10
|
-
) => boolean;
|
|
11
|
-
},
|
|
12
|
-
) => {
|
|
13
|
-
const proxer = <I extends object>(target: I, keys: (number | string)[], level: number) =>
|
|
14
|
-
new Proxy(target, {
|
|
15
|
-
get: (target, key, reciever) => {
|
|
16
|
-
const value =
|
|
17
|
-
level === 0 && handler.get != null ? handler.get(target as never, key, reciever) : target[key as never];
|
|
18
|
-
|
|
19
|
-
return typeof value === 'object' && value !== null
|
|
20
|
-
? proxer(
|
|
21
|
-
Array.isArray(value) ? value.slice(0) : { ...value },
|
|
22
|
-
keys.concat(Array.isArray(target) ? +(key as never) : (key as never)),
|
|
23
|
-
level + 1,
|
|
24
|
-
)
|
|
25
|
-
: value;
|
|
26
|
-
},
|
|
27
|
-
set: (target, key, value) => {
|
|
28
|
-
if (!handler.onSet(target, keys, key as never, value, target[key as never])) return true;
|
|
29
|
-
target[key as never] = value as never;
|
|
30
|
-
return true;
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return proxer(target, [], 0);
|
|
35
|
-
};
|