Serializer.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. /** @type {Context | undefined} */
  26. this.context = context;
  27. }
  28. /**
  29. * Serializes this instance into the provided serializer context.
  30. * @template ExtendedContext
  31. * @param {DeserializedValue | Promise<DeserializedValue>} obj object
  32. * @param {Context & ExtendedContext} context context object
  33. * @returns {Promise<SerializedValue>} result
  34. */
  35. serialize(obj, context) {
  36. const ctx = { ...context, ...this.context };
  37. let current = obj;
  38. for (const middleware of this.serializeMiddlewares) {
  39. if (
  40. current &&
  41. typeof (/** @type {Promise<DeserializedValue>} */ (current).then) ===
  42. "function"
  43. ) {
  44. current =
  45. /** @type {Promise<DeserializedValue>} */
  46. (current).then((data) => data && middleware.serialize(data, ctx));
  47. } else if (current) {
  48. try {
  49. current = middleware.serialize(current, ctx);
  50. } catch (err) {
  51. current = Promise.reject(err);
  52. }
  53. } else {
  54. break;
  55. }
  56. }
  57. return /** @type {Promise<SerializedValue>} */ (current);
  58. }
  59. /**
  60. * Restores this instance from the provided deserializer context.
  61. * @template ExtendedContext
  62. * @param {SerializedValue | Promise<SerializedValue>} value value
  63. * @param {Context & ExtendedContext} context object
  64. * @returns {Promise<DeserializedValue>} result
  65. */
  66. deserialize(value, context) {
  67. const ctx = { ...context, ...this.context };
  68. let current = value;
  69. for (const middleware of this.deserializeMiddlewares) {
  70. current =
  71. current &&
  72. typeof (/** @type {Promise<SerializedValue>} */ (current).then) ===
  73. "function"
  74. ? /** @type {Promise<SerializedValue>} */ (current).then((data) =>
  75. middleware.deserialize(data, ctx)
  76. )
  77. : middleware.deserialize(current, ctx);
  78. }
  79. return /** @type {Promise<DeserializedValue>} */ (current);
  80. }
  81. }
  82. module.exports = Serializer;