pre-process-record.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // ██████╗ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██████╗███████╗███████╗███████╗
  2. // ██╔══██╗██╔══██╗██╔════╝ ██╔══██╗██╔══██╗██╔═══██╗██╔════╝██╔════╝██╔════╝██╔════╝
  3. // ██████╔╝██████╔╝█████╗█████╗██████╔╝██████╔╝██║ ██║██║ █████╗ ███████╗███████╗
  4. // ██╔═══╝ ██╔══██╗██╔══╝╚════╝██╔═══╝ ██╔══██╗██║ ██║██║ ██╔══╝ ╚════██║╚════██║
  5. // ██║ ██║ ██║███████╗ ██║ ██║ ██║╚██████╔╝╚██████╗███████╗███████║███████║
  6. // ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝╚══════╝╚══════╝╚══════╝
  7. //
  8. // ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ SSSSSS
  9. // ██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗ S
  10. // ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██║ ██║ SSSSSS
  11. // ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║ ██║ S
  12. // ██║ ██║███████╗╚██████╗╚██████╔╝██║ ██║██████╔╝ S
  13. // ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ SSSSSSS
  14. //
  15. var _ = require('@sailshq/lodash');
  16. var utils = require('waterline-utils');
  17. var eachRecordDeep = utils.eachRecordDeep;
  18. /**
  19. * [exports description]
  20. *
  21. * TODO: Document this utility
  22. *
  23. * TODO: change the name of this utility to reflect the fact that its job is
  24. * to pre-process new incoming records (plural)
  25. *
  26. * @param {[type]} options [description]
  27. * @return {[type]} [description]
  28. */
  29. module.exports = function preProcessRecord(options) {
  30. // ╦ ╦╔═╗╦ ╦╔╦╗╔═╗╔╦╗╔═╗ ┌─┐┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
  31. // ╚╗╔╝╠═╣║ ║ ║║╠═╣ ║ ║╣ │ │├─┘ │ ││ ││││└─┐
  32. // ╚╝ ╩ ╩╩═╝╩═╩╝╩ ╩ ╩ ╚═╝ └─┘┴ ┴ ┴└─┘┘└┘└─┘
  33. if (_.isUndefined(options) || !_.isPlainObject(options)) {
  34. throw new Error('Invalid options argument. Options must contain: records, identity, and orm.');
  35. }
  36. if (!_.has(options, 'records') || !_.isArray(options.records)) {
  37. throw new Error('Invalid option used in options argument. Missing or invalid records.');
  38. }
  39. if (!_.has(options, 'identity') || !_.isString(options.identity)) {
  40. throw new Error('Invalid option used in options argument. Missing or invalid identity.');
  41. }
  42. if (!_.has(options, 'orm') || !_.isPlainObject(options.orm)) {
  43. throw new Error('Invalid option used in options argument. Missing or invalid orm.');
  44. }
  45. // Key the collections by identity instead of column name
  46. var collections = _.reduce(options.orm.collections, function(memo, val) {
  47. memo[val.identity] = val;
  48. return memo;
  49. }, {});
  50. options.orm.collections = collections;
  51. // Run all the new, incoming records through the iterator so that they can be normalized
  52. // with anything adapter-specific before getting written to the database.
  53. // > (This should *never* go more than one level deep!)
  54. eachRecordDeep(options.records, function iterator(record, WLModel, depth) {
  55. if (depth !== 1) {
  56. throw new Error('Consistency violation: Incoming new records in a s3q should never necessitate deep iteration! If you are seeing this error, it is probably because of a bug in this adapter, or in Waterline core.');
  57. }
  58. _.each(WLModel.definition, function checkAttributes(attrDef) {
  59. var columnName = attrDef.columnName;
  60. // JSON stringify the values provided for any `type: 'json'` attributes
  61. // because MySQL can't store JSON.
  62. if (attrDef.type === 'json' && _.has(record, columnName)) {
  63. // Special case: If this is the `null` literal, leave it alone.
  64. // But otherwise, stringify it into a JSON string.
  65. // (even if it's already a string!)
  66. if (!_.isNull(record[columnName])) {
  67. record[columnName] = JSON.stringify(record[columnName]);
  68. }
  69. }//>-
  70. });
  71. }, true, options.identity, options.orm);
  72. };