From 3975ea5ed82b7d8eb22ca4e38bf83c06f91af408 Mon Sep 17 00:00:00 2001 From: Ray Epps Date: Thu, 5 Jan 2023 19:23:42 -0700 Subject: [PATCH] add keys function to object module (#226) * add keys function to object module --- .github/pull_request_template.md | 1 + cdn/radash.esm.js | 44 ++++++++++++++++-------- cdn/radash.js | 43 ++++++++++++++++------- cdn/radash.min.js | 2 +- docs/object/keys.mdx | 58 ++++++++++++++++++++++++++++++++ package.json | 6 ++-- src/index.ts | 1 + src/object.ts | 26 +++++++++++++- src/tests/object.test.ts | 32 ++++++++++++++++++ 9 files changed, 181 insertions(+), 32 deletions(-) create mode 100644 docs/object/keys.mdx diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index aba83ddd..bd888d23 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,6 +8,7 @@ Please provide a detailed description of the changes and the intent behind them - [ ] Tests have 100% coverage - [ ] If code changes were made, the version in `package.json` has been bumped (matching semver) - [ ] If code changes were made, the `yarn build` command has been run and to update the `cdn` directory +- [ ] If code changes were made, the documentation (in the `/docs` directory) has been updated ## Resolves diff --git a/cdn/radash.esm.js b/cdn/radash.esm.js index c597cd99..ea5cd5e2 100644 --- a/cdn/radash.esm.js +++ b/cdn/radash.esm.js @@ -557,8 +557,8 @@ const toInt = (value, defaultValue) => { const shake = (obj, filter = (x) => x === void 0) => { if (!obj) return {}; - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { if (filter(obj[key])) { return acc; } else { @@ -568,15 +568,15 @@ const shake = (obj, filter = (x) => x === void 0) => { }, {}); }; const mapKeys = (obj, mapFunc) => { - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[mapFunc(key, obj[key])] = obj[key]; return acc; }, {}); }; const mapValues = (obj, mapFunc) => { - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[key] = mapFunc(obj[key], key); return acc; }, {}); @@ -593,8 +593,8 @@ const mapEntries = (obj, toEntry) => { const invert = (obj) => { if (!obj) return {}; - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[obj[key]] = key; return acc; }, {}); @@ -625,21 +625,21 @@ const listify = (obj, toItem) => { return acc; }, []); }; -const pick = (obj, keys) => { +const pick = (obj, keys2) => { if (!obj) return {}; - return keys.reduce((acc, key) => { + return keys2.reduce((acc, key) => { if (obj.hasOwnProperty(key)) acc[key] = obj[key]; return acc; }, {}); }; -const omit = (obj, keys) => { +const omit = (obj, keys2) => { if (!obj) return {}; - if (!keys || keys.length === 0) + if (!keys2 || keys2.length === 0) return obj; - return keys.reduce( + return keys2.reduce( (acc, key) => { delete acc[key]; return acc; @@ -681,6 +681,22 @@ const assign = (a, b) => { }; }, {}); }; +const keys = (value) => { + if (!value) + return []; + const getKeys = (nested, paths) => { + if (isObject(nested)) { + return Object.entries(nested).flatMap( + ([k, v]) => getKeys(v, [...paths, k]) + ); + } + if (isArray(nested)) { + return nested.flatMap((item, i) => getKeys(item, [...paths, `${i}`])); + } + return [paths.join(".")]; + }; + return getKeys(value, []); +}; const random = (min, max) => { return Math.floor(Math.random() * (max - min + 1) + min); @@ -819,4 +835,4 @@ const trim = (str, charsToTrim = " ") => { return str.replace(regex, ""); }; -export { alphabetical, assign, boil, callable, camel, capitalize, chain, clone, cluster, compose, counting, dash, debounce, defer, diff, draw, first, flat, fork, get, group, intersects, invert, isArray, isDate, isEmpty, isEqual, isFloat, isFunction, isInt, isNumber, isObject, isPrimitive, isString, isSymbol, iterate, last, list, listify, lowerize, map, mapEntries, mapKeys, mapValues, max, memo, merge, min, objectify, omit, parallel, partial, partob, pascal, pick, proxied, random, range, reduce, replace, replaceOrAppend, retry, select, series, shake, shift, shuffle, sift, sleep, snake, sort, sum, template, throttle, title, toFloat, toInt, toggle, trim, tryit as try, tryit, uid, unique, upperize, zip, zipToObject }; +export { alphabetical, assign, boil, callable, camel, capitalize, chain, clone, cluster, compose, counting, dash, debounce, defer, diff, draw, first, flat, fork, get, group, intersects, invert, isArray, isDate, isEmpty, isEqual, isFloat, isFunction, isInt, isNumber, isObject, isPrimitive, isString, isSymbol, iterate, keys, last, list, listify, lowerize, map, mapEntries, mapKeys, mapValues, max, memo, merge, min, objectify, omit, parallel, partial, partob, pascal, pick, proxied, random, range, reduce, replace, replaceOrAppend, retry, select, series, shake, shift, shuffle, sift, sleep, snake, sort, sum, template, throttle, title, toFloat, toInt, toggle, trim, tryit as try, tryit, uid, unique, upperize, zip, zipToObject }; diff --git a/cdn/radash.js b/cdn/radash.js index 3661fa80..f9348b7f 100644 --- a/cdn/radash.js +++ b/cdn/radash.js @@ -560,8 +560,8 @@ var radash = (function (exports) { const shake = (obj, filter = (x) => x === void 0) => { if (!obj) return {}; - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { if (filter(obj[key])) { return acc; } else { @@ -571,15 +571,15 @@ var radash = (function (exports) { }, {}); }; const mapKeys = (obj, mapFunc) => { - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[mapFunc(key, obj[key])] = obj[key]; return acc; }, {}); }; const mapValues = (obj, mapFunc) => { - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[key] = mapFunc(obj[key], key); return acc; }, {}); @@ -596,8 +596,8 @@ var radash = (function (exports) { const invert = (obj) => { if (!obj) return {}; - const keys = Object.keys(obj); - return keys.reduce((acc, key) => { + const keys2 = Object.keys(obj); + return keys2.reduce((acc, key) => { acc[obj[key]] = key; return acc; }, {}); @@ -628,21 +628,21 @@ var radash = (function (exports) { return acc; }, []); }; - const pick = (obj, keys) => { + const pick = (obj, keys2) => { if (!obj) return {}; - return keys.reduce((acc, key) => { + return keys2.reduce((acc, key) => { if (obj.hasOwnProperty(key)) acc[key] = obj[key]; return acc; }, {}); }; - const omit = (obj, keys) => { + const omit = (obj, keys2) => { if (!obj) return {}; - if (!keys || keys.length === 0) + if (!keys2 || keys2.length === 0) return obj; - return keys.reduce( + return keys2.reduce( (acc, key) => { delete acc[key]; return acc; @@ -684,6 +684,22 @@ var radash = (function (exports) { }; }, {}); }; + const keys = (value) => { + if (!value) + return []; + const getKeys = (nested, paths) => { + if (isObject(nested)) { + return Object.entries(nested).flatMap( + ([k, v]) => getKeys(v, [...paths, k]) + ); + } + if (isArray(nested)) { + return nested.flatMap((item, i) => getKeys(item, [...paths, `${i}`])); + } + return [paths.join(".")]; + }; + return getKeys(value, []); + }; const random = (min, max) => { return Math.floor(Math.random() * (max - min + 1) + min); @@ -858,6 +874,7 @@ var radash = (function (exports) { exports.isString = isString; exports.isSymbol = isSymbol; exports.iterate = iterate; + exports.keys = keys; exports.last = last; exports.list = list; exports.listify = listify; diff --git a/cdn/radash.min.js b/cdn/radash.min.js index 2e2b2191..0698a0d2 100644 --- a/cdn/radash.min.js +++ b/cdn/radash.min.js @@ -1 +1 @@ -var radash=function(i){"use strict";const $=t=>!!t&&t.constructor===Symbol,N=t=>!!t&&t.constructor===Array,_=t=>!!t&&t.constructor===Object,z=t=>t==null||typeof t!="object"&&typeof t!="function",y=t=>!!(t&&t.constructor&&t.call&&t.apply),D=t=>typeof t=="string"||t instanceof String,F=t=>h(t)&&t%1===0,R=t=>h(t)&&t%1!==0,h=t=>{try{return Number(t)===t}catch{return!1}},P=t=>Object.prototype.toString.call(t)==="[object Date]",Z=t=>{if(t===!0||t===!1||t==null)return!0;if(h(t))return t===0;if(P(t))return isNaN(t.getTime());if(y(t)||$(t))return!1;const e=t.length;if(h(e))return e===0;const n=t.size;return h(n)?n===0:Object.keys(t).length===0},S=(t,e)=>{if(Object.is(t,e))return!0;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.toString()===e.toString();if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;const n=Reflect.ownKeys(t),r=Reflect.ownKeys(e);if(n.length!==r.length)return!1;for(let s=0;st.reduce((n,r)=>{const s=e(r);return n[s]||(n[s]=[]),n[s].push(r),n},{});function q(...t){return!t||!t.length?[]:new Array(Math.max(...t.map(({length:e})=>e))).fill([]).map((e,n)=>t.map(r=>r[n]))}function I(t,e){if(!t||!t.length)return{};const n=y(e)?e:N(e)?(r,s)=>e[s]:(r,s)=>e;return t.reduce((r,s,u)=>(r[s]=n(s,u),r),{})}const b=(t,e)=>!t||(t.length??0)===0?null:t.reduce(e),U=(t,e)=>(t||[]).reduce((n,r)=>n+(e?e(r):r),0),v=(t,e=void 0)=>t?.length>0?t[0]:e,J=(t,e=void 0)=>t?.length>0?t[t.length-1]:e,T=(t,e,n=!1)=>{if(!t)return[];const r=(u,c)=>e(u)-e(c),s=(u,c)=>e(c)-e(u);return t.slice().sort(n===!0?s:r)},K=(t,e,n="asc")=>{if(!t)return[];const r=(u,c)=>`${e(u)}`.localeCompare(e(c)),s=(u,c)=>`${e(c)}`.localeCompare(e(u));return t.slice().sort(n==="desc"?s:r)},W=(t,e)=>t?t.reduce((n,r)=>{const s=e(r);return n[s]=(n[s]??0)+1,n},{}):{},X=(t,e,n)=>{if(!t)return[];if(!e)return[...t];for(let r=0;rr)=>t.reduce((r,s)=>(r[e(s)]=n(s),r),{}),G=(t,e,n)=>t?t.reduce((r,s,u)=>(n(s,u)&&r.push(e(s,u)),r),[]):[],H=(t,e)=>{const n=e||(r=>r);return b(t,(r,s)=>n(r)>n(s)?r:s)},Q=(t,e)=>{const n=e||(r=>r);return b(t,(r,s)=>n(r){const n=Math.ceil(t.length/e);return new Array(n).fill(null).map((r,s)=>t.slice(s*e,s*e+e))},x=(t,e)=>{const n=t.reduce((r,s)=>{const u=e?e(s):s;return r[u]||(r[u]=s),r},{});return Object.values(n)};function*k(t,e,n=s=>s,r=1){const s=y(n)?n:()=>n,u=e?t:0,c=e??t;for(let o=u;o<=c&&(yield s(o),!(o+r>c));o+=r);}const A=(t,e,n,r)=>Array.from(k(t,e,n,r)),tt=t=>t.reduce((e,n)=>(e.push(...n),e),[]),et=(t,e,n)=>{if(!t||!e)return!1;const r=n??(u=>u),s=e.reduce((u,c)=>(u[r(c)]=!0,u),{});return t.some(u=>s[r(u)])},j=(t,e)=>t?t.reduce((n,r)=>{const[s,u]=n;return e(r)?[[...s,r],u]:[s,[...u,r]]},[[],[]]):[[],[]],nt=(t,e,n)=>!e&&!t?[]:e?t?n?t.reduce((r,s)=>{const u=e.find(c=>n(s)===n(c));return u?r.push(u):r.push(s),r},[]):t:[]:t,rt=(t,e,n)=>{if(!t&&!e)return[];if(!e)return[...t];if(!t)return[e];for(let r=0;r{if(!t&&!e)return[];if(!t)return[e];if(!e)return[...t];const s=n?(o,f)=>n(o,f)===n(e,f):o=>o===e;return t.find(s)?t.filter((o,f)=>!s(o,f)):(r?.strategy??"append")==="append"?[...t,e]:[e,...t]},it=t=>t?.filter(e=>!!e)??[],B=(t,e,n)=>{let r=n;for(let s=1;s<=t;s++)r=e(r,s);return r},ut=(t,e,n=r=>r)=>{if(!t?.length&&!e?.length)return[];if(t?.length===void 0)return[...e];if(!e?.length)return[...t];const r=e.reduce((s,u)=>(s[n(u)]=!0,s),{});return t.filter(s=>!r[n(s)])};function ct(t,e){if(t.length===0)return t;const n=e%t.length;return n===0?t:[...t.slice(-n,t.length),...t.slice(0,-n)]}const ot=async(t,e,n)=>{const r=n!==void 0;if(!r&&t?.length<1)throw new Error("Cannot reduce empty array with no init value");const s=r?t:t.slice(1);let u=r?n:t[0];for(const c of s)u=await e(u,c);return u},lt=async(t,e)=>{if(!t)return[];let n=[],r=0;for(const s of t){const u=await e(s,r++);n.push(u)}return n},ft=async t=>{const e=[],n=(u,c)=>e.push({fn:u,rethrow:c?.rethrow??!1}),[r,s]=await m(t)(n);for(const{fn:u,rethrow:c}of e){const[o]=await m(u)(r);if(c)throw o}if(r)throw r;return s};class at extends Error{constructor(e=[]){super();const n=e.find(r=>r.name)?.name??"";this.name=`AggregateError(${n}...)`,this.message=`AggregateError with ${e.length} errors`,this.stack=e.find(r=>r.stack)?.stack??this.stack,this.errors=e}}const dt=async(t,e,n)=>{const r=e.map((a,p)=>({index:p,item:a})),s=async a=>{const p=[];for(;;){const l=r.pop();if(!l)return a(p);const[d,g]=await m(n)(l.item);p.push({error:d,result:g,index:l.index})}},u=A(1,t).map(()=>new Promise(s)),c=await Promise.all(u),[o,f]=j(T(c.flat(),a=>a.index),a=>!!a.error);if(o.length>0)throw new at(o.map(a=>a.error));return f.map(a=>a.result)},gt=async(t,e)=>{const n=t?.times??3,r=t?.delay,s=t?.backoff??null;for(const u of k(1,n)){const[c,o]=await m(e)(f=>{throw{_exited:f}});if(!c)return o;if(c._exited)throw c._exited;if(u===n)throw c;r&&await O(r),s&&await O(s(u))}},O=t=>new Promise(e=>setTimeout(e,t)),m=t=>async(...e)=>{try{return[void 0,await t(...e)]}catch(n){return[n,void 0]}},ht=(...t)=>(...e)=>t.slice(1).reduce((n,r)=>r(n),t[0](...e)),mt=(...t)=>t.reverse().reduce((e,n)=>n(e)),wt=(t,...e)=>(...n)=>t(...e,...n),pt=(t,e)=>n=>t({...e,...n}),yt=t=>new Proxy({},{get:(e,n)=>t(n)}),bt=(t,e,n,r)=>function(...u){const c=n?n(...u):JSON.stringify({args:u}),o=t[c];if(o!==void 0&&(!o.exp||o.exp>new Date().getTime()))return o.value;const f=e(...u);return t[c]={exp:r?new Date().getTime()+r:null,value:f},f},kt=(t,e={})=>bt({},t,e.key??null,e.ttl??null),At=({delay:t},e)=>{let n,r=!0;const s=(...u)=>{r?(clearTimeout(n),n=setTimeout(()=>{r&&e(...u)},t)):e(...u)};return s.cancel=()=>{r=!1},s.flush=(...u)=>e(...u),s},Ot=({interval:t},e)=>{let n=!0;return(...s)=>{n&&(e(...s),n=!1,setTimeout(()=>{n=!0},t))}},Ct=(t,e)=>{const n=()=>{};return new Proxy(Object.assign(n,t),{get:(r,s)=>r[s],set:(r,s,u)=>(r[s]=u,!0),apply:(r,s,u)=>e(Object.assign({},r))(...u)})},Et=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseFloat(t);return isNaN(r)?n:r},$t=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseInt(t);return isNaN(r)?n:r},Nt=(t,e=n=>n===void 0)=>t?Object.keys(t).reduce((r,s)=>(e(t[s])||(r[s]=t[s]),r),{}):{},C=(t,e)=>Object.keys(t).reduce((r,s)=>(r[e(s,t[s])]=t[s],r),{}),_t=(t,e)=>Object.keys(t).reduce((r,s)=>(r[s]=e(t[s],s),r),{}),zt=(t,e)=>t?Object.entries(t).reduce((n,[r,s])=>{const[u,c]=e(r,s);return n[u]=c,n},{}):{},Pt=t=>t?Object.keys(t).reduce((n,r)=>(n[t[r]]=r,n),{}):{},St=t=>C(t,e=>e.toLowerCase()),Tt=t=>C(t,e=>e.toUpperCase()),jt=t=>{if(z(t))return t;if(typeof t=="function")return t.bind({});const e=new t.constructor;return Object.getOwnPropertyNames(t).forEach(n=>{e[n]=t[n]}),e},Bt=(t,e)=>{if(!t)return[];const n=Object.entries(t);return n.length===0?[]:n.reduce((r,s)=>(r.push(e(s[0],s[1])),r),[])},Lt=(t,e)=>t?e.reduce((n,r)=>(t.hasOwnProperty(r)&&(n[r]=t[r]),n),{}):{},Dt=(t,e)=>t?!e||e.length===0?t:e.reduce((n,r)=>(delete n[r],n),{...t}):{},Ft=(t,e,n=null)=>{const r=e.split(/[\.\[\]]/g);let s=t;for(const u of r){if(s===null||s===void 0)return n;u.trim()!==""&&(s=s[u])}return s===void 0?n:s},L=(t,e)=>!t&&!e?{}:t?e?Object.entries(t).reduce((n,[r,s])=>({...n,[r]:(()=>_(s)?L(s,e[r]):e[r])()}),{}):t:e,E=(t,e)=>Math.floor(Math.random()*(e-t+1)+t),Rt=t=>{const e=t.length;if(e===0)return null;const n=E(0,e-1);return t[n]},Zt=t=>t.map(e=>({rand:Math.random(),value:e})).sort((e,n)=>e.rand-n.rand).map(e=>e.value),Mt=(t,e="")=>{const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"+e;return B(t,r=>r+n.charAt(E(0,n.length-1)),"")},qt=(t,e=n=>`${n}`)=>{const{indexesByKey:n,itemsByIndex:r}=t.reduce((l,d,g)=>({indexesByKey:{...l.indexesByKey,[e(d)]:g},itemsByIndex:{...l.itemsByIndex,[g]:d}}),{indexesByKey:{},itemsByIndex:{}}),s=(l,d)=>n[e(l)]n[e(l)]>n[e(d)]?l:d,c=()=>r[0],o=()=>r[t.length-1],f=l=>r[n[e(l)]+1]??c(),a=l=>r[n[e(l)]-1]??o();return{min:s,max:u,first:c,last:o,next:f,previous:a,spin:(l,d)=>{if(d===0)return l;const g=Math.abs(d),Yt=g>t.length?g%t.length:g;return A(0,Yt-1).reduce(d>0?f:a,l)}}},w=t=>{if(!t||t.length===0)return"";const e=t.toLowerCase();return e.substring(0,1).toUpperCase()+e.substring(1,e.length)},It=t=>{const e=t?.replace(/([A-Z])+/g,w)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`)},Ut=t=>{const e=t?.replace(/([A-Z])+/g,w).split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}_${r.toLowerCase()}`)},vt=t=>{const e=t?.replace(/([A-Z])+/g,w)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}-${r.toLowerCase()}`)},Jt=t=>{const e=t?.split(/[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")},Kt=t=>t?t.split(/(?=[A-Z])|[\.\-\s_]/).map(e=>e.trim()).filter(e=>!!e).map(e=>w(e.toLowerCase())).join(" "):"",Wt=(t,e,n=/\{\{(.+?)\}\}/g)=>Array.from(t.matchAll(n)).reduce((r,s)=>r.replace(s[0],e[s[1]]),t),Xt=(t,e=" ")=>{if(!t)return"";const n=new RegExp(`^[${e}]+|[${e}]+$`,"g");return t.replace(n,"")};return i.alphabetical=K,i.assign=L,i.boil=b,i.callable=Ct,i.camel=It,i.capitalize=w,i.chain=ht,i.clone=jt,i.cluster=V,i.compose=mt,i.counting=W,i.dash=vt,i.debounce=At,i.defer=ft,i.diff=ut,i.draw=Rt,i.first=v,i.flat=tt,i.fork=j,i.get=Ft,i.group=M,i.intersects=et,i.invert=Pt,i.isArray=N,i.isDate=P,i.isEmpty=Z,i.isEqual=S,i.isFloat=R,i.isFunction=y,i.isInt=F,i.isNumber=h,i.isObject=_,i.isPrimitive=z,i.isString=D,i.isSymbol=$,i.iterate=B,i.last=J,i.list=A,i.listify=Bt,i.lowerize=St,i.map=lt,i.mapEntries=zt,i.mapKeys=C,i.mapValues=_t,i.max=H,i.memo=kt,i.merge=nt,i.min=Q,i.objectify=Y,i.omit=Dt,i.parallel=dt,i.partial=wt,i.partob=pt,i.pascal=Jt,i.pick=Lt,i.proxied=yt,i.random=E,i.range=k,i.reduce=ot,i.replace=X,i.replaceOrAppend=rt,i.retry=gt,i.select=G,i.series=qt,i.shake=Nt,i.shift=ct,i.shuffle=Zt,i.sift=it,i.sleep=O,i.snake=Ut,i.sort=T,i.sum=U,i.template=Wt,i.throttle=Ot,i.title=Kt,i.toFloat=Et,i.toInt=$t,i.toggle=st,i.trim=Xt,i.try=m,i.tryit=m,i.uid=Mt,i.unique=x,i.upperize=Tt,i.zip=q,i.zipToObject=I,i}({}); +var radash=function(s){"use strict";const _=t=>!!t&&t.constructor===Symbol,b=t=>!!t&&t.constructor===Array,k=t=>!!t&&t.constructor===Object,j=t=>t==null||typeof t!="object"&&typeof t!="function",y=t=>!!(t&&t.constructor&&t.call&&t.apply),M=t=>typeof t=="string"||t instanceof String,D=t=>h(t)&&t%1===0,F=t=>h(t)&&t%1!==0,h=t=>{try{return Number(t)===t}catch{return!1}},z=t=>Object.prototype.toString.call(t)==="[object Date]",R=t=>{if(t===!0||t===!1||t==null)return!0;if(h(t))return t===0;if(z(t))return isNaN(t.getTime());if(y(t)||_(t))return!1;const e=t.length;if(h(e))return e===0;const n=t.size;return h(n)?n===0:Object.keys(t).length===0},P=(t,e)=>{if(Object.is(t,e))return!0;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.toString()===e.toString();if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;const n=Reflect.ownKeys(t),r=Reflect.ownKeys(e);if(n.length!==r.length)return!1;for(let i=0;it.reduce((n,r)=>{const i=e(r);return n[i]||(n[i]=[]),n[i].push(r),n},{});function q(...t){return!t||!t.length?[]:new Array(Math.max(...t.map(({length:e})=>e))).fill([]).map((e,n)=>t.map(r=>r[n]))}function I(t,e){if(!t||!t.length)return{};const n=y(e)?e:b(e)?(r,i)=>e[i]:(r,i)=>e;return t.reduce((r,i,u)=>(r[i]=n(i,u),r),{})}const O=(t,e)=>!t||(t.length??0)===0?null:t.reduce(e),U=(t,e)=>(t||[]).reduce((n,r)=>n+(e?e(r):r),0),K=(t,e=void 0)=>t?.length>0?t[0]:e,v=(t,e=void 0)=>t?.length>0?t[t.length-1]:e,S=(t,e,n=!1)=>{if(!t)return[];const r=(u,c)=>e(u)-e(c),i=(u,c)=>e(c)-e(u);return t.slice().sort(n===!0?i:r)},J=(t,e,n="asc")=>{if(!t)return[];const r=(u,c)=>`${e(u)}`.localeCompare(e(c)),i=(u,c)=>`${e(c)}`.localeCompare(e(u));return t.slice().sort(n==="desc"?i:r)},W=(t,e)=>t?t.reduce((n,r)=>{const i=e(r);return n[i]=(n[i]??0)+1,n},{}):{},X=(t,e,n)=>{if(!t)return[];if(!e)return[...t];for(let r=0;rr)=>t.reduce((r,i)=>(r[e(i)]=n(i),r),{}),G=(t,e,n)=>t?t.reduce((r,i,u)=>(n(i,u)&&r.push(e(i,u)),r),[]):[],H=(t,e)=>{const n=e||(r=>r);return O(t,(r,i)=>n(r)>n(i)?r:i)},Q=(t,e)=>{const n=e||(r=>r);return O(t,(r,i)=>n(r){const n=Math.ceil(t.length/e);return new Array(n).fill(null).map((r,i)=>t.slice(i*e,i*e+e))},x=(t,e)=>{const n=t.reduce((r,i)=>{const u=e?e(i):i;return r[u]||(r[u]=i),r},{});return Object.values(n)};function*A(t,e,n=i=>i,r=1){const i=y(n)?n:()=>n,u=e?t:0,c=e??t;for(let o=u;o<=c&&(yield i(o),!(o+r>c));o+=r);}const C=(t,e,n,r)=>Array.from(A(t,e,n,r)),tt=t=>t.reduce((e,n)=>(e.push(...n),e),[]),et=(t,e,n)=>{if(!t||!e)return!1;const r=n??(u=>u),i=e.reduce((u,c)=>(u[r(c)]=!0,u),{});return t.some(u=>i[r(u)])},T=(t,e)=>t?t.reduce((n,r)=>{const[i,u]=n;return e(r)?[[...i,r],u]:[i,[...u,r]]},[[],[]]):[[],[]],nt=(t,e,n)=>!e&&!t?[]:e?t?n?t.reduce((r,i)=>{const u=e.find(c=>n(i)===n(c));return u?r.push(u):r.push(i),r},[]):t:[]:t,rt=(t,e,n)=>{if(!t&&!e)return[];if(!e)return[...t];if(!t)return[e];for(let r=0;r{if(!t&&!e)return[];if(!t)return[e];if(!e)return[...t];const i=n?(o,l)=>n(o,l)===n(e,l):o=>o===e;return t.find(i)?t.filter((o,l)=>!i(o,l)):(r?.strategy??"append")==="append"?[...t,e]:[e,...t]},st=t=>t?.filter(e=>!!e)??[],B=(t,e,n)=>{let r=n;for(let i=1;i<=t;i++)r=e(r,i);return r},ut=(t,e,n=r=>r)=>{if(!t?.length&&!e?.length)return[];if(t?.length===void 0)return[...e];if(!e?.length)return[...t];const r=e.reduce((i,u)=>(i[n(u)]=!0,i),{});return t.filter(i=>!r[n(i)])};function ct(t,e){if(t.length===0)return t;const n=e%t.length;return n===0?t:[...t.slice(-n,t.length),...t.slice(0,-n)]}const ot=async(t,e,n)=>{const r=n!==void 0;if(!r&&t?.length<1)throw new Error("Cannot reduce empty array with no init value");const i=r?t:t.slice(1);let u=r?n:t[0];for(const c of i)u=await e(u,c);return u},ft=async(t,e)=>{if(!t)return[];let n=[],r=0;for(const i of t){const u=await e(i,r++);n.push(u)}return n},lt=async t=>{const e=[],n=(u,c)=>e.push({fn:u,rethrow:c?.rethrow??!1}),[r,i]=await m(t)(n);for(const{fn:u,rethrow:c}of e){const[o]=await m(u)(r);if(c)throw o}if(r)throw r;return i};class at extends Error{constructor(e=[]){super();const n=e.find(r=>r.name)?.name??"";this.name=`AggregateError(${n}...)`,this.message=`AggregateError with ${e.length} errors`,this.stack=e.find(r=>r.stack)?.stack??this.stack,this.errors=e}}const dt=async(t,e,n)=>{const r=e.map((a,p)=>({index:p,item:a})),i=async a=>{const p=[];for(;;){const f=r.pop();if(!f)return a(p);const[d,g]=await m(n)(f.item);p.push({error:d,result:g,index:f.index})}},u=C(1,t).map(()=>new Promise(i)),c=await Promise.all(u),[o,l]=T(S(c.flat(),a=>a.index),a=>!!a.error);if(o.length>0)throw new at(o.map(a=>a.error));return l.map(a=>a.result)},gt=async(t,e)=>{const n=t?.times??3,r=t?.delay,i=t?.backoff??null;for(const u of A(1,n)){const[c,o]=await m(e)(l=>{throw{_exited:l}});if(!c)return o;if(c._exited)throw c._exited;if(u===n)throw c;r&&await E(r),i&&await E(i(u))}},E=t=>new Promise(e=>setTimeout(e,t)),m=t=>async(...e)=>{try{return[void 0,await t(...e)]}catch(n){return[n,void 0]}},ht=(...t)=>(...e)=>t.slice(1).reduce((n,r)=>r(n),t[0](...e)),mt=(...t)=>t.reverse().reduce((e,n)=>n(e)),wt=(t,...e)=>(...n)=>t(...e,...n),pt=(t,e)=>n=>t({...e,...n}),yt=t=>new Proxy({},{get:(e,n)=>t(n)}),bt=(t,e,n,r)=>function(...u){const c=n?n(...u):JSON.stringify({args:u}),o=t[c];if(o!==void 0&&(!o.exp||o.exp>new Date().getTime()))return o.value;const l=e(...u);return t[c]={exp:r?new Date().getTime()+r:null,value:l},l},kt=(t,e={})=>bt({},t,e.key??null,e.ttl??null),Ot=({delay:t},e)=>{let n,r=!0;const i=(...u)=>{r?(clearTimeout(n),n=setTimeout(()=>{r&&e(...u)},t)):e(...u)};return i.cancel=()=>{r=!1},i.flush=(...u)=>e(...u),i},At=({interval:t},e)=>{let n=!0;return(...i)=>{n&&(e(...i),n=!1,setTimeout(()=>{n=!0},t))}},Ct=(t,e)=>{const n=()=>{};return new Proxy(Object.assign(n,t),{get:(r,i)=>r[i],set:(r,i,u)=>(r[i]=u,!0),apply:(r,i,u)=>e(Object.assign({},r))(...u)})},Et=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseFloat(t);return isNaN(r)?n:r},$t=(t,e)=>{const n=e===void 0?0:e;if(t==null)return n;const r=parseInt(t);return isNaN(r)?n:r},Nt=(t,e=n=>n===void 0)=>t?Object.keys(t).reduce((r,i)=>(e(t[i])||(r[i]=t[i]),r),{}):{},$=(t,e)=>Object.keys(t).reduce((r,i)=>(r[e(i,t[i])]=t[i],r),{}),_t=(t,e)=>Object.keys(t).reduce((r,i)=>(r[i]=e(t[i],i),r),{}),jt=(t,e)=>t?Object.entries(t).reduce((n,[r,i])=>{const[u,c]=e(r,i);return n[u]=c,n},{}):{},zt=t=>t?Object.keys(t).reduce((n,r)=>(n[t[r]]=r,n),{}):{},Pt=t=>$(t,e=>e.toLowerCase()),St=t=>$(t,e=>e.toUpperCase()),Tt=t=>{if(j(t))return t;if(typeof t=="function")return t.bind({});const e=new t.constructor;return Object.getOwnPropertyNames(t).forEach(n=>{e[n]=t[n]}),e},Bt=(t,e)=>{if(!t)return[];const n=Object.entries(t);return n.length===0?[]:n.reduce((r,i)=>(r.push(e(i[0],i[1])),r),[])},Lt=(t,e)=>t?e.reduce((n,r)=>(t.hasOwnProperty(r)&&(n[r]=t[r]),n),{}):{},Mt=(t,e)=>t?!e||e.length===0?t:e.reduce((n,r)=>(delete n[r],n),{...t}):{},Dt=(t,e,n=null)=>{const r=e.split(/[\.\[\]]/g);let i=t;for(const u of r){if(i===null||i===void 0)return n;u.trim()!==""&&(i=i[u])}return i===void 0?n:i},L=(t,e)=>!t&&!e?{}:t?e?Object.entries(t).reduce((n,[r,i])=>({...n,[r]:(()=>k(i)?L(i,e[r]):e[r])()}),{}):t:e,Ft=t=>{if(!t)return[];const e=(n,r)=>k(n)?Object.entries(n).flatMap(([i,u])=>e(u,[...r,i])):b(n)?n.flatMap((i,u)=>e(i,[...r,`${u}`])):[r.join(".")];return e(t,[])},N=(t,e)=>Math.floor(Math.random()*(e-t+1)+t),Rt=t=>{const e=t.length;if(e===0)return null;const n=N(0,e-1);return t[n]},Zt=t=>t.map(e=>({rand:Math.random(),value:e})).sort((e,n)=>e.rand-n.rand).map(e=>e.value),qt=(t,e="")=>{const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"+e;return B(t,r=>r+n.charAt(N(0,n.length-1)),"")},It=(t,e=n=>`${n}`)=>{const{indexesByKey:n,itemsByIndex:r}=t.reduce((f,d,g)=>({indexesByKey:{...f.indexesByKey,[e(d)]:g},itemsByIndex:{...f.itemsByIndex,[g]:d}}),{indexesByKey:{},itemsByIndex:{}}),i=(f,d)=>n[e(f)]n[e(f)]>n[e(d)]?f:d,c=()=>r[0],o=()=>r[t.length-1],l=f=>r[n[e(f)]+1]??c(),a=f=>r[n[e(f)]-1]??o();return{min:i,max:u,first:c,last:o,next:l,previous:a,spin:(f,d)=>{if(d===0)return f;const g=Math.abs(d),Gt=g>t.length?g%t.length:g;return C(0,Gt-1).reduce(d>0?l:a,f)}}},w=t=>{if(!t||t.length===0)return"";const e=t.toLowerCase();return e.substring(0,1).toUpperCase()+e.substring(1,e.length)},Ut=t=>{const e=t?.replace(/([A-Z])+/g,w)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}${r.charAt(0).toUpperCase()}${r.slice(1)}`)},Kt=t=>{const e=t?.replace(/([A-Z])+/g,w).split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}_${r.toLowerCase()}`)},vt=t=>{const e=t?.replace(/([A-Z])+/g,w)?.split(/(?=[A-Z])|[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.length===1?e[0]:e.reduce((n,r)=>`${n}-${r.toLowerCase()}`)},Jt=t=>{const e=t?.split(/[\.\-\s_]/).map(n=>n.toLowerCase())??[];return e.length===0?"":e.map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join("")},Wt=t=>t?t.split(/(?=[A-Z])|[\.\-\s_]/).map(e=>e.trim()).filter(e=>!!e).map(e=>w(e.toLowerCase())).join(" "):"",Xt=(t,e,n=/\{\{(.+?)\}\}/g)=>Array.from(t.matchAll(n)).reduce((r,i)=>r.replace(i[0],e[i[1]]),t),Yt=(t,e=" ")=>{if(!t)return"";const n=new RegExp(`^[${e}]+|[${e}]+$`,"g");return t.replace(n,"")};return s.alphabetical=J,s.assign=L,s.boil=O,s.callable=Ct,s.camel=Ut,s.capitalize=w,s.chain=ht,s.clone=Tt,s.cluster=V,s.compose=mt,s.counting=W,s.dash=vt,s.debounce=Ot,s.defer=lt,s.diff=ut,s.draw=Rt,s.first=K,s.flat=tt,s.fork=T,s.get=Dt,s.group=Z,s.intersects=et,s.invert=zt,s.isArray=b,s.isDate=z,s.isEmpty=R,s.isEqual=P,s.isFloat=F,s.isFunction=y,s.isInt=D,s.isNumber=h,s.isObject=k,s.isPrimitive=j,s.isString=M,s.isSymbol=_,s.iterate=B,s.keys=Ft,s.last=v,s.list=C,s.listify=Bt,s.lowerize=Pt,s.map=ft,s.mapEntries=jt,s.mapKeys=$,s.mapValues=_t,s.max=H,s.memo=kt,s.merge=nt,s.min=Q,s.objectify=Y,s.omit=Mt,s.parallel=dt,s.partial=wt,s.partob=pt,s.pascal=Jt,s.pick=Lt,s.proxied=yt,s.random=N,s.range=A,s.reduce=ot,s.replace=X,s.replaceOrAppend=rt,s.retry=gt,s.select=G,s.series=It,s.shake=Nt,s.shift=ct,s.shuffle=Zt,s.sift=st,s.sleep=E,s.snake=Kt,s.sort=S,s.sum=U,s.template=Xt,s.throttle=At,s.title=Wt,s.toFloat=Et,s.toInt=$t,s.toggle=it,s.trim=Yt,s.try=m,s.tryit=m,s.uid=qt,s.unique=x,s.upperize=St,s.zip=q,s.zipToObject=I,s}({}); diff --git a/docs/object/keys.mdx b/docs/object/keys.mdx new file mode 100644 index 00000000..857d9c00 --- /dev/null +++ b/docs/object/keys.mdx @@ -0,0 +1,58 @@ +--- +title: keys +description: Get all keys from an object deeply +group: Object +--- + +## Basic usage + +Given an object, return all of it's keys and children's keys deeply as a flat string list. + +```ts +import { keys } from 'radash' + +const ra = { + name: 'ra', + power: 100, + friend: { + name: 'loki', + power: 80 + }, + enemies: [ + { + name: 'hathor', + power: 12 + } + ] +} + +keys(ra) +// => [ +// 'name', +// 'power', +// 'friend.name', +// 'friend.power', +// 'enemies.0.name', +// 'enemies.0.power' +// ] +``` + +This is a function you might like to use with `get`, which dynamically looks up values in an object given a string path. Using the two together you could do something like flatten a deep object. + +```ts +import { keys, get, objectify } from 'radash' + +objectify( + keys(ra), + key => key, + key => get(ra, key) +) +// => { +// 'name': 'ra' +// 'power': 100 +// 'friend.name': 'loki' +// 'friend.power': 80 +// 'enemies.0.name': 'hathor' +// 'enemies.0.power': 12 +// } +``` diff --git a/package.json b/package.json index 401fc4c0..497ede73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "radash", - "version": "10.3.2", + "version": "10.4.0", "description": "Functional utility library - modern, simple, typed, powerful", "main": "dist/cjs/index.cjs", "module": "dist/esm/index.mjs", @@ -27,8 +27,8 @@ "docs:install": "yarn && yarn add --dev next@12.3.4", "docs:build": "chiller build --ci", "lint": "tslint -p tsconfig.json", - "format": "prettier --write \"./**/*.ts\"", - "format:check": "prettier --check \"**/*.ts\" --ignore-unknown" + "format": "prettier --write \"src/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\" --ignore-unknown" }, "devDependencies": { "@rollup/plugin-typescript": "^10.0.1", diff --git a/src/index.ts b/src/index.ts index 215e35f6..f8e182c5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -57,6 +57,7 @@ export { clone, get, invert, + keys, listify, lowerize, mapEntries, diff --git a/src/object.ts b/src/object.ts index a08a9013..6632799c 100644 --- a/src/object.ts +++ b/src/object.ts @@ -1,4 +1,4 @@ -import { isObject, isPrimitive } from './typed' +import { isArray, isObject, isPrimitive } from './typed' type LowercasedKeys> = { [P in keyof T & string as Lowercase

]: T[P] @@ -245,3 +245,27 @@ export const assign = >( } }, {} as X) } + +/** + * Get a string list of all key names that exist in + * an object (deep). + * + * @example + * keys({ name: 'ra' }) // ['name'] + * keys({ name: 'ra', children: [{ name: 'hathor' }] }) // ['name', 'children.0.name'] + */ +export const keys = (value: TValue): string[] => { + if (!value) return [] + const getKeys = (nested: any, paths: string[]): string[] => { + if (isObject(nested)) { + return Object.entries(nested).flatMap(([k, v]) => + getKeys(v, [...paths, k]) + ) + } + if (isArray(nested)) { + return nested.flatMap((item, i) => getKeys(item, [...paths, `${i}`])) + } + return [paths.join('.')] + } + return getKeys(value, []) +} diff --git a/src/tests/object.test.ts b/src/tests/object.test.ts index 0f109088..8d11378c 100644 --- a/src/tests/object.test.ts +++ b/src/tests/object.test.ts @@ -383,4 +383,36 @@ describe('object module', () => { assert.deepEqual(result, b) }) }) + + describe('keys function', () => { + test('handles bad input', () => { + assert.deepEqual(_.keys({}), []) + assert.deepEqual(_.keys(null as any), []) + assert.deepEqual(_.keys(undefined as any), []) + }) + test('returns correct list of keys', () => { + const ra = { + name: 'ra', + power: 100, + friend: { + name: 'loki', + power: 80 + }, + enemies: [ + { + name: 'hathor', + power: 12 + } + ] + } + assert.deepEqual(_.keys(ra), [ + 'name', + 'power', + 'friend.name', + 'friend.power', + 'enemies.0.name', + 'enemies.0.power' + ]) + }) + }) })