included obj lib
Massimo Melina committed
Dec 17, 2021 at 10:46 UTC
c3eff9638fc84d88875830129211ff02e55a2085
3 files changed
+109
-4
src/misc.ts
+5
@@ -1,5 +1,6 @@
1
import { stat } from 'fs/promises'
2
import glob from 'fast-glob'
3
+import { objSameKeys } from './obj'
4
5
export function enforceFinal(sub:string, s:string) {
6
return s.endsWith(sub) ? s : s+sub
@@ -32,3 +33,7 @@ export async function globDir(path: string, ignore?: any[]) {
33
ignore: ignore?.flat().filter(Boolean).map(x => path!+x),
34
})
35
}
36
+
37
+export function setHidden(dest: object, src:object) {
38
+ Object.defineProperties(dest, objSameKeys(src, value => ({ enumerable:false, value })))
39
+}
src/obj.ts
new
+102
@@ -0,0 +1,102 @@
1
+/** creates an object iterating an array or an object.
2
+ * The callback(val,key/index) should return [val,key] to set both, or just [val] and they key is kept, or just the key (no array) and val will be kept,
3
+ * or an object to merge with the result, or undefined to skip.
4
+ */
5
+type Key = string | number
6
+type Mapper = (v?: any, k?: Key, src?:any, dst?:object) => any
7
+
8
+export function obj(src:any, cb: string | Mapper, skipUndefined:boolean=true, dst:any={}) {
9
+ const short = (typeof cb==='string')
10
+ let i = 0
11
+ if (Array.isArray(src))
12
+ for (const e of src)
13
+ work(e, i++)
14
+ else
15
+ for (const k in src)
16
+ work(src[k], k)
17
+ return dst
18
+
19
+ function work(entry:any, k: Key) {
20
+ const r = short ? entry[cb] : cb(entry,k,src,dst)
21
+ if (short)
22
+ add(k, r)
23
+ else if (Array.isArray(r))
24
+ if (r.length===1)
25
+ add(k, r[0])
26
+ else
27
+ add(r[1], r[0])
28
+ else if (r instanceof Object)
29
+ Object.assign(dst, r)
30
+ else
31
+ add(r, entry)
32
+ }
33
+
34
+ function add(k: Key | string[], v: any) {
35
+ if (k === undefined || (skipUndefined && v === undefined))
36
+ return
37
+ let o = dst
38
+ if (Array.isArray(k))
39
+ if (k.length === 1)
40
+ k = k[0]
41
+ else {
42
+ const a = k
43
+ k = a.pop() as Key
44
+ for (const k1 of a) // @ts-ignore
45
+ o = o[k1] instanceof Object ? o[k1] : (o[k1] = {})
46
+ }
47
+ o[k] = v
48
+ }
49
+}
50
+
51
+export function objFilter(src:any, cb:Mapper) {
52
+ return obj(src, function(v,k){ // @ts-ignore
53
+ return cb.apply(this,arguments) ? k : undefined
54
+ })
55
+}
56
+
57
+export function objSameKeys(src:any, cb:Mapper | string) {
58
+ return obj(src, typeof cb === 'string' ? cb : (...args)=> [cb(...args)])
59
+}
60
+
61
+export function objFromKeys(keys: string[], returnValueFromKey:(k:string)=>any, skipUndefined=true) {
62
+ return obj(keys, k => [returnValueFromKey(k), k], skipUndefined)
63
+}
64
+
65
+// useful only in the extent of making clear your intentions
66
+export const objSameValues = obj
67
+
68
+//** replace object's (or array's) values with those returned by callback
69
+export function remap(obj:any, map:Mapper, skipUndefined=true) {
70
+ if (!obj) return
71
+ if (Array.isArray(obj)) {
72
+ let k = obj.length
73
+ while (k--) {
74
+ const v = map(obj[k], k)
75
+ if (v !== undefined || !skipUndefined)
76
+ obj[k] = v
77
+ else
78
+ obj.splice(k, 1) // will this cause problems if we remove in the middle?
79
+ }
80
+ return
81
+ }
82
+ for (const k in obj) {
83
+ const v = map(obj[k], k)
84
+ if (v !== undefined || !skipUndefined)
85
+ obj[k] = v
86
+ else
87
+ delete obj[k]
88
+ }
89
+}
90
+
91
+// replace object's keys using map object. If undefined the key will be removed.
92
+export function remapKeys(obj:any, map:Record<string,string>) {
93
+ if (obj)
94
+ for (const k in obj)
95
+ if (obj.hasOwnProperty(k) && map.hasOwnProperty(k)) {
96
+ const newK = map[k]
97
+ if (newK !== undefined)
98
+ obj[newK] = obj[k]
99
+ delete obj[k]
100
+ }
101
+ return obj
102
+}
src/perm.ts
+2
-4
@@ -4,6 +4,7 @@ import _ from 'lodash'
4
import yaml from 'yaml'
5
import { hashPassword } from './crypt'
6
import { argv } from './const'
7
+import { setHidden } from './misc'
8
9
const PATH = argv.accounts || 'accounts.yaml'
10
@@ -44,10 +45,7 @@ async function load() {
45
accounts = res.accounts
46
let changed = false
47
await Promise.all(_.map(accounts, async (rec,k) => {
47
- Object.defineProperty(rec, 'user', {
48
- enumerable: false, // sneak it in
49
- value: k,
50
- })
48
+ setHidden(rec, { user: k })
49
if (rec.password) {
50
rec.hashedPassword = await hashPassword(rec.password)
51
delete rec.password