| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							|  |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var object = require('ig-object') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	makeIndex(<name>[, <options>])
 | 
					
						
							|  |  |  | //	makeIndex(<name>, <generate>[, <options>])
 | 
					
						
							|  |  |  | //		-> <index-handler> 
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | //	Call/get
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | //	<index-handler>()
 | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Call the index handler method...
 | 
					
						
							|  |  |  | //	<index-handler>('__call__', ..)
 | 
					
						
							|  |  |  | //		-> ...
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Get merged data (cached)
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | //	<index-handler>('get')
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | // 		NOTE: when a getter is pending (promise), all consecutive calls 
 | 
					
						
							|  |  |  | // 			will resolve the original getter return value...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Get sync or cached result and do "lazy" background update...
 | 
					
						
							|  |  |  | //	<index-handler>('lazy')
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | // 		NOTE: if <index-handler>(..) is synchronous, this will wait till
 | 
					
						
							|  |  |  | // 			it returns and will return the result.
 | 
					
						
							|  |  |  | // 		NOTE: 'lazy' mode is generally faster as it does all the checks and 
 | 
					
						
							|  |  |  | // 			updating (if needed) in a background promise, but can return 
 | 
					
						
							|  |  |  | // 			outdated cached results.
 | 
					
						
							|  |  |  | // 		NOTE: as a side-effect this avoids returning promises if a cached 
 | 
					
						
							|  |  |  | // 			value is available. i.e. a promise is returned only when 
 | 
					
						
							|  |  |  | // 			getting/generating a value for the first time.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Get cached result and trigger a background update...
 | 
					
						
							|  |  |  | //	<index-handler>('cached')
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //		-> undefined
 | 
					
						
							|  |  |  | //		NOTE: this is like 'lazy' but will not wait for <index-handler>)(..)
 | 
					
						
							|  |  |  | //			to return, making it even faster but as a trade off it will
 | 
					
						
							|  |  |  | //			return the cached and possibly outdated result even if 
 | 
					
						
							|  |  |  | //			<index-handler>(..) is synchronous.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Get local data (uncached)...
 | 
					
						
							|  |  |  | //	<index-handler>('local')
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Clear cache...
 | 
					
						
							|  |  |  | //	<index-handler>('clear')
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Reset cache (clear then get)...
 | 
					
						
							|  |  |  | //	<index-handler>('reset')
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Get index status...
 | 
					
						
							|  |  |  | //	<index-handler>('status')
 | 
					
						
							|  |  |  | //		-> 'empty'
 | 
					
						
							|  |  |  | //		-> 'pending'
 | 
					
						
							|  |  |  | //		-> 'cached'
 | 
					
						
							|  |  |  | //		-> 'outdated'
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	Run custom action...
 | 
					
						
							|  |  |  | //	<index-handler>(<action-name>), ...)
 | 
					
						
							|  |  |  | //		-> <data>
 | 
					
						
							|  |  |  | //		-> <promise>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: the main differences between the 'get', 'lazy' and 'cached' actions:
 | 
					
						
							|  |  |  | // 		'get'
 | 
					
						
							|  |  |  | // 			generate/merge are all sync/async as defined
 | 
					
						
							|  |  |  | // 			when cached value available validate and return either the cached value or generate
 | 
					
						
							|  |  |  | // 		'lazy'
 | 
					
						
							|  |  |  | // 			XXX
 | 
					
						
							|  |  |  | // 		'cached'
 | 
					
						
							|  |  |  | // 			call get in background
 | 
					
						
							|  |  |  | // 			return cached value or undefined
 | 
					
						
							|  |  |  | // 	  
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Special methods:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Special method to generate local <data>...
 | 
					
						
							|  |  |  | // 	.__<name>__()
 | 
					
						
							|  |  |  | // 		-> <data>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Merge local data with other sources...
 | 
					
						
							|  |  |  | // 	.__<name>_merge__(<data>)
 | 
					
						
							|  |  |  | // 		-> <data>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Test if cache is valid...
 | 
					
						
							|  |  |  | // 	.__<name>_isvalid__(<timestamp>)
 | 
					
						
							|  |  |  | // 		-> <bool>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Handle custom action...
 | 
					
						
							|  |  |  | // 	.__<name>_<action-name>__(<data>. ...)
 | 
					
						
							|  |  |  | // 		-> <data>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Special attributes:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Cached data...
 | 
					
						
							|  |  |  | // 	.__<name>_cache / .<name>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Modification time...
 | 
					
						
							|  |  |  | // 	.__<name>_modified
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Pending generator promise...
 | 
					
						
							|  |  |  | // 	.__<name>_promise
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Options format:
 | 
					
						
							|  |  |  | // 	{
 | 
					
						
							|  |  |  | // 		// XXX
 | 
					
						
							|  |  |  | // 		attr: false 
 | 
					
						
							|  |  |  | // 			| true 
 | 
					
						
							|  |  |  | // 			| <name>,
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// list of dependencies that when changed will trigger a cache 
 | 
					
						
							|  |  |  | // 		// drop on current index...
 | 
					
						
							|  |  |  | // 		// NOTE: dependency checking is done via .modified time, if value
 | 
					
						
							|  |  |  | // 		//		is changed manually and not via an action then the system
 | 
					
						
							|  |  |  | // 		//		will not catch the change.
 | 
					
						
							|  |  |  | // 		depends: [ 
 | 
					
						
							|  |  |  | // 			<index-name>, 
 | 
					
						
							|  |  |  | // 			... 
 | 
					
						
							|  |  |  | // 		],
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// custom action...
 | 
					
						
							|  |  |  | // 		// NOTE: this is the same as defining .__<name>_<action-name>__(..)
 | 
					
						
							|  |  |  | // 		//		method...
 | 
					
						
							|  |  |  | // 		<action-name>: <func>,
 | 
					
						
							|  |  |  | // 	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX do we separate internal methods and actions???
 | 
					
						
							|  |  |  | // 		i.e. __<name>_merge__(..) / __<name>_isvalid__(..) and the rest...
 | 
					
						
							|  |  |  | var makeIndex =  | 
					
						
							|  |  |  | module.makeIndex = | 
					
						
							|  |  |  | function(name, generate, options={}){ | 
					
						
							|  |  |  | 	// makeIndex(<name>, <options>)
 | 
					
						
							|  |  |  | 	if(generate  | 
					
						
							|  |  |  | 			&& typeof(generate) != 'function'){ | 
					
						
							|  |  |  | 		options = generate  | 
					
						
							|  |  |  | 		generate = options.generate } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// attr names...
 | 
					
						
							|  |  |  | 	var cache =  | 
					
						
							|  |  |  | 		typeof(options.attr) == 'string' ? | 
					
						
							|  |  |  | 			options.attr | 
					
						
							|  |  |  | 		// XXX revise default...
 | 
					
						
							|  |  |  | 		: !!options.attr ? | 
					
						
							|  |  |  | 			name | 
					
						
							|  |  |  | 		: `__${name}_cache` | 
					
						
							|  |  |  | 	var modified = `__${name}_modified` | 
					
						
							|  |  |  | 	var promise = `__${name}_promise` | 
					
						
							|  |  |  | 	var test = `__${name}_isvalid__` | 
					
						
							|  |  |  | 	var merge = `__${name}_merge__` | 
					
						
							|  |  |  | 	var special = `__${name}__` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set modified time...
 | 
					
						
							|  |  |  | 	var _stamp = function(that, res){ | 
					
						
							|  |  |  | 		res instanceof Promise ? | 
					
						
							|  |  |  | 			res.then(function(){ | 
					
						
							|  |  |  | 				that[modified] = Date.now() }) | 
					
						
							|  |  |  | 			: (that[modified] = Date.now()) | 
					
						
							|  |  |  | 		return res } | 
					
						
							|  |  |  | 	// make local cache...
 | 
					
						
							|  |  |  | 	var _make = function(that){ | 
					
						
							|  |  |  | 		return that[special] != null ? | 
					
						
							|  |  |  | 				that[special]() | 
					
						
							|  |  |  | 				: (generate  | 
					
						
							|  |  |  | 					&& generate.call(that)) } | 
					
						
							|  |  |  | 	var _smake = function(that){ | 
					
						
							|  |  |  | 		return _stamp(that, _make(that)) } | 
					
						
							|  |  |  | 	// unwrap a promised value into cache...
 | 
					
						
							|  |  |  | 	var _await = function(obj, val){ | 
					
						
							|  |  |  | 		if(val instanceof Promise){ | 
					
						
							|  |  |  | 			// NOTE: this avoids a race condition when a getter is called
 | 
					
						
							|  |  |  | 			// 		while a previous getter is still pending...
 | 
					
						
							|  |  |  | 			if(obj[promise] == null){ | 
					
						
							|  |  |  | 				obj[promise] = val | 
					
						
							|  |  |  | 				val.then( | 
					
						
							|  |  |  | 					function(value){ | 
					
						
							|  |  |  | 						delete obj[promise] | 
					
						
							|  |  |  | 						obj[cache] = value }, | 
					
						
							|  |  |  | 					function(err){ | 
					
						
							|  |  |  | 						// XXX should we report this???
 | 
					
						
							|  |  |  | 						delete obj[promise] }) } | 
					
						
							|  |  |  | 			val = obj[promise] } | 
					
						
							|  |  |  | 		return val } | 
					
						
							|  |  |  | 	var _deferred = async function(obj, ...args){ | 
					
						
							|  |  |  | 		return meth.call(obj, ...args) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// build the method...
 | 
					
						
							|  |  |  | 	var meth | 
					
						
							|  |  |  | 	return (meth = Object.assign( | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | 		function(action, ...args){ | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | 			action = action === undefined ? | 
					
						
							|  |  |  | 				('__call__' in options ? | 
					
						
							|  |  |  | 					'__call__' | 
					
						
							|  |  |  | 					: 'get') | 
					
						
							|  |  |  | 				: action | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 			// action: status...
 | 
					
						
							|  |  |  | 			if(action == 'status'){ | 
					
						
							|  |  |  | 				if(this[cache] instanceof Promise){ | 
					
						
							|  |  |  | 					return 'pending' } | 
					
						
							|  |  |  | 				if(cache in this){ | 
					
						
							|  |  |  | 					var cur = this[modified] | 
					
						
							|  |  |  | 					// user test...
 | 
					
						
							|  |  |  | 					if(test in this  | 
					
						
							|  |  |  | 							&& !this[test](cur)){ | 
					
						
							|  |  |  | 						return 'outdated' | 
					
						
							|  |  |  | 					// check dependencies...
 | 
					
						
							|  |  |  | 					} else if(meth.options.depends){ | 
					
						
							|  |  |  | 						for(var dep of meth.options.depends){ | 
					
						
							|  |  |  | 							if(this[`__${this[dep].index}_modified`] > cur){ | 
					
						
							|  |  |  | 								return 'outdated' } } } | 
					
						
							|  |  |  | 					return 'cached' } | 
					
						
							|  |  |  | 				return 'empty' } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// action: lazy...
 | 
					
						
							|  |  |  | 			if(action == 'lazy'){ | 
					
						
							|  |  |  | 				if(this[cache] instanceof Promise){ | 
					
						
							|  |  |  | 					return this[cache] } | 
					
						
							|  |  |  | 				var res = meth.call(this, 'get') | 
					
						
							|  |  |  | 				return (this[cache] | 
					
						
							|  |  |  | 						&& res instanceof Promise) ?  | 
					
						
							|  |  |  | 					this[cache] | 
					
						
							|  |  |  | 					: res } | 
					
						
							|  |  |  | 			// action: cached...
 | 
					
						
							|  |  |  | 			if(action == 'cached'){ | 
					
						
							|  |  |  | 				_deferred(this, 'get') | 
					
						
							|  |  |  | 				return this[cache] } | 
					
						
							|  |  |  | 			// action: local...
 | 
					
						
							|  |  |  | 			// NOTE: this is intentionally not cached...
 | 
					
						
							|  |  |  | 			if(action == 'local'){ | 
					
						
							|  |  |  | 				return _make(this) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// action: clear/reset...
 | 
					
						
							|  |  |  | 			if(action == 'clear'  | 
					
						
							|  |  |  | 					|| action == 'reset'){ | 
					
						
							| 
									
										
										
										
											2022-11-06 22:38:34 +03:00
										 |  |  | 				delete this[cache]  | 
					
						
							|  |  |  | 				'reset' in options | 
					
						
							|  |  |  | 					&& options['reset'].call(this, null, name) } | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 			if(action == 'clear'){ | 
					
						
							|  |  |  | 				return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// validate cache...
 | 
					
						
							|  |  |  | 			if(cache in this | 
					
						
							|  |  |  | 					&& meth.call(this, 'status') == 'outdated'){ | 
					
						
							|  |  |  | 				delete this[cache] } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// action: other...
 | 
					
						
							|  |  |  | 			if(action != 'get'  | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | 					&& action != '__call__' | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 					&& action != 'reset'){ | 
					
						
							|  |  |  | 				var action_meth = `__${name}_${action}__` | 
					
						
							|  |  |  | 				// generate cache if not available...
 | 
					
						
							|  |  |  | 				var cur = cache in this ? | 
					
						
							|  |  |  | 					this[cache] | 
					
						
							|  |  |  | 					: meth.call(this, 'reset') | 
					
						
							| 
									
										
										
										
											2022-11-06 22:38:34 +03:00
										 |  |  | 				var res = _await(this,  | 
					
						
							|  |  |  | 					this[cache] =  | 
					
						
							|  |  |  | 						// NOTE: this[action_meth] will fully shadow options[action]...
 | 
					
						
							|  |  |  | 						action_meth in this ? | 
					
						
							|  |  |  | 							this[action_meth](cur, ...args) | 
					
						
							|  |  |  | 						: (action in options  | 
					
						
							|  |  |  | 								&& typeof(options[action]) == 'function') ? | 
					
						
							|  |  |  | 							//options[action].call(this, cur, ...args)
 | 
					
						
							|  |  |  | 							options[action].call(this, cur, name, ...args) | 
					
						
							|  |  |  | 						: cur)  | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 				res !== cur | 
					
						
							|  |  |  | 					&& _stamp(this, res) | 
					
						
							|  |  |  | 				return res } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | 			// get/generate the data...
 | 
					
						
							|  |  |  | 			var res = _await(this,  | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 				this[cache] = | 
					
						
							|  |  |  | 					// cached...
 | 
					
						
							|  |  |  | 					this[cache] != null ? | 
					
						
							|  |  |  | 						this[cache]  | 
					
						
							|  |  |  | 					// generate + merge...
 | 
					
						
							|  |  |  | 					: this[merge] != null ? | 
					
						
							|  |  |  | 						// NOTE: need to set the timestamp after the merge...
 | 
					
						
							|  |  |  | 						_stamp(this,  | 
					
						
							|  |  |  | 							this[merge](_make(this))) | 
					
						
							|  |  |  | 					// generate...
 | 
					
						
							| 
									
										
										
										
											2022-11-07 16:01:53 +03:00
										 |  |  | 					: _smake(this))  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// action: call...
 | 
					
						
							|  |  |  | 			// NOTE: this directly returns the result to user but will 
 | 
					
						
							|  |  |  | 			// 		not automatically influence the stored value...
 | 
					
						
							|  |  |  | 			if(action == '__call__'){ | 
					
						
							|  |  |  | 				return options.__call__.call(this, res, name, ...args) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// action: get...
 | 
					
						
							|  |  |  | 			return res }, | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			index: name, | 
					
						
							|  |  |  | 			indexed: true, | 
					
						
							|  |  |  | 			options, | 
					
						
							|  |  |  | 		})) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | // XXX
 | 
					
						
							|  |  |  | var iter = | 
					
						
							|  |  |  | module.iter = | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | function*(obj){ | 
					
						
							|  |  |  | 	for(var key of object.deepKeys(obj)){ | 
					
						
							|  |  |  | 		var d = object.values(obj, key, true).next().value.value | 
					
						
							|  |  |  | 		// XXX should makeIndex(..) be a constructor -- i.e. an instanceof test???
 | 
					
						
							|  |  |  | 		if(typeof(d) == 'function'  | 
					
						
							|  |  |  | 				&& d.indexed){ | 
					
						
							|  |  |  | 			yield key } } } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // 	.index(obj)
 | 
					
						
							|  |  |  | // 	.index(obj, 'get')
 | 
					
						
							|  |  |  | // 		-> <indexi>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	.index(obj, <action>, ...)
 | 
					
						
							|  |  |  | // 		-> <indexi>
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	.index('obj, new', <name>, <generate>[, <options>])
 | 
					
						
							|  |  |  | //		-> <index-handler> 
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | // XXX
 | 
					
						
							|  |  |  | var index = | 
					
						
							|  |  |  | module.index = | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | async function(obj, action='get', ...args){ | 
					
						
							|  |  |  | 	// create a new index...
 | 
					
						
							|  |  |  | 	if(action == 'new'){ | 
					
						
							|  |  |  | 		var res = module.makeIndex(...args) | 
					
						
							|  |  |  | 		var [name, _, options={}] = args | 
					
						
							|  |  |  | 		var attr = name | 
					
						
							|  |  |  | 		if(options.attr){ | 
					
						
							|  |  |  | 			var attr = `__${name}` | 
					
						
							|  |  |  | 			Object.defineProperty(obj, name, { | 
					
						
							|  |  |  | 				get: function(){  | 
					
						
							|  |  |  | 					return obj[attr] }, }) } | 
					
						
							|  |  |  | 		return (obj[attr] = res) } | 
					
						
							|  |  |  | 	// propagate action...
 | 
					
						
							|  |  |  | 	return Object.fromEntries( | 
					
						
							|  |  |  | 		await Promise.all( | 
					
						
							|  |  |  | 			module.iter(obj) | 
					
						
							|  |  |  | 				.map(async function(name){ | 
					
						
							|  |  |  | 					return [ | 
					
						
							|  |  |  | 						obj[name].index,  | 
					
						
							|  |  |  | 						await obj[name](action, ...args), | 
					
						
							|  |  |  | 					] }))) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var IndexManagerMixin =  | 
					
						
							|  |  |  | module.IndexManagerMixin = | 
					
						
							|  |  |  | object.Mixin('IndexManagerMixin', { | 
					
						
							|  |  |  | 	// List of index handler attribute names...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX rename???
 | 
					
						
							|  |  |  | 	get index_attrs(){ | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 		return [...module.iter(this)] }, | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 	index: async function(action='get', ...args){ | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 		return module.index(this, ...arguments) }, | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | var indexTest =  | 
					
						
							|  |  |  | module.indexTest = | 
					
						
							|  |  |  | IndexManagerMixin({ | 
					
						
							|  |  |  | 	// tests...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	moo: module.makeIndex('moo', () => 123), | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	foo_index: module.makeIndex('foo', () => 123, { | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 		attr: true, | 
					
						
							|  |  |  | 		add: function(cur, val){ | 
					
						
							|  |  |  | 			return cur + val }, | 
					
						
							|  |  |  | 	}), | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__boo_add__: function(cur, val){ | 
					
						
							|  |  |  | 		return cur + val }, | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	boo: module.makeIndex('boo', () => 123), | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	__soo_add__: async function(cur, val){ | 
					
						
							|  |  |  | 		return await cur + val }, | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	__soo: module.makeIndex('soo', async () => 123), | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 	get soo(){ | 
					
						
							|  |  |  | 		return this.__soo() }, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	__sum: module.makeIndex('sum',  | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 		async function(){ | 
					
						
							|  |  |  | 			return await this.moo()  | 
					
						
							|  |  |  | 				+ await this.foo_index() | 
					
						
							|  |  |  | 				+ await this.boo()  | 
					
						
							|  |  |  | 				+ await this.soo }, | 
					
						
							|  |  |  | 		{ depends: [ | 
					
						
							|  |  |  | 			'moo',  | 
					
						
							|  |  |  | 			'foo_index',  | 
					
						
							|  |  |  | 			'boo',  | 
					
						
							|  |  |  | 			'__soo', | 
					
						
							|  |  |  | 		], }), | 
					
						
							|  |  |  | 	get sum(){ | 
					
						
							|  |  |  | 		return this.__sum() }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__merged__: function(){ | 
					
						
							|  |  |  | 		return 777 }, | 
					
						
							|  |  |  | 	__merged_merge__: async function(data){ | 
					
						
							|  |  |  | 		return (await data) + 777 }, | 
					
						
							| 
									
										
										
										
											2022-10-23 13:38:14 +03:00
										 |  |  | 	__merged: module.makeIndex('merged'), | 
					
						
							| 
									
										
										
										
											2022-10-23 02:21:34 +03:00
										 |  |  | 	get merged(){ | 
					
						
							|  |  |  | 		return this.__merged() }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 nowrap :                        */ return module }) |