@gorgonjs/gorgon 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../provider/memory.ts","../index.ts"],"sourcesContent":["import {IGorgonCacheProvider, GorgonPolicySanitized} from '../index';\n\ninterface IGorgonMemoryCacheProvider extends IGorgonCacheProvider {\n _clear: (key:string) => boolean;\n}\n\n// Created as a function to allow for multiple instances of the memory cache, if needed\nconst MemoryCacheCreator = ():IGorgonMemoryCacheProvider =>{\n\n const cache = {};\n const hOP = cache.hasOwnProperty;\n\n// Memory cache is about the simplist cache possible, use it as an example\n const memoryCache = {\n\n init: async() => {\n // This should be used to update the cache on boot,\n // memory cache will be blank on boot by default\n return;\n },\n\n get: async(key:string) => {\n\n if (hOP.call(cache, key) && cache[key].val) {\n // The cached item exists, return it\n return cache[key].val;\n } else {\n // The cached item does not exist reject\n return undefined;\n }\n\n },\n\n set: async(key:string, value:any, policy: GorgonPolicySanitized) => {\n\n // Clear in case it exists\n await memoryCache.clear(key);\n\n // Set a timemout to self-remove from the cache if in policy\n var to = false as boolean | number;\n\n if (policy && policy.expiry && policy.expiry > 0) {\n to = setTimeout(function() {\n memoryCache.clear(key);\n }, policy.expiry);\n }\n\n // Store the cached item\n cache[key] = {\n policy: policy,\n val: value,\n to: to,\n };\n\n return value;\n\n },\n\n keys: async() => {\n return Object.keys(cache);\n },\n\n clear: async(key?:string) => {\n\n // Clears a single key or complete clear on empty\n // Clear all items in the cache\n if (!key) {\n for (var i in cache) {\n memoryCache._clear(i);\n }\n return true;\n }\n\n return memoryCache._clear(key);\n },\n\n _clear: (key:string) => {\n // Clear a single item, making sure to remove the extra timeout\n if (hOP.call(cache, key)) {\n if (cache[key].to) {\n clearTimeout(cache[key].to);\n }\n\n cache[key] = null;\n delete cache[key];\n return true;\n }\n\n return false;\n },\n\n };\n\n return memoryCache;\n\n}\n\nexport default MemoryCacheCreator;\n","import MemoryCache from './provider/memory';\n\nexport type asyncFunction = () => Promise<any> | (() => any);\nexport type GorgonSettings = {\n debug: boolean;\n defaultProvider: string;\n retry: number;\n}\nexport type GorgonSettingsInput = {\n debug?: boolean;\n defaultProvider?: string;\n retry?: number;\n}\nexport type GorgonPolicy = {\n expiry: number | Date | false;\n provider: string;\n};\nexport type GorgonPolicyInput = GorgonPolicy | number | Date;\nexport type GorgonPolicySanitized = {\n expiry: number | false;\n provider: string;\n};\ntype GorgonCurrentTaskItem = Array<{\n res?: any;\n rej?: any;\n queued: Date;\n}>;\nexport interface IGorgonCacheProvider {\n init: () => Promise<void>;\n get: (key: string) => Promise<any>;\n set: <R>(key: string, value: R, policy: GorgonPolicySanitized) => Promise<R>;\n clear: (key?: string) => Promise<boolean>;\n keys: () => Promise<string[]>;\n}\n\nconst Gorgon = (() => {\n\n const currentTasks = {} as {[key: string]: GorgonCurrentTaskItem};\n const hOP = currentTasks.hasOwnProperty;\n\n const settings = {\n debug: false,\n defaultProvider: 'memory',\n retry: 5000,\n } as GorgonSettings;\n\n const policyMaker = function(incPolicy?: GorgonPolicyInput) {\n const outPolicy = {\n expiry: false,\n provider: settings.defaultProvider,\n } as GorgonPolicySanitized;\n\n // Blank policy, false, or no policy. lets store forever\n if (!incPolicy) {\n return outPolicy;\n }\n\n // Type is a full policy object\n if(incPolicy instanceof Date) {\n var d = new Date();\n\n outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);\n }else if (typeof incPolicy === 'object' && incPolicy.expiry) {\n if(incPolicy.expiry instanceof Date) {\n outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);\n }else{\n outPolicy.expiry = incPolicy.expiry;\n }\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if(typeof incPolicy === 'object') {\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if(typeof incPolicy === 'number') {\n outPolicy.expiry = incPolicy;\n }\n\n // Number is too small, negative or not a number\n outPolicy.expiry = outPolicy.expiry && outPolicy.expiry > 0 ? outPolicy.expiry : false;\n\n return outPolicy;\n };\n\n const gorgonCore = {\n\n // Providers available for use\n providers: {} as {[key: string]: IGorgonCacheProvider},\n\n // Allows for settings on the gorgon cache\n settings: (newSettings?: GorgonSettingsInput) => {\n if (!newSettings) {\n return settings;\n }\n\n Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing\n\n return settings;\n },\n\n // Add a provider\n addProvider: (name: string, provider:IGorgonCacheProvider) => {\n provider.init(); // Trigger for provider to clear any old cache items or any other cleanup\n gorgonCore.providers[name] = provider;\n },\n\n // Place an item into the cache\n put: async<R>(key:string, value:R, policy?: GorgonPolicyInput):Promise<R> => {\n policy = policyMaker(policy);\n var prov = gorgonCore.providers[policy.provider];\n\n return prov.set(key, value, policyMaker(policy));\n },\n\n // Clear one or all items in the cache\n clear: async(key: string, provider?: string) => {\n\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n // Clear a wildcard search of objects\n if (key && key.indexOf('*') > -1) {\n return prov.keys().then(function(keys) {\n var cacheMatchKeys = keys.filter(function(str) {\n return new RegExp('^' + key.split('*').join('.*') + '$').test(str);\n });\n\n var clearPromises = cacheMatchKeys.map(prov.clear);\n // Incase someone somehow used a wildcard in their cached key (don't do this)\n\n clearPromises.push(prov.clear(key));\n return Promise.all(clearPromises);\n });\n }\n\n // Not a special clear\n return prov.clear(key);\n\n },\n\n // Clear all keys/values in the cache\n clearAll: async(provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n return prov.clear();\n },\n\n // Allows you to instantly overwite a cache object\n overwrite: async(key:string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {\n\n try{\n const resolvedData = await asyncFunc();\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n return val;\n }catch (e) {\n throw e;\n }\n\n },\n\n // Allows you to get from the cache or pull from the promise\n get: async<R>(key:string, asyncFunc:() => R, policy?: GorgonPolicyInput):Promise<R> => {\n\n policy = policyMaker(policy);\n const prov = gorgonCore.providers[policy.provider];\n\n const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found\n\n // If we have a current value sent it out; cache hit!\n if(currentVal !== undefined) {\n if(settings.debug) {console.info('[Gorgon] Cache hit for key: ' + key, currentVal);}\n return currentVal;\n }\n\n // Are we currently already running this cache item?\n if (hOP.call(currentTasks, key) && Array.isArray(currentTasks[key]) && currentTasks[key].length > 0) {\n // Add to the current task, but ignore if any items is below retry anyway threshold\n var oldQueue = false;\n\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {\n oldQueue = true;\n }\n }\n\n // Add to the current queue\n if(!oldQueue) {\n if(settings.debug) {console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);}\n\n var concurent = new Promise(function(resolve: (value: R) => void, reject) {\n currentTasks[key].push({\n res: resolve,\n rej: reject,\n queued: new Date(),\n });\n });\n\n return concurent;\n }\n }else{\n // Add current task to list, this is the first one so the primary\n currentTasks[key] = [{queued: new Date()}];\n }\n\n try{\n if(settings.debug) {console.info('[Gorgon] Cache miss, resolving item for: ' + key);}\n\n // This is the primary item, lets resolve and push it out\n const resolvedData = await asyncFunc();\n\n if(settings.debug) {console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);}\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].res) {\n if(settings.debug) {console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);}\n\n currentTasks[key][i].res(val);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n return val;\n\n }catch (e) {\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].rej) {\n currentTasks[key][i].rej(e);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n throw e;\n }\n\n },\n\n\n };\n\n gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple\n\n return gorgonCore;\n\n})();\n\nexport {MemoryCache};\nexport default Gorgon;\n"],"names":["MemoryCacheCreator","cache","hOP","memoryCache","key","value","policy","to","Gorgon","currentTasks","settings","policyMaker","incPolicy","outPolicy","d","gorgonCore","newSettings","name","provider","prov","keys","cacheMatchKeys","str","clearPromises","asyncFunc","resolvedData","e","currentVal","oldQueue","i","concurent","resolve","reject","val","MemoryCache"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../provider/memory.ts","../index.ts"],"sourcesContent":["import {IGorgonCacheProvider, GorgonPolicySanitized} from '../index';\n\ninterface IGorgonMemoryCacheProvider extends IGorgonCacheProvider {\n _clear: (key:string) => boolean;\n}\n\n// Created as a function to allow for multiple instances of the memory cache, if needed\nconst MemoryCacheCreator = ():IGorgonMemoryCacheProvider =>{\n\n const cache = {};\n const hOP = cache.hasOwnProperty;\n\n// Memory cache is about the simplist cache possible, use it as an example\n const memoryCache = {\n\n init: async() => {\n // This should be used to update the cache on boot,\n // memory cache will be blank on boot by default\n return;\n },\n\n get: async(key:string) => {\n\n if (hOP.call(cache, key) && cache[key].val) {\n // The cached item exists, return it\n return cache[key].val;\n } else {\n // The cached item does not exist reject\n return undefined;\n }\n\n },\n\n set: async(key:string, value:any, policy: GorgonPolicySanitized) => {\n\n // Clear in case it exists\n await memoryCache.clear(key);\n\n // Set a timemout to self-remove from the cache if in policy\n var to = false as boolean | number;\n\n if (policy && policy.expiry && policy.expiry > 0) {\n to = setTimeout(function() {\n memoryCache.clear(key);\n }, policy.expiry);\n }\n\n // Store the cached item\n cache[key] = {\n policy: policy,\n val: value,\n to: to,\n };\n\n return value;\n\n },\n\n keys: async() => {\n return Object.keys(cache);\n },\n\n clear: async(key?:string) => {\n\n // Clears a single key or complete clear on empty\n // Clear all items in the cache\n if (!key) {\n for (var i in cache) {\n memoryCache._clear(i);\n }\n return true;\n }\n\n return memoryCache._clear(key);\n },\n\n _clear: (key:string) => {\n // Clear a single item, making sure to remove the extra timeout\n if (hOP.call(cache, key)) {\n if (cache[key].to) {\n clearTimeout(cache[key].to);\n }\n\n cache[key] = null;\n delete cache[key];\n return true;\n }\n\n return false;\n },\n\n };\n\n return memoryCache;\n\n}\n\nexport default MemoryCacheCreator;\n","import MemoryCache from './provider/memory';\n\nexport type asyncFunction = () => Promise<any> | (() => any);\nexport type GorgonHookKey =\n | 'settings'\n | 'addProvider'\n | 'put'\n | 'clear'\n | 'clearAll'\n | 'overwrite'\n | 'get'\n | 'valueError';\nexport type GorgonHook = (key: GorgonHookKey, input?: any, output?: any) => void;\nexport type GorgonSettings = {\n debug: boolean;\n defaultProvider: string;\n retry: number;\n};\nexport type GorgonSettingsInput = {\n debug?: boolean;\n defaultProvider?: string;\n retry?: number;\n};\nexport type GorgonPolicy = {\n expiry: number | Date | false;\n provider: string;\n};\nexport type GorgonPolicyInput = GorgonPolicy | number | Date;\nexport type GorgonPolicySanitized = {\n expiry: number | false;\n provider: string;\n};\ntype GorgonCurrentTaskItem = Array<{\n res?: any;\n rej?: any;\n queued: Date;\n}>;\nexport interface IGorgonCacheProvider {\n init: () => Promise<void>;\n get: (key: string) => Promise<any>;\n set: <R>(key: string, value: R, policy: GorgonPolicySanitized) => Promise<R>;\n clear: (key?: string) => Promise<boolean>;\n keys: () => Promise<string[]>;\n}\n\nconst Gorgon = (() => {\n const currentTasks = {} as { [key: string]: GorgonCurrentTaskItem };\n const hOP = currentTasks.hasOwnProperty;\n\n const settings = {\n debug: false,\n defaultProvider: 'memory',\n retry: 5000,\n } as GorgonSettings;\n\n const policyMaker = function (incPolicy?: GorgonPolicyInput) {\n const outPolicy = {\n expiry: false,\n provider: settings.defaultProvider,\n } as GorgonPolicySanitized;\n\n // Blank policy, false, or no policy. lets store forever\n if (!incPolicy) {\n return outPolicy;\n }\n\n // Type is a full policy object\n if (incPolicy instanceof Date) {\n var d = new Date();\n\n outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);\n } else if (typeof incPolicy === 'object' && incPolicy.expiry) {\n if (incPolicy.expiry instanceof Date) {\n outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);\n } else {\n outPolicy.expiry = incPolicy.expiry;\n }\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if (typeof incPolicy === 'object') {\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if (typeof incPolicy === 'number') {\n outPolicy.expiry = incPolicy;\n }\n\n // Number is too small, negative or not a number\n outPolicy.expiry = outPolicy.expiry && outPolicy.expiry > 0 ? outPolicy.expiry : false;\n\n return outPolicy;\n };\n\n const gorgonCore = {\n // Providers available for use\n providers: {} as { [key: string]: IGorgonCacheProvider },\n\n // Hooks\n hooks: {} as { [key: string]: Array<GorgonHook> },\n\n _callHooks: (key: GorgonHookKey, input?: any, output?: any) => {\n if (hOP.call(gorgonCore.hooks, key)) {\n for (var i in gorgonCore.hooks[key]) {\n if (typeof gorgonCore.hooks[key][i] === 'function') {\n try {\n gorgonCore.hooks[key][i](key, input, output);\n } catch (e) {\n console.error('[Gorgon] Hook error for hook: ' + key, e);\n }\n }\n }\n }\n },\n\n // Allows for settings on the gorgon cache\n settings: (newSettings?: GorgonSettingsInput) => {\n if (!newSettings) {\n return settings;\n }\n\n Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing\n\n gorgonCore._callHooks('settings', newSettings, settings);\n\n return settings;\n },\n\n // add a hook or array of hooks\n addHook: (key: GorgonHookKey, hook: GorgonHook | Array<GorgonHook>) => {\n if (!hOP.call(gorgonCore.hooks, key)) {\n gorgonCore.hooks[key] = [];\n }\n\n if (Array.isArray(hook)) {\n gorgonCore.hooks[key] = gorgonCore.hooks[key].concat(hook);\n } else {\n gorgonCore.hooks[key].push(hook);\n }\n },\n\n // Add a provider\n addProvider: (name: string, provider: IGorgonCacheProvider) => {\n provider.init(); // Trigger for provider to clear any old cache items or any other cleanup\n gorgonCore.providers[name] = provider;\n\n gorgonCore._callHooks('addProvider', { name, provider });\n },\n\n // Place an item into the cache\n put: async <R>(key: string, value: R, policy?: GorgonPolicyInput): Promise<R> => {\n policy = policyMaker(policy);\n var prov = gorgonCore.providers[policy.provider];\n\n gorgonCore._callHooks('put', { key, value, policy }, value);\n\n return prov.set(key, value, policyMaker(policy));\n },\n\n // Clear one or all items in the cache\n clear: async (key: string, provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n gorgonCore._callHooks('clear', { key, provider });\n\n // Clear a wildcard search of objects\n if (key && key.indexOf('*') > -1) {\n return prov.keys().then(function (keys) {\n var cacheMatchKeys = keys.filter(function (str) {\n return new RegExp('^' + key.split('*').join('.*') + '$').test(str);\n });\n\n var clearPromises = cacheMatchKeys.map(prov.clear);\n // Incase someone somehow used a wildcard in their cached key (don't do this)\n\n clearPromises.push(prov.clear(key));\n return Promise.all(clearPromises);\n });\n }\n\n // Not a special clear\n return prov.clear(key);\n },\n\n // Clear all keys/values in the cache\n clearAll: async (provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n gorgonCore._callHooks('clearAll', { provider });\n\n return prov.clear();\n },\n\n // Allows you to instantly overwite a cache object\n overwrite: async (key: string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {\n try {\n const resolvedData = await asyncFunc();\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n gorgonCore._callHooks('overwrite', { key, asyncFunc, policy }, val);\n\n return val;\n } catch (e) {\n throw e;\n }\n },\n\n // Allows you to get from the cache or pull from the promise\n get: async <R>(key: string, asyncFunc: () => R, policy?: GorgonPolicyInput): Promise<R> => {\n policy = policyMaker(policy);\n const prov = gorgonCore.providers[policy.provider];\n\n const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found\n\n // If we have a current value sent it out; cache hit!\n if (currentVal !== undefined) {\n if (settings.debug) {\n console.info('[Gorgon] Cache hit for key: ' + key, currentVal);\n }\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: true, queued: false }, currentVal);\n\n return currentVal;\n }\n\n // Are we currently already running this cache item?\n if (hOP.call(currentTasks, key) && Array.isArray(currentTasks[key]) && currentTasks[key].length > 0) {\n // Add to the current task, but ignore if any items is below retry anyway threshold\n var oldQueue = false;\n\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {\n oldQueue = true;\n }\n }\n\n // Add to the current queue\n if (!oldQueue) {\n if (settings.debug) {\n console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);\n }\n\n var concurent = new Promise(function (resolve: (value: R) => void, reject) {\n currentTasks[key].push({\n res: resolve,\n rej: reject,\n queued: new Date(),\n });\n });\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: true }, concurent);\n\n return concurent;\n }\n } else {\n // Add current task to list, this is the first one so the primary\n currentTasks[key] = [{ queued: new Date() }];\n }\n\n try {\n if (settings.debug) {\n console.info('[Gorgon] Cache miss, resolving item for: ' + key);\n }\n\n // This is the primary item\n const resolver = asyncFunc();\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: false }, resolver);\n\n // wait for it to finish then push it out\n const resolvedData = await resolver;\n\n if (settings.debug) {\n console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);\n }\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].res) {\n if (settings.debug) {\n console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);\n }\n\n currentTasks[key][i].res(val);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n return val;\n } catch (e) {\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].rej) {\n currentTasks[key][i].rej(e);\n }\n }\n\n gorgonCore._callHooks('valueError', { key, asyncFunc, policy, cacheHit: false, queued: false }, e);\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n throw e;\n }\n },\n };\n\n gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple\n\n return gorgonCore;\n})();\n\nexport { MemoryCache };\nexport default Gorgon;\n"],"names":["MemoryCacheCreator","cache","hOP","memoryCache","key","value","policy","to","i","Gorgon","currentTasks","settings","policyMaker","incPolicy","outPolicy","d","gorgonCore","input","output","e","newSettings","hook","name","provider","prov","keys","cacheMatchKeys","str","clearPromises","asyncFunc","resolvedData","val","currentVal","oldQueue","concurent","resolve","reject","resolver","MemoryCache"],"mappings":"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"}
package/index.ts CHANGED
@@ -1,16 +1,26 @@
1
1
  import MemoryCache from './provider/memory';
2
2
 
3
3
  export type asyncFunction = () => Promise<any> | (() => any);
4
+ export type GorgonHookKey =
5
+ | 'settings'
6
+ | 'addProvider'
7
+ | 'put'
8
+ | 'clear'
9
+ | 'clearAll'
10
+ | 'overwrite'
11
+ | 'get'
12
+ | 'valueError';
13
+ export type GorgonHook = (key: GorgonHookKey, input?: any, output?: any) => void;
4
14
  export type GorgonSettings = {
5
15
  debug: boolean;
6
16
  defaultProvider: string;
7
17
  retry: number;
8
- }
18
+ };
9
19
  export type GorgonSettingsInput = {
10
20
  debug?: boolean;
11
21
  defaultProvider?: string;
12
22
  retry?: number;
13
- }
23
+ };
14
24
  export type GorgonPolicy = {
15
25
  expiry: number | Date | false;
16
26
  provider: string;
@@ -34,8 +44,7 @@ export interface IGorgonCacheProvider {
34
44
  }
35
45
 
36
46
  const Gorgon = (() => {
37
-
38
- const currentTasks = {} as {[key: string]: GorgonCurrentTaskItem};
47
+ const currentTasks = {} as { [key: string]: GorgonCurrentTaskItem };
39
48
  const hOP = currentTasks.hasOwnProperty;
40
49
 
41
50
  const settings = {
@@ -44,7 +53,7 @@ const Gorgon = (() => {
44
53
  retry: 5000,
45
54
  } as GorgonSettings;
46
55
 
47
- const policyMaker = function(incPolicy?: GorgonPolicyInput) {
56
+ const policyMaker = function (incPolicy?: GorgonPolicyInput) {
48
57
  const outPolicy = {
49
58
  expiry: false,
50
59
  provider: settings.defaultProvider,
@@ -56,20 +65,20 @@ const Gorgon = (() => {
56
65
  }
57
66
 
58
67
  // Type is a full policy object
59
- if(incPolicy instanceof Date) {
68
+ if (incPolicy instanceof Date) {
60
69
  var d = new Date();
61
70
 
62
71
  outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);
63
- }else if (typeof incPolicy === 'object' && incPolicy.expiry) {
64
- if(incPolicy.expiry instanceof Date) {
72
+ } else if (typeof incPolicy === 'object' && incPolicy.expiry) {
73
+ if (incPolicy.expiry instanceof Date) {
65
74
  outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);
66
- }else{
75
+ } else {
67
76
  outPolicy.expiry = incPolicy.expiry;
68
77
  }
69
78
  outPolicy.provider = incPolicy.provider || outPolicy.provider;
70
- } else if(typeof incPolicy === 'object') {
79
+ } else if (typeof incPolicy === 'object') {
71
80
  outPolicy.provider = incPolicy.provider || outPolicy.provider;
72
- } else if(typeof incPolicy === 'number') {
81
+ } else if (typeof incPolicy === 'number') {
73
82
  outPolicy.expiry = incPolicy;
74
83
  }
75
84
 
@@ -80,9 +89,25 @@ const Gorgon = (() => {
80
89
  };
81
90
 
82
91
  const gorgonCore = {
83
-
84
92
  // Providers available for use
85
- providers: {} as {[key: string]: IGorgonCacheProvider},
93
+ providers: {} as { [key: string]: IGorgonCacheProvider },
94
+
95
+ // Hooks
96
+ hooks: {} as { [key: string]: Array<GorgonHook> },
97
+
98
+ _callHooks: (key: GorgonHookKey, input?: any, output?: any) => {
99
+ if (hOP.call(gorgonCore.hooks, key)) {
100
+ for (var i in gorgonCore.hooks[key]) {
101
+ if (typeof gorgonCore.hooks[key][i] === 'function') {
102
+ try {
103
+ gorgonCore.hooks[key][i](key, input, output);
104
+ } catch (e) {
105
+ console.error('[Gorgon] Hook error for hook: ' + key, e);
106
+ }
107
+ }
108
+ }
109
+ }
110
+ },
86
111
 
87
112
  // Allows for settings on the gorgon cache
88
113
  settings: (newSettings?: GorgonSettingsInput) => {
@@ -92,32 +117,52 @@ const Gorgon = (() => {
92
117
 
93
118
  Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing
94
119
 
120
+ gorgonCore._callHooks('settings', newSettings, settings);
121
+
95
122
  return settings;
96
123
  },
97
124
 
125
+ // add a hook or array of hooks
126
+ addHook: (key: GorgonHookKey, hook: GorgonHook | Array<GorgonHook>) => {
127
+ if (!hOP.call(gorgonCore.hooks, key)) {
128
+ gorgonCore.hooks[key] = [];
129
+ }
130
+
131
+ if (Array.isArray(hook)) {
132
+ gorgonCore.hooks[key] = gorgonCore.hooks[key].concat(hook);
133
+ } else {
134
+ gorgonCore.hooks[key].push(hook);
135
+ }
136
+ },
137
+
98
138
  // Add a provider
99
- addProvider: (name: string, provider:IGorgonCacheProvider) => {
139
+ addProvider: (name: string, provider: IGorgonCacheProvider) => {
100
140
  provider.init(); // Trigger for provider to clear any old cache items or any other cleanup
101
141
  gorgonCore.providers[name] = provider;
142
+
143
+ gorgonCore._callHooks('addProvider', { name, provider });
102
144
  },
103
145
 
104
146
  // Place an item into the cache
105
- put: async<R>(key:string, value:R, policy?: GorgonPolicyInput):Promise<R> => {
147
+ put: async <R>(key: string, value: R, policy?: GorgonPolicyInput): Promise<R> => {
106
148
  policy = policyMaker(policy);
107
149
  var prov = gorgonCore.providers[policy.provider];
108
150
 
151
+ gorgonCore._callHooks('put', { key, value, policy }, value);
152
+
109
153
  return prov.set(key, value, policyMaker(policy));
110
154
  },
111
155
 
112
- // Clear one or all items in the cache
113
- clear: async(key: string, provider?: string) => {
114
-
156
+ // Clear one or all items in the cache
157
+ clear: async (key: string, provider?: string) => {
115
158
  var prov = gorgonCore.providers[provider || settings.defaultProvider];
116
159
 
160
+ gorgonCore._callHooks('clear', { key, provider });
161
+
117
162
  // Clear a wildcard search of objects
118
163
  if (key && key.indexOf('*') > -1) {
119
- return prov.keys().then(function(keys) {
120
- var cacheMatchKeys = keys.filter(function(str) {
164
+ return prov.keys().then(function (keys) {
165
+ var cacheMatchKeys = keys.filter(function (str) {
121
166
  return new RegExp('^' + key.split('*').join('.*') + '$').test(str);
122
167
  });
123
168
 
@@ -131,42 +176,47 @@ const Gorgon = (() => {
131
176
 
132
177
  // Not a special clear
133
178
  return prov.clear(key);
134
-
135
179
  },
136
180
 
137
181
  // Clear all keys/values in the cache
138
- clearAll: async(provider?: string) => {
182
+ clearAll: async (provider?: string) => {
139
183
  var prov = gorgonCore.providers[provider || settings.defaultProvider];
140
184
 
185
+ gorgonCore._callHooks('clearAll', { provider });
186
+
141
187
  return prov.clear();
142
188
  },
143
189
 
144
190
  // Allows you to instantly overwite a cache object
145
- overwrite: async(key:string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {
146
-
147
- try{
191
+ overwrite: async (key: string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {
192
+ try {
148
193
  const resolvedData = await asyncFunc();
149
194
 
150
195
  const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));
151
196
 
197
+ gorgonCore._callHooks('overwrite', { key, asyncFunc, policy }, val);
198
+
152
199
  return val;
153
- }catch (e) {
200
+ } catch (e) {
154
201
  throw e;
155
202
  }
156
-
157
203
  },
158
204
 
159
205
  // Allows you to get from the cache or pull from the promise
160
- get: async<R>(key:string, asyncFunc:() => R, policy?: GorgonPolicyInput):Promise<R> => {
161
-
206
+ get: async <R>(key: string, asyncFunc: () => R, policy?: GorgonPolicyInput): Promise<R> => {
162
207
  policy = policyMaker(policy);
163
208
  const prov = gorgonCore.providers[policy.provider];
164
209
 
165
210
  const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found
166
211
 
167
212
  // If we have a current value sent it out; cache hit!
168
- if(currentVal !== undefined) {
169
- if(settings.debug) {console.info('[Gorgon] Cache hit for key: ' + key, currentVal);}
213
+ if (currentVal !== undefined) {
214
+ if (settings.debug) {
215
+ console.info('[Gorgon] Cache hit for key: ' + key, currentVal);
216
+ }
217
+
218
+ gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: true, queued: false }, currentVal);
219
+
170
220
  return currentVal;
171
221
  }
172
222
 
@@ -176,16 +226,18 @@ const Gorgon = (() => {
176
226
  var oldQueue = false;
177
227
 
178
228
  for (var i in currentTasks[key]) {
179
- if(currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {
229
+ if (currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {
180
230
  oldQueue = true;
181
231
  }
182
232
  }
183
233
 
184
234
  // Add to the current queue
185
- if(!oldQueue) {
186
- if(settings.debug) {console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);}
235
+ if (!oldQueue) {
236
+ if (settings.debug) {
237
+ console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);
238
+ }
187
239
 
188
- var concurent = new Promise(function(resolve: (value: R) => void, reject) {
240
+ var concurent = new Promise(function (resolve: (value: R) => void, reject) {
189
241
  currentTasks[key].push({
190
242
  res: resolve,
191
243
  rej: reject,
@@ -193,27 +245,40 @@ const Gorgon = (() => {
193
245
  });
194
246
  });
195
247
 
248
+ gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: true }, concurent);
249
+
196
250
  return concurent;
197
251
  }
198
- }else{
252
+ } else {
199
253
  // Add current task to list, this is the first one so the primary
200
- currentTasks[key] = [{queued: new Date()}];
254
+ currentTasks[key] = [{ queued: new Date() }];
201
255
  }
202
256
 
203
- try{
204
- if(settings.debug) {console.info('[Gorgon] Cache miss, resolving item for: ' + key);}
257
+ try {
258
+ if (settings.debug) {
259
+ console.info('[Gorgon] Cache miss, resolving item for: ' + key);
260
+ }
205
261
 
206
- // This is the primary item, lets resolve and push it out
207
- const resolvedData = await asyncFunc();
262
+ // This is the primary item
263
+ const resolver = asyncFunc();
264
+
265
+ gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: false }, resolver);
208
266
 
209
- if(settings.debug) {console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);}
267
+ // wait for it to finish then push it out
268
+ const resolvedData = await resolver;
269
+
270
+ if (settings.debug) {
271
+ console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);
272
+ }
210
273
 
211
274
  const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));
212
275
 
213
276
  if (hOP.call(currentTasks, key)) {
214
277
  for (var i in currentTasks[key]) {
215
- if(currentTasks[key][i].res) {
216
- if(settings.debug) {console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);}
278
+ if (currentTasks[key][i].res) {
279
+ if (settings.debug) {
280
+ console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);
281
+ }
217
282
 
218
283
  currentTasks[key][i].res(val);
219
284
  }
@@ -224,32 +289,29 @@ const Gorgon = (() => {
224
289
  }
225
290
 
226
291
  return val;
227
-
228
- }catch (e) {
292
+ } catch (e) {
229
293
  if (hOP.call(currentTasks, key)) {
230
294
  for (var i in currentTasks[key]) {
231
- if(currentTasks[key][i].rej) {
295
+ if (currentTasks[key][i].rej) {
232
296
  currentTasks[key][i].rej(e);
233
297
  }
234
298
  }
235
299
 
300
+ gorgonCore._callHooks('valueError', { key, asyncFunc, policy, cacheHit: false, queued: false }, e);
301
+
236
302
  currentTasks[key] = [];
237
303
  delete currentTasks[key];
238
304
  }
239
305
 
240
306
  throw e;
241
307
  }
242
-
243
308
  },
244
-
245
-
246
309
  };
247
310
 
248
311
  gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple
249
312
 
250
313
  return gorgonCore;
251
-
252
314
  })();
253
315
 
254
- export {MemoryCache};
316
+ export { MemoryCache };
255
317
  export default Gorgon;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorgonjs/gorgon",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "A simple caching library for async functions",
5
5
  "homepage": "https://gorgonjs.dev",
6
6
  "main": "./dist/index.umd.js",
@@ -38,6 +38,7 @@
38
38
  "@typescript-eslint/eslint-plugin": "^6.0.0",
39
39
  "@typescript-eslint/parser": "^6.0.0",
40
40
  "@vitest/coverage-c8": "^0.25.0",
41
+ "@vitest/coverage-v8": "^0.34.3",
41
42
  "eslint": "^8.45.0",
42
43
  "jest": "^27.5.1",
43
44
  "typescript": "^5.1.6",