parse.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /**
  2. * Module dependencies
  3. */
  4. var util = require('util');
  5. var _ = require('@sailshq/lodash');
  6. var hydrate = require('./hydrate');
  7. /**
  8. * A variation on JSON.parse that also takes care of a few additional
  9. * edge-cases including eval-ing stringified functions.
  10. *
  11. * TODO: if `typeSchema` is provided, also coerce the decoded value to match.
  12. *
  13. * @param {String} value
  14. * @param {*} typeSchema - optionally provide `typeSchema` so that it can be used to improve the accuracy of the deserialized result (specifically it is necessary to eval lamda functions)
  15. * @param {Boolean} unsafeMode - enable to use `eval` to hydrate stringified functions based on `typeSchema` (this is not safe to use on user-provided input and so is disabled by default)
  16. * @return {*}
  17. */
  18. module.exports = function parse (value, typeSchema, unsafeMode) {
  19. // `unsafeMode` is disabled by default
  20. unsafeMode = unsafeMode || false;
  21. if (!_.isString(value)) {
  22. throw new Error('rttc.decode() expects a string value, but a '+typeof value+' was provided:'+util.inspect(value, false, null));
  23. }
  24. if (unsafeMode && _.isUndefined(typeSchema)) {
  25. throw new Error('rttc.decode() cannot enable `unsafeMode` without also providing a `typeSchema`.');
  26. }
  27. var deserializedVal;
  28. // Attempt to parse provided JSON-encoded value
  29. try {
  30. deserializedVal = JSON.parse(value);
  31. }
  32. catch (e) {
  33. throw new Error('Could not JSON.parse() provided value: '+value);
  34. }
  35. // Deserialize any lamda functions that exist in the provided input value
  36. // (but only in `unsafeMode`, and if `typeSchema` is provided)
  37. //
  38. // If this is a lamda type, or something which MIGHT contain a lamda type
  39. // (i.e. nested array or dictionary type schema), we must recursively iterate over the
  40. // type schema looking for lamda types, and when we find them, parse input values as
  41. // stringified machine fn bodies, converting them to hydrated JavaScript functions.
  42. if (unsafeMode) {
  43. deserializedVal = hydrate(deserializedVal, typeSchema);
  44. }
  45. return deserializedVal;
  46. };