options.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. /** @template T @typedef {(string | Record<string, string | string[] | T>)[] | Record<string, string | string[] | T>} ContainerOptionsFormat */
  7. /**
  8. * @template T
  9. * @template N
  10. * @param {ContainerOptionsFormat<T>} options options passed by the user
  11. * @param {function(string | string[], string) : N} normalizeSimple normalize a simple item
  12. * @param {function(T, string) : N} normalizeOptions normalize a complex item
  13. * @param {function(string, N): void} fn processing function
  14. * @returns {void}
  15. */
  16. const process = (options, normalizeSimple, normalizeOptions, fn) => {
  17. const array = items => {
  18. for (const item of items) {
  19. if (typeof item === "string") {
  20. fn(item, normalizeSimple(item, item));
  21. } else if (item && typeof item === "object") {
  22. object(item);
  23. } else {
  24. throw new Error("Unexpected options format");
  25. }
  26. }
  27. };
  28. const object = obj => {
  29. for (const [key, value] of Object.entries(obj)) {
  30. if (typeof value === "string" || Array.isArray(value)) {
  31. fn(key, normalizeSimple(value, key));
  32. } else {
  33. fn(key, normalizeOptions(value, key));
  34. }
  35. }
  36. };
  37. if (!options) {
  38. return;
  39. } else if (Array.isArray(options)) {
  40. array(options);
  41. } else if (typeof options === "object") {
  42. object(options);
  43. } else {
  44. throw new Error("Unexpected options format");
  45. }
  46. };
  47. /**
  48. * @template T
  49. * @template R
  50. * @param {ContainerOptionsFormat<T>} options options passed by the user
  51. * @param {function(string | string[], string) : R} normalizeSimple normalize a simple item
  52. * @param {function(T, string) : R} normalizeOptions normalize a complex item
  53. * @returns {[string, R][]} parsed options
  54. */
  55. const parseOptions = (options, normalizeSimple, normalizeOptions) => {
  56. /** @type {[string, R][]} */
  57. const items = [];
  58. process(options, normalizeSimple, normalizeOptions, (key, value) => {
  59. items.push([key, value]);
  60. });
  61. return items;
  62. };
  63. /**
  64. * @template T
  65. * @param {string} scope scope name
  66. * @param {ContainerOptionsFormat<T>} options options passed by the user
  67. * @returns {Record<string, string | string[] | T>} options to spread or pass
  68. */
  69. const scope = (scope, options) => {
  70. /** @type {Record<string, string | string[] | T>} */
  71. const obj = {};
  72. process(
  73. options,
  74. item => /** @type {string | string[] | T} */ (item),
  75. item => /** @type {string | string[] | T} */ (item),
  76. (key, value) => {
  77. obj[
  78. key.startsWith("./") ? `${scope}${key.slice(1)}` : `${scope}/${key}`
  79. ] = value;
  80. }
  81. );
  82. return obj;
  83. };
  84. exports.parseOptions = parseOptions;
  85. exports.scope = scope;