@nativelayer.dev/restate 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.
Potentially problematic release.
This version of @nativelayer.dev/restate might be problematic. Click here for more details.
- package/.github/workflows/release.yml +20 -0
- package/CHANGELOG.md +16 -0
- package/LICENSE +132 -0
- package/README.md +1349 -0
- package/dist/plugin/async.cjs.min.js +8 -0
- package/dist/plugin/async.esm.min.js +8 -0
- package/dist/plugin/history.cjs.min.js +8 -0
- package/dist/plugin/history.esm.min.js +8 -0
- package/dist/plugin/immutable.cjs.min.js +8 -0
- package/dist/plugin/immutable.esm.min.js +8 -0
- package/dist/plugin/persistence.cjs.min.js +8 -0
- package/dist/plugin/persistence.esm.min.js +8 -0
- package/dist/plugin/validate.cjs.min.js +8 -0
- package/dist/plugin/validate.esm.min.js +8 -0
- package/dist/restate.cjs.min.js +2 -0
- package/dist/restate.esm.min.js +2 -0
- package/package.json +49 -0
- package/restate-logo.jpg +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/async v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";
|
|
3
|
+
/*!
|
|
4
|
+
* restate AsyncPlugin v1.0.0
|
|
5
|
+
* restate Async Plugin
|
|
6
|
+
* (c) 2025 restate contributors
|
|
7
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
8
|
+
*/function e(e={}){const{maxRetries:t=10,defaultTimeout:a=3e4,maxCacheSize:n=100,exponentialBackoff:s=!0}=e;return function(e){const r={name:"async",install(){r._asyncOperations=new Map,r._asyncCache=new Map,r._pendingRequests=new Map,Object.defineProperty(e._proxy,"$async",{value:(e,t,a={})=>r._handleAsync(e,t,a),enumerable:!1}),Object.defineProperty(e._proxy,"$clearCache",{value:t=>(t?r._asyncCache.delete(t):r._asyncCache.clear(),e._proxy),enumerable:!1}),Object.defineProperty(e._proxy,"$isLoading",{value:e=>r._asyncOperations.has(e),enumerable:!1}),e._pluginHooks.onDestroy.push(()=>{r._asyncOperations.clear(),r._asyncCache.clear(),r._pendingRequests.forEach(e=>e.abort()),r._pendingRequests.clear()})},_withTimeout:(e,t)=>!t||t<=0?e():Promise.race([e(),new Promise((e,a)=>setTimeout(()=>a(new Error(`AsyncPlugin: Request timed out after ${t}ms`)),t))]),_evictOldestCache(){if(r._asyncCache.size>=n){const e=r._asyncCache.keys().next().value;r._asyncCache.delete(e)}},async _handleAsync(n,s,c={}){const{cache:i=!1,cacheTime:o=3e5,dedupe:y=!0,retries:_=0,retryDelay:u=1e3,timeout:l=a,optimistic:p=null,loadingKey:h=`${n}Loading`,errorKey:d=`${n}Error`,dataKey:m=n}=c,x=Math.min(_,t);if(i&&r._asyncCache.has(n)){const t=r._asyncCache.get(n);if(Date.now()-t.timestamp<o)return e._proxy[m]=t.data,t.data;r._asyncCache.delete(n)}if(y&&r._pendingRequests.has(n))return r._pendingRequests.get(n);e._proxy[h]=!0,e._proxy[d]=null,null!==p&&(e._proxy[m]=p);const f=r._executeWithRetry(s,x,u,l);y&&r._pendingRequests.set(n,f),r._asyncOperations.set(n,{startTime:Date.now(),promise:f});try{const t=await f;return e._proxy[m]=t,e._proxy[h]=!1,e._proxy[d]=null,i&&(r._evictOldestCache(),r._asyncCache.set(n,{data:t,timestamp:Date.now()})),t}catch(t){throw e._proxy[h]=!1,e._proxy[d]=t,t}finally{r._asyncOperations.delete(n),y&&r._pendingRequests.delete(n)}},async _executeWithRetry(e,t,a,n){let c;for(let i=0;i<=t;i++)try{return await r._withTimeout(e,n)}catch(e){if(c=e,i<t){const e=s?a*Math.pow(2,i):a;await new Promise(t=>setTimeout(t,e))}}throw c}};return r}}e.create=e,exports.AsyncPlugin=e;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/async v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
/*!
|
|
3
|
+
* restate AsyncPlugin v1.0.0
|
|
4
|
+
* restate Async Plugin
|
|
5
|
+
* (c) 2025 restate contributors
|
|
6
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
7
|
+
*/
|
|
8
|
+
function e(e={}){const{maxRetries:t=10,defaultTimeout:a=3e4,maxCacheSize:n=100,exponentialBackoff:s=!0}=e;return function(e){const r={name:"async",install(){r._asyncOperations=new Map,r._asyncCache=new Map,r._pendingRequests=new Map,Object.defineProperty(e._proxy,"$async",{value:(e,t,a={})=>r._handleAsync(e,t,a),enumerable:!1}),Object.defineProperty(e._proxy,"$clearCache",{value:t=>(t?r._asyncCache.delete(t):r._asyncCache.clear(),e._proxy),enumerable:!1}),Object.defineProperty(e._proxy,"$isLoading",{value:e=>r._asyncOperations.has(e),enumerable:!1}),e._pluginHooks.onDestroy.push(()=>{r._asyncOperations.clear(),r._asyncCache.clear(),r._pendingRequests.forEach(e=>e.abort()),r._pendingRequests.clear()})},_withTimeout:(e,t)=>!t||t<=0?e():Promise.race([e(),new Promise((e,a)=>setTimeout(()=>a(new Error(`AsyncPlugin: Request timed out after ${t}ms`)),t))]),_evictOldestCache(){if(r._asyncCache.size>=n){const e=r._asyncCache.keys().next().value;r._asyncCache.delete(e)}},async _handleAsync(n,s,c={}){const{cache:o=!1,cacheTime:i=3e5,dedupe:y=!0,retries:_=0,retryDelay:l=1e3,timeout:p=a,optimistic:u=null,loadingKey:h=`${n}Loading`,errorKey:d=`${n}Error`,dataKey:m=n}=c,x=Math.min(_,t);if(o&&r._asyncCache.has(n)){const t=r._asyncCache.get(n);if(Date.now()-t.timestamp<i)return e._proxy[m]=t.data,t.data;r._asyncCache.delete(n)}if(y&&r._pendingRequests.has(n))return r._pendingRequests.get(n);e._proxy[h]=!0,e._proxy[d]=null,null!==u&&(e._proxy[m]=u);const f=r._executeWithRetry(s,x,l,p);y&&r._pendingRequests.set(n,f),r._asyncOperations.set(n,{startTime:Date.now(),promise:f});try{const t=await f;return e._proxy[m]=t,e._proxy[h]=!1,e._proxy[d]=null,o&&(r._evictOldestCache(),r._asyncCache.set(n,{data:t,timestamp:Date.now()})),t}catch(t){throw e._proxy[h]=!1,e._proxy[d]=t,t}finally{r._asyncOperations.delete(n),y&&r._pendingRequests.delete(n)}},async _executeWithRetry(e,t,a,n){let c;for(let o=0;o<=t;o++)try{return await r._withTimeout(e,n)}catch(e){if(c=e,o<t){const e=s?a*Math.pow(2,o):a;await new Promise(t=>setTimeout(t,e))}}throw c}};return r}}e.create=e;export{e as AsyncPlugin};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/history v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";
|
|
3
|
+
/*!
|
|
4
|
+
* restate HistoryPlugin v1.0.0
|
|
5
|
+
* History Plugin for restate (closure-based)
|
|
6
|
+
* (c) 2025 restate contributors
|
|
7
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
8
|
+
*/exports.HistoryPlugin=function(t={}){return function(e){const r={trackHistory:!0,maxHistory:50,...t};let n=[],o=-1,s=!1;function i(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;if(t instanceof Date)return new Date(t);if(e.has(t))return e.get(t);const r=Array.isArray(t)?[]:{};if(e.set(t,r),Array.isArray(t))for(let n=0;n<t.length;n++)r[n]=i(t[n],e);else for(const n in t)Object.prototype.hasOwnProperty.call(t,n)&&(r[n]=i(t[n],e));return r}function a(t,e,r=new WeakSet){if(t===e)return!0;if("object"!=typeof t||"object"!=typeof e)return!1;if(null===t||null===e)return!1;if(r.has(t))return!0;r.add(t);if(Array.isArray(t)!==Array.isArray(e))return!1;const n=Object.keys(t),o=Object.keys(e);if(n.length!==o.length)return!1;for(const o of n){if(!Object.prototype.hasOwnProperty.call(e,o))return!1;if(!a(t[o],e[o],r))return!1}return!0}function u(){if(!r.trackHistory||e._isDestroyed||s)return;const t={state:i(e._state),timestamp:Date.now()};o<n.length-1&&(n=n.slice(0,o+1));const u=n[n.length-1];u&&a(u.state,t.state)||(n.push(t),o=n.length-1,n.length>r.maxHistory&&(n.shift(),o--))}function c(t){if(e._isDestroyed)return;s=!0;const r=e._options.immutable;e._options.immutable=!1;for(const t in e._state)delete e._state[t];Object.assign(e._state,i(t.state)),e._notifyImmediate("history",t),e._options.immutable=r,s=!1}function f(){return o>0}function y(){return o<n.length-1}return{name:"history",install(){u()},methods:{$undo:()=>(f()&&c(n[--o]),e._proxy),$redo:()=>(y()&&c(n[++o]),e._proxy),$canUndo:()=>f(),$canRedo:()=>y(),$getHistory:()=>({history:n.map((t,e)=>({index:e,timestamp:t.timestamp})),currentIndex:o,canUndo:f(),canRedo:y()}),$clearHistory:()=>(n=[],o=-1,e._proxy)},hooks:{beforeSet(){u()},beforeBulk(){u()},onDestroy(){n=[],o=-1}}}}};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/history v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
/*!
|
|
3
|
+
* restate HistoryPlugin v1.0.0
|
|
4
|
+
* History Plugin for restate (closure-based)
|
|
5
|
+
* (c) 2025 restate contributors
|
|
6
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
7
|
+
*/
|
|
8
|
+
function t(t={}){return function(e){const r={trackHistory:!0,maxHistory:50,...t};let n=[],o=-1,s=!1;function i(t,e=new WeakMap){if(null===t||"object"!=typeof t)return t;if(t instanceof Date)return new Date(t);if(e.has(t))return e.get(t);const r=Array.isArray(t)?[]:{};if(e.set(t,r),Array.isArray(t))for(let n=0;n<t.length;n++)r[n]=i(t[n],e);else for(const n in t)Object.prototype.hasOwnProperty.call(t,n)&&(r[n]=i(t[n],e));return r}function a(t,e,r=new WeakSet){if(t===e)return!0;if("object"!=typeof t||"object"!=typeof e)return!1;if(null===t||null===e)return!1;if(r.has(t))return!0;r.add(t);if(Array.isArray(t)!==Array.isArray(e))return!1;const n=Object.keys(t),o=Object.keys(e);if(n.length!==o.length)return!1;for(const o of n){if(!Object.prototype.hasOwnProperty.call(e,o))return!1;if(!a(t[o],e[o],r))return!1}return!0}function c(){if(!r.trackHistory||e._isDestroyed||s)return;const t={state:i(e._state),timestamp:Date.now()};o<n.length-1&&(n=n.slice(0,o+1));const c=n[n.length-1];c&&a(c.state,t.state)||(n.push(t),o=n.length-1,n.length>r.maxHistory&&(n.shift(),o--))}function u(t){if(e._isDestroyed)return;s=!0;const r=e._options.immutable;e._options.immutable=!1;for(const t in e._state)delete e._state[t];Object.assign(e._state,i(t.state)),e._notifyImmediate("history",t),e._options.immutable=r,s=!1}function f(){return o>0}function y(){return o<n.length-1}return{name:"history",install(){c()},methods:{$undo:()=>(f()&&u(n[--o]),e._proxy),$redo:()=>(y()&&u(n[++o]),e._proxy),$canUndo:()=>f(),$canRedo:()=>y(),$getHistory:()=>({history:n.map((t,e)=>({index:e,timestamp:t.timestamp})),currentIndex:o,canUndo:f(),canRedo:y()}),$clearHistory:()=>(n=[],o=-1,e._proxy)},hooks:{beforeSet(){c()},beforeBulk(){c()},onDestroy(){n=[],o=-1}}}}}export{t as HistoryPlugin};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/immutable v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";
|
|
3
|
+
/*!
|
|
4
|
+
* restate ImmutablePlugin v1.0.0
|
|
5
|
+
* Immutable Plugin for restate (hook-based, no double proxy)
|
|
6
|
+
* (c) 2025 restate contributors
|
|
7
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
8
|
+
*/function t(t={}){return function(r){const e={strict:!0,customErrorMessage:null,...t};return{name:"immutable",hooks:{beforeSet(t,r,s,o){if(e.strict&&!this._bulkMode){const s=o.concat(r).join(".");!function(t,r){if("function"==typeof e.customErrorMessage)throw new Error(e.customErrorMessage(t,r));throw new Error(`Cannot directly mutate ${t} '${r}'. Use state.$set() to update state`)}(Array.isArray(t)&&!isNaN(r)?"array index":"property",s)}}},methods:{$enableImmutable:()=>(e.strict=!0,r._proxy),$disableImmutable:()=>(e.strict=!1,r._proxy),$isImmutable:()=>e.strict,$setImmutableOptions:t=>(Object.assign(e,t),r._proxy)}}}}exports.FlexibleImmutablePlugin=function(r={}){return t({strict:!0,...r})},exports.ImmutablePlugin=t,exports.StrictImmutablePlugin=function(r={}){return t({strict:!0,...r})};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/immutable v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
/*!
|
|
3
|
+
* restate ImmutablePlugin v1.0.0
|
|
4
|
+
* Immutable Plugin for restate (hook-based, no double proxy)
|
|
5
|
+
* (c) 2025 restate contributors
|
|
6
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
7
|
+
*/
|
|
8
|
+
function t(t={}){return function(r){const e={strict:!0,customErrorMessage:null,...t};return{name:"immutable",hooks:{beforeSet(t,r,o,s){if(e.strict&&!this._bulkMode){const o=s.concat(r).join(".");!function(t,r){if("function"==typeof e.customErrorMessage)throw new Error(e.customErrorMessage(t,r));throw new Error(`Cannot directly mutate ${t} '${r}'. Use state.$set() to update state`)}(Array.isArray(t)&&!isNaN(r)?"array index":"property",o)}}},methods:{$enableImmutable:()=>(e.strict=!0,r._proxy),$disableImmutable:()=>(e.strict=!1,r._proxy),$isImmutable:()=>e.strict,$setImmutableOptions:t=>(Object.assign(e,t),r._proxy)}}}}function r(r={}){return t({strict:!0,...r})}function e(r={}){return t({strict:!0,...r})}export{e as FlexibleImmutablePlugin,t as ImmutablePlugin,r as StrictImmutablePlugin};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/persistence v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";
|
|
3
|
+
/*!
|
|
4
|
+
* restate PersistencePlugin v1.0.0
|
|
5
|
+
* Persistence Plugin for restate (closure-based)
|
|
6
|
+
* (c) 2025 restate contributors
|
|
7
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
8
|
+
*/exports.PersistencePlugin=function(e={}){return function(t){const r={persist:!0,persistKey:"restate",persistStorage:"localStorage",persistDebounce:300,persistInclude:null,persistExclude:null,persistEncrypt:!1,persistIntegrity:!1,persistVersion:1,persistMigrations:{},persistValidateSchema:null,...e};let n=null,s=null,o=null,i=!1,a=null,c=null,l=null;const u="undefined"!=typeof crypto&&crypto.subtle;async function p(e,t,r){const n=new TextEncoder,s=await crypto.subtle.importKey("raw",n.encode(e),"PBKDF2",!1,["deriveBits","deriveKey"]),o="encrypt"===r?{name:"AES-GCM",length:256}:{name:"HMAC",hash:"SHA-256"},i="encrypt"===r?["encrypt","decrypt"]:["sign","verify"];return crypto.subtle.deriveKey({name:"PBKDF2",salt:n.encode(t),iterations:1e5,hash:"SHA-256"},s,o,!1,i)}function y(e,t=new WeakMap){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e);if(t.has(e))return t.get(e);if(Array.isArray(e)){const r=[];t.set(e,r);for(let n=0;n<e.length;n++)r[n]=y(e[n],t);return r}const r={};t.set(e,r);for(const n in e)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=y(e[n],t));return r}function f(){if(!n)return!1;try{return n.hasItem(r.persistKey)}catch(e){return console.error("restate: Error checking persistence:",e),!1}}function m(e,t,r){if(r){const r={};for(const n of t){const t=d(e,n);void 0!==t&&g(r,n,t)}return r}{const r=y(e);for(const e of t)h(r,e);return r}}function d(e,t){return t.split(".").reduce((e,t)=>e&&void 0!==e[t]?e[t]:void 0,e)}function g(e,t,r){const n=t.split(".");let s=e;for(let e=0;e<n.length-1;e++){const t=n[e];t in s&&"object"==typeof s[t]||(s[t]={}),s=s[t]}s[n[n.length-1]]=r}function h(e,t){const r=t.split(".");let n=e;for(let e=0;e<r.length-1;e++){const t=r[e];if(!n[t]||"object"!=typeof n[t])return;n=n[t]}delete n[r[r.length-1]]}async function b(){if(!n)return!1;try{const e=function(){let e=y(t._state);return r.persistInclude?m(e,r.persistInclude,!0):r.persistExclude?m(e,r.persistExclude,!1):e}(),o={version:r.persistVersion,timestamp:Date.now(),state:e};let i=JSON.stringify(o),a=null;l&&(a=await async function(e){if(!l)return null;const t=new TextEncoder,r=await crypto.subtle.sign("HMAC",l,t.encode(e));return btoa(String.fromCharCode(...new Uint8Array(r)))}(i)),c?i=await async function(e){if(!c)return e;const t=new TextEncoder,r=crypto.getRandomValues(new Uint8Array(12)),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},c,t.encode(e)),s=new Uint8Array(r.length+n.byteLength);return s.set(r),s.set(new Uint8Array(n),r.length),btoa(String.fromCharCode(...s))}(i):s&&(i=s(i));const u=a?JSON.stringify({data:i,hmac:a}):i;return n.setItem(r.persistKey,u),!0}catch(e){return console.error("restate: Error saving state:",e),!1}}async function w(){if(!n)return!1;try{if(!f())return!1;let e=n.getItem(r.persistKey),s=e,a=null;try{const t=JSON.parse(e);t&&"object"==typeof t&&"data"in t&&"hmac"in t&&(s=t.data,a=t.hmac)}catch(e){}if(c){if(s=await async function(e){if(!c)return e;try{const t=Uint8Array.from(atob(e),e=>e.charCodeAt(0)),r=t.slice(0,12),n=t.slice(12),s=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},c,n);return(new TextDecoder).decode(s)}catch(e){return console.error("restate: Decryption failed - data may be corrupted or wrong key"),null}}(s),null===s)return console.error("restate: Failed to decrypt persisted state"),!1}else o&&(s=o(s));if(l){const e=await async function(e,t){if(!l)return!0;if(!t)return!1;try{const r=new TextEncoder,n=Uint8Array.from(atob(t),e=>e.charCodeAt(0));return crypto.subtle.verify("HMAC",l,n,r.encode(e))}catch(e){return!1}}(s,a);if(!e)return console.error("restate: Integrity check failed - persisted data may be tampered"),!1}const u=JSON.parse(s);if(r.persistValidateSchema){if(!r.persistValidateSchema(u.state))return console.error("restate: Schema validation failed for persisted state"),!1}const p=function(e){let t=e;const n=r.persistVersion,s=e.version||1;if(s<n){const e=r.persistMigrations;for(let r=s+1;r<=n;r++)if("function"==typeof e[r])try{t={version:r,state:e[r](t.state)}}catch(e){console.error(`restate: Error in migration v${r}:`,e);break}}return t}(u);return function(e){i=!0;const r=t._options.immutable;t._options.immutable=!1;for(const e in t._state)delete t._state[e];Object.assign(t._state,y(e)),t._notifyImmediate("persistence",e),t._options.immutable=r,i=!1}(p.state),!0}catch(e){return console.error("restate: Error loading state:",e),!1}}return{name:"persistence",install:async()=>{r.persist&&(!function(){const e=r.persistStorage;if("string"==typeof e)if("localStorage"===e)n={getItem:e=>localStorage.getItem(e),setItem:(e,t)=>localStorage.setItem(e,t),removeItem:e=>localStorage.removeItem(e),hasItem:e=>null!==localStorage.getItem(e)};else{if("sessionStorage"!==e)throw new Error(`restate: Unknown storage type '${e}'.`);n={getItem:e=>sessionStorage.getItem(e),setItem:(e,t)=>sessionStorage.setItem(e,t),removeItem:e=>sessionStorage.removeItem(e),hasItem:e=>null!==sessionStorage.getItem(e)}}else{if(!e||"object"!=typeof e)throw new Error("restate: persistStorage must be a string or storage adapter object.");{const t=["getItem","setItem","removeItem","hasItem"];for(const r of t)if("function"!=typeof e[r])throw new Error(`restate: Custom storage adapter must implement ${r}()`);n=e}}}(),await async function(){const e=r.persistEncrypt,t=r.persistIntegrity;if(e&&"object"==typeof e&&e.encrypt&&e.decrypt)return s=e.encrypt,void(o=e.decrypt);if(e&&u){const t="string"==typeof e?e:r.persistKey,n=`restate-aes-${r.persistKey}`;c=await p(t,n,"encrypt")}else e&&!u&&console.warn("restate: Web Crypto API not available. Encryption disabled.");if(t&&u){const n="string"==typeof t?t:"string"==typeof e?e:r.persistKey,s=`restate-hmac-${r.persistKey}`;l=await p(n,s,"hmac")}else t&&!u&&console.warn("restate: Web Crypto API not available. Integrity checking disabled.")}(),f()&&await w())},methods:{$save:()=>b(),$load:()=>w(),$clear:()=>function(){if(!n)return!1;try{return n.removeItem(r.persistKey),!0}catch(e){return console.error("restate: Error clearing persisted state:",e),!1}}(),$exists:()=>f(),$setPersistenceOptions:e=>(Object.assign(r,e),t._proxy),$setEncryption:(e,r)=>(s=e,o=r,t._proxy)},hooks:{afterNotify:()=>{r.persist&&!i&&(a&&clearTimeout(a),a=setTimeout(()=>b(),r.persistDebounce))},onDestroy:()=>{a&&(clearTimeout(a),a=null)}}}}};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/persistence v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
/*!
|
|
3
|
+
* restate PersistencePlugin v1.0.0
|
|
4
|
+
* Persistence Plugin for restate (closure-based)
|
|
5
|
+
* (c) 2025 restate contributors
|
|
6
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
7
|
+
*/
|
|
8
|
+
function e(e={}){return function(t){const r={persist:!0,persistKey:"restate",persistStorage:"localStorage",persistDebounce:300,persistInclude:null,persistExclude:null,persistEncrypt:!1,persistIntegrity:!1,persistVersion:1,persistMigrations:{},persistValidateSchema:null,...e};let n=null,s=null,o=null,i=!1,a=null,c=null,l=null;const u="undefined"!=typeof crypto&&crypto.subtle;async function p(e,t,r){const n=new TextEncoder,s=await crypto.subtle.importKey("raw",n.encode(e),"PBKDF2",!1,["deriveBits","deriveKey"]),o="encrypt"===r?{name:"AES-GCM",length:256}:{name:"HMAC",hash:"SHA-256"},i="encrypt"===r?["encrypt","decrypt"]:["sign","verify"];return crypto.subtle.deriveKey({name:"PBKDF2",salt:n.encode(t),iterations:1e5,hash:"SHA-256"},s,o,!1,i)}function y(e,t=new WeakMap){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e);if(t.has(e))return t.get(e);if(Array.isArray(e)){const r=[];t.set(e,r);for(let n=0;n<e.length;n++)r[n]=y(e[n],t);return r}const r={};t.set(e,r);for(const n in e)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=y(e[n],t));return r}function f(){if(!n)return!1;try{return n.hasItem(r.persistKey)}catch(e){return console.error("restate: Error checking persistence:",e),!1}}function m(e,t,r){if(r){const r={};for(const n of t){const t=d(e,n);void 0!==t&&g(r,n,t)}return r}{const r=y(e);for(const e of t)h(r,e);return r}}function d(e,t){return t.split(".").reduce((e,t)=>e&&void 0!==e[t]?e[t]:void 0,e)}function g(e,t,r){const n=t.split(".");let s=e;for(let e=0;e<n.length-1;e++){const t=n[e];t in s&&"object"==typeof s[t]||(s[t]={}),s=s[t]}s[n[n.length-1]]=r}function h(e,t){const r=t.split(".");let n=e;for(let e=0;e<r.length-1;e++){const t=r[e];if(!n[t]||"object"!=typeof n[t])return;n=n[t]}delete n[r[r.length-1]]}async function b(){if(!n)return!1;try{const e=function(){let e=y(t._state);return r.persistInclude?m(e,r.persistInclude,!0):r.persistExclude?m(e,r.persistExclude,!1):e}(),o={version:r.persistVersion,timestamp:Date.now(),state:e};let i=JSON.stringify(o),a=null;l&&(a=await async function(e){if(!l)return null;const t=new TextEncoder,r=await crypto.subtle.sign("HMAC",l,t.encode(e));return btoa(String.fromCharCode(...new Uint8Array(r)))}(i)),c?i=await async function(e){if(!c)return e;const t=new TextEncoder,r=crypto.getRandomValues(new Uint8Array(12)),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},c,t.encode(e)),s=new Uint8Array(r.length+n.byteLength);return s.set(r),s.set(new Uint8Array(n),r.length),btoa(String.fromCharCode(...s))}(i):s&&(i=s(i));const u=a?JSON.stringify({data:i,hmac:a}):i;return n.setItem(r.persistKey,u),!0}catch(e){return console.error("restate: Error saving state:",e),!1}}async function w(){if(!n)return!1;try{if(!f())return!1;let e=n.getItem(r.persistKey),s=e,a=null;try{const t=JSON.parse(e);t&&"object"==typeof t&&"data"in t&&"hmac"in t&&(s=t.data,a=t.hmac)}catch(e){}if(c){if(s=await async function(e){if(!c)return e;try{const t=Uint8Array.from(atob(e),e=>e.charCodeAt(0)),r=t.slice(0,12),n=t.slice(12),s=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},c,n);return(new TextDecoder).decode(s)}catch(e){return console.error("restate: Decryption failed - data may be corrupted or wrong key"),null}}(s),null===s)return console.error("restate: Failed to decrypt persisted state"),!1}else o&&(s=o(s));if(l){const e=await async function(e,t){if(!l)return!0;if(!t)return!1;try{const r=new TextEncoder,n=Uint8Array.from(atob(t),e=>e.charCodeAt(0));return crypto.subtle.verify("HMAC",l,n,r.encode(e))}catch(e){return!1}}(s,a);if(!e)return console.error("restate: Integrity check failed - persisted data may be tampered"),!1}const u=JSON.parse(s);if(r.persistValidateSchema){if(!r.persistValidateSchema(u.state))return console.error("restate: Schema validation failed for persisted state"),!1}const p=function(e){let t=e;const n=r.persistVersion,s=e.version||1;if(s<n){const e=r.persistMigrations;for(let r=s+1;r<=n;r++)if("function"==typeof e[r])try{t={version:r,state:e[r](t.state)}}catch(e){console.error(`restate: Error in migration v${r}:`,e);break}}return t}(u);return function(e){i=!0;const r=t._options.immutable;t._options.immutable=!1;for(const e in t._state)delete t._state[e];Object.assign(t._state,y(e)),t._notifyImmediate("persistence",e),t._options.immutable=r,i=!1}(p.state),!0}catch(e){return console.error("restate: Error loading state:",e),!1}}return{name:"persistence",install:async()=>{r.persist&&(!function(){const e=r.persistStorage;if("string"==typeof e)if("localStorage"===e)n={getItem:e=>localStorage.getItem(e),setItem:(e,t)=>localStorage.setItem(e,t),removeItem:e=>localStorage.removeItem(e),hasItem:e=>null!==localStorage.getItem(e)};else{if("sessionStorage"!==e)throw new Error(`restate: Unknown storage type '${e}'.`);n={getItem:e=>sessionStorage.getItem(e),setItem:(e,t)=>sessionStorage.setItem(e,t),removeItem:e=>sessionStorage.removeItem(e),hasItem:e=>null!==sessionStorage.getItem(e)}}else{if(!e||"object"!=typeof e)throw new Error("restate: persistStorage must be a string or storage adapter object.");{const t=["getItem","setItem","removeItem","hasItem"];for(const r of t)if("function"!=typeof e[r])throw new Error(`restate: Custom storage adapter must implement ${r}()`);n=e}}}(),await async function(){const e=r.persistEncrypt,t=r.persistIntegrity;if(e&&"object"==typeof e&&e.encrypt&&e.decrypt)return s=e.encrypt,void(o=e.decrypt);if(e&&u){const t="string"==typeof e?e:r.persistKey,n=`restate-aes-${r.persistKey}`;c=await p(t,n,"encrypt")}else e&&!u&&console.warn("restate: Web Crypto API not available. Encryption disabled.");if(t&&u){const n="string"==typeof t?t:"string"==typeof e?e:r.persistKey,s=`restate-hmac-${r.persistKey}`;l=await p(n,s,"hmac")}else t&&!u&&console.warn("restate: Web Crypto API not available. Integrity checking disabled.")}(),f()&&await w())},methods:{$save:()=>b(),$load:()=>w(),$clear:()=>function(){if(!n)return!1;try{return n.removeItem(r.persistKey),!0}catch(e){return console.error("restate: Error clearing persisted state:",e),!1}}(),$exists:()=>f(),$setPersistenceOptions:e=>(Object.assign(r,e),t._proxy),$setEncryption:(e,r)=>(s=e,o=r,t._proxy)},hooks:{afterNotify:()=>{r.persist&&!i&&(a&&clearTimeout(a),a=setTimeout(()=>b(),r.persistDebounce))},onDestroy:()=>{a&&(clearTimeout(a),a=null)}}}}}export{e as PersistencePlugin};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/validate v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";
|
|
3
|
+
/*!
|
|
4
|
+
* restate ValidatePlugin v1.0.0
|
|
5
|
+
* Plugin to validate types or values on set operations
|
|
6
|
+
* (c) 2025 restate contributors
|
|
7
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
8
|
+
*/exports.ValidatePlugin=function(n={}){return function(t){const e={...n};function r(n,t){const r=n.join("."),i=e[r];if("function"==typeof i){if(!i(t))throw new TypeError(`Validation failed for '${r}': received ${function(n){if(null===n)return"null";if(void 0===n)return"undefined";const t=typeof n;return"string"===t?n.length>20?`[string, ${n.length} chars]`:`"${n.slice(0,20)}"`:"number"===t||"boolean"===t?String(n):Array.isArray(n)?`[array, ${n.length} items]`:"object"===t?`[object, ${Object.keys(n).length} keys]`:"function"===t?"[function]":`[${t}]`}(t)}`)}}return{name:"validation",hooks:{beforeSet(n,t,e,i){r(i.concat(t),e)}},methods:{$validators:n=>(Object.assign(e,n),t._proxy)}}}};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/*! plugin/validate v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
/*!
|
|
3
|
+
* restate ValidatePlugin v1.0.0
|
|
4
|
+
* Plugin to validate types or values on set operations
|
|
5
|
+
* (c) 2025 restate contributors
|
|
6
|
+
* Released under the SEE LICENSE IN EULA-COMMERCIAL.md License
|
|
7
|
+
*/
|
|
8
|
+
function n(n={}){return function(t){const e={...n};function o(n,t){const o=n.join("."),r=e[o];if("function"==typeof r){if(!r(t))throw new TypeError(`Validation failed for '${o}': received ${function(n){if(null===n)return"null";if(void 0===n)return"undefined";const t=typeof n;return"string"===t?n.length>20?`[string, ${n.length} chars]`:`"${n.slice(0,20)}"`:"number"===t||"boolean"===t?String(n):Array.isArray(n)?`[array, ${n.length} items]`:"object"===t?`[object, ${Object.keys(n).length} keys]`:"function"===t?"[function]":`[${t}]`}(t)}`)}}return{name:"validation",hooks:{beforeSet(n,t,e,r){o(r.concat(t),e)}},methods:{$validators:n=>(Object.assign(e,n),t._proxy)}}}}export{n as ValidatePlugin};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! restate v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
"use strict";const e=["$onChange","$watch","$unwatch","$set","$computed","$dependencies","$methods","$destroy","$registry","use"],t=["_"];class s{constructor(e={},t={}){this._state=e,this._exactWatchers=new Map,this._shallowWildcards=new Map,this._deepWildcards=new Map,this._proxyCache=new WeakMap,this._computed={},this._computedDependencies=new Map,this._computedCache=new Map,this._tracking=!1,this._currentComputedKey=null,this._accessedPaths=new Set,this._maxDepth=t.maxDepth||100,this._onChange=null,this._isDestroyed=!1,this._bulkMode=!1,this._bulkChanges=new Map,this._plugins=new Map,this._pluginLoadOrder=[],this._pluginHooks={beforeNotify:[],afterNotify:[],beforeSet:[],afterSet:[],beforeBulk:[],afterBulk:[],onDestroy:[]},this._methodRegistry=new Map,this._proxy=this._wrap(e,[],!0),this._setupProxyMethods(),t.plugins&&t.plugins.forEach(e=>this.use(e))}_registerMethod(e,t,s=!1,r=null){this._methodRegistry.set(e,{source:t,configurable:s,originalFn:r})}_isReservedPrefix(e){return t.some(t=>e.startsWith(t))}_checkMethodCollision(t,s,r=!1){if(this._isReservedPrefix(t))return{error:`Plugin '${s}' cannot define method '${t}': names starting with '_' are reserved for internal use`};const i=this._methodRegistry.get(t);if(!i)return null;if(e.includes(t))return{error:`Plugin '${s}' cannot override core method '${t}'`};if(!r){const e=this._pluginLoadOrder,r=i.source.startsWith("plugin:")?e.indexOf(i.source.replace("plugin:",""))+1:0,o=e.indexOf(s)+1;return{error:`Method collision: '${t}'\n - First defined by: ${i.source}${r?` (loaded #${r})`:""}\n - Attempted by: plugin '${s}'${o?` (loaded #${o})`:""}\n Consider renaming the method or using 'overrides: ["${t}"]' in the plugin definition.`}}return i.configurable?null:{error:`Plugin '${s}' cannot override '${t}': method is not configurable (defined by ${i.source})`}}use(e){if("function"==typeof e&&(e=e(this)),!e.name)throw new Error("Plugin must have a name");if(this._plugins.has(e.name))throw new Error(`Plugin '${e.name}' is already registered`);if(this._pluginLoadOrder.push(e.name),this._plugins.set(e.name,e),e.hooks&&Object.keys(e.hooks).forEach(t=>{this._pluginHooks[t]&&this._pluginHooks[t].push(e.hooks[t])}),e.wrap&&Object.keys(e.wrap).forEach(t=>{const s=e.wrap[t],r=this._methodRegistry.get(t);if(!r)throw new Error(`Plugin '${e.name}' attempted to wrap '${t}', but it doesn't exist.\n Available methods: ${Array.from(this._methodRegistry.keys()).join(", ")}`);if("function"!=typeof s)throw new Error(`Plugin '${e.name}': wrap['${t}'] must be a function`);const i=this._proxy[t];if("function"!=typeof i)throw new Error(`Plugin '${e.name}': cannot wrap '${t}' - it's not a function`);const o=s(i.bind(this._proxy));Object.defineProperty(this._proxy,t,{value:o.bind(this),enumerable:!1,configurable:!0,writable:!0}),this._methodRegistry.set(t,{...r,wrappedBy:e.name,originalFn:i})}),e.methods){const t=e.overrides||[];Object.keys(e.methods).forEach(s=>{const r=t.includes(s),i=this._checkMethodCollision(s,e.name,r);if(i)throw new Error(i.error);if(r&&this._methodRegistry.has(s)){const t=this._methodRegistry.get(s);console.warn(`restate: Plugin '${e.name}' is overriding method '${s}' (previously defined by ${t.source})`)}Object.defineProperty(this._proxy,s,{value:e.methods[s].bind(this),enumerable:!1,configurable:!0,writable:!0}),this._registerMethod(s,`plugin:${e.name}`,!0)})}return e.install&&e.install.call(this),this}_notify(e,t,s){this._isDestroyed||(this._runHooks("beforeNotify",e,t,s),this._bulkMode?this._bulkChanges.set(e,t):this._notifyImmediate(e,t,s))}_notifyImmediate(e,t,s){if(this._isDestroyed)return;if("function"==typeof this._onChange)try{this._onChange(e,t,s)}catch(e){console.error("restate: Error in onChange handler:",e)}const r=this._exactWatchers.get(e);if(r)try{r(e,t,s)}catch(t){console.error(`restate: Error in watcher for '${e}':`,t)}const i=e.split(".");if(i.length>=2){const r=i.slice(0,-1).join("."),o=this._shallowWildcards.get(r);if(o)for(const i of o)try{i(e,t,s)}catch(e){console.error(`restate: Error in watcher for '${r}.*':`,e)}}let o="";for(let r=0;r<i.length-1;r++){o=0===r?i[0]:o+"."+i[r];const n=this._deepWildcards.get(o);if(n)for(const r of n)try{r(e,t,s)}catch(e){console.error(`restate: Error in watcher for '${o}.**':`,e)}}this._runHooks("afterNotify",e,t,s)}_runHooks(e,...t){const s="beforeSet"===e;this._pluginHooks[e].forEach(r=>{if(s)r.call(this,...t);else try{r.call(this,...t)}catch(t){console.error(`restate: Error in ${e} hook:`,t)}})}_bulk(e){if(!this._isDestroyed){if(this._bulkMode)return e(this._proxy);this._runHooks("beforeBulk"),this._bulkMode=!0;try{const t=e(this._proxy);return this._flushBulkChanges(),t}finally{this._bulkMode=!1,this._runHooks("afterBulk")}}}_flushBulkChanges(){if(0!==this._bulkChanges.size){if("function"==typeof this._onChange)try{this._onChange("bulk",Array.from(this._bulkChanges.entries()))}catch(e){console.error("restate: Error in onChange during bulk:",e)}for(const[e,t]of this._bulkChanges){const s=this._exactWatchers.get(e);if(s)try{s(e,t)}catch(t){console.error(`restate: Error in watcher for '${e}':`,t)}const r=e.split(".");if(r.length>=2){const s=r.slice(0,-1).join("."),i=this._shallowWildcards.get(s);if(i)for(const r of i)try{r(e,t)}catch(e){console.error(`restate: Error in watcher for '${s}.*':`,e)}}let i="";for(let s=0;s<r.length-1;s++){i=0===s?r[0]:i+"."+r[s];const o=this._deepWildcards.get(i);if(o)for(const s of o)try{s(e,t)}catch(e){console.error(`restate: Error in watcher for '${i}.**':`,e)}}}this._bulkChanges.clear()}}_getComputedValue(e,t){if(this._computedCache.has(e))return this._computedCache.get(e);if(this._computedCallStack||(this._computedCallStack=new Set),this._computedCallStack.has(e))return void console.error(`restate: Circular dependency detected in computed property '${e}'`);this._computedCallStack.add(e);const s=this._tracking,r=this._currentComputedKey,i=s?[...this._accessedPaths]:null;let o;this._tracking=!0,this._currentComputedKey=e,this._accessedPaths.clear();try{o=t(this._proxy)}catch(t){console.error(`restate: Error computing '${e}':`,t),o=void 0}if(this._computedDependencies.set(e,new Set(this._accessedPaths)),this._computedCache.set(e,o),this._computedCallStack.delete(e),this._tracking=s,this._currentComputedKey=r,i){this._accessedPaths.clear();for(const e of i)this._accessedPaths.add(e)}return o}_invalidateComputed(e){const t=new Set,s=[e];for(;s.length>0;){const e=s.shift(),r=[];for(const[s,i]of this._computedDependencies)i.has(e)&&!t.has(s)&&r.push(s);for(const e of r)this._computedCache.delete(e),this._computedDependencies.delete(e),t.add(e),s.push(e)}}_wrap(e,t=[],s=!1){if(this._isDestroyed)return e;if("object"!=typeof e||null===e)return e;if(t.length>this._maxDepth)return e;if(!s&&this._proxyCache.has(e))return this._proxyCache.get(e);if(Array.isArray(e))return this._wrapArray(e,t);const r=new Proxy(e,{get:(e,r)=>{if(this._isDestroyed)return e[r];const i=String(r);if(s&&i in this._computed)return this._tracking&&this._currentComputedKey&&this._currentComputedKey!==i&&this._accessedPaths.add(i),this._getComputedValue(i,this._computed[i]);if(this._tracking&&this._currentComputedKey){const e=t.length>0?t.concat(r).join("."):i;this._accessedPaths.add(e)}const o=e[r];return"object"==typeof o&&null!==o?this._wrap(o,t.concat(r)):o},set:(e,s,r)=>{if(this._isDestroyed)return!1;this._runHooks("beforeSet",e,s,r,t);const i=e[s];if(i!==r){"object"==typeof i&&null!==i&&this._proxyCache.delete(i),e[s]=r;const o=t.concat(s).join(".");this._invalidateComputed(String(s)),t.length>0&&this._invalidateComputed(o),this._notify(o,r,i)}return this._runHooks("afterSet",e,s,r,t),!0},has:(e,t)=>{const r=String(t);return!(!s||!(r in this._computed))||t in e},ownKeys:e=>{const t=Reflect.ownKeys(e);if(s){const e=Object.keys(this._computed);for(const s of e)t.includes(s)||t.push(s)}return t},getOwnPropertyDescriptor:(e,t)=>{const r=String(t);return s&&r in this._computed?{configurable:!0,enumerable:!0,value:this._getComputedValue(r,this._computed[r])}:Object.getOwnPropertyDescriptor(e,t)}});return s||this._proxyCache.set(e,r),r}_wrapArray(e,t){if(t.length>this._maxDepth)return e;if(this._proxyCache.has(e))return this._proxyCache.get(e);const s=new Proxy(e,{get:(e,s)=>{if(this._isDestroyed)return e[s];if(this._tracking&&this._currentComputedKey){const e=t.concat(s).join(".");this._accessedPaths.add(e)}if("function"==typeof e[s])return this._wrapArrayMethod(e,s,t);const r=e[s];return"object"==typeof r&&null!==r?this._wrap(r,t.concat(s)):r},set:(e,s,r)=>{if(this._isDestroyed)return!1;const i=e[s];if(i!==r&&("object"==typeof i&&null!==i&&this._proxyCache.delete(i),e[s]=r,!isNaN(s))){const i=t.concat(s).join(".");this._invalidateComputed(i),this._notify(i,r),this._notify(t.concat("length").join("."),e.length)}return!0}});return this._proxyCache.set(e,s),s}_wrapArrayMethod(e,t,s){const r=e[t],i=["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"];return function(...o){if(this._isDestroyed)return r.apply(e,o);const n=e.length,h=r.apply(e,o);if(i.includes(t)){const t=s.join(".");this._invalidateComputed(t),this._notify(t,e),e.length!==n&&this._notify(s.concat("length").join("."),e.length)}return h}.bind(this)}_addWatcher(e,t){if(e.endsWith(".**")){const s=e.slice(0,-3);this._deepWildcards.has(s)||this._deepWildcards.set(s,new Set),this._deepWildcards.get(s).add(t)}else if(e.endsWith(".*")){const s=e.slice(0,-2);this._shallowWildcards.has(s)||this._shallowWildcards.set(s,new Set),this._shallowWildcards.get(s).add(t)}else this._exactWatchers.set(e,t)}_removeWatcher(e){if(e.endsWith(".**")){const t=e.slice(0,-3);this._deepWildcards.delete(t)}else if(e.endsWith(".*")){const t=e.slice(0,-2);this._shallowWildcards.delete(t)}else this._exactWatchers.delete(e)}_clearAllWatchers(){this._exactWatchers.clear(),this._shallowWildcards.clear(),this._deepWildcards.clear()}_setupProxyMethods(){const t=(e,t)=>{Object.defineProperty(this._proxy,e,{value:t,enumerable:!1,configurable:!1,writable:!1}),this._registerMethod(e,"core",!1)};t("$onChange",e=>(this._onChange=e,this._proxy)),t("$watch",(e,t)=>"function"==typeof t?(this._addWatcher(e,t),()=>this._proxy.$unwatch(e)):this._proxy),t("$unwatch",e=>(this._removeWatcher(e),this._proxy)),t("$set",e=>"function"==typeof e?this._bulk(e):this._bulk(t=>{this._applyUpdates(t,e)})),t("$computed",e=>{const t=["__proto__","constructor","prototype"];for(const[s,r]of Object.entries(e))t.includes(s)?console.warn(`restate: Skipping reserved computed key '${s}'`):"function"==typeof r?this._computed[s]=r:console.warn(`restate: Computed property '${s}' must be a function`);return this._proxy}),t("$dependencies",()=>{const e={};for(const[t,s]of this._computedDependencies)e[t]=Array.from(s);return e}),t("$methods",t=>(Object.entries(t).forEach(([t,s])=>{if("function"!=typeof s)throw new Error(`restate: Method '${t}' must be a function`);if(e.includes(t))throw new Error(`restate: Cannot define method '${t}' - it's a reserved core method`);if(this._isReservedPrefix(t))throw new Error(`restate: Cannot define method '${t}' - names starting with '_' are reserved`);const r=this._methodRegistry.get(t);r&&r.source.startsWith("plugin:")&&console.warn(`restate: $methods() is overriding '${t}' (previously defined by ${r.source})`),Object.defineProperty(this._proxy,t,{value:s.bind(this._proxy),enumerable:!1,writable:!0,configurable:!0}),this._registerMethod(t,"user",!0)}),this._proxy)),t("$registry",()=>{const e={};for(const[t,s]of this._methodRegistry)e[t]={...s},delete e[t].originalFn;return e}),t("$destroy",()=>(this._runHooks("onDestroy"),this._isDestroyed=!0,this._clearAllWatchers(),this._onChange=null,this._plugins.clear(),this._pluginLoadOrder=[],this._methodRegistry.clear(),this._proxyCache=new WeakMap,this._computed={},this._computedDependencies.clear(),this._computedCache.clear(),this._computedCallStack&&this._computedCallStack.clear(),this._proxy))}_applyUpdates(e,t,s=[]){if(this._isDestroyed)return;const r=["__proto__","constructor","prototype"];for(const[i,o]of Object.entries(t))r.includes(i)||("object"!=typeof o||null===o||Array.isArray(o)?e[i]=o:(e[i]&&"object"==typeof e[i]||(e[i]={}),this._applyUpdates(e[i],o,s.concat(i))))}}exports.restate=function(e={}){const t=new s(e,{plugins:[]}),r=t._proxy;return r.use=function(e,s){const r="function"==typeof e?e(t):e;return t.use(r),t._proxy},r};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! restate v0.2.0 | Copyright (c) 2025 Yannick J.A. Charlery (https://github.com/ynck-chrl/restate) | PolyForm Noncommercial 1.0.0 | https://polyformproject.org/licenses/noncommercial/1.0.0 | Commercial: info@nativelayer.dev */
|
|
2
|
+
const e=["$onChange","$watch","$unwatch","$set","$computed","$dependencies","$methods","$destroy","$registry","use"],t=["_"];class s{constructor(e={},t={}){this._state=e,this._exactWatchers=new Map,this._shallowWildcards=new Map,this._deepWildcards=new Map,this._proxyCache=new WeakMap,this._computed={},this._computedDependencies=new Map,this._computedCache=new Map,this._tracking=!1,this._currentComputedKey=null,this._accessedPaths=new Set,this._maxDepth=t.maxDepth||100,this._onChange=null,this._isDestroyed=!1,this._bulkMode=!1,this._bulkChanges=new Map,this._plugins=new Map,this._pluginLoadOrder=[],this._pluginHooks={beforeNotify:[],afterNotify:[],beforeSet:[],afterSet:[],beforeBulk:[],afterBulk:[],onDestroy:[]},this._methodRegistry=new Map,this._proxy=this._wrap(e,[],!0),this._setupProxyMethods(),t.plugins&&t.plugins.forEach(e=>this.use(e))}_registerMethod(e,t,s=!1,r=null){this._methodRegistry.set(e,{source:t,configurable:s,originalFn:r})}_isReservedPrefix(e){return t.some(t=>e.startsWith(t))}_checkMethodCollision(t,s,r=!1){if(this._isReservedPrefix(t))return{error:`Plugin '${s}' cannot define method '${t}': names starting with '_' are reserved for internal use`};const i=this._methodRegistry.get(t);if(!i)return null;if(e.includes(t))return{error:`Plugin '${s}' cannot override core method '${t}'`};if(!r){const e=this._pluginLoadOrder,r=i.source.startsWith("plugin:")?e.indexOf(i.source.replace("plugin:",""))+1:0,o=e.indexOf(s)+1;return{error:`Method collision: '${t}'\n - First defined by: ${i.source}${r?` (loaded #${r})`:""}\n - Attempted by: plugin '${s}'${o?` (loaded #${o})`:""}\n Consider renaming the method or using 'overrides: ["${t}"]' in the plugin definition.`}}return i.configurable?null:{error:`Plugin '${s}' cannot override '${t}': method is not configurable (defined by ${i.source})`}}use(e){if("function"==typeof e&&(e=e(this)),!e.name)throw new Error("Plugin must have a name");if(this._plugins.has(e.name))throw new Error(`Plugin '${e.name}' is already registered`);if(this._pluginLoadOrder.push(e.name),this._plugins.set(e.name,e),e.hooks&&Object.keys(e.hooks).forEach(t=>{this._pluginHooks[t]&&this._pluginHooks[t].push(e.hooks[t])}),e.wrap&&Object.keys(e.wrap).forEach(t=>{const s=e.wrap[t],r=this._methodRegistry.get(t);if(!r)throw new Error(`Plugin '${e.name}' attempted to wrap '${t}', but it doesn't exist.\n Available methods: ${Array.from(this._methodRegistry.keys()).join(", ")}`);if("function"!=typeof s)throw new Error(`Plugin '${e.name}': wrap['${t}'] must be a function`);const i=this._proxy[t];if("function"!=typeof i)throw new Error(`Plugin '${e.name}': cannot wrap '${t}' - it's not a function`);const o=s(i.bind(this._proxy));Object.defineProperty(this._proxy,t,{value:o.bind(this),enumerable:!1,configurable:!0,writable:!0}),this._methodRegistry.set(t,{...r,wrappedBy:e.name,originalFn:i})}),e.methods){const t=e.overrides||[];Object.keys(e.methods).forEach(s=>{const r=t.includes(s),i=this._checkMethodCollision(s,e.name,r);if(i)throw new Error(i.error);if(r&&this._methodRegistry.has(s)){const t=this._methodRegistry.get(s);console.warn(`restate: Plugin '${e.name}' is overriding method '${s}' (previously defined by ${t.source})`)}Object.defineProperty(this._proxy,s,{value:e.methods[s].bind(this),enumerable:!1,configurable:!0,writable:!0}),this._registerMethod(s,`plugin:${e.name}`,!0)})}return e.install&&e.install.call(this),this}_notify(e,t,s){this._isDestroyed||(this._runHooks("beforeNotify",e,t,s),this._bulkMode?this._bulkChanges.set(e,t):this._notifyImmediate(e,t,s))}_notifyImmediate(e,t,s){if(this._isDestroyed)return;if("function"==typeof this._onChange)try{this._onChange(e,t,s)}catch(e){console.error("restate: Error in onChange handler:",e)}const r=this._exactWatchers.get(e);if(r)try{r(e,t,s)}catch(t){console.error(`restate: Error in watcher for '${e}':`,t)}const i=e.split(".");if(i.length>=2){const r=i.slice(0,-1).join("."),o=this._shallowWildcards.get(r);if(o)for(const i of o)try{i(e,t,s)}catch(e){console.error(`restate: Error in watcher for '${r}.*':`,e)}}let o="";for(let r=0;r<i.length-1;r++){o=0===r?i[0]:o+"."+i[r];const n=this._deepWildcards.get(o);if(n)for(const r of n)try{r(e,t,s)}catch(e){console.error(`restate: Error in watcher for '${o}.**':`,e)}}this._runHooks("afterNotify",e,t,s)}_runHooks(e,...t){const s="beforeSet"===e;this._pluginHooks[e].forEach(r=>{if(s)r.call(this,...t);else try{r.call(this,...t)}catch(t){console.error(`restate: Error in ${e} hook:`,t)}})}_bulk(e){if(!this._isDestroyed){if(this._bulkMode)return e(this._proxy);this._runHooks("beforeBulk"),this._bulkMode=!0;try{const t=e(this._proxy);return this._flushBulkChanges(),t}finally{this._bulkMode=!1,this._runHooks("afterBulk")}}}_flushBulkChanges(){if(0!==this._bulkChanges.size){if("function"==typeof this._onChange)try{this._onChange("bulk",Array.from(this._bulkChanges.entries()))}catch(e){console.error("restate: Error in onChange during bulk:",e)}for(const[e,t]of this._bulkChanges){const s=this._exactWatchers.get(e);if(s)try{s(e,t)}catch(t){console.error(`restate: Error in watcher for '${e}':`,t)}const r=e.split(".");if(r.length>=2){const s=r.slice(0,-1).join("."),i=this._shallowWildcards.get(s);if(i)for(const r of i)try{r(e,t)}catch(e){console.error(`restate: Error in watcher for '${s}.*':`,e)}}let i="";for(let s=0;s<r.length-1;s++){i=0===s?r[0]:i+"."+r[s];const o=this._deepWildcards.get(i);if(o)for(const s of o)try{s(e,t)}catch(e){console.error(`restate: Error in watcher for '${i}.**':`,e)}}}this._bulkChanges.clear()}}_getComputedValue(e,t){if(this._computedCache.has(e))return this._computedCache.get(e);if(this._computedCallStack||(this._computedCallStack=new Set),this._computedCallStack.has(e))return void console.error(`restate: Circular dependency detected in computed property '${e}'`);this._computedCallStack.add(e);const s=this._tracking,r=this._currentComputedKey,i=s?[...this._accessedPaths]:null;let o;this._tracking=!0,this._currentComputedKey=e,this._accessedPaths.clear();try{o=t(this._proxy)}catch(t){console.error(`restate: Error computing '${e}':`,t),o=void 0}if(this._computedDependencies.set(e,new Set(this._accessedPaths)),this._computedCache.set(e,o),this._computedCallStack.delete(e),this._tracking=s,this._currentComputedKey=r,i){this._accessedPaths.clear();for(const e of i)this._accessedPaths.add(e)}return o}_invalidateComputed(e){const t=new Set,s=[e];for(;s.length>0;){const e=s.shift(),r=[];for(const[s,i]of this._computedDependencies)i.has(e)&&!t.has(s)&&r.push(s);for(const e of r)this._computedCache.delete(e),this._computedDependencies.delete(e),t.add(e),s.push(e)}}_wrap(e,t=[],s=!1){if(this._isDestroyed)return e;if("object"!=typeof e||null===e)return e;if(t.length>this._maxDepth)return e;if(!s&&this._proxyCache.has(e))return this._proxyCache.get(e);if(Array.isArray(e))return this._wrapArray(e,t);const r=new Proxy(e,{get:(e,r)=>{if(this._isDestroyed)return e[r];const i=String(r);if(s&&i in this._computed)return this._tracking&&this._currentComputedKey&&this._currentComputedKey!==i&&this._accessedPaths.add(i),this._getComputedValue(i,this._computed[i]);if(this._tracking&&this._currentComputedKey){const e=t.length>0?t.concat(r).join("."):i;this._accessedPaths.add(e)}const o=e[r];return"object"==typeof o&&null!==o?this._wrap(o,t.concat(r)):o},set:(e,s,r)=>{if(this._isDestroyed)return!1;this._runHooks("beforeSet",e,s,r,t);const i=e[s];if(i!==r){"object"==typeof i&&null!==i&&this._proxyCache.delete(i),e[s]=r;const o=t.concat(s).join(".");this._invalidateComputed(String(s)),t.length>0&&this._invalidateComputed(o),this._notify(o,r,i)}return this._runHooks("afterSet",e,s,r,t),!0},has:(e,t)=>{const r=String(t);return!(!s||!(r in this._computed))||t in e},ownKeys:e=>{const t=Reflect.ownKeys(e);if(s){const e=Object.keys(this._computed);for(const s of e)t.includes(s)||t.push(s)}return t},getOwnPropertyDescriptor:(e,t)=>{const r=String(t);return s&&r in this._computed?{configurable:!0,enumerable:!0,value:this._getComputedValue(r,this._computed[r])}:Object.getOwnPropertyDescriptor(e,t)}});return s||this._proxyCache.set(e,r),r}_wrapArray(e,t){if(t.length>this._maxDepth)return e;if(this._proxyCache.has(e))return this._proxyCache.get(e);const s=new Proxy(e,{get:(e,s)=>{if(this._isDestroyed)return e[s];if(this._tracking&&this._currentComputedKey){const e=t.concat(s).join(".");this._accessedPaths.add(e)}if("function"==typeof e[s])return this._wrapArrayMethod(e,s,t);const r=e[s];return"object"==typeof r&&null!==r?this._wrap(r,t.concat(s)):r},set:(e,s,r)=>{if(this._isDestroyed)return!1;const i=e[s];if(i!==r&&("object"==typeof i&&null!==i&&this._proxyCache.delete(i),e[s]=r,!isNaN(s))){const i=t.concat(s).join(".");this._invalidateComputed(i),this._notify(i,r),this._notify(t.concat("length").join("."),e.length)}return!0}});return this._proxyCache.set(e,s),s}_wrapArrayMethod(e,t,s){const r=e[t],i=["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"];return function(...o){if(this._isDestroyed)return r.apply(e,o);const n=e.length,h=r.apply(e,o);if(i.includes(t)){const t=s.join(".");this._invalidateComputed(t),this._notify(t,e),e.length!==n&&this._notify(s.concat("length").join("."),e.length)}return h}.bind(this)}_addWatcher(e,t){if(e.endsWith(".**")){const s=e.slice(0,-3);this._deepWildcards.has(s)||this._deepWildcards.set(s,new Set),this._deepWildcards.get(s).add(t)}else if(e.endsWith(".*")){const s=e.slice(0,-2);this._shallowWildcards.has(s)||this._shallowWildcards.set(s,new Set),this._shallowWildcards.get(s).add(t)}else this._exactWatchers.set(e,t)}_removeWatcher(e){if(e.endsWith(".**")){const t=e.slice(0,-3);this._deepWildcards.delete(t)}else if(e.endsWith(".*")){const t=e.slice(0,-2);this._shallowWildcards.delete(t)}else this._exactWatchers.delete(e)}_clearAllWatchers(){this._exactWatchers.clear(),this._shallowWildcards.clear(),this._deepWildcards.clear()}_setupProxyMethods(){const t=(e,t)=>{Object.defineProperty(this._proxy,e,{value:t,enumerable:!1,configurable:!1,writable:!1}),this._registerMethod(e,"core",!1)};t("$onChange",e=>(this._onChange=e,this._proxy)),t("$watch",(e,t)=>"function"==typeof t?(this._addWatcher(e,t),()=>this._proxy.$unwatch(e)):this._proxy),t("$unwatch",e=>(this._removeWatcher(e),this._proxy)),t("$set",e=>"function"==typeof e?this._bulk(e):this._bulk(t=>{this._applyUpdates(t,e)})),t("$computed",e=>{const t=["__proto__","constructor","prototype"];for(const[s,r]of Object.entries(e))t.includes(s)?console.warn(`restate: Skipping reserved computed key '${s}'`):"function"==typeof r?this._computed[s]=r:console.warn(`restate: Computed property '${s}' must be a function`);return this._proxy}),t("$dependencies",()=>{const e={};for(const[t,s]of this._computedDependencies)e[t]=Array.from(s);return e}),t("$methods",t=>(Object.entries(t).forEach(([t,s])=>{if("function"!=typeof s)throw new Error(`restate: Method '${t}' must be a function`);if(e.includes(t))throw new Error(`restate: Cannot define method '${t}' - it's a reserved core method`);if(this._isReservedPrefix(t))throw new Error(`restate: Cannot define method '${t}' - names starting with '_' are reserved`);const r=this._methodRegistry.get(t);r&&r.source.startsWith("plugin:")&&console.warn(`restate: $methods() is overriding '${t}' (previously defined by ${r.source})`),Object.defineProperty(this._proxy,t,{value:s.bind(this._proxy),enumerable:!1,writable:!0,configurable:!0}),this._registerMethod(t,"user",!0)}),this._proxy)),t("$registry",()=>{const e={};for(const[t,s]of this._methodRegistry)e[t]={...s},delete e[t].originalFn;return e}),t("$destroy",()=>(this._runHooks("onDestroy"),this._isDestroyed=!0,this._clearAllWatchers(),this._onChange=null,this._plugins.clear(),this._pluginLoadOrder=[],this._methodRegistry.clear(),this._proxyCache=new WeakMap,this._computed={},this._computedDependencies.clear(),this._computedCache.clear(),this._computedCallStack&&this._computedCallStack.clear(),this._proxy))}_applyUpdates(e,t,s=[]){if(this._isDestroyed)return;const r=["__proto__","constructor","prototype"];for(const[i,o]of Object.entries(t))r.includes(i)||("object"!=typeof o||null===o||Array.isArray(o)?e[i]=o:(e[i]&&"object"==typeof e[i]||(e[i]={}),this._applyUpdates(e[i],o,s.concat(i))))}}function restate(e={}){const t=new s(e,{plugins:[]}),r=t._proxy;return r.use=function(e,s){const r="function"==typeof e?e(t):e;return t.use(r),t._proxy},r}export{restate};
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nativelayer.dev/restate",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A minimal, framework-agnostic reactive state management library built on ES6 proxies.",
|
|
6
|
+
"main": "./dist/restate.cjs.min.js",
|
|
7
|
+
"module": "./dist/restate.esm.min.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/restate.esm.min.js",
|
|
11
|
+
"require": "./dist/restate.cjs.min.js"
|
|
12
|
+
},
|
|
13
|
+
"./plugins/*": {
|
|
14
|
+
"import": "./dist/plugin/*.esm.min.js",
|
|
15
|
+
"require": "./dist/plugin/*.cjs.min.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"author": "Yannick J.A. Charlery <ynck.chrl@protonmail.com>",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/ynck-chrl/restate"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/ynck-chrl/restate",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/ynck-chrl/restate/issues"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
32
|
+
"files": [
|
|
33
|
+
"**/*"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"state",
|
|
37
|
+
"state management",
|
|
38
|
+
"reactive",
|
|
39
|
+
"proxy",
|
|
40
|
+
"lightweight",
|
|
41
|
+
"plugin",
|
|
42
|
+
"extensible",
|
|
43
|
+
"computed",
|
|
44
|
+
"observable",
|
|
45
|
+
"watcher",
|
|
46
|
+
"framework-agnostic",
|
|
47
|
+
"zero-dependencies"
|
|
48
|
+
]
|
|
49
|
+
}
|
package/restate-logo.jpg
ADDED
|
Binary file
|