index.cjs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. 'use strict';
  2. function createContext(opts = {}) {
  3. let currentInstance;
  4. let isSingleton = false;
  5. const checkConflict = (instance) => {
  6. if (currentInstance && currentInstance !== instance) {
  7. throw new Error("Context conflict");
  8. }
  9. };
  10. let als;
  11. if (opts.asyncContext) {
  12. const _AsyncLocalStorage = opts.AsyncLocalStorage || globalThis.AsyncLocalStorage;
  13. if (_AsyncLocalStorage) {
  14. als = new _AsyncLocalStorage();
  15. } else {
  16. console.warn("[unctx] `AsyncLocalStorage` is not provided.");
  17. }
  18. }
  19. const _getCurrentInstance = () => {
  20. if (als) {
  21. const instance = als.getStore();
  22. if (instance !== void 0) {
  23. return instance;
  24. }
  25. }
  26. return currentInstance;
  27. };
  28. return {
  29. use: () => {
  30. const _instance = _getCurrentInstance();
  31. if (_instance === void 0) {
  32. throw new Error("Context is not available");
  33. }
  34. return _instance;
  35. },
  36. tryUse: () => {
  37. return _getCurrentInstance();
  38. },
  39. set: (instance, replace) => {
  40. if (!replace) {
  41. checkConflict(instance);
  42. }
  43. currentInstance = instance;
  44. isSingleton = true;
  45. },
  46. unset: () => {
  47. currentInstance = void 0;
  48. isSingleton = false;
  49. },
  50. call: (instance, callback) => {
  51. checkConflict(instance);
  52. currentInstance = instance;
  53. try {
  54. return als ? als.run(instance, callback) : callback();
  55. } finally {
  56. if (!isSingleton) {
  57. currentInstance = void 0;
  58. }
  59. }
  60. },
  61. async callAsync(instance, callback) {
  62. currentInstance = instance;
  63. const onRestore = () => {
  64. currentInstance = instance;
  65. };
  66. const onLeave = () => currentInstance === instance ? onRestore : void 0;
  67. asyncHandlers.add(onLeave);
  68. try {
  69. const r = als ? als.run(instance, callback) : callback();
  70. if (!isSingleton) {
  71. currentInstance = void 0;
  72. }
  73. return await r;
  74. } finally {
  75. asyncHandlers.delete(onLeave);
  76. }
  77. }
  78. };
  79. }
  80. function createNamespace(defaultOpts = {}) {
  81. const contexts = {};
  82. return {
  83. get(key, opts = {}) {
  84. if (!contexts[key]) {
  85. contexts[key] = createContext({ ...defaultOpts, ...opts });
  86. }
  87. return contexts[key];
  88. }
  89. };
  90. }
  91. const _globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {};
  92. const globalKey = "__unctx__";
  93. const defaultNamespace = _globalThis[globalKey] || (_globalThis[globalKey] = createNamespace());
  94. const getContext = (key, opts = {}) => defaultNamespace.get(key, opts);
  95. const useContext = (key, opts = {}) => getContext(key, opts).use;
  96. const asyncHandlersKey = "__unctx_async_handlers__";
  97. const asyncHandlers = _globalThis[asyncHandlersKey] || (_globalThis[asyncHandlersKey] = /* @__PURE__ */ new Set());
  98. function executeAsync(function_) {
  99. const restores = [];
  100. for (const leaveHandler of asyncHandlers) {
  101. const restore2 = leaveHandler();
  102. if (restore2) {
  103. restores.push(restore2);
  104. }
  105. }
  106. const restore = () => {
  107. for (const restore2 of restores) {
  108. restore2();
  109. }
  110. };
  111. let awaitable = function_();
  112. if (awaitable && typeof awaitable === "object" && "catch" in awaitable) {
  113. awaitable = awaitable.catch((error) => {
  114. restore();
  115. throw error;
  116. });
  117. }
  118. return [awaitable, restore];
  119. }
  120. function withAsyncContext(function_, transformed) {
  121. if (!transformed) {
  122. console.warn(
  123. "[unctx] `withAsyncContext` needs transformation for async context support in",
  124. function_,
  125. "\n",
  126. function_.toString()
  127. );
  128. }
  129. return function_;
  130. }
  131. exports.createContext = createContext;
  132. exports.createNamespace = createNamespace;
  133. exports.defaultNamespace = defaultNamespace;
  134. exports.executeAsync = executeAsync;
  135. exports.getContext = getContext;
  136. exports.useContext = useContext;
  137. exports.withAsyncContext = withAsyncContext;