Created
January 16, 2018 01:24
-
-
Save neftaly/504d6ea7b438cd9dc1cd0e1e28e65b89 to your computer and use it in GitHub Desktop.
DynamoDB backup (v3) raw file to/from JSON
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const R = require('ramda'); | |
| const typeEncoder = (mode, type) => { | |
| if (mode !== 'fromDynamo' && mode !== 'toDynamo') { | |
| throw new Error('Invalid mode: ' + mode); | |
| } | |
| const numberEncoder = mode === 'fromDynamo' ? Number : String; | |
| switch (R.toUpper(type)) { | |
| case 'S': return String; | |
| case 'N': return numberEncoder; | |
| case 'B': return Buffer; | |
| case 'NULLVALUE': | |
| case 'NULL': return R.always(mode === 'fromDynamo' ? null : true); | |
| case 'BOOL': return Boolean; | |
| case 'SS': return R.map(String); | |
| case 'NS': return R.map(numberEncoder); | |
| case 'BS': return R.map(Buffer); | |
| case 'L': | |
| case 'M': | |
| return mode === 'fromDynamo' ? fromDynamo : R.map(toDynamo); | |
| default: throw new Error('Unknown type: ' + type); | |
| } | |
| }; | |
| // Get Dynamo type from JS value | |
| // :: jsValue => dynamoType | |
| const getType = value => { | |
| const getSetType = R.compose( | |
| R.unless(R.identity, R.always('l')), | |
| R.reduce((prior, current) => { | |
| const set = current + 'S'; | |
| const list = R.reduced('l'); | |
| if (prior && prior !== set) return list; | |
| return R.contains(set, ['sS', 'nS', 'bS']) ? set : list; | |
| }, false), | |
| R.map(getType) | |
| ); | |
| const constructor = value === null ? value : value.constructor; | |
| switch (constructor) { | |
| case String: return 's'; | |
| case Number: return 'n'; | |
| case Buffer: return 'b'; | |
| case null: return 'nULLValue'; | |
| case Boolean: return 'bOOL'; | |
| case Array: return getSetType(value); | |
| case Object: return 'm'; | |
| default: throw new Error('Unknown type: ' + constructor); | |
| } | |
| }; | |
| // Convert from JS to DynamoDB | |
| // :: jsMap => dynamoMap | |
| const toDynamo = value => { | |
| if (value === undefined) { | |
| return undefined; | |
| } | |
| const type = getType(value); | |
| const newValue = typeEncoder('toDynamo', type)(value); | |
| return { [type]: newValue }; | |
| }; | |
| // Convert from DynamoDB to JS | |
| // :: dynamoMap => jsMap | |
| const fromDynamo = R.compose( | |
| R.map(row => { | |
| const type = R.compose(R.head, R.keys)(row); | |
| const value = row[type]; | |
| return typeEncoder('fromDynamo', type)(value); | |
| }), | |
| R.defaultTo({}) | |
| ); | |
| // Convert from DDB string to JS | |
| const lineToJS = fromDynamo; | |
| // :: string => object | |
| const toJS = R.compose( | |
| R.map(lineToJS), | |
| R.match(/[^\r\n]+/g) | |
| ); | |
| // Convert from JS to DDB string | |
| const lineFromJS = R.compose( | |
| JSON.stringify, | |
| R.prop('m'), | |
| toDynamo | |
| ); | |
| // :: object => string | |
| const fromJS = R.compose( | |
| R.join('\n'), | |
| R.map(lineFromJS), | |
| R.values | |
| ); | |
| module.exports = { | |
| toJS, | |
| fromJS, | |
| lineToJS, | |
| lineFroms | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment