@mkrause/lifecycle-loader
Advanced tools
+12
-12
@@ -6,2 +6,3 @@ "use strict"; | ||
| }); | ||
| exports.isLoadable = exports.default = exports.Loader = exports.Loadable = void 0; | ||
| Object.defineProperty(exports, "isProxyable", { | ||
@@ -13,16 +14,13 @@ enumerable: true, | ||
| }); | ||
| exports.default = exports.Loader = exports.isLoadable = exports.isStatus = exports.status = exports.Loadable = void 0; | ||
| exports.status = exports.isStatus = void 0; | ||
| var _proxyExtend = require("proxy-extend"); | ||
| var LoadableDefs = _interopRequireWildcard(require("./interfaces/Loadable.js")); | ||
| var LoaderDefs = _interopRequireWildcard(require("./interfaces/Loader.js")); | ||
| function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
| function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
| // Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy) | ||
| const Loadable = Object.assign((item, status = {}) => LoadableDefs.LoadableProxy(item, status), { | ||
| const Loadable = Object.assign(function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| return LoadableDefs.LoadableProxy(item, status); | ||
| }, { | ||
| // Keys | ||
@@ -35,2 +33,3 @@ item: LoadableDefs.itemKey, | ||
| // Prevent widening to `symbol` | ||
| isStatus: LoadableDefs.isStatus, | ||
@@ -52,14 +51,14 @@ isLoadable: LoadableDefs.isLoadable, | ||
| asFailed: LoadableDefs.asFailed | ||
| }); // Shorthand exports | ||
| }); | ||
| // Shorthand exports | ||
| exports.Loadable = Loadable; | ||
| const status = LoadableDefs.statusKey; // Prevent widening to `symbol` | ||
| exports.status = status; | ||
| const isStatus = LoadableDefs.isStatus; | ||
| exports.isStatus = isStatus; | ||
| const isLoadable = LoadableDefs.isLoadable; // Utilities | ||
| const isLoadable = LoadableDefs.isLoadable; | ||
| // Utilities | ||
| exports.isLoadable = isLoadable; | ||
| /* | ||
@@ -77,2 +76,3 @@ export { | ||
| */ | ||
| const Loader = { | ||
@@ -79,0 +79,0 @@ resource: LoaderDefs.resourceKey, |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts"],"names":["Loadable","Object","assign","item","status","LoadableDefs","LoadableProxy","itemKey","statusKey","construct","constructKey","isStatus","isLoadable","Record","LoadableRecord","Proxy","getItem","resource","getStatus","update","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","Loader","LoaderDefs","resourceKey","fromPromise"],"mappings":";;;;;;;;;;;;;AAEA;;AAEA;;AACA;;;;;;AAQA;AACO,MAAMA,QAAQ,GAAGC,MAAM,CAACC,MAAP,CACpB,CAAsBC,IAAtB,EAA6CC,MAAqC,GAAG,EAArF,KACIC,YAAY,CAACC,aAAb,CAA2BH,IAA3B,EAAiCC,MAAjC,CAFgB,EAGpB;AACI;AACAD,EAAAA,IAAI,EAAEE,YAAY,CAACE,OAFvB;AAEgE;AAC5DH,EAAAA,MAAM,EAAEC,YAAY,CAACG,SAHzB;AAGsE;AAClEC,EAAAA,SAAS,EAAEJ,YAAY,CAACK,YAJ5B;AAI+E;AAE3EC,EAAAA,QAAQ,EAAEN,YAAY,CAACM,QAN3B;AAOIC,EAAAA,UAAU,EAAEP,YAAY,CAACO,UAP7B;AASI;AACAC,EAAAA,MAAM,EAAER,YAAY,CAACS,cAVzB;AAWIC,EAAAA,KAAK,EAAEV,YAAY,CAACC,aAXxB;AAaI;AACAU,EAAAA,OAAO,EAAMC,QAAJ,IAA+BA,QAAQ,CAACZ,YAAY,CAACE,OAAd,CAdpD;AAeIW,EAAAA,SAAS,EAAMD,QAAJ,IAA+BA,QAAQ,CAACZ,YAAY,CAACG,SAAd,CAftD;AAiBI;AACAW,EAAAA,MAAM,EAAEd,YAAY,CAACc,MAlBzB;AAmBIC,EAAAA,UAAU,EAAEf,YAAY,CAACe,UAnB7B;AAoBIC,EAAAA,YAAY,EAAEhB,YAAY,CAACgB,YApB/B;AAqBIC,EAAAA,SAAS,EAAEjB,YAAY,CAACiB,SArB5B;AAsBIC,EAAAA,SAAS,EAAElB,YAAY,CAACkB,SAtB5B;AAuBIC,EAAAA,OAAO,EAAEnB,YAAY,CAACmB,OAvB1B;AAwBIC,EAAAA,QAAQ,EAAEpB,YAAY,CAACoB;AAxB3B,CAHoB,CAAjB,C,CA+BP;;;AACO,MAAMrB,MAAqC,GAAGC,YAAY,CAACG,SAA3D,C,CAAsE;;;AACtE,MAAMG,QAAQ,GAAGN,YAAY,CAACM,QAA9B;;AACA,MAAMC,UAAU,GAAGP,YAAY,CAACO,UAAhC,C,CAEP;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEO,MAAMc,MAAM,GAAG;AAClBT,EAAAA,QAAQ,EAAEU,UAAU,CAACC,WADH;AAElBC,EAAAA,WAAW,EAAEF,UAAU,CAACE;AAFN,CAAf;;eAOQ7B,Q","sourcesContent":["\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\nimport { isProxyable } from 'proxy-extend';\n\nimport * as LoadableDefs from './interfaces/Loadable.js';\nimport * as LoaderDefs from './interfaces/Loader.js';\n\n\nexport type Status = LoadableDefs.Status;\nexport type Loadable<T> = LoadableDefs.Loadable<T>;\nexport type { Proxyable };\nexport type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>;\n\n// Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy)\nexport const Loadable = Object.assign(\n <T extends Proxyable>(item ?: undefined | T, status : Partial<LoadableDefs.Status> = {}) =>\n LoadableDefs.LoadableProxy(item, status),\n {\n // Keys\n item: LoadableDefs.itemKey as typeof LoadableDefs.itemKey, // Prevent widening to `symbol`\n status: LoadableDefs.statusKey as typeof LoadableDefs.statusKey, // Prevent widening to `symbol`\n construct: LoadableDefs.constructKey as typeof LoadableDefs.constructKey, // Prevent widening to `symbol`\n \n isStatus: LoadableDefs.isStatus,\n isLoadable: LoadableDefs.isLoadable,\n \n // Constructors\n Record: LoadableDefs.LoadableRecord,\n Proxy: LoadableDefs.LoadableProxy,\n \n // Accessor functions\n getItem: <T>(resource : Loadable<T>) => resource[LoadableDefs.itemKey],\n getStatus: <T>(resource : Loadable<T>) => resource[LoadableDefs.statusKey],\n \n // Updater functions\n update: LoadableDefs.update,\n updateItem: LoadableDefs.updateItem,\n updateStatus: LoadableDefs.updateStatus,\n asPending: LoadableDefs.asPending,\n asLoading: LoadableDefs.asLoading,\n asReady: LoadableDefs.asReady,\n asFailed: LoadableDefs.asFailed,\n },\n);\n\n// Shorthand exports\nexport const status: typeof LoadableDefs.statusKey = LoadableDefs.statusKey; // Prevent widening to `symbol`\nexport const isStatus = LoadableDefs.isStatus;\nexport const isLoadable = LoadableDefs.isLoadable;\n\n// Utilities\nexport { isProxyable };\n\n\n/*\nexport {\n LoadError,\n LoadablePromise,\n};\n\nexport const loader = <T>(\n item : Loadable<T>,\n executor : (resolve : (item : Loadable<T>) => void, reject : (item : Loadable<T>) => void) => void,\n ) =>\n new LoadablePromise(executor, item);\n*/\n\nexport const Loader = {\n resource: LoaderDefs.resourceKey,\n fromPromise: LoaderDefs.fromPromise,\n};\n\nexport type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>;\n\nexport default Loadable;\n"],"file":"index.js"} | ||
| {"version":3,"file":"index.js","names":["_proxyExtend","require","LoadableDefs","_interopRequireWildcard","LoaderDefs","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","Loadable","assign","item","status","arguments","length","undefined","LoadableProxy","itemKey","statusKey","construct","constructKey","isStatus","isLoadable","Record","LoadableRecord","Proxy","getItem","resource","getStatus","update","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","exports","Loader","resourceKey","fromPromise","_default"],"sources":["../src/index.ts"],"sourcesContent":["\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\nimport { isProxyable } from 'proxy-extend';\n\nimport * as LoadableDefs from './interfaces/Loadable.js';\nimport * as LoaderDefs from './interfaces/Loader.js';\n\n\nexport type Status = LoadableDefs.Status;\nexport type Loadable<T> = LoadableDefs.Loadable<T>;\nexport type { Proxyable };\nexport type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>;\n\n// Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy)\nexport const Loadable = Object.assign(\n <T extends Proxyable>(item ?: undefined | T, status : Partial<LoadableDefs.Status> = {}) =>\n LoadableDefs.LoadableProxy(item, status),\n {\n // Keys\n item: LoadableDefs.itemKey as typeof LoadableDefs.itemKey, // Prevent widening to `symbol`\n status: LoadableDefs.statusKey as typeof LoadableDefs.statusKey, // Prevent widening to `symbol`\n construct: LoadableDefs.constructKey as typeof LoadableDefs.constructKey, // Prevent widening to `symbol`\n \n isStatus: LoadableDefs.isStatus,\n isLoadable: LoadableDefs.isLoadable,\n \n // Constructors\n Record: LoadableDefs.LoadableRecord,\n Proxy: LoadableDefs.LoadableProxy,\n \n // Accessor functions\n getItem: <T>(resource : Loadable<T>) => resource[LoadableDefs.itemKey],\n getStatus: <T>(resource : Loadable<T>) => resource[LoadableDefs.statusKey],\n \n // Updater functions\n update: LoadableDefs.update,\n updateItem: LoadableDefs.updateItem,\n updateStatus: LoadableDefs.updateStatus,\n asPending: LoadableDefs.asPending,\n asLoading: LoadableDefs.asLoading,\n asReady: LoadableDefs.asReady,\n asFailed: LoadableDefs.asFailed,\n },\n);\n\n// Shorthand exports\nexport const status: typeof LoadableDefs.statusKey = LoadableDefs.statusKey; // Prevent widening to `symbol`\nexport const isStatus = LoadableDefs.isStatus;\nexport const isLoadable = LoadableDefs.isLoadable;\n\n// Utilities\nexport { isProxyable };\n\n\n/*\nexport {\n LoadError,\n LoadablePromise,\n};\n\nexport const loader = <T>(\n item : Loadable<T>,\n executor : (resolve : (item : Loadable<T>) => void, reject : (item : Loadable<T>) => void) => void,\n ) =>\n new LoadablePromise(executor, item);\n*/\n\nexport const Loader = {\n resource: LoaderDefs.resourceKey,\n fromPromise: LoaderDefs.fromPromise,\n};\n\nexport type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>;\n\nexport default Loadable;\n"],"mappings":"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"} |
@@ -6,14 +6,32 @@ "use strict"; | ||
| }); | ||
| exports.asFailed = exports.asReady = exports.asLoading = exports.asPending = exports.updateStatus = exports.updateItem = exports.update = exports.LoadableProxy = exports.LoadableRecord = exports.isLoadable = exports.isStatus = exports.constructKey = exports.statusKey = exports.itemKey = void 0; | ||
| exports.updateStatus = exports.updateItem = exports.update = exports.statusKey = exports.itemKey = exports.isStatus = exports.isLoadable = exports.constructKey = exports.asReady = exports.asPending = exports.asLoading = exports.asFailed = exports.LoadableRecord = exports.LoadableProxy = void 0; | ||
| var _messageTag = _interopRequireDefault(require("message-tag")); | ||
| var _proxyExtend = _interopRequireWildcard(require("proxy-extend")); | ||
| function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
| function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
| // An *item* is the data part of a resource (can be anything). | ||
| /* | ||
| A *status* is an object that describes the current loading state of some resource. | ||
| Status flags: | ||
| - ready: indicates whether this resource can be used or not (whether the data can be read safely) | ||
| - loading: indicates whether we are currently in the process of loading this resource | ||
| - error: indicates that the last load attempt resulted in an error | ||
| Note that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready). | ||
| This is so that we can, for example, start loading new data while keeping information such as an error | ||
| state, for UI purposes. All the possible combinations listed below. | ||
| - !ready + !loading + !error "pending", nothing done yet, not even attempted to load | ||
| - !ready + loading + !error "loading", for the first time, no older data available | ||
| - ready + !loading + !error "ready" (or "idle"), can use the data as needed | ||
| - ready + loading + !error "ready" (or "reloading"), ready but also loading an updated version | ||
| - !ready + !loading + error "failed", and not yet any attempt to retry (no older data available) | ||
| - !ready + loading + error "failed", but we're currently retrying (no older data available) | ||
| - ready + !loading + error "failed", and not yet any attempt to retry (there is older data available) | ||
| - ready + loading + error "failed", but we're currently retrying (there is older data available) | ||
| */ | ||
| const defaultStatus = { | ||
@@ -23,4 +41,5 @@ ready: false, | ||
| error: null | ||
| }; // Property key symbols | ||
| }; | ||
| // Property key symbols | ||
| const itemKey = Symbol.for('lifecycle.loadable.item'); | ||
@@ -30,6 +49,6 @@ exports.itemKey = itemKey; | ||
| exports.statusKey = statusKey; | ||
| const constructKey = Symbol.for('lifecycle.loadable.construct'); // A *resource* (or "Loadable") is an object that has both an item and a status. | ||
| const constructKey = Symbol.for('lifecycle.loadable.construct'); | ||
| // A *resource* (or "Loadable") is an object that has both an item and a status. | ||
| exports.constructKey = constructKey; | ||
| const isStatus = value => { | ||
@@ -39,8 +58,5 @@ if (typeof value !== 'object' || value === null) { | ||
| } | ||
| return 'ready' in value && typeof value.ready === 'boolean' && 'loading' in value && typeof value.loading === 'boolean' && 'error' in value && (value.error === null || value.error instanceof Error); | ||
| }; | ||
| exports.isStatus = isStatus; | ||
| const isLoadable = value => { | ||
@@ -50,5 +66,5 @@ if (!(typeof value === 'object' && value !== null)) { | ||
| } | ||
| return itemKey in value && statusKey in value && typeof value[statusKey] === 'object' && constructKey in value && typeof value[constructKey] === 'function'; | ||
| }; | ||
| /* | ||
@@ -58,11 +74,11 @@ LoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also | ||
| */ | ||
| exports.isLoadable = isLoadable; | ||
| const LoadableRecord = (item, status = {}) => { | ||
| const LoadableRecord = function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| // If the status is ready, then `item` cannot be `undefined` | ||
| if (status.ready === true && typeof item === 'undefined') { | ||
| throw new TypeError('Expected an item, but given `undefined`'); | ||
| } // If the status is not ready, then `item` must be `undefined` | ||
| } | ||
| // If the status is not ready, then `item` must be `undefined` | ||
| //if (status.ready === false && typeof item !== 'undefined') { | ||
@@ -72,4 +88,4 @@ // throw new TypeError($msg`Expected \`undefined\`, but given ${item}`); | ||
| const statusWithDefaults = { ...defaultStatus, | ||
| const statusWithDefaults = { | ||
| ...defaultStatus, | ||
| ready: typeof item !== 'undefined', | ||
@@ -88,2 +104,3 @@ ...status | ||
| }; | ||
| /* | ||
@@ -93,11 +110,11 @@ LoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same | ||
| */ | ||
| exports.LoadableRecord = LoadableRecord; | ||
| const LoadableProxy = (item, status = {}) => { | ||
| const LoadableProxy = function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| // If the status is ready, then `item` cannot be `undefined` | ||
| if (status.ready === true && typeof item === 'undefined') { | ||
| throw new TypeError('Expected an item, but given `undefined`'); | ||
| } // If the status is not ready, then `item` must be `undefined` | ||
| } | ||
| // If the status is not ready, then `item` must be `undefined` | ||
| //if (status.ready === false && typeof item !== 'undefined') { | ||
@@ -107,12 +124,17 @@ // throw new TypeError($msg`Expected \`undefined\`, but given ${item}`); | ||
| const statusWithDefaults = { ...defaultStatus, | ||
| const statusWithDefaults = { | ||
| ...defaultStatus, | ||
| ready: typeof item !== 'undefined', | ||
| ...status | ||
| }; // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over) | ||
| }; | ||
| // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over) | ||
| if (_proxyExtend.default.is(item)) { | ||
| throw new TypeError((0, _messageTag.default)`Cannot create a LoadableProxy from an item which is already a LoadableProxy`); // TODO: maybe just unwrap the given proxy and override the status? | ||
| throw new TypeError((0, _messageTag.default)`Cannot create a LoadableProxy from an item which is already a LoadableProxy`); | ||
| // TODO: maybe just unwrap the given proxy and override the status? | ||
| //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item); | ||
| } // If the item itself is a loadable resource, return it as is? | ||
| } | ||
| // If the item itself is a loadable resource, return it as is? | ||
| // (Alternatively, unwrap it and convert to a LoadableProxy instead) | ||
@@ -123,9 +145,6 @@ //if (isLoadable(item)) { | ||
| const itemProxyable = typeof item === 'undefined' ? null : item; | ||
| if (!(0, _proxyExtend.isProxyable)(itemProxyable)) { | ||
| throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`); | ||
| } | ||
| return (0, _proxyExtend.default)(itemProxyable, { | ||
@@ -136,23 +155,24 @@ [itemKey]: item, | ||
| }); | ||
| }; // Updater methods | ||
| }; | ||
| // Updater methods | ||
| exports.LoadableProxy = LoadableProxy; | ||
| const update = (resource, item, status = {}) => resource[constructKey](item, { ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| const update = function (resource, item) { | ||
| let status = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
| return resource[constructKey](item, { | ||
| ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| }; | ||
| exports.update = update; | ||
| const updateItem = (resource, item) => resource[constructKey](item, resource[statusKey]); | ||
| exports.updateItem = updateItem; | ||
| const updateStatus = (resource, status = {}) => resource[constructKey](resource[itemKey], { ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| const updateStatus = function (resource) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| return resource[constructKey](resource[itemKey], { | ||
| ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| }; | ||
| exports.updateStatus = updateStatus; | ||
| const asPending = resource => update(resource, undefined, { | ||
@@ -163,13 +183,9 @@ ready: false, | ||
| }); | ||
| exports.asPending = asPending; | ||
| const asLoading = resource => updateStatus(resource, { | ||
| loading: true | ||
| }); // TODO: should we also clear any error here? | ||
| exports.asLoading = asLoading; | ||
| const asReady = (resource, item) => update(resource, typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing | ||
| const asReady = (resource, item) => update(resource, typeof item === 'undefined' ? resource[itemKey] : item, | ||
| // `item` is optional, if not present use existing | ||
| { | ||
@@ -180,5 +196,3 @@ ready: true, | ||
| }); | ||
| exports.asReady = asReady; | ||
| const asFailed = (resource, reason) => updateStatus(resource, { | ||
@@ -188,4 +202,3 @@ loading: false, | ||
| }); | ||
| exports.asFailed = asFailed; | ||
| //# sourceMappingURL=Loadable.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/interfaces/Loadable.ts"],"names":["defaultStatus","ready","loading","error","itemKey","Symbol","for","statusKey","constructKey","isStatus","value","Error","isLoadable","LoadableRecord","item","status","TypeError","statusWithDefaults","loadable","LoadableProxy","extend","is","itemProxyable","update","resource","updateItem","updateStatus","asPending","undefined","asLoading","asReady","asFailed","reason"],"mappings":"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","sourcesContent":["\nimport $msg from 'message-tag';\nimport extend, { isProxyable } from 'proxy-extend';\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\n\n\n// An *item* is the data part of a resource (can be anything).\nexport type Item = unknown;\n\n/*\nA *status* is an object that describes the current loading state of some resource.\n\nStatus flags:\n - ready: indicates whether this resource can be used or not (whether the data can be read safely)\n - loading: indicates whether we are currently in the process of loading this resource\n - error: indicates that the last load attempt resulted in an error\n\nNote that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready).\nThis is so that we can, for example, start loading new data while keeping information such as an error\nstate, for UI purposes. All the possible combinations listed below.\n\n- !ready + !loading + !error \"pending\", nothing done yet, not even attempted to load\n- !ready + loading + !error \"loading\", for the first time, no older data available\n- ready + !loading + !error \"ready\" (or \"idle\"), can use the data as needed\n- ready + loading + !error \"ready\" (or \"reloading\"), ready but also loading an updated version\n- !ready + !loading + error \"failed\", and not yet any attempt to retry (no older data available)\n- !ready + loading + error \"failed\", but we're currently retrying (no older data available)\n- ready + !loading + error \"failed\", and not yet any attempt to retry (there is older data available)\n- ready + loading + error \"failed\", but we're currently retrying (there is older data available)\n*/\nexport type Status = {\n ready : boolean,\n loading : boolean,\n error : null | Error,\n};\nconst defaultStatus : Status = { ready: false, loading: false, error: null };\n\n\n// Property key symbols\nexport const itemKey: unique symbol = Symbol.for('lifecycle.loadable.item');\nexport const statusKey: unique symbol = Symbol.for('lifecycle.loadable.status');\nexport const constructKey: unique symbol = Symbol.for('lifecycle.loadable.construct');\n\n// A *resource* (or \"Loadable\") is an object that has both an item and a status.\nexport type Loadable<T> = {\n [itemKey] : undefined | T, // May be `undefined` when status is not ready (if ready *must not* be `undefined`)\n [statusKey] : Status,\n \n // Construct a new resource from this one, using the given item and status\n [constructKey] : (item : undefined | T, status : Status) => Loadable<T>,\n};\n\nexport const isStatus = (value : unknown) : value is Status => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n \n return 'ready' in value && typeof (value as Status).ready === 'boolean'\n && 'loading' in value && typeof (value as Status).loading === 'boolean'\n && 'error' in value && ((value as Status).error === null || (value as Status).error instanceof Error);\n};\n\nexport const isLoadable = (value : unknown) : value is Loadable<unknown> => {\n if (!(typeof value === 'object' && value !== null)) {\n return false;\n }\n \n return itemKey in value\n && statusKey in value && typeof (value as { [statusKey] : unknown })[statusKey] === 'object'\n && constructKey in value && typeof (value as { [constructKey] : unknown })[constructKey] === 'function';\n};\n\n\n/*\nLoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also\nexposes these as regular (non-symbol) properties (so you can access them simply as `res.item` and `res.status`).\n*/\nexport type LoadableRecordT<T> = Loadable<T> & { item : undefined | T, status : Status };\nexport const LoadableRecord = <T>(item ?: undefined | T, status : Partial<Status> = {}) : LoadableRecordT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n const loadable : LoadableRecordT<T> = {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableRecord,\n \n // Also expose as regular (non-symbol) keys\n item,\n status: statusWithDefaults,\n };\n \n return loadable;\n};\n\n\n/*\nLoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same\nas the item itself (status is \"hidden\" using a symbol key).\n*/\nexport type LoadableProxyT<T extends Proxyable> = Loadable<T>\n & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>);\nexport const LoadableProxy = <T extends Proxyable>(\n item ?: undefined | T,\n status : Partial<Status> = {}\n ) : LoadableProxyT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over)\n if (extend.is(item)) {\n throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`);\n \n // TODO: maybe just unwrap the given proxy and override the status?\n //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item);\n }\n \n // If the item itself is a loadable resource, return it as is?\n // (Alternatively, unwrap it and convert to a LoadableProxy instead)\n //if (isLoadable(item)) {\n // return item;\n //}\n \n const itemProxyable = typeof item === 'undefined' ? null : item;\n \n if (!isProxyable(itemProxyable)) {\n throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`);\n }\n \n return extend(itemProxyable, {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableProxy,\n }) as unknown as LoadableProxyT<T>;\n };\n\n\n// Updater methods\n\nexport const update = <T>(resource : Loadable<T>, item : undefined | T, status : Partial<Status> = {}) =>\n resource[constructKey](item, { ...resource[statusKey], ...status });\nexport const updateItem = <T>(resource : Loadable<T>, item : undefined | T) =>\n resource[constructKey](item, resource[statusKey]);\nexport const updateStatus = <T>(resource : Loadable<T>, status : Partial<Status> = {}) =>\n resource[constructKey](resource[itemKey], { ...resource[statusKey], ...status });\n\nexport const asPending = <T>(resource : Loadable<T>) =>\n update(resource, undefined, { ready: false, loading: false, error: null })\nexport const asLoading = <T>(resource : Loadable<T>) =>\n updateStatus(resource, { loading: true }); // TODO: should we also clear any error here?\nexport const asReady = <T>(resource : Loadable<T>, item ?: T) => update(resource,\n typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing\n { ready: true, loading: false, error: null }\n);\nexport const asFailed = <T>(resource : Loadable<T>, reason : Error) =>\n updateStatus(resource, { loading: false, error: reason });\n"],"file":"Loadable.js"} | ||
| {"version":3,"file":"Loadable.js","names":["_messageTag","_interopRequireDefault","require","_proxyExtend","_interopRequireWildcard","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","obj","__esModule","default","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","defaultStatus","ready","loading","error","itemKey","Symbol","for","exports","statusKey","constructKey","isStatus","value","Error","isLoadable","LoadableRecord","item","status","arguments","length","undefined","TypeError","statusWithDefaults","loadable","LoadableProxy","extend","is","$msg","itemProxyable","isProxyable","update","resource","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","reason"],"sources":["../../src/interfaces/Loadable.ts"],"sourcesContent":["\nimport $msg from 'message-tag';\nimport extend, { isProxyable } from 'proxy-extend';\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\n\n\n// An *item* is the data part of a resource (can be anything).\nexport type Item = unknown;\n\n/*\nA *status* is an object that describes the current loading state of some resource.\n\nStatus flags:\n - ready: indicates whether this resource can be used or not (whether the data can be read safely)\n - loading: indicates whether we are currently in the process of loading this resource\n - error: indicates that the last load attempt resulted in an error\n\nNote that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready).\nThis is so that we can, for example, start loading new data while keeping information such as an error\nstate, for UI purposes. All the possible combinations listed below.\n\n- !ready + !loading + !error \"pending\", nothing done yet, not even attempted to load\n- !ready + loading + !error \"loading\", for the first time, no older data available\n- ready + !loading + !error \"ready\" (or \"idle\"), can use the data as needed\n- ready + loading + !error \"ready\" (or \"reloading\"), ready but also loading an updated version\n- !ready + !loading + error \"failed\", and not yet any attempt to retry (no older data available)\n- !ready + loading + error \"failed\", but we're currently retrying (no older data available)\n- ready + !loading + error \"failed\", and not yet any attempt to retry (there is older data available)\n- ready + loading + error \"failed\", but we're currently retrying (there is older data available)\n*/\nexport type Status = {\n ready : boolean,\n loading : boolean,\n error : null | Error,\n};\nconst defaultStatus : Status = { ready: false, loading: false, error: null };\n\n\n// Property key symbols\nexport const itemKey: unique symbol = Symbol.for('lifecycle.loadable.item');\nexport const statusKey: unique symbol = Symbol.for('lifecycle.loadable.status');\nexport const constructKey: unique symbol = Symbol.for('lifecycle.loadable.construct');\n\n// A *resource* (or \"Loadable\") is an object that has both an item and a status.\nexport type Loadable<T> = {\n [itemKey] : undefined | T, // May be `undefined` when status is not ready (if ready *must not* be `undefined`)\n [statusKey] : Status,\n \n // Construct a new resource from this one, using the given item and status\n [constructKey] : (item : undefined | T, status : Status) => Loadable<T>,\n};\n\nexport const isStatus = (value : unknown) : value is Status => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n \n return 'ready' in value && typeof (value as Status).ready === 'boolean'\n && 'loading' in value && typeof (value as Status).loading === 'boolean'\n && 'error' in value && ((value as Status).error === null || (value as Status).error instanceof Error);\n};\n\nexport const isLoadable = (value : unknown) : value is Loadable<unknown> => {\n if (!(typeof value === 'object' && value !== null)) {\n return false;\n }\n \n return itemKey in value\n && statusKey in value && typeof (value as { [statusKey] : unknown })[statusKey] === 'object'\n && constructKey in value && typeof (value as { [constructKey] : unknown })[constructKey] === 'function';\n};\n\n\n/*\nLoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also\nexposes these as regular (non-symbol) properties (so you can access them simply as `res.item` and `res.status`).\n*/\nexport type LoadableRecordT<T> = Loadable<T> & { item : undefined | T, status : Status };\nexport const LoadableRecord = <T>(item ?: undefined | T, status : Partial<Status> = {}) : LoadableRecordT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n const loadable : LoadableRecordT<T> = {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableRecord,\n \n // Also expose as regular (non-symbol) keys\n item,\n status: statusWithDefaults,\n };\n \n return loadable;\n};\n\n\n/*\nLoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same\nas the item itself (status is \"hidden\" using a symbol key).\n*/\nexport type LoadableProxyT<T extends Proxyable> = Loadable<T>\n & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>);\nexport const LoadableProxy = <T extends Proxyable>(\n item ?: undefined | T,\n status : Partial<Status> = {}\n ) : LoadableProxyT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over)\n if (extend.is(item)) {\n throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`);\n \n // TODO: maybe just unwrap the given proxy and override the status?\n //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item);\n }\n \n // If the item itself is a loadable resource, return it as is?\n // (Alternatively, unwrap it and convert to a LoadableProxy instead)\n //if (isLoadable(item)) {\n // return item;\n //}\n \n const itemProxyable = typeof item === 'undefined' ? null : item;\n \n if (!isProxyable(itemProxyable)) {\n throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`);\n }\n \n return extend(itemProxyable, {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableProxy,\n }) as unknown as LoadableProxyT<T>;\n };\n\n\n// Updater methods\n\nexport const update = <T>(resource : Loadable<T>, item : undefined | T, status : Partial<Status> = {}) =>\n resource[constructKey](item, { ...resource[statusKey], ...status });\nexport const updateItem = <T>(resource : Loadable<T>, item : undefined | T) =>\n resource[constructKey](item, resource[statusKey]);\nexport const updateStatus = <T>(resource : Loadable<T>, status : Partial<Status> = {}) =>\n resource[constructKey](resource[itemKey], { ...resource[statusKey], ...status });\n\nexport const asPending = <T>(resource : Loadable<T>) =>\n update(resource, undefined, { ready: false, loading: false, error: null })\nexport const asLoading = <T>(resource : Loadable<T>) =>\n updateStatus(resource, { loading: true }); // TODO: should we also clear any error here?\nexport const asReady = <T>(resource : Loadable<T>, item ?: T) => update(resource,\n typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing\n { ready: true, loading: false, error: null }\n);\nexport const asFailed = <T>(resource : Loadable<T>, reason : Error) =>\n updateStatus(resource, { loading: false, error: reason });\n"],"mappings":"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"} |
@@ -6,10 +6,6 @@ "use strict"; | ||
| }); | ||
| exports.fromPromise = exports.LoadError = exports.resourceKey = void 0; | ||
| exports.resourceKey = exports.fromPromise = exports.LoadError = void 0; | ||
| var _messageTag = _interopRequireDefault(require("message-tag")); | ||
| var _Loadable = require("./Loadable.js"); | ||
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
| function _extendableBuiltin(cls) { | ||
@@ -21,3 +17,2 @@ function ExtendableBuiltin() { | ||
| } | ||
| ExtendableBuiltin.prototype = Object.create(cls.prototype, { | ||
@@ -31,3 +26,2 @@ constructor: { | ||
| }); | ||
| if (Object.setPrototypeOf) { | ||
@@ -38,23 +32,24 @@ Object.setPrototypeOf(ExtendableBuiltin, cls); | ||
| } | ||
| return ExtendableBuiltin; | ||
| } | ||
| // A *loader* is a function that takes a resource (the current state), and returns a promise for | ||
| // a new (loaded) resource (so always async, by definition). | ||
| const resourceKey = Symbol.for('lifecycle.loadable.loader-resource'); // Version of `Error` that keeps a reference to the resource | ||
| // A *loader creator* is a function that returns a loader. | ||
| const resourceKey = Symbol.for('lifecycle.loadable.loader-resource'); | ||
| // Version of `Error` that keeps a reference to the resource | ||
| exports.resourceKey = resourceKey; | ||
| class LoadError extends _extendableBuiltin(Error) { | ||
| constructor(reason, resource) { | ||
| let message = reason; | ||
| if (reason instanceof Error) { | ||
| message = reason.message; | ||
| } | ||
| super((0, _messageTag.default)`Loading failed: ${message}`); | ||
| this[resourceKey] = resource; | ||
| } | ||
| } | ||
| } | ||
| /* | ||
@@ -143,9 +138,6 @@ // type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void; | ||
| */ | ||
| exports.LoadError = LoadError; | ||
| const fromPromise = (promise, resource) => { | ||
| // Use the given resource, or use a LoadableProxy by default if none given | ||
| const resourceLoading = resource !== null && resource !== void 0 ? resource : (0, _Loadable.LoadableProxy)(undefined, { | ||
| const resourceLoading = resource ?? (0, _Loadable.LoadableProxy)(undefined, { | ||
| loading: true | ||
@@ -157,3 +149,2 @@ }); | ||
| [resourceKey]: resourceLoading, | ||
| subscribe(subscriber) { | ||
@@ -163,8 +154,6 @@ subscriber(resourceLoading); | ||
| } | ||
| }); | ||
| return promiseWithResource; | ||
| }; | ||
| exports.fromPromise = fromPromise; | ||
| //# sourceMappingURL=Loader.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/interfaces/Loader.ts"],"names":["resourceKey","Symbol","for","LoadError","Error","constructor","reason","resource","message","fromPromise","promise","resourceLoading","undefined","loading","promiseWithResource","Object","assign","then","result","subscribe","subscriber"],"mappings":";;;;;;;AACA;;AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,MAAMA,WAAW,GAAGC,MAAM,CAACC,GAAP,CAAW,oCAAX,CAApB,C,CAGP;;;;AACO,MAAMC,SAAN,4BAA2BC,KAA3B,EAAiC;AAGpCC,EAAAA,WAAW,CAACC,MAAD,EAAmBC,QAAnB,EAA2C;AAClD,QAAIC,OAAO,GAAGF,MAAd;;AACA,QAAIA,MAAM,YAAYF,KAAtB,EAA6B;AACzBI,MAAAA,OAAO,GAAGF,MAAM,CAACE,OAAjB;AACH;;AAED,UAAM,wBAAK,mBAAkBA,OAAQ,EAArC;AACA,SAAKR,WAAL,IAAoBO,QAApB;AACH;;AAXmC;AAcxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AASO,MAAME,WAAW,GAAG,CACnBC,OADmB,EAEnBH,QAFmB,KAGO;AAC1B;AACA,QAAMI,eAA6B,GAAGJ,QAAH,aAAGA,QAAH,cAAGA,QAAH,GAAe,6BAAiBK,SAAjB,EAA4B;AAAEC,IAAAA,OAAO,EAAE;AAAX,GAA5B,CAAlD;AAEA,QAAMC,mBAA4C,GAAGC,MAAM,CAACC,MAAP,CACjDN,OAAO,CAACO,IAAR,CACKC,MAAD,IAAgB,uBAAQP,eAAR,EAAyBO,MAAzB,CADpB,EAEKZ,MAAD,IAAoB;AAChB,UAAM,IAAIH,SAAJ,CAAcG,MAAd,EAAsB,wBAASK,eAAT,EAA0BL,MAA1B,CAAtB,CAAN;AACH,GAJL,CADiD,EAOjD;AACI,KAACN,WAAD,GAAeW,eADnB;;AAEIQ,IAAAA,SAAS,CAACC,UAAD,EAAgD;AACrDA,MAAAA,UAAU,CAACT,eAAD,CAAV;AAEAD,MAAAA,OAAO,CAACO,IAAR,CACKC,MAAD,IAAgBE,UAAU,CAAC,uBAAQT,eAAR,EAAyBO,MAAzB,CAAD,CAD9B,EAEKZ,MAAD,IAAoBc,UAAU,CAAC,wBAAST,eAAT,EAA0BL,MAA1B,CAAD,CAFlC;AAIH;;AATL,GAPiD,CAArD;AAoBA,SAAOQ,mBAAP;AACH,CA5BE","sourcesContent":["\nimport $msg from 'message-tag';\nimport type { Proxyable } from 'proxy-extend';\n\nimport { Status, Loadable, itemKey, statusKey, LoadableProxy, asReady, asFailed } from './Loadable.js';\n\n\n// A *loader* is a function that takes a resource (the current state), and returns a promise for\n// a new (loaded) resource (so always async, by definition).\nexport type Loader<T> = (resource : Loadable<T>) => Promise<Loadable<T>>;\n\n// A *loader creator* is a function that returns a loader.\nexport type LoaderCreator<T> = (...args : Array<unknown>) => Loader<T>;\n\n\nexport const resourceKey = Symbol.for('lifecycle.loadable.loader-resource');\n\n\n// Version of `Error` that keeps a reference to the resource\nexport class LoadError<T> extends Error {\n readonly [resourceKey] : Loadable<T>;\n \n constructor(reason : unknown, resource : Loadable<T>) {\n let message = reason;\n if (reason instanceof Error) {\n message = reason.message;\n }\n \n super($msg`Loading failed: ${message}`);\n this[resourceKey] = resource;\n }\n}\n\n/*\n// type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void;\ntype Resolver<T> = (value ?: T | PromiseLike<T>) => void;\ntype Rejecter = (reason ?: any) => void;\ntype PromiseExecutor<T> = (resolve : Resolver<T>, reject : Rejecter) => void;\n\n// Extended version of `Promise` that works with loadable resources.\n// Note: although the ES6 spec allows extending Promise, babel by default does not support it. Can\n// use the `transform-builtin-extend` plugin.\n// https://github.com/babel/babel/issues/1120\n// \n// Note: should extending Promise become an issue, we could always fall back to just implementing\n// the \"thenable\" interface (i.e. just a method named `then()`).\nexport class LoadablePromise<T> extends Promise<Loadable<T>> {\n // Set the species to regular `Promise`, so that `then()` chaining will not try to create\n // a new LoadablePromise (which fails due to lack of information given to the constructor).\n static [Symbol.species] = Promise;\n \n // Create from existing promise\n static from<T>(resource : Loadable<T>, promise : Promise<Loadable<T>>) : LoadablePromise<T> {\n return new LoadablePromise((resolve, reject) => {\n promise.then(resolve, reject);\n }, resource);\n }\n \n private fulfilled : boolean = false;\n public readonly resource : Loadable<T>;\n \n constructor(\n executor : (resolve : (resource : Loadable<T>) => void, reject : (resource : Loadable<T>) => void) => void,\n resource : Loadable<T>\n ) {\n super((resolve : Resolver<Loadable<T>>, reject : Rejecter) => {\n // Note: need to do this check here, because we cannot do it before `super()`, but we also want\n // it before the call to `executor()`.\n if (!resource[statusKey].loading) {\n throw new TypeError($msg`Expected resource with status loading, given ${resource[statusKey]}`);\n }\n \n executor(\n (resource : Loadable<T>) => {\n if (!resource[statusKey].ready) {\n throw new TypeError($msg`Expected resource with status ready, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n resolve(resource);\n },\n (resource : Loadable<T>) => {\n if (!resource[statusKey].error) {\n throw new TypeError($msg`Expected resource with status failed, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n reject(new LoadError(resource[statusKey].error, resource));\n },\n );\n });\n \n this.resource = resource;\n }\n \n // Similar to `then()`, but will be called:\n // - Once, synchronously, with the resource in loading state, *if* the resource is not already fulfilled\n // (resolved or rejected) synchronously.\n // - Second, when the resource is fulfilled, with the resource in the corresponding state (ready/failed).\n // In addition, `subscribe` does not distinguish between resolved/rejected, it only takes\n // one function which is called regardless of the result (check the `status` instead).\n subscribe(this : LoadablePromise<T>, subscriber : (resource : Loadable<T>) => void) : typeof this {\n if (!this.fulfilled) {\n // Note: should be guaranteed to be in loading state (by the check in the constructor)\n subscriber(this.resource);\n }\n \n this.then(\n (resourceReady : Loadable<T>) => { subscriber(resourceReady); },\n (reason : LoadError<T>) => { subscriber(reason.resource); },\n );\n \n return this;\n }\n}\n*/\n\n\nexport type PromiseWithResource<T> = PromiseLike<Loadable<T>> & {\n [resourceKey] : Loadable<T>,\n //subscribe : () => ..., // TODO\n};\n\n\nexport const fromPromise = <T extends Proxyable>(\n promise : PromiseLike<T>,\n resource ?: Loadable<T>\n ) : PromiseWithResource<T> => {\n // Use the given resource, or use a LoadableProxy by default if none given\n const resourceLoading : Loadable<T> = resource ?? LoadableProxy<T>(undefined, { loading: true });\n \n const promiseWithResource : PromiseWithResource<T> = Object.assign(\n promise.then(\n (result : T) => asReady(resourceLoading, result),\n (reason : Error) => {\n throw new LoadError(reason, asFailed(resourceLoading, reason));\n },\n ),\n {\n [resourceKey]: resourceLoading,\n subscribe(subscriber : (resource : Loadable<T>) => void) {\n subscriber(resourceLoading);\n \n promise.then(\n (result : T) => subscriber(asReady(resourceLoading, result)),\n (reason : Error) => subscriber(asFailed(resourceLoading, reason)),\n );\n },\n },\n );\n \n return promiseWithResource;\n };\n"],"file":"Loader.js"} | ||
| {"version":3,"file":"Loader.js","names":["_messageTag","_interopRequireDefault","require","_Loadable","obj","__esModule","default","_extendableBuiltin","cls","ExtendableBuiltin","instance","Reflect","construct","Array","from","arguments","Object","setPrototypeOf","getPrototypeOf","prototype","create","constructor","value","enumerable","writable","configurable","__proto__","resourceKey","Symbol","for","exports","LoadError","Error","reason","resource","message","$msg","fromPromise","promise","resourceLoading","LoadableProxy","undefined","loading","promiseWithResource","assign","then","result","asReady","asFailed","subscribe","subscriber"],"sources":["../../src/interfaces/Loader.ts"],"sourcesContent":["\nimport $msg from 'message-tag';\nimport type { Proxyable } from 'proxy-extend';\n\nimport { Status, Loadable, itemKey, statusKey, LoadableProxy, asReady, asFailed } from './Loadable.js';\n\n\n// A *loader* is a function that takes a resource (the current state), and returns a promise for\n// a new (loaded) resource (so always async, by definition).\nexport type Loader<T> = (resource : Loadable<T>) => Promise<Loadable<T>>;\n\n// A *loader creator* is a function that returns a loader.\nexport type LoaderCreator<T> = (...args : Array<unknown>) => Loader<T>;\n\n\nexport const resourceKey = Symbol.for('lifecycle.loadable.loader-resource');\n\n\n// Version of `Error` that keeps a reference to the resource\nexport class LoadError<T> extends Error {\n readonly [resourceKey] : Loadable<T>;\n \n constructor(reason : unknown, resource : Loadable<T>) {\n let message = reason;\n if (reason instanceof Error) {\n message = reason.message;\n }\n \n super($msg`Loading failed: ${message}`);\n this[resourceKey] = resource;\n }\n}\n\n/*\n// type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void;\ntype Resolver<T> = (value ?: T | PromiseLike<T>) => void;\ntype Rejecter = (reason ?: any) => void;\ntype PromiseExecutor<T> = (resolve : Resolver<T>, reject : Rejecter) => void;\n\n// Extended version of `Promise` that works with loadable resources.\n// Note: although the ES6 spec allows extending Promise, babel by default does not support it. Can\n// use the `transform-builtin-extend` plugin.\n// https://github.com/babel/babel/issues/1120\n// \n// Note: should extending Promise become an issue, we could always fall back to just implementing\n// the \"thenable\" interface (i.e. just a method named `then()`).\nexport class LoadablePromise<T> extends Promise<Loadable<T>> {\n // Set the species to regular `Promise`, so that `then()` chaining will not try to create\n // a new LoadablePromise (which fails due to lack of information given to the constructor).\n static [Symbol.species] = Promise;\n \n // Create from existing promise\n static from<T>(resource : Loadable<T>, promise : Promise<Loadable<T>>) : LoadablePromise<T> {\n return new LoadablePromise((resolve, reject) => {\n promise.then(resolve, reject);\n }, resource);\n }\n \n private fulfilled : boolean = false;\n public readonly resource : Loadable<T>;\n \n constructor(\n executor : (resolve : (resource : Loadable<T>) => void, reject : (resource : Loadable<T>) => void) => void,\n resource : Loadable<T>\n ) {\n super((resolve : Resolver<Loadable<T>>, reject : Rejecter) => {\n // Note: need to do this check here, because we cannot do it before `super()`, but we also want\n // it before the call to `executor()`.\n if (!resource[statusKey].loading) {\n throw new TypeError($msg`Expected resource with status loading, given ${resource[statusKey]}`);\n }\n \n executor(\n (resource : Loadable<T>) => {\n if (!resource[statusKey].ready) {\n throw new TypeError($msg`Expected resource with status ready, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n resolve(resource);\n },\n (resource : Loadable<T>) => {\n if (!resource[statusKey].error) {\n throw new TypeError($msg`Expected resource with status failed, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n reject(new LoadError(resource[statusKey].error, resource));\n },\n );\n });\n \n this.resource = resource;\n }\n \n // Similar to `then()`, but will be called:\n // - Once, synchronously, with the resource in loading state, *if* the resource is not already fulfilled\n // (resolved or rejected) synchronously.\n // - Second, when the resource is fulfilled, with the resource in the corresponding state (ready/failed).\n // In addition, `subscribe` does not distinguish between resolved/rejected, it only takes\n // one function which is called regardless of the result (check the `status` instead).\n subscribe(this : LoadablePromise<T>, subscriber : (resource : Loadable<T>) => void) : typeof this {\n if (!this.fulfilled) {\n // Note: should be guaranteed to be in loading state (by the check in the constructor)\n subscriber(this.resource);\n }\n \n this.then(\n (resourceReady : Loadable<T>) => { subscriber(resourceReady); },\n (reason : LoadError<T>) => { subscriber(reason.resource); },\n );\n \n return this;\n }\n}\n*/\n\n\nexport type PromiseWithResource<T> = PromiseLike<Loadable<T>> & {\n [resourceKey] : Loadable<T>,\n //subscribe : () => ..., // TODO\n};\n\n\nexport const fromPromise = <T extends Proxyable>(\n promise : PromiseLike<T>,\n resource ?: Loadable<T>\n ) : PromiseWithResource<T> => {\n // Use the given resource, or use a LoadableProxy by default if none given\n const resourceLoading : Loadable<T> = resource ?? LoadableProxy<T>(undefined, { loading: true });\n \n const promiseWithResource : PromiseWithResource<T> = Object.assign(\n promise.then(\n (result : T) => asReady(resourceLoading, result),\n (reason : Error) => {\n throw new LoadError(reason, asFailed(resourceLoading, reason));\n },\n ),\n {\n [resourceKey]: resourceLoading,\n subscribe(subscriber : (resource : Loadable<T>) => void) {\n subscriber(resourceLoading);\n \n promise.then(\n (result : T) => subscriber(asReady(resourceLoading, result)),\n (reason : Error) => subscriber(asFailed(resourceLoading, reason)),\n );\n },\n },\n );\n \n return promiseWithResource;\n };\n"],"mappings":"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"} |
+10
-4
@@ -5,3 +5,6 @@ import { isProxyable } from 'proxy-extend'; | ||
| // Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy) | ||
| export const Loadable = Object.assign((item, status = {}) => LoadableDefs.LoadableProxy(item, status), { | ||
| export const Loadable = Object.assign(function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| return LoadableDefs.LoadableProxy(item, status); | ||
| }, { | ||
| // Keys | ||
@@ -14,2 +17,3 @@ item: LoadableDefs.itemKey, | ||
| // Prevent widening to `symbol` | ||
| isStatus: LoadableDefs.isStatus, | ||
@@ -31,10 +35,12 @@ isLoadable: LoadableDefs.isLoadable, | ||
| asFailed: LoadableDefs.asFailed | ||
| }); // Shorthand exports | ||
| }); | ||
| // Shorthand exports | ||
| export const status = LoadableDefs.statusKey; // Prevent widening to `symbol` | ||
| export const isStatus = LoadableDefs.isStatus; | ||
| export const isLoadable = LoadableDefs.isLoadable; // Utilities | ||
| export const isLoadable = LoadableDefs.isLoadable; | ||
| // Utilities | ||
| export { isProxyable }; | ||
| /* | ||
@@ -41,0 +47,0 @@ export { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts"],"names":["isProxyable","LoadableDefs","LoaderDefs","Loadable","Object","assign","item","status","LoadableProxy","itemKey","statusKey","construct","constructKey","isStatus","isLoadable","Record","LoadableRecord","Proxy","getItem","resource","getStatus","update","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","Loader","resourceKey","fromPromise"],"mappings":"AAEA,SAASA,WAAT,QAA4B,cAA5B;AAEA,OAAO,KAAKC,YAAZ,MAA8B,0BAA9B;AACA,OAAO,KAAKC,UAAZ,MAA4B,wBAA5B;AAQA;AACA,OAAO,MAAMC,QAAQ,GAAGC,MAAM,CAACC,MAAP,CACpB,CAAsBC,IAAtB,EAA6CC,MAAqC,GAAG,EAArF,KACIN,YAAY,CAACO,aAAb,CAA2BF,IAA3B,EAAiCC,MAAjC,CAFgB,EAGpB;AACI;AACAD,EAAAA,IAAI,EAAEL,YAAY,CAACQ,OAFvB;AAEgE;AAC5DF,EAAAA,MAAM,EAAEN,YAAY,CAACS,SAHzB;AAGsE;AAClEC,EAAAA,SAAS,EAAEV,YAAY,CAACW,YAJ5B;AAI+E;AAE3EC,EAAAA,QAAQ,EAAEZ,YAAY,CAACY,QAN3B;AAOIC,EAAAA,UAAU,EAAEb,YAAY,CAACa,UAP7B;AASI;AACAC,EAAAA,MAAM,EAAEd,YAAY,CAACe,cAVzB;AAWIC,EAAAA,KAAK,EAAEhB,YAAY,CAACO,aAXxB;AAaI;AACAU,EAAAA,OAAO,EAAMC,QAAJ,IAA+BA,QAAQ,CAAClB,YAAY,CAACQ,OAAd,CAdpD;AAeIW,EAAAA,SAAS,EAAMD,QAAJ,IAA+BA,QAAQ,CAAClB,YAAY,CAACS,SAAd,CAftD;AAiBI;AACAW,EAAAA,MAAM,EAAEpB,YAAY,CAACoB,MAlBzB;AAmBIC,EAAAA,UAAU,EAAErB,YAAY,CAACqB,UAnB7B;AAoBIC,EAAAA,YAAY,EAAEtB,YAAY,CAACsB,YApB/B;AAqBIC,EAAAA,SAAS,EAAEvB,YAAY,CAACuB,SArB5B;AAsBIC,EAAAA,SAAS,EAAExB,YAAY,CAACwB,SAtB5B;AAuBIC,EAAAA,OAAO,EAAEzB,YAAY,CAACyB,OAvB1B;AAwBIC,EAAAA,QAAQ,EAAE1B,YAAY,CAAC0B;AAxB3B,CAHoB,CAAjB,C,CA+BP;;AACA,OAAO,MAAMpB,MAAqC,GAAGN,YAAY,CAACS,SAA3D,C,CAAsE;;AAC7E,OAAO,MAAMG,QAAQ,GAAGZ,YAAY,CAACY,QAA9B;AACP,OAAO,MAAMC,UAAU,GAAGb,YAAY,CAACa,UAAhC,C,CAEP;;AACA,SAASd,WAAT;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,MAAM4B,MAAM,GAAG;AAClBT,EAAAA,QAAQ,EAAEjB,UAAU,CAAC2B,WADH;AAElBC,EAAAA,WAAW,EAAE5B,UAAU,CAAC4B;AAFN,CAAf;AAOP,eAAe3B,QAAf","sourcesContent":["\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\nimport { isProxyable } from 'proxy-extend';\n\nimport * as LoadableDefs from './interfaces/Loadable.js';\nimport * as LoaderDefs from './interfaces/Loader.js';\n\n\nexport type Status = LoadableDefs.Status;\nexport type Loadable<T> = LoadableDefs.Loadable<T>;\nexport type { Proxyable };\nexport type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>;\n\n// Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy)\nexport const Loadable = Object.assign(\n <T extends Proxyable>(item ?: undefined | T, status : Partial<LoadableDefs.Status> = {}) =>\n LoadableDefs.LoadableProxy(item, status),\n {\n // Keys\n item: LoadableDefs.itemKey as typeof LoadableDefs.itemKey, // Prevent widening to `symbol`\n status: LoadableDefs.statusKey as typeof LoadableDefs.statusKey, // Prevent widening to `symbol`\n construct: LoadableDefs.constructKey as typeof LoadableDefs.constructKey, // Prevent widening to `symbol`\n \n isStatus: LoadableDefs.isStatus,\n isLoadable: LoadableDefs.isLoadable,\n \n // Constructors\n Record: LoadableDefs.LoadableRecord,\n Proxy: LoadableDefs.LoadableProxy,\n \n // Accessor functions\n getItem: <T>(resource : Loadable<T>) => resource[LoadableDefs.itemKey],\n getStatus: <T>(resource : Loadable<T>) => resource[LoadableDefs.statusKey],\n \n // Updater functions\n update: LoadableDefs.update,\n updateItem: LoadableDefs.updateItem,\n updateStatus: LoadableDefs.updateStatus,\n asPending: LoadableDefs.asPending,\n asLoading: LoadableDefs.asLoading,\n asReady: LoadableDefs.asReady,\n asFailed: LoadableDefs.asFailed,\n },\n);\n\n// Shorthand exports\nexport const status: typeof LoadableDefs.statusKey = LoadableDefs.statusKey; // Prevent widening to `symbol`\nexport const isStatus = LoadableDefs.isStatus;\nexport const isLoadable = LoadableDefs.isLoadable;\n\n// Utilities\nexport { isProxyable };\n\n\n/*\nexport {\n LoadError,\n LoadablePromise,\n};\n\nexport const loader = <T>(\n item : Loadable<T>,\n executor : (resolve : (item : Loadable<T>) => void, reject : (item : Loadable<T>) => void) => void,\n ) =>\n new LoadablePromise(executor, item);\n*/\n\nexport const Loader = {\n resource: LoaderDefs.resourceKey,\n fromPromise: LoaderDefs.fromPromise,\n};\n\nexport type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>;\n\nexport default Loadable;\n"],"file":"index.js"} | ||
| {"version":3,"file":"index.js","names":["isProxyable","LoadableDefs","LoaderDefs","Loadable","Object","assign","item","status","arguments","length","undefined","LoadableProxy","itemKey","statusKey","construct","constructKey","isStatus","isLoadable","Record","LoadableRecord","Proxy","getItem","resource","getStatus","update","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","Loader","resourceKey","fromPromise"],"sources":["../src/index.ts"],"sourcesContent":["\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\nimport { isProxyable } from 'proxy-extend';\n\nimport * as LoadableDefs from './interfaces/Loadable.js';\nimport * as LoaderDefs from './interfaces/Loader.js';\n\n\nexport type Status = LoadableDefs.Status;\nexport type Loadable<T> = LoadableDefs.Loadable<T>;\nexport type { Proxyable };\nexport type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>;\n\n// Wrap up the definitions in a single `Loadable` object, which can also be invocated as a function (uses Proxy)\nexport const Loadable = Object.assign(\n <T extends Proxyable>(item ?: undefined | T, status : Partial<LoadableDefs.Status> = {}) =>\n LoadableDefs.LoadableProxy(item, status),\n {\n // Keys\n item: LoadableDefs.itemKey as typeof LoadableDefs.itemKey, // Prevent widening to `symbol`\n status: LoadableDefs.statusKey as typeof LoadableDefs.statusKey, // Prevent widening to `symbol`\n construct: LoadableDefs.constructKey as typeof LoadableDefs.constructKey, // Prevent widening to `symbol`\n \n isStatus: LoadableDefs.isStatus,\n isLoadable: LoadableDefs.isLoadable,\n \n // Constructors\n Record: LoadableDefs.LoadableRecord,\n Proxy: LoadableDefs.LoadableProxy,\n \n // Accessor functions\n getItem: <T>(resource : Loadable<T>) => resource[LoadableDefs.itemKey],\n getStatus: <T>(resource : Loadable<T>) => resource[LoadableDefs.statusKey],\n \n // Updater functions\n update: LoadableDefs.update,\n updateItem: LoadableDefs.updateItem,\n updateStatus: LoadableDefs.updateStatus,\n asPending: LoadableDefs.asPending,\n asLoading: LoadableDefs.asLoading,\n asReady: LoadableDefs.asReady,\n asFailed: LoadableDefs.asFailed,\n },\n);\n\n// Shorthand exports\nexport const status: typeof LoadableDefs.statusKey = LoadableDefs.statusKey; // Prevent widening to `symbol`\nexport const isStatus = LoadableDefs.isStatus;\nexport const isLoadable = LoadableDefs.isLoadable;\n\n// Utilities\nexport { isProxyable };\n\n\n/*\nexport {\n LoadError,\n LoadablePromise,\n};\n\nexport const loader = <T>(\n item : Loadable<T>,\n executor : (resolve : (item : Loadable<T>) => void, reject : (item : Loadable<T>) => void) => void,\n ) =>\n new LoadablePromise(executor, item);\n*/\n\nexport const Loader = {\n resource: LoaderDefs.resourceKey,\n fromPromise: LoaderDefs.fromPromise,\n};\n\nexport type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>;\n\nexport default Loadable;\n"],"mappings":"AAEA,SAASA,WAAW,QAAQ,cAAc;AAE1C,OAAO,KAAKC,YAAY,MAAM,0BAA0B;AACxD,OAAO,KAAKC,UAAU,MAAM,wBAAwB;AAQpD;AACA,OAAO,MAAMC,QAAQ,GAAGC,MAAM,CAACC,MAAM,CACjC,UAAsBC,IAAqB;EAAA,IAAEC,MAAqC,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EAAA,OACnFP,YAAY,CAACU,aAAa,CAACL,IAAI,EAAEC,MAAM,CAAC;AAAA,GAC5C;EACI;EACAD,IAAI,EAAEL,YAAY,CAACW,OAAsC;EAAG;EAC5DL,MAAM,EAAEN,YAAY,CAACY,SAA0C;EAAG;EAClEC,SAAS,EAAEb,YAAY,CAACc,YAAgD;EAAG;;EAE3EC,QAAQ,EAAEf,YAAY,CAACe,QAAQ;EAC/BC,UAAU,EAAEhB,YAAY,CAACgB,UAAU;EAEnC;EACAC,MAAM,EAAEjB,YAAY,CAACkB,cAAc;EACnCC,KAAK,EAAEnB,YAAY,CAACU,aAAa;EAEjC;EACAU,OAAO,EAAMC,QAAsB,IAAKA,QAAQ,CAACrB,YAAY,CAACW,OAAO,CAAC;EACtEW,SAAS,EAAMD,QAAsB,IAAKA,QAAQ,CAACrB,YAAY,CAACY,SAAS,CAAC;EAE1E;EACAW,MAAM,EAAEvB,YAAY,CAACuB,MAAM;EAC3BC,UAAU,EAAExB,YAAY,CAACwB,UAAU;EACnCC,YAAY,EAAEzB,YAAY,CAACyB,YAAY;EACvCC,SAAS,EAAE1B,YAAY,CAAC0B,SAAS;EACjCC,SAAS,EAAE3B,YAAY,CAAC2B,SAAS;EACjCC,OAAO,EAAE5B,YAAY,CAAC4B,OAAO;EAC7BC,QAAQ,EAAE7B,YAAY,CAAC6B;AAC3B,CAAC,CACJ;;AAED;AACA,OAAO,MAAMvB,MAAqC,GAAGN,YAAY,CAACY,SAAS,CAAC,CAAC;AAC7E,OAAO,MAAMG,QAAQ,GAAGf,YAAY,CAACe,QAAQ;AAC7C,OAAO,MAAMC,UAAU,GAAGhB,YAAY,CAACgB,UAAU;;AAEjD;AACA,SAASjB,WAAW;;AAGpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,MAAM+B,MAAM,GAAG;EAClBT,QAAQ,EAAEpB,UAAU,CAAC8B,WAAW;EAChCC,WAAW,EAAE/B,UAAU,CAAC+B;AAC5B,CAAC;AAID,eAAe9B,QAAQ"} |
| import $msg from 'message-tag'; | ||
| import extend, { isProxyable } from 'proxy-extend'; | ||
| // An *item* is the data part of a resource (can be anything). | ||
| /* | ||
| A *status* is an object that describes the current loading state of some resource. | ||
| Status flags: | ||
| - ready: indicates whether this resource can be used or not (whether the data can be read safely) | ||
| - loading: indicates whether we are currently in the process of loading this resource | ||
| - error: indicates that the last load attempt resulted in an error | ||
| Note that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready). | ||
| This is so that we can, for example, start loading new data while keeping information such as an error | ||
| state, for UI purposes. All the possible combinations listed below. | ||
| - !ready + !loading + !error "pending", nothing done yet, not even attempted to load | ||
| - !ready + loading + !error "loading", for the first time, no older data available | ||
| - ready + !loading + !error "ready" (or "idle"), can use the data as needed | ||
| - ready + loading + !error "ready" (or "reloading"), ready but also loading an updated version | ||
| - !ready + !loading + error "failed", and not yet any attempt to retry (no older data available) | ||
| - !ready + loading + error "failed", but we're currently retrying (no older data available) | ||
| - ready + !loading + error "failed", and not yet any attempt to retry (there is older data available) | ||
| - ready + loading + error "failed", but we're currently retrying (there is older data available) | ||
| */ | ||
| const defaultStatus = { | ||
@@ -7,8 +32,11 @@ ready: false, | ||
| error: null | ||
| }; // Property key symbols | ||
| }; | ||
| // Property key symbols | ||
| export const itemKey = Symbol.for('lifecycle.loadable.item'); | ||
| export const statusKey = Symbol.for('lifecycle.loadable.status'); | ||
| export const constructKey = Symbol.for('lifecycle.loadable.construct'); // A *resource* (or "Loadable") is an object that has both an item and a status. | ||
| export const constructKey = Symbol.for('lifecycle.loadable.construct'); | ||
| // A *resource* (or "Loadable") is an object that has both an item and a status. | ||
| export const isStatus = value => { | ||
@@ -18,3 +46,2 @@ if (typeof value !== 'object' || value === null) { | ||
| } | ||
| return 'ready' in value && typeof value.ready === 'boolean' && 'loading' in value && typeof value.loading === 'boolean' && 'error' in value && (value.error === null || value.error instanceof Error); | ||
@@ -26,5 +53,5 @@ }; | ||
| } | ||
| return itemKey in value && statusKey in value && typeof value[statusKey] === 'object' && constructKey in value && typeof value[constructKey] === 'function'; | ||
| }; | ||
| /* | ||
@@ -35,7 +62,10 @@ LoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also | ||
| export const LoadableRecord = (item, status = {}) => { | ||
| export const LoadableRecord = function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| // If the status is ready, then `item` cannot be `undefined` | ||
| if (status.ready === true && typeof item === 'undefined') { | ||
| throw new TypeError('Expected an item, but given `undefined`'); | ||
| } // If the status is not ready, then `item` must be `undefined` | ||
| } | ||
| // If the status is not ready, then `item` must be `undefined` | ||
| //if (status.ready === false && typeof item !== 'undefined') { | ||
@@ -45,4 +75,4 @@ // throw new TypeError($msg`Expected \`undefined\`, but given ${item}`); | ||
| const statusWithDefaults = { ...defaultStatus, | ||
| const statusWithDefaults = { | ||
| ...defaultStatus, | ||
| ready: typeof item !== 'undefined', | ||
@@ -61,2 +91,3 @@ ...status | ||
| }; | ||
| /* | ||
@@ -67,7 +98,10 @@ LoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same | ||
| export const LoadableProxy = (item, status = {}) => { | ||
| export const LoadableProxy = function (item) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| // If the status is ready, then `item` cannot be `undefined` | ||
| if (status.ready === true && typeof item === 'undefined') { | ||
| throw new TypeError('Expected an item, but given `undefined`'); | ||
| } // If the status is not ready, then `item` must be `undefined` | ||
| } | ||
| // If the status is not ready, then `item` must be `undefined` | ||
| //if (status.ready === false && typeof item !== 'undefined') { | ||
@@ -77,12 +111,17 @@ // throw new TypeError($msg`Expected \`undefined\`, but given ${item}`); | ||
| const statusWithDefaults = { ...defaultStatus, | ||
| const statusWithDefaults = { | ||
| ...defaultStatus, | ||
| ready: typeof item !== 'undefined', | ||
| ...status | ||
| }; // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over) | ||
| }; | ||
| // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over) | ||
| if (extend.is(item)) { | ||
| throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`); // TODO: maybe just unwrap the given proxy and override the status? | ||
| throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`); | ||
| // TODO: maybe just unwrap the given proxy and override the status? | ||
| //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item); | ||
| } // If the item itself is a loadable resource, return it as is? | ||
| } | ||
| // If the item itself is a loadable resource, return it as is? | ||
| // (Alternatively, unwrap it and convert to a LoadableProxy instead) | ||
@@ -93,9 +132,6 @@ //if (isLoadable(item)) { | ||
| const itemProxyable = typeof item === 'undefined' ? null : item; | ||
| if (!isProxyable(itemProxyable)) { | ||
| throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`); | ||
| } | ||
| return extend(itemProxyable, { | ||
@@ -106,11 +142,21 @@ [itemKey]: item, | ||
| }); | ||
| }; // Updater methods | ||
| }; | ||
| export const update = (resource, item, status = {}) => resource[constructKey](item, { ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| // Updater methods | ||
| export const update = function (resource, item) { | ||
| let status = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
| return resource[constructKey](item, { | ||
| ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| }; | ||
| export const updateItem = (resource, item) => resource[constructKey](item, resource[statusKey]); | ||
| export const updateStatus = (resource, status = {}) => resource[constructKey](resource[itemKey], { ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| export const updateStatus = function (resource) { | ||
| let status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
| return resource[constructKey](resource[itemKey], { | ||
| ...resource[statusKey], | ||
| ...status | ||
| }); | ||
| }; | ||
| export const asPending = resource => update(resource, undefined, { | ||
@@ -124,4 +170,4 @@ ready: false, | ||
| }); // TODO: should we also clear any error here? | ||
| export const asReady = (resource, item) => update(resource, typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing | ||
| export const asReady = (resource, item) => update(resource, typeof item === 'undefined' ? resource[itemKey] : item, | ||
| // `item` is optional, if not present use existing | ||
| { | ||
@@ -128,0 +174,0 @@ ready: true, |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/interfaces/Loadable.ts"],"names":["$msg","extend","isProxyable","defaultStatus","ready","loading","error","itemKey","Symbol","for","statusKey","constructKey","isStatus","value","Error","isLoadable","LoadableRecord","item","status","TypeError","statusWithDefaults","loadable","LoadableProxy","is","itemProxyable","update","resource","updateItem","updateStatus","asPending","undefined","asLoading","asReady","asFailed","reason"],"mappings":"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","sourcesContent":["\nimport $msg from 'message-tag';\nimport extend, { isProxyable } from 'proxy-extend';\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\n\n\n// An *item* is the data part of a resource (can be anything).\nexport type Item = unknown;\n\n/*\nA *status* is an object that describes the current loading state of some resource.\n\nStatus flags:\n - ready: indicates whether this resource can be used or not (whether the data can be read safely)\n - loading: indicates whether we are currently in the process of loading this resource\n - error: indicates that the last load attempt resulted in an error\n\nNote that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready).\nThis is so that we can, for example, start loading new data while keeping information such as an error\nstate, for UI purposes. All the possible combinations listed below.\n\n- !ready + !loading + !error \"pending\", nothing done yet, not even attempted to load\n- !ready + loading + !error \"loading\", for the first time, no older data available\n- ready + !loading + !error \"ready\" (or \"idle\"), can use the data as needed\n- ready + loading + !error \"ready\" (or \"reloading\"), ready but also loading an updated version\n- !ready + !loading + error \"failed\", and not yet any attempt to retry (no older data available)\n- !ready + loading + error \"failed\", but we're currently retrying (no older data available)\n- ready + !loading + error \"failed\", and not yet any attempt to retry (there is older data available)\n- ready + loading + error \"failed\", but we're currently retrying (there is older data available)\n*/\nexport type Status = {\n ready : boolean,\n loading : boolean,\n error : null | Error,\n};\nconst defaultStatus : Status = { ready: false, loading: false, error: null };\n\n\n// Property key symbols\nexport const itemKey: unique symbol = Symbol.for('lifecycle.loadable.item');\nexport const statusKey: unique symbol = Symbol.for('lifecycle.loadable.status');\nexport const constructKey: unique symbol = Symbol.for('lifecycle.loadable.construct');\n\n// A *resource* (or \"Loadable\") is an object that has both an item and a status.\nexport type Loadable<T> = {\n [itemKey] : undefined | T, // May be `undefined` when status is not ready (if ready *must not* be `undefined`)\n [statusKey] : Status,\n \n // Construct a new resource from this one, using the given item and status\n [constructKey] : (item : undefined | T, status : Status) => Loadable<T>,\n};\n\nexport const isStatus = (value : unknown) : value is Status => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n \n return 'ready' in value && typeof (value as Status).ready === 'boolean'\n && 'loading' in value && typeof (value as Status).loading === 'boolean'\n && 'error' in value && ((value as Status).error === null || (value as Status).error instanceof Error);\n};\n\nexport const isLoadable = (value : unknown) : value is Loadable<unknown> => {\n if (!(typeof value === 'object' && value !== null)) {\n return false;\n }\n \n return itemKey in value\n && statusKey in value && typeof (value as { [statusKey] : unknown })[statusKey] === 'object'\n && constructKey in value && typeof (value as { [constructKey] : unknown })[constructKey] === 'function';\n};\n\n\n/*\nLoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also\nexposes these as regular (non-symbol) properties (so you can access them simply as `res.item` and `res.status`).\n*/\nexport type LoadableRecordT<T> = Loadable<T> & { item : undefined | T, status : Status };\nexport const LoadableRecord = <T>(item ?: undefined | T, status : Partial<Status> = {}) : LoadableRecordT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n const loadable : LoadableRecordT<T> = {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableRecord,\n \n // Also expose as regular (non-symbol) keys\n item,\n status: statusWithDefaults,\n };\n \n return loadable;\n};\n\n\n/*\nLoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same\nas the item itself (status is \"hidden\" using a symbol key).\n*/\nexport type LoadableProxyT<T extends Proxyable> = Loadable<T>\n & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>);\nexport const LoadableProxy = <T extends Proxyable>(\n item ?: undefined | T,\n status : Partial<Status> = {}\n ) : LoadableProxyT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over)\n if (extend.is(item)) {\n throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`);\n \n // TODO: maybe just unwrap the given proxy and override the status?\n //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item);\n }\n \n // If the item itself is a loadable resource, return it as is?\n // (Alternatively, unwrap it and convert to a LoadableProxy instead)\n //if (isLoadable(item)) {\n // return item;\n //}\n \n const itemProxyable = typeof item === 'undefined' ? null : item;\n \n if (!isProxyable(itemProxyable)) {\n throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`);\n }\n \n return extend(itemProxyable, {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableProxy,\n }) as unknown as LoadableProxyT<T>;\n };\n\n\n// Updater methods\n\nexport const update = <T>(resource : Loadable<T>, item : undefined | T, status : Partial<Status> = {}) =>\n resource[constructKey](item, { ...resource[statusKey], ...status });\nexport const updateItem = <T>(resource : Loadable<T>, item : undefined | T) =>\n resource[constructKey](item, resource[statusKey]);\nexport const updateStatus = <T>(resource : Loadable<T>, status : Partial<Status> = {}) =>\n resource[constructKey](resource[itemKey], { ...resource[statusKey], ...status });\n\nexport const asPending = <T>(resource : Loadable<T>) =>\n update(resource, undefined, { ready: false, loading: false, error: null })\nexport const asLoading = <T>(resource : Loadable<T>) =>\n updateStatus(resource, { loading: true }); // TODO: should we also clear any error here?\nexport const asReady = <T>(resource : Loadable<T>, item ?: T) => update(resource,\n typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing\n { ready: true, loading: false, error: null }\n);\nexport const asFailed = <T>(resource : Loadable<T>, reason : Error) =>\n updateStatus(resource, { loading: false, error: reason });\n"],"file":"Loadable.js"} | ||
| {"version":3,"file":"Loadable.js","names":["$msg","extend","isProxyable","defaultStatus","ready","loading","error","itemKey","Symbol","for","statusKey","constructKey","isStatus","value","Error","isLoadable","LoadableRecord","item","status","arguments","length","undefined","TypeError","statusWithDefaults","loadable","LoadableProxy","is","itemProxyable","update","resource","updateItem","updateStatus","asPending","asLoading","asReady","asFailed","reason"],"sources":["../../src/interfaces/Loadable.ts"],"sourcesContent":["\nimport $msg from 'message-tag';\nimport extend, { isProxyable } from 'proxy-extend';\nimport type { Proxyable, ProxyableExternal } from 'proxy-extend';\n\n\n// An *item* is the data part of a resource (can be anything).\nexport type Item = unknown;\n\n/*\nA *status* is an object that describes the current loading state of some resource.\n\nStatus flags:\n - ready: indicates whether this resource can be used or not (whether the data can be read safely)\n - loading: indicates whether we are currently in the process of loading this resource\n - error: indicates that the last load attempt resulted in an error\n\nNote that each of the flags is independent, rather than being a linear transition (e.g. loading -> ready).\nThis is so that we can, for example, start loading new data while keeping information such as an error\nstate, for UI purposes. All the possible combinations listed below.\n\n- !ready + !loading + !error \"pending\", nothing done yet, not even attempted to load\n- !ready + loading + !error \"loading\", for the first time, no older data available\n- ready + !loading + !error \"ready\" (or \"idle\"), can use the data as needed\n- ready + loading + !error \"ready\" (or \"reloading\"), ready but also loading an updated version\n- !ready + !loading + error \"failed\", and not yet any attempt to retry (no older data available)\n- !ready + loading + error \"failed\", but we're currently retrying (no older data available)\n- ready + !loading + error \"failed\", and not yet any attempt to retry (there is older data available)\n- ready + loading + error \"failed\", but we're currently retrying (there is older data available)\n*/\nexport type Status = {\n ready : boolean,\n loading : boolean,\n error : null | Error,\n};\nconst defaultStatus : Status = { ready: false, loading: false, error: null };\n\n\n// Property key symbols\nexport const itemKey: unique symbol = Symbol.for('lifecycle.loadable.item');\nexport const statusKey: unique symbol = Symbol.for('lifecycle.loadable.status');\nexport const constructKey: unique symbol = Symbol.for('lifecycle.loadable.construct');\n\n// A *resource* (or \"Loadable\") is an object that has both an item and a status.\nexport type Loadable<T> = {\n [itemKey] : undefined | T, // May be `undefined` when status is not ready (if ready *must not* be `undefined`)\n [statusKey] : Status,\n \n // Construct a new resource from this one, using the given item and status\n [constructKey] : (item : undefined | T, status : Status) => Loadable<T>,\n};\n\nexport const isStatus = (value : unknown) : value is Status => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n \n return 'ready' in value && typeof (value as Status).ready === 'boolean'\n && 'loading' in value && typeof (value as Status).loading === 'boolean'\n && 'error' in value && ((value as Status).error === null || (value as Status).error instanceof Error);\n};\n\nexport const isLoadable = (value : unknown) : value is Loadable<unknown> => {\n if (!(typeof value === 'object' && value !== null)) {\n return false;\n }\n \n return itemKey in value\n && statusKey in value && typeof (value as { [statusKey] : unknown })[statusKey] === 'object'\n && constructKey in value && typeof (value as { [constructKey] : unknown })[constructKey] === 'function';\n};\n\n\n/*\nLoadableRecord: simple resource implementation that just stores the item and status in a plain object. Also\nexposes these as regular (non-symbol) properties (so you can access them simply as `res.item` and `res.status`).\n*/\nexport type LoadableRecordT<T> = Loadable<T> & { item : undefined | T, status : Status };\nexport const LoadableRecord = <T>(item ?: undefined | T, status : Partial<Status> = {}) : LoadableRecordT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n const loadable : LoadableRecordT<T> = {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableRecord,\n \n // Also expose as regular (non-symbol) keys\n item,\n status: statusWithDefaults,\n };\n \n return loadable;\n};\n\n\n/*\nLoadableProxy: resource implementation that uses a Proxy, in order to expose an interface that appears the same\nas the item itself (status is \"hidden\" using a symbol key).\n*/\nexport type LoadableProxyT<T extends Proxyable> = Loadable<T>\n & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>);\nexport const LoadableProxy = <T extends Proxyable>(\n item ?: undefined | T,\n status : Partial<Status> = {}\n ) : LoadableProxyT<T> => {\n // If the status is ready, then `item` cannot be `undefined`\n if (status.ready === true && typeof item === 'undefined') {\n throw new TypeError('Expected an item, but given `undefined`');\n }\n \n // If the status is not ready, then `item` must be `undefined`\n //if (status.ready === false && typeof item !== 'undefined') {\n // throw new TypeError($msg`Expected \\`undefined\\`, but given ${item}`);\n //}\n \n const statusWithDefaults = {\n ...defaultStatus,\n ready: typeof item !== 'undefined',\n ...status,\n };\n \n // Prevent proxying multiple times (to prevent bugs where an object is repeatedly proxied over and over)\n if (extend.is(item)) {\n throw new TypeError($msg`Cannot create a LoadableProxy from an item which is already a LoadableProxy`);\n \n // TODO: maybe just unwrap the given proxy and override the status?\n //const { extension: { [itemKey]: _item, [statusKey]: _status } } = extend.unwrap(item);\n }\n \n // If the item itself is a loadable resource, return it as is?\n // (Alternatively, unwrap it and convert to a LoadableProxy instead)\n //if (isLoadable(item)) {\n // return item;\n //}\n \n const itemProxyable = typeof item === 'undefined' ? null : item;\n \n if (!isProxyable(itemProxyable)) {\n throw new TypeError(`Cannot proxy the given value: ${itemProxyable}`);\n }\n \n return extend(itemProxyable, {\n [itemKey]: item,\n [statusKey]: statusWithDefaults,\n [constructKey]: LoadableProxy,\n }) as unknown as LoadableProxyT<T>;\n };\n\n\n// Updater methods\n\nexport const update = <T>(resource : Loadable<T>, item : undefined | T, status : Partial<Status> = {}) =>\n resource[constructKey](item, { ...resource[statusKey], ...status });\nexport const updateItem = <T>(resource : Loadable<T>, item : undefined | T) =>\n resource[constructKey](item, resource[statusKey]);\nexport const updateStatus = <T>(resource : Loadable<T>, status : Partial<Status> = {}) =>\n resource[constructKey](resource[itemKey], { ...resource[statusKey], ...status });\n\nexport const asPending = <T>(resource : Loadable<T>) =>\n update(resource, undefined, { ready: false, loading: false, error: null })\nexport const asLoading = <T>(resource : Loadable<T>) =>\n updateStatus(resource, { loading: true }); // TODO: should we also clear any error here?\nexport const asReady = <T>(resource : Loadable<T>, item ?: T) => update(resource,\n typeof item === 'undefined' ? resource[itemKey] : item, // `item` is optional, if not present use existing\n { ready: true, loading: false, error: null }\n);\nexport const asFailed = <T>(resource : Loadable<T>, reason : Error) =>\n updateStatus(resource, { loading: false, error: reason });\n"],"mappings":"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"} |
@@ -7,3 +7,2 @@ function _extendableBuiltin(cls) { | ||
| } | ||
| ExtendableBuiltin.prototype = Object.create(cls.prototype, { | ||
@@ -17,3 +16,2 @@ constructor: { | ||
| }); | ||
| if (Object.setPrototypeOf) { | ||
@@ -24,25 +22,24 @@ Object.setPrototypeOf(ExtendableBuiltin, cls); | ||
| } | ||
| return ExtendableBuiltin; | ||
| } | ||
| import $msg from 'message-tag'; | ||
| import { LoadableProxy, asReady, asFailed } from './Loadable.js'; | ||
| import $msg from 'message-tag'; | ||
| import { LoadableProxy, asReady, asFailed } from './Loadable.js'; // A *loader* is a function that takes a resource (the current state), and returns a promise for | ||
| // A *loader* is a function that takes a resource (the current state), and returns a promise for | ||
| // a new (loaded) resource (so always async, by definition). | ||
| // A *loader creator* is a function that returns a loader. | ||
| export const resourceKey = Symbol.for('lifecycle.loadable.loader-resource'); | ||
| export const resourceKey = Symbol.for('lifecycle.loadable.loader-resource'); // Version of `Error` that keeps a reference to the resource | ||
| // Version of `Error` that keeps a reference to the resource | ||
| export class LoadError extends _extendableBuiltin(Error) { | ||
| constructor(reason, resource) { | ||
| let message = reason; | ||
| if (reason instanceof Error) { | ||
| message = reason.message; | ||
| } | ||
| super($msg`Loading failed: ${message}`); | ||
| this[resourceKey] = resource; | ||
| } | ||
| } | ||
| } | ||
| /* | ||
@@ -134,3 +131,3 @@ // type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void; | ||
| // Use the given resource, or use a LoadableProxy by default if none given | ||
| const resourceLoading = resource !== null && resource !== void 0 ? resource : LoadableProxy(undefined, { | ||
| const resourceLoading = resource ?? LoadableProxy(undefined, { | ||
| loading: true | ||
@@ -142,3 +139,2 @@ }); | ||
| [resourceKey]: resourceLoading, | ||
| subscribe(subscriber) { | ||
@@ -148,3 +144,2 @@ subscriber(resourceLoading); | ||
| } | ||
| }); | ||
@@ -151,0 +146,0 @@ return promiseWithResource; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/interfaces/Loader.ts"],"names":["$msg","LoadableProxy","asReady","asFailed","resourceKey","Symbol","for","LoadError","Error","constructor","reason","resource","message","fromPromise","promise","resourceLoading","undefined","loading","promiseWithResource","Object","assign","then","result","subscribe","subscriber"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AACA,OAAOA,IAAP,MAAiB,aAAjB;AAGA,SAA+CC,aAA/C,EAA8DC,OAA9D,EAAuEC,QAAvE,QAAuF,eAAvF,C,CAGA;AACA;;AAOA,OAAO,MAAMC,WAAW,GAAGC,MAAM,CAACC,GAAP,CAAW,oCAAX,CAApB,C,CAGP;;AACA,OAAO,MAAMC,SAAN,4BAA2BC,KAA3B,EAAiC;AAGpCC,EAAAA,WAAW,CAACC,MAAD,EAAmBC,QAAnB,EAA2C;AAClD,QAAIC,OAAO,GAAGF,MAAd;;AACA,QAAIA,MAAM,YAAYF,KAAtB,EAA6B;AACzBI,MAAAA,OAAO,GAAGF,MAAM,CAACE,OAAjB;AACH;;AAED,UAAMZ,IAAK,mBAAkBY,OAAQ,EAArC;AACA,SAAKR,WAAL,IAAoBO,QAApB;AACH;;AAXmC;AAcxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA,OAAO,MAAME,WAAW,GAAG,CACnBC,OADmB,EAEnBH,QAFmB,KAGO;AAC1B;AACA,QAAMI,eAA6B,GAAGJ,QAAH,aAAGA,QAAH,cAAGA,QAAH,GAAeV,aAAa,CAAIe,SAAJ,EAAe;AAAEC,IAAAA,OAAO,EAAE;AAAX,GAAf,CAA/D;AAEA,QAAMC,mBAA4C,GAAGC,MAAM,CAACC,MAAP,CACjDN,OAAO,CAACO,IAAR,CACKC,MAAD,IAAgBpB,OAAO,CAACa,eAAD,EAAkBO,MAAlB,CAD3B,EAEKZ,MAAD,IAAoB;AAChB,UAAM,IAAIH,SAAJ,CAAcG,MAAd,EAAsBP,QAAQ,CAACY,eAAD,EAAkBL,MAAlB,CAA9B,CAAN;AACH,GAJL,CADiD,EAOjD;AACI,KAACN,WAAD,GAAeW,eADnB;;AAEIQ,IAAAA,SAAS,CAACC,UAAD,EAAgD;AACrDA,MAAAA,UAAU,CAACT,eAAD,CAAV;AAEAD,MAAAA,OAAO,CAACO,IAAR,CACKC,MAAD,IAAgBE,UAAU,CAACtB,OAAO,CAACa,eAAD,EAAkBO,MAAlB,CAAR,CAD9B,EAEKZ,MAAD,IAAoBc,UAAU,CAACrB,QAAQ,CAACY,eAAD,EAAkBL,MAAlB,CAAT,CAFlC;AAIH;;AATL,GAPiD,CAArD;AAoBA,SAAOQ,mBAAP;AACH,CA5BE","sourcesContent":["\nimport $msg from 'message-tag';\nimport type { Proxyable } from 'proxy-extend';\n\nimport { Status, Loadable, itemKey, statusKey, LoadableProxy, asReady, asFailed } from './Loadable.js';\n\n\n// A *loader* is a function that takes a resource (the current state), and returns a promise for\n// a new (loaded) resource (so always async, by definition).\nexport type Loader<T> = (resource : Loadable<T>) => Promise<Loadable<T>>;\n\n// A *loader creator* is a function that returns a loader.\nexport type LoaderCreator<T> = (...args : Array<unknown>) => Loader<T>;\n\n\nexport const resourceKey = Symbol.for('lifecycle.loadable.loader-resource');\n\n\n// Version of `Error` that keeps a reference to the resource\nexport class LoadError<T> extends Error {\n readonly [resourceKey] : Loadable<T>;\n \n constructor(reason : unknown, resource : Loadable<T>) {\n let message = reason;\n if (reason instanceof Error) {\n message = reason.message;\n }\n \n super($msg`Loading failed: ${message}`);\n this[resourceKey] = resource;\n }\n}\n\n/*\n// type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void;\ntype Resolver<T> = (value ?: T | PromiseLike<T>) => void;\ntype Rejecter = (reason ?: any) => void;\ntype PromiseExecutor<T> = (resolve : Resolver<T>, reject : Rejecter) => void;\n\n// Extended version of `Promise` that works with loadable resources.\n// Note: although the ES6 spec allows extending Promise, babel by default does not support it. Can\n// use the `transform-builtin-extend` plugin.\n// https://github.com/babel/babel/issues/1120\n// \n// Note: should extending Promise become an issue, we could always fall back to just implementing\n// the \"thenable\" interface (i.e. just a method named `then()`).\nexport class LoadablePromise<T> extends Promise<Loadable<T>> {\n // Set the species to regular `Promise`, so that `then()` chaining will not try to create\n // a new LoadablePromise (which fails due to lack of information given to the constructor).\n static [Symbol.species] = Promise;\n \n // Create from existing promise\n static from<T>(resource : Loadable<T>, promise : Promise<Loadable<T>>) : LoadablePromise<T> {\n return new LoadablePromise((resolve, reject) => {\n promise.then(resolve, reject);\n }, resource);\n }\n \n private fulfilled : boolean = false;\n public readonly resource : Loadable<T>;\n \n constructor(\n executor : (resolve : (resource : Loadable<T>) => void, reject : (resource : Loadable<T>) => void) => void,\n resource : Loadable<T>\n ) {\n super((resolve : Resolver<Loadable<T>>, reject : Rejecter) => {\n // Note: need to do this check here, because we cannot do it before `super()`, but we also want\n // it before the call to `executor()`.\n if (!resource[statusKey].loading) {\n throw new TypeError($msg`Expected resource with status loading, given ${resource[statusKey]}`);\n }\n \n executor(\n (resource : Loadable<T>) => {\n if (!resource[statusKey].ready) {\n throw new TypeError($msg`Expected resource with status ready, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n resolve(resource);\n },\n (resource : Loadable<T>) => {\n if (!resource[statusKey].error) {\n throw new TypeError($msg`Expected resource with status failed, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n reject(new LoadError(resource[statusKey].error, resource));\n },\n );\n });\n \n this.resource = resource;\n }\n \n // Similar to `then()`, but will be called:\n // - Once, synchronously, with the resource in loading state, *if* the resource is not already fulfilled\n // (resolved or rejected) synchronously.\n // - Second, when the resource is fulfilled, with the resource in the corresponding state (ready/failed).\n // In addition, `subscribe` does not distinguish between resolved/rejected, it only takes\n // one function which is called regardless of the result (check the `status` instead).\n subscribe(this : LoadablePromise<T>, subscriber : (resource : Loadable<T>) => void) : typeof this {\n if (!this.fulfilled) {\n // Note: should be guaranteed to be in loading state (by the check in the constructor)\n subscriber(this.resource);\n }\n \n this.then(\n (resourceReady : Loadable<T>) => { subscriber(resourceReady); },\n (reason : LoadError<T>) => { subscriber(reason.resource); },\n );\n \n return this;\n }\n}\n*/\n\n\nexport type PromiseWithResource<T> = PromiseLike<Loadable<T>> & {\n [resourceKey] : Loadable<T>,\n //subscribe : () => ..., // TODO\n};\n\n\nexport const fromPromise = <T extends Proxyable>(\n promise : PromiseLike<T>,\n resource ?: Loadable<T>\n ) : PromiseWithResource<T> => {\n // Use the given resource, or use a LoadableProxy by default if none given\n const resourceLoading : Loadable<T> = resource ?? LoadableProxy<T>(undefined, { loading: true });\n \n const promiseWithResource : PromiseWithResource<T> = Object.assign(\n promise.then(\n (result : T) => asReady(resourceLoading, result),\n (reason : Error) => {\n throw new LoadError(reason, asFailed(resourceLoading, reason));\n },\n ),\n {\n [resourceKey]: resourceLoading,\n subscribe(subscriber : (resource : Loadable<T>) => void) {\n subscriber(resourceLoading);\n \n promise.then(\n (result : T) => subscriber(asReady(resourceLoading, result)),\n (reason : Error) => subscriber(asFailed(resourceLoading, reason)),\n );\n },\n },\n );\n \n return promiseWithResource;\n };\n"],"file":"Loader.js"} | ||
| {"version":3,"file":"Loader.js","names":["$msg","LoadableProxy","asReady","asFailed","resourceKey","Symbol","for","LoadError","_extendableBuiltin","Error","constructor","reason","resource","message","fromPromise","promise","resourceLoading","undefined","loading","promiseWithResource","Object","assign","then","result","subscribe","subscriber"],"sources":["../../src/interfaces/Loader.ts"],"sourcesContent":["\nimport $msg from 'message-tag';\nimport type { Proxyable } from 'proxy-extend';\n\nimport { Status, Loadable, itemKey, statusKey, LoadableProxy, asReady, asFailed } from './Loadable.js';\n\n\n// A *loader* is a function that takes a resource (the current state), and returns a promise for\n// a new (loaded) resource (so always async, by definition).\nexport type Loader<T> = (resource : Loadable<T>) => Promise<Loadable<T>>;\n\n// A *loader creator* is a function that returns a loader.\nexport type LoaderCreator<T> = (...args : Array<unknown>) => Loader<T>;\n\n\nexport const resourceKey = Symbol.for('lifecycle.loadable.loader-resource');\n\n\n// Version of `Error` that keeps a reference to the resource\nexport class LoadError<T> extends Error {\n readonly [resourceKey] : Loadable<T>;\n \n constructor(reason : unknown, resource : Loadable<T>) {\n let message = reason;\n if (reason instanceof Error) {\n message = reason.message;\n }\n \n super($msg`Loading failed: ${message}`);\n this[resourceKey] = resource;\n }\n}\n\n/*\n// type Fulfill = (resolve : (result : unknown) => void, reject : (reason : unknown) => void) => void;\ntype Resolver<T> = (value ?: T | PromiseLike<T>) => void;\ntype Rejecter = (reason ?: any) => void;\ntype PromiseExecutor<T> = (resolve : Resolver<T>, reject : Rejecter) => void;\n\n// Extended version of `Promise` that works with loadable resources.\n// Note: although the ES6 spec allows extending Promise, babel by default does not support it. Can\n// use the `transform-builtin-extend` plugin.\n// https://github.com/babel/babel/issues/1120\n// \n// Note: should extending Promise become an issue, we could always fall back to just implementing\n// the \"thenable\" interface (i.e. just a method named `then()`).\nexport class LoadablePromise<T> extends Promise<Loadable<T>> {\n // Set the species to regular `Promise`, so that `then()` chaining will not try to create\n // a new LoadablePromise (which fails due to lack of information given to the constructor).\n static [Symbol.species] = Promise;\n \n // Create from existing promise\n static from<T>(resource : Loadable<T>, promise : Promise<Loadable<T>>) : LoadablePromise<T> {\n return new LoadablePromise((resolve, reject) => {\n promise.then(resolve, reject);\n }, resource);\n }\n \n private fulfilled : boolean = false;\n public readonly resource : Loadable<T>;\n \n constructor(\n executor : (resolve : (resource : Loadable<T>) => void, reject : (resource : Loadable<T>) => void) => void,\n resource : Loadable<T>\n ) {\n super((resolve : Resolver<Loadable<T>>, reject : Rejecter) => {\n // Note: need to do this check here, because we cannot do it before `super()`, but we also want\n // it before the call to `executor()`.\n if (!resource[statusKey].loading) {\n throw new TypeError($msg`Expected resource with status loading, given ${resource[statusKey]}`);\n }\n \n executor(\n (resource : Loadable<T>) => {\n if (!resource[statusKey].ready) {\n throw new TypeError($msg`Expected resource with status ready, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n resolve(resource);\n },\n (resource : Loadable<T>) => {\n if (!resource[statusKey].error) {\n throw new TypeError($msg`Expected resource with status failed, given ${resource[statusKey]}`);\n }\n \n this.fulfilled = true;\n reject(new LoadError(resource[statusKey].error, resource));\n },\n );\n });\n \n this.resource = resource;\n }\n \n // Similar to `then()`, but will be called:\n // - Once, synchronously, with the resource in loading state, *if* the resource is not already fulfilled\n // (resolved or rejected) synchronously.\n // - Second, when the resource is fulfilled, with the resource in the corresponding state (ready/failed).\n // In addition, `subscribe` does not distinguish between resolved/rejected, it only takes\n // one function which is called regardless of the result (check the `status` instead).\n subscribe(this : LoadablePromise<T>, subscriber : (resource : Loadable<T>) => void) : typeof this {\n if (!this.fulfilled) {\n // Note: should be guaranteed to be in loading state (by the check in the constructor)\n subscriber(this.resource);\n }\n \n this.then(\n (resourceReady : Loadable<T>) => { subscriber(resourceReady); },\n (reason : LoadError<T>) => { subscriber(reason.resource); },\n );\n \n return this;\n }\n}\n*/\n\n\nexport type PromiseWithResource<T> = PromiseLike<Loadable<T>> & {\n [resourceKey] : Loadable<T>,\n //subscribe : () => ..., // TODO\n};\n\n\nexport const fromPromise = <T extends Proxyable>(\n promise : PromiseLike<T>,\n resource ?: Loadable<T>\n ) : PromiseWithResource<T> => {\n // Use the given resource, or use a LoadableProxy by default if none given\n const resourceLoading : Loadable<T> = resource ?? LoadableProxy<T>(undefined, { loading: true });\n \n const promiseWithResource : PromiseWithResource<T> = Object.assign(\n promise.then(\n (result : T) => asReady(resourceLoading, result),\n (reason : Error) => {\n throw new LoadError(reason, asFailed(resourceLoading, reason));\n },\n ),\n {\n [resourceKey]: resourceLoading,\n subscribe(subscriber : (resource : Loadable<T>) => void) {\n subscriber(resourceLoading);\n \n promise.then(\n (result : T) => subscriber(asReady(resourceLoading, result)),\n (reason : Error) => subscriber(asFailed(resourceLoading, reason)),\n );\n },\n },\n );\n \n return promiseWithResource;\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AACA,OAAOA,IAAI,MAAM,aAAa;AAG9B,SAA+CC,aAAa,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,eAAe;;AAGtG;AACA;AAGA;AAIA,OAAO,MAAMC,WAAW,GAAGC,MAAM,CAACC,GAAG,CAAC,oCAAoC,CAAC;;AAG3E;AACA,OAAO,MAAMC,SAAS,SAAAC,kBAAA,CAAYC,KAAK,EAAC;EAGpCC,WAAWA,CAACC,MAAgB,EAAEC,QAAsB,EAAE;IAClD,IAAIC,OAAO,GAAGF,MAAM;IACpB,IAAIA,MAAM,YAAYF,KAAK,EAAE;MACzBI,OAAO,GAAGF,MAAM,CAACE,OAAO;IAC5B;IAEA,KAAK,CAACb,IAAK,mBAAkBa,OAAQ,EAAC,CAAC;IACvC,IAAI,CAACT,WAAW,CAAC,GAAGQ,QAAQ;EAChC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AASA,OAAO,MAAME,WAAW,GAAGA,CACnBC,OAAwB,EACxBH,QAAuB,KACG;EAC1B;EACA,MAAMI,eAA6B,GAAGJ,QAAQ,IAAIX,aAAa,CAAIgB,SAAS,EAAE;IAAEC,OAAO,EAAE;EAAK,CAAC,CAAC;EAEhG,MAAMC,mBAA4C,GAAGC,MAAM,CAACC,MAAM,CAC9DN,OAAO,CAACO,IAAI,CACPC,MAAU,IAAKrB,OAAO,CAACc,eAAe,EAAEO,MAAM,CAAC,EAC/CZ,MAAc,IAAK;IAChB,MAAM,IAAIJ,SAAS,CAACI,MAAM,EAAER,QAAQ,CAACa,eAAe,EAAEL,MAAM,CAAC,CAAC;EAClE,CAAC,CACJ,EACD;IACI,CAACP,WAAW,GAAGY,eAAe;IAC9BQ,SAASA,CAACC,UAA6C,EAAE;MACrDA,UAAU,CAACT,eAAe,CAAC;MAE3BD,OAAO,CAACO,IAAI,CACPC,MAAU,IAAKE,UAAU,CAACvB,OAAO,CAACc,eAAe,EAAEO,MAAM,CAAC,CAAC,EAC3DZ,MAAc,IAAKc,UAAU,CAACtB,QAAQ,CAACa,eAAe,EAAEL,MAAM,CAAC,CAAC,CACpE;IACL;EACJ,CAAC,CACJ;EAED,OAAOQ,mBAAmB;AAC9B,CAAC"} |
+15
-15
| { | ||
| "name": "@mkrause/lifecycle-loader", | ||
| "version": "0.3.2", | ||
| "version": "0.4.0", | ||
| "author": "mkrause", | ||
@@ -17,3 +17,3 @@ "license": "MIT", | ||
| "engines": { | ||
| "node": ">= 12.13" | ||
| "node": ">= 14.15" | ||
| }, | ||
@@ -33,20 +33,20 @@ "main": "./lib-cjs/index.js", | ||
| "devDependencies": { | ||
| "@babel/core": "^7.15.0", | ||
| "@babel/register": "^7.14.5", | ||
| "@babel/cli": "^7.14.8", | ||
| "@babel/preset-env": "^7.15.0", | ||
| "@babel/preset-typescript": "^7.15.0", | ||
| "@babel/core": "^7.21.4", | ||
| "@babel/register": "^7.21.0", | ||
| "@babel/cli": "^7.21.0", | ||
| "@babel/preset-env": "^7.21.4", | ||
| "@babel/preset-typescript": "^7.21.4", | ||
| "babel-plugin-transform-builtin-extend": "^1.1.2", | ||
| "typescript": "^4.3.5", | ||
| "expect-type": "^0.12.0", | ||
| "@types/node": "^16.4.13", | ||
| "mocha": "^9.0.3", | ||
| "chai": "^4.3.4", | ||
| "typescript": "^5.0.4", | ||
| "expect-type": "^0.15.0", | ||
| "@types/node": "^18.15.11", | ||
| "mocha": "^10.2.0", | ||
| "chai": "^4.3.7", | ||
| "chai-as-promised": "^7.1.1", | ||
| "sinon": "^11.1.2" | ||
| "sinon": "^15.0.3" | ||
| }, | ||
| "dependencies": { | ||
| "message-tag": "^0.6.0", | ||
| "proxy-extend": "^1.3.0" | ||
| "message-tag": "^0.10.0", | ||
| "proxy-extend": "^2.0.0" | ||
| } | ||
| } |
+4
-5
| # lifecycle-loader | ||
| [](https://www.npmjs.com/package/@mkrause/lifecycle-loader) | ||
| [](https://travis-ci.org/mkrause/lifecycle-loader) | ||
|  | ||
|  | ||
| [](https://www.npmjs.com/package/@mkrause/lifecycle-loader) | ||
| [](https://github.com/mkrause/lifecycle-loader/actions) | ||
| [](https://github.com/mkrause/lifecycle-loader) | ||
| [](https://github.com/mkrause/lifecycle-loader) | ||
| Utilities for working with asynchronously loaded state. This library is intended to be used as a primitive within a higher-level API library, see for example: [lifecycle-rest](https://github.com/mkrause/lifecycle-rest). | ||
@@ -11,0 +10,0 @@ |
@@ -5,6 +5,6 @@ import type { Proxyable } from 'proxy-extend'; | ||
| import * as LoaderDefs from './interfaces/Loader.js'; | ||
| export declare type Status = LoadableDefs.Status; | ||
| export declare type Loadable<T> = LoadableDefs.Loadable<T>; | ||
| export type Status = LoadableDefs.Status; | ||
| export type Loadable<T> = LoadableDefs.Loadable<T>; | ||
| export type { Proxyable }; | ||
| export declare type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>; | ||
| export type LoadableProxy<T extends Proxyable> = LoadableDefs.LoadableProxyT<T>; | ||
| export declare const Loadable: (<T extends Proxyable>(item?: T | undefined, status?: Partial<LoadableDefs.Status>) => LoadableDefs.LoadableProxyT<T>) & { | ||
@@ -36,4 +36,4 @@ item: typeof LoadableDefs.itemKey; | ||
| }; | ||
| export declare type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>; | ||
| export type PromiseWithResource<T> = LoaderDefs.PromiseWithResource<T>; | ||
| export default Loadable; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AAGrD,oBAAY,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;AACzC,oBAAY,QAAQ,CAAC,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnD,YAAY,EAAE,SAAS,EAAE,CAAC;AAC1B,oBAAY,aAAa,CAAC,CAAC,SAAS,SAAS,IAAI,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAGhF,eAAO,MAAM,QAAQ,wDACqC,QAAQ,mBAAmB,CAAC;;;;;;;;;;;;;;;;;CA4BrF,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,OAAO,YAAY,CAAC,SAAkC,CAAC;AAC5E,eAAO,MAAM,QAAQ,kDAAwB,CAAC;AAC9C,eAAO,MAAM,UAAU,6DAA0B,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,CAAC;AAgBvB,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAEF,oBAAY,mBAAmB,CAAC,CAAC,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEvE,eAAe,QAAQ,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AAGrD,MAAM,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;AACzC,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnD,YAAY,EAAE,SAAS,EAAE,CAAC;AAC1B,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,SAAS,IAAI,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAGhF,eAAO,MAAM,QAAQ,wDACqC,QAAQ,mBAAmB,CAAC;;;;;;;;;;;;;;;;;CA4BrF,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,OAAO,YAAY,CAAC,SAAkC,CAAC;AAC5E,eAAO,MAAM,QAAQ,kDAAwB,CAAC;AAC9C,eAAO,MAAM,UAAU,6DAA0B,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,CAAC;AAgBvB,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAEvE,eAAe,QAAQ,CAAC"} |
| import type { Proxyable, ProxyableExternal } from 'proxy-extend'; | ||
| export declare type Item = unknown; | ||
| export declare type Status = { | ||
| export type Item = unknown; | ||
| export type Status = { | ||
| ready: boolean; | ||
@@ -11,3 +11,3 @@ loading: boolean; | ||
| export declare const constructKey: unique symbol; | ||
| export declare type Loadable<T> = { | ||
| export type Loadable<T> = { | ||
| [itemKey]: undefined | T; | ||
@@ -19,3 +19,3 @@ [statusKey]: Status; | ||
| export declare const isLoadable: (value: unknown) => value is Loadable<unknown>; | ||
| export declare type LoadableRecordT<T> = Loadable<T> & { | ||
| export type LoadableRecordT<T> = Loadable<T> & { | ||
| item: undefined | T; | ||
@@ -25,3 +25,3 @@ status: Status; | ||
| export declare const LoadableRecord: <T>(item?: T | undefined, status?: Partial<Status>) => LoadableRecordT<T>; | ||
| export declare type LoadableProxyT<T extends Proxyable> = Loadable<T> & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>); | ||
| export type LoadableProxyT<T extends Proxyable> = Loadable<T> & (T extends undefined ? ProxyableExternal<null> : ProxyableExternal<T>); | ||
| export declare const LoadableProxy: <T extends Proxyable>(item?: T | undefined, status?: Partial<Status>) => LoadableProxyT<T>; | ||
@@ -28,0 +28,0 @@ export declare const update: <T>(resource: Loadable<T>, item: T | undefined, status?: Partial<Status>) => Loadable<T>; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Loadable.d.ts","sourceRoot":"","sources":["../../src/interfaces/Loadable.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAIjE,oBAAY,IAAI,GAAG,OAAO,CAAC;AAuB3B,oBAAY,MAAM,GAAG;IACjB,KAAK,EAAG,OAAO,CAAC;IAChB,OAAO,EAAG,OAAO,CAAC;IAClB,KAAK,EAAG,IAAI,GAAG,KAAK,CAAC;CACxB,CAAC;AAKF,eAAO,MAAM,OAAO,EAAE,OAAO,MAA8C,CAAC;AAC5E,eAAO,MAAM,SAAS,EAAE,OAAO,MAAgD,CAAC;AAChF,eAAO,MAAM,YAAY,EAAE,OAAO,MAAmD,CAAC;AAGtF,oBAAY,QAAQ,CAAC,CAAC,IAAI;IACtB,CAAC,OAAO,CAAC,EAAG,SAAS,GAAG,CAAC,CAAC;IAC1B,CAAC,SAAS,CAAC,EAAG,MAAM,CAAC;IAGrB,CAAC,YAAY,CAAC,EAAG,CAAC,IAAI,EAAG,SAAS,GAAG,CAAC,EAAE,MAAM,EAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC3E,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAY,OAAO,oBAQvC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAY,OAAO,+BAQzC,CAAC;AAOF,oBAAY,eAAe,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAG,SAAS,GAAG,CAAC,CAAC;IAAC,MAAM,EAAG,MAAM,CAAA;CAAE,CAAC;AACzF,eAAO,MAAM,cAAc,qCAAuC,QAAQ,MAAM,CAAC,uBA4BhF,CAAC;AAOF,oBAAY,cAAc,CAAC,CAAC,SAAS,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,GACvD,CAAC,CAAC,SAAS,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,eAAO,MAAM,aAAa,uDAET,QAAQ,MAAM,CAAC,sBA2C3B,CAAC;AAKN,eAAO,MAAM,MAAM,2DAA8D,QAAQ,MAAM,CAAC,gBACzB,CAAC;AACxE,eAAO,MAAM,UAAU,gEAC8B,CAAC;AACtD,eAAO,MAAM,YAAY,sCAAwC,QAAQ,MAAM,CAAC,gBACI,CAAC;AAErF,eAAO,MAAM,SAAS,2CACwD,CAAA;AAC9E,eAAO,MAAM,SAAS,2CACuB,CAAC;AAC9C,eAAO,MAAM,OAAO,iEAGnB,CAAC;AACF,eAAO,MAAM,QAAQ,qCAAwC,KAAK,gBACL,CAAC"} | ||
| {"version":3,"file":"Loadable.d.ts","sourceRoot":"","sources":["../../src/interfaces/Loadable.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAIjE,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC;AAuB3B,MAAM,MAAM,MAAM,GAAG;IACjB,KAAK,EAAG,OAAO,CAAC;IAChB,OAAO,EAAG,OAAO,CAAC;IAClB,KAAK,EAAG,IAAI,GAAG,KAAK,CAAC;CACxB,CAAC;AAKF,eAAO,MAAM,OAAO,EAAE,OAAO,MAA8C,CAAC;AAC5E,eAAO,MAAM,SAAS,EAAE,OAAO,MAAgD,CAAC;AAChF,eAAO,MAAM,YAAY,EAAE,OAAO,MAAmD,CAAC;AAGtF,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACtB,CAAC,OAAO,CAAC,EAAG,SAAS,GAAG,CAAC,CAAC;IAC1B,CAAC,SAAS,CAAC,EAAG,MAAM,CAAC;IAGrB,CAAC,YAAY,CAAC,EAAG,CAAC,IAAI,EAAG,SAAS,GAAG,CAAC,EAAE,MAAM,EAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC3E,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAY,OAAO,oBAQvC,CAAC;AAEF,eAAO,MAAM,UAAU,UAAY,OAAO,+BAQzC,CAAC;AAOF,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAG,SAAS,GAAG,CAAC,CAAC;IAAC,MAAM,EAAG,MAAM,CAAA;CAAE,CAAC;AACzF,eAAO,MAAM,cAAc,qCAAuC,QAAQ,MAAM,CAAC,uBA4BhF,CAAC;AAOF,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,GACvD,CAAC,CAAC,SAAS,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,eAAO,MAAM,aAAa,uDAET,QAAQ,MAAM,CAAC,sBA2C3B,CAAC;AAKN,eAAO,MAAM,MAAM,2DAA8D,QAAQ,MAAM,CAAC,gBACzB,CAAC;AACxE,eAAO,MAAM,UAAU,gEAC8B,CAAC;AACtD,eAAO,MAAM,YAAY,sCAAwC,QAAQ,MAAM,CAAC,gBACI,CAAC;AAErF,eAAO,MAAM,SAAS,2CACwD,CAAA;AAC9E,eAAO,MAAM,SAAS,2CACuB,CAAC;AAC9C,eAAO,MAAM,OAAO,iEAGnB,CAAC;AACF,eAAO,MAAM,QAAQ,qCAAwC,KAAK,gBACL,CAAC"} |
| import type { Proxyable } from 'proxy-extend'; | ||
| import { Loadable } from './Loadable.js'; | ||
| export declare type Loader<T> = (resource: Loadable<T>) => Promise<Loadable<T>>; | ||
| export declare type LoaderCreator<T> = (...args: Array<unknown>) => Loader<T>; | ||
| export type Loader<T> = (resource: Loadable<T>) => Promise<Loadable<T>>; | ||
| export type LoaderCreator<T> = (...args: Array<unknown>) => Loader<T>; | ||
| export declare const resourceKey: unique symbol; | ||
@@ -10,3 +10,3 @@ export declare class LoadError<T> extends Error { | ||
| } | ||
| export declare type PromiseWithResource<T> = PromiseLike<Loadable<T>> & { | ||
| export type PromiseWithResource<T> = PromiseLike<Loadable<T>> & { | ||
| [resourceKey]: Loadable<T>; | ||
@@ -13,0 +13,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"Loader.d.ts","sourceRoot":"","sources":["../../src/interfaces/Loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAU,QAAQ,EAAwD,MAAM,eAAe,CAAC;AAKvG,oBAAY,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAGzE,oBAAY,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,EAAG,KAAK,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAGvE,eAAO,MAAM,WAAW,eAAmD,CAAC;AAI5E,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,KAAK;IACnC,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAEzB,MAAM,EAAG,OAAO,EAAE,QAAQ,EAAG,QAAQ,CAAC,CAAC,CAAC;CASvD;AAuFD,oBAAY,mBAAmB,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG;IAC5D,CAAC,WAAW,CAAC,EAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;CAE/B,CAAC;AAGF,eAAO,MAAM,WAAW,8GA4BnB,CAAC"} | ||
| {"version":3,"file":"Loader.d.ts","sourceRoot":"","sources":["../../src/interfaces/Loader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAU,QAAQ,EAAwD,MAAM,eAAe,CAAC;AAKvG,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAGzE,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,EAAG,KAAK,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAGvE,eAAO,MAAM,WAAW,eAAmD,CAAC;AAI5E,qBAAa,SAAS,CAAC,CAAC,CAAE,SAAQ,KAAK;IACnC,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAEzB,MAAM,EAAG,OAAO,EAAE,QAAQ,EAAG,QAAQ,CAAC,CAAC,CAAC;CASvD;AAuFD,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG;IAC5D,CAAC,WAAW,CAAC,EAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;CAE/B,CAAC;AAGF,eAAO,MAAM,WAAW,8GA4BnB,CAAC"} |
-16
| # Changelog | ||
| - v0.3.x | ||
| - Drop support for Node v10 | ||
| - Drop support for some older browsers (including all versions of IE) | ||
| - v0.2.x | ||
| - Rename LoadableSimple -> LoadableRecord | ||
| - Add type guards: `isStatus`, `isLoadable` | ||
| - v0.1.x | ||
| - Rewrite in TypeScript. | ||
| - v0.0.x | ||
| - Initial version. |
127335
7.36%1118
9.61%24
-4%262
-0.38%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated