You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					143 lines
				
				2.7 KiB
			
		
		
			
		
	
	
					143 lines
				
				2.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								const isObj = require('is-obj');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const disallowedKeys = [
							 | 
						||
| 
								 | 
							
									'__proto__',
							 | 
						||
| 
								 | 
							
									'prototype',
							 | 
						||
| 
								 | 
							
									'constructor'
							 | 
						||
| 
								 | 
							
								];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const isValidPath = pathSegments => !pathSegments.some(segment => disallowedKeys.includes(segment));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function getPathSegments(path) {
							 | 
						||
| 
								 | 
							
									const pathArray = path.split('.');
							 | 
						||
| 
								 | 
							
									const parts = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (let i = 0; i < pathArray.length; i++) {
							 | 
						||
| 
								 | 
							
										let p = pathArray[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										while (p[p.length - 1] === '\\' && pathArray[i + 1] !== undefined) {
							 | 
						||
| 
								 | 
							
											p = p.slice(0, -1) + '.';
							 | 
						||
| 
								 | 
							
											p += pathArray[++i];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										parts.push(p);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (!isValidPath(parts)) {
							 | 
						||
| 
								 | 
							
										return [];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return parts;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
									get(object, path, value) {
							 | 
						||
| 
								 | 
							
										if (!isObj(object) || typeof path !== 'string') {
							 | 
						||
| 
								 | 
							
											return value === undefined ? object : value;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const pathArray = getPathSegments(path);
							 | 
						||
| 
								 | 
							
										if (pathArray.length === 0) {
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (let i = 0; i < pathArray.length; i++) {
							 | 
						||
| 
								 | 
							
											if (!Object.prototype.propertyIsEnumerable.call(object, pathArray[i])) {
							 | 
						||
| 
								 | 
							
												return value;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											object = object[pathArray[i]];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (object === undefined || object === null) {
							 | 
						||
| 
								 | 
							
												// `object` is either `undefined` or `null` so we want to stop the loop, and
							 | 
						||
| 
								 | 
							
												// if this is not the last bit of the path, and
							 | 
						||
| 
								 | 
							
												// if it did't return `undefined`
							 | 
						||
| 
								 | 
							
												// it would return `null` if `object` is `null`
							 | 
						||
| 
								 | 
							
												// but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied value, not `null`
							 | 
						||
| 
								 | 
							
												if (i !== pathArray.length - 1) {
							 | 
						||
| 
								 | 
							
													return value;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return object;
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									set(object, path, value) {
							 | 
						||
| 
								 | 
							
										if (!isObj(object) || typeof path !== 'string') {
							 | 
						||
| 
								 | 
							
											return object;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const root = object;
							 | 
						||
| 
								 | 
							
										const pathArray = getPathSegments(path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (let i = 0; i < pathArray.length; i++) {
							 | 
						||
| 
								 | 
							
											const p = pathArray[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (!isObj(object[p])) {
							 | 
						||
| 
								 | 
							
												object[p] = {};
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (i === pathArray.length - 1) {
							 | 
						||
| 
								 | 
							
												object[p] = value;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											object = object[p];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return root;
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									delete(object, path) {
							 | 
						||
| 
								 | 
							
										if (!isObj(object) || typeof path !== 'string') {
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const pathArray = getPathSegments(path);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (let i = 0; i < pathArray.length; i++) {
							 | 
						||
| 
								 | 
							
											const p = pathArray[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (i === pathArray.length - 1) {
							 | 
						||
| 
								 | 
							
												delete object[p];
							 | 
						||
| 
								 | 
							
												return true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											object = object[p];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (!isObj(object)) {
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									has(object, path) {
							 | 
						||
| 
								 | 
							
										if (!isObj(object) || typeof path !== 'string') {
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const pathArray = getPathSegments(path);
							 | 
						||
| 
								 | 
							
										if (pathArray.length === 0) {
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// eslint-disable-next-line unicorn/no-for-loop
							 | 
						||
| 
								 | 
							
										for (let i = 0; i < pathArray.length; i++) {
							 | 
						||
| 
								 | 
							
											if (isObj(object)) {
							 | 
						||
| 
								 | 
							
												if (!(pathArray[i] in object)) {
							 | 
						||
| 
								 | 
							
													return false;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												object = object[pathArray[i]];
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								};
							 |