Serializer.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. /**
  6. * @template T, K, C
  7. * @typedef {import("./SerializerMiddleware")<T, K, C>} SerializerMiddleware
  8. */
  9. /**
  10. * @template DeserializedValue
  11. * @template SerializedValue
  12. * @template Context
  13. */
  14. class Serializer {
  15. /**
  16. * @param {SerializerMiddleware<EXPECTED_ANY, EXPECTED_ANY, EXPECTED_ANY>[]} middlewares serializer middlewares
  17. * @param {Context=} context context
  18. */
  19. constructor(middlewares, context) {
  20. this.serializeMiddlewares = middlewares.slice();
  21. this.deserializeMiddlewares = middlewares.slice().reverse();
  22. this.context = context;
  23. }
  24. /**
  25. * @template ExtendedContext
  26. * @param {DeserializedValue | Promise<DeserializedValue>} obj object
  27. * @param {Context & ExtendedContext} context context object
  28. * @returns {Promise<SerializedValue>} result
  29. */
  30. serialize(obj, context) {
  31. const ctx = { ...context, ...this.context };
  32. let current = obj;
  33. for (const middleware of this.serializeMiddlewares) {
  34. if (
  35. current &&
  36. typeof (/** @type {Promise<DeserializedValue>} */ (current).then) ===
  37. "function"
  38. ) {
  39. current =
  40. /** @type {Promise<DeserializedValue>} */
  41. (current).then(data => data && middleware.serialize(data, ctx));
  42. } else if (current) {
  43. try {
  44. current = middleware.serialize(current, ctx);
  45. } catch (err) {
  46. current = Promise.reject(err);
  47. }
  48. } else break;
  49. }
  50. return /** @type {Promise<SerializedValue>} */ (current);
  51. }
  52. /**
  53. * @template ExtendedContext
  54. * @param {SerializedValue | Promise<SerializedValue>} value value
  55. * @param {Context & ExtendedContext} context object
  56. * @returns {Promise<DeserializedValue>} result
  57. */
  58. deserialize(value, context) {
  59. const ctx = { ...context, ...this.context };
  60. let current = value;
  61. for (const middleware of this.deserializeMiddlewares) {
  62. current =
  63. current &&
  64. typeof (/** @type {Promise<SerializedValue>} */ (current).then) ===
  65. "function"
  66. ? /** @type {Promise<SerializedValue>} */ (current).then(data =>
  67. middleware.deserialize(data, ctx)
  68. )
  69. : middleware.deserialize(current, ctx);
  70. }
  71. return /** @type {Promise<DeserializedValue>} */ (current);
  72. }
  73. }
  74. module.exports = Serializer;