Skip to content

Commit 0a26210

Browse files
committed
Add inverse transform
1 parent 470cb06 commit 0a26210

File tree

6 files changed

+57
-16
lines changed

6 files changed

+57
-16
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ For more control over an attribute's behavior, you can specify an object as the
387387
| prefix | `string` | `string` | A prefix to be added to an attribute when saved to DynamoDB. This prefix will be removed when parsing the data. |
388388
| suffix | `string` | `string` | A suffix to be added to an attribute when saved to DynamoDB. This suffix will be removed when parsing the data. |
389389
| transform | `function` | all | A function that transforms the input before sending to DynamoDB. This accepts two arguments, the value passed and an object containing the data from other attributes. |
390+
| inverseTransform | `function` | all | A function that transforms the input before sending to the parser. This accepts two arguments, the value passed and an object containing the data from other attributes. |
390391
| partitionKey | `boolean` or `string` | all | Flags an attribute as the 'partitionKey' for this Entity. If set to `true`, it will be mapped to the Table's `partitionKey`. If set to the name of an **index** defined on the Table, it will be mapped to the secondary index's `partitionKey` |
391392
| sortKey | `boolean` or `string` | all | Flags an attribute as the 'sortKey' for this Entity. If set to `true`, it will be mapped to the Table's `sortKey`. If set to the name of an **index** defined on the Table, it will be mapped to the secondary index's `sortKey` |
392393

__tests__/entities/test-entity.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module.exports = {
2727
test_string_set_type_coerce: { type: 'set', setType: 'string', coerce: true },
2828
test_number_set_type_coerce: { type: 'set', setType: 'number', coerce: true },
2929
test_binary: { type: 'binary' },
30-
simple_string: 'string'
30+
simple_string: 'string',
31+
inverse_transformed_simple_string: { type: 'string', inverseTransform: (input) => input.toUpperCase() }
3132
}
3233
}

__tests__/entity-creation.unit.test.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,5 +565,35 @@ describe('Entity creation', ()=> {
565565

566566
}) // creates attribute with transformations
567567

568+
it('creates an attribute with a inverseTransformation function', async () => {
569+
// Create basic table
570+
const TestTable = new Table({
571+
name: 'test-table',
572+
partitionKey: 'pk',
573+
sortKey: 'sk',
574+
DocumentClient
575+
})
568576

569-
})
577+
// Create basic entity
578+
const TestEntity = new Entity({
579+
name: 'TestEnt',
580+
attributes: {
581+
pk: { partitionKey: true, inverseTransform: (val) => val.toUpperCase(), default: 'pkDef' },
582+
test: {
583+
inverseTransform: (val,data) => {
584+
return val.toUpperCase()
585+
},
586+
default: () => 'defaultVal',
587+
},
588+
sk: { type: 'string', sortKey: true },
589+
testx: ['sk',0],
590+
testy: ['sk',1, {
591+
default: () => 'testDefaultX',
592+
inverseTransform: (val) => { return '__'+val.toUpperCase() }
593+
}]
594+
},
595+
table: TestTable,
596+
timestamps: false
597+
})
598+
})
599+
})

__tests__/entity.parse.unit.test.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ const TestTable = new Table({
2121
describe('parse',()=>{
2222

2323
it('parses single item', ()=>{
24-
let item = TestEntity.parse({ pk: '[email protected]', sk: 'email', test_string: 'test', _et: 'TestEntity' })
24+
let item = TestEntity.parse({ pk: '[email protected]', sk: 'email', test_string: 'test', inverse_transformed_simple_string: 'transformed' , _et: 'TestEntity' })
2525
expect(item).toEqual({
2626
2727
test_type: 'email',
2828
test_string: 'test',
29-
entity: 'TestEntity'
29+
entity: 'TestEntity',
30+
inverse_transformed_simple_string: 'TRANSFORMED'
3031
})
3132
})
3233

@@ -40,19 +41,21 @@ describe('parse',()=>{
4041

4142
it('parses multiple items', ()=>{
4243
let items = TestEntity.parse([
43-
{ pk: '[email protected]', sk: 'email', test_string: 'test' },
44-
{ pk: '[email protected]', sk: 'email2', test_string: 'test2' }
44+
{ pk: '[email protected]', sk: 'email', test_string: 'test', inverse_transformed_simple_string: 'transformed' },
45+
{ pk: '[email protected]', sk: 'email2', test_string: 'test2', inverse_transformed_simple_string: 'transformed' }
4546
])
4647
expect(items).toEqual([
4748
{
4849
4950
test_type: 'email',
50-
test_string: 'test'
51+
test_string: 'test',
52+
inverse_transformed_simple_string: 'TRANSFORMED'
5153
},
5254
{
5355
5456
test_type: 'email2',
55-
test_string: 'test2'
57+
test_string: 'test2',
58+
inverse_transformed_simple_string: 'TRANSFORMED'
5659
}
5760
])
5861
})

lib/formatItem.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,21 @@ module.exports = (DocumentClient) => (attributes,linked,item,include=[]) => {
3636
if ((attributes[field] && attributes[field].hidden) || (include.length > 0 && !include.includes(field))) return acc
3737
// Extract values from sets
3838
if (attributes[field] && attributes[field].type === 'set' && Array.isArray(item[field].values)) { item[field] = item[field].values }
39+
40+
const fieldValue = attributes[field] && (attributes[field].prefix || attributes[field].suffix)
41+
? item[field]
42+
.replace(new RegExp(`^${escapeRegExp(attributes[field].prefix)}`),'')
43+
.replace(new RegExp(`${escapeRegExp(attributes[field].suffix)}$`),'')
44+
: item[field]
45+
46+
const transformedValue = attributes[field] && attributes[field].inverseTransform ? attributes[field].inverseTransform(fieldValue, item) : fieldValue
47+
3948
return Object.assign(acc,{
40-
[(attributes[field] && attributes[field].alias) || field]: (
41-
attributes[field] && (attributes[field].prefix || attributes[field].suffix)
42-
? item[field]
43-
.replace(new RegExp(`^${escapeRegExp(attributes[field].prefix)}`),'')
44-
.replace(new RegExp(`${escapeRegExp(attributes[field].suffix)}$`),'')
45-
: item[field]
46-
)
49+
[(attributes[field] && attributes[field].alias) || field]: transformedValue
4750
})
4851
},{})
4952
}
5053

5154
function escapeRegExp(text) {
5255
return text ? text.replace(/[-[\]{}()*+?.,\\^$|#]/g, '\\$&') : ''
53-
}
56+
}

lib/parseMapping.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ module.exports = (field,config,track) => {
2424
case 'transform':
2525
if (typeof config[prop] !== 'function') error(`'${prop}' must be a function`)
2626
break
27+
case 'inverseTransform':
28+
if (typeof config[prop] !== 'function') error(`'${prop}' must be a function`)
29+
break
2730
case 'coerce':
2831
case 'onUpdate':
2932
case 'hidden':

0 commit comments

Comments
 (0)