Serializer.js 2.5 KB

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