userIntegrations.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * Recursively traverses an object to update an existing nested key.
  3. * Note: The provided key path must include existing properties,
  4. * the function will not create objects while traversing.
  5. *
  6. * @param obj An object to update
  7. * @param value The value to update the nested key with
  8. * @param keyPath The path to the key to update ex. fizz.buzz.foo
  9. */
  10. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  11. function setNestedKey(obj, keyPath, value) {
  12. // Ex. foo.bar.zoop will extract foo and bar.zoop
  13. const match = keyPath.match(/([a-z_]+)\.(.*)/i);
  14. // The match will be null when there's no more recursing to do, i.e., when we've reached the right level of the object
  15. if (match === null) {
  16. obj[keyPath] = value;
  17. } else {
  18. // `match[1]` is the initial segment of the path, and `match[2]` is the remainder of the path
  19. const innerObj = obj[match[1]];
  20. setNestedKey(innerObj, match[2], value);
  21. }
  22. }
  23. /**
  24. * Enforces inclusion of a given integration with specified options in an integration array originally determined by the
  25. * user, by either including the given default instance or by patching an existing user instance with the given options.
  26. *
  27. * Ideally this would happen when integrations are set up, but there isn't currently a mechanism there for merging
  28. * options from a default integration instance with those from a user-provided instance of the same integration, only
  29. * for allowing the user to override a default instance entirely. (TODO: Fix that.)
  30. *
  31. * @param defaultIntegrationInstance An instance of the integration with the correct options already set
  32. * @param userIntegrations Integrations defined by the user.
  33. * @param forcedOptions Options with which to patch an existing user-derived instance on the integration.
  34. * @returns A final integrations array.
  35. *
  36. * @deprecated This will be removed in v8.
  37. */
  38. function addOrUpdateIntegration(
  39. defaultIntegrationInstance,
  40. userIntegrations,
  41. forcedOptions = {},
  42. ) {
  43. return (
  44. Array.isArray(userIntegrations)
  45. ? addOrUpdateIntegrationInArray(defaultIntegrationInstance, userIntegrations, forcedOptions)
  46. : addOrUpdateIntegrationInFunction(
  47. defaultIntegrationInstance,
  48. // Somehow TS can't figure out that not being an array makes this necessarily a function
  49. userIntegrations ,
  50. forcedOptions,
  51. )
  52. ) ;
  53. }
  54. function addOrUpdateIntegrationInArray(
  55. defaultIntegrationInstance,
  56. userIntegrations,
  57. forcedOptions,
  58. ) {
  59. const userInstance = userIntegrations.find(integration => integration.name === defaultIntegrationInstance.name);
  60. if (userInstance) {
  61. for (const [keyPath, value] of Object.entries(forcedOptions)) {
  62. setNestedKey(userInstance, keyPath, value);
  63. }
  64. return userIntegrations;
  65. }
  66. return [...userIntegrations, defaultIntegrationInstance];
  67. }
  68. function addOrUpdateIntegrationInFunction(
  69. defaultIntegrationInstance,
  70. userIntegrationsFunc,
  71. forcedOptions,
  72. ) {
  73. const wrapper = defaultIntegrations => {
  74. const userFinalIntegrations = userIntegrationsFunc(defaultIntegrations);
  75. // There are instances where we want the user to be able to prevent an integration from appearing at all, which they
  76. // would do by providing a function which filters out the integration in question. If that's happened in one of
  77. // those cases, don't add our default back in.
  78. if (defaultIntegrationInstance.allowExclusionByUser) {
  79. const userFinalInstance = userFinalIntegrations.find(
  80. integration => integration.name === defaultIntegrationInstance.name,
  81. );
  82. if (!userFinalInstance) {
  83. return userFinalIntegrations;
  84. }
  85. }
  86. return addOrUpdateIntegrationInArray(defaultIntegrationInstance, userFinalIntegrations, forcedOptions);
  87. };
  88. return wrapper;
  89. }
  90. export { addOrUpdateIntegration };
  91. //# sourceMappingURL=userIntegrations.js.map