Skip to content

Commit

Permalink
Add transformFirst option to allow a one-time modification of keys
Browse files Browse the repository at this point in the history
  • Loading branch information
jottinger committed Aug 4, 2020
1 parent 5264f07 commit 5345739
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 5 deletions.
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ flatten({

### transformKey

Transform each part of a flat key before and after flattening.
Transform each part of a flat key before and after flattening.

```javascript
var flatten = require('flat')
Expand Down Expand Up @@ -208,6 +208,59 @@ unflatten({
// }
```

### transformFirst

Transforms the top-level key before and after flattening. It has two arguments:

1. The key to transform
1. An optional delimiter. This is not required, but allows the transformation to
add a new key to the transformation.

```javascript
var flatten = require('flat')
var unflatten = require('flat').unflatten

flatten({
key1: {
keyA: 'valueI'
},
key2: {
keyB: 'valueII'
},
key3: { a: { b: { c: 2 } } }
}, {
transformFirst: function(key, delim){
return 'foo' + delim + key;
}
})

// {
// 'foo.key1.keyA': 'valueI',
// 'foo.key2.keyB': 'valueII',
// 'foo.key3.a.b.c': 2
// }

unflatten({
'foo.key1.keyA': 'valueI',
'foo.key2.keyB': 'valueII',
'foo.key3.a.b.c': 2
}, {
transformFirst: function(key, delim){
return key.substring((key+delim).length)
}
})

// {
// key1: {
// keyA: 'valueI'
// },
// key2: {
// keyB: 'valueII'
// },
// key3: { a: { b: { c: 2 } } }
// }
```

## Command Line Usage

`flat` is also available as a command line tool. You can run it with
Expand Down
10 changes: 6 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ function flatten (target, opts) {
const delimiter = opts.delimiter || '.'
const maxDepth = opts.maxDepth
const transformKey = opts.transformKey || keyIdentity
const transformFirst = opts.transformFirst || keyIdentity
const output = {}

function step (object, prev, currentDepth) {
Expand All @@ -30,18 +31,18 @@ function flatten (target, opts) {

const newKey = prev
? prev + delimiter + transformKey(key)
: transformKey(key)
: transformFirst(transformKey(key), delimiter)

if (!isarray && !isbuffer && isobject && Object.keys(value).length &&
(!opts.maxDepth || currentDepth < maxDepth)) {
return step(value, newKey, currentDepth + 1)
return step(value, newKey, currentDepth + 1, false)
}

output[newKey] = value
})
}

step(target)
step(target, false, 1)

return output
}
Expand All @@ -52,6 +53,7 @@ function unflatten (target, opts) {
const delimiter = opts.delimiter || '.'
const overwrite = opts.overwrite || false
const transformKey = opts.transformKey || keyIdentity
const transformFirst = opts.transformFirst || keyIdentity
const result = {}

const isbuffer = isBuffer(target)
Expand Down Expand Up @@ -110,7 +112,7 @@ function unflatten (target, opts) {
}, {})

Object.keys(target).forEach(function (key) {
const split = key.split(delimiter).map(transformKey)
const split = transformFirst(key, delimiter).split(delimiter).map(transformKey)
let key1 = getkey(split.shift())
let key2 = getkey(split[0])
let recipient = result
Expand Down
169 changes: 169 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,125 @@ suite('Flatten', function () {
})
})

test('Transformed First Key', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformFirst: function (key) {
return '__' + key + '__'
}
}), {
'__hello__.world.again': 'good morning',
'__lorem__.ipsum.dolor': 'good evening'
})
})

test('Transformed First Key with Custom Delimiter', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformFirst: function (key) {
return '__' + key + '__'
},
delimiter: ':'
}), {
'__hello__:world:again': 'good morning',
'__lorem__:ipsum:dolor': 'good evening'
})
})

test('Transformed First Key to Add Prefix with Default Delimiter', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformFirst: function (key, delim) {
return 'foo' + delim + key
}
}), {
'foo.hello.world.again': 'good morning',
'foo.lorem.ipsum.dolor': 'good evening'
})
})


test('Transformed First Key to Add Prefix with Custom Delimiter', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformFirst: function (key, delim) {
return 'foo' + delim + key
},
delimiter: ':'
}), {
'foo:hello:world:again': 'good morning',
'foo:lorem:ipsum:dolor': 'good evening'
})
})


test('Transformed Results and Keys', function () {
assert.deepStrictEqual(flatten({
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
}, {
transformKey: function (key) {
return '__' + key + '__'
},
transformFirst: function (key, delim) {
return 'translated' + delim + key
}
}), {
'translated.__hello__.__world__.__again__': 'good morning',
'translated.__lorem__.__ipsum__.__dolor__': 'good evening'
})
})



test('Should keep number in the left when object', function () {
assert.deepStrictEqual(flatten({
hello: {
Expand Down Expand Up @@ -321,6 +440,56 @@ suite('Unflatten', function () {
})
})


test('Transformed First Key', function () {
assert.deepStrictEqual(unflatten({
'foo.hello.world.again': 'good morning',
'foo.lorem.ipsum.dolor': 'good evening'
}, {
transformFirst: function (key, delim) {
return key.substring(('foo'+delim).length)
}
}), {
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
})
})


test('Transformed First Key and Subsequent Keys', function () {
assert.deepStrictEqual(unflatten({
'foo.__hello__.__world__.__again__': 'good morning',
'foo.__lorem__.__ipsum__.__dolor__': 'good evening'
}, {
transformKey: function (key) {
return key.substring(2, key.length - 2)
},
transformFirst: function (key, delim) {
return key.substring(('foo'+delim).length)
}
}), {
hello: {
world: {
again: 'good morning'
}
},
lorem: {
ipsum: {
dolor: 'good evening'
}
}
})
})


test('Messy', function () {
assert.deepStrictEqual({
hello: { world: 'again' },
Expand Down

0 comments on commit 5345739

Please sign in to comment.