Skip to content

Commit f6f8d29

Browse files
committed
2 parents 09573a7 + ca50a53 commit f6f8d29

File tree

7 files changed

+45
-19
lines changed

7 files changed

+45
-19
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ timestamps | `Boolean` | no | Automatically add and manage `created` and `modifi
138138
created | `string` | no | Override default `created` field name |
139139
modified | `string` | no | Override default `modified` field name |
140140
schema | `object` | yes | Complex type that specifies the schema for the model (see below) |
141+
delimiter | `string` | no | The string that separates composite values in your sort key (`#` default) |
141142

142143
### Schema Definition
143144

__tests__/model-creation.unit.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ describe('model creation', ()=> {
2828
table: 'test-table',
2929
partitionKey: 'pk',
3030
sortKey: null,
31+
delimiter: '#',
3132
schema: {
3233
pk: { type: 'string', coerce: true },
3334
__model: { type: 'string', default: 'Default', coerce: true, hidden: true }
@@ -54,6 +55,7 @@ describe('model creation', ()=> {
5455
table: 'test-table',
5556
partitionKey: 'pk',
5657
sortKey: null,
58+
delimiter: '#',
5759
schema: {
5860
pk: { type: 'string', coerce: true }
5961
},
@@ -81,6 +83,7 @@ describe('model creation', ()=> {
8183
table: 'test-table',
8284
partitionKey: 'pk',
8385
sortKey: null,
86+
delimiter: '#',
8487
schema: {
8588
pk: { type: 'string', coerce: true },
8689
__model: { type: 'string', default: 'Default', hidden: true, coerce: true },
@@ -115,6 +118,7 @@ describe('model creation', ()=> {
115118
table: 'test-table',
116119
partitionKey: 'pk',
117120
sortKey: null,
121+
delimiter: '#',
118122
schema: {
119123
pk: { type: 'string', coerce: true },
120124
my_model_field: { type: 'string', default: 'Default', hidden: true, coerce: true }
@@ -147,6 +151,7 @@ describe('model creation', ()=> {
147151
table: 'test-table',
148152
partitionKey: 'pk',
149153
sortKey: null,
154+
delimiter: '#',
150155
schema: {
151156
pk: { type: 'string', coerce: true },
152157
__model: { type: 'string', default: 'Default', hidden: true, coerce: true },
@@ -182,6 +187,7 @@ describe('model creation', ()=> {
182187
table: 'test-table',
183188
partitionKey: 'pk',
184189
sortKey: null,
190+
delimiter: '#',
185191
schema: {
186192
pk: { type: 'string', coerce: true },
187193
__model: { type: 'string', default: 'Default', coerce: true, hidden: true },
@@ -259,6 +265,18 @@ describe('model creation', ()=> {
259265
expect(result).toThrow(`'sortKey' must be string value`)
260266
})
261267

268+
it('fails when creating a model with a non-string delimiter', () => {
269+
let result = () => new Model('TestModel',{
270+
table: 'test-table',
271+
partitionKey: 'pk',
272+
delimiter: 123,
273+
schema: {
274+
pk: 'string'
275+
}
276+
})
277+
expect(result).toThrow(`'delimiter' must be string value`)
278+
})
279+
262280
it('fails when creating a model without a table', () => {
263281
let result = () => new Model('TestModel',{
264282
partitionKey: 'pk',

__tests__/models/simple-model.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@ module.exports = {
2121
test_composite: ['sk',0, { save: true }],
2222
test_composite2: ['sk',1],
2323
test_undefined: { default: () => undefined }
24-
}
24+
},
25+
26+
// Define delimiter
27+
delimiter: '|'
2528
}

__tests__/parse.unit.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe('parse',()=>{
7171
})
7272

7373
it('parses composite field', ()=>{
74-
let item = SimpleModel.parse({ pk: 'test@test.com', sk: 'active#email', test_composite: 'test' })
74+
let item = SimpleModel.parse({ pk: 'test@test.com', sk: 'active|email', test_composite: 'test' })
7575
expect(item).toEqual({
7676
pk: 'test@test.com',
7777
test_composite: 'test',

__tests__/put.unit.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ describe('put',()=>{
8484
test_composite2: 'test2'
8585
})
8686
expect(Item.pk).toBe('test-pk')
87-
expect(Item.sk).toBe('test#test2')
87+
expect(Item.sk).toBe('test|test2')
8888
expect(Item.test_composite).toBe('test')
8989
expect(Item).not.toHaveProperty('test_composite2')
9090
})

index.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// TODO: Add delimiter option
2-
31
// TODO: prevent reserved field names ?
42

53
// TODO: Add date type
@@ -33,22 +31,22 @@ class Model {
3331

3432
parse(input,omit=[]) {
3533
// Load the schema
36-
let { schema, linked } = this.Model
34+
let { schema, linked, delimiter } = this.Model
3735

3836
// Assume standard response from DynamoDB
3937
let data = input.Item || input.Items || input
4038

4139
if (Array.isArray(data)) {
42-
return data.map(item => formatItem(schema,linked,item,omit))
40+
return data.map(item => formatItem(schema,linked,item,omit,delimiter))
4341
} else {
44-
return formatItem(schema,linked,data,omit)
42+
return formatItem(schema,linked,data,omit,delimiter)
4543
}
4644
}
4745

4846
get(item={},params={}) {
4947
// Extract schema and merge defaults
50-
let { schema, defaults, linked, partitionKey, sortKey, table } = this.Model
51-
let data = normalizeData(schema,linked,Object.assign({},defaults,item),true)
48+
let { schema, defaults, linked, partitionKey, sortKey, table, delimiter } = this.Model
49+
let data = normalizeData(schema,linked,Object.assign({},defaults,item),delimiter,true)
5250

5351
return Object.assign(
5452
{
@@ -92,10 +90,10 @@ class Model {
9290
// error(`ConditionExpression must be a string`)
9391

9492
// Extract schema and defaults
95-
let { schema, defaults, required, linked, partitionKey, sortKey, table } = this.Model
93+
let { schema, defaults, required, linked, partitionKey, sortKey, table, delimiter } = this.Model
9694

9795
// Merge defaults
98-
let data = normalizeData(schema,linked,Object.assign({},defaults,item))
96+
let data = normalizeData(schema,linked,Object.assign({},defaults,item),delimiter)
9997

10098
// Check for required fields
10199
Object.keys(required).forEach(field =>
@@ -265,10 +263,10 @@ class Model {
265263

266264
put(item={},params={}) {
267265
// Extract schema and defaults
268-
let { schema, defaults, required, linked, partitionKey, sortKey, table } = this.Model
266+
let { schema, defaults, required, linked, partitionKey, sortKey, table, delimiter } = this.Model
269267

270268
// Merge defaults
271-
let data = normalizeData(schema,linked,Object.assign({},defaults,item))
269+
let data = normalizeData(schema,linked,Object.assign({},defaults,item),delimiter)
272270

273271
// Check for required fields
274272
Object.keys(required).forEach(field =>
@@ -338,6 +336,11 @@ const parseModel = (name,model) => {
338336
let schema = typeof model.schema === 'object' && !Array.isArray(model.schema) ?
339337
model.schema : error(`Please provide a valid 'schema'`)
340338

339+
let delimiter = '#'
340+
if (typeof model.delimiter === 'string' && model.delimiter.trim().length > 0) {
341+
delimiter = model.delimiter.trim()
342+
} else if (model.delimiter) error(`'delimiter' must be string value with length >= 1`)
343+
341344
// Add model_field
342345
if (model_field) {
343346
schema[model_field] = { type: 'string', default: model_name, hidden: true }
@@ -362,6 +365,7 @@ const parseModel = (name,model) => {
362365
table,
363366
partitionKey,
364367
sortKey,
368+
delimiter,
365369
schema: Object.keys(schema).reduce((acc,field) => {
366370
if (typeof schema[field] === 'string') {
367371
return validTypes.includes(schema[field]) ?
@@ -551,14 +555,14 @@ const getKey = (data,schema,partitionKey,sortKey) => {
551555

552556

553557
// Format item based on schema
554-
const formatItem = (schema,linked,item,omit) => {
558+
const formatItem = (schema,linked,item,omit,delimiter) => {
555559
return Object.keys(item).reduce((acc,field) => {
556560

557561
if (linked[field]) {
558562
Object.assign(acc, linked[field].reduce((acc,f,i) => {
559563
if (schema[f].save || schema[f].hidden || omit.includes(f)) return acc
560564
return Object.assign(acc,{
561-
[schema[f].alias || f]: validateType(schema[f],f,item[field].split('#')[i])
565+
[schema[f].alias || f]: validateType(schema[f],f,item[field].split(delimiter)[i])
562566
})
563567
},{}))
564568
}
@@ -571,7 +575,7 @@ const formatItem = (schema,linked,item,omit) => {
571575
}
572576

573577

574-
const normalizeData = (schema,linked,data,filter=false) => {
578+
const normalizeData = (schema,linked,data,delimiter,filter=false) => {
575579
let _data = Object.keys(data).reduce((acc,field) => {
576580
return Object.assign(acc,
577581
schema[field] ? { [schema[field].mapped || field] : data[field] }
@@ -592,7 +596,7 @@ const normalizeData = (schema,linked,data,filter=false) => {
592596
// error(`${linked[field].join(', ')} are all required for composite key`)
593597
// } else
594598
if (values.length === linked[field].length) {
595-
return Object.assign(acc, { [field]: values.join('#') })
599+
return Object.assign(acc, { [field]: values.join(delimiter) })
596600
} else {
597601
return acc
598602
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@
4040
"eslint": "^6.7.1",
4141
"jest": "^24.9.0"
4242
}
43-
}
43+
}

0 commit comments

Comments
 (0)