@ryangjchandler/spruce
Advanced tools
Comparing version 2.6.3 to 2.7.0
@@ -1,2 +0,578 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.spruce=t()}(this,function(){function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),r.push.apply(r,n)}return r}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var r,n=(function(e,t){e.exports=function(){var e=/^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;function t(e){var t,r=e.replace(/^v/,"").replace(/\+.*$/,""),n=-1===(t=r).indexOf("-")?t.length:t.indexOf("-"),i=r.substring(0,n).split(".");return i.push(r.substring(n+1)),i}function r(e){return isNaN(Number(e))?e:Number(e)}function n(t){if("string"!=typeof t)throw new TypeError("Invalid argument expected string");if(!e.test(t))throw new Error("Invalid argument not valid semver ('"+t+"' received)")}function i(e,i){[e,i].forEach(n);for(var s=t(e),o=t(i),c=0;c<Math.max(s.length-1,o.length-1);c++){var a=parseInt(s[c]||0,10),u=parseInt(o[c]||0,10);if(a>u)return 1;if(u>a)return-1}var f=s[s.length-1],h=o[o.length-1];if(f&&h){var p=f.split(".").map(r),d=h.split(".").map(r);for(c=0;c<Math.max(p.length,d.length);c++){if(void 0===p[c]||"string"==typeof d[c]&&"number"==typeof p[c])return-1;if(void 0===d[c]||"string"==typeof p[c]&&"number"==typeof d[c])return 1;if(p[c]>d[c])return 1;if(d[c]>p[c])return-1}}else if(f||h)return f?-1:1;return 0}var s=[">",">=","=","<","<="],o={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1]};return i.validate=function(t){return"string"==typeof t&&e.test(t)},i.compare=function(e,t,r){!function(e){if("string"!=typeof e)throw new TypeError("Invalid operator type, expected string but got "+typeof e);if(-1===s.indexOf(e))throw new TypeError("Invalid operator, expected one of "+s.join("|"))}(r);var n=i(e,t);return o[r].indexOf(n)>-1},i}()}(r={exports:{}}),r.exports),i=function(e){return null==e},s=function(e){return Object.getPrototypeOf(e)===Object.prototype},o=function(e){return Array.isArray(e)},c=function(e,t){return Object.entries(e).forEach(function(r){var n=r[0],a=r[1];i(a)||!s(a)&&!o(a)||(e[n]=c(a,t))}),new Proxy(e,{get:function(e,r,n){return t.get(e,r,n)},set:function(e,r,n,a){i(n)||!s(n)&&!o(n)||(n=c(n,t));var u=e[r];return e[r]=n,i(u)||i(u.__watchers)||(e[r].__watchers=u.__watchers),t.set(e,r,e[r],a),!0}})},a={stores:{},persistenceDriver:window.localStorage,persisted:[],subscribers:[],pendingWatchers:{},disableReactivity:!1,startingCallbacks:[],startedCallbacks:[],hasStarted:!1,start:function(){var e=this;this.startingCallbacks.forEach(function(e){return e()}),this.attach(),this.stores=c(this.stores,{get:function(t,r,n){return Object.is(n,e.stores)&&["get","set","toggle","call","clear"].includes(r)?e[r].bind(e):Reflect.get(t,r,n)},set:function(t,r,n,i){if(!e.disableReactivity){e.updateSubscribers(),e.runWatchers(t,r,n,i),e.disableReactivity=!0;try{e.persisted.forEach(e.updateLocalStorage.bind(e))}catch(e){}e.disableReactivity=!1}}}),this.hasStarted=!0,this.disableReactivity=!0,Object.entries(this.pendingWatchers).forEach(function(t){var r=t[0];t[1].forEach(function(t){return e.watch(r,t)})}),this.disableReactivity=!1,this.startedCallbacks.forEach(function(e){return e()})},starting:function(e){this.startingCallbacks.push(e)},started:function(e){this.startedCallbacks.push(e)},attach:function(){if(!(navigator.userAgent.includes("Node.js")||navigator.userAgent.includes("jsdom")||window.Alpine&&n.compare(window.Alpine.version,"2.7.0",">=")))throw new Error("[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.");var e=this;window.Alpine.addMagicProperty("store",function(t){return e.subscribe(t),e.stores})},store:function(e,t,r){if(void 0===r&&(r=!1),"function"==typeof t&&(t=t()),r)try{this.stores[e]=this.retrieveFromLocalStorage(e,(n={},Object.entries(t).filter(function(e){return"function"==typeof e[1]}).forEach(function(e){return n[e[0]]=e[1]}),n)),this.persisted.includes(e)||this.persisted.push(e)}catch(e){}var n;return this.stores[e]||(this.stores[e]=t),this.stores[e]},reset:function(e,t){void 0!==this.stores[e]&&(this.stores[e]=t)},subscribe:function(e){return this.subscribers.includes(e)||this.subscribers.push(e),this.stores},updateSubscribers:function(){this.subscribers.filter(function(e){return!!e.__x}).forEach(function(e){e.__x.updateElements(e)})},retrieveFromLocalStorage:function(e,t){void 0===t&&(t={});var r=this.persistenceDriver.getItem("__spruce:"+e);if(!r)return null;var n=JSON.parse(r);return"object"==typeof n&&(delete(n=Object.assign(t,n)).__watchers,delete n.__key_name),n},updateLocalStorage:function(r){var n=function(r){for(var n=1;n<arguments.length;n++){var i=null!=arguments[n]?arguments[n]:{};n%2?t(Object(i),!0).forEach(function(t){e(r,t,i[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):t(Object(i)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))})}return r}({},this.store(r));delete n.__watchers,delete n.__key_name,this.persistenceDriver.setItem("__spruce:"+r,JSON.stringify(this.store(r)))},get:function(e,t){return void 0===t&&(t=this.stores),e.split(".").reduce(function(e,t){return e[t]},t)},set:function(e,t,r){return void 0===r&&(r=this.stores),o(e)||(e=e.split(".")),1===e.length?r[e[0]]=t:r[e[0]]?this.set(e.slice(1),t,r[e[0]]):(r[e[0]]={},this.set(e.slice(1),t,r[e[0]]))},toggle:function(e){return this.set(e,!this.get(e))},call:function(e){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];return this.get(e).apply(void 0,t)},clear:function(e){return this.persistenceDriver.removeItem("__spruce:"+e)},watch:function(e,t){var r=this;if(!this.hasStarted)return this.pendingWatchers[e]||(this.pendingWatchers[e]=[]),this.pendingWatchers[e].push(t),[function(){return r.unwatch(e,t)}];var n=e.split("."),c=n.reduce(function(e,t){var r=e[t];return i(r)||!s(r)&&!o(r)?e:r},this.stores),a=Object.is(c,this.get(e))?"__self":n[n.length-1];return c.__watchers||(c.__watchers=new Map),c.__watchers.has(a)||c.__watchers.set(a,new Set),c.__watchers.get(a).add(t),[function(){return r.unwatch(e,t)}]},unwatch:function(e,t){var r=e.split("."),n=r.reduce(function(e,t){var r=e[t];return i(r)||!s(r)&&!o(r)?e:r},this.stores),c=Object.is(n,this.get(e))?"__self":r[r.length-1],a=n.__watchers;a.has(c)&&a.get(c).delete(t)},watchers:function(e){var t=e.split("."),r=t.reduce(function(e,t){var r=e[t];return i(r)||!s(r)&&!o(r)?e:r},this.stores),n=Object.is(r,this.get(e))?"__self":t[t.length-1];return r.__watchers?r.__watchers.get(n):{}},runWatchers:function(e,t,r){e.__watchers&&(e.__watchers.has(t)&&e.__watchers.get(t).forEach(function(e){return e(r)}),e.__watchers.has("__self")&&e.__watchers.get("__self").forEach(function(e){return e(r,t)}))},persistUsing:function(e){if(this.persisted.length>0&&console.warn("[Spruce] You have already initialised a persisted store. Changing the driver may cause issues."),"function"!=typeof e.getItem)throw new Error("[Spruce] The persistence driver must have a `getItem(key)` method.");if("function"!=typeof e.setItem)throw new Error("[Spruce] The persistence driver must have a `setItem(key, value)` method.");if("function"!=typeof e.removeItem)throw new Error("[Spruce] The persistence driver must have a `removeItem(name)` method.");this.persistenceDriver=e}};window.Spruce=a;var u=window.deferLoadingAlpine||function(e){e()};return window.deferLoadingAlpine=function(e){window.Spruce.start(),u(e)},a}); | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Spruce = factory()); | ||
}(this, (function () { 'use strict'; | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
} | ||
return obj; | ||
} | ||
function ownKeys(object, enumerableOnly) { | ||
var keys = Object.keys(object); | ||
if (Object.getOwnPropertySymbols) { | ||
var symbols = Object.getOwnPropertySymbols(object); | ||
if (enumerableOnly) symbols = symbols.filter(function (sym) { | ||
return Object.getOwnPropertyDescriptor(object, sym).enumerable; | ||
}); | ||
keys.push.apply(keys, symbols); | ||
} | ||
return keys; | ||
} | ||
function _objectSpread2(target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i] != null ? arguments[i] : {}; | ||
if (i % 2) { | ||
ownKeys(Object(source), true).forEach(function (key) { | ||
_defineProperty(target, key, source[key]); | ||
}); | ||
} else if (Object.getOwnPropertyDescriptors) { | ||
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); | ||
} else { | ||
ownKeys(Object(source)).forEach(function (key) { | ||
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); | ||
}); | ||
} | ||
} | ||
return target; | ||
} | ||
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; | ||
function createCommonjsModule(fn) { | ||
var module = { exports: {} }; | ||
return fn(module, module.exports), module.exports; | ||
} | ||
/* global define */ | ||
var compareVersions = createCommonjsModule(function (module, exports) { | ||
(function (root, factory) { | ||
/* istanbul ignore next */ | ||
{ | ||
module.exports = factory(); | ||
} | ||
})(commonjsGlobal, function () { | ||
var semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+))?(?:-[\da-z\-]+(?:\.[\da-z\-]+)*)?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i; | ||
function indexOrEnd(str, q) { | ||
return str.indexOf(q) === -1 ? str.length : str.indexOf(q); | ||
} | ||
function split(v) { | ||
var c = v.replace(/^v/, '').replace(/\+.*$/, ''); | ||
var patchIndex = indexOrEnd(c, '-'); | ||
var arr = c.substring(0, patchIndex).split('.'); | ||
arr.push(c.substring(patchIndex + 1)); | ||
return arr; | ||
} | ||
function tryParse(v) { | ||
return isNaN(Number(v)) ? v : Number(v); | ||
} | ||
function validate(version) { | ||
if (typeof version !== 'string') { | ||
throw new TypeError('Invalid argument expected string'); | ||
} | ||
if (!semver.test(version)) { | ||
throw new Error('Invalid argument not valid semver (\'' + version + '\' received)'); | ||
} | ||
} | ||
function compareVersions(v1, v2) { | ||
[v1, v2].forEach(validate); | ||
var s1 = split(v1); | ||
var s2 = split(v2); | ||
for (var i = 0; i < Math.max(s1.length - 1, s2.length - 1); i++) { | ||
var n1 = parseInt(s1[i] || 0, 10); | ||
var n2 = parseInt(s2[i] || 0, 10); | ||
if (n1 > n2) return 1; | ||
if (n2 > n1) return -1; | ||
} | ||
var sp1 = s1[s1.length - 1]; | ||
var sp2 = s2[s2.length - 1]; | ||
if (sp1 && sp2) { | ||
var p1 = sp1.split('.').map(tryParse); | ||
var p2 = sp2.split('.').map(tryParse); | ||
for (i = 0; i < Math.max(p1.length, p2.length); i++) { | ||
if (p1[i] === undefined || typeof p2[i] === 'string' && typeof p1[i] === 'number') return -1; | ||
if (p2[i] === undefined || typeof p1[i] === 'string' && typeof p2[i] === 'number') return 1; | ||
if (p1[i] > p2[i]) return 1; | ||
if (p2[i] > p1[i]) return -1; | ||
} | ||
} else if (sp1 || sp2) { | ||
return sp1 ? -1 : 1; | ||
} | ||
return 0; | ||
} | ||
var allowedOperators = ['>', '>=', '=', '<', '<=']; | ||
var operatorResMap = { | ||
'>': [1], | ||
'>=': [0, 1], | ||
'=': [0], | ||
'<=': [-1, 0], | ||
'<': [-1] | ||
}; | ||
function validateOperator(op) { | ||
if (typeof op !== 'string') { | ||
throw new TypeError('Invalid operator type, expected string but got ' + typeof op); | ||
} | ||
if (allowedOperators.indexOf(op) === -1) { | ||
throw new TypeError('Invalid operator, expected one of ' + allowedOperators.join('|')); | ||
} | ||
} | ||
compareVersions.validate = function (version) { | ||
return typeof version === 'string' && semver.test(version); | ||
}; | ||
compareVersions.compare = function (v1, v2, operator) { | ||
// Validate operator | ||
validateOperator(operator); // since result of compareVersions can only be -1 or 0 or 1 | ||
// a simple map can be used to replace switch | ||
var res = compareVersions(v1, v2); | ||
return operatorResMap[operator].indexOf(res) > -1; | ||
}; | ||
return compareVersions; | ||
}); | ||
}); | ||
const isNullOrUndefined = value => { | ||
return value === null || value === undefined; | ||
}; | ||
const isObject = _ => { | ||
return Object.getPrototypeOf(_) === Object.prototype; | ||
}; | ||
const isArray = _ => Array.isArray(_); | ||
const getMethods = obj => { | ||
let methods = {}; | ||
Object.entries(obj).filter(([_, value]) => typeof value === 'function').forEach(([key, value]) => methods[key] = value); | ||
return methods; | ||
}; | ||
const isTesting = () => { | ||
return navigator.userAgent.includes("Node.js") || navigator.userAgent.includes("jsdom"); | ||
}; | ||
const checkForAlpine = () => { | ||
if (isTesting()) { | ||
return true; | ||
} | ||
if (!window.Alpine) { | ||
return false; | ||
} | ||
return compareVersions.compare(window.Alpine.version, '2.7.0', '>='); | ||
}; | ||
const createObservable = (target, callbacks) => { | ||
Object.entries(target).forEach(([key, value]) => { | ||
if (!isNullOrUndefined(value) && (isObject(value) || isArray(value))) { | ||
target[key] = createObservable(value, callbacks); | ||
} | ||
}); | ||
return new Proxy(target, { | ||
get(target, key, receiver) { | ||
return callbacks.get(target, key, receiver); | ||
}, | ||
set(target, key, value, receiver) { | ||
if (!isNullOrUndefined(value) && (isObject(value) || isArray(value))) { | ||
value = createObservable(value, callbacks); | ||
} | ||
let originalValue = target[key]; | ||
target[key] = value; // Copy watchers from the original value if they exist | ||
if (!isNullOrUndefined(originalValue) && !isNullOrUndefined(originalValue.__watchers)) { | ||
target[key].__watchers = originalValue.__watchers; | ||
} | ||
callbacks.set(target, key, target[key], receiver); | ||
return true; | ||
} | ||
}); | ||
}; | ||
const Spruce = { | ||
stores: {}, | ||
persistenceDriver: window.localStorage, | ||
persisted: [], | ||
persistedDrivers: {}, | ||
subscribers: [], | ||
pendingWatchers: {}, | ||
disableReactivity: false, | ||
startingCallbacks: [], | ||
startedCallbacks: [], | ||
hasStarted: false, | ||
start() { | ||
this.startingCallbacks.forEach(fn => fn()); | ||
this.attach(); | ||
this.stores = createObservable(this.stores, { | ||
get: (target, key, receiver) => { | ||
if (Object.is(receiver, this.stores) && ['get', 'set', 'toggle', 'call', 'clear'].includes(key)) { | ||
return this[key].bind(this); | ||
} | ||
return Reflect.get(target, key, receiver); | ||
}, | ||
set: (target, key, value, receiver) => { | ||
if (this.disableReactivity) { | ||
return; | ||
} | ||
this.updateSubscribers(); | ||
this.runWatchers(target, key, value, receiver); | ||
this.disableReactivity = true; | ||
try { | ||
this.persisted.forEach(this.updateLocalStorage.bind(this)); | ||
} catch (e) {// Do nothing here (thanks Safari!) | ||
} | ||
this.disableReactivity = false; | ||
} | ||
}); | ||
this.hasStarted = true; | ||
this.disableReactivity = true; | ||
Object.entries(this.pendingWatchers).forEach(([name, callbacks]) => { | ||
callbacks.forEach(callback => this.watch(name, callback)); | ||
}); | ||
this.disableReactivity = false; | ||
this.startedCallbacks.forEach(fn => fn()); | ||
}, | ||
starting(callback) { | ||
this.startingCallbacks.push(callback); | ||
}, | ||
started(callback) { | ||
this.startedCallbacks.push(callback); | ||
}, | ||
attach() { | ||
if (!checkForAlpine()) { | ||
throw new Error('[Spruce] You must be using Alpine >= 2.5.0 to use Spruce.'); | ||
} | ||
const self = this; | ||
window.Alpine.addMagicProperty('store', el => { | ||
self.subscribe(el); | ||
return self.stores; | ||
}); | ||
}, | ||
store(name, state, persist = false) { | ||
if (typeof state === 'function') { | ||
state = state(); | ||
} | ||
const isValidDriver = this.isValidDriver(persist); | ||
if (persist === true || isValidDriver) { | ||
try { | ||
this.stores[name] = this.retrieveFromLocalStorage(name, getMethods(state), isValidDriver ? persist : undefined); | ||
if (isValidDriver) { | ||
this.persistedDrivers[name] = persist; | ||
} | ||
if (!this.persisted.includes(name)) { | ||
this.persisted.push(name); | ||
} | ||
} catch (e) {// Do nothing here (thanks Safari!) | ||
} | ||
} | ||
if (!this.stores[name]) { | ||
this.stores[name] = state; | ||
} | ||
return this.stores[name]; | ||
}, | ||
reset(name, state) { | ||
if (this.stores[name] === undefined) { | ||
return; | ||
} | ||
this.stores[name] = state; | ||
}, | ||
delete(name, reload = true) { | ||
if (this.stores[name] === undefined) { | ||
return false; | ||
} | ||
delete this.stores[name]; | ||
if (reload) { | ||
this.updateSubscribers(); | ||
} | ||
return true; | ||
}, | ||
deleteAll() { | ||
const results = Object.keys(this.stores).map(key => this.delete(key, false)); | ||
this.updateSubscribers(); | ||
return !results.some(bool => !bool); | ||
}, | ||
subscribe(el) { | ||
if (!this.subscribers.includes(el)) { | ||
this.subscribers.push(el); | ||
} | ||
return this.stores; | ||
}, | ||
updateSubscribers() { | ||
this.subscribers.filter(el => !!el.__x).forEach(el => { | ||
el.__x.updateElements(el); | ||
}); | ||
}, | ||
retrieveFromLocalStorage(name, methods = {}, handler) { | ||
let driver = this.persistenceDriver; | ||
if (handler !== undefined) { | ||
this.guardAgainstInvalidDrivers(handler); | ||
driver = handler; | ||
} | ||
const value = driver.getItem(`__spruce:${name}`); | ||
if (!value) { | ||
return null; | ||
} | ||
let storage = JSON.parse(value); | ||
if (typeof storage === 'object') { | ||
storage = Object.assign(methods, storage); | ||
delete storage.__watchers; | ||
delete storage.__key_name; | ||
} | ||
return storage; | ||
}, | ||
updateLocalStorage(name) { | ||
const store = _objectSpread2({}, this.store(name)); | ||
delete store.__watchers; | ||
delete store.__key_name; | ||
const driver = this.persistedDrivers[name] || this.persistenceDriver; | ||
driver.setItem(`__spruce:${name}`, JSON.stringify(this.store(name))); | ||
}, | ||
get(name, target = this.stores) { | ||
return name.split('.').reduce((target, part) => target[part], target); | ||
}, | ||
set(name, value, target = this.stores) { | ||
if (!isArray(name)) { | ||
name = name.split('.'); | ||
} | ||
if (name.length === 1) return target[name[0]] = value; | ||
if (target[name[0]]) { | ||
return this.set(name.slice(1), value, target[name[0]]); | ||
} else { | ||
target[name[0]] = {}; | ||
return this.set(name.slice(1), value, target[name[0]]); | ||
} | ||
}, | ||
toggle(name) { | ||
return this.set(name, !this.get(name)); | ||
}, | ||
call(name, ...args) { | ||
return this.get(name)(...args); | ||
}, | ||
clear(name) { | ||
return this.persistenceDriver.removeItem(`__spruce:${name}`); | ||
}, | ||
watch(name, callback) { | ||
if (!this.hasStarted) { | ||
this.pendingWatchers[name] || (this.pendingWatchers[name] = []); | ||
this.pendingWatchers[name].push(callback); | ||
return [() => this.unwatch(name, callback)]; | ||
} | ||
const nameParts = name.split('.'); | ||
const target = nameParts.reduce((target, part) => { | ||
const sub = target[part]; | ||
if (!isNullOrUndefined(sub) && (isObject(sub) || isArray(sub))) { | ||
return sub; | ||
} | ||
return target; | ||
}, this.stores); | ||
/** | ||
* If the target object / array is the property | ||
* that needs to be watched, a magic `__self` key is | ||
* used so that runner can pick up on it later. | ||
*/ | ||
const part = Object.is(target, this.get(name)) ? '__self' : nameParts[nameParts.length - 1]; | ||
if (!target.hasOwnProperty('__watchers')) { | ||
Object.defineProperty(target, '__watchers', { | ||
enumerable: false, | ||
value: new Map(), | ||
configurable: true | ||
}); | ||
} | ||
if (!target.__watchers.has(part)) { | ||
target.__watchers.set(part, new Set()); | ||
} | ||
target.__watchers.get(part).add(callback); | ||
return [() => this.unwatch(name, callback)]; | ||
}, | ||
unwatch(name, callback) { | ||
const nameParts = name.split('.'); | ||
const target = nameParts.reduce((target, part) => { | ||
const sub = target[part]; | ||
if (!isNullOrUndefined(sub) && (isObject(sub) || isArray(sub))) { | ||
return sub; | ||
} | ||
return target; | ||
}, this.stores); | ||
const part = Object.is(target, this.get(name)) ? '__self' : nameParts[nameParts.length - 1]; | ||
const watchers = target.__watchers; | ||
if (!watchers.has(part)) { | ||
return; | ||
} | ||
watchers.get(part).delete(callback); | ||
}, | ||
watchers(name) { | ||
const nameParts = name.split('.'); | ||
const target = nameParts.reduce((target, part) => { | ||
const sub = target[part]; | ||
if (!isNullOrUndefined(sub) && (isObject(sub) || isArray(sub))) { | ||
return sub; | ||
} | ||
return target; | ||
}, this.stores); | ||
const part = Object.is(target, this.get(name)) ? '__self' : nameParts[nameParts.length - 1]; | ||
if (!target.__watchers) { | ||
return {}; | ||
} | ||
return target.__watchers.get(part); | ||
}, | ||
runWatchers(target, key, value) { | ||
if (!target.__watchers) { | ||
return; | ||
} | ||
if (target.__watchers.has(key)) { | ||
target.__watchers.get(key).forEach(f => f(value)); | ||
} | ||
/** | ||
* The `__self` key is used for watchers that are registered | ||
* to the object or array being updated. | ||
*/ | ||
if (target.__watchers.has('__self')) { | ||
target.__watchers.get('__self').forEach(f => f(value, key)); | ||
} | ||
}, | ||
persistUsing(driver) { | ||
if (this.persisted.length > 0) { | ||
console.warn('[Spruce] You have already initialised a persisted store. Changing the driver may cause issues.'); | ||
} | ||
this.guardAgainstInvalidDrivers(driver); | ||
this.persistenceDriver = driver; | ||
}, | ||
guardAgainstInvalidDrivers(driver) { | ||
if (typeof driver.getItem !== 'function') { | ||
throw new Error('[Spruce] The persistence driver must have a `getItem(key)` method.'); | ||
} | ||
if (typeof driver.setItem !== 'function') { | ||
throw new Error('[Spruce] The persistence driver must have a `setItem(key, value)` method.'); | ||
} | ||
if (typeof driver.removeItem !== 'function') { | ||
throw new Error('[Spruce] The persistence driver must have a `removeItem(name)` method.'); | ||
} | ||
}, | ||
isValidDriver(driver) { | ||
try { | ||
this.guardAgainstInvalidDrivers(driver); | ||
} catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
}; | ||
window.Spruce = Spruce; | ||
const deferrer = window.deferLoadingAlpine || function (callback) { | ||
callback(); | ||
}; | ||
window.deferLoadingAlpine = function (callback) { | ||
window.Spruce.start(); | ||
deferrer(callback); | ||
}; | ||
return Spruce; | ||
}))); | ||
//# sourceMappingURL=spruce.umd.js.map |
{ | ||
"name": "@ryangjchandler/spruce", | ||
"description": "A lightweight state management layer for Alpine.js", | ||
"version": "2.6.3", | ||
"version": "2.7.0", | ||
"repository": { | ||
@@ -11,10 +11,6 @@ "type": "git", | ||
"license": "MIT", | ||
"source": "src/index.js", | ||
"main": "dist/spruce.js", | ||
"umd:main": "dist/spruce.umd.js", | ||
"module": "dist/spruce.module.js", | ||
"main": "dist/spruce.umd.js", | ||
"scripts": { | ||
"build": "microbundle", | ||
"watch": "microbundle watch", | ||
"test": "jest", | ||
"build": "rollup -c", | ||
"watch": "rollup -c -w", | ||
"pre-cypress": "http-server", | ||
@@ -27,14 +23,14 @@ "cypress": "start-server-and-test 'http-server -c-1 --silent' 8080 'npx cypress run'" | ||
"devDependencies": { | ||
"@babel/core": "^7.13.10", | ||
"@babel/preset-env": "^7.9.5", | ||
"@testing-library/dom": "^7.2.2", | ||
"@testing-library/jest-dom": "^5.5.0", | ||
"@rollup/plugin-babel": "^5.3.0", | ||
"@rollup/plugin-commonjs": "^17.1.0", | ||
"@rollup/plugin-node-resolve": "^11.2.0", | ||
"compare-versions": "3.6.0", | ||
"cypress": "^6.0", | ||
"http-server": "^0.12.3", | ||
"jest": "^25.4.0", | ||
"jsdom-simulant": "^1.1.2", | ||
"microbundle": "^0.11.0", | ||
"observable-membrane": "^0.26.1", | ||
"rollup": "^2.41.0", | ||
"rollup-plugin-filesize": "^9.1.1", | ||
"start-server-and-test": "^1.11.5" | ||
} | ||
} |
@@ -11,2 +11,4 @@ import { getMethods, checkForAlpine, isObject, isArray, isNullOrUndefined } from './utils' | ||
persistedDrivers: {}, | ||
subscribers: [], | ||
@@ -97,7 +99,17 @@ | ||
} | ||
const isValidDriver = this.isValidDriver(persist) | ||
if (persist) { | ||
if (persist === true || isValidDriver) { | ||
try { | ||
this.stores[name] = this.retrieveFromLocalStorage(name, getMethods(state)) | ||
this.stores[name] = this.retrieveFromLocalStorage( | ||
name, | ||
getMethods(state), | ||
isValidDriver ? persist : undefined | ||
) | ||
if (isValidDriver) { | ||
this.persistedDrivers[name] = persist | ||
} | ||
if (!this.persisted.includes(name)) { | ||
@@ -126,2 +138,24 @@ this.persisted.push(name) | ||
delete(name, reload = true) { | ||
if (this.stores[name] === undefined) { | ||
return false; | ||
} | ||
delete this.stores[name] | ||
if (reload) { | ||
this.updateSubscribers() | ||
} | ||
return true; | ||
}, | ||
deleteAll() { | ||
const results = Object.keys(this.stores).map(key => this.delete(key, false)) | ||
this.updateSubscribers() | ||
return !results.some(bool => !bool) | ||
}, | ||
subscribe(el) { | ||
@@ -141,5 +175,13 @@ if (!this.subscribers.includes(el)) { | ||
retrieveFromLocalStorage(name, methods = {}) { | ||
const value = this.persistenceDriver.getItem(`__spruce:${name}`) | ||
retrieveFromLocalStorage(name, methods = {}, handler) { | ||
let driver = this.persistenceDriver | ||
if (handler !== undefined) { | ||
this.guardAgainstInvalidDrivers(handler) | ||
driver = handler | ||
} | ||
const value = driver.getItem(`__spruce:${name}`) | ||
if (! value) { | ||
@@ -167,3 +209,5 @@ return null | ||
this.persistenceDriver.setItem(`__spruce:${name}`, JSON.stringify(this.store(name))) | ||
const driver = this.persistedDrivers[name] || this.persistenceDriver | ||
driver.setItem(`__spruce:${name}`, JSON.stringify(this.store(name))) | ||
}, | ||
@@ -231,4 +275,8 @@ | ||
if (! target.__watchers) { | ||
target.__watchers = new Map | ||
if (! target.hasOwnProperty('__watchers')) { | ||
Object.defineProperty(target, '__watchers', { | ||
enumerable: false, | ||
value: new Map, | ||
configurable: true | ||
}) | ||
} | ||
@@ -313,2 +361,8 @@ | ||
this.guardAgainstInvalidDrivers(driver) | ||
this.persistenceDriver = driver | ||
}, | ||
guardAgainstInvalidDrivers(driver) { | ||
if (typeof driver.getItem !== 'function') { | ||
@@ -325,4 +379,12 @@ throw new Error('[Spruce] The persistence driver must have a `getItem(key)` method.') | ||
} | ||
}, | ||
this.persistenceDriver = driver | ||
isValidDriver(driver) { | ||
try { | ||
this.guardAgainstInvalidDrivers(driver) | ||
} catch (e) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
@@ -329,0 +391,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import compareVersions from 'compare-versions' | ||
import { compare } from 'compare-versions' | ||
@@ -35,3 +35,3 @@ export const isNullOrUndefined = value => { | ||
return compareVersions.compare(window.Alpine.version, '2.7.0', '>=') | ||
return compare(window.Alpine.version, '2.7.0', '>=') | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
818
63804
7
1