UNPKG

@goiam/react

Version:

React SDK for Go-IAM - A lightweight Identity and Access Management server

1,149 lines (1,134 loc) 74.4 kB
'use strict'; var React = require('react'); var jsxRuntime = require('react/jsx-runtime'); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var __assign$1 = function() { __assign$1 = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign$1.apply(this, arguments); }; typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; /** * Copied from fbjs is-shallow-equal */ var hasOwnProperty = Object.prototype.hasOwnProperty; /** * inlined Object.is polyfill to avoid requiring consumers ship their own * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is */ function is(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 // Added the nonzero y check to make Flow happy, but it is redundant return x !== 0 || y !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } } /** * Performs equality by iterating through keys on an object and returning false * when any key has values which are not strictly equal between the arguments. * Returns true when the values of all keys are strictly equal. */ function shallowEqual(objA, objB) { if (is(objA, objB)) { return true; } if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { return false; } var keysA = Object.keys(objA); var keysB = Object.keys(objB); if (keysA.length !== keysB.length) { return false; } // Test for A's keys different from B. for (var i = 0; i < keysA.length; i++) { if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { return false; } } return true; } /** * Special symbol which might be used to delete properties * from an object calling [State.set](#set) or [State.merge](#merge). * * [Learn more...](https://hookstate.js.org/docs/nested-state#deleting-existing-element) */ var none = Symbol('none'); // type PickByType<T, U, B = false> = Pick<T, KeysOfType<T, U, B>>; /** * A symbol which is used for type inference marking. * * @hidden * @ignore */ var __state = Symbol('__state'); function hookstate(initial, extension) { var store = createStore(initial); store.activate(extension); var methods = store.toMethods(); return methods.self(); } function useHookstate(source, extension) { var parentMethods = Object(source) === source ? source[self] : undefined; if (parentMethods) { if (parentMethods.isMounted) { // Scoped state mount // eslint-disable-next-line react-hooks/rules-of-hooks var initializer = function () { // warning: this is called twice in react strict mode var store = parentMethods.store; var onSetUsedCallback = function () { return setValue_1({ store: store, state: state, source: value_1.source, parentMethods: parentMethods }); }; var state = new StateMethodsImpl(store, parentMethods.path, store.get(parentMethods.path), store.edition, onSetUsedCallback); return { store: store, state: state, source: source, parentMethods: parentMethods }; }; var _a = React.useState(initializer), value_1 = _a[0], setValue_1 = _a[1]; if (value_1.store !== parentMethods.store || !('source' in value_1)) { value_1.state.onUnmount(); value_1.parentMethods.unsubscribe(value_1.state); value_1 = initializer(); } // TODO move to a class hide props on prototype level // hide props from development tools Object.defineProperty(value_1, 'store', { enumerable: false }); Object.defineProperty(value_1, 'state', { enumerable: false }); Object.defineProperty(value_1, 'source', { enumerable: false }); Object.defineProperty(value_1, 'parentMethods', { enumerable: false }); value_1.state.reconstruct(parentMethods.path, value_1.store.get(parentMethods.path), value_1.store.edition, // parent state object has changed its reference object // so the scopped state should change too value_1.source !== source); value_1.source = source; // need to subscribe in sync mode, because // safari delays calling the effect giving priority to timeouts and network events, // which can cause the state update parentMethods.subscribe(value_1.state); // no-op if already subscribed useIsomorphicLayoutEffect(function () { // warning: in strict mode, effect is called twice // so need to restore subscription and reconstruct the extension // after the first effect unmount callback value_1.state.onMount(); // no-op if already mounted parentMethods.subscribe(value_1.state); // no-op if already subscribed return function () { value_1.state.onUnmount(); parentMethods.unsubscribe(value_1.state); }; }, []); var state = value_1.state.self(); // expose property in development tools value_1['[hookstate(scoped)]'] = state; // TODO use label here, add core extension to label states return state; } else { // Global state mount or destroyed link // eslint-disable-next-line react-hooks/rules-of-hooks var initializer = function () { // warning: this is called twice in react strict mode var store = parentMethods.store; var onSetUsedCallback = function () { return value_2.state.isMounted && setValue_2({ store: store, state: state, source: value_2.source // mutable, get the latest from value }); }; var state = new StateMethodsImpl(store, RootPath, store.get(RootPath), store.edition, onSetUsedCallback); return { store: store, state: state, source: source }; }; var _b = React.useState(initializer), value_2 = _b[0], setValue_2 = _b[1]; if (value_2.store !== parentMethods.store || !('source' in value_2)) { value_2.state.onUnmount(); value_2.store.unsubscribe(value_2.state); value_2 = initializer(); } // hide props from development tools Object.defineProperty(value_2, 'store', { enumerable: false }); Object.defineProperty(value_2, 'state', { enumerable: false }); Object.defineProperty(value_2, 'source', { enumerable: false }); value_2.state.reconstruct(RootPath, value_2.store.get(RootPath), value_2.store.edition, // parent state object has changed its reference object // so the scopped state should change too value_2.source !== source); value_2.source = source; // need to subscribe in sync mode, because // safari delays calling the effect giving priority to timeouts and network events, // which can cause the state update value_2.store.subscribe(value_2.state); // no-op if already subscribed useIsomorphicLayoutEffect(function () { // warning: in strict mode, effect is called twice // so need to restore subscription and reconstruct the extension // after the first effect unmount callback value_2.state.onMount(); // no-op if already mounted value_2.store.subscribe(value_2.state); // no-op if already subscribed return function () { value_2.state.onUnmount(); value_2.store.unsubscribe(value_2.state); }; }, []); var state = value_2.state.self(); for (var ind = 0; ind < parentMethods.path.length; ind += 1) { state = state.nested(parentMethods.path[ind]); } // expose property in development tools value_2['[hookstate(global)]'] = state; // TODO use label here, add core extension to label states return state; } } else { // Local state mount // eslint-disable-next-line react-hooks/rules-of-hooks var initializer = function () { // warning: this is called twice in react strict mode var store = createStore(source); var onSetUsedCallback = function () { return value_3.state.isMounted && setValue_3({ store: store, state: state, }); }; var state = new StateMethodsImpl(store, RootPath, store.get(RootPath), store.edition, onSetUsedCallback); return { store: store, state: state }; }; var _c = React.useState(initializer), value_3 = _c[0], setValue_3 = _c[1]; if ('source' in value_3) { value_3.state.onUnmount(); value_3.store.unsubscribe(value_3.state); value_3.store.deactivate(); value_3 = initializer(); } // hide props from development tools Object.defineProperty(value_3, 'store', { enumerable: false }); Object.defineProperty(value_3, 'state', { enumerable: false }); value_3.state.reconstruct(RootPath, value_3.store.get(RootPath), value_3.store.edition, false); // need to subscribe in sync mode, because // safari delays calling the effect giving priority to timeouts and network events, // which can cause the state update value_3.store.subscribe(value_3.state); // no-op if already subscribed // need to attach the extension straight away // because extension methods are used in render function // and we can not defer it to the effect callback value_3.store.activate(extension); // no-op if already attached useIsomorphicLayoutEffect(function () { // warning: in strict mode, effect is called twice // so need to restore subscription and reconstruct the extension // after the first effect unmount callback value_3.state.onMount(); // no-op if already mounted value_3.store.subscribe(value_3.state); // no-op if already subscribed value_3.store.activate(extension); // no-op if already attached return function () { value_3.state.onUnmount(); value_3.store.unsubscribe(value_3.state); value_3.store.deactivate(); // this will destroy the extensions }; }, []); var state = value_3.state.self(); // expose property in development tools value_3['[hookstate(local)]'] = state; // TODO use label here, add core extension to label states return state; } } /// /// INTERNAL SYMBOLS (LIBRARY IMPLEMENTATION) /// var self = Symbol('self'); var ErrorId; (function (ErrorId) { ErrorId[ErrorId["StateUsedInDependencyList"] = 100] = "StateUsedInDependencyList"; ErrorId[ErrorId["InitStateToValueFromState"] = 101] = "InitStateToValueFromState"; ErrorId[ErrorId["SetStateToValueFromState"] = 102] = "SetStateToValueFromState"; ErrorId[ErrorId["GetStateWhenPromised"] = 103] = "GetStateWhenPromised"; ErrorId[ErrorId["SetStateWhenPromised"] = 104] = "SetStateWhenPromised"; ErrorId[ErrorId["SetStateNestedToPromised"] = 105] = "SetStateNestedToPromised"; ErrorId[ErrorId["SetStateWhenDestroyed"] = 106] = "SetStateWhenDestroyed"; ErrorId[ErrorId["ToJson_Value"] = 108] = "ToJson_Value"; ErrorId[ErrorId["ToJson_State"] = 109] = "ToJson_State"; ErrorId[ErrorId["GetProperty_Function"] = 110] = "GetProperty_Function"; ErrorId[ErrorId["InitStateStoreSwitchover"] = 111] = "InitStateStoreSwitchover"; ErrorId[ErrorId["GetUnknownPlugin"] = 120] = "GetUnknownPlugin"; ErrorId[ErrorId["SetProperty_State"] = 201] = "SetProperty_State"; ErrorId[ErrorId["SetProperty_Value"] = 202] = "SetProperty_Value"; ErrorId[ErrorId["SetPrototypeOf_State"] = 203] = "SetPrototypeOf_State"; ErrorId[ErrorId["SetPrototypeOf_Value"] = 204] = "SetPrototypeOf_Value"; ErrorId[ErrorId["PreventExtensions_State"] = 205] = "PreventExtensions_State"; ErrorId[ErrorId["PreventExtensions_Value"] = 206] = "PreventExtensions_Value"; ErrorId[ErrorId["DefineProperty_State"] = 207] = "DefineProperty_State"; ErrorId[ErrorId["DefineProperty_Value"] = 208] = "DefineProperty_Value"; ErrorId[ErrorId["DeleteProperty_State"] = 209] = "DeleteProperty_State"; ErrorId[ErrorId["DeleteProperty_Value"] = 210] = "DeleteProperty_Value"; ErrorId[ErrorId["Construct_State"] = 211] = "Construct_State"; ErrorId[ErrorId["Construct_Value"] = 212] = "Construct_Value"; ErrorId[ErrorId["Apply_State"] = 213] = "Apply_State"; ErrorId[ErrorId["Apply_Value"] = 214] = "Apply_Value"; })(ErrorId || (ErrorId = {})); var StateInvalidUsageError = /** @class */ (function (_super) { __extends(StateInvalidUsageError, _super); function StateInvalidUsageError(path, id, details) { return _super.call(this, "Error: HOOKSTATE-".concat(id, " [path: /").concat(path.join('/')).concat(details ? ", details: ".concat(details) : '', "]. ") + "See https://hookstate.js.org/docs/exceptions#hookstate-".concat(id)) || this; } return StateInvalidUsageError; }(Error)); var SelfMethodsID = Symbol('ProxyMarker'); var RootPath = []; var Store = /** @class */ (function () { function Store(_value) { var _this = this; this._value = _value; // > 0 means active store, < 0 means destroyed // please note, in react strict mode and hot reload cases // state can be reused, so we should support store resurection this.edition = 1; this._subscribers = new Set(); if (Object(_value) === _value && configuration.promiseDetector(_value)) { this.setPromised(_value); } else if (_value === none) { this.setPromised(undefined); } var onSetUsedStoreStateMethods = function () { _this._stateMethods.reconstruct(RootPath, _this.get(RootPath), _this.edition, false); }; onSetUsedStoreStateMethods[IsUnmounted] = true; this._stateMethods = new StateMethodsImpl(this, RootPath, this.get(RootPath), this.edition, onSetUsedStoreStateMethods); this.subscribe(this._stateMethods); } Store.prototype.setPromised = function (promise) { var _this = this; this._value = none; this._promiseError = undefined; this._promiseResolver = undefined; if (!promise) { this._promise = new Promise(function (resolve) { _this._promiseResolver = resolve; }); return; } promise = promise .then(function (r) { if (_this._promise === promise) { _this._promise = undefined; _this._promiseError = undefined; _this._promiseResolver === undefined; _this.update(_this._stateMethods.self(), _this.set(RootPath, r)); } }) .catch(function (err) { if (_this._promise === promise) { _this._promise = undefined; _this._promiseResolver = undefined; _this._promiseError = err; _this.edition += 1; var ad = { path: RootPath }; _this.update(_this._stateMethods.self(), ad); } }); this._promise = promise; }; Store.prototype.activate = function (extensionFactory) { var _a, _b, _c, _d; if (this.edition < 0) { this.edition = -this.edition; } if (this._extension === undefined) { this._extension = extensionFactory === null || extensionFactory === void 0 ? void 0 : extensionFactory(); this._extensionMethods = (_b = (_a = this._extension) === null || _a === void 0 ? void 0 : _a.onCreate) === null || _b === void 0 ? void 0 : _b.call(_a, this._stateMethods.self(), {}); // this is invoked with all extension methods activated on the state (_d = (_c = this._extension) === null || _c === void 0 ? void 0 : _c.onInit) === null || _d === void 0 ? void 0 : _d.call(_c, this._stateMethods.self(), this._extensionMethods || {}); } }; Store.prototype.deactivate = function () { var _a, _b; if (this._extension) { (_b = (_a = this._extension).onDestroy) === null || _b === void 0 ? void 0 : _b.call(_a, this._stateMethods.self()); delete this._extension; delete this._extensionMethods; } if (this.edition > 0) { this.edition = -this.edition; } }; Object.defineProperty(Store.prototype, "extension", { get: function () { return this._extensionMethods; }, enumerable: false, configurable: true }); Object.defineProperty(Store.prototype, "promise", { get: function () { return this._promise; }, enumerable: false, configurable: true }); Object.defineProperty(Store.prototype, "promiseError", { get: function () { return this._promiseError; }, enumerable: false, configurable: true }); Store.prototype.get = function (path) { var result = this._value; if (result === none) { return result; } path.forEach(function (p) { result = result[p]; }); return result; }; Store.prototype.set = function (path, value) { var _a, _b; if (path.length === 0) { // Root value UPDATE case, if (value === none) { this.setPromised(undefined); } else if (Object(value) === value && configuration.promiseDetector(value)) { this.setPromised(value); value = none; } else if (this._promise && !this._promiseResolver) { throw new StateInvalidUsageError(path, ErrorId.SetStateWhenPromised); } else { this._promiseError = undefined; } var prevValue = this._value; this._value = value; this.afterSet(); if (prevValue === none && this._value !== none && this._promiseResolver) { this._promise = undefined; this._promiseError = undefined; var resolver = this._promiseResolver; this._promiseResolver === undefined; resolver(this._value); } return { path: path }; } if (Object(value) === value && configuration.promiseDetector(value)) { // TODO this one still can get into the state as nested property, need to check on read instead throw new StateInvalidUsageError(path, ErrorId.SetStateNestedToPromised); } var target = this._value; for (var i = 0; i < path.length - 1; i += 1) { target = target[path[i]]; } var p = path[path.length - 1]; if (p in target) { if (value !== none) { // Property UPDATE case target[p] = value; this.afterSet(); return { path: path }; } else { // Property DELETE case if (Array.isArray(target) && typeof p === 'number') { target.splice(p, 1); } else { delete target[p]; } this.afterSet(); // if an array of objects is about to loose existing property // we consider it is the whole object is changed // which is identified by upper path return { path: path.slice(0, -1), actions: (_a = {}, _a[p] = "D", _a) }; } } if (value !== none) { // Property INSERT case target[p] = value; this.afterSet(); // if an array of objects is about to be extended by new property // we consider it is the whole object is changed // which is identified by upper path return { path: path.slice(0, -1), actions: (_b = {}, _b[p] = "I", _b) }; } // Non-existing property DELETE case // no-op return { path: path }; }; Store.prototype.preset = function (state, value) { var _a, _b; (_b = (_a = this._extension) === null || _a === void 0 ? void 0 : _a.onPreset) === null || _b === void 0 ? void 0 : _b.call(_a, state, value, this._stateMethods.self()); }; Store.prototype.premerge = function (state, value) { var _a, _b; (_b = (_a = this._extension) === null || _a === void 0 ? void 0 : _a.onPremerge) === null || _b === void 0 ? void 0 : _b.call(_a, state, value, this._stateMethods.self()); }; Store.prototype.update = function (state, ad) { var _this = this; var _a, _b; (_b = (_a = this._extension) === null || _a === void 0 ? void 0 : _a.onSet) === null || _b === void 0 ? void 0 : _b.call(_a, state, ad, this._stateMethods.self()); var actions = new Set(); // check if actions descriptor can be unfolded into a number of individual update actions // this is the case when merge call swaps to properties for example // so we optimize rerendering only these properties if (ad.actions && Object.values(ad.actions).findIndex(function (i) { return i !== "U"; }) === -1) { // all actions are update actions Object.keys(ad.actions).forEach(function (key) { _this._subscribers.forEach(function (s) { return s.onSet({ path: ad.path.concat(key) }, actions); }); }); } else { this._subscribers.forEach(function (s) { return s.onSet(ad, actions); }); } actions.forEach(function (a) { return a(); }); }; Store.prototype.afterSet = function () { if (this.edition > 0) { this.edition += 1; } if (this.edition < 0) { this.edition -= 1; } }; Store.prototype.toMethods = function () { return this._stateMethods; }; Store.prototype.subscribe = function (l) { this._subscribers.add(l); }; Store.prototype.unsubscribe = function (l) { this._subscribers.delete(l); }; Store.prototype.toJSON = function () { throw new StateInvalidUsageError(RootPath, ErrorId.ToJson_Value); }; return Store; }()); // use symbol property to allow for easier reference finding var UnusedValue = Symbol('UnusedValue'); // use symbol to mark that a function has no effect anymore var IsUnmounted = Symbol('IsUnmounted'); var StateMethodsImpl = /** @class */ (function () { function StateMethodsImpl(store, path, valueSource, valueEdition, onSetUsed) { this.store = store; this.path = path; this.valueSource = valueSource; this.valueEdition = valueEdition; this.onSetUsed = onSetUsed; this.valueUsed = UnusedValue; } Object.defineProperty(StateMethodsImpl.prototype, __state, { get: function () { return [this.get(), this.self()]; }, enumerable: false, configurable: true }); StateMethodsImpl.prototype.reconstruct = function (path, valueSource, valueEdition, reset) { this.path = path; this.valueSource = valueSource; this.valueEdition = valueEdition; this.valueUsed = UnusedValue; if (reset) { delete this.selfUsed; delete this.childrenCreated; delete this.childrenUsedPrevious; } else { this.valueUsedNoProxyPrevious = this.valueUsedNoProxy; this.childrenUsedPrevious = this.childrenUsed; } delete this.valueUsedNoProxy; delete this.childrenUsed; // We should not delete subscribers as these are self cleaned up when unmounted // Theoretically it is possible to reconnect subscribers like we done it for // children, but it is easier and more efficient to leave subscribers to have independent lifecycle // If we delete subscribers here, scoped states wrapped in React.memo // will lose state change propagation and rerendering for scopped states // delete this.subscribers; }; StateMethodsImpl.prototype.reconnect = function () { // Mark it's as used, because it is used in a dependency list // (we are making it's value used implicitly, so rerender is triggered). // Otherwise, no rerender => no effects running, even when a value is changed. // This is marking the state used a bit more than it might be really used // in the effect callback. More optimized / precise implementation would be // to remember useSelf as previous (similar to childrenUsed), // but it is a lot more complicated and the benefit is not worth the complexity. // So, mark it used. // We also using it without proxy if it wass used without proxy during the // previous render, because otherwise children usage might be not traced completely // and so will not result in renreder if children are updated. // This is covered by some tests, but there are so many possible corner cases... this.get({ __internalAllowPromised: true, noproxy: this.valueUsedNoProxyPrevious }); this.childrenUsed = __assign(__assign({}, this.childrenUsedPrevious), this.childrenUsed); }; StateMethodsImpl.prototype.getUntracked = function (__internalAllowPromised) { if (this.valueEdition !== this.store.edition) { this.valueSource = this.store.get(this.path); this.valueEdition = this.store.edition; if (this.valueUsed !== UnusedValue) { this.valueUsed = UnusedValue; this.get({ __internalAllowPromised: true }); // renew cache to keep it marked used } } if (__internalAllowPromised) { return this.valueSource; } if (this.store.promiseError) { throw this.store.promiseError; } if (this.store.promise) { throw new StateInvalidUsageError(this.path, ErrorId.GetStateWhenPromised); } return this.valueSource; }; StateMethodsImpl.prototype.get = function (options) { var _a; var valueSource = this.getUntracked(options === null || options === void 0 ? void 0 : options.__internalAllowPromised); if (options === null || options === void 0 ? void 0 : options.stealth) { return valueSource; } if (this.valueUsed === UnusedValue) { if (Array.isArray(valueSource)) { this.valueUsed = this.valueArrayImpl(valueSource); } else if (Object(valueSource) === valueSource) { if (((_a = valueSource.constructor) === null || _a === void 0 ? void 0 : _a.name) === "Object") { this.valueUsed = this.valueObjectImpl(valueSource); } else { // any other object except Object, for example Date this.valueUsedNoProxy = true; this.valueUsed = valueSource; } } else { this.valueUsed = valueSource; } } if (options === null || options === void 0 ? void 0 : options.noproxy) { this.valueUsedNoProxy = true; return valueSource; } return this.valueUsed; }; Object.defineProperty(StateMethodsImpl.prototype, "value", { get: function () { // various tools, including react dev tools and webpack import // inspect an object and it's properties // so these should not throw // return this.get({ __internalAllowPromised: true }) return this.get(); }, enumerable: false, configurable: true }); StateMethodsImpl.prototype.setUntrackedV4 = function (newValue) { if (typeof newValue === 'function') { newValue = newValue(this.getUntracked()); } this.store.preset(this.self(), newValue); if (Object(newValue) === newValue && newValue[SelfMethodsID]) { // TODO check on read instead as it might escape as nested on set anyway throw new StateInvalidUsageError(this.path, ErrorId.SetStateToValueFromState); } if (newValue !== Object(newValue) && newValue === this.getUntracked(true)) { // this is primitive value and has not changed // so skip this set call as it does not make an effect return null; } return this.store.set(this.path, newValue); }; StateMethodsImpl.prototype.set = function (newValue) { var ad = this.setUntrackedV4(newValue); if (ad) { this.store.update(this.self(), ad); } }; StateMethodsImpl.prototype.mergeUntracked = function (sourceValue) { var r = this.mergeUntrackedV4(sourceValue); if (r) { return [r.path]; } return []; }; StateMethodsImpl.prototype.mergeUntrackedV4 = function (sourceValue) { var currentValue = this.getUntracked(); if (typeof sourceValue === 'function') { sourceValue = sourceValue(currentValue); } this.store.premerge(this.self(), sourceValue); if (Array.isArray(currentValue)) { if (Array.isArray(sourceValue)) { var ad_1 = { path: this.path, actions: {} }; sourceValue.forEach(function (e, i) { ad_1.actions[currentValue.push(e) - 1] = "I"; }); if (Object.keys(ad_1.actions).length > 0) { this.setUntrackedV4(currentValue); return ad_1; } return null; } else { var ad_2 = { path: this.path, actions: {} }; var deletedIndexes_1 = []; Object.keys(sourceValue) .map(function (i) { return Number(i); }) .sort(function (a, b) { return a - b; }) .forEach(function (i) { var index = Number(i); var newPropValue = sourceValue[index]; if (newPropValue === none) { ad_2.actions[index] = "D"; deletedIndexes_1.push(index); } else { if (index in currentValue) { ad_2.actions[index] = "U"; } else { ad_2.actions[index] = "I"; } currentValue[index] = newPropValue; } }); // indexes are ascending sorted as per above // so, delete one by one from the end // this way index positions do not change deletedIndexes_1.reverse().forEach(function (p) { currentValue.splice(p, 1); }); if (Object.keys(ad_2.actions).length > 0) { this.setUntrackedV4(currentValue); return ad_2; } return null; } } else if (Object(currentValue) === currentValue) { var ad_3 = { path: this.path, actions: {} }; Object.keys(sourceValue).forEach(function (key) { var newPropValue = sourceValue[key]; if (newPropValue === none) { ad_3.actions[key] = "D"; delete currentValue[key]; } else { if (key in currentValue) { ad_3.actions[key] = "U"; } else { ad_3.actions[key] = "I"; } currentValue[key] = newPropValue; } }); if (Object.keys(ad_3.actions).length > 0) { this.setUntrackedV4(currentValue); return ad_3; } return null; } else if (typeof currentValue === 'string') { return this.setUntrackedV4((currentValue + String(sourceValue))); } else { return this.setUntrackedV4(sourceValue); } }; StateMethodsImpl.prototype.merge = function (sourceValue) { var r = this.mergeUntrackedV4(sourceValue); if (r) { this.store.update(this.self(), r); } }; StateMethodsImpl.prototype.nested = function (key) { return this.child(key).self(); }; StateMethodsImpl.prototype.rerender = function (paths) { for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) { var path = paths_1[_i]; this.store.update(this.self(), { path: path }); } }; StateMethodsImpl.prototype.activate = function (extensionFactory) { this.store.activate(extensionFactory); }; StateMethodsImpl.prototype.deactivate = function () { this.store.deactivate(); }; StateMethodsImpl.prototype.subscribe = function (l) { if (this.subscribers === undefined) { this.subscribers = new Set(); } this.subscribers.add(l); }; StateMethodsImpl.prototype.unsubscribe = function (l) { if (this.subscribers) { this.subscribers.delete(l); } }; Object.defineProperty(StateMethodsImpl.prototype, "isMounted", { get: function () { return !this.onSetUsed[IsUnmounted]; }, enumerable: false, configurable: true }); StateMethodsImpl.prototype.onMount = function () { delete this.onSetUsed[IsUnmounted]; }; StateMethodsImpl.prototype.onUnmount = function () { this.onSetUsed[IsUnmounted] = true; }; StateMethodsImpl.prototype.onSet = function (ad, actions) { var _this = this; var update = function () { var _a; var isAffected = false; if (_this.valueUsedNoProxy // TODO this condition becomes redundant when Downgraded plugins is deleted && _this.valueUsed !== UnusedValue) { actions.add(_this.onSetUsed); delete _this.selfUsed; isAffected = true; } var path = ad.path; var nextChildKey = path[_this.path.length]; if (nextChildKey === undefined) { // There is no next child to dive into // So it is this one which was updated if (_this.valueUsed !== UnusedValue) { actions.add(_this.onSetUsed); delete _this.selfUsed; delete _this.childrenUsed; if (ad.actions && _this.childrenCreated) { // TODO add automated unit tests for this part if (Array.isArray(_this.valueSource) && Object.values(ad.actions).includes("D")) { // this is an array and some elements were removed // so invalidate cache for all children after the first deleted var firstDeletedIndex = Object.keys(ad.actions) .map(function (i) { return Number(i); }) .sort(function (a, b) { return a - b; }) .find(function (i) { var _a; return ((_a = ad.actions) === null || _a === void 0 ? void 0 : _a[i]) === "D"; }); for (var childKey in _this.childrenCreated) { if (Number(childKey) >= firstDeletedIndex || childKey in ad.actions) { delete _this.childrenCreated[childKey]; } } } else { for (var childKey in ad.actions) { delete _this.childrenCreated[childKey]; } } } else { delete _this.childrenCreated; } return true; } } else { var nextChild = (_a = _this.childrenUsed) === null || _a === void 0 ? void 0 : _a[nextChildKey]; if (nextChild && nextChild.onSet(ad, actions)) { delete _this.selfUsed; return true; } } return isAffected; }; var updated = update(); if (!updated && this.subscribers !== undefined) { this.subscribers.forEach(function (s) { if (s.onSet(ad, actions)) { delete _this.selfUsed; } }); } return updated; }; Object.defineProperty(StateMethodsImpl.prototype, "keys", { get: function () { var value = this.get(); if (Array.isArray(value)) { return Object.keys(value).map(function (i) { return Number(i); }).filter(function (i) { return Number.isInteger(i); }); } if (Object(value) === value) { return Object.keys(value); } return undefined; }, enumerable: false, configurable: true }); StateMethodsImpl.prototype.child = function (key) { this.childrenUsed = this.childrenUsed || {}; var cachedChild = this.childrenUsed.hasOwnProperty(key) && this.childrenUsed[key]; if (cachedChild) { return cachedChild; } var valueSource = this.valueSource[key]; if (typeof valueSource === 'function') { // hitting a method of a custom type, should be no-op throw new StateInvalidUsageError(this.path, ErrorId.GetProperty_Function); } this.childrenCreated = this.childrenCreated || {}; var child = this.childrenCreated[key]; var r; if (child) { child.reconstruct(this.path.concat(key), valueSource, this.valueEdition, false); r = child; } else { r = new StateMethodsImpl(this.store, this.path.concat(key), valueSource, this.valueEdition, this.onSetUsed); this.childrenCreated[key] = r; } if (this.valueUsedNoProxy) { // TODO this is redundant when Downgraded plugin is deleted r.valueUsedNoProxy = true; } this.childrenUsed[key] = r; return r; }; StateMethodsImpl.prototype.valueArrayImpl = function (currentValue) { var _this = this; return proxyWrap(this.path, currentValue, function () { return currentValue; }, function (target, key) { if (key === 'length') { return target.length; } if (key in Array.prototype) { return Array.prototype[key]; } if (key === SelfMethodsID) { return _this; } if (typeof key === 'symbol') { // allow clients to associate hidden cache with state values return target[key]; } var index = Number(key); if (!Number.isInteger(index)) { return undefined; } return _this.child(index).get(); }, function (target, key, value) { if (typeof key === 'symbol') { // allow clients to associate hidden cache with state values target[key] = value; return true; } throw new StateInvalidUsageError(_this.path, ErrorId.SetProperty_Value); }, true); }; StateMethodsImpl.prototype.valueObjectImpl = function (currentValue) { var _this = this; return proxyWrap(this.path, currentValue, function () { return currentValue; }, function (target, key) { if (key in Object.prototype) { return Object.prototype[key]; } if (key === SelfMethodsID) { return _this; } if (typeof key === 'symbol') { // allow clients to associate hidden cache with state values return target[key]; } return _this.child(key).get(); }, function (target, key, value) { if (typeof key === 'symbol') { // allow clients to associate hidden cache with state values target[key] = value; return true; } throw new StateInvalidUsageError(_this.path, ErrorId.SetProperty_Value); }, true); }; StateMethodsImpl.prototype.self = function () { var _this = this; if (this.selfUsed) { return this.selfUsed; } var getter = function (_, key) { if (key === self) { return _this; } if (typeof key === 'symbol') { return undefined; } if (key === 'toJSON') { throw new StateInvalidUsageError(_this.path, ErrorId.ToJson_State); } var nestedGetter = function (prop) { var currentValue = _this.get({ __internalAllowPromised: prop === '$$typeof' || prop === 'constructor' }); if (prop in Object.prototype) { // Mark it used entirely, so changes to the value // invalidate and rerender results for Object.prototype.toString(), // for example. // We check for Object prototype functions // even for primitive values, because primitive values still // can have object methods. return Object.prototype[prop]; } if ( // if currentValue is primitive type (Object(currentValue) !== currentValue) && // if promised, it will be none currentValue !== none) { // This was an error case, but various tools like webpack bundler // and react dev tools attempt to get props out of non-null object, // so this was changed to return just undefined for any property request // as there is no way to fix 3rd party tools. // Logging a warning to console is also not an option // as it pollutes console for legitimate apps on app start app. // Ref: https://github.com/avkonst/hookstate/issues/125 return undefined; } if (Array.isArray(currentValue)) { if (prop === 'length') { return currentValue.length; } if (prop in Array.prototype) { return Array.prototype[prop]; } var index = Number(prop); if (!Number.isInteger(index)) { return undefined; } return _this.nested(index); } return _this.nested(prop.toString()); }; switch (key) { case 'path': return _this.path; case 'keys': return _this.keys; case 'value': return _this.value; case 'ornull': return _this.ornull; case 'promised': return _this.promised; case 'promise': return _this.promise; case 'error': return _this.error; case 'get': return function (opts) { return _this.get(opts); }; case 'set': return function (p) { return _this.set(p); }; case 'merge': return function (p) { return _this.merge(p); }; case 'nested': return function (p) { return nestedGetter(p); }; default: // check if extension method var ext = _this.store.extension; if (ext && key in ext) { return ext[key](_this.self()); } // otherwise nested child return nestedGetter(key); } }; this.selfUsed = proxyWrap(this.path, this.valueSource, function (opts) { return _this.get({ __internalAllowPromised: true, stealth: opts === null || opts === void 0 ? void 0 : opts.stealth }); }, getter, function (_, key, value) { throw new StateInvalidUsageError(_this.path, ErrorId.SetProperty_State); }, false); return this.selfUsed; }; Object.defineProperty(StateMethodsImpl.prototype, "promised", { get: function () { this.get({ __internalAllowPromised: tr