Comparing version 0.0.3 to 0.0.4
1203
dist/index.js
@@ -1,1202 +0,1 @@ | ||
import { z } from 'zod'; | ||
import { useRef, useSyncExternalStore } from 'react'; | ||
const isSecureHydrationGluon = (gluon) => { | ||
if (!gluon.isSSR()) { | ||
return false; | ||
} | ||
// @ts-ignore | ||
return gluon.constructor.SECURE_HYDRATION; | ||
}; | ||
const safeParse = (value) => { | ||
try { | ||
return JSON.parse(value); | ||
} | ||
catch (error) { | ||
console.error(error); | ||
return value; | ||
} | ||
}; | ||
const isServer = () => { | ||
return typeof window === 'undefined'; | ||
}; | ||
var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols; | ||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
/** | ||
* Combine two comparators into a single comparators. | ||
*/ | ||
function combineComparators(comparatorA, comparatorB) { | ||
return function isEqual(a, b, state) { | ||
return comparatorA(a, b, state) && comparatorB(a, b, state); | ||
}; | ||
} | ||
/** | ||
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing | ||
* for circular references to be safely included in the comparison without creating | ||
* stack overflows. | ||
*/ | ||
function createIsCircular(areItemsEqual) { | ||
return function isCircular(a, b, state) { | ||
if (!a || !b || typeof a !== 'object' || typeof b !== 'object') { | ||
return areItemsEqual(a, b, state); | ||
} | ||
var cache = state.cache; | ||
var cachedA = cache.get(a); | ||
var cachedB = cache.get(b); | ||
if (cachedA && cachedB) { | ||
return cachedA === b && cachedB === a; | ||
} | ||
cache.set(a, b); | ||
cache.set(b, a); | ||
var result = areItemsEqual(a, b, state); | ||
cache.delete(a); | ||
cache.delete(b); | ||
return result; | ||
}; | ||
} | ||
/** | ||
* Get the properties to strictly examine, which include both own properties that are | ||
* not enumerable and symbol properties. | ||
*/ | ||
function getStrictProperties(object) { | ||
return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object)); | ||
} | ||
/** | ||
* Whether the object contains the property passed as an own property. | ||
*/ | ||
var hasOwn = Object.hasOwn || | ||
(function (object, property) { | ||
return hasOwnProperty.call(object, property); | ||
}); | ||
/** | ||
* Whether the values passed are strictly equal or both NaN. | ||
*/ | ||
function sameValueZeroEqual(a, b) { | ||
return a || b ? a === b : a === b || (a !== a && b !== b); | ||
} | ||
var OWNER = '_owner'; | ||
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys = Object.keys; | ||
/** | ||
* Whether the arrays are equal in value. | ||
*/ | ||
function areArraysEqual(a, b, state) { | ||
var index = a.length; | ||
if (b.length !== index) { | ||
return false; | ||
} | ||
while (index-- > 0) { | ||
if (!state.equals(a[index], b[index], index, index, a, b, state)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Whether the dates passed are equal in value. | ||
*/ | ||
function areDatesEqual(a, b) { | ||
return sameValueZeroEqual(a.getTime(), b.getTime()); | ||
} | ||
/** | ||
* Whether the `Map`s are equal in value. | ||
*/ | ||
function areMapsEqual(a, b, state) { | ||
if (a.size !== b.size) { | ||
return false; | ||
} | ||
var matchedIndices = {}; | ||
var aIterable = a.entries(); | ||
var index = 0; | ||
var aResult; | ||
var bResult; | ||
while ((aResult = aIterable.next())) { | ||
if (aResult.done) { | ||
break; | ||
} | ||
var bIterable = b.entries(); | ||
var hasMatch = false; | ||
var matchIndex = 0; | ||
while ((bResult = bIterable.next())) { | ||
if (bResult.done) { | ||
break; | ||
} | ||
var _a = aResult.value, aKey = _a[0], aValue = _a[1]; | ||
var _b = bResult.value, bKey = _b[0], bValue = _b[1]; | ||
if (!hasMatch && | ||
!matchedIndices[matchIndex] && | ||
(hasMatch = | ||
state.equals(aKey, bKey, index, matchIndex, a, b, state) && | ||
state.equals(aValue, bValue, aKey, bKey, a, b, state))) { | ||
matchedIndices[matchIndex] = true; | ||
} | ||
matchIndex++; | ||
} | ||
if (!hasMatch) { | ||
return false; | ||
} | ||
index++; | ||
} | ||
return true; | ||
} | ||
/** | ||
* Whether the objects are equal in value. | ||
*/ | ||
function areObjectsEqual(a, b, state) { | ||
var properties = keys(a); | ||
var index = properties.length; | ||
if (keys(b).length !== index) { | ||
return false; | ||
} | ||
var property; | ||
// Decrementing `while` showed faster results than either incrementing or | ||
// decrementing `for` loop and than an incrementing `while` loop. Declarative | ||
// methods like `some` / `every` were not used to avoid incurring the garbage | ||
// cost of anonymous callbacks. | ||
while (index-- > 0) { | ||
property = properties[index]; | ||
if (property === OWNER && | ||
(a.$$typeof || b.$$typeof) && | ||
a.$$typeof !== b.$$typeof) { | ||
return false; | ||
} | ||
if (!hasOwn(b, property) || | ||
!state.equals(a[property], b[property], property, property, a, b, state)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Whether the objects are equal in value with strict property checking. | ||
*/ | ||
function areObjectsEqualStrict(a, b, state) { | ||
var properties = getStrictProperties(a); | ||
var index = properties.length; | ||
if (getStrictProperties(b).length !== index) { | ||
return false; | ||
} | ||
var property; | ||
var descriptorA; | ||
var descriptorB; | ||
// Decrementing `while` showed faster results than either incrementing or | ||
// decrementing `for` loop and than an incrementing `while` loop. Declarative | ||
// methods like `some` / `every` were not used to avoid incurring the garbage | ||
// cost of anonymous callbacks. | ||
while (index-- > 0) { | ||
property = properties[index]; | ||
if (property === OWNER && | ||
(a.$$typeof || b.$$typeof) && | ||
a.$$typeof !== b.$$typeof) { | ||
return false; | ||
} | ||
if (!hasOwn(b, property)) { | ||
return false; | ||
} | ||
if (!state.equals(a[property], b[property], property, property, a, b, state)) { | ||
return false; | ||
} | ||
descriptorA = getOwnPropertyDescriptor(a, property); | ||
descriptorB = getOwnPropertyDescriptor(b, property); | ||
if ((descriptorA || descriptorB) && | ||
(!descriptorA || | ||
!descriptorB || | ||
descriptorA.configurable !== descriptorB.configurable || | ||
descriptorA.enumerable !== descriptorB.enumerable || | ||
descriptorA.writable !== descriptorB.writable)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Whether the primitive wrappers passed are equal in value. | ||
*/ | ||
function arePrimitiveWrappersEqual(a, b) { | ||
return sameValueZeroEqual(a.valueOf(), b.valueOf()); | ||
} | ||
/** | ||
* Whether the regexps passed are equal in value. | ||
*/ | ||
function areRegExpsEqual(a, b) { | ||
return a.source === b.source && a.flags === b.flags; | ||
} | ||
/** | ||
* Whether the `Set`s are equal in value. | ||
*/ | ||
function areSetsEqual(a, b, state) { | ||
if (a.size !== b.size) { | ||
return false; | ||
} | ||
var matchedIndices = {}; | ||
var aIterable = a.values(); | ||
var aResult; | ||
var bResult; | ||
while ((aResult = aIterable.next())) { | ||
if (aResult.done) { | ||
break; | ||
} | ||
var bIterable = b.values(); | ||
var hasMatch = false; | ||
var matchIndex = 0; | ||
while ((bResult = bIterable.next())) { | ||
if (bResult.done) { | ||
break; | ||
} | ||
if (!hasMatch && | ||
!matchedIndices[matchIndex] && | ||
(hasMatch = state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state))) { | ||
matchedIndices[matchIndex] = true; | ||
} | ||
matchIndex++; | ||
} | ||
if (!hasMatch) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Whether the TypedArray instances are equal in value. | ||
*/ | ||
function areTypedArraysEqual(a, b) { | ||
var index = a.length; | ||
if (b.length !== index) { | ||
return false; | ||
} | ||
while (index-- > 0) { | ||
if (a[index] !== b[index]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
var ARGUMENTS_TAG = '[object Arguments]'; | ||
var BOOLEAN_TAG = '[object Boolean]'; | ||
var DATE_TAG = '[object Date]'; | ||
var MAP_TAG = '[object Map]'; | ||
var NUMBER_TAG = '[object Number]'; | ||
var OBJECT_TAG = '[object Object]'; | ||
var REG_EXP_TAG = '[object RegExp]'; | ||
var SET_TAG = '[object Set]'; | ||
var STRING_TAG = '[object String]'; | ||
var isArray = Array.isArray; | ||
var isTypedArray = typeof ArrayBuffer === 'function' && ArrayBuffer.isView | ||
? ArrayBuffer.isView | ||
: null; | ||
var assign = Object.assign; | ||
var getTag = Object.prototype.toString.call.bind(Object.prototype.toString); | ||
/** | ||
* Create a comparator method based on the type-specific equality comparators passed. | ||
*/ | ||
function createEqualityComparator(_a) { | ||
var areArraysEqual = _a.areArraysEqual, areDatesEqual = _a.areDatesEqual, areMapsEqual = _a.areMapsEqual, areObjectsEqual = _a.areObjectsEqual, arePrimitiveWrappersEqual = _a.arePrimitiveWrappersEqual, areRegExpsEqual = _a.areRegExpsEqual, areSetsEqual = _a.areSetsEqual, areTypedArraysEqual = _a.areTypedArraysEqual; | ||
/** | ||
* compare the value of the two objects and return true if they are equivalent in values | ||
*/ | ||
return function comparator(a, b, state) { | ||
// If the items are strictly equal, no need to do a value comparison. | ||
if (a === b) { | ||
return true; | ||
} | ||
// If the items are not non-nullish objects, then the only possibility | ||
// of them being equal but not strictly is if they are both `NaN`. Since | ||
// `NaN` is uniquely not equal to itself, we can use self-comparison of | ||
// both objects, which is faster than `isNaN()`. | ||
if (a == null || | ||
b == null || | ||
typeof a !== 'object' || | ||
typeof b !== 'object') { | ||
return a !== a && b !== b; | ||
} | ||
var constructor = a.constructor; | ||
// Checks are listed in order of commonality of use-case: | ||
// 1. Common complex object types (plain object, array) | ||
// 2. Common data values (date, regexp) | ||
// 3. Less-common complex object types (map, set) | ||
// 4. Less-common data values (promise, primitive wrappers) | ||
// Inherently this is both subjective and assumptive, however | ||
// when reviewing comparable libraries in the wild this order | ||
// appears to be generally consistent. | ||
// Constructors should match, otherwise there is potential for false positives | ||
// between class and subclass or custom object and POJO. | ||
if (constructor !== b.constructor) { | ||
return false; | ||
} | ||
// `isPlainObject` only checks against the object's own realm. Cross-realm | ||
// comparisons are rare, and will be handled in the ultimate fallback, so | ||
// we can avoid capturing the string tag. | ||
if (constructor === Object) { | ||
return areObjectsEqual(a, b, state); | ||
} | ||
// `isArray()` works on subclasses and is cross-realm, so we can avoid capturing | ||
// the string tag or doing an `instanceof` check. | ||
if (isArray(a)) { | ||
return areArraysEqual(a, b, state); | ||
} | ||
// `isTypedArray()` works on all possible TypedArray classes, so we can avoid | ||
// capturing the string tag or comparing against all possible constructors. | ||
if (isTypedArray != null && isTypedArray(a)) { | ||
return areTypedArraysEqual(a, b, state); | ||
} | ||
// Try to fast-path equality checks for other complex object types in the | ||
// same realm to avoid capturing the string tag. Strict equality is used | ||
// instead of `instanceof` because it is more performant for the common | ||
// use-case. If someone is subclassing a native class, it will be handled | ||
// with the string tag comparison. | ||
if (constructor === Date) { | ||
return areDatesEqual(a, b, state); | ||
} | ||
if (constructor === RegExp) { | ||
return areRegExpsEqual(a, b, state); | ||
} | ||
if (constructor === Map) { | ||
return areMapsEqual(a, b, state); | ||
} | ||
if (constructor === Set) { | ||
return areSetsEqual(a, b, state); | ||
} | ||
// Since this is a custom object, capture the string tag to determing its type. | ||
// This is reasonably performant in modern environments like v8 and SpiderMonkey. | ||
var tag = getTag(a); | ||
if (tag === DATE_TAG) { | ||
return areDatesEqual(a, b, state); | ||
} | ||
if (tag === REG_EXP_TAG) { | ||
return areRegExpsEqual(a, b, state); | ||
} | ||
if (tag === MAP_TAG) { | ||
return areMapsEqual(a, b, state); | ||
} | ||
if (tag === SET_TAG) { | ||
return areSetsEqual(a, b, state); | ||
} | ||
if (tag === OBJECT_TAG) { | ||
// The exception for value comparison is custom `Promise`-like class instances. These should | ||
// be treated the same as standard `Promise` objects, which means strict equality, and if | ||
// it reaches this point then that strict equality comparison has already failed. | ||
return (typeof a.then !== 'function' && | ||
typeof b.then !== 'function' && | ||
areObjectsEqual(a, b, state)); | ||
} | ||
// If an arguments tag, it should be treated as a standard object. | ||
if (tag === ARGUMENTS_TAG) { | ||
return areObjectsEqual(a, b, state); | ||
} | ||
// As the penultimate fallback, check if the values passed are primitive wrappers. This | ||
// is very rare in modern JS, which is why it is deprioritized compared to all other object | ||
// types. | ||
if (tag === BOOLEAN_TAG || tag === NUMBER_TAG || tag === STRING_TAG) { | ||
return arePrimitiveWrappersEqual(a, b, state); | ||
} | ||
// If not matching any tags that require a specific type of comparison, then we hard-code false because | ||
// the only thing remaining is strict equality, which has already been compared. This is for a few reasons: | ||
// - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only | ||
// comparison that can be made. | ||
// - For types that can be introspected, but rarely have requirements to be compared | ||
// (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common | ||
// use-cases (may be included in a future release, if requested enough). | ||
// - For types that can be introspected but do not have an objective definition of what | ||
// equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare. | ||
// In all cases, these decisions should be reevaluated based on changes to the language and | ||
// common development practices. | ||
return false; | ||
}; | ||
} | ||
/** | ||
* Create the configuration object used for building comparators. | ||
*/ | ||
function createEqualityComparatorConfig(_a) { | ||
var circular = _a.circular, createCustomConfig = _a.createCustomConfig, strict = _a.strict; | ||
var config = { | ||
areArraysEqual: strict | ||
? areObjectsEqualStrict | ||
: areArraysEqual, | ||
areDatesEqual: areDatesEqual, | ||
areMapsEqual: strict | ||
? combineComparators(areMapsEqual, areObjectsEqualStrict) | ||
: areMapsEqual, | ||
areObjectsEqual: strict | ||
? areObjectsEqualStrict | ||
: areObjectsEqual, | ||
arePrimitiveWrappersEqual: arePrimitiveWrappersEqual, | ||
areRegExpsEqual: areRegExpsEqual, | ||
areSetsEqual: strict | ||
? combineComparators(areSetsEqual, areObjectsEqualStrict) | ||
: areSetsEqual, | ||
areTypedArraysEqual: strict | ||
? areObjectsEqualStrict | ||
: areTypedArraysEqual, | ||
}; | ||
if (createCustomConfig) { | ||
config = assign({}, config, createCustomConfig(config)); | ||
} | ||
if (circular) { | ||
var areArraysEqual$1 = createIsCircular(config.areArraysEqual); | ||
var areMapsEqual$1 = createIsCircular(config.areMapsEqual); | ||
var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual); | ||
var areSetsEqual$1 = createIsCircular(config.areSetsEqual); | ||
config = assign({}, config, { | ||
areArraysEqual: areArraysEqual$1, | ||
areMapsEqual: areMapsEqual$1, | ||
areObjectsEqual: areObjectsEqual$1, | ||
areSetsEqual: areSetsEqual$1, | ||
}); | ||
} | ||
return config; | ||
} | ||
/** | ||
* Default equality comparator pass-through, used as the standard `isEqual` creator for | ||
* use inside the built comparator. | ||
*/ | ||
function createInternalEqualityComparator(compare) { | ||
return function (a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) { | ||
return compare(a, b, state); | ||
}; | ||
} | ||
/** | ||
* Create the `isEqual` function used by the consuming application. | ||
*/ | ||
function createIsEqual(_a) { | ||
var circular = _a.circular, comparator = _a.comparator, createState = _a.createState, equals = _a.equals, strict = _a.strict; | ||
if (createState) { | ||
return function isEqual(a, b) { | ||
var _a = createState(), _b = _a.cache, cache = _b === void 0 ? circular ? new WeakMap() : undefined : _b, meta = _a.meta; | ||
return comparator(a, b, { | ||
cache: cache, | ||
equals: equals, | ||
meta: meta, | ||
strict: strict, | ||
}); | ||
}; | ||
} | ||
if (circular) { | ||
return function isEqual(a, b) { | ||
return comparator(a, b, { | ||
cache: new WeakMap(), | ||
equals: equals, | ||
meta: undefined, | ||
strict: strict, | ||
}); | ||
}; | ||
} | ||
var state = { | ||
cache: undefined, | ||
equals: equals, | ||
meta: undefined, | ||
strict: strict, | ||
}; | ||
return function isEqual(a, b) { | ||
return comparator(a, b, state); | ||
}; | ||
} | ||
/** | ||
* Whether the items passed are deeply-equal in value. | ||
*/ | ||
var deepEqual = createCustomEqual(); | ||
/** | ||
* Whether the items passed are deeply-equal in value based on strict comparison. | ||
*/ | ||
createCustomEqual({ strict: true }); | ||
/** | ||
* Whether the items passed are deeply-equal in value, including circular references. | ||
*/ | ||
createCustomEqual({ circular: true }); | ||
/** | ||
* Whether the items passed are deeply-equal in value, including circular references, | ||
* based on strict comparison. | ||
*/ | ||
createCustomEqual({ | ||
circular: true, | ||
strict: true, | ||
}); | ||
/** | ||
* Whether the items passed are shallowly-equal in value. | ||
*/ | ||
createCustomEqual({ | ||
createInternalComparator: function () { return sameValueZeroEqual; }, | ||
}); | ||
/** | ||
* Whether the items passed are shallowly-equal in value based on strict comparison | ||
*/ | ||
createCustomEqual({ | ||
strict: true, | ||
createInternalComparator: function () { return sameValueZeroEqual; }, | ||
}); | ||
/** | ||
* Whether the items passed are shallowly-equal in value, including circular references. | ||
*/ | ||
createCustomEqual({ | ||
circular: true, | ||
createInternalComparator: function () { return sameValueZeroEqual; }, | ||
}); | ||
/** | ||
* Whether the items passed are shallowly-equal in value, including circular references, | ||
* based on strict comparison. | ||
*/ | ||
createCustomEqual({ | ||
circular: true, | ||
createInternalComparator: function () { return sameValueZeroEqual; }, | ||
strict: true, | ||
}); | ||
/** | ||
* Create a custom equality comparison method. | ||
* | ||
* This can be done to create very targeted comparisons in extreme hot-path scenarios | ||
* where the standard methods are not performant enough, but can also be used to provide | ||
* support for legacy environments that do not support expected features like | ||
* `RegExp.prototype.flags` out of the box. | ||
*/ | ||
function createCustomEqual(options) { | ||
if (options === void 0) { options = {}; } | ||
var _a = options.circular, circular = _a === void 0 ? false : _a, createCustomInternalComparator = options.createInternalComparator, createState = options.createState, _b = options.strict, strict = _b === void 0 ? false : _b; | ||
var config = createEqualityComparatorConfig(options); | ||
var comparator = createEqualityComparator(config); | ||
var equals = createCustomInternalComparator | ||
? createCustomInternalComparator(comparator) | ||
: createInternalEqualityComparator(comparator); | ||
return createIsEqual({ circular: circular, comparator: comparator, createState: createState, equals: equals, strict: strict }); | ||
} | ||
class GluonSubscription { | ||
constructor() { | ||
Object.defineProperty(this, "subscribers", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: new Set() | ||
}); | ||
} | ||
subscribe(callback) { | ||
this.subscribers.add(callback); | ||
return () => { | ||
this.subscribers.delete(callback); | ||
}; | ||
} | ||
unsubscribe() { | ||
this.subscribers.clear(); | ||
} | ||
emit(value) { | ||
this.subscribers.forEach((callback) => callback(value)); | ||
} | ||
} | ||
class Gluon extends GluonSubscription { | ||
constructor(name, options) { | ||
super(); | ||
Object.defineProperty(this, "name", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: name | ||
}); | ||
Object.defineProperty(this, "options", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: options | ||
}); | ||
Object.defineProperty(this, "value", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: null | ||
}); | ||
Object.defineProperty(this, "error", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: null | ||
}); | ||
Object.defineProperty(this, "requestId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: null | ||
}); | ||
// This is used to avoid calling setup() on each render | ||
// each request is unique | ||
if (isServer()) { | ||
this.requestId = this.getRequestId(); | ||
} | ||
this.computeSchema(); | ||
this.setup(this.options.options); | ||
} | ||
// This method is used when there is no schema provided | ||
// to compute the schema accordingly to the defaultValue type | ||
computeSchema() { | ||
if (this.options.schema) { | ||
return; | ||
} | ||
if (typeof this.options.defaultValue === 'number') { | ||
this.options.schema = z.number(); | ||
} | ||
} | ||
configure(callback) { | ||
callback?.(); | ||
// This is the default behavior, when there is no value at initialization (setted by the callback) | ||
// no error and there is a default value, we set the value to the default value | ||
// if she is provided | ||
if (!this.value && !this.error && typeof this.options.defaultValue !== 'undefined') { | ||
this.set(this.options.defaultValue); | ||
} | ||
} | ||
getRequestId() { | ||
// @ts-ignore | ||
const requestId = globalThis?.request?.id ?? null; | ||
if (!requestId) { | ||
throw new Error('Cannot retrieve the request id, please make sure that framework is correctly patched or you are not using static rendering'); | ||
} | ||
return requestId; | ||
} | ||
parse(value) { | ||
if (this.options.schema) { | ||
let parsedValue = value; | ||
// @ts-ignore | ||
const typeName = this.options.schema._def.typeName; | ||
// This formatting is only needed when the incomming value is a string | ||
// so we need to convert it to the right type accordingly to the schema | ||
if (typeof value === 'string') { | ||
if (typeName === 'ZodObject') { | ||
parsedValue = safeParse(value); | ||
} | ||
if (typeName === 'ZodBoolean') { | ||
parsedValue = value === 'true' || value === '1'; | ||
} | ||
if (typeName === 'ZodNumber') { | ||
parsedValue = Number(value); | ||
} | ||
} | ||
const output = this.options.schema.safeParse(parsedValue); | ||
if (output.success) { | ||
this.error = null; | ||
return output.data; | ||
} | ||
this.error = output.error; | ||
return null; | ||
} | ||
// If there is no schema, we treat every value as a string | ||
return value; | ||
} | ||
// If this method return false or throw an error, the value will not be updated | ||
// instead of returning true, the value will be updated | ||
update(value, callback) { | ||
const oldValue = this.value; | ||
let oldError = this.error; | ||
let alreadHasError = this.error !== null; | ||
if (this.options.schema) { | ||
this.value = this.parse(value); | ||
} | ||
else { | ||
this.value = value; | ||
} | ||
// If there is no error, it's mean error was removed and we can trigger the callback | ||
// or the error changed, so we need to trigger the callback | ||
if (!this.error || !deepEqual(oldError?.errors, this.error?.errors)) { | ||
alreadHasError = false; | ||
} | ||
// If the value is the same, we don't need to trigger the callback | ||
// and no need to notify the subscribers | ||
// only in the case where the value is valid (no error) | ||
// and also if there is already an error, we don't need to emit the new value (prevent unwanted re-render) | ||
if ((!this.error && deepEqual(oldValue, this.value)) | ||
|| alreadHasError) | ||
return; | ||
// Actual behavior, if a wrong value is pushed, we simple log the error | ||
// and every next behavior stay the same as a valid value | ||
// it's mean if the schema is wrong, the callback will be called and every subscribers | ||
// will be notified of the new value and also the related error | ||
this.emit(value); | ||
callback(); | ||
} | ||
get() { | ||
// When we are on the server, we need to call setup() each time | ||
// to hydrate the gluon with the right value | ||
// to prevent to many setup() calls with execute the setup only | ||
// when the request is different | ||
if (isServer()) { | ||
const requestId = this.getRequestId(); | ||
if (this.requestId !== requestId) { | ||
this.setup(this.options.options); | ||
this.requestId = requestId; | ||
} | ||
} | ||
return this.value; | ||
} | ||
// This method is used to know if the gluon need to be hydrated | ||
// it's mean the gluon came with a presetted-value from the server and some code | ||
// should be apply to hydrate the value, but this behavior could be disabled | ||
isSSR() { | ||
return this.options.ssr ?? true; | ||
} | ||
} | ||
Object.defineProperty(Gluon, "SECURE_HYDRATION", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: false | ||
}); | ||
class QueryGluon extends Gluon { | ||
// @ts-ignore | ||
setup(options) { | ||
this.configure(() => { | ||
// this workaround is needed because the hostname is not available in the globalThis | ||
// so to have a behavior that is working on both server and client, we need to use the | ||
// example.com hostname to retrieve the search | ||
// @ts-ignore | ||
const url = new URL(`http://example.com${isServer() ? globalThis?.request?.url ?? '' : window.location.search}`); | ||
const searchParams = new URLSearchParams(url.search); | ||
let value = searchParams.get(this.name); | ||
// If there is no value in the url and the gluon is alread initialized | ||
// it's mean the user change the value manual in the url so we need to reset the internal value of | ||
// the gluon by forcing the update with the default value | ||
if (this.value && !value) { | ||
value = this.options.defaultValue; | ||
} | ||
if (value) { | ||
this.value = this.parse(value); | ||
} | ||
}); | ||
} | ||
set(value) { | ||
this.update(value, () => { | ||
if (isServer()) { | ||
return; | ||
} | ||
// This part of the set method is only called on the client | ||
// and is used to update the query string (not needed on the server) | ||
const searchParams = new URLSearchParams(window.location.search); | ||
let waitForUpdate = false; | ||
// If the value is null, it's mean it's first time we set the value | ||
// (query string is empty), we need to wait a little bit before pushing the new value | ||
// to prevent hmr to trigger an url update | ||
if (!searchParams.get(this.name)) { | ||
waitForUpdate = true; | ||
} | ||
searchParams.set(this.name, typeof value === 'object' | ||
? JSON.stringify(value) | ||
: value); | ||
if (waitForUpdate) { | ||
setTimeout(() => this.replaceState(searchParams), QueryGluon.PUSH_STATE_DELAY); | ||
return; | ||
} | ||
this.replaceState(searchParams); | ||
}); | ||
} | ||
replaceState(searchParams) { | ||
window.history.replaceState({ ...window.history.state }, '', `?${searchParams.toString()}`); | ||
} | ||
} | ||
Object.defineProperty(QueryGluon, "PUSH_STATE_DELAY", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: 10 | ||
}); | ||
class LocalGluon extends Gluon { | ||
setup() { | ||
// There is nothing to do on the server | ||
// no need to call configure (no need to trigger the callback) | ||
// so we can return | ||
if (isServer()) { | ||
return; | ||
} | ||
this.configure(() => { | ||
const value = localStorage.getItem(this.name); | ||
if (value) { | ||
this.value = this.parse(value); | ||
} | ||
}); | ||
} | ||
set(value) { | ||
// Nothing could be done on the server | ||
// because localStorage is not available | ||
if (isServer()) { | ||
return; | ||
} | ||
this.update(value, () => { | ||
localStorage.setItem(this.name, typeof value === 'object' | ||
? JSON.stringify(value) | ||
: value); | ||
}); | ||
} | ||
} | ||
Object.defineProperty(LocalGluon, "SECURE_HYDRATION", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: true | ||
}); | ||
function parse(str, options) { | ||
if (typeof str !== "string") { | ||
throw new TypeError("argument str must be a string"); | ||
} | ||
const obj = {}; | ||
const opt = {}; | ||
const dec = opt.decode || decode; | ||
let index = 0; | ||
while (index < str.length) { | ||
const eqIdx = str.indexOf("=", index); | ||
if (eqIdx === -1) { | ||
break; | ||
} | ||
let endIdx = str.indexOf(";", index); | ||
if (endIdx === -1) { | ||
endIdx = str.length; | ||
} else if (endIdx < eqIdx) { | ||
index = str.lastIndexOf(";", eqIdx - 1) + 1; | ||
continue; | ||
} | ||
const key = str.slice(index, eqIdx).trim(); | ||
if (opt?.filter && !opt?.filter(key)) { | ||
index = endIdx + 1; | ||
continue; | ||
} | ||
if (void 0 === obj[key]) { | ||
let val = str.slice(eqIdx + 1, endIdx).trim(); | ||
if (val.codePointAt(0) === 34) { | ||
val = val.slice(1, -1); | ||
} | ||
obj[key] = tryDecode(val, dec); | ||
} | ||
index = endIdx + 1; | ||
} | ||
return obj; | ||
} | ||
function decode(str) { | ||
return str.includes("%") ? decodeURIComponent(str) : str; | ||
} | ||
function tryDecode(str, decode2) { | ||
try { | ||
return decode2(str); | ||
} catch { | ||
return str; | ||
} | ||
} | ||
const fieldContentRegExp = /^[\u0009\u0020-\u007E\u0080-\u00FF]+$/; | ||
function serialize(name, value, options) { | ||
const opt = options || {}; | ||
const enc = opt.encode || encodeURIComponent; | ||
if (typeof enc !== "function") { | ||
throw new TypeError("option encode is invalid"); | ||
} | ||
if (!fieldContentRegExp.test(name)) { | ||
throw new TypeError("argument name is invalid"); | ||
} | ||
const encodedValue = enc(value); | ||
if (encodedValue && !fieldContentRegExp.test(encodedValue)) { | ||
throw new TypeError("argument val is invalid"); | ||
} | ||
let str = name + "=" + encodedValue; | ||
if (void 0 !== opt.maxAge && opt.maxAge !== null) { | ||
const maxAge = opt.maxAge - 0; | ||
if (Number.isNaN(maxAge) || !Number.isFinite(maxAge)) { | ||
throw new TypeError("option maxAge is invalid"); | ||
} | ||
str += "; Max-Age=" + Math.floor(maxAge); | ||
} | ||
if (opt.domain) { | ||
if (!fieldContentRegExp.test(opt.domain)) { | ||
throw new TypeError("option domain is invalid"); | ||
} | ||
str += "; Domain=" + opt.domain; | ||
} | ||
if (opt.path) { | ||
if (!fieldContentRegExp.test(opt.path)) { | ||
throw new TypeError("option path is invalid"); | ||
} | ||
str += "; Path=" + opt.path; | ||
} | ||
if (opt.expires) { | ||
if (!isDate(opt.expires) || Number.isNaN(opt.expires.valueOf())) { | ||
throw new TypeError("option expires is invalid"); | ||
} | ||
str += "; Expires=" + opt.expires.toUTCString(); | ||
} | ||
if (opt.httpOnly) { | ||
str += "; HttpOnly"; | ||
} | ||
if (opt.secure) { | ||
str += "; Secure"; | ||
} | ||
if (opt.priority) { | ||
const priority = typeof opt.priority === "string" ? opt.priority.toLowerCase() : opt.priority; | ||
switch (priority) { | ||
case "low": { | ||
str += "; Priority=Low"; | ||
break; | ||
} | ||
case "medium": { | ||
str += "; Priority=Medium"; | ||
break; | ||
} | ||
case "high": { | ||
str += "; Priority=High"; | ||
break; | ||
} | ||
default: { | ||
throw new TypeError("option priority is invalid"); | ||
} | ||
} | ||
} | ||
if (opt.sameSite) { | ||
const sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite; | ||
switch (sameSite) { | ||
case true: { | ||
str += "; SameSite=Strict"; | ||
break; | ||
} | ||
case "lax": { | ||
str += "; SameSite=Lax"; | ||
break; | ||
} | ||
case "strict": { | ||
str += "; SameSite=Strict"; | ||
break; | ||
} | ||
case "none": { | ||
str += "; SameSite=None"; | ||
break; | ||
} | ||
default: { | ||
throw new TypeError("option sameSite is invalid"); | ||
} | ||
} | ||
} | ||
if (opt.partitioned) { | ||
str += "; Partitioned"; | ||
} | ||
return str; | ||
} | ||
function isDate(val) { | ||
return Object.prototype.toString.call(val) === "[object Date]" || val instanceof Date; | ||
} | ||
class CookieGluon extends Gluon { | ||
setup(options) { | ||
// @ts-ignore | ||
this['cookiesOptions'] = options; | ||
this.configure(() => { | ||
// @ts-ignore | ||
const cookies = isServer() ? globalThis?.__incrementalCache?.requestHeaders?.cookie ?? '' : window.document.cookie; | ||
const parsedCookies = parse(cookies); | ||
let value = parsedCookies[this.name]; | ||
// If there is no value in the url and the gluon is alread initialized | ||
// it's mean the user change the value manual in the url so we need to reset the internal value of | ||
// the gluon by forcing the update with the default value | ||
if (this.value && !value) { | ||
value = this.options.defaultValue; | ||
} | ||
if (value) { | ||
this.value = this.parse(value); | ||
} | ||
}); | ||
} | ||
// @ts-ignore | ||
set(value) { | ||
this.update(value, () => { | ||
if (isServer()) { | ||
return; | ||
} | ||
const newCookie = serialize(this.name, typeof value === 'object' ? JSON.stringify(value) : value, | ||
// @ts-ignore | ||
this['cookiesOptions'] ?? {}); | ||
window.document.cookie = newCookie; | ||
}); | ||
} | ||
} | ||
class SessionGluon extends Gluon { | ||
setup() { | ||
// There is nothing to do on the server | ||
// no need to call configure (no need to trigger the callback) | ||
// so we can return | ||
if (isServer()) { | ||
return; | ||
} | ||
this.configure(() => { | ||
const value = sessionStorage.getItem(this.name); | ||
if (value) { | ||
this.value = this.parse(value); | ||
} | ||
}); | ||
} | ||
set(value) { | ||
// Nothing could be done on the server | ||
// because sessionStorage is not available | ||
if (isServer()) { | ||
return; | ||
} | ||
this.update(value, () => { | ||
sessionStorage.setItem(this.name, typeof value === 'object' | ||
? JSON.stringify(value) | ||
: value); | ||
}); | ||
} | ||
} | ||
Object.defineProperty(SessionGluon, "SECURE_HYDRATION", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: true | ||
}); | ||
const gluon = (name, options) => { | ||
if (options.from === 'query') { | ||
return new QueryGluon(name, options); | ||
} | ||
if (options.from === 'local') { | ||
return new LocalGluon(name, options); | ||
} | ||
if (options.from === 'cookie') { | ||
return new CookieGluon(name, options); | ||
} | ||
if (options.from === 'session') { | ||
return new SessionGluon(name, options); | ||
} | ||
throw new Error('Cannot create a Gluon from this source'); | ||
}; | ||
class ReadGluon extends GluonSubscription { | ||
constructor(getter, deps) { | ||
super(); | ||
Object.defineProperty(this, "getter", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: getter | ||
}); | ||
Object.defineProperty(this, "deps", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: deps | ||
}); | ||
Object.defineProperty(this, "value", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: null | ||
}); | ||
Object.defineProperty(this, "requestId", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: null | ||
}); | ||
Object.defineProperty(this, "unsubscribes", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: [] | ||
}); | ||
if (isServer()) { | ||
this.requestId = this.getRequestId(); | ||
} | ||
this.value = this.getter(); | ||
this.deps.forEach((dep) => { | ||
return dep.subscribe(() => { | ||
this.value = this.getter(); | ||
this.emit(this.value); | ||
}); | ||
}); | ||
} | ||
getRequestId() { | ||
// @ts-ignore | ||
const requestId = globalThis?.request?.id ?? null; | ||
if (!requestId) { | ||
throw new Error('Cannot retrieve the request id, please make sure that framework is correctly patched or you are not using static rendering'); | ||
} | ||
return requestId; | ||
} | ||
get() { | ||
if (isServer()) { | ||
const requestId = this.getRequestId(); | ||
if (this.requestId !== requestId) { | ||
this.requestId = requestId; | ||
this.value = this.getter(); | ||
} | ||
} | ||
return this.value; | ||
} | ||
asSecureHydrationDeps() { | ||
return this.deps.some((dep) => isSecureHydrationGluon(dep)); | ||
} | ||
} | ||
const computed = (getter, deps) => { | ||
return new ReadGluon(getter, deps); | ||
}; | ||
function asHydrationGuard(gluon) { | ||
if (gluon instanceof Gluon) { | ||
return isSecureHydrationGluon(gluon); | ||
} | ||
return gluon.asSecureHydrationDeps(); | ||
} | ||
const useGluon = (name, options) => { | ||
const gluonRef = useRef(); | ||
const isMountedRef = useRef(false); | ||
const countRef = useRef(0); | ||
if (!gluonRef.current) { | ||
gluonRef.current = typeof name === 'string' | ||
? gluon(name, options) | ||
: name; | ||
} | ||
const proxyRef = useRef(new Proxy({ value: gluonRef.current.get(), error: null }, { | ||
get: (...args) => { | ||
if (args[1] === 'value') { | ||
if (asHydrationGuard(gluonRef.current) && !isMountedRef.current) | ||
return null; | ||
return gluonRef.current?.get(); | ||
} | ||
if (args[1] === 'error' && gluonRef.current instanceof Gluon) { | ||
return gluonRef.current.error; | ||
} | ||
return Reflect.get(...args); | ||
}, | ||
set: (...args) => { | ||
if (gluonRef.current instanceof ReadGluon) { | ||
console.error('Cannot set a ReadGluon'); | ||
return false; | ||
} | ||
if (args[1] === 'value') { | ||
gluonRef.current.set(args[2]); | ||
} | ||
return Reflect.set(...args); | ||
} | ||
})); | ||
// To understand who useSyncExternalStore works, it's pretty basic | ||
// the callback is used to trigger the render of the component, if the value changes | ||
// and call the internal callback of the useSyncExternalStore, so useSyncExternalStore | ||
// will trigger a render, getSnapshot and getServerSnapshot is used to confirm the change | ||
// if the callback is called but the snapshot didn't change, the component will not be re-rendered | ||
useSyncExternalStore((callback) => { | ||
if (!isMountedRef.current) { | ||
isMountedRef.current = true; | ||
// This behavior is needed to prevent hydration error | ||
// because some gluon children class are not able to fetch the value from | ||
// the server (from the request) and we need to skip the first render (first value is null) | ||
// and manually calling the callback | ||
if (asHydrationGuard(gluonRef.current) && countRef.current === 0) { | ||
countRef.current++; | ||
callback(); | ||
} | ||
} | ||
const unsubscribe = gluonRef.current.subscribe(() => { | ||
countRef.current++; | ||
callback(); | ||
}); | ||
return unsubscribe; | ||
}, () => countRef.current, () => countRef.current); | ||
return proxyRef.current; | ||
}; | ||
export { computed, gluon, useGluon }; | ||
//# sourceMappingURL=index.js.map | ||
import{z as V}from"zod";import{useRef as w,useSyncExternalStore as W}from"react";const j=r=>r.isSSR()?r.constructor.SECURE_HYDRATION:!1,z=r=>{try{return JSON.parse(r)}catch(e){return console.error(e),r}},d=()=>typeof window>"u";var J=Object.getOwnPropertyNames,Y=Object.getOwnPropertySymbols,F=Object.prototype.hasOwnProperty;function A(r,e){return function(t,n,u){return r(t,n,u)&&e(t,n,u)}}function E(r){return function(i,t,n){if(!i||!t||typeof i!="object"||typeof t!="object")return r(i,t,n);var u=n.cache,a=u.get(i),s=u.get(t);if(a&&s)return a===t&&s===i;u.set(i,t),u.set(t,i);var l=r(i,t,n);return u.delete(i),u.delete(t),l}}function P(r){return J(r).concat(Y(r))}var R=Object.hasOwn||function(r,e){return F.call(r,e)};function g(r,e){return r||e?r===e:r===e||r!==r&&e!==e}var T="_owner",x=Object.getOwnPropertyDescriptor,C=Object.keys;function Z(r,e,i){var t=r.length;if(e.length!==t)return!1;for(;t-- >0;)if(!i.equals(r[t],e[t],t,t,r,e,i))return!1;return!0}function X(r,e){return g(r.getTime(),e.getTime())}function I(r,e,i){if(r.size!==e.size)return!1;for(var t={},n=r.entries(),u=0,a,s;(a=n.next())&&!a.done;){for(var l=e.entries(),f=!1,o=0;(s=l.next())&&!s.done;){var c=a.value,p=c[0],m=c[1],h=s.value,O=h[0],L=h[1];!f&&!t[o]&&(f=i.equals(p,O,u,o,r,e,i)&&i.equals(m,L,p,O,r,e,i))&&(t[o]=!0),o++}if(!f)return!1;u++}return!0}function K(r,e,i){var t=C(r),n=t.length;if(C(e).length!==n)return!1;for(var u;n-- >0;)if(u=t[n],u===T&&(r.$$typeof||e.$$typeof)&&r.$$typeof!==e.$$typeof||!R(e,u)||!i.equals(r[u],e[u],u,u,r,e,i))return!1;return!0}function b(r,e,i){var t=P(r),n=t.length;if(P(e).length!==n)return!1;for(var u,a,s;n-- >0;)if(u=t[n],u===T&&(r.$$typeof||e.$$typeof)&&r.$$typeof!==e.$$typeof||!R(e,u)||!i.equals(r[u],e[u],u,u,r,e,i)||(a=x(r,u),s=x(e,u),(a||s)&&(!a||!s||a.configurable!==s.configurable||a.enumerable!==s.enumerable||a.writable!==s.writable)))return!1;return!0}function Q(r,e){return g(r.valueOf(),e.valueOf())}function ee(r,e){return r.source===e.source&&r.flags===e.flags}function k(r,e,i){if(r.size!==e.size)return!1;for(var t={},n=r.values(),u,a;(u=n.next())&&!u.done;){for(var s=e.values(),l=!1,f=0;(a=s.next())&&!a.done;)!l&&!t[f]&&(l=i.equals(u.value,a.value,u.value,a.value,r,e,i))&&(t[f]=!0),f++;if(!l)return!1}return!0}function re(r,e){var i=r.length;if(e.length!==i)return!1;for(;i-- >0;)if(r[i]!==e[i])return!1;return!0}var te="[object Arguments]",ie="[object Boolean]",ne="[object Date]",ue="[object Map]",ae="[object Number]",se="[object Object]",oe="[object RegExp]",ce="[object Set]",le="[object String]",fe=Array.isArray,N=typeof ArrayBuffer=="function"&&ArrayBuffer.isView?ArrayBuffer.isView:null,G=Object.assign,pe=Object.prototype.toString.call.bind(Object.prototype.toString);function he(r){var e=r.areArraysEqual,i=r.areDatesEqual,t=r.areMapsEqual,n=r.areObjectsEqual,u=r.arePrimitiveWrappersEqual,a=r.areRegExpsEqual,s=r.areSetsEqual,l=r.areTypedArraysEqual;return function(o,c,p){if(o===c)return!0;if(o==null||c==null||typeof o!="object"||typeof c!="object")return o!==o&&c!==c;var m=o.constructor;if(m!==c.constructor)return!1;if(m===Object)return n(o,c,p);if(fe(o))return e(o,c,p);if(N!=null&&N(o))return l(o,c,p);if(m===Date)return i(o,c,p);if(m===RegExp)return a(o,c,p);if(m===Map)return t(o,c,p);if(m===Set)return s(o,c,p);var h=pe(o);return h===ne?i(o,c,p):h===oe?a(o,c,p):h===ue?t(o,c,p):h===ce?s(o,c,p):h===se?typeof o.then!="function"&&typeof c.then!="function"&&n(o,c,p):h===te?n(o,c,p):h===ie||h===ae||h===le?u(o,c,p):!1}}function de(r){var e=r.circular,i=r.createCustomConfig,t=r.strict,n={areArraysEqual:t?b:Z,areDatesEqual:X,areMapsEqual:t?A(I,b):I,areObjectsEqual:t?b:K,arePrimitiveWrappersEqual:Q,areRegExpsEqual:ee,areSetsEqual:t?A(k,b):k,areTypedArraysEqual:t?b:re};if(i&&(n=G({},n,i(n))),e){var u=E(n.areArraysEqual),a=E(n.areMapsEqual),s=E(n.areObjectsEqual),l=E(n.areSetsEqual);n=G({},n,{areArraysEqual:u,areMapsEqual:a,areObjectsEqual:s,areSetsEqual:l})}return n}function me(r){return function(e,i,t,n,u,a,s){return r(e,i,s)}}function ye(r){var e=r.circular,i=r.comparator,t=r.createState,n=r.equals,u=r.strict;if(t)return function(l,f){var o=t(),c=o.cache,p=c===void 0?e?new WeakMap:void 0:c,m=o.meta;return i(l,f,{cache:p,equals:n,meta:m,strict:u})};if(e)return function(l,f){return i(l,f,{cache:new WeakMap,equals:n,meta:void 0,strict:u})};var a={cache:void 0,equals:n,meta:void 0,strict:u};return function(l,f){return i(l,f,a)}}var D=y();y({strict:!0}),y({circular:!0}),y({circular:!0,strict:!0}),y({createInternalComparator:function(){return g}}),y({strict:!0,createInternalComparator:function(){return g}}),y({circular:!0,createInternalComparator:function(){return g}}),y({circular:!0,createInternalComparator:function(){return g},strict:!0});function y(r){r===void 0&&(r={});var e=r.circular,i=e===void 0?!1:e,t=r.createInternalComparator,n=r.createState,u=r.strict,a=u===void 0?!1:u,s=de(r),l=he(s),f=t?t(l):me(l);return ye({circular:i,comparator:l,createState:n,equals:f,strict:a})}class ${constructor(){Object.defineProperty(this,"subscribers",{enumerable:!0,configurable:!0,writable:!0,value:new Set})}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}unsubscribe(){this.subscribers.clear()}emit(e){this.subscribers.forEach(i=>i(e))}}class v extends ${constructor(e,i){super(),Object.defineProperty(this,"name",{enumerable:!0,configurable:!0,writable:!0,value:e}),Object.defineProperty(this,"options",{enumerable:!0,configurable:!0,writable:!0,value:i}),Object.defineProperty(this,"value",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"error",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"requestId",{enumerable:!0,configurable:!0,writable:!0,value:null}),d()&&(this.requestId=this.getRequestId()),this.computeSchema(),this.setup(this.options.options)}computeSchema(){this.options.schema||typeof this.options.defaultValue=="number"&&(this.options.schema=V.number())}configure(e){e?.(),!this.value&&!this.error&&typeof this.options.defaultValue<"u"&&this.set(this.options.defaultValue)}getRequestId(){const e=globalThis?.request?.id??null;if(!e)throw new Error("Cannot retrieve the request id, please make sure that framework is correctly patched or you are not using static rendering");return e}parse(e){if(this.options.schema){let i=e;const t=this.options.schema._def.typeName;typeof e=="string"&&(t==="ZodObject"&&(i=z(e)),t==="ZodBoolean"&&(i=e==="true"||e==="1"),t==="ZodNumber"&&(i=Number(e)));const n=this.options.schema.safeParse(i);return n.success?(this.error=null,n.data):(this.error=n.error,null)}return e}update(e,i){const t=this.value;let n=this.error,u=this.error!==null;this.options.schema?this.value=this.parse(e):this.value=e,(!this.error||!D(n?.errors,this.error?.errors))&&(u=!1),!(!this.error&&D(t,this.value)||u)&&(this.emit(e),i())}get(){if(d()){const e=this.getRequestId();this.requestId!==e&&(this.setup(this.options.options),this.requestId=e)}return this.value}isSSR(){return this.options.ssr??!0}}Object.defineProperty(v,"SECURE_HYDRATION",{enumerable:!0,configurable:!0,writable:!0,value:!1});class S extends v{setup(e){this.configure(()=>{const i=new URL(`http://example.com${d()?globalThis?.request?.url??"":window.location.search}`);let n=new URLSearchParams(i.search).get(this.name);this.value&&!n&&(n=this.options.defaultValue),n&&(this.value=this.parse(n))})}set(e){this.update(e,()=>{if(d())return;const i=new URLSearchParams(window.location.search);let t=!1;if(i.get(this.name)||(t=!0),i.set(this.name,typeof e=="object"?JSON.stringify(e):e),t){setTimeout(()=>this.replaceState(i),S.PUSH_STATE_DELAY);return}this.replaceState(i)})}replaceState(e){window.history.replaceState({...window.history.state},"",`?${e.toString()}`)}}Object.defineProperty(S,"PUSH_STATE_DELAY",{enumerable:!0,configurable:!0,writable:!0,value:10});class U extends v{setup(){d()||this.configure(()=>{const e=localStorage.getItem(this.name);e&&(this.value=this.parse(e))})}set(e){d()||this.update(e,()=>{localStorage.setItem(this.name,typeof e=="object"?JSON.stringify(e):e)})}}Object.defineProperty(U,"SECURE_HYDRATION",{enumerable:!0,configurable:!0,writable:!0,value:!0});function ve(r,e){if(typeof r!="string")throw new TypeError("argument str must be a string");const i={},t={},n=t.decode||ge;let u=0;for(;u<r.length;){const a=r.indexOf("=",u);if(a===-1)break;let s=r.indexOf(";",u);if(s===-1)s=r.length;else if(s<a){u=r.lastIndexOf(";",a-1)+1;continue}const l=r.slice(u,a).trim();if(t?.filter&&!t?.filter(l)){u=s+1;continue}if(i[l]===void 0){let f=r.slice(a+1,s).trim();f.codePointAt(0)===34&&(f=f.slice(1,-1)),i[l]=be(f,n)}u=s+1}return i}function ge(r){return r.includes("%")?decodeURIComponent(r):r}function be(r,e){try{return e(r)}catch{return r}}const q=/^[\u0009\u0020-\u007E\u0080-\u00FF]+$/;function we(r,e,i){const t=i||{},n=t.encode||encodeURIComponent;if(typeof n!="function")throw new TypeError("option encode is invalid");if(!q.test(r))throw new TypeError("argument name is invalid");const u=n(e);if(u&&!q.test(u))throw new TypeError("argument val is invalid");let a=r+"="+u;if(t.maxAge!==void 0&&t.maxAge!==null){const s=t.maxAge-0;if(Number.isNaN(s)||!Number.isFinite(s))throw new TypeError("option maxAge is invalid");a+="; Max-Age="+Math.floor(s)}if(t.domain){if(!q.test(t.domain))throw new TypeError("option domain is invalid");a+="; Domain="+t.domain}if(t.path){if(!q.test(t.path))throw new TypeError("option path is invalid");a+="; Path="+t.path}if(t.expires){if(!Ee(t.expires)||Number.isNaN(t.expires.valueOf()))throw new TypeError("option expires is invalid");a+="; Expires="+t.expires.toUTCString()}if(t.httpOnly&&(a+="; HttpOnly"),t.secure&&(a+="; Secure"),t.priority)switch(typeof t.priority=="string"?t.priority.toLowerCase():t.priority){case"low":{a+="; Priority=Low";break}case"medium":{a+="; Priority=Medium";break}case"high":{a+="; Priority=High";break}default:throw new TypeError("option priority is invalid")}if(t.sameSite)switch(typeof t.sameSite=="string"?t.sameSite.toLowerCase():t.sameSite){case!0:{a+="; SameSite=Strict";break}case"lax":{a+="; SameSite=Lax";break}case"strict":{a+="; SameSite=Strict";break}case"none":{a+="; SameSite=None";break}default:throw new TypeError("option sameSite is invalid")}return t.partitioned&&(a+="; Partitioned"),a}function Ee(r){return Object.prototype.toString.call(r)==="[object Date]"||r instanceof Date}class qe extends v{setup(e){this.cookiesOptions=e,this.configure(()=>{const i=d()?globalThis?.__incrementalCache?.requestHeaders?.cookie??"":window.document.cookie;let n=ve(i)[this.name];this.value&&!n&&(n=this.options.defaultValue),n&&(this.value=this.parse(n))})}set(e){this.update(e,()=>{if(d())return;const i=we(this.name,typeof e=="object"?JSON.stringify(e):e,this.cookiesOptions??{});window.document.cookie=i})}}class H extends v{setup(){d()||this.configure(()=>{const e=sessionStorage.getItem(this.name);e&&(this.value=this.parse(e))})}set(e){d()||this.update(e,()=>{sessionStorage.setItem(this.name,typeof e=="object"?JSON.stringify(e):e)})}}Object.defineProperty(H,"SECURE_HYDRATION",{enumerable:!0,configurable:!0,writable:!0,value:!0});const _=(r,e)=>{if(e.from==="query")return new S(r,e);if(e.from==="local")return new U(r,e);if(e.from==="cookie")return new qe(r,e);if(e.from==="session")return new H(r,e);throw new Error("Cannot create a Gluon from this source")};class M extends ${constructor(e,i){super(),Object.defineProperty(this,"getter",{enumerable:!0,configurable:!0,writable:!0,value:e}),Object.defineProperty(this,"deps",{enumerable:!0,configurable:!0,writable:!0,value:i}),Object.defineProperty(this,"value",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"requestId",{enumerable:!0,configurable:!0,writable:!0,value:null}),Object.defineProperty(this,"unsubscribes",{enumerable:!0,configurable:!0,writable:!0,value:[]}),d()&&(this.requestId=this.getRequestId()),this.value=this.getter(),this.deps.forEach(t=>t.subscribe(()=>{this.value=this.getter(),this.emit(this.value)}))}getRequestId(){const e=globalThis?.request?.id??null;if(!e)throw new Error("Cannot retrieve the request id, please make sure that framework is correctly patched or you are not using static rendering");return e}get(){if(d()){const e=this.getRequestId();this.requestId!==e&&(this.requestId=e,this.value=this.getter())}return this.value}asSecureHydrationDeps(){return this.deps.some(e=>j(e))}}const Se=(r,e)=>new M(r,e);function B(r){return r instanceof v?j(r):r.asSecureHydrationDeps()}const Oe=(r,e)=>{const i=w(),t=w(!1),n=w(0);i.current||(i.current=typeof r=="string"?_(r,e):r);const u=w(new Proxy({value:i.current.get(),error:null},{get:(...a)=>a[1]==="value"?B(i.current)&&!t.current?null:i.current?.get():a[1]==="error"&&i.current instanceof v?i.current.error:Reflect.get(...a),set:(...a)=>i.current instanceof M?(console.error("Cannot set a ReadGluon"),!1):(a[1]==="value"&&i.current.set(a[2]),Reflect.set(...a))}));return W(a=>(t.current||(t.current=!0,B(i.current)&&n.current===0&&(n.current++,a())),i.current.subscribe(()=>{n.current++,a()})),()=>n.current,()=>n.current),u.current};export{Se as computed,_ as gluon,Oe as useGluon}; |
{ | ||
"name": "stayte", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"description": "The persistent state library for the modern web", | ||
@@ -14,7 +14,7 @@ "exports": { | ||
"patches", | ||
"scripts", | ||
"scripts/patch.js", | ||
"tsconfig.json" | ||
], | ||
"scripts": { | ||
"postinstall": "node scripts/patch.js > file", | ||
"postinstall": "node scripts/patch.js", | ||
"dev": "rollup --config rollup.config.mjs --watch", | ||
@@ -21,0 +21,0 @@ "build": "rm -rf dist && rollup --config rollup.config.mjs" |
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
22454
16
258
1